vendor: 4,970 bytes, lines 1-161
1/* ---------------------------------------------------------- 2 * Plugins 3 * ---------------------------------------------------------- */ 4 5(function (global, factory) { 6 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 7 typeof define === 'function' && define.amd ? define(['exports'], factory) : 8 (global = global || self, factory(global.window = global.window || {})); 9}(this, (function (exports) { 'use strict'; 10 11 function _inheritsLoose(subClass, superClass) { 12 subClass.prototype = Object.create(superClass.prototype); 13 subClass.prototype.constructor = subClass; 14 subClass.__proto__ = superClass; 15 } 16 17 function _assertThisInitialized(self) { 18 if (self === void 0) { 19 throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 20 } 21 22 return self; 23 } 24 25 /*! 26 * GSAP 3.12.5 27 * https://gsap.com 28 * 29 * @license Copyright 2008-2024, GreenSock. All rights reserved. 30 * Subject to the terms at https://gsap.com/standard-license or for 31 * Club GSAP members, the agreement issued with that membership. 32 * @author: Jack Doyle, [email protected] 33 */ 34 var _config = { 35 autoSleep: 120, 36 force3D: "auto", 37 nullTargetWarn: 1, 38 units: { 39 lineHeight: "" 40 } 41 }, 42 _defaults = { 43 duration: .5, 44 overwrite: false, 45 delay: 0 46 }, 47 _suppressOverwrites, 48 _reverting, 49 _context, 50 _bigNum = 1e8, 51 _tinyNum = 1 / _bigNum, 52 _2PI = Math.PI * 2, 53 _HALF_PI = _2PI / 4, 54 _gsID = 0, 55 _sqrt = Math.sqrt, 56 _cos = Math.cos, 57 _sin = Math.sin, 58 _isString = function _isString(value) { 59 return typeof value === "string"; 60 }, 61 _isFunction = function _isFunction(value) { 62 return typeof value === "function"; 63 }, 64 _isNumber = function _isNumber(value) { 65 return typeof value === "number"; 66 }, 67 _isUndefined = function _isUndefined(value) { 68 return typeof value === "undefined"; 69 }, 70 _isObject = function _isObject(value) { 71 return typeof value === "object"; 72 }, 73 _isNotFalse = function _isNotFalse(value) { 74 return value !== false; 75 }, 76 _windowExists = function _windowExists() { 77 return typeof window !== "undefined"; 78 }, 79 _isFuncOrString = function _isFuncOrString(value) { 80 return _isFunction(value) || _isString(value); 81 }, 82 _isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView || function () {}, 83 _isArray = Array.isArray, 84 _strictNumExp = /(?:-?\.?\d|\.)+/gi, 85 _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/g, 86 _numWithUnitExp = /[-+=.]*\d+[.e-]*\d*[a-z%]*/g, 87 _complexStringNumExp = /[-+=.]*\d+\.?\d*(?:e-|e\+)?\d*/gi, 88 _relExp = /[+-]=-?[.\d]+/, 89 _delimitedValueExp = /[^,'"\[\]\s]+/gi, 90 _unitExp = /^[+\-=e\s\d]*\d+[.\d]*([a-z]*|%)\s*$/i, 91 _globalTimeline, 92 _win, 93 _coreInitted, 94 _doc, 95 _globals = {}, 96 _installScope = {}, 97 _coreReady, 98 _install = function _install(scope) { 99 return (_installScope = _merge(scope, _globals)) && gsap; 100 }, 101 _missingPlugin = function _missingPlugin(property, value) { 102 return console.warn("Invalid property", property, "set to", value, "Missing plugin? gsap.registerPlugin()"); 103 }, 104 _warn = function _warn(message, suppress) { 105 return !suppress && console.warn(message); 106 }, 107 _addGlobal = function _addGlobal(name, obj) { 108 return name && (_globals[name] = obj) && _installScope && (_installScope[name] = obj) || _globals; 109 }, 110 _emptyFunc = function _emptyFunc() { 111 return 0; 112 }, 113 _startAtRevertConfig = { 114 suppressEvents: true, 115 isStart: true, 116 kill: false 117 }, 118 _revertConfigNoKill = { 119 suppressEvents: true, 120 kill: false 121 }, 122 _revertConfig = { 123 suppressEvents: true 124 }, 125 _reservedProps = {}, 126 _lazyTweens = [], 127 _lazyLookup = {}, 128 _lastRenderedFrame, 129 _plugins = {}, 130 _effects = {}, 131 _nextGCFrame = 30, 132 _harnessPlugins = [], 133 _callbackNames = "", 134 _harness = function _harness(targets) { 135 var target = targets[0], 136 harnessPlugin, 137 i; 138 _isObject(target) || _isFunction(target) || (targets = [targets]); 139 140 if (!(harnessPlugin = (target._gsap || {}).harness)) { 141 i = _harnessPlugins.length; 142 143 while (i-- && !_harnessPlugins[i].targetTest(target)) {} 144 145 harnessPlugin = _harnessPlugins[i]; 146 } 147 148 i = targets.length; 149 150 while (i--) { 151 targets[i] && (targets[i]._gsap || (targets[i]._gsap = new GSCache(targets[i], harnessPlugin))) || targets.splice(i, 1); 152 } 153 154 return targets; 155 }, 156 _getCache = function _getCache(target) { 157 return target._gsap || _harness(toArray(target))[0]._gsap; 158 }, 159 _getProperty = function _getProperty(target, property, v) { 160 return (v = target[property]) && _isFunction(v) ? target[property]() : _isUndefined(v) && target.getAttribute && target.getAttribute(property) || v; 161 },
vendor: 6,338 bytes, lines 162-371
162 _forEachName = function _forEachName(names, func) { 163 return (names = names.split(",")).forEach(func) || names; 164 }, 165 _round = function _round(value) { 166 return Math.round(value * 100000) / 100000 || 0; 167 }, 168 _roundPrecise = function _roundPrecise(value) { 169 return Math.round(value * 10000000) / 10000000 || 0; 170 }, 171 _parseRelative = function _parseRelative(start, value) { 172 var operator = value.charAt(0), 173 end = parseFloat(value.substr(2)); 174 start = parseFloat(start); 175 return operator === "+" ? start + end : operator === "-" ? start - end : operator === "*" ? start * end : start / end; 176 }, 177 _arrayContainsAny = function _arrayContainsAny(toSearch, toFind) { 178 var l = toFind.length, 179 i = 0; 180 181 for (; toSearch.indexOf(toFind[i]) < 0 && ++i < l;) {} 182 183 return i < l; 184 }, 185 _lazyRender = function _lazyRender() { 186 var l = _lazyTweens.length, 187 a = _lazyTweens.slice(0), 188 i, 189 tween; 190 191 _lazyLookup = {}; 192 _lazyTweens.length = 0; 193 194 for (i = 0; i < l; i++) { 195 tween = a[i]; 196 tween && tween._lazy && (tween.render(tween._lazy[0], tween._lazy[1], true)._lazy = 0); 197 } 198 }, 199 _lazySafeRender = function _lazySafeRender(animation, time, suppressEvents, force) { 200 _lazyTweens.length && !_reverting && _lazyRender(); 201 animation.render(time, suppressEvents, force || _reverting && time < 0 && (animation._initted || animation._startAt)); 202 _lazyTweens.length && !_reverting && _lazyRender(); 203 }, 204 _numericIfPossible = function _numericIfPossible(value) { 205 var n = parseFloat(value); 206 return (n || n === 0) && (value + "").match(_delimitedValueExp).length < 2 ? n : _isString(value) ? value.trim() : value; 207 }, 208 _passThrough = function _passThrough(p) { 209 return p; 210 }, 211 _setDefaults = function _setDefaults(obj, defaults) { 212 for (var p in defaults) { 213 p in obj || (obj[p] = defaults[p]); 214 } 215 216 return obj; 217 }, 218 _setKeyframeDefaults = function _setKeyframeDefaults(excludeDuration) { 219 return function (obj, defaults) { 220 for (var p in defaults) { 221 p in obj || p === "duration" && excludeDuration || p === "ease" || (obj[p] = defaults[p]); 222 } 223 }; 224 }, 225 _merge = function _merge(base, toMerge) { 226 for (var p in toMerge) { 227 base[p] = toMerge[p]; 228 } 229 230 return base; 231 }, 232 _mergeDeep = function _mergeDeep(base, toMerge) { 233 for (var p in toMerge) { 234 p !== "__proto__" && p !== "constructor" && p !== "prototype" && (base[p] = _isObject(toMerge[p]) ? _mergeDeep(base[p] || (base[p] = {}), toMerge[p]) : toMerge[p]); 235 } 236 237 return base; 238 }, 239 _copyExcluding = function _copyExcluding(obj, excluding) { 240 var copy = {}, 241 p; 242 243 for (p in obj) { 244 p in excluding || (copy[p] = obj[p]); 245 } 246 247 return copy; 248 }, 249 _inheritDefaults = function _inheritDefaults(vars) { 250 var parent = vars.parent || _globalTimeline, 251 func = vars.keyframes ? _setKeyframeDefaults(_isArray(vars.keyframes)) : _setDefaults; 252 253 if (_isNotFalse(vars.inherit)) { 254 while (parent) { 255 func(vars, parent.vars.defaults); 256 parent = parent.parent || parent._dp; 257 } 258 } 259 260 return vars; 261 }, 262 _arraysMatch = function _arraysMatch(a1, a2) { 263 var i = a1.length, 264 match = i === a2.length; 265 266 while (match && i-- && a1[i] === a2[i]) {} 267 268 return i < 0; 269 }, 270 _addLinkedListItem = function _addLinkedListItem(parent, child, firstProp, lastProp, sortBy) { 271 if (firstProp === void 0) { 272 firstProp = "_first"; 273 } 274 275 if (lastProp === void 0) { 276 lastProp = "_last"; 277 } 278 279 var prev = parent[lastProp], 280 t; 281 282 if (sortBy) { 283 t = child[sortBy]; 284 285 while (prev && prev[sortBy] > t) { 286 prev = prev._prev; 287 } 288 } 289 290 if (prev) { 291 child._next = prev._next; 292 prev._next = child; 293 } else { 294 child._next = parent[firstProp]; 295 parent[firstProp] = child; 296 } 297 298 if (child._next) { 299 child._next._prev = child; 300 } else { 301 parent[lastProp] = child; 302 } 303 304 child._prev = prev; 305 child.parent = child._dp = parent; 306 return child; 307 }, 308 _removeLinkedListItem = function _removeLinkedListItem(parent, child, firstProp, lastProp) { 309 if (firstProp === void 0) { 310 firstProp = "_first"; 311 } 312 313 if (lastProp === void 0) { 314 lastProp = "_last"; 315 } 316 317 var prev = child._prev, 318 next = child._next; 319 320 if (prev) { 321 prev._next = next; 322 } else if (parent[firstProp] === child) { 323 parent[firstProp] = next; 324 } 325 326 if (next) { 327 next._prev = prev; 328 } else if (parent[lastProp] === child) { 329 parent[lastProp] = prev; 330 } 331 332 child._next = child._prev = child.parent = null; 333 }, 334 _removeFromParent = function _removeFromParent(child, onlyIfParentHasAutoRemove) { 335 child.parent && (!onlyIfParentHasAutoRemove || child.parent.autoRemoveChildren) && child.parent.remove && child.parent.remove(child); 336 child._act = 0; 337 }, 338 _uncache = function _uncache(animation, child) { 339 if (animation && (!child || child._end > animation._dur || child._start < 0)) { 340 var a = animation; 341 342 while (a) { 343 a._dirty = 1; 344 a = a.parent; 345 } 346 } 347 348 return animation; 349 }, 350 _recacheAncestors = function _recacheAncestors(animation) { 351 var parent = animation.parent; 352 353 while (parent && parent.parent) { 354 parent._dirty = 1; 355 parent.totalDuration(); 356 parent = parent.parent; 357 } 358 359 return animation; 360 }, 361 _rewindStartAt = function _rewindStartAt(tween, totalTime, suppressEvents, force) { 362 return tween._startAt && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween.vars.immediateRender && !tween.vars.autoRevert || tween._startAt.render(totalTime, true, force)); 363 }, 364 _hasNoPausedAncestors = function _hasNoPausedAncestors(animation) { 365 return !animation || animation._ts && _hasNoPausedAncestors(animation.parent); 366 }, 367 _elapsedCycleDuration = function _elapsedCycleDuration(animation) { 368 return animation._repeat ? _animationCycle(animation._tTime, animation = animation.duration() + animation._rDelay) * animation : 0; 369 }, 370 _animationCycle = function _animationCycle(tTime, cycleDuration) { 371 var whole = Math.floor(tTime /= cycleDuration
vendor: 17,487 bytes, lines 371-839
371); 372 return tTime && whole === tTime ? whole - 1 : whole; 373 }, 374 _parentToChildTotalTime = function _parentToChildTotalTime(parentTime, child) { 375 return (parentTime - child._start) * child._ts + (child._ts >= 0 ? 0 : child._dirty ? child.totalDuration() : child._tDur); 376 }, 377 _setEnd = function _setEnd(animation) { 378 return animation._end = _roundPrecise(animation._start + (animation._tDur / Math.abs(animation._ts || animation._rts || _tinyNum) || 0)); 379 }, 380 _alignPlayhead = function _alignPlayhead(animation, totalTime) { 381 var parent = animation._dp; 382 383 if (parent && parent.smoothChildTiming && animation._ts) { 384 animation._start = _roundPrecise(parent._time - (animation._ts > 0 ? totalTime / animation._ts : ((animation._dirty ? animation.totalDuration() : animation._tDur) - totalTime) / -animation._ts)); 385 386 _setEnd(animation); 387 388 parent._dirty || _uncache(parent, animation); 389 } 390 391 return animation; 392 }, 393 _postAddChecks = function _postAddChecks(timeline, child) { 394 var t; 395 396 if (child._time || !child._dur && child._initted || child._start < timeline._time && (child._dur || !child.add)) { 397 t = _parentToChildTotalTime(timeline.rawTime(), child); 398 399 if (!child._dur || _clamp(0, child.totalDuration(), t) - child._tTime > _tinyNum) { 400 child.render(t, true); 401 } 402 } 403 404 if (_uncache(timeline, child)._dp && timeline._initted && timeline._time >= timeline._dur && timeline._ts) { 405 if (timeline._dur < timeline.duration()) { 406 t = timeline; 407 408 while (t._dp) { 409 t.rawTime() >= 0 && t.totalTime(t._tTime); 410 t = t._dp; 411 } 412 } 413 414 timeline._zTime = -_tinyNum; 415 } 416 }, 417 _addToTimeline = function _addToTimeline(timeline, child, position, skipChecks) { 418 child.parent && _removeFromParent(child); 419 child._start = _roundPrecise((_isNumber(position) ? position : position || timeline !== _globalTimeline ? _parsePosition(timeline, position, child) : timeline._time) + child._delay); 420 child._end = _roundPrecise(child._start + (child.totalDuration() / Math.abs(child.timeScale()) || 0)); 421 422 _addLinkedListItem(timeline, child, "_first", "_last", timeline._sort ? "_start" : 0); 423 424 _isFromOrFromStart(child) || (timeline._recent = child); 425 skipChecks || _postAddChecks(timeline, child); 426 timeline._ts < 0 && _alignPlayhead(timeline, timeline._tTime); 427 return timeline; 428 }, 429 _scrollTrigger = function _scrollTrigger(animation, trigger) { 430 return (_globals.ScrollTrigger || _missingPlugin("scrollTrigger", trigger)) && _globals.ScrollTrigger.create(trigger, animation); 431 }, 432 _attemptInitTween = function _attemptInitTween(tween, time, force, suppressEvents, tTime) { 433 _initTween(tween, time, tTime); 434 435 if (!tween._initted) { 436 return 1; 437 } 438 439 if (!force && tween._pt && !_reverting && (tween._dur && tween.vars.lazy !== false || !tween._dur && tween.vars.lazy) && _lastRenderedFrame !== _ticker.frame) { 440 _lazyTweens.push(tween); 441 442 tween._lazy = [tTime, suppressEvents]; 443 return 1; 444 } 445 }, 446 _parentPlayheadIsBeforeStart = function _parentPlayheadIsBeforeStart(_ref) { 447 var parent = _ref.parent; 448 return parent && parent._ts && parent._initted && !parent._lock && (parent.rawTime() < 0 || _parentPlayheadIsBeforeStart(parent)); 449 }, 450 _isFromOrFromStart = function _isFromOrFromStart(_ref2) { 451 var data = _ref2.data; 452 return data === "isFromStart" || data === "isStart"; 453 }, 454 _renderZeroDurationTween = function _renderZeroDurationTween(tween, totalTime, suppressEvents, force) { 455 var prevRatio = tween.ratio, 456 ratio = totalTime < 0 || !totalTime && (!tween._start && _parentPlayheadIsBeforeStart(tween) && !(!tween._initted && _isFromOrFromStart(tween)) || (tween._ts < 0 || tween._dp._ts < 0) && !_isFromOrFromStart(tween)) ? 0 : 1, 457 repeatDelay = tween._rDelay, 458 tTime = 0, 459 pt, 460 iteration, 461 prevIteration; 462 463 if (repeatDelay && tween._repeat) { 464 tTime = _clamp(0, tween._tDur, totalTime); 465 iteration = _animationCycle(tTime, repeatDelay); 466 tween._yoyo && iteration & 1 && (ratio = 1 - ratio); 467 468 if (iteration !== _animationCycle(tween._tTime, repeatDelay)) { 469 prevRatio = 1 - ratio; 470 tween.vars.repeatRefresh && tween._initted && tween.invalidate(); 471 } 472 } 473 474 if (ratio !== prevRatio || _reverting || force || tween._zTime === _tinyNum || !totalTime && tween._zTime) { 475 if (!tween._initted && _attemptInitTween(tween, totalTime, force, suppressEvents, tTime)) { 476 return; 477 } 478 479 prevIteration = tween._zTime; 480 tween._zTime = totalTime || (suppressEvents ? _tinyNum : 0); 481 suppressEvents || (suppressEvents = totalTime && !prevIteration); 482 tween.ratio = ratio; 483 tween._from && (ratio = 1 - ratio); 484 tween._time = 0; 485 tween._tTime = tTime; 486 pt = tween._pt; 487 488 while (pt) { 489 pt.r(ratio, pt.d); 490 pt = pt._next; 491 } 492 493 totalTime < 0 && _rewindStartAt(tween, totalTime, suppressEvents, true); 494 tween._onUpdate && !suppressEvents && _callback(tween, "onUpdate"); 495 tTime && tween._repeat && !suppressEvents && tween.parent && _callback(tween, "onRepeat"); 496 497 if ((totalTime >= tween._tDur || totalTime < 0) && tween.ratio === ratio) { 498 ratio && _removeFromParent(tween, 1); 499 500 if (!suppressEvents && !_reverting) { 501 _callback(tween, ratio ? "onComplete" : "onReverseComplete", true); 502 503 tween._prom && tween._prom(); 504 } 505 } 506 } else if (!tween._zTime) { 507 tween._zTime = totalTime; 508 } 509 }, 510 _findNextPauseTween = function _findNextPauseTween(animation, prevTime, time) { 511 var child; 512 513 if (time > prevTime) { 514 child = animation._first; 515 516 while (child && child._start <= time) { 517 if (child.data === "isPause" && child._start > prevTime) { 518 return child; 519 } 520 521 child = child._next; 522 } 523 } else { 524 child = animation._last; 525 526 while (child && child._start >= time) { 527 if (child.data === "isPause" && child._start < prevTime) { 528 return child; 529 } 530 531 child = child._prev; 532 } 533 } 534 }, 535 _setDuration = function _setDuration(animation, duration, skipUncache, leavePlayhead) { 536 var repeat = animation._repeat, 537 dur = _roundPrecise(duration) || 0, 538 totalProgress = animation._tTime / animation._tDur; 539 totalProgress && !leavePlayhead && (animation._time *= dur / animation._dur); 540 animation._dur = dur; 541 animation._tDur = !repeat ? dur : repeat < 0 ? 1e10 : _roundPrecise(dur * (repeat + 1) + animation._rDelay * repeat); 542 totalProgress > 0 && !leavePlayhead && _alignPlayhead(animation, animation._tTime = animation._tDur * totalProgress); 543 animation.parent && _setEnd(animation); 544 skipUncache || _uncache(animation.parent, animation); 545 return animation; 546 }, 547 _onUpdateTotalDuration = function _onUpdateTotalDuration(animation) { 548 return animation instanceof Timeline ? _uncache(animation) : _setDuration(animation, animation._dur); 549 }, 550 _zeroPosition = { 551 _start: 0, 552 endTime: _emptyFunc, 553 totalDuration: _emptyFunc 554 }, 555 _parsePosition = function _parsePosition(animation, position, percentAnimation) { 556 var labels = animation.labels, 557 recent = animation._recent || _zeroPosition, 558 clippedDuration = animation.duration() >= _bigNum ? recent.endTime(false) : animation._dur, 559 i, 560 offset, 561 isPercent; 562 563 if (_isString(position) && (isNaN(position) || position in labels)) { 564 offset = position.charAt(0); 565 isPercent = position.substr(-1) === "%"; 566 i = position.indexOf("="); 567 568 if (offset === "<" || offset === ">") { 569 i >= 0 && (position = position.replace(/=/, "")); 570 return (offset === "<" ? recent._start : recent.endTime(recent._repeat >= 0)) + (parseFloat(position.substr(1)) || 0) * (isPercent ? (i < 0 ? recent : percentAnimation).totalDuration() / 100 : 1); 571 } 572 573 if (i < 0) { 574 position in labels || (labels[position] = clippedDuration); 575 return labels[position]; 576 } 577 578 offset = parseFloat(position.charAt(i - 1) + position.substr(i + 1)); 579 580 if (isPercent && percentAnimation) { 581 offset = offset / 100 * (_isArray(percentAnimation) ? percentAnimation[0] : percentAnimation).totalDuration(); 582 } 583 584 return i > 1 ? _parsePosition(animation, position.substr(0, i - 1), percentAnimation) + offset : clippedDuration + offset; 585 } 586 587 return position == null ? clippedDuration : +position; 588 }, 589 _createTweenType = function _createTweenType(type, params, timeline) { 590 var isLegacy = _isNumber(params[1]), 591 varsIndex = (isLegacy ? 2 : 1) + (type < 2 ? 0 : 1), 592 vars = params[varsIndex], 593 irVars, 594 parent; 595 596 isLegacy && (vars.duration = params[1]); 597 vars.parent = timeline; 598 599 if (type) { 600 irVars = vars; 601 parent = timeline; 602 603 while (parent && !("immediateRender" in irVars)) { 604 irVars = parent.vars.defaults || {}; 605 parent = _isNotFalse(parent.vars.inherit) && parent.parent; 606 } 607 608 vars.immediateRender = _isNotFalse(irVars.immediateRender); 609 type < 2 ? vars.runBackwards = 1 : vars.startAt = params[varsIndex - 1]; 610 } 611 612 return new Tween(params[0], vars, params[varsIndex + 1]); 613 }, 614 _conditionalReturn = function _conditionalReturn(value, func) { 615 return value || value === 0 ? func(value) : func; 616 }, 617 _clamp = function _clamp(min, max, value) { 618 return value < min ? min : value > max ? max : value; 619 }, 620 getUnit = function getUnit(value, v) { 621 return !_isString(value) || !(v = _unitExp.exec(value)) ? "" : v[1]; 622 }, 623 clamp = function clamp(min, max, value) { 624 return _conditionalReturn(value, function (v) { 625 return _clamp(min, max, v); 626 }); 627 }, 628 _slice = [].slice, 629 _isArrayLike = function _isArrayLike(value, nonEmpty) { 630 return value && _isObject(value) && "length" in value && (!nonEmpty && !value.length || value.length - 1 in value && _isObject(value[0])) && !value.nodeType && value !== _win; 631 }, 632 _flatten = function _flatten(ar, leaveStrings, accumulator) { 633 if (accumulator === void 0) { 634 accumulator = []; 635 } 636 637 return ar.forEach(function (value) { 638 var _accumulator; 639 640 return _isString(value) && !leaveStrings || _isArrayLike(value, 1) ? (_accumulator = accumulator).push.apply(_accumulator, toArray(value)) : accumulator.push(value); 641 }) || accumulator; 642 }, 643 toArray = function toArray(value, scope, leaveStrings) { 644 return _context && !scope && _context.selector ? _context.selector(value) : _isString(value) && !leaveStrings && (_coreInitted || !_wake()) ? _slice.call((scope || _doc).querySelectorAll(value), 0) : _isArray(value) ? _flatten(value, leaveStrings) : _isArrayLike(value) ? _slice.call(value, 0) : value ? [value] : []; 645 }, 646 selector = function selector(value) { 647 value = toArray(value)[0] || _warn("Invalid scope") || {}; 648 return function (v) { 649 var el = value.current || value.nativeElement || value; 650 return toArray(v, el.querySelectorAll ? el : el === value ? _warn("Invalid scope") || _doc.createElement("div") : value); 651 }; 652 }, 653 shuffle = function shuffle(a) { 654 return a.sort(function () { 655 return .5 - Math.random(); 656 }); 657 }, 658 distribute = function distribute(v) { 659 if (_isFunction(v)) { 660 return v; 661 } 662 663 var vars = _isObject(v) ? v : { 664 each: v 665 }, 666 ease = _parseEase(vars.ease), 667 from = vars.from || 0, 668 base = parseFloat(vars.base) || 0, 669 cache = {}, 670 isDecimal = from > 0 && from < 1, 671 ratios = isNaN(from) || isDecimal, 672 axis = vars.axis, 673 ratioX = from, 674 ratioY = from; 675 676 if (_isString(from)) { 677 ratioX = ratioY = { 678 center: .5, 679 edges: .5, 680 end: 1 681 }[from] || 0; 682 } else if (!isDecimal && ratios) { 683 ratioX = from[0]; 684 ratioY = from[1]; 685 } 686 687 return function (i, target, a) { 688 var l = (a || vars).length, 689 distances = cache[l], 690 originX, 691 originY, 692 x, 693 y, 694 d, 695 j, 696 max, 697 min, 698 wrapAt; 699 700 if (!distances) { 701 wrapAt = vars.grid === "auto" ? 0 : (vars.grid || [1, _bigNum])[1]; 702 703 if (!wrapAt) { 704 max = -_bigNum; 705 706 while (max < (max = a[wrapAt++].getBoundingClientRect().left) && wrapAt < l) {} 707 708 wrapAt < l && wrapAt--; 709 } 710 711 distances = cache[l] = []; 712 originX = ratios ? Math.min(wrapAt, l) * ratioX - .5 : from % wrapAt; 713 originY = wrapAt === _bigNum ? 0 : ratios ? l * ratioY / wrapAt - .5 : from / wrapAt | 0; 714 max = 0; 715 min = _bigNum; 716 717 for (j = 0; j < l; j++) { 718 x = j % wrapAt - originX; 719 y = originY - (j / wrapAt | 0); 720 distances[j] = d = !axis ? _sqrt(x * x + y * y) : Math.abs(axis === "y" ? y : x); 721 d > max && (max = d); 722 d < min && (min = d); 723 } 724 725 from === "random" && shuffle(distances); 726 distances.max = max - min; 727 distances.min = min; 728 distances.v = l = (parseFloat(vars.amount) || parseFloat(vars.each) * (wrapAt > l ? l - 1 : !axis ? Math.max(wrapAt, l / wrapAt) : axis === "y" ? l / wrapAt : wrapAt) || 0) * (from === "edges" ? -1 : 1); 729 distances.b = l < 0 ? base - l : base; 730 distances.u = getUnit(vars.amount || vars.each) || 0; 731 ease = ease && l < 0 ? _invertEase(ease) : ease; 732 } 733 734 l = (distances[i] - distances.min) / distances.max || 0; 735 return _roundPrecise(distances.b + (ease ? ease(l) : l) * distances.v) + distances.u; 736 }; 737 }, 738 _roundModifier = function _roundModifier(v) { 739 var p = Math.pow(10, ((v + "").split(".")[1] || "").length); 740 return function (raw) { 741 var n = _roundPrecise(Math.round(parseFloat(raw) / v) * v * p); 742 743 return (n - n % 1) / p + (_isNumber(raw) ? 0 : getUnit(raw)); 744 }; 745 }, 746 snap = function snap(snapTo, value) { 747 var isArray = _isArray(snapTo), 748 radius, 749 is2D; 750 751 if (!isArray && _isObject(snapTo)) { 752 radius = isArray = snapTo.radius || _bigNum; 753 754 if (snapTo.values) { 755 snapTo = toArray(snapTo.values); 756 757 if (is2D = !_isNumber(snapTo[0])) { 758 radius *= radius; 759 } 760 } else { 761 snapTo = _roundModifier(snapTo.increment); 762 } 763 } 764 765 return _conditionalReturn(value, !isArray ? _roundModifier(snapTo) : _isFunction(snapTo) ? function (raw) { 766 is2D = snapTo(raw); 767 return Math.abs(is2D - raw) <= radius ? is2D : raw; 768 } : function (raw) { 769 var x = parseFloat(is2D ? raw.x : raw), 770 y = parseFloat(is2D ? raw.y : 0), 771 min = _bigNum, 772 closest = 0, 773 i = snapTo.length, 774 dx, 775 dy; 776 777 while (i--) { 778 if (is2D) { 779 dx = snapTo[i].x - x; 780 dy = snapTo[i].y - y; 781 dx = dx * dx + dy * dy; 782 } else { 783 dx = Math.abs(snapTo[i] - x); 784 } 785 786 if (dx < min) { 787 min = dx; 788 closest = i; 789 } 790 } 791 792 closest = !radius || min <= radius ? snapTo[closest] : raw; 793 return is2D || closest === raw || _isNumber(raw) ? closest : closest + getUnit(raw); 794 }); 795 }, 796 random = function random(min, max, roundingIncrement, returnFunction) { 797 return _conditionalReturn(_isArray(min) ? !max : roundingIncrement === true ? !!(roundingIncrement = 0) : !returnFunction, function () { 798 return _isArray(min) ? min[~~(Math.random() * min.length)] : (roundingIncrement = roundingIncrement || 1e-5) && (returnFunction = roundingIncrement < 1 ? Math.pow(10, (roundingIncrement + "").length - 2) : 1) && Math.floor(Math.round((min - roundingIncrement / 2 + Math.random() * (max - min + roundingIncrement * .99)) / roundingIncrement) * roundingIncrement * returnFunction) / returnFunction; 799 }); 800 }, 801 pipe = function pipe() { 802 for (var _len = arguments.length, functions = new Array(_len), _key = 0; _key < _len; _key++) { 803 functions[_key] = arguments[_key]; 804 } 805 806 return function (value) { 807 return functions.reduce(function (v, f) { 808 return f(v); 809 }, value); 810 }; 811 }, 812 unitize = function unitize(func, unit) { 813 return function (value) { 814 return func(parseFloat(value)) + (unit || getUnit(value)); 815 }; 816 }, 817 normalize = function normalize(min, max, value) { 818 return mapRange(min, max, 0, 1, value); 819 }, 820 _wrapArray = function _wrapArray(a, wrapper, value) { 821 return _conditionalReturn(value, function (index) { 822 return a[~~wrapper(index)]; 823 }); 824 }, 825 wrap = function wrap(min, max, value) { 826 var range = max - min; 827 return _isArray(min) ? _wrapArray(min, wrap(0, min.length), max) : _conditionalReturn(value, function (value) { 828 return (range + (value - min) % range) % range + min; 829 }); 830 }, 831 wrapYoyo = function wrapYoyo(min, max, value) { 832 var range = max - min, 833 total = range * 2; 834 return _isArray(min) ? _wrapArray(min, wrapYoyo(0, min.length - 1), max) : _conditionalReturn(value, function (value) { 835 value = (total + (value - min) % total) % total || 0; 836 return min + (value > range ? total - value : value); 837 }); 838 }, 839 _replaceRandom = function _replaceRandom(
vendor: 531 bytes, lines 839-855
839value) { 840 var prev = 0, 841 s = "", 842 i, 843 nums, 844 end, 845 isArray; 846 847 while (~(i = value.indexOf("random(", prev))) { 848 end = value.indexOf(")", i); 849 isArray = value.charAt(i + 7) === "["; 850 nums = value.substr(i + 7, end - i - 7).match(isArray ? _delimitedValueExp : _strictNumExp); 851 s += value.substr(prev, i - prev) + random(isArray ? nums : +nums[0], isArray ? 0 : +nums[1], +nums[2] || 1e-5); 852 prev = end + 1; 853 } 854 855 return s + value.substr(prev, value.length - prev
vendor: 14,290 bytes, lines 855-1371
855); 856 }, 857 mapRange = function mapRange(inMin, inMax, outMin, outMax, value) { 858 var inRange = inMax - inMin, 859 outRange = outMax - outMin; 860 return _conditionalReturn(value, function (value) { 861 return outMin + ((value - inMin) / inRange * outRange || 0); 862 }); 863 }, 864 interpolate = function interpolate(start, end, progress, mutate) { 865 var func = isNaN(start + end) ? 0 : function (p) { 866 return (1 - p) * start + p * end; 867 }; 868 869 if (!func) { 870 var isString = _isString(start), 871 master = {}, 872 p, 873 i, 874 interpolators, 875 l, 876 il; 877 878 progress === true && (mutate = 1) && (progress = null); 879 880 if (isString) { 881 start = { 882 p: start 883 }; 884 end = { 885 p: end 886 }; 887 } else if (_isArray(start) && !_isArray(end)) { 888 interpolators = []; 889 l = start.length; 890 il = l - 2; 891 892 for (i = 1; i < l; i++) { 893 interpolators.push(interpolate(start[i - 1], start[i])); 894 } 895 896 l--; 897 898 func = function func(p) { 899 p *= l; 900 var i = Math.min(il, ~~p); 901 return interpolators[i](p - i); 902 }; 903 904 progress = end; 905 } else if (!mutate) { 906 start = _merge(_isArray(start) ? [] : {}, start); 907 } 908 909 if (!interpolators) { 910 for (p in end) { 911 _addPropTween.call(master, start, p, "get", end[p]); 912 } 913 914 func = function func(p) { 915 return _renderPropTweens(p, master) || (isString ? start.p : start); 916 }; 917 } 918 } 919 920 return _conditionalReturn(progress, func); 921 }, 922 _getLabelInDirection = function _getLabelInDirection(timeline, fromTime, backward) { 923 var labels = timeline.labels, 924 min = _bigNum, 925 p, 926 distance, 927 label; 928 929 for (p in labels) { 930 distance = labels[p] - fromTime; 931 932 if (distance < 0 === !!backward && distance && min > (distance = Math.abs(distance))) { 933 label = p; 934 min = distance; 935 } 936 } 937 938 return label; 939 }, 940 _callback = function _callback(animation, type, executeLazyFirst) { 941 var v = animation.vars, 942 callback = v[type], 943 prevContext = _context, 944 context = animation._ctx, 945 params, 946 scope, 947 result; 948 949 if (!callback) { 950 return; 951 } 952 953 params = v[type + "Params"]; 954 scope = v.callbackScope || animation; 955 executeLazyFirst && _lazyTweens.length && _lazyRender(); 956 context && (_context = context); 957 result = params ? callback.apply(scope, params) : callback.call(scope); 958 _context = prevContext; 959 return result; 960 }, 961 _interrupt = function _interrupt(animation) { 962 _removeFromParent(animation); 963 964 animation.scrollTrigger && animation.scrollTrigger.kill(!!_reverting); 965 animation.progress() < 1 && _callback(animation, "onInterrupt"); 966 return animation; 967 }, 968 _quickTween, 969 _registerPluginQueue = [], 970 _createPlugin = function _createPlugin(config) { 971 if (!config) return; 972 config = !config.name && config["default"] || config; 973 974 if (_windowExists() || config.headless) { 975 var name = config.name, 976 isFunc = _isFunction(config), 977 Plugin = name && !isFunc && config.init ? function () { 978 this._props = []; 979 } : config, 980 instanceDefaults = { 981 init: _emptyFunc, 982 render: _renderPropTweens, 983 add: _addPropTween, 984 kill: _killPropTweensOf, 985 modifier: _addPluginModifier, 986 rawVars: 0 987 }, 988 statics = { 989 targetTest: 0, 990 get: 0, 991 getSetter: _getSetter, 992 aliases: {}, 993 register: 0 994 }; 995 996 _wake(); 997 998 if (config !== Plugin) { 999 if (_plugins[name]) { 1000 return; 1001 } 1002 1003 _setDefaults(Plugin, _setDefaults(_copyExcluding(config, instanceDefaults), statics)); 1004 1005 _merge(Plugin.prototype, _merge(instanceDefaults, _copyExcluding(config, statics))); 1006 1007 _plugins[Plugin.prop = name] = Plugin; 1008 1009 if (config.targetTest) { 1010 _harnessPlugins.push(Plugin); 1011 1012 _reservedProps[name] = 1; 1013 } 1014 1015 name = (name === "css" ? "CSS" : name.charAt(0).toUpperCase() + name.substr(1)) + "Plugin"; 1016 } 1017 1018 _addGlobal(name, Plugin); 1019 1020 config.register && config.register(gsap, Plugin, PropTween); 1021 } else { 1022 _registerPluginQueue.push(config); 1023 } 1024 }, 1025 _255 = 255, 1026 _colorLookup = { 1027 aqua: [0, _255, _255], 1028 lime: [0, _255, 0], 1029 silver: [192, 192, 192], 1030 black: [0, 0, 0], 1031 maroon: [128, 0, 0], 1032 teal: [0, 128, 128], 1033 blue: [0, 0, _255], 1034 navy: [0, 0, 128], 1035 white: [_255, _255, _255], 1036 olive: [128, 128, 0], 1037 yellow: [_255, _255, 0], 1038 orange: [_255, 165, 0], 1039 gray: [128, 128, 128], 1040 purple: [128, 0, 128], 1041 green: [0, 128, 0], 1042 red: [_255, 0, 0], 1043 pink: [_255, 192, 203], 1044 cyan: [0, _255, _255], 1045 transparent: [_255, _255, _255, 0] 1046 }, 1047 _hue = function _hue(h, m1, m2) { 1048 h += h < 0 ? 1 : h > 1 ? -1 : 0; 1049 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; 1050 }, 1051 splitColor = function splitColor(v, toHSL, forceAlpha) { 1052 var a = !v ? _colorLookup.black : _isNumber(v) ? [v >> 16, v >> 8 & _255, v & _255] : 0, 1053 r, 1054 g, 1055 b, 1056 h, 1057 s, 1058 l, 1059 max, 1060 min, 1061 d, 1062 wasHSL; 1063 1064 if (!a) { 1065 if (v.substr(-1) === ",") { 1066 v = v.substr(0, v.length - 1); 1067 } 1068 1069 if (_colorLookup[v]) { 1070 a = _colorLookup[v]; 1071 } else if (v.charAt(0) === "#") { 1072 if (v.length < 6) { 1073 r = v.charAt(1); 1074 g = v.charAt(2); 1075 b = v.charAt(3); 1076 v = "#" + r + r + g + g + b + b + (v.length === 5 ? v.charAt(4) + v.charAt(4) : ""); 1077 } 1078 1079 if (v.length === 9) { 1080 a = parseInt(v.substr(1, 6), 16); 1081 return [a >> 16, a >> 8 & _255, a & _255, parseInt(v.substr(7), 16) / 255]; 1082 } 1083 1084 v = parseInt(v.substr(1), 16); 1085 a = [v >> 16, v >> 8 & _255, v & _255]; 1086 } else if (v.substr(0, 3) === "hsl") { 1087 a = wasHSL = v.match(_strictNumExp); 1088 1089 if (!toHSL) { 1090 h = +a[0] % 360 / 360; 1091 s = +a[1] / 100; 1092 l = +a[2] / 100; 1093 g = l <= .5 ? l * (s + 1) : l + s - l * s; 1094 r = l * 2 - g; 1095 a.length > 3 && (a[3] *= 1); 1096 a[0] = _hue(h + 1 / 3, r, g); 1097 a[1] = _hue(h, r, g); 1098 a[2] = _hue(h - 1 / 3, r, g); 1099 } else if (~v.indexOf("=")) { 1100 a = v.match(_numExp); 1101 forceAlpha && a.length < 4 && (a[3] = 1); 1102 return a; 1103 } 1104 } else { 1105 a = v.match(_strictNumExp) || _colorLookup.transparent; 1106 } 1107 1108 a = a.map(Number); 1109 } 1110 1111 if (toHSL && !wasHSL) { 1112 r = a[0] / _255; 1113 g = a[1] / _255; 1114 b = a[2] / _255; 1115 max = Math.max(r, g, b); 1116 min = Math.min(r, g, b); 1117 l = (max + min) / 2; 1118 1119 if (max === min) { 1120 h = s = 0; 1121 } else { 1122 d = max - min; 1123 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 1124 h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4; 1125 h *= 60; 1126 } 1127 1128 a[0] = ~~(h + .5); 1129 a[1] = ~~(s * 100 + .5); 1130 a[2] = ~~(l * 100 + .5); 1131 } 1132 1133 forceAlpha && a.length < 4 && (a[3] = 1); 1134 return a; 1135 }, 1136 _colorOrderData = function _colorOrderData(v) { 1137 var values = [], 1138 c = [], 1139 i = -1; 1140 v.split(_colorExp).forEach(function (v) { 1141 var a = v.match(_numWithUnitExp) || []; 1142 values.push.apply(values, a); 1143 c.push(i += a.length + 1); 1144 }); 1145 values.c = c; 1146 return values; 1147 }, 1148 _formatColors = function _formatColors(s, toHSL, orderMatchData) { 1149 var result = "", 1150 colors = (s + result).match(_colorExp), 1151 type = toHSL ? "hsla(" : "rgba(", 1152 i = 0, 1153 c, 1154 shell, 1155 d, 1156 l; 1157 1158 if (!colors) { 1159 return s; 1160 } 1161 1162 colors = colors.map(function (color) { 1163 return (color = splitColor(color, toHSL, 1)) && type + (toHSL ? color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : color.join(",")) + ")"; 1164 }); 1165 1166 if (orderMatchData) { 1167 d = _colorOrderData(s); 1168 c = orderMatchData.c; 1169 1170 if (c.join(result) !== d.c.join(result)) { 1171 shell = s.replace(_colorExp, "1").split(_numWithUnitExp); 1172 l = shell.length - 1; 1173 1174 for (; i < l; i++) { 1175 result += shell[i] + (~c.indexOf(i) ? colors.shift() || type + "0,0,0,0)" : (d.length ? d : colors.length ? colors : orderMatchData).shift()); 1176 } 1177 } 1178 } 1179 1180 if (!shell) { 1181 shell = s.split(_colorExp); 1182 l = shell.length - 1; 1183 1184 for (; i < l; i++) { 1185 result += shell[i] + colors[i]; 1186 } 1187 } 1188 1189 return result + shell[l]; 1190 }, 1191 _colorExp = function () { 1192 var s = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3,4}){1,2}\\b", 1193 p; 1194 1195 for (p in _colorLookup) { 1196 s += "|" + p + "\\b"; 1197 } 1198 1199 return new RegExp(s + ")", "gi"); 1200 }(), 1201 _hslExp = /hsl[a]?\(/, 1202 _colorStringFilter = function _colorStringFilter(a) { 1203 var combined = a.join(" "), 1204 toHSL; 1205 _colorExp.lastIndex = 0; 1206 1207 if (_colorExp.test(combined)) { 1208 toHSL = _hslExp.test(combined); 1209 a[1] = _formatColors(a[1], toHSL); 1210 a[0] = _formatColors(a[0], toHSL, _colorOrderData(a[1])); 1211 return true; 1212 } 1213 }, 1214 _tickerActive, 1215 _ticker = function () { 1216 var _getTime = Date.now, 1217 _lagThreshold = 500, 1218 _adjustedLag = 33, 1219 _startTime = _getTime(), 1220 _lastUpdate = _startTime, 1221 _gap = 1000 / 240, 1222 _nextTime = _gap, 1223 _listeners = [], 1224 _id, 1225 _req, 1226 _raf, 1227 _self, 1228 _delta, 1229 _i, 1230 _tick = function _tick(v) { 1231 var elapsed = _getTime() - _lastUpdate, 1232 manual = v === true, 1233 overlap, 1234 dispatch, 1235 time, 1236 frame; 1237 1238 (elapsed > _lagThreshold || elapsed < 0) && (_startTime += elapsed - _adjustedLag); 1239 _lastUpdate += elapsed; 1240 time = _lastUpdate - _startTime; 1241 overlap = time - _nextTime; 1242 1243 if (overlap > 0 || manual) { 1244 frame = ++_self.frame; 1245 _delta = time - _self.time * 1000; 1246 _self.time = time = time / 1000; 1247 _nextTime += overlap + (overlap >= _gap ? 4 : _gap - overlap); 1248 dispatch = 1; 1249 } 1250 1251 manual || (_id = _req(_tick)); 1252 1253 if (dispatch) { 1254 for (_i = 0; _i < _listeners.length; _i++) { 1255 _listeners[_i](time, _delta, frame, v); 1256 } 1257 } 1258 }; 1259 1260 _self = { 1261 time: 0, 1262 frame: 0, 1263 tick: function tick() { 1264 _tick(true); 1265 }, 1266 deltaRatio: function deltaRatio(fps) { 1267 return _delta / (1000 / (fps || 60)); 1268 }, 1269 wake: function wake() { 1270 if (_coreReady) { 1271 if (!_coreInitted && _windowExists()) { 1272 _win = _coreInitted = window; 1273 _doc = _win.document || {}; 1274 _globals.gsap = gsap; 1275 (_win.gsapVersions || (_win.gsapVersions = [])).push(gsap.version); 1276 1277 _install(_installScope || _win.GreenSockGlobals || !_win.gsap && _win || {}); 1278 1279 _registerPluginQueue.forEach(_createPlugin); 1280 } 1281 1282 _raf = typeof requestAnimationFrame !== "undefined" && requestAnimationFrame; 1283 _id && _self.sleep(); 1284 1285 _req = _raf || function (f) { 1286 return setTimeout(f, _nextTime - _self.time * 1000 + 1 | 0); 1287 }; 1288 1289 _tickerActive = 1; 1290 1291 _tick(2); 1292 } 1293 }, 1294 sleep: function sleep() { 1295 (_raf ? cancelAnimationFrame : clearTimeout)(_id); 1296 _tickerActive = 0; 1297 _req = _emptyFunc; 1298 }, 1299 lagSmoothing: function lagSmoothing(threshold, adjustedLag) { 1300 _lagThreshold = threshold || Infinity; 1301 _adjustedLag = Math.min(adjustedLag || 33, _lagThreshold); 1302 }, 1303 fps: function fps(_fps) { 1304 _gap = 1000 / (_fps || 240); 1305 _nextTime = _self.time * 1000 + _gap; 1306 }, 1307 add: function add(callback, once, prioritize) { 1308 var func = once ? function (t, d, f, v) { 1309 callback(t, d, f, v); 1310 1311 _self.remove(func); 1312 } : callback; 1313 1314 _self.remove(callback); 1315 1316 _listeners[prioritize ? "unshift" : "push"](func); 1317 1318 _wake(); 1319 1320 return func; 1321 }, 1322 remove: function remove(callback, i) { 1323 ~(i = _listeners.indexOf(callback)) && _listeners.splice(i, 1) && _i >= i && _i--; 1324 }, 1325 _listeners: _listeners 1326 }; 1327 return _self; 1328 }(), 1329 _wake = function _wake() { 1330 return !_tickerActive && _ticker.wake(); 1331 }, 1332 _easeMap = {}, 1333 _customEaseExp = /^[\d.\-M][\d.\-,\s]/, 1334 _quotesExp = /["']/g, 1335 _parseObjectInString = function _parseObjectInString(value) { 1336 var obj = {}, 1337 split = value.substr(1, value.length - 3).split(":"), 1338 key = split[0], 1339 i = 1, 1340 l = split.length, 1341 index, 1342 val, 1343 parsedVal; 1344 1345 for (; i < l; i++) { 1346 val = split[i]; 1347 index = i !== l - 1 ? val.lastIndexOf(",") : val.length; 1348 parsedVal = val.substr(0, index); 1349 obj[key] = isNaN(parsedVal) ? parsedVal.replace(_quotesExp, "").trim() : +parsedVal; 1350 key = val.substr(index + 1).trim(); 1351 } 1352 1353 return obj; 1354 }, 1355 _valueInParentheses = function _valueInParentheses(value) { 1356 var open = value.indexOf("(") + 1, 1357 close = value.indexOf(")"), 1358 nested = value.indexOf("(", open); 1359 return value.substring(open, ~nested && nested < close ? value.indexOf(")", close + 1) : close); 1360 }, 1361 _configEaseFromString = function _configEaseFromString(name) { 1362 var split = (name + "").split("("), 1363 ease = _easeMap[split[0]]; 1364 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; 1365 }, 1366 _invertEase = function _invertEase(ease) { 1367 return function (p) { 1368 return 1 - ease(1 - p); 1369 }; 1370 }, 1371 _p
1371ropagateYoyoEase = function _propagateYoyoEase(timeline, isYoyo) { 1372 var child = timeline._first, 1373 ease; 1374 1375 while (child) { 1376 if (child instanceof Timeline) { 1377 _propagateYoyoEase(child, isYoyo); 1378 } else if (child.vars.yoyoEase && (!child._yoyo || !child._repeat) && child._yoyo !== isYoyo) { 1379 if (child.timeline) { 1380 _propagateYoyoEase(child.timeline, isYoyo); 1381 } else { 1382 ease = child._ease; 1383 child._ease = child._yEase; 1384 child._yEase = ease; 1385 child._yoyo = isYoyo; 1386 } 1387 } 1388 1389 child = child._next; 1390 }
vendor: 3,445 bytes, lines 1390-1501
1390 1391 }, 1392 _parseEase = function _parseEase(ease, defaultEase) { 1393 return !ease ? defaultEase : (_isFunction(ease) ? ease : _easeMap[ease] || _configEaseFromString(ease)) || defaultEase; 1394 }, 1395 _insertEase = function _insertEase(names, easeIn, easeOut, easeInOut) { 1396 if (easeOut === void 0) { 1397 easeOut = function easeOut(p) { 1398 return 1 - easeIn(1 - p); 1399 }; 1400 } 1401 1402 if (easeInOut === void 0) { 1403 easeInOut = function easeInOut(p) { 1404 return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2; 1405 }; 1406 } 1407 1408 var ease = { 1409 easeIn: easeIn, 1410 easeOut: easeOut, 1411 easeInOut: easeInOut 1412 }, 1413 lowercaseName; 1414 1415 _forEachName(names, function (name) { 1416 _easeMap[name] = _globals[name] = ease; 1417 _easeMap[lowercaseName = name.toLowerCase()] = easeOut; 1418 1419 for (var p in ease) { 1420 _easeMap[lowercaseName + (p === "easeIn" ? ".in" : p === "easeOut" ? ".out" : ".inOut")] = _easeMap[name + "." + p] = ease[p]; 1421 } 1422 }); 1423 1424 return ease; 1425 }, 1426 _easeInOutFromOut = function _easeInOutFromOut(easeOut) { 1427 return function (p) { 1428 return p < .5 ? (1 - easeOut(1 - p * 2)) / 2 : .5 + easeOut((p - .5) * 2) / 2; 1429 }; 1430 }, 1431 _configElastic = function _configElastic(type, amplitude, period) { 1432 var p1 = amplitude >= 1 ? amplitude : 1, 1433 p2 = (period || (type ? .3 : .45)) / (amplitude < 1 ? amplitude : 1), 1434 p3 = p2 / _2PI * (Math.asin(1 / p1) || 0), 1435 easeOut = function easeOut(p) { 1436 return p === 1 ? 1 : p1 * Math.pow(2, -10 * p) * _sin((p - p3) * p2) + 1; 1437 }, 1438 ease = type === "out" ? easeOut : type === "in" ? function (p) { 1439 return 1 - easeOut(1 - p); 1440 } : _easeInOutFromOut(easeOut); 1441 1442 p2 = _2PI / p2; 1443 1444 ease.config = function (amplitude, period) { 1445 return _configElastic(type, amplitude, period); 1446 }; 1447 1448 return ease; 1449 }, 1450 _configBack = function _configBack(type, overshoot) { 1451 if (overshoot === void 0) { 1452 overshoot = 1.70158; 1453 } 1454 1455 var easeOut = function easeOut(p) { 1456 return p ? --p * p * ((overshoot + 1) * p + overshoot) + 1 : 0; 1457 }, 1458 ease = type === "out" ? easeOut : type === "in" ? function (p) { 1459 return 1 - easeOut(1 - p); 1460 } : _easeInOutFromOut(easeOut); 1461 1462 ease.config = function (overshoot) { 1463 return _configBack(type, overshoot); 1464 }; 1465 1466 return ease; 1467 }; 1468 1469 _forEachName("Linear,Quad,Cubic,Quart,Quint,Strong", function (name, i) { 1470 var power = i < 5 ? i + 1 : i; 1471 1472 _insertEase(name + ",Power" + (power - 1), i ? function (p) { 1473 return Math.pow(p, power); 1474 } : function (p) { 1475 return p; 1476 }, function (p) { 1477 return 1 - Math.pow(1 - p, power); 1478 }, function (p) { 1479 return p < .5 ? Math.pow(p * 2, power) / 2 : 1 - Math.pow((1 - p) * 2, power) / 2; 1480 }); 1481 }); 1482 1483 _easeMap.Linear.easeNone = _easeMap.none = _easeMap.Linear.easeIn; 1484 1485 _insertEase("Elastic", _configElastic("in"), _configElastic("out"), _configElastic()); 1486 1487 (function (n, c) { 1488 var n1 = 1 / c, 1489 n2 = 2 * n1, 1490 n3 = 2.5 * n1, 1491 easeOut = function easeOut(p) { 1492 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; 1493 }; 1494 1495 _insertEase("Bounce", function (p) { 1496 return 1 - easeOut(1 - p); 1497 }, easeOut); 1498 })(7.5625, 2.75); 1499 1500 _insertEase("Expo", function (p) { 1501 return
vendor: 18,509 bytes, lines 1501-2076
1501p ? Math.pow(2, 10 * (p - 1)) : 0; 1502 }); 1503 1504 _insertEase("Circ", function (p) { 1505 return -(_sqrt(1 - p * p) - 1); 1506 }); 1507 1508 _insertEase("Sine", function (p) { 1509 return p === 1 ? 1 : -_cos(p * _HALF_PI) + 1; 1510 }); 1511 1512 _insertEase("Back", _configBack("in"), _configBack("out"), _configBack()); 1513 1514 _easeMap.SteppedEase = _easeMap.steps = _globals.SteppedEase = { 1515 config: function config(steps, immediateStart) { 1516 if (steps === void 0) { 1517 steps = 1; 1518 } 1519 1520 var p1 = 1 / steps, 1521 p2 = steps + (immediateStart ? 0 : 1), 1522 p3 = immediateStart ? 1 : 0, 1523 max = 1 - _tinyNum; 1524 return function (p) { 1525 return ((p2 * _clamp(0, max, p) | 0) + p3) * p1; 1526 }; 1527 } 1528 }; 1529 _defaults.ease = _easeMap["quad.out"]; 1530 1531 _forEachName("onComplete,onUpdate,onStart,onRepeat,onReverseComplete,onInterrupt", function (name) { 1532 return _callbackNames += name + "," + name + "Params,"; 1533 }); 1534 1535 var GSCache = function GSCache(target, harness) { 1536 this.id = _gsID++; 1537 target._gsap = this; 1538 this.target = target; 1539 this.harness = harness; 1540 this.get = harness ? harness.get : _getProperty; 1541 this.set = harness ? harness.getSetter : _getSetter; 1542 }; 1543 var Animation = function () { 1544 function Animation(vars) { 1545 this.vars = vars; 1546 this._delay = +vars.delay || 0; 1547 1548 if (this._repeat = vars.repeat === Infinity ? -2 : vars.repeat || 0) { 1549 this._rDelay = vars.repeatDelay || 0; 1550 this._yoyo = !!vars.yoyo || !!vars.yoyoEase; 1551 } 1552 1553 this._ts = 1; 1554 1555 _setDuration(this, +vars.duration, 1, 1); 1556 1557 this.data = vars.data; 1558 1559 if (_context) { 1560 this._ctx = _context; 1561 1562 _context.data.push(this); 1563 } 1564 1565 _tickerActive || _ticker.wake(); 1566 } 1567 1568 var _proto = Animation.prototype; 1569 1570 _proto.delay = function delay(value) { 1571 if (value || value === 0) { 1572 this.parent && this.parent.smoothChildTiming && this.startTime(this._start + value - this._delay); 1573 this._delay = value; 1574 return this; 1575 } 1576 1577 return this._delay; 1578 }; 1579 1580 _proto.duration = function duration(value) { 1581 return arguments.length ? this.totalDuration(this._repeat > 0 ? value + (value + this._rDelay) * this._repeat : value) : this.totalDuration() && this._dur; 1582 }; 1583 1584 _proto.totalDuration = function totalDuration(value) { 1585 if (!arguments.length) { 1586 return this._tDur; 1587 } 1588 1589 this._dirty = 0; 1590 return _setDuration(this, this._repeat < 0 ? value : (value - this._repeat * this._rDelay) / (this._repeat + 1)); 1591 }; 1592 1593 _proto.totalTime = function totalTime(_totalTime, suppressEvents) { 1594 _wake(); 1595 1596 if (!arguments.length) { 1597 return this._tTime; 1598 } 1599 1600 var parent = this._dp; 1601 1602 if (parent && parent.smoothChildTiming && this._ts) { 1603 _alignPlayhead(this, _totalTime); 1604 1605 !parent._dp || parent.parent || _postAddChecks(parent, this); 1606 1607 while (parent && parent.parent) { 1608 if (parent.parent._time !== parent._start + (parent._ts >= 0 ? parent._tTime / parent._ts : (parent.totalDuration() - parent._tTime) / -parent._ts)) { 1609 parent.totalTime(parent._tTime, true); 1610 } 1611 1612 parent = parent.parent; 1613 } 1614 1615 if (!this.parent && this._dp.autoRemoveChildren && (this._ts > 0 && _totalTime < this._tDur || this._ts < 0 && _totalTime > 0 || !this._tDur && !_totalTime)) { 1616 _addToTimeline(this._dp, this, this._start - this._delay); 1617 } 1618 } 1619 1620 if (this._tTime !== _totalTime || !this._dur && !suppressEvents || this._initted && Math.abs(this._zTime) === _tinyNum || !_totalTime && !this._initted && (this.add || this._ptLookup)) { 1621 this._ts || (this._pTime = _totalTime); 1622 1623 _lazySafeRender(this, _totalTime, suppressEvents); 1624 } 1625 1626 return this; 1627 }; 1628 1629 _proto.time = function time(value, suppressEvents) { 1630 return arguments.length ? this.totalTime(Math.min(this.totalDuration(), value + _elapsedCycleDuration(this)) % (this._dur + this._rDelay) || (value ? this._dur : 0), suppressEvents) : this._time; 1631 }; 1632 1633 _proto.totalProgress = function totalProgress(value, suppressEvents) { 1634 return arguments.length ? this.totalTime(this.totalDuration() * value, suppressEvents) : this.totalDuration() ? Math.min(1, this._tTime / this._tDur) : this.rawTime() > 0 ? 1 : 0; 1635 }; 1636 1637 _proto.progress = function progress(value, suppressEvents) { 1638 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.rawTime() > 0 ? 1 : 0; 1639 }; 1640 1641 _proto.iteration = function iteration(value, suppressEvents) { 1642 var cycleDuration = this.duration() + this._rDelay; 1643 1644 return arguments.length ? this.totalTime(this._time + (value - 1) * cycleDuration, suppressEvents) : this._repeat ? _animationCycle(this._tTime, cycleDuration) + 1 : 1; 1645 }; 1646 1647 _proto.timeScale = function timeScale(value, suppressEvents) { 1648 if (!arguments.length) { 1649 return this._rts === -_tinyNum ? 0 : this._rts; 1650 } 1651 1652 if (this._rts === value) { 1653 return this; 1654 } 1655 1656 var tTime = this.parent && this._ts ? _parentToChildTotalTime(this.parent._time, this) : this._tTime; 1657 this._rts = +value || 0; 1658 this._ts = this._ps || value === -_tinyNum ? 0 : this._rts; 1659 this.totalTime(_clamp(-Math.abs(this._delay), this._tDur, tTime), suppressEvents !== false); 1660 1661 _setEnd(this); 1662 1663 return _recacheAncestors(this); 1664 }; 1665 1666 _proto.paused = function paused(value) { 1667 if (!arguments.length) { 1668 return this._ps; 1669 } 1670 1671 if (this._ps !== value) { 1672 this._ps = value; 1673 1674 if (value) { 1675 this._pTime = this._tTime || Math.max(-this._delay, this.rawTime()); 1676 this._ts = this._act = 0; 1677 } else { 1678 _wake(); 1679 1680 this._ts = this._rts; 1681 this.totalTime(this.parent && !this.parent.smoothChildTiming ? this.rawTime() : this._tTime || this._pTime, this.progress() === 1 && Math.abs(this._zTime) !== _tinyNum && (this._tTime -= _tinyNum)); 1682 } 1683 } 1684 1685 return this; 1686 }; 1687 1688 _proto.startTime = function startTime(value) { 1689 if (arguments.length) { 1690 this._start = value; 1691 var parent = this.parent || this._dp; 1692 parent && (parent._sort || !this.parent) && _addToTimeline(parent, this, value - this._delay); 1693 return this; 1694 } 1695 1696 return this._start; 1697 }; 1698 1699 _proto.endTime = function endTime(includeRepeats) { 1700 return this._start + (_isNotFalse(includeRepeats) ? this.totalDuration() : this.duration()) / Math.abs(this._ts || 1); 1701 }; 1702 1703 _proto.rawTime = function rawTime(wrapRepeats) { 1704 var parent = this.parent || this._dp; 1705 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); 1706 }; 1707 1708 _proto.revert = function revert(config) { 1709 if (config === void 0) { 1710 config = _revertConfig; 1711 } 1712 1713 var prevIsReverting = _reverting; 1714 _reverting = config; 1715 1716 if (this._initted || this._startAt) { 1717 this.timeline && this.timeline.revert(config); 1718 this.totalTime(-0.01, config.suppressEvents); 1719 } 1720 1721 this.data !== "nested" && config.kill !== false && this.kill(); 1722 _reverting = prevIsReverting; 1723 return this; 1724 }; 1725 1726 _proto.globalTime = function globalTime(rawTime) { 1727 var animation = this, 1728 time = arguments.length ? rawTime : animation.rawTime(); 1729 1730 while (animation) { 1731 time = animation._start + time / (Math.abs(animation._ts) || 1); 1732 animation = animation._dp; 1733 } 1734 1735 return !this.parent && this._sat ? this._sat.globalTime(rawTime) : time; 1736 }; 1737 1738 _proto.repeat = function repeat(value) { 1739 if (arguments.length) { 1740 this._repeat = value === Infinity ? -2 : value; 1741 return _onUpdateTotalDuration(this); 1742 } 1743 1744 return this._repeat === -2 ? Infinity : this._repeat; 1745 }; 1746 1747 _proto.repeatDelay = function repeatDelay(value) { 1748 if (arguments.length) { 1749 var time = this._time; 1750 this._rDelay = value; 1751 1752 _onUpdateTotalDuration(this); 1753 1754 return time ? this.time(time) : this; 1755 } 1756 1757 return this._rDelay; 1758 }; 1759 1760 _proto.yoyo = function yoyo(value) { 1761 if (arguments.length) { 1762 this._yoyo = value; 1763 return this; 1764 } 1765 1766 return this._yoyo; 1767 }; 1768 1769 _proto.seek = function seek(position, suppressEvents) { 1770 return this.totalTime(_parsePosition(this, position), _isNotFalse(suppressEvents)); 1771 }; 1772 1773 _proto.restart = function restart(includeDelay, suppressEvents) { 1774 return this.play().totalTime(includeDelay ? -this._delay : 0, _isNotFalse(suppressEvents)); 1775 }; 1776 1777 _proto.play = function play(from, suppressEvents) { 1778 from != null && this.seek(from, suppressEvents); 1779 return this.reversed(false).paused(false); 1780 }; 1781 1782 _proto.reverse = function reverse(from, suppressEvents) { 1783 from != null && this.seek(from || this.totalDuration(), suppressEvents); 1784 return this.reversed(true).paused(false); 1785 }; 1786 1787 _proto.pause = function pause(atTime, suppressEvents) { 1788 atTime != null && this.seek(atTime, suppressEvents); 1789 return this.paused(true); 1790 }; 1791 1792 _proto.resume = function resume() { 1793 return this.paused(false); 1794 }; 1795 1796 _proto.reversed = function reversed(value) { 1797 if (arguments.length) { 1798 !!value !== this.reversed() && this.timeScale(-this._rts || (value ? -_tinyNum : 0)); 1799 return this; 1800 } 1801 1802 return this._rts < 0; 1803 }; 1804 1805 _proto.invalidate = function invalidate() { 1806 this._initted = this._act = 0; 1807 this._zTime = -_tinyNum; 1808 return this; 1809 }; 1810 1811 _proto.isActive = function isActive() { 1812 var parent = this.parent || this._dp, 1813 start = this._start, 1814 rawTime; 1815 return !!(!parent || this._ts && this._initted && parent.isActive() && (rawTime = parent.rawTime(true)) >= start && rawTime < this.endTime(true) - _tinyNum); 1816 }; 1817 1818 _proto.eventCallback = function eventCallback(type, callback, params) { 1819 var vars = this.vars; 1820 1821 if (arguments.length > 1) { 1822 if (!callback) { 1823 delete vars[type]; 1824 } else { 1825 vars[type] = callback; 1826 params && (vars[type + "Params"] = params); 1827 type === "onUpdate" && (this._onUpdate = callback); 1828 } 1829 1830 return this; 1831 } 1832 1833 return vars[type]; 1834 }; 1835 1836 _proto.then = function then(onFulfilled) { 1837 var self = this; 1838 return new Promise(function (resolve) { 1839 var f = _isFunction(onFulfilled) ? onFulfilled : _passThrough, 1840 _resolve = function _resolve() { 1841 var _then = self.then; 1842 self.then = null; 1843 _isFunction(f) && (f = f(self)) && (f.then || f === self) && (self.then = _then); 1844 resolve(f); 1845 self.then = _then; 1846 }; 1847 1848 if (self._initted && self.totalProgress() === 1 && self._ts >= 0 || !self._tTime && self._ts < 0) { 1849 _resolve(); 1850 } else { 1851 self._prom = _resolve; 1852 } 1853 }); 1854 }; 1855 1856 _proto.kill = function kill() { 1857 _interrupt(this); 1858 }; 1859 1860 return Animation; 1861 }(); 1862 1863 _setDefaults(Animation.prototype, { 1864 _time: 0, 1865 _start: 0, 1866 _end: 0, 1867 _tTime: 0, 1868 _tDur: 0, 1869 _dirty: 0, 1870 _repeat: 0, 1871 _yoyo: false, 1872 parent: null, 1873 _initted: false, 1874 _rDelay: 0, 1875 _ts: 1, 1876 _dp: 0, 1877 ratio: 0, 1878 _zTime: -_tinyNum, 1879 _prom: 0, 1880 _ps: false, 1881 _rts: 1 1882 }); 1883 1884 var Timeline = function (_Animation) { 1885 _inheritsLoose(Timeline, _Animation); 1886 1887 function Timeline(vars, position) { 1888 var _this; 1889 1890 if (vars === void 0) { 1891 vars = {}; 1892 } 1893 1894 _this = _Animation.call(this, vars) || this; 1895 _this.labels = {}; 1896 _this.smoothChildTiming = !!vars.smoothChildTiming; 1897 _this.autoRemoveChildren = !!vars.autoRemoveChildren; 1898 _this._sort = _isNotFalse(vars.sortChildren); 1899 _globalTimeline && _addToTimeline(vars.parent || _globalTimeline, _assertThisInitialized(_this), position); 1900 vars.reversed && _this.reverse(); 1901 vars.paused && _this.paused(true); 1902 vars.scrollTrigger && _scrollTrigger(_assertThisInitialized(_this), vars.scrollTrigger); 1903 return _this; 1904 } 1905 1906 var _proto2 = Timeline.prototype; 1907 1908 _proto2.to = function to(targets, vars, position) { 1909 _createTweenType(0, arguments, this); 1910 1911 return this; 1912 }; 1913 1914 _proto2.from = function from(targets, vars, position) { 1915 _createTweenType(1, arguments, this); 1916 1917 return this; 1918 }; 1919 1920 _proto2.fromTo = function fromTo(targets, fromVars, toVars, position) { 1921 _createTweenType(2, arguments, this); 1922 1923 return this; 1924 }; 1925 1926 _proto2.set = function set(targets, vars, position) { 1927 vars.duration = 0; 1928 vars.parent = this; 1929 _inheritDefaults(vars).repeatDelay || (vars.repeat = 0); 1930 vars.immediateRender = !!vars.immediateRender; 1931 new Tween(targets, vars, _parsePosition(this, position), 1); 1932 return this; 1933 }; 1934 1935 _proto2.call = function call(callback, params, position) { 1936 return _addToTimeline(this, Tween.delayedCall(0, callback, params), position); 1937 }; 1938 1939 _proto2.staggerTo = function staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) { 1940 vars.duration = duration; 1941 vars.stagger = vars.stagger || stagger; 1942 vars.onComplete = onCompleteAll; 1943 vars.onCompleteParams = onCompleteAllParams; 1944 vars.parent = this; 1945 new Tween(targets, vars, _parsePosition(this, position)); 1946 return this; 1947 }; 1948 1949 _proto2.staggerFrom = function staggerFrom(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) { 1950 vars.runBackwards = 1; 1951 _inheritDefaults(vars).immediateRender = _isNotFalse(vars.immediateRender); 1952 return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams); 1953 }; 1954 1955 _proto2.staggerFromTo = function staggerFromTo(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams) { 1956 toVars.startAt = fromVars; 1957 _inheritDefaults(toVars).immediateRender = _isNotFalse(toVars.immediateRender); 1958 return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams); 1959 }; 1960 1961 _proto2.render = function render(totalTime, suppressEvents, force) { 1962 var prevTime = this._time, 1963 tDur = this._dirty ? this.totalDuration() : this._tDur, 1964 dur = this._dur, 1965 tTime = totalTime <= 0 ? 0 : _roundPrecise(totalTime), 1966 crossingStart = this._zTime < 0 !== totalTime < 0 && (this._initted || !dur), 1967 time, 1968 child, 1969 next, 1970 iteration, 1971 cycleDuration, 1972 prevPaused, 1973 pauseTween, 1974 timeScale, 1975 prevStart, 1976 prevIteration, 1977 yoyo, 1978 isYoyo; 1979 this !== _globalTimeline && tTime > tDur && totalTime >= 0 && (tTime = tDur); 1980 1981 if (tTime !== this._tTime || force || crossingStart) { 1982 if (prevTime !== this._time && dur) { 1983 tTime += this._time - prevTime; 1984 totalTime += this._time - prevTime; 1985 } 1986 1987 time = tTime; 1988 prevStart = this._start; 1989 timeScale = this._ts; 1990 prevPaused = !timeScale; 1991 1992 if (crossingStart) { 1993 dur || (prevTime = this._zTime); 1994 (totalTime || !suppressEvents) && (this._zTime = totalTime); 1995 } 1996 1997 if (this._repeat) { 1998 yoyo = this._yoyo; 1999 cycleDuration = dur + this._rDelay; 2000 2001 if (this._repeat < -1 && totalTime < 0) { 2002 return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force); 2003 } 2004 2005 time = _roundPrecise(tTime % cycleDuration); 2006 2007 if (tTime === tDur) { 2008 iteration = this._repeat; 2009 time = dur; 2010 } else { 2011 iteration = ~~(tTime / cycleDuration); 2012 2013 if (iteration && iteration === tTime / cycleDuration) { 2014 time = dur; 2015 iteration--; 2016 } 2017 2018 time > dur && (time = dur); 2019 } 2020 2021 prevIteration = _animationCycle(this._tTime, cycleDuration); 2022 !prevTime && this._tTime && prevIteration !== iteration && this._tTime - prevIteration * cycleDuration - this._dur <= 0 && (prevIteration = iteration); 2023 2024 if (yoyo && iteration & 1) { 2025 time = dur - time; 2026 isYoyo = 1; 2027 } 2028 2029 if (iteration !== prevIteration && !this._lock) { 2030 var rewinding = yoyo && prevIteration & 1, 2031 doesWrap = rewinding === (yoyo && iteration & 1); 2032 iteration < prevIteration && (rewinding = !rewinding); 2033 prevTime = rewinding ? 0 : tTime % dur ? dur : tTime; 2034 this._lock = 1; 2035 this.render(prevTime || (isYoyo ? 0 : _roundPrecise(iteration * cycleDuration)), suppressEvents, !dur)._lock = 0; 2036 this._tTime = tTime; 2037 !suppressEvents && this.parent && _callback(this, "onRepeat"); 2038 this.vars.repeatRefresh && !isYoyo && (this.invalidate()._lock = 1); 2039 2040 if (prevTime && prevTime !== this._time || prevPaused !== !this._ts || this.vars.onRepeat && !this.parent && !this._act) { 2041 return this; 2042 } 2043 2044 dur = this._dur; 2045 tDur = this._tDur; 2046 2047 if (doesWrap) { 2048 this._lock = 2; 2049 prevTime = rewinding ? dur : -0.0001; 2050 this.render(prevTime, true); 2051 this.vars.repeatRefresh && !isYoyo && this.invalidate(); 2052 } 2053 2054 this._lock = 0; 2055 2056 if (!this._ts && !prevPaused) { 2057 return this; 2058 } 2059 2060 _propagateYoyoEase(this, isYoyo); 2061 } 2062 } 2063 2064 if (this._hasPause && !this._forcing && this._lock < 2) { 2065 pauseTween = _findNextPauseTween(this, _roundPrecise(prevTime), _roundPrecise(time)); 2066 2067 if (pauseTween) { 2068 tTime -= time - (time = pauseTween._start); 2069 } 2070 } 2071 2072 this._tTime = tTime; 2073 this._time = time; 2074 this._act = !timeScale; 2075 2076 if (!this._initted) {
vendor: 30,026 bytes, lines 2077-3039
2077 this._onUpdate = this.vars.onUpdate; 2078 this._initted = 1; 2079 this._zTime = totalTime; 2080 prevTime = 0; 2081 } 2082 2083 if (!prevTime && time && !suppressEvents && !iteration) { 2084 _callback(this, "onStart"); 2085 2086 if (this._tTime !== tTime) { 2087 return this; 2088 } 2089 } 2090 2091 if (time >= prevTime && totalTime >= 0) { 2092 child = this._first; 2093 2094 while (child) { 2095 next = child._next; 2096 2097 if ((child._act || time >= child._start) && child._ts && pauseTween !== child) { 2098 if (child.parent !== this) { 2099 return this.render(totalTime, suppressEvents, force); 2100 } 2101 2102 child.render(child._ts > 0 ? (time - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (time - child._start) * child._ts, suppressEvents, force); 2103 2104 if (time !== this._time || !this._ts && !prevPaused) { 2105 pauseTween = 0; 2106 next && (tTime += this._zTime = -_tinyNum); 2107 break; 2108 } 2109 } 2110 2111 child = next; 2112 } 2113 } else { 2114 child = this._last; 2115 var adjustedTime = totalTime < 0 ? totalTime : time; 2116 2117 while (child) { 2118 next = child._prev; 2119 2120 if ((child._act || adjustedTime <= child._end) && child._ts && pauseTween !== child) { 2121 if (child.parent !== this) { 2122 return this.render(totalTime, suppressEvents, force); 2123 } 2124 2125 child.render(child._ts > 0 ? (adjustedTime - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (adjustedTime - child._start) * child._ts, suppressEvents, force || _reverting && (child._initted || child._startAt)); 2126 2127 if (time !== this._time || !this._ts && !prevPaused) { 2128 pauseTween = 0; 2129 next && (tTime += this._zTime = adjustedTime ? -_tinyNum : _tinyNum); 2130 break; 2131 } 2132 } 2133 2134 child = next; 2135 } 2136 } 2137 2138 if (pauseTween && !suppressEvents) { 2139 this.pause(); 2140 pauseTween.render(time >= prevTime ? 0 : -_tinyNum)._zTime = time >= prevTime ? 1 : -1; 2141 2142 if (this._ts) { 2143 this._start = prevStart; 2144 2145 _setEnd(this); 2146 2147 return this.render(totalTime, suppressEvents, force); 2148 } 2149 } 2150 2151 this._onUpdate && !suppressEvents && _callback(this, "onUpdate", true); 2152 if (tTime === tDur && this._tTime >= this.totalDuration() || !tTime && prevTime) if (prevStart === this._start || Math.abs(timeScale) !== Math.abs(this._ts)) if (!this._lock) { 2153 (totalTime || !dur) && (tTime === tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1); 2154 2155 if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime || !tDur)) { 2156 _callback(this, tTime === tDur && totalTime >= 0 ? "onComplete" : "onReverseComplete", true); 2157 2158 this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom(); 2159 } 2160 } 2161 } 2162 2163 return this; 2164 }; 2165 2166 _proto2.add = function add(child, position) { 2167 var _this2 = this; 2168 2169 _isNumber(position) || (position = _parsePosition(this, position, child)); 2170 2171 if (!(child instanceof Animation)) { 2172 if (_isArray(child)) { 2173 child.forEach(function (obj) { 2174 return _this2.add(obj, position); 2175 }); 2176 return this; 2177 } 2178 2179 if (_isString(child)) { 2180 return this.addLabel(child, position); 2181 } 2182 2183 if (_isFunction(child)) { 2184 child = Tween.delayedCall(0, child); 2185 } else { 2186 return this; 2187 } 2188 } 2189 2190 return this !== child ? _addToTimeline(this, child, position) : this; 2191 }; 2192 2193 _proto2.getChildren = function getChildren(nested, tweens, timelines, ignoreBeforeTime) { 2194 if (nested === void 0) { 2195 nested = true; 2196 } 2197 2198 if (tweens === void 0) { 2199 tweens = true; 2200 } 2201 2202 if (timelines === void 0) { 2203 timelines = true; 2204 } 2205 2206 if (ignoreBeforeTime === void 0) { 2207 ignoreBeforeTime = -_bigNum; 2208 } 2209 2210 var a = [], 2211 child = this._first; 2212 2213 while (child) { 2214 if (child._start >= ignoreBeforeTime) { 2215 if (child instanceof Tween) { 2216 tweens && a.push(child); 2217 } else { 2218 timelines && a.push(child); 2219 nested && a.push.apply(a, child.getChildren(true, tweens, timelines)); 2220 } 2221 } 2222 2223 child = child._next; 2224 } 2225 2226 return a; 2227 }; 2228 2229 _proto2.getById = function getById(id) { 2230 var animations = this.getChildren(1, 1, 1), 2231 i = animations.length; 2232 2233 while (i--) { 2234 if (animations[i].vars.id === id) { 2235 return animations[i]; 2236 } 2237 } 2238 }; 2239 2240 _proto2.remove = function remove(child) { 2241 if (_isString(child)) { 2242 return this.removeLabel(child); 2243 } 2244 2245 if (_isFunction(child)) { 2246 return this.killTweensOf(child); 2247 } 2248 2249 _removeLinkedListItem(this, child); 2250 2251 if (child === this._recent) { 2252 this._recent = this._last; 2253 } 2254 2255 return _uncache(this); 2256 }; 2257 2258 _proto2.totalTime = function totalTime(_totalTime2, suppressEvents) { 2259 if (!arguments.length) { 2260 return this._tTime; 2261 } 2262 2263 this._forcing = 1; 2264 2265 if (!this._dp && this._ts) { 2266 this._start = _roundPrecise(_ticker.time - (this._ts > 0 ? _totalTime2 / this._ts : (this.totalDuration() - _totalTime2) / -this._ts)); 2267 } 2268 2269 _Animation.prototype.totalTime.call(this, _totalTime2, suppressEvents); 2270 2271 this._forcing = 0; 2272 return this; 2273 }; 2274 2275 _proto2.addLabel = function addLabel(label, position) { 2276 this.labels[label] = _parsePosition(this, position); 2277 return this; 2278 }; 2279 2280 _proto2.removeLabel = function removeLabel(label) { 2281 delete this.labels[label]; 2282 return this; 2283 }; 2284 2285 _proto2.addPause = function addPause(position, callback, params) { 2286 var t = Tween.delayedCall(0, callback || _emptyFunc, params); 2287 t.data = "isPause"; 2288 this._hasPause = 1; 2289 return _addToTimeline(this, t, _parsePosition(this, position)); 2290 }; 2291 2292 _proto2.removePause = function removePause(position) { 2293 var child = this._first; 2294 position = _parsePosition(this, position); 2295 2296 while (child) { 2297 if (child._start === position && child.data === "isPause") { 2298 _removeFromParent(child); 2299 } 2300 2301 child = child._next; 2302 } 2303 }; 2304 2305 _proto2.killTweensOf = function killTweensOf(targets, props, onlyActive) { 2306 var tweens = this.getTweensOf(targets, onlyActive), 2307 i = tweens.length; 2308 2309 while (i--) { 2310 _overwritingTween !== tweens[i] && tweens[i].kill(targets, props); 2311 } 2312 2313 return this; 2314 }; 2315 2316 _proto2.getTweensOf = function getTweensOf(targets, onlyActive) { 2317 var a = [], 2318 parsedTargets = toArray(targets), 2319 child = this._first, 2320 isGlobalTime = _isNumber(onlyActive), 2321 children; 2322 2323 while (child) { 2324 if (child instanceof Tween) { 2325 if (_arrayContainsAny(child._targets, parsedTargets) && (isGlobalTime ? (!_overwritingTween || child._initted && child._ts) && child.globalTime(0) <= onlyActive && child.globalTime(child.totalDuration()) > onlyActive : !onlyActive || child.isActive())) { 2326 a.push(child); 2327 } 2328 } else if ((children = child.getTweensOf(parsedTargets, onlyActive)).length) { 2329 a.push.apply(a, children); 2330 } 2331 2332 child = child._next; 2333 } 2334 2335 return a; 2336 }; 2337 2338 _proto2.tweenTo = function tweenTo(position, vars) { 2339 vars = vars || {}; 2340 2341 var tl = this, 2342 endTime = _parsePosition(tl, position), 2343 _vars = vars, 2344 startAt = _vars.startAt, 2345 _onStart = _vars.onStart, 2346 onStartParams = _vars.onStartParams, 2347 immediateRender = _vars.immediateRender, 2348 initted, 2349 tween = Tween.to(tl, _setDefaults({ 2350 ease: vars.ease || "none", 2351 lazy: false, 2352 immediateRender: false, 2353 time: endTime, 2354 overwrite: "auto", 2355 duration: vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()) || _tinyNum, 2356 onStart: function onStart() { 2357 tl.pause(); 2358 2359 if (!initted) { 2360 var duration = vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()); 2361 tween._dur !== duration && _setDuration(tween, duration, 0, 1).render(tween._time, true, true); 2362 initted = 1; 2363 } 2364 2365 _onStart && _onStart.apply(tween, onStartParams || []); 2366 } 2367 }, vars)); 2368 2369 return immediateRender ? tween.render(0) : tween; 2370 }; 2371 2372 _proto2.tweenFromTo = function tweenFromTo(fromPosition, toPosition, vars) { 2373 return this.tweenTo(toPosition, _setDefaults({ 2374 startAt: { 2375 time: _parsePosition(this, fromPosition) 2376 } 2377 }, vars)); 2378 }; 2379 2380 _proto2.recent = function recent() { 2381 return this._recent; 2382 }; 2383 2384 _proto2.nextLabel = function nextLabel(afterTime) { 2385 if (afterTime === void 0) { 2386 afterTime = this._time; 2387 } 2388 2389 return _getLabelInDirection(this, _parsePosition(this, afterTime)); 2390 }; 2391 2392 _proto2.previousLabel = function previousLabel(beforeTime) { 2393 if (beforeTime === void 0) { 2394 beforeTime = this._time; 2395 } 2396 2397 return _getLabelInDirection(this, _parsePosition(this, beforeTime), 1); 2398 }; 2399 2400 _proto2.currentLabel = function currentLabel(value) { 2401 return arguments.length ? this.seek(value, true) : this.previousLabel(this._time + _tinyNum); 2402 }; 2403 2404 _proto2.shiftChildren = function shiftChildren(amount, adjustLabels, ignoreBeforeTime) { 2405 if (ignoreBeforeTime === void 0) { 2406 ignoreBeforeTime = 0; 2407 } 2408 2409 var child = this._first, 2410 labels = this.labels, 2411 p; 2412 2413 while (child) { 2414 if (child._start >= ignoreBeforeTime) { 2415 child._start += amount; 2416 child._end += amount; 2417 } 2418 2419 child = child._next; 2420 } 2421 2422 if (adjustLabels) { 2423 for (p in labels) { 2424 if (labels[p] >= ignoreBeforeTime) { 2425 labels[p] += amount; 2426 } 2427 } 2428 } 2429 2430 return _uncache(this); 2431 }; 2432 2433 _proto2.invalidate = function invalidate(soft) { 2434 var child = this._first; 2435 this._lock = 0; 2436 2437 while (child) { 2438 child.invalidate(soft); 2439 child = child._next; 2440 } 2441 2442 return _Animation.prototype.invalidate.call(this, soft); 2443 }; 2444 2445 _proto2.clear = function clear(includeLabels) { 2446 if (includeLabels === void 0) { 2447 includeLabels = true; 2448 } 2449 2450 var child = this._first, 2451 next; 2452 2453 while (child) { 2454 next = child._next; 2455 this.remove(child); 2456 child = next; 2457 } 2458 2459 this._dp && (this._time = this._tTime = this._pTime = 0); 2460 includeLabels && (this.labels = {}); 2461 return _uncache(this); 2462 }; 2463 2464 _proto2.totalDuration = function totalDuration(value) { 2465 var max = 0, 2466 self = this, 2467 child = self._last, 2468 prevStart = _bigNum, 2469 prev, 2470 start, 2471 parent; 2472 2473 if (arguments.length) { 2474 return self.timeScale((self._repeat < 0 ? self.duration() : self.totalDuration()) / (self.reversed() ? -value : value)); 2475 } 2476 2477 if (self._dirty) { 2478 parent = self.parent; 2479 2480 while (child) { 2481 prev = child._prev; 2482 child._dirty && child.totalDuration(); 2483 start = child._start; 2484 2485 if (start > prevStart && self._sort && child._ts && !self._lock) { 2486 self._lock = 1; 2487 _addToTimeline(self, child, start - child._delay, 1)._lock = 0; 2488 } else { 2489 prevStart = start; 2490 } 2491 2492 if (start < 0 && child._ts) { 2493 max -= start; 2494 2495 if (!parent && !self._dp || parent && parent.smoothChildTiming) { 2496 self._start += start / self._ts; 2497 self._time -= start; 2498 self._tTime -= start; 2499 } 2500 2501 self.shiftChildren(-start, false, -1e999); 2502 prevStart = 0; 2503 } 2504 2505 child._end > max && child._ts && (max = child._end); 2506 child = prev; 2507 } 2508 2509 _setDuration(self, self === _globalTimeline && self._time > max ? self._time : max, 1, 1); 2510 2511 self._dirty = 0; 2512 } 2513 2514 return self._tDur; 2515 }; 2516 2517 Timeline.updateRoot = function updateRoot(time) { 2518 if (_globalTimeline._ts) { 2519 _lazySafeRender(_globalTimeline, _parentToChildTotalTime(time, _globalTimeline)); 2520 2521 _lastRenderedFrame = _ticker.frame; 2522 } 2523 2524 if (_ticker.frame >= _nextGCFrame) { 2525 _nextGCFrame += _config.autoSleep || 120; 2526 var child = _globalTimeline._first; 2527 if (!child || !child._ts) if (_config.autoSleep && _ticker._listeners.length < 2) { 2528 while (child && !child._ts) { 2529 child = child._next; 2530 } 2531 2532 child || _ticker.sleep(); 2533 } 2534 } 2535 }; 2536 2537 return Timeline; 2538 }(Animation); 2539 2540 _setDefaults(Timeline.prototype, { 2541 _lock: 0, 2542 _hasPause: 0, 2543 _forcing: 0 2544 }); 2545 2546 var _addComplexStringPropTween = function _addComplexStringPropTween(target, prop, start, end, setter, stringFilter, funcParam) { 2547 var pt = new PropTween(this._pt, target, prop, 0, 1, _renderComplexString, null, setter), 2548 index = 0, 2549 matchIndex = 0, 2550 result, 2551 startNums, 2552 color, 2553 endNum, 2554 chunk, 2555 startNum, 2556 hasRandom, 2557 a; 2558 pt.b = start; 2559 pt.e = end; 2560 start += ""; 2561 end += ""; 2562 2563 if (hasRandom = ~end.indexOf("random(")) { 2564 end = _replaceRandom(end); 2565 } 2566 2567 if (stringFilter) { 2568 a = [start, end]; 2569 stringFilter(a, target, prop); 2570 start = a[0]; 2571 end = a[1]; 2572 } 2573 2574 startNums = start.match(_complexStringNumExp) || []; 2575 2576 while (result = _complexStringNumExp.exec(end)) { 2577 endNum = result[0]; 2578 chunk = end.substring(index, result.index); 2579 2580 if (color) { 2581 color = (color + 1) % 5; 2582 } else if (chunk.substr(-5) === "rgba(") { 2583 color = 1; 2584 } 2585 2586 if (endNum !== startNums[matchIndex++]) { 2587 startNum = parseFloat(startNums[matchIndex - 1]) || 0; 2588 pt._pt = { 2589 _next: pt._pt, 2590 p: chunk || matchIndex === 1 ? chunk : ",", 2591 s: startNum, 2592 c: endNum.charAt(1) === "=" ? _parseRelative(startNum, endNum) - startNum : parseFloat(endNum) - startNum, 2593 m: color && color < 4 ? Math.round : 0 2594 }; 2595 index = _complexStringNumExp.lastIndex; 2596 } 2597 } 2598 2599 pt.c = index < end.length ? end.substring(index, end.length) : ""; 2600 pt.fp = funcParam; 2601 2602 if (_relExp.test(end) || hasRandom) { 2603 pt.e = 0; 2604 } 2605 2606 this._pt = pt; 2607 return pt; 2608 }, 2609 _addPropTween = function _addPropTween(target, prop, start, end, index, targets, modifier, stringFilter, funcParam, optional) { 2610 _isFunction(end) && (end = end(index || 0, target, targets)); 2611 var currentValue = target[prop], 2612 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](), 2613 setter = !_isFunction(currentValue) ? _setterPlain : funcParam ? _setterFuncWithParam : _setterFunc, 2614 pt; 2615 2616 if (_isString(end)) { 2617 if (~end.indexOf("random(")) { 2618 end = _replaceRandom(end); 2619 } 2620 2621 if (end.charAt(1) === "=") { 2622 pt = _parseRelative(parsedStart, end) + (getUnit(parsedStart) || 0); 2623 2624 if (pt || pt === 0) { 2625 end = pt; 2626 } 2627 } 2628 } 2629 2630 if (!optional || parsedStart !== end || _forceAllPropTweens) { 2631 if (!isNaN(parsedStart * end) && end !== "") { 2632 pt = new PropTween(this._pt, target, prop, +parsedStart || 0, end - (parsedStart || 0), typeof currentValue === "boolean" ? _renderBoolean : _renderPlain, 0, setter); 2633 funcParam && (pt.fp = funcParam); 2634 modifier && pt.modifier(modifier, this, target); 2635 return this._pt = pt; 2636 } 2637 2638 !currentValue && !(prop in target) && _missingPlugin(prop, end); 2639 return _addComplexStringPropTween.call(this, target, prop, parsedStart, end, setter, stringFilter || _config.stringFilter, funcParam); 2640 } 2641 }, 2642 _processVars = function _processVars(vars, index, target, targets, tween) { 2643 _isFunction(vars) && (vars = _parseFuncOrString(vars, tween, index, target, targets)); 2644 2645 if (!_isObject(vars) || vars.style && vars.nodeType || _isArray(vars) || _isTypedArray(vars)) { 2646 return _isString(vars) ? _parseFuncOrString(vars, tween, index, target, targets) : vars; 2647 } 2648 2649 var copy = {}, 2650 p; 2651 2652 for (p in vars) { 2653 copy[p] = _parseFuncOrString(vars[p], tween, index, target, targets); 2654 } 2655 2656 return copy; 2657 }, 2658 _checkPlugin = function _checkPlugin(property, vars, tween, index, target, targets) { 2659 var plugin, pt, ptLookup, i; 2660 2661 if (_plugins[property] && (plugin = new _plugins[property]()).init(target, plugin.rawVars ? vars[property] : _processVars(vars[property], index, target, targets, tween), tween, index, targets) !== false) { 2662 tween._pt = pt = new PropTween(tween._pt, target, property, 0, 1, plugin.render, plugin, 0, plugin.priority); 2663 2664 if (tween !== _quickTween) { 2665 ptLookup = tween._ptLookup[tween._targets.indexOf(target)]; 2666 i = plugin._props.length; 2667 2668 while (i--) { 2669 ptLookup[plugin._props[i]] = pt; 2670 } 2671 } 2672 } 2673 2674 return plugin; 2675 }, 2676 _overwritingTween, 2677 _forceAllPropTweens, 2678 _initTween = function _initTween(tween, time, tTime) { 2679 var vars = tween.vars, 2680 ease = vars.ease, 2681 startAt = vars.startAt, 2682 immediateRender = vars.immediateRender, 2683 lazy = vars.lazy, 2684 onUpdate = vars.onUpdate, 2685 runBackwards = vars.runBackwards, 2686 yoyoEase = vars.yoyoEase, 2687 keyframes = vars.keyframes, 2688 autoRevert = vars.autoRevert, 2689 dur = tween._dur, 2690 prevStartAt = tween._startAt, 2691 targets = tween._targets, 2692 parent = tween.parent, 2693 fullTargets = parent && parent.data === "nested" ? parent.vars.targets : targets, 2694 autoOverwrite = tween._overwrite === "auto" && !_suppressOverwrites, 2695 tl = tween.timeline, 2696 cleanVars, 2697 i, 2698 p, 2699 pt, 2700 target, 2701 hasPriority, 2702 gsData, 2703 harness, 2704 plugin, 2705 ptLookup, 2706 index, 2707 harnessVars, 2708 overwritten; 2709 tl && (!keyframes || !ease) && (ease = "none"); 2710 tween._ease = _parseEase(ease, _defaults.ease); 2711 tween._yEase = yoyoEase ? _invertEase(_parseEase(yoyoEase === true ? ease : yoyoEase, _defaults.ease)) : 0; 2712 2713 if (yoyoEase && tween._yoyo && !tween._repeat) { 2714 yoyoEase = tween._yEase; 2715 tween._yEase = tween._ease; 2716 tween._ease = yoyoEase; 2717 } 2718 2719 tween._from = !tl && !!vars.runBackwards; 2720 2721 if (!tl || keyframes && !vars.stagger) { 2722 harness = targets[0] ? _getCache(targets[0]).harness : 0; 2723 harnessVars = harness && vars[harness.prop]; 2724 cleanVars = _copyExcluding(vars, _reservedProps); 2725 2726 if (prevStartAt) { 2727 prevStartAt._zTime < 0 && prevStartAt.progress(1); 2728 time < 0 && runBackwards && immediateRender && !autoRevert ? prevStartAt.render(-1, true) : prevStartAt.revert(runBackwards && dur ? _revertConfigNoKill : _startAtRevertConfig); 2729 prevStartAt._lazy = 0; 2730 } 2731 2732 if (startAt) { 2733 _removeFromParent(tween._startAt = Tween.set(targets, _setDefaults({ 2734 data: "isStart", 2735 overwrite: false, 2736 parent: parent, 2737 immediateRender: true, 2738 lazy: !prevStartAt && _isNotFalse(lazy), 2739 startAt: null, 2740 delay: 0, 2741 onUpdate: onUpdate && function () { 2742 return _callback(tween, "onUpdate"); 2743 }, 2744 stagger: 0 2745 }, startAt))); 2746 2747 tween._startAt._dp = 0; 2748 tween._startAt._sat = tween; 2749 time < 0 && (_reverting || !immediateRender && !autoRevert) && tween._startAt.revert(_revertConfigNoKill); 2750 2751 if (immediateRender) { 2752 if (dur && time <= 0 && tTime <= 0) { 2753 time && (tween._zTime = time); 2754 return; 2755 } 2756 } 2757 } else if (runBackwards && dur) { 2758 if (!prevStartAt) { 2759 time && (immediateRender = false); 2760 p = _setDefaults({ 2761 overwrite: false, 2762 data: "isFromStart", 2763 lazy: immediateRender && !prevStartAt && _isNotFalse(lazy), 2764 immediateRender: immediateRender, 2765 stagger: 0, 2766 parent: parent 2767 }, cleanVars); 2768 harnessVars && (p[harness.prop] = harnessVars); 2769 2770 _removeFromParent(tween._startAt = Tween.set(targets, p)); 2771 2772 tween._startAt._dp = 0; 2773 tween._startAt._sat = tween; 2774 time < 0 && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween._startAt.render(-1, true)); 2775 tween._zTime = time; 2776 2777 if (!immediateRender) { 2778 _initTween(tween._startAt, _tinyNum, _tinyNum); 2779 } else if (!time) { 2780 return; 2781 } 2782 } 2783 } 2784 2785 tween._pt = tween._ptCache = 0; 2786 lazy = dur && _isNotFalse(lazy) || lazy && !dur; 2787 2788 for (i = 0; i < targets.length; i++) { 2789 target = targets[i]; 2790 gsData = target._gsap || _harness(targets)[i]._gsap; 2791 tween._ptLookup[i] = ptLookup = {}; 2792 _lazyLookup[gsData.id] && _lazyTweens.length && _lazyRender(); 2793 index = fullTargets === targets ? i : fullTargets.indexOf(target); 2794 2795 if (harness && (plugin = new harness()).init(target, harnessVars || cleanVars, tween, index, fullTargets) !== false) { 2796 tween._pt = pt = new PropTween(tween._pt, target, plugin.name, 0, 1, plugin.render, plugin, 0, plugin.priority); 2797 2798 plugin._props.forEach(function (name) { 2799 ptLookup[name] = pt; 2800 }); 2801 2802 plugin.priority && (hasPriority = 1); 2803 } 2804 2805 if (!harness || harnessVars) { 2806 for (p in cleanVars) { 2807 if (_plugins[p] && (plugin = _checkPlugin(p, cleanVars, tween, index, target, fullTargets))) { 2808 plugin.priority && (hasPriority = 1); 2809 } else { 2810 ptLookup[p] = pt = _addPropTween.call(tween, target, p, "get", cleanVars[p], index, fullTargets, 0, vars.stringFilter); 2811 } 2812 } 2813 } 2814 2815 tween._op && tween._op[i] && tween.kill(target, tween._op[i]); 2816 2817 if (autoOverwrite && tween._pt) { 2818 _overwritingTween = tween; 2819 2820 _globalTimeline.killTweensOf(target, ptLookup, tween.globalTime(time)); 2821 2822 overwritten = !tween.parent; 2823 _overwritingTween = 0; 2824 } 2825 2826 tween._pt && lazy && (_lazyLookup[gsData.id] = 1); 2827 } 2828 2829 hasPriority && _sortPropTweensByPriority(tween); 2830 tween._onInit && tween._onInit(tween); 2831 } 2832 2833 tween._onUpdate = onUpdate; 2834 tween._initted = (!tween._op || tween._pt) && !overwritten; 2835 keyframes && time <= 0 && tl.render(_bigNum, true, true); 2836 }, 2837 _updatePropTweens = function _updatePropTweens(tween, property, value, start, startIsRelative, ratio, time, skipRecursion) { 2838 var ptCache = (tween._pt && tween._ptCache || (tween._ptCache = {}))[property], 2839 pt, 2840 rootPT, 2841 lookup, 2842 i; 2843 2844 if (!ptCache) { 2845 ptCache = tween._ptCache[property] = []; 2846 lookup = tween._ptLookup; 2847 i = tween._targets.length; 2848 2849 while (i--) { 2850 pt = lookup[i][property]; 2851 2852 if (pt && pt.d && pt.d._pt) { 2853 pt = pt.d._pt; 2854 2855 while (pt && pt.p !== property && pt.fp !== property) { 2856 pt = pt._next; 2857 } 2858 } 2859 2860 if (!pt) { 2861 _forceAllPropTweens = 1; 2862 tween.vars[property] = "+=0"; 2863 2864 _initTween(tween, time); 2865 2866 _forceAllPropTweens = 0; 2867 return skipRecursion ? _warn(property + " not eligible for reset") : 1; 2868 } 2869 2870 ptCache.push(pt); 2871 } 2872 } 2873 2874 i = ptCache.length; 2875 2876 while (i--) { 2877 rootPT = ptCache[i]; 2878 pt = rootPT._pt || rootPT; 2879 pt.s = (start || start === 0) && !startIsRelative ? start : pt.s + (start || 0) + ratio * pt.c; 2880 pt.c = value - pt.s; 2881 rootPT.e && (rootPT.e = _round(value) + getUnit(rootPT.e)); 2882 rootPT.b && (rootPT.b = pt.s + getUnit(rootPT.b)); 2883 } 2884 }, 2885 _addAliasesToVars = function _addAliasesToVars(targets, vars) { 2886 var harness = targets[0] ? _getCache(targets[0]).harness : 0, 2887 propertyAliases = harness && harness.aliases, 2888 copy, 2889 p, 2890 i, 2891 aliases; 2892 2893 if (!propertyAliases) { 2894 return vars; 2895 } 2896 2897 copy = _merge({}, vars); 2898 2899 for (p in propertyAliases) { 2900 if (p in copy) { 2901 aliases = propertyAliases[p].split(","); 2902 i = aliases.length; 2903 2904 while (i--) { 2905 copy[aliases[i]] = copy[p]; 2906 } 2907 } 2908 } 2909 2910 return copy; 2911 }, 2912 _parseKeyframe = function _parseKeyframe(prop, obj, allProps, easeEach) { 2913 var ease = obj.ease || easeEach || "power1.inOut", 2914 p, 2915 a; 2916 2917 if (_isArray(obj)) { 2918 a = allProps[prop] || (allProps[prop] = []); 2919 obj.forEach(function (value, i) { 2920 return a.push({ 2921 t: i / (obj.length - 1) * 100, 2922 v: value, 2923 e: ease 2924 }); 2925 }); 2926 } else { 2927 for (p in obj) { 2928 a = allProps[p] || (allProps[p] = []); 2929 p === "ease" || a.push({ 2930 t: parseFloat(prop), 2931 v: obj[p], 2932 e: ease 2933 }); 2934 } 2935 } 2936 }, 2937 _parseFuncOrString = function _parseFuncOrString(value, tween, i, target, targets) { 2938 return _isFunction(value) ? value.call(tween, i, target, targets) : _isString(value) && ~value.indexOf("random(") ? _replaceRandom(value) : value; 2939 }, 2940 _staggerTweenProps = _callbackNames + "repeat,repeatDelay,yoyo,repeatRefresh,yoyoEase,autoRevert", 2941 _staggerPropsToSkip = {}; 2942 2943 _forEachName(_staggerTweenProps + ",id,stagger,delay,duration,paused,scrollTrigger", function (name) { 2944 return _staggerPropsToSkip[name] = 1; 2945 }); 2946 2947 var Tween = function (_Animation2) { 2948 _inheritsLoose(Tween, _Animation2); 2949 2950 function Tween(targets, vars, position, skipInherit) { 2951 var _this3; 2952 2953 if (typeof vars === "number") { 2954 position.duration = vars; 2955 vars = position; 2956 position = null; 2957 } 2958 2959 _this3 = _Animation2.call(this, skipInherit ? vars : _inheritDefaults(vars)) || this; 2960 var _this3$vars = _this3.vars, 2961 duration = _this3$vars.duration, 2962 delay = _this3$vars.delay, 2963 immediateRender = _this3$vars.immediateRender, 2964 stagger = _this3$vars.stagger, 2965 overwrite = _this3$vars.overwrite, 2966 keyframes = _this3$vars.keyframes, 2967 defaults = _this3$vars.defaults, 2968 scrollTrigger = _this3$vars.scrollTrigger, 2969 yoyoEase = _this3$vars.yoyoEase, 2970 parent = vars.parent || _globalTimeline, 2971 parsedTargets = (_isArray(targets) || _isTypedArray(targets) ? _isNumber(targets[0]) : "length" in vars) ? [targets] : toArray(targets), 2972 tl, 2973 i, 2974 copy, 2975 l, 2976 p, 2977 curTarget, 2978 staggerFunc, 2979 staggerVarsToMerge; 2980 _this3._targets = parsedTargets.length ? _harness(parsedTargets) : _warn("GSAP target " + targets + " not found. https://gsap.com", !_config.nullTargetWarn) || []; 2981 _this3._ptLookup = []; 2982 _this3._overwrite = overwrite; 2983 2984 if (keyframes || stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) { 2985 vars = _this3.vars; 2986 tl = _this3.timeline = new Timeline({ 2987 data: "nested", 2988 defaults: defaults || {}, 2989 targets: parent && parent.data === "nested" ? parent.vars.targets : parsedTargets 2990 }); 2991 tl.kill(); 2992 tl.parent = tl._dp = _assertThisInitialized(_this3); 2993 tl._start = 0; 2994 2995 if (stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) { 2996 l = parsedTargets.length; 2997 staggerFunc = stagger && distribute(stagger); 2998 2999 if (_isObject(stagger)) { 3000 for (p in stagger) { 3001 if (~_staggerTweenProps.indexOf(p)) { 3002 staggerVarsToMerge || (staggerVarsToMerge = {}); 3003 staggerVarsToMerge[p] = stagger[p]; 3004 } 3005 } 3006 } 3007 3008 for (i = 0; i < l; i++) { 3009 copy = _copyExcluding(vars, _staggerPropsToSkip); 3010 copy.stagger = 0; 3011 yoyoEase && (copy.yoyoEase = yoyoEase); 3012 staggerVarsToMerge && _merge(copy, staggerVarsToMerge); 3013 curTarget = parsedTargets[i]; 3014 copy.duration = +_parseFuncOrString(duration, _assertThisInitialized(_this3), i, curTarget, parsedTargets); 3015 copy.delay = (+_parseFuncOrString(delay, _assertThisInitialized(_this3), i, curTarget, parsedTargets) || 0) - _this3._delay; 3016 3017 if (!stagger && l === 1 && copy.delay) { 3018 _this3._delay = delay = copy.delay; 3019 _this3._start += delay; 3020 copy.delay = 0; 3021 } 3022 3023 tl.to(curTarget, copy, staggerFunc ? staggerFunc(i, curTarget, parsedTargets) : 0); 3024 tl._ease = _easeMap.none; 3025 } 3026 3027 tl.duration() ? duration = delay = 0 : _this3.timeline = 0; 3028 } else if (keyframes) { 3029 _inheritDefaults(_setDefaults(tl.vars.defaults, { 3030 ease: "none" 3031 })); 3032 3033 tl._ease = _parseEase(keyframes.ease || vars.ease || "none"); 3034 var time = 0, 3035 a, 3036 kf, 3037 v; 3038 3039 if (_isArray(keyframes)) {
vendor: 6,477 bytes, lines 3040-3246
3040 keyframes.forEach(function (frame) { 3041 return tl.to(parsedTargets, frame, ">"); 3042 }); 3043 tl.duration(); 3044 } else { 3045 copy = {}; 3046 3047 for (p in keyframes) { 3048 p === "ease" || p === "easeEach" || _parseKeyframe(p, keyframes[p], copy, keyframes.easeEach); 3049 } 3050 3051 for (p in copy) { 3052 a = copy[p].sort(function (a, b) { 3053 return a.t - b.t; 3054 }); 3055 time = 0; 3056 3057 for (i = 0; i < a.length; i++) { 3058 kf = a[i]; 3059 v = { 3060 ease: kf.e, 3061 duration: (kf.t - (i ? a[i - 1].t : 0)) / 100 * duration 3062 }; 3063 v[p] = kf.v; 3064 tl.to(parsedTargets, v, time); 3065 time += v.duration; 3066 } 3067 } 3068 3069 tl.duration() < duration && tl.to({}, { 3070 duration: duration - tl.duration() 3071 }); 3072 } 3073 } 3074 3075 duration || _this3.duration(duration = tl.duration()); 3076 } else { 3077 _this3.timeline = 0; 3078 } 3079 3080 if (overwrite === true && !_suppressOverwrites) { 3081 _overwritingTween = _assertThisInitialized(_this3); 3082 3083 _globalTimeline.killTweensOf(parsedTargets); 3084 3085 _overwritingTween = 0; 3086 } 3087 3088 _addToTimeline(parent, _assertThisInitialized(_this3), position); 3089 3090 vars.reversed && _this3.reverse(); 3091 vars.paused && _this3.paused(true); 3092 3093 if (immediateRender || !duration && !keyframes && _this3._start === _roundPrecise(parent._time) && _isNotFalse(immediateRender) && _hasNoPausedAncestors(_assertThisInitialized(_this3)) && parent.data !== "nested") { 3094 _this3._tTime = -_tinyNum; 3095 3096 _this3.render(Math.max(0, -delay) || 0); 3097 } 3098 3099 scrollTrigger && _scrollTrigger(_assertThisInitialized(_this3), scrollTrigger); 3100 return _this3; 3101 } 3102 3103 var _proto3 = Tween.prototype; 3104 3105 _proto3.render = function render(totalTime, suppressEvents, force) { 3106 var prevTime = this._time, 3107 tDur = this._tDur, 3108 dur = this._dur, 3109 isNegative = totalTime < 0, 3110 tTime = totalTime > tDur - _tinyNum && !isNegative ? tDur : totalTime < _tinyNum ? 0 : totalTime, 3111 time, 3112 pt, 3113 iteration, 3114 cycleDuration, 3115 prevIteration, 3116 isYoyo, 3117 ratio, 3118 timeline, 3119 yoyoEase; 3120 3121 if (!dur) { 3122 _renderZeroDurationTween(this, totalTime, suppressEvents, force); 3123 } else if (tTime !== this._tTime || !totalTime || force || !this._initted && this._tTime || this._startAt && this._zTime < 0 !== isNegative) { 3124 time = tTime; 3125 timeline = this.timeline; 3126 3127 if (this._repeat) { 3128 cycleDuration = dur + this._rDelay; 3129 3130 if (this._repeat < -1 && isNegative) { 3131 return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force); 3132 } 3133 3134 time = _roundPrecise(tTime % cycleDuration); 3135 3136 if (tTime === tDur) { 3137 iteration = this._repeat; 3138 time = dur; 3139 } else { 3140 iteration = ~~(tTime / cycleDuration); 3141 3142 if (iteration && iteration === _roundPrecise(tTime / cycleDuration)) { 3143 time = dur; 3144 iteration--; 3145 } 3146 3147 time > dur && (time = dur); 3148 } 3149 3150 isYoyo = this._yoyo && iteration & 1; 3151 3152 if (isYoyo) { 3153 yoyoEase = this._yEase; 3154 time = dur - time; 3155 } 3156 3157 prevIteration = _animationCycle(this._tTime, cycleDuration); 3158 3159 if (time === prevTime && !force && this._initted && iteration === prevIteration) { 3160 this._tTime = tTime; 3161 return this; 3162 } 3163 3164 if (iteration !== prevIteration) { 3165 timeline && this._yEase && _propagateYoyoEase(timeline, isYoyo); 3166 3167 if (this.vars.repeatRefresh && !isYoyo && !this._lock && this._time !== cycleDuration && this._initted) { 3168 this._lock = force = 1; 3169 this.render(_roundPrecise(cycleDuration * iteration), true).invalidate()._lock = 0; 3170 } 3171 } 3172 } 3173 3174 if (!this._initted) { 3175 if (_attemptInitTween(this, isNegative ? totalTime : time, force, suppressEvents, tTime)) { 3176 this._tTime = 0; 3177 return this; 3178 } 3179 3180 if (prevTime !== this._time && !(force && this.vars.repeatRefresh && iteration !== prevIteration)) { 3181 return this; 3182 } 3183 3184 if (dur !== this._dur) { 3185 return this.render(totalTime, suppressEvents, force); 3186 } 3187 } 3188 3189 this._tTime = tTime; 3190 this._time = time; 3191 3192 if (!this._act && this._ts) { 3193 this._act = 1; 3194 this._lazy = 0; 3195 } 3196 3197 this.ratio = ratio = (yoyoEase || this._ease)(time / dur); 3198 3199 if (this._from) { 3200 this.ratio = ratio = 1 - ratio; 3201 } 3202 3203 if (time && !prevTime && !suppressEvents && !iteration) { 3204 _callback(this, "onStart"); 3205 3206 if (this._tTime !== tTime) { 3207 return this; 3208 } 3209 } 3210 3211 pt = this._pt; 3212 3213 while (pt) { 3214 pt.r(ratio, pt.d); 3215 pt = pt._next; 3216 } 3217 3218 timeline && timeline.render(totalTime < 0 ? totalTime : timeline._dur * timeline._ease(time / this._dur), suppressEvents, force) || this._startAt && (this._zTime = totalTime); 3219 3220 if (this._onUpdate && !suppressEvents) { 3221 isNegative && _rewindStartAt(this, totalTime, suppressEvents, force); 3222 3223 _callback(this, "onUpdate"); 3224 } 3225 3226 this._repeat && iteration !== prevIteration && this.vars.onRepeat && !suppressEvents && this.parent && _callback(this, "onRepeat"); 3227 3228 if ((tTime === this._tDur || !tTime) && this._tTime === tTime) { 3229 isNegative && !this._onUpdate && _rewindStartAt(this, totalTime, true, true); 3230 (totalTime || !dur) && (tTime === this._tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1); 3231 3232 if (!suppressEvents && !(isNegative && !prevTime) && (tTime || prevTime || isYoyo)) { 3233 _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true); 3234 3235 this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom(); 3236 } 3237 } 3238 } 3239 3240 return this; 3241 }; 3242 3243 _proto3.targets = function targets() { 3244 return this._targets; 3245 }; 3246
vendor: 1,310 bytes, lines 3247-3280
3247 _proto3.invalidate = function invalidate(soft) { 3248 (!soft || !this.vars.runBackwards) && (this._startAt = 0); 3249 this._pt = this._op = this._onUpdate = this._lazy = this.ratio = 0; 3250 this._ptLookup = []; 3251 this.timeline && this.timeline.invalidate(soft); 3252 return _Animation2.prototype.invalidate.call(this, soft); 3253 }; 3254 3255 _proto3.resetTo = function resetTo(property, value, start, startIsRelative, skipRecursion) { 3256 _tickerActive || _ticker.wake(); 3257 this._ts || this.play(); 3258 var time = Math.min(this._dur, (this._dp._time - this._start) * this._ts), 3259 ratio; 3260 this._initted || _initTween(this, time); 3261 ratio = this._ease(time / this._dur); 3262 3263 if (_updatePropTweens(this, property, value, start, startIsRelative, ratio, time, skipRecursion)) { 3264 return this.resetTo(property, value, start, startIsRelative, 1); 3265 } 3266 3267 _alignPlayhead(this, 0); 3268 3269 this.parent || _addLinkedListItem(this._dp, this, "_first", "_last", this._dp._sort ? "_start" : 0); 3270 return this.render(0); 3271 }; 3272 3273 _proto3.kill = function kill(targets, vars) { 3274 if (vars === void 0) { 3275 vars = "all"; 3276 } 3277 3278 if (!targets && (!vars || vars === "all")) { 3279 this._lazy = this._pt = 0; 3280 return this.parent ? _interrupt(this) :
vendor: 16,527 bytes, lines 3280-3882
3280 this; 3281 } 3282 3283 if (this.timeline) { 3284 var tDur = this.timeline.totalDuration(); 3285 this.timeline.killTweensOf(targets, vars, _overwritingTween && _overwritingTween.vars.overwrite !== true)._first || _interrupt(this); 3286 this.parent && tDur !== this.timeline.totalDuration() && _setDuration(this, this._dur * this.timeline._tDur / tDur, 0, 1); 3287 return this; 3288 } 3289 3290 var parsedTargets = this._targets, 3291 killingTargets = targets ? toArray(targets) : parsedTargets, 3292 propTweenLookup = this._ptLookup, 3293 firstPT = this._pt, 3294 overwrittenProps, 3295 curLookup, 3296 curOverwriteProps, 3297 props, 3298 p, 3299 pt, 3300 i; 3301 3302 if ((!vars || vars === "all") && _arraysMatch(parsedTargets, killingTargets)) { 3303 vars === "all" && (this._pt = 0); 3304 return _interrupt(this); 3305 } 3306 3307 overwrittenProps = this._op = this._op || []; 3308 3309 if (vars !== "all") { 3310 if (_isString(vars)) { 3311 p = {}; 3312 3313 _forEachName(vars, function (name) { 3314 return p[name] = 1; 3315 }); 3316 3317 vars = p; 3318 } 3319 3320 vars = _addAliasesToVars(parsedTargets, vars); 3321 } 3322 3323 i = parsedTargets.length; 3324 3325 while (i--) { 3326 if (~killingTargets.indexOf(parsedTargets[i])) { 3327 curLookup = propTweenLookup[i]; 3328 3329 if (vars === "all") { 3330 overwrittenProps[i] = vars; 3331 props = curLookup; 3332 curOverwriteProps = {}; 3333 } else { 3334 curOverwriteProps = overwrittenProps[i] = overwrittenProps[i] || {}; 3335 props = vars; 3336 } 3337 3338 for (p in props) { 3339 pt = curLookup && curLookup[p]; 3340 3341 if (pt) { 3342 if (!("kill" in pt.d) || pt.d.kill(p) === true) { 3343 _removeLinkedListItem(this, pt, "_pt"); 3344 } 3345 3346 delete curLookup[p]; 3347 } 3348 3349 if (curOverwriteProps !== "all") { 3350 curOverwriteProps[p] = 1; 3351 } 3352 } 3353 } 3354 } 3355 3356 this._initted && !this._pt && firstPT && _interrupt(this); 3357 return this; 3358 }; 3359 3360 Tween.to = function to(targets, vars) { 3361 return new Tween(targets, vars, arguments[2]); 3362 }; 3363 3364 Tween.from = function from(targets, vars) { 3365 return _createTweenType(1, arguments); 3366 }; 3367 3368 Tween.delayedCall = function delayedCall(delay, callback, params, scope) { 3369 return new Tween(callback, 0, { 3370 immediateRender: false, 3371 lazy: false, 3372 overwrite: false, 3373 delay: delay, 3374 onComplete: callback, 3375 onReverseComplete: callback, 3376 onCompleteParams: params, 3377 onReverseCompleteParams: params, 3378 callbackScope: scope 3379 }); 3380 }; 3381 3382 Tween.fromTo = function fromTo(targets, fromVars, toVars) { 3383 return _createTweenType(2, arguments); 3384 }; 3385 3386 Tween.set = function set(targets, vars) { 3387 vars.duration = 0; 3388 vars.repeatDelay || (vars.repeat = 0); 3389 return new Tween(targets, vars); 3390 }; 3391 3392 Tween.killTweensOf = function killTweensOf(targets, props, onlyActive) { 3393 return _globalTimeline.killTweensOf(targets, props, onlyActive); 3394 }; 3395 3396 return Tween; 3397 }(Animation); 3398 3399 _setDefaults(Tween.prototype, { 3400 _targets: [], 3401 _lazy: 0, 3402 _startAt: 0, 3403 _op: 0, 3404 _onInit: 0 3405 }); 3406 3407 _forEachName("staggerTo,staggerFrom,staggerFromTo", function (name) { 3408 Tween[name] = function () { 3409 var tl = new Timeline(), 3410 params = _slice.call(arguments, 0); 3411 3412 params.splice(name === "staggerFromTo" ? 5 : 4, 0, 0); 3413 return tl[name].apply(tl, params); 3414 }; 3415 }); 3416 3417 var _setterPlain = function _setterPlain(target, property, value) { 3418 return target[property] = value; 3419 }, 3420 _setterFunc = function _setterFunc(target, property, value) { 3421 return target[property](value); 3422 }, 3423 _setterFuncWithParam = function _setterFuncWithParam(target, property, value, data) { 3424 return target[property](data.fp, value); 3425 }, 3426 _setterAttribute = function _setterAttribute(target, property, value) { 3427 return target.setAttribute(property, value); 3428 }, 3429 _getSetter = function _getSetter(target, property) { 3430 return _isFunction(target[property]) ? _setterFunc : _isUndefined(target[property]) && target.setAttribute ? _setterAttribute : _setterPlain; 3431 }, 3432 _renderPlain = function _renderPlain(ratio, data) { 3433 return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 1000000) / 1000000, data); 3434 }, 3435 _renderBoolean = function _renderBoolean(ratio, data) { 3436 return data.set(data.t, data.p, !!(data.s + data.c * ratio), data); 3437 }, 3438 _renderComplexString = function _renderComplexString(ratio, data) { 3439 var pt = data._pt, 3440 s = ""; 3441 3442 if (!ratio && data.b) { 3443 s = data.b; 3444 } else if (ratio === 1 && data.e) { 3445 s = data.e; 3446 } else { 3447 while (pt) { 3448 s = pt.p + (pt.m ? pt.m(pt.s + pt.c * ratio) : Math.round((pt.s + pt.c * ratio) * 10000) / 10000) + s; 3449 pt = pt._next; 3450 } 3451 3452 s += data.c; 3453 } 3454 3455 data.set(data.t, data.p, s, data); 3456 }, 3457 _renderPropTweens = function _renderPropTweens(ratio, data) { 3458 var pt = data._pt; 3459 3460 while (pt) { 3461 pt.r(ratio, pt.d); 3462 pt = pt._next; 3463 } 3464 }, 3465 _addPluginModifier = function _addPluginModifier(modifier, tween, target, property) { 3466 var pt = this._pt, 3467 next; 3468 3469 while (pt) { 3470 next = pt._next; 3471 pt.p === property && pt.modifier(modifier, tween, target); 3472 pt = next; 3473 } 3474 }, 3475 _killPropTweensOf = function _killPropTweensOf(property) { 3476 var pt = this._pt, 3477 hasNonDependentRemaining, 3478 next; 3479 3480 while (pt) { 3481 next = pt._next; 3482 3483 if (pt.p === property && !pt.op || pt.op === property) { 3484 _removeLinkedListItem(this, pt, "_pt"); 3485 } else if (!pt.dep) { 3486 hasNonDependentRemaining = 1; 3487 } 3488 3489 pt = next; 3490 } 3491 3492 return !hasNonDependentRemaining; 3493 }, 3494 _setterWithModifier = function _setterWithModifier(target, property, value, data) { 3495 data.mSet(target, property, data.m.call(data.tween, value, data.mt), data); 3496 }, 3497 _sortPropTweensByPriority = function _sortPropTweensByPriority(parent) { 3498 var pt = parent._pt, 3499 next, 3500 pt2, 3501 first, 3502 last; 3503 3504 while (pt) { 3505 next = pt._next; 3506 pt2 = first; 3507 3508 while (pt2 && pt2.pr > pt.pr) { 3509 pt2 = pt2._next; 3510 } 3511 3512 if (pt._prev = pt2 ? pt2._prev : last) { 3513 pt._prev._next = pt; 3514 } else { 3515 first = pt; 3516 } 3517 3518 if (pt._next = pt2) { 3519 pt2._prev = pt; 3520 } else { 3521 last = pt; 3522 } 3523 3524 pt = next; 3525 } 3526 3527 parent._pt = first; 3528 }; 3529 3530 var PropTween = function () { 3531 function PropTween(next, target, prop, start, change, renderer, data, setter, priority) { 3532 this.t = target; 3533 this.s = start; 3534 this.c = change; 3535 this.p = prop; 3536 this.r = renderer || _renderPlain; 3537 this.d = data || this; 3538 this.set = setter || _setterPlain; 3539 this.pr = priority || 0; 3540 this._next = next; 3541 3542 if (next) { 3543 next._prev = this; 3544 } 3545 } 3546 3547 var _proto4 = PropTween.prototype; 3548 3549 _proto4.modifier = function modifier(func, tween, target) { 3550 this.mSet = this.mSet || this.set; 3551 this.set = _setterWithModifier; 3552 this.m = func; 3553 this.mt = target; 3554 this.tween = tween; 3555 }; 3556 3557 return PropTween; 3558 }(); 3559 3560 _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) { 3561 return _reservedProps[name] = 1; 3562 }); 3563 3564 _globals.TweenMax = _globals.TweenLite = Tween; 3565 _globals.TimelineLite = _globals.TimelineMax = Timeline; 3566 _globalTimeline = new Timeline({ 3567 sortChildren: false, 3568 defaults: _defaults, 3569 autoRemoveChildren: true, 3570 id: "root", 3571 smoothChildTiming: true 3572 }); 3573 _config.stringFilter = _colorStringFilter; 3574 3575 var _media = [], 3576 _listeners = {}, 3577 _emptyArray = [], 3578 _lastMediaTime = 0, 3579 _contextID = 0, 3580 _dispatch = function _dispatch(type) { 3581 return (_listeners[type] || _emptyArray).map(function (f) { 3582 return f(); 3583 }); 3584 }, 3585 _onMediaChange = function _onMediaChange() { 3586 var time = Date.now(), 3587 matches = []; 3588 3589 if (time - _lastMediaTime > 2) { 3590 _dispatch("matchMediaInit"); 3591 3592 _media.forEach(function (c) { 3593 var queries = c.queries, 3594 conditions = c.conditions, 3595 match, 3596 p, 3597 anyMatch, 3598 toggled; 3599 3600 for (p in queries) { 3601 match = _win.matchMedia(queries[p]).matches; 3602 match && (anyMatch = 1); 3603 3604 if (match !== conditions[p]) { 3605 conditions[p] = match; 3606 toggled = 1; 3607 } 3608 } 3609 3610 if (toggled) { 3611 c.revert(); 3612 anyMatch && matches.push(c); 3613 } 3614 }); 3615 3616 _dispatch("matchMediaRevert"); 3617 3618 matches.forEach(function (c) { 3619 return c.onMatch(c, function (func) { 3620 return c.add(null, func); 3621 }); 3622 }); 3623 _lastMediaTime = time; 3624 3625 _dispatch("matchMedia"); 3626 } 3627 }; 3628 3629 var Context = function () { 3630 function Context(func, scope) { 3631 this.selector = scope && selector(scope); 3632 this.data = []; 3633 this._r = []; 3634 this.isReverted = false; 3635 this.id = _contextID++; 3636 func && this.add(func); 3637 } 3638 3639 var _proto5 = Context.prototype; 3640 3641 _proto5.add = function add(name, func, scope) { 3642 if (_isFunction(name)) { 3643 scope = func; 3644 func = name; 3645 name = _isFunction; 3646 } 3647 3648 var self = this, 3649 f = function f() { 3650 var prev = _context, 3651 prevSelector = self.selector, 3652 result; 3653 prev && prev !== self && prev.data.push(self); 3654 scope && (self.selector = selector(scope)); 3655 _context = self; 3656 result = func.apply(self, arguments); 3657 _isFunction(result) && self._r.push(result); 3658 _context = prev; 3659 self.selector = prevSelector; 3660 self.isReverted = false; 3661 return result; 3662 }; 3663 3664 self.last = f; 3665 return name === _isFunction ? f(self, function (func) { 3666 return self.add(null, func); 3667 }) : name ? self[name] = f : f; 3668 }; 3669 3670 _proto5.ignore = function ignore(func) { 3671 var prev = _context; 3672 _context = null; 3673 func(this); 3674 _context = prev; 3675 }; 3676 3677 _proto5.getTweens = function getTweens() { 3678 var a = []; 3679 this.data.forEach(function (e) { 3680 return e instanceof Context ? a.push.apply(a, e.getTweens()) : e instanceof Tween && !(e.parent && e.parent.data === "nested") && a.push(e); 3681 }); 3682 return a; 3683 }; 3684 3685 _proto5.clear = function clear() { 3686 this._r.length = this.data.length = 0; 3687 }; 3688 3689 _proto5.kill = function kill(revert, matchMedia) { 3690 var _this4 = this; 3691 3692 if (revert) { 3693 (function () { 3694 var tweens = _this4.getTweens(), 3695 i = _this4.data.length, 3696 t; 3697 3698 while (i--) { 3699 t = _this4.data[i]; 3700 3701 if (t.data === "isFlip") { 3702 t.revert(); 3703 t.getChildren(true, true, false).forEach(function (tween) { 3704 return tweens.splice(tweens.indexOf(tween), 1); 3705 }); 3706 } 3707 } 3708 3709 tweens.map(function (t) { 3710 return { 3711 g: t._dur || t._delay || t._sat && !t._sat.vars.immediateRender ? t.globalTime(0) : -Infinity, 3712 t: t 3713 }; 3714 }).sort(function (a, b) { 3715 return b.g - a.g || -Infinity; 3716 }).forEach(function (o) { 3717 return o.t.revert(revert); 3718 }); 3719 i = _this4.data.length; 3720 3721 while (i--) { 3722 t = _this4.data[i]; 3723 3724 if (t instanceof Timeline) { 3725 if (t.data !== "nested") { 3726 t.scrollTrigger && t.scrollTrigger.revert(); 3727 t.kill(); 3728 } 3729 } else { 3730 !(t instanceof Tween) && t.revert && t.revert(revert); 3731 } 3732 } 3733 3734 _this4._r.forEach(function (f) { 3735 return f(revert, _this4); 3736 }); 3737 3738 _this4.isReverted = true; 3739 })(); 3740 } else { 3741 this.data.forEach(function (e) { 3742 return e.kill && e.kill(); 3743 }); 3744 } 3745 3746 this.clear(); 3747 3748 if (matchMedia) { 3749 var i = _media.length; 3750 3751 while (i--) { 3752 _media[i].id === this.id && _media.splice(i, 1); 3753 } 3754 } 3755 }; 3756 3757 _proto5.revert = function revert(config) { 3758 this.kill(config || {}); 3759 }; 3760 3761 return Context; 3762 }(); 3763 3764 var MatchMedia = function () { 3765 function MatchMedia(scope) { 3766 this.contexts = []; 3767 this.scope = scope; 3768 _context && _context.data.push(this); 3769 } 3770 3771 var _proto6 = MatchMedia.prototype; 3772 3773 _proto6.add = function add(conditions, func, scope) { 3774 _isObject(conditions) || (conditions = { 3775 matches: conditions 3776 }); 3777 var context = new Context(0, scope || this.scope), 3778 cond = context.conditions = {}, 3779 mq, 3780 p, 3781 active; 3782 _context && !context.selector && (context.selector = _context.selector); 3783 this.contexts.push(context); 3784 func = context.add("onMatch", func); 3785 context.queries = conditions; 3786 3787 for (p in conditions) { 3788 if (p === "all") { 3789 active = 1; 3790 } else { 3791 mq = _win.matchMedia(conditions[p]); 3792 3793 if (mq) { 3794 _media.indexOf(context) < 0 && _media.push(context); 3795 (cond[p] = mq.matches) && (active = 1); 3796 mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange); 3797 } 3798 } 3799 } 3800 3801 active && func(context, function (f) { 3802 return context.add(null, f); 3803 }); 3804 return this; 3805 }; 3806 3807 _proto6.revert = function revert(config) { 3808 this.kill(config || {}); 3809 }; 3810 3811 _proto6.kill = function kill(revert) { 3812 this.contexts.forEach(function (c) { 3813 return c.kill(revert, true); 3814 }); 3815 }; 3816 3817 return MatchMedia; 3818 }(); 3819 3820 var _gsap = { 3821 registerPlugin: function registerPlugin() { 3822 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 3823 args[_key2] = arguments[_key2]; 3824 } 3825 3826 args.forEach(function (config) { 3827 return _createPlugin(config); 3828 }); 3829 }, 3830 timeline: function timeline(vars) { 3831 return new Timeline(vars); 3832 }, 3833 getTweensOf: function getTweensOf(targets, onlyActive) { 3834 return _globalTimeline.getTweensOf(targets, onlyActive); 3835 }, 3836 getProperty: function getProperty(target, property, unit, uncache) { 3837 _isString(target) && (target = toArray(target)[0]); 3838 3839 var getter = _getCache(target || {}).get, 3840 format = unit ? _passThrough : _numericIfPossible; 3841 3842 unit === "native" && (unit = ""); 3843 return !target ? target : !property ? function (property, unit, uncache) { 3844 return format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache)); 3845 } : format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache)); 3846 }, 3847 quickSetter: function quickSetter(target, property, unit) { 3848 target = toArray(target); 3849 3850 if (target.length > 1) { 3851 var setters = target.map(function (t) { 3852 return gsap.quickSetter(t, property, unit); 3853 }), 3854 l = setters.length; 3855 return function (value) { 3856 var i = l; 3857 3858 while (i--) { 3859 setters[i](value); 3860 } 3861 }; 3862 } 3863 3864 target = target[0] || {}; 3865 3866 var Plugin = _plugins[property], 3867 cache = _getCache(target), 3868 p = cache.harness && (cache.harness.aliases || {})[property] || property, 3869 setter = Plugin ? function (value) { 3870 var p = new Plugin(); 3871 _quickTween._pt = 0; 3872 p.init(target, unit ? value + unit : value, _quickTween, 0, [target]); 3873 p.render(1, p); 3874 _quickTween._pt && _renderPropTweens(1, _quickTween); 3875 } : cache.set(target, p); 3876 3877 return Plugin ? setter : function (value) { 3878 return setter(target, p, unit ? value + unit : value, cache, 1); 3879 }; 3880 }, 3881 quickTo: function quickTo(target, property, vars) { 3882 var _
3882merge2; 3883 3884 var tween = gsap.to(target, _merge((_merge2 = {}, _merge2[property] = "+=0.1", _merge2.paused = true, _merge
vendor: 5,649 bytes, lines 3884-4086
38842), vars || {})), 3885 func = function func(value, start, startIsRelative) { 3886 return tween.resetTo(property, value, start, startIsRelative); 3887 }; 3888 3889 func.tween = tween; 3890 return func; 3891 }, 3892 isTweening: function isTweening(targets) { 3893 return _globalTimeline.getTweensOf(targets, true).length > 0; 3894 }, 3895 defaults: function defaults(value) { 3896 value && value.ease && (value.ease = _parseEase(value.ease, _defaults.ease)); 3897 return _mergeDeep(_defaults, value || {}); 3898 }, 3899 config: function config(value) { 3900 return _mergeDeep(_config, value || {}); 3901 }, 3902 registerEffect: function registerEffect(_ref3) { 3903 var name = _ref3.name, 3904 effect = _ref3.effect, 3905 plugins = _ref3.plugins, 3906 defaults = _ref3.defaults, 3907 extendTimeline = _ref3.extendTimeline; 3908 (plugins || "").split(",").forEach(function (pluginName) { 3909 return pluginName && !_plugins[pluginName] && !_globals[pluginName] && _warn(name + " effect requires " + pluginName + " plugin."); 3910 }); 3911 3912 _effects[name] = function (targets, vars, tl) { 3913 return effect(toArray(targets), _setDefaults(vars || {}, defaults), tl); 3914 }; 3915 3916 if (extendTimeline) { 3917 Timeline.prototype[name] = function (targets, vars, position) { 3918 return this.add(_effects[name](targets, _isObject(vars) ? vars : (position = vars) && {}, this), position); 3919 }; 3920 } 3921 }, 3922 registerEase: function registerEase(name, ease) { 3923 _easeMap[name] = _parseEase(ease); 3924 }, 3925 parseEase: function parseEase(ease, defaultEase) { 3926 return arguments.length ? _parseEase(ease, defaultEase) : _easeMap; 3927 }, 3928 getById: function getById(id) { 3929 return _globalTimeline.getById(id); 3930 }, 3931 exportRoot: function exportRoot(vars, includeDelayedCalls) { 3932 if (vars === void 0) { 3933 vars = {}; 3934 } 3935 3936 var tl = new Timeline(vars), 3937 child, 3938 next; 3939 tl.smoothChildTiming = _isNotFalse(vars.smoothChildTiming); 3940 3941 _globalTimeline.remove(tl); 3942 3943 tl._dp = 0; 3944 tl._time = tl._tTime = _globalTimeline._time; 3945 child = _globalTimeline._first; 3946 3947 while (child) { 3948 next = child._next; 3949 3950 if (includeDelayedCalls || !(!child._dur && child instanceof Tween && child.vars.onComplete === child._targets[0])) { 3951 _addToTimeline(tl, child, child._start - child._delay); 3952 } 3953 3954 child = next; 3955 } 3956 3957 _addToTimeline(_globalTimeline, tl, 0); 3958 3959 return tl; 3960 }, 3961 context: function context(func, scope) { 3962 return func ? new Context(func, scope) : _context; 3963 }, 3964 matchMedia: function matchMedia(scope) { 3965 return new MatchMedia(scope); 3966 }, 3967 matchMediaRefresh: function matchMediaRefresh() { 3968 return _media.forEach(function (c) { 3969 var cond = c.conditions, 3970 found, 3971 p; 3972 3973 for (p in cond) { 3974 if (cond[p]) { 3975 cond[p] = false; 3976 found = 1; 3977 } 3978 } 3979 3980 found && c.revert(); 3981 }) || _onMediaChange(); 3982 }, 3983 addEventListener: function addEventListener(type, callback) { 3984 var a = _listeners[type] || (_listeners[type] = []); 3985 ~a.indexOf(callback) || a.push(callback); 3986 }, 3987 removeEventListener: function removeEventListener(type, callback) { 3988 var a = _listeners[type], 3989 i = a && a.indexOf(callback); 3990 i >= 0 && a.splice(i, 1); 3991 }, 3992 utils: { 3993 wrap: wrap, 3994 wrapYoyo: wrapYoyo, 3995 distribute: distribute, 3996 random: random, 3997 snap: snap, 3998 normalize: normalize, 3999 getUnit: getUnit, 4000 clamp: clamp, 4001 splitColor: splitColor, 4002 toArray: toArray, 4003 selector: selector, 4004 mapRange: mapRange, 4005 pipe: pipe, 4006 unitize: unitize, 4007 interpolate: interpolate, 4008 shuffle: shuffle 4009 }, 4010 install: _install, 4011 effects: _effects, 4012 ticker: _ticker, 4013 updateRoot: Timeline.updateRoot, 4014 plugins: _plugins, 4015 globalTimeline: _globalTimeline, 4016 core: { 4017 PropTween: PropTween, 4018 globals: _addGlobal, 4019 Tween: Tween, 4020 Timeline: Timeline, 4021 Animation: Animation, 4022 getCache: _getCache, 4023 _removeLinkedListItem: _removeLinkedListItem, 4024 reverting: function reverting() { 4025 return _reverting; 4026 }, 4027 context: function context(toAdd) { 4028 if (toAdd && _context) { 4029 _context.data.push(toAdd); 4030 4031 toAdd._ctx = _context; 4032 } 4033 4034 return _context; 4035 }, 4036 suppressOverwrites: function suppressOverwrites(value) { 4037 return _suppressOverwrites = value; 4038 } 4039 } 4040 }; 4041 4042 _forEachName("to,from,fromTo,delayedCall,set,killTweensOf", function (name) { 4043 return _gsap[name] = Tween[name]; 4044 }); 4045 4046 _ticker.add(Timeline.updateRoot); 4047 4048 _quickTween = _gsap.to({}, { 4049 duration: 0 4050 }); 4051 4052 var _getPluginPropTween = function _getPluginPropTween(plugin, prop) { 4053 var pt = plugin._pt; 4054 4055 while (pt && pt.p !== prop && pt.op !== prop && pt.fp !== prop) { 4056 pt = pt._next; 4057 } 4058 4059 return pt; 4060 }, 4061 _addModifiers = function _addModifiers(tween, modifiers) { 4062 var targets = tween._targets, 4063 p, 4064 i, 4065 pt; 4066 4067 for (p in modifiers) { 4068 i = targets.length; 4069 4070 while (i--) { 4071 pt = tween._ptLookup[i][p]; 4072 4073 if (pt && (pt = pt.d)) { 4074 if (pt._pt) { 4075 pt = _getPluginPropTween(pt, p); 4076 } 4077 4078 pt && pt.modifier && pt.modifier(modifiers[p], tween, targets[i], p); 4079 } 4080 } 4081 } 4082 }, 4083 _buildModifierPlugin = function _buildModifierPlugin(name, modifier) { 4084 return { 4085 name: name, 4086
vendor: 21,125 bytes, lines 4086-4737
4086rawVars: 1, 4087 init: function init(target, vars, tween) { 4088 tween._onInit = function (tween) { 4089 var temp, p; 4090 4091 if (_isString(vars)) { 4092 temp = {}; 4093 4094 _forEachName(vars, function (name) { 4095 return temp[name] = 1; 4096 }); 4097 4098 vars = temp; 4099 } 4100 4101 if (modifier) { 4102 temp = {}; 4103 4104 for (p in vars) { 4105 temp[p] = modifier(vars[p]); 4106 } 4107 4108 vars = temp; 4109 } 4110 4111 _addModifiers(tween, vars); 4112 }; 4113 } 4114 }; 4115 }; 4116 4117 var gsap = _gsap.registerPlugin({ 4118 name: "attr", 4119 init: function init(target, vars, tween, index, targets) { 4120 var p, pt, v; 4121 this.tween = tween; 4122 4123 for (p in vars) { 4124 v = target.getAttribute(p) || ""; 4125 pt = this.add(target, "setAttribute", (v || 0) + "", vars[p], index, targets, 0, 0, p); 4126 pt.op = p; 4127 pt.b = v; 4128 4129 this._props.push(p); 4130 } 4131 }, 4132 render: function render(ratio, data) { 4133 var pt = data._pt; 4134 4135 while (pt) { 4136 _reverting ? pt.set(pt.t, pt.p, pt.b, pt) : pt.r(ratio, pt.d); 4137 pt = pt._next; 4138 } 4139 } 4140 }, { 4141 name: "endArray", 4142 init: function init(target, value) { 4143 var i = value.length; 4144 4145 while (i--) { 4146 this.add(target, i, target[i] || 0, value[i], 0, 0, 0, 0, 0, 1); 4147 } 4148 } 4149 }, _buildModifierPlugin("roundProps", _roundModifier), _buildModifierPlugin("modifiers"), _buildModifierPlugin("snap", snap)) || _gsap; 4150 Tween.version = Timeline.version = gsap.version = "3.12.5"; 4151 _coreReady = 1; 4152 _windowExists() && _wake(); 4153 var Power0 = _easeMap.Power0, 4154 Power1 = _easeMap.Power1, 4155 Power2 = _easeMap.Power2, 4156 Power3 = _easeMap.Power3, 4157 Power4 = _easeMap.Power4, 4158 Linear = _easeMap.Linear, 4159 Quad = _easeMap.Quad, 4160 Cubic = _easeMap.Cubic, 4161 Quart = _easeMap.Quart, 4162 Quint = _easeMap.Quint, 4163 Strong = _easeMap.Strong, 4164 Elastic = _easeMap.Elastic, 4165 Back = _easeMap.Back, 4166 SteppedEase = _easeMap.SteppedEase, 4167 Bounce = _easeMap.Bounce, 4168 Sine = _easeMap.Sine, 4169 Expo = _easeMap.Expo, 4170 Circ = _easeMap.Circ; 4171 4172 var _win$1, 4173 _doc$1, 4174 _docElement, 4175 _pluginInitted, 4176 _tempDiv, 4177 _tempDivStyler, 4178 _recentSetterPlugin, 4179 _reverting$1, 4180 _windowExists$1 = function _windowExists() { 4181 return typeof window !== "undefined"; 4182 }, 4183 _transformProps = {}, 4184 _RAD2DEG = 180 / Math.PI, 4185 _DEG2RAD = Math.PI / 180, 4186 _atan2 = Math.atan2, 4187 _bigNum$1 = 1e8, 4188 _capsExp = /([A-Z])/g, 4189 _horizontalExp = /(left|right|width|margin|padding|x)/i, 4190 _complexExp = /[\s,\(]\S/, 4191 _propertyAliases = { 4192 autoAlpha: "opacity,visibility", 4193 scale: "scaleX,scaleY", 4194 alpha: "opacity" 4195 }, 4196 _renderCSSProp = function _renderCSSProp(ratio, data) { 4197 return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); 4198 }, 4199 _renderPropWithEnd = function _renderPropWithEnd(ratio, data) { 4200 return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); 4201 }, 4202 _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) { 4203 return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data); 4204 }, 4205 _renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) { 4206 var value = data.s + data.c * ratio; 4207 data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data); 4208 }, 4209 _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) { 4210 return data.set(data.t, data.p, ratio ? data.e : data.b, data); 4211 }, 4212 _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) { 4213 return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data); 4214 }, 4215 _setterCSSStyle = function _setterCSSStyle(target, property, value) { 4216 return target.style[property] = value; 4217 }, 4218 _setterCSSProp = function _setterCSSProp(target, property, value) { 4219 return target.style.setProperty(property, value); 4220 }, 4221 _setterTransform = function _setterTransform(target, property, value) { 4222 return target._gsap[property] = value; 4223 }, 4224 _setterScale = function _setterScale(target, property, value) { 4225 return target._gsap.scaleX = target._gsap.scaleY = value; 4226 }, 4227 _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) { 4228 var cache = target._gsap; 4229 cache.scaleX = cache.scaleY = value; 4230 cache.renderTransform(ratio, cache); 4231 }, 4232 _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) { 4233 var cache = target._gsap; 4234 cache[property] = value; 4235 cache.renderTransform(ratio, cache); 4236 }, 4237 _transformProp = "transform", 4238 _transformOriginProp = _transformProp + "Origin", 4239 _saveStyle = function _saveStyle(property, isNotCSS) { 4240 var _this = this; 4241 4242 var target = this.target, 4243 style = target.style, 4244 cache = target._gsap; 4245 4246 if (property in _transformProps && style) { 4247 this.tfm = this.tfm || {}; 4248 4249 if (property !== "transform") { 4250 property = _propertyAliases[property] || property; 4251 ~property.indexOf(",") ? property.split(",").forEach(function (a) { 4252 return _this.tfm[a] = _get(target, a); 4253 }) : this.tfm[property] = cache.x ? cache[property] : _get(target, property); 4254 property === _transformOriginProp && (this.tfm.zOrigin = cache.zOrigin); 4255 } else { 4256 return _propertyAliases.transform.split(",").forEach(function (p) { 4257 return _saveStyle.call(_this, p, isNotCSS); 4258 }); 4259 } 4260 4261 if (this.props.indexOf(_transformProp) >= 0) { 4262 return; 4263 } 4264 4265 if (cache.svg) { 4266 this.svgo = target.getAttribute("data-svg-origin"); 4267 this.props.push(_transformOriginProp, isNotCSS, ""); 4268 } 4269 4270 property = _transformProp; 4271 } 4272 4273 (style || isNotCSS) && this.props.push(property, isNotCSS, style[property]); 4274 }, 4275 _removeIndependentTransforms = function _removeIndependentTransforms(style) { 4276 if (style.translate) { 4277 style.removeProperty("translate"); 4278 style.removeProperty("scale"); 4279 style.removeProperty("rotate"); 4280 } 4281 }, 4282 _revertStyle = function _revertStyle() { 4283 var props = this.props, 4284 target = this.target, 4285 style = target.style, 4286 cache = target._gsap, 4287 i, 4288 p; 4289 4290 for (i = 0; i < props.length; i += 3) { 4291 props[i + 1] ? target[props[i]] = props[i + 2] : props[i + 2] ? style[props[i]] = props[i + 2] : style.removeProperty(props[i].substr(0, 2) === "--" ? props[i] : props[i].replace(_capsExp, "-$1").toLowerCase()); 4292 } 4293 4294 if (this.tfm) { 4295 for (p in this.tfm) { 4296 cache[p] = this.tfm[p]; 4297 } 4298 4299 if (cache.svg) { 4300 cache.renderTransform(); 4301 target.setAttribute("data-svg-origin", this.svgo || ""); 4302 } 4303 4304 i = _reverting$1(); 4305 4306 if ((!i || !i.isStart) && !style[_transformProp]) { 4307 _removeIndependentTransforms(style); 4308 4309 if (cache.zOrigin && style[_transformOriginProp]) { 4310 style[_transformOriginProp] += " " + cache.zOrigin + "px"; 4311 cache.zOrigin = 0; 4312 cache.renderTransform(); 4313 } 4314 4315 cache.uncache = 1; 4316 } 4317 } 4318 }, 4319 _getStyleSaver = function _getStyleSaver(target, properties) { 4320 var saver = { 4321 target: target, 4322 props: [], 4323 revert: _revertStyle, 4324 save: _saveStyle 4325 }; 4326 target._gsap || gsap.core.getCache(target); 4327 properties && properties.split(",").forEach(function (p) { 4328 return saver.save(p); 4329 }); 4330 return saver; 4331 }, 4332 _supports3D, 4333 _createElement = function _createElement(type, ns) { 4334 var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type); 4335 return e && e.style ? e : _doc$1.createElement(type); 4336 }, 4337 _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) { 4338 var cs = getComputedStyle(target); 4339 return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || ""; 4340 }, 4341 _prefixes = "O,Moz,ms,Ms,Webkit".split(","), 4342 _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) { 4343 var e = element || _tempDiv, 4344 s = e.style, 4345 i = 5; 4346 4347 if (property in s && !preferPrefix) { 4348 return property; 4349 } 4350 4351 property = property.charAt(0).toUpperCase() + property.substr(1); 4352 4353 while (i-- && !(_prefixes[i] + property in s)) {} 4354 4355 return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property; 4356 }, 4357 _initCore = function _initCore() { 4358 if (_windowExists$1() && window.document) { 4359 _win$1 = window; 4360 _doc$1 = _win$1.document; 4361 _docElement = _doc$1.documentElement; 4362 _tempDiv = _createElement("div") || { 4363 style: {} 4364 }; 4365 _tempDivStyler = _createElement("div"); 4366 _transformProp = _checkPropPrefix(_transformProp); 4367 _transformOriginProp = _transformProp + "Origin"; 4368 _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0"; 4369 _supports3D = !!_checkPropPrefix("perspective"); 4370 _reverting$1 = gsap.core.reverting; 4371 _pluginInitted = 1; 4372 } 4373 }, 4374 _getBBoxHack = function _getBBoxHack(swapIfPossible) { 4375 var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"), 4376 oldParent = this.parentNode, 4377 oldSibling = this.nextSibling, 4378 oldCSS = this.style.cssText, 4379 bbox; 4380 4381 _docElement.appendChild(svg); 4382 4383 svg.appendChild(this); 4384 this.style.display = "block"; 4385 4386 if (swapIfPossible) { 4387 try { 4388 bbox = this.getBBox(); 4389 this._gsapBBox = this.getBBox; 4390 this.getBBox = _getBBoxHack; 4391 } catch (e) {} 4392 } else if (this._gsapBBox) { 4393 bbox = this._gsapBBox(); 4394 } 4395 4396 if (oldParent) { 4397 if (oldSibling) { 4398 oldParent.insertBefore(this, oldSibling); 4399 } else { 4400 oldParent.appendChild(this); 4401 } 4402 } 4403 4404 _docElement.removeChild(svg); 4405 4406 this.style.cssText = oldCSS; 4407 return bbox; 4408 }, 4409 _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) { 4410 var i = attributesArray.length; 4411 4412 while (i--) { 4413 if (target.hasAttribute(attributesArray[i])) { 4414 return target.getAttribute(attributesArray[i]); 4415 } 4416 } 4417 }, 4418 _getBBox = function _getBBox(target) { 4419 var bounds; 4420 4421 try { 4422 bounds = target.getBBox(); 4423 } catch (error) { 4424 bounds = _getBBoxHack.call(target, true); 4425 } 4426 4427 bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true)); 4428 return bounds && !bounds.width && !bounds.x && !bounds.y ? { 4429 x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0, 4430 y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0, 4431 width: 0, 4432 height: 0 4433 } : bounds; 4434 }, 4435 _isSVG = function _isSVG(e) { 4436 return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e)); 4437 }, 4438 _removeProperty = function _removeProperty(target, property) { 4439 if (property) { 4440 var style = target.style, 4441 first2Chars; 4442 4443 if (property in _transformProps && property !== _transformOriginProp) { 4444 property = _transformProp; 4445 } 4446 4447 if (style.removeProperty) { 4448 first2Chars = property.substr(0, 2); 4449 4450 if (first2Chars === "ms" || property.substr(0, 6) === "webkit") { 4451 property = "-" + property; 4452 } 4453 4454 style.removeProperty(first2Chars === "--" ? property : property.replace(_capsExp, "-$1").toLowerCase()); 4455 } else { 4456 style.removeAttribute(property); 4457 } 4458 } 4459 }, 4460 _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) { 4461 var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue); 4462 plugin._pt = pt; 4463 pt.b = beginning; 4464 pt.e = end; 4465 4466 plugin._props.push(property); 4467 4468 return pt; 4469 }, 4470 _nonConvertibleUnits = { 4471 deg: 1, 4472 rad: 1, 4473 turn: 1 4474 }, 4475 _nonStandardLayouts = { 4476 grid: 1, 4477 flex: 1 4478 }, 4479 _convertToUnit = function _convertToUnit(target, property, value, unit) { 4480 var curValue = parseFloat(value) || 0, 4481 curUnit = (value + "").trim().substr((curValue + "").length) || "px", 4482 style = _tempDiv.style, 4483 horizontal = _horizontalExp.test(property), 4484 isRootSVG = target.tagName.toLowerCase() === "svg", 4485 measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"), 4486 amount = 100, 4487 toPixels = unit === "px", 4488 toPercent = unit === "%", 4489 px, 4490 parent, 4491 cache, 4492 isSVG; 4493 4494 if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) { 4495 return curValue; 4496 } 4497 4498 curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px")); 4499 isSVG = target.getCTM && _isSVG(target); 4500 4501 if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) { 4502 px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty]; 4503 return _round(toPercent ? curValue / px * amount : curValue / 100 * px); 4504 } 4505 4506 style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit); 4507 parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode; 4508 4509 if (isSVG) { 4510 parent = (target.ownerSVGElement || {}).parentNode; 4511 } 4512 4513 if (!parent || parent === _doc$1 || !parent.appendChild) { 4514 parent = _doc$1.body; 4515 } 4516 4517 cache = parent._gsap; 4518 4519 if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time && !cache.uncache) { 4520 return _round(curValue / cache.width * amount); 4521 } else { 4522 if (toPercent && (property === "height" || property === "width")) { 4523 var v = target.style[property]; 4524 target.style[property] = amount + unit; 4525 px = target[measureProperty]; 4526 v ? target.style[property] = v : _removeProperty(target, property); 4527 } else { 4528 (toPercent || curUnit === "%") && !_nonStandardLayouts[_getComputedProperty(parent, "display")] && (style.position = _getComputedProperty(target, "position")); 4529 parent === target && (style.position = "static"); 4530 parent.appendChild(_tempDiv); 4531 px = _tempDiv[measureProperty]; 4532 parent.removeChild(_tempDiv); 4533 style.position = "absolute"; 4534 } 4535 4536 if (horizontal && toPercent) { 4537 cache = _getCache(parent); 4538 cache.time = _ticker.time; 4539 cache.width = parent[measureProperty]; 4540 } 4541 } 4542 4543 return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0); 4544 }, 4545 _get = function _get(target, property, unit, uncache) { 4546 var value; 4547 _pluginInitted || _initCore(); 4548 4549 if (property in _propertyAliases && property !== "transform") { 4550 property = _propertyAliases[property]; 4551 4552 if (~property.indexOf(",")) { 4553 property = property.split(",")[0]; 4554 } 4555 } 4556 4557 if (_transformProps[property] && property !== "transform") { 4558 value = _parseTransform(target, uncache); 4559 value = property !== "transformOrigin" ? value[property] : value.svg ? value.origin : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px"; 4560 } else { 4561 value = target.style[property]; 4562 4563 if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) { 4564 value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0); 4565 } 4566 } 4567 4568 return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value; 4569 }, 4570 _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) { 4571 if (!start || start === "none") { 4572 var p = _checkPropPrefix(prop, target, 1), 4573 s = p && _getComputedProperty(target, p, 1); 4574 4575 if (s && s !== start) { 4576 prop = p; 4577 start = s; 4578 } else if (prop === "borderColor") { 4579 start = _getComputedProperty(target, "borderTopColor"); 4580 } 4581 } 4582 4583 var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString), 4584 index = 0, 4585 matchIndex = 0, 4586 a, 4587 result, 4588 startValues, 4589 startNum, 4590 color, 4591 startValue, 4592 endValue, 4593 endNum, 4594 chunk, 4595 endUnit, 4596 startUnit, 4597 endValues; 4598 pt.b = start; 4599 pt.e = end; 4600 start += ""; 4601 end += ""; 4602 4603 if (end === "auto") { 4604 startValue = target.style[prop]; 4605 target.style[prop] = end; 4606 end = _getComputedProperty(target, prop) || end; 4607 startValue ? target.style[prop] = startValue : _removeProperty(target, prop); 4608 } 4609 4610 a = [start, end]; 4611 4612 _colorStringFilter(a); 4613 4614 start = a[0]; 4615 end = a[1]; 4616 startValues = start.match(_numWithUnitExp) || []; 4617 endValues = end.match(_numWithUnitExp) || []; 4618 4619 if (endValues.length) { 4620 while (result = _numWithUnitExp.exec(end)) { 4621 endValue = result[0]; 4622 chunk = end.substring(index, result.index); 4623 4624 if (color) { 4625 color = (color + 1) % 5; 4626 } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") { 4627 color = 1; 4628 } 4629 4630 if (endValue !== (startValue = startValues[matchIndex++] || "")) { 4631 startNum = parseFloat(startValue) || 0; 4632 startUnit = startValue.substr((startNum + "").length); 4633 endValue.charAt(1) === "=" && (endValue = _parseRelative(startNum, endValue) + startUnit); 4634 endNum = parseFloat(endValue); 4635 endUnit = endValue.substr((endNum + "").length); 4636 index = _numWithUnitExp.lastIndex - endUnit.length; 4637 4638 if (!endUnit) { 4639 endUnit = endUnit || _config.units[prop] || startUnit; 4640 4641 if (index === end.length) { 4642 end += endUnit; 4643 pt.e += endUnit; 4644 } 4645 } 4646 4647 if (startUnit !== endUnit) { 4648 startNum = _convertToUnit(target, prop, startValue, endUnit) || 0; 4649 } 4650 4651 pt._pt = { 4652 _next: pt._pt, 4653 p: chunk || matchIndex === 1 ? chunk : ",", 4654 s: startNum, 4655 c: endNum - startNum, 4656 m: color && color < 4 || prop === "zIndex" ? Math.round : 0 4657 }; 4658 } 4659 } 4660 4661 pt.c = index < end.length ? end.substring(index, end.length) : ""; 4662 } else { 4663 pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue; 4664 } 4665 4666 _relExp.test(end) && (pt.e = 0); 4667 this._pt = pt; 4668 return pt; 4669 }, 4670 _keywordToPercent = { 4671 top: "0%", 4672 bottom: "100%", 4673 left: "0%", 4674 right: "100%", 4675 center: "50%" 4676 }, 4677 _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) { 4678 var split = value.split(" "), 4679 x = split[0], 4680 y = split[1] || "50%"; 4681 4682 if (x === "top" || x === "bottom" || y === "left" || y === "right") { 4683 value = x; 4684 x = y; 4685 y = value; 4686 } 4687 4688 split[0] = _keywordToPercent[x] || x; 4689 split[1] = _keywordToPercent[y] || y; 4690 return split.join(" "); 4691 }, 4692 _renderClearProps = function _renderClearProps(ratio, data) { 4693 if (data.tween && data.tween._time === data.tween._dur) { 4694 var target = data.t, 4695 style = target.style, 4696 props = data.u, 4697 cache = target._gsap, 4698 prop, 4699 clearTransforms, 4700 i; 4701 4702 if (props === "all" || props === true) { 4703 style.cssText = ""; 4704 clearTransforms = 1; 4705 } else { 4706 props = props.split(","); 4707 i = props.length; 4708 4709 while (--i > -1) { 4710 prop = props[i]; 4711 4712 if (_transformProps[prop]) { 4713 clearTransforms = 1; 4714 prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp; 4715 } 4716 4717 _removeProperty(target, prop); 4718 } 4719 } 4720 4721 if (clearTransforms) { 4722 _removeProperty(target, _transformProp); 4723 4724 if (cache) { 4725 cache.svg && target.removeAttribute("transform"); 4726 4727 _parseTransform(target, 1); 4728 4729 cache.uncache = 1; 4730 4731 _removeIndependentTransforms(style); 4732 } 4733 } 4734 } 4735 }, 4736 _specialProps = { 4737 clearProps: function clearProps(plugin, target, property, endValue, tween) {
vendor: 1,580 bytes, lines 4738-4778
4738 if (tween.data !== "isFromStart") { 4739 var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps); 4740 pt.u = endValue; 4741 pt.pr = -10; 4742 pt.tween = tween; 4743 4744 plugin._props.push(property); 4745 4746 return 1; 4747 } 4748 } 4749 }, 4750 _identity2DMatrix = [1, 0, 0, 1, 0, 0], 4751 _rotationalProperties = {}, 4752 _isNullTransform = function _isNullTransform(value) { 4753 return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value; 4754 }, 4755 _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) { 4756 var matrixString = _getComputedProperty(target, _transformProp); 4757 4758 return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round); 4759 }, 4760 _getMatrix = function _getMatrix(target, force2D) { 4761 var cache = target._gsap || _getCache(target), 4762 style = target.style, 4763 matrix = _getComputedTransformMatrixAsArray(target), 4764 parent, 4765 nextSibling, 4766 temp, 4767 addedToDOM; 4768 4769 if (cache.svg && target.getAttribute("transform")) { 4770 temp = target.transform.baseVal.consolidate().matrix; 4771 matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f]; 4772 return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix; 4773 } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) { 4774 temp = style.display; 4775 style.display = "block"; 4776 parent = target.parentNode; 4777 4778 if (!parent || !target.offsetParent
vendor: 18,926 bytes, lines 4778-5375
4778) { 4779 addedToDOM = 1; 4780 nextSibling = target.nextElementSibling; 4781 4782 _docElement.appendChild(target); 4783 } 4784 4785 matrix = _getComputedTransformMatrixAsArray(target); 4786 temp ? style.display = temp : _removeProperty(target, "display"); 4787 4788 if (addedToDOM) { 4789 nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target); 4790 } 4791 } 4792 4793 return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix; 4794 }, 4795 _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) { 4796 var cache = target._gsap, 4797 matrix = matrixArray || _getMatrix(target, true), 4798 xOriginOld = cache.xOrigin || 0, 4799 yOriginOld = cache.yOrigin || 0, 4800 xOffsetOld = cache.xOffset || 0, 4801 yOffsetOld = cache.yOffset || 0, 4802 a = matrix[0], 4803 b = matrix[1], 4804 c = matrix[2], 4805 d = matrix[3], 4806 tx = matrix[4], 4807 ty = matrix[5], 4808 originSplit = origin.split(" "), 4809 xOrigin = parseFloat(originSplit[0]) || 0, 4810 yOrigin = parseFloat(originSplit[1]) || 0, 4811 bounds, 4812 determinant, 4813 x, 4814 y; 4815 4816 if (!originIsAbsolute) { 4817 bounds = _getBBox(target); 4818 xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * bounds.width : xOrigin); 4819 yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin); 4820 } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) { 4821 x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant; 4822 y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant; 4823 xOrigin = x; 4824 yOrigin = y; 4825 } 4826 4827 if (smooth || smooth !== false && cache.smooth) { 4828 tx = xOrigin - xOriginOld; 4829 ty = yOrigin - yOriginOld; 4830 cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx; 4831 cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty; 4832 } else { 4833 cache.xOffset = cache.yOffset = 0; 4834 } 4835 4836 cache.xOrigin = xOrigin; 4837 cache.yOrigin = yOrigin; 4838 cache.smooth = !!smooth; 4839 cache.origin = origin; 4840 cache.originIsAbsolute = !!originIsAbsolute; 4841 target.style[_transformOriginProp] = "0px 0px"; 4842 4843 if (pluginToAddPropTweensTo) { 4844 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin); 4845 4846 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin); 4847 4848 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset); 4849 4850 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset); 4851 } 4852 4853 target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin); 4854 }, 4855 _parseTransform = function _parseTransform(target, uncache) { 4856 var cache = target._gsap || new GSCache(target); 4857 4858 if ("x" in cache && !uncache && !cache.uncache) { 4859 return cache; 4860 } 4861 4862 var style = target.style, 4863 invertedScaleX = cache.scaleX < 0, 4864 px = "px", 4865 deg = "deg", 4866 cs = getComputedStyle(target), 4867 origin = _getComputedProperty(target, _transformOriginProp) || "0", 4868 x, 4869 y, 4870 z, 4871 scaleX, 4872 scaleY, 4873 rotation, 4874 rotationX, 4875 rotationY, 4876 skewX, 4877 skewY, 4878 perspective, 4879 xOrigin, 4880 yOrigin, 4881 matrix, 4882 angle, 4883 cos, 4884 sin, 4885 a, 4886 b, 4887 c, 4888 d, 4889 a12, 4890 a22, 4891 t1, 4892 t2, 4893 t3, 4894 a13, 4895 a23, 4896 a33, 4897 a42, 4898 a43, 4899 a32; 4900 x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0; 4901 scaleX = scaleY = 1; 4902 cache.svg = !!(target.getCTM && _isSVG(target)); 4903 4904 if (cs.translate) { 4905 if (cs.translate !== "none" || cs.scale !== "none" || cs.rotate !== "none") { 4906 style[_transformProp] = (cs.translate !== "none" ? "translate3d(" + (cs.translate + " 0 0").split(" ").slice(0, 3).join(", ") + ") " : "") + (cs.rotate !== "none" ? "rotate(" + cs.rotate + ") " : "") + (cs.scale !== "none" ? "scale(" + cs.scale.split(" ").join(",") + ") " : "") + (cs[_transformProp] !== "none" ? cs[_transformProp] : ""); 4907 } 4908 4909 style.scale = style.rotate = style.translate = "none"; 4910 } 4911 4912 matrix = _getMatrix(target, cache.svg); 4913 4914 if (cache.svg) { 4915 if (cache.uncache) { 4916 t2 = target.getBBox(); 4917 origin = cache.xOrigin - t2.x + "px " + (cache.yOrigin - t2.y) + "px"; 4918 t1 = ""; 4919 } else { 4920 t1 = !uncache && target.getAttribute("data-svg-origin"); 4921 } 4922 4923 _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix); 4924 } 4925 4926 xOrigin = cache.xOrigin || 0; 4927 yOrigin = cache.yOrigin || 0; 4928 4929 if (matrix !== _identity2DMatrix) { 4930 a = matrix[0]; 4931 b = matrix[1]; 4932 c = matrix[2]; 4933 d = matrix[3]; 4934 x = a12 = matrix[4]; 4935 y = a22 = matrix[5]; 4936 4937 if (matrix.length === 6) { 4938 scaleX = Math.sqrt(a * a + b * b); 4939 scaleY = Math.sqrt(d * d + c * c); 4940 rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0; 4941 skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0; 4942 skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD))); 4943 4944 if (cache.svg) { 4945 x -= xOrigin - (xOrigin * a + yOrigin * c); 4946 y -= yOrigin - (xOrigin * b + yOrigin * d); 4947 } 4948 } else { 4949 a32 = matrix[6]; 4950 a42 = matrix[7]; 4951 a13 = matrix[8]; 4952 a23 = matrix[9]; 4953 a33 = matrix[10]; 4954 a43 = matrix[11]; 4955 x = matrix[12]; 4956 y = matrix[13]; 4957 z = matrix[14]; 4958 angle = _atan2(a32, a33); 4959 rotationX = angle * _RAD2DEG; 4960 4961 if (angle) { 4962 cos = Math.cos(-angle); 4963 sin = Math.sin(-angle); 4964 t1 = a12 * cos + a13 * sin; 4965 t2 = a22 * cos + a23 * sin; 4966 t3 = a32 * cos + a33 * sin; 4967 a13 = a12 * -sin + a13 * cos; 4968 a23 = a22 * -sin + a23 * cos; 4969 a33 = a32 * -sin + a33 * cos; 4970 a43 = a42 * -sin + a43 * cos; 4971 a12 = t1; 4972 a22 = t2; 4973 a32 = t3; 4974 } 4975 4976 angle = _atan2(-c, a33); 4977 rotationY = angle * _RAD2DEG; 4978 4979 if (angle) { 4980 cos = Math.cos(-angle); 4981 sin = Math.sin(-angle); 4982 t1 = a * cos - a13 * sin; 4983 t2 = b * cos - a23 * sin; 4984 t3 = c * cos - a33 * sin; 4985 a43 = d * sin + a43 * cos; 4986 a = t1; 4987 b = t2; 4988 c = t3; 4989 } 4990 4991 angle = _atan2(b, a); 4992 rotation = angle * _RAD2DEG; 4993 4994 if (angle) { 4995 cos = Math.cos(angle); 4996 sin = Math.sin(angle); 4997 t1 = a * cos + b * sin; 4998 t2 = a12 * cos + a22 * sin; 4999 b = b * cos - a * sin; 5000 a22 = a22 * cos - a12 * sin; 5001 a = t1; 5002 a12 = t2; 5003 } 5004 5005 if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) { 5006 rotationX = rotation = 0; 5007 rotationY = 180 - rotationY; 5008 } 5009 5010 scaleX = _round(Math.sqrt(a * a + b * b + c * c)); 5011 scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32)); 5012 angle = _atan2(a12, a22); 5013 skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0; 5014 perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0; 5015 } 5016 5017 if (cache.svg) { 5018 t1 = target.getAttribute("transform"); 5019 cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp)); 5020 t1 && target.setAttribute("transform", t1); 5021 } 5022 } 5023 5024 if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) { 5025 if (invertedScaleX) { 5026 scaleX *= -1; 5027 skewX += rotation <= 0 ? 180 : -180; 5028 rotation += rotation <= 0 ? 180 : -180; 5029 } else { 5030 scaleY *= -1; 5031 skewX += skewX <= 0 ? 180 : -180; 5032 } 5033 } 5034 5035 uncache = uncache || cache.uncache; 5036 cache.x = x - ((cache.xPercent = x && (!uncache && cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px; 5037 cache.y = y - ((cache.yPercent = y && (!uncache && cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px; 5038 cache.z = z + px; 5039 cache.scaleX = _round(scaleX); 5040 cache.scaleY = _round(scaleY); 5041 cache.rotation = _round(rotation) + deg; 5042 cache.rotationX = _round(rotationX) + deg; 5043 cache.rotationY = _round(rotationY) + deg; 5044 cache.skewX = skewX + deg; 5045 cache.skewY = skewY + deg; 5046 cache.transformPerspective = perspective + px; 5047 5048 if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || !uncache && cache.zOrigin || 0) { 5049 style[_transformOriginProp] = _firstTwoOnly(origin); 5050 } 5051 5052 cache.xOffset = cache.yOffset = 0; 5053 cache.force3D = _config.force3D; 5054 cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms; 5055 cache.uncache = 0; 5056 return cache; 5057 }, 5058 _firstTwoOnly = function _firstTwoOnly(value) { 5059 return (value = value.split(" "))[0] + " " + value[1]; 5060 }, 5061 _addPxTranslate = function _addPxTranslate(target, start, value) { 5062 var unit = getUnit(start); 5063 return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit; 5064 }, 5065 _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) { 5066 cache.z = "0px"; 5067 cache.rotationY = cache.rotationX = "0deg"; 5068 cache.force3D = 0; 5069 5070 _renderCSSTransforms(ratio, cache); 5071 }, 5072 _zeroDeg = "0deg", 5073 _zeroPx = "0px", 5074 _endParenthesis = ") ", 5075 _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) { 5076 var _ref = cache || this, 5077 xPercent = _ref.xPercent, 5078 yPercent = _ref.yPercent, 5079 x = _ref.x, 5080 y = _ref.y, 5081 z = _ref.z, 5082 rotation = _ref.rotation, 5083 rotationY = _ref.rotationY, 5084 rotationX = _ref.rotationX, 5085 skewX = _ref.skewX, 5086 skewY = _ref.skewY, 5087 scaleX = _ref.scaleX, 5088 scaleY = _ref.scaleY, 5089 transformPerspective = _ref.transformPerspective, 5090 force3D = _ref.force3D, 5091 target = _ref.target, 5092 zOrigin = _ref.zOrigin, 5093 transforms = "", 5094 use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true; 5095 5096 if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) { 5097 var angle = parseFloat(rotationY) * _DEG2RAD, 5098 a13 = Math.sin(angle), 5099 a33 = Math.cos(angle), 5100 cos; 5101 5102 angle = parseFloat(rotationX) * _DEG2RAD; 5103 cos = Math.cos(angle); 5104 x = _addPxTranslate(target, x, a13 * cos * -zOrigin); 5105 y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin); 5106 z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin); 5107 } 5108 5109 if (transformPerspective !== _zeroPx) { 5110 transforms += "perspective(" + transformPerspective + _endParenthesis; 5111 } 5112 5113 if (xPercent || yPercent) { 5114 transforms += "translate(" + xPercent + "%, " + yPercent + "%) "; 5115 } 5116 5117 if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) { 5118 transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis; 5119 } 5120 5121 if (rotation !== _zeroDeg) { 5122 transforms += "rotate(" + rotation + _endParenthesis; 5123 } 5124 5125 if (rotationY !== _zeroDeg) { 5126 transforms += "rotateY(" + rotationY + _endParenthesis; 5127 } 5128 5129 if (rotationX !== _zeroDeg) { 5130 transforms += "rotateX(" + rotationX + _endParenthesis; 5131 } 5132 5133 if (skewX !== _zeroDeg || skewY !== _zeroDeg) { 5134 transforms += "skew(" + skewX + ", " + skewY + _endParenthesis; 5135 } 5136 5137 if (scaleX !== 1 || scaleY !== 1) { 5138 transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis; 5139 } 5140 5141 target.style[_transformProp] = transforms || "translate(0, 0)"; 5142 }, 5143 _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) { 5144 var _ref2 = cache || this, 5145 xPercent = _ref2.xPercent, 5146 yPercent = _ref2.yPercent, 5147 x = _ref2.x, 5148 y = _ref2.y, 5149 rotation = _ref2.rotation, 5150 skewX = _ref2.skewX, 5151 skewY = _ref2.skewY, 5152 scaleX = _ref2.scaleX, 5153 scaleY = _ref2.scaleY, 5154 target = _ref2.target, 5155 xOrigin = _ref2.xOrigin, 5156 yOrigin = _ref2.yOrigin, 5157 xOffset = _ref2.xOffset, 5158 yOffset = _ref2.yOffset, 5159 forceCSS = _ref2.forceCSS, 5160 tx = parseFloat(x), 5161 ty = parseFloat(y), 5162 a11, 5163 a21, 5164 a12, 5165 a22, 5166 temp; 5167 5168 rotation = parseFloat(rotation); 5169 skewX = parseFloat(skewX); 5170 skewY = parseFloat(skewY); 5171 5172 if (skewY) { 5173 skewY = parseFloat(skewY); 5174 skewX += skewY; 5175 rotation += skewY; 5176 } 5177 5178 if (rotation || skewX) { 5179 rotation *= _DEG2RAD; 5180 skewX *= _DEG2RAD; 5181 a11 = Math.cos(rotation) * scaleX; 5182 a21 = Math.sin(rotation) * scaleX; 5183 a12 = Math.sin(rotation - skewX) * -scaleY; 5184 a22 = Math.cos(rotation - skewX) * scaleY; 5185 5186 if (skewX) { 5187 skewY *= _DEG2RAD; 5188 temp = Math.tan(skewX - skewY); 5189 temp = Math.sqrt(1 + temp * temp); 5190 a12 *= temp; 5191 a22 *= temp; 5192 5193 if (skewY) { 5194 temp = Math.tan(skewY); 5195 temp = Math.sqrt(1 + temp * temp); 5196 a11 *= temp; 5197 a21 *= temp; 5198 } 5199 } 5200 5201 a11 = _round(a11); 5202 a21 = _round(a21); 5203 a12 = _round(a12); 5204 a22 = _round(a22); 5205 } else { 5206 a11 = scaleX; 5207 a22 = scaleY; 5208 a21 = a12 = 0; 5209 } 5210 5211 if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) { 5212 tx = _convertToUnit(target, "x", x, "px"); 5213 ty = _convertToUnit(target, "y", y, "px"); 5214 } 5215 5216 if (xOrigin || yOrigin || xOffset || yOffset) { 5217 tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset); 5218 ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset); 5219 } 5220 5221 if (xPercent || yPercent) { 5222 temp = target.getBBox(); 5223 tx = _round(tx + xPercent / 100 * temp.width); 5224 ty = _round(ty + yPercent / 100 * temp.height); 5225 } 5226 5227 temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")"; 5228 target.setAttribute("transform", temp); 5229 forceCSS && (target.style[_transformProp] = temp); 5230 }, 5231 _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue) { 5232 var cap = 360, 5233 isString = _isString(endValue), 5234 endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1), 5235 change = endNum - startNum, 5236 finalValue = startNum + change + "deg", 5237 direction, 5238 pt; 5239 5240 if (isString) { 5241 direction = endValue.split("_")[1]; 5242 5243 if (direction === "short") { 5244 change %= cap; 5245 5246 if (change !== change % (cap / 2)) { 5247 change += change < 0 ? cap : -cap; 5248 } 5249 } 5250 5251 if (direction === "cw" && change < 0) { 5252 change = (change + cap * _bigNum$1) % cap - ~~(change / cap) * cap; 5253 } else if (direction === "ccw" && change > 0) { 5254 change = (change - cap * _bigNum$1) % cap - ~~(change / cap) * cap; 5255 } 5256 } 5257 5258 plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd); 5259 pt.e = finalValue; 5260 pt.u = "deg"; 5261 5262 plugin._props.push(property); 5263 5264 return pt; 5265 }, 5266 _assign = function _assign(target, source) { 5267 for (var p in source) { 5268 target[p] = source[p]; 5269 } 5270 5271 return target; 5272 }, 5273 _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) { 5274 var startCache = _assign({}, target._gsap), 5275 exclude = "perspective,force3D,transformOrigin,svgOrigin", 5276 style = target.style, 5277 endCache, 5278 p, 5279 startValue, 5280 endValue, 5281 startNum, 5282 endNum, 5283 startUnit, 5284 endUnit; 5285 5286 if (startCache.svg) { 5287 startValue = target.getAttribute("transform"); 5288 target.setAttribute("transform", ""); 5289 style[_transformProp] = transforms; 5290 endCache = _parseTransform(target, 1); 5291 5292 _removeProperty(target, _transformProp); 5293 5294 target.setAttribute("transform", startValue); 5295 } else { 5296 startValue = getComputedStyle(target)[_transformProp]; 5297 style[_transformProp] = transforms; 5298 endCache = _parseTransform(target, 1); 5299 style[_transformProp] = startValue; 5300 } 5301 5302 for (p in _transformProps) { 5303 startValue = startCache[p]; 5304 endValue = endCache[p]; 5305 5306 if (startValue !== endValue && exclude.indexOf(p) < 0) { 5307 startUnit = getUnit(startValue); 5308 endUnit = getUnit(endValue); 5309 startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue); 5310 endNum = parseFloat(endValue); 5311 plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp); 5312 plugin._pt.u = endUnit || 0; 5313 5314 plugin._props.push(p); 5315 } 5316 } 5317 5318 _assign(endCache, startCache); 5319 }; 5320 5321 _forEachName("padding,margin,Width,Radius", function (name, index) { 5322 var t = "Top", 5323 r = "Right", 5324 b = "Bottom", 5325 l = "Left", 5326 props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) { 5327 return index < 2 ? name + side : "border" + side + name; 5328 }); 5329 5330 _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) { 5331 var a, vars; 5332 5333 if (arguments.length < 4) { 5334 a = props.map(function (prop) { 5335 return _get(plugin, prop, property); 5336 }); 5337 vars = a.join(" "); 5338 return vars.split(a[0]).length === 5 ? a[0] : vars; 5339 } 5340 5341 a = (endValue + "").split(" "); 5342 vars = {}; 5343 props.forEach(function (prop, i) { 5344 return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0]; 5345 }); 5346 plugin.init(target, vars, tween); 5347 }; 5348 }); 5349 5350 var CSSPlugin = { 5351 name: "css", 5352 register: _initCore, 5353 targetTest: function targetTest(target) { 5354 return target.style && target.nodeType; 5355 }, 5356 init: function init(target, vars, tween, index, targets) { 5357 var props = this._props, 5358 style = target.style, 5359 startAt = tween.vars.startAt, 5360 startValue, 5361 endValue, 5362 endNum, 5363 startNum, 5364 type, 5365 specialProp, 5366 p, 5367 startUnit, 5368 endUnit, 5369 relative, 5370 isTransformRelated, 5371 transformPropTween, 5372 cache, 5373 smooth, 5374 hasPriority, 5375 inlineProps
vendor: 8,025 bytes, lines 5375-5562
5375; 5376 _pluginInitted || _initCore(); 5377 this.styles = this.styles || _getStyleSaver(target); 5378 inlineProps = this.styles.props; 5379 this.tween = tween; 5380 5381 for (p in vars) { 5382 if (p === "autoRound") { 5383 continue; 5384 } 5385 5386 endValue = vars[p]; 5387 5388 if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) { 5389 continue; 5390 } 5391 5392 type = typeof endValue; 5393 specialProp = _specialProps[p]; 5394 5395 if (type === "function") { 5396 endValue = endValue.call(tween, index, target, targets); 5397 type = typeof endValue; 5398 } 5399 5400 if (type === "string" && ~endValue.indexOf("random(")) { 5401 endValue = _replaceRandom(endValue); 5402 } 5403 5404 if (specialProp) { 5405 specialProp(this, target, p, endValue, tween) && (hasPriority = 1); 5406 } else if (p.substr(0, 2) === "--") { 5407 startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim(); 5408 endValue += ""; 5409 _colorExp.lastIndex = 0; 5410 5411 if (!_colorExp.test(startValue)) { 5412 startUnit = getUnit(startValue); 5413 endUnit = getUnit(endValue); 5414 } 5415 5416 endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit); 5417 this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p); 5418 props.push(p); 5419 inlineProps.push(p, 0, style[p]); 5420 } else if (type !== "undefined") { 5421 if (startAt && p in startAt) { 5422 startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p]; 5423 _isString(startValue) && ~startValue.indexOf("random(") && (startValue = _replaceRandom(startValue)); 5424 getUnit(startValue + "") || startValue === "auto" || (startValue += _config.units[p] || getUnit(_get(target, p)) || ""); 5425 (startValue + "").charAt(1) === "=" && (startValue = _get(target, p)); 5426 } else { 5427 startValue = _get(target, p); 5428 } 5429 5430 startNum = parseFloat(startValue); 5431 relative = type === "string" && endValue.charAt(1) === "=" && endValue.substr(0, 2); 5432 relative && (endValue = endValue.substr(2)); 5433 endNum = parseFloat(endValue); 5434 5435 if (p in _propertyAliases) { 5436 if (p === "autoAlpha") { 5437 if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) { 5438 startNum = 0; 5439 } 5440 5441 inlineProps.push("visibility", 0, style.visibility); 5442 5443 _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum); 5444 } 5445 5446 if (p !== "scale" && p !== "transform") { 5447 p = _propertyAliases[p]; 5448 ~p.indexOf(",") && (p = p.split(",")[0]); 5449 } 5450 } 5451 5452 isTransformRelated = p in _transformProps; 5453 5454 if (isTransformRelated) { 5455 this.styles.save(p); 5456 5457 if (!transformPropTween) { 5458 cache = target._gsap; 5459 cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform); 5460 smooth = vars.smoothOrigin !== false && cache.smooth; 5461 transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1); 5462 transformPropTween.dep = 1; 5463 } 5464 5465 if (p === "scale") { 5466 this._pt = new PropTween(this._pt, cache, "scaleY", cache.scaleY, (relative ? _parseRelative(cache.scaleY, relative + endNum) : endNum) - cache.scaleY || 0, _renderCSSProp); 5467 this._pt.u = 0; 5468 props.push("scaleY", p); 5469 p += "X"; 5470 } else if (p === "transformOrigin") { 5471 inlineProps.push(_transformOriginProp, 0, style[_transformOriginProp]); 5472 endValue = _convertKeywordsToPercentages(endValue); 5473 5474 if (cache.svg) { 5475 _applySVGOrigin(target, endValue, 0, smooth, 0, this); 5476 } else { 5477 endUnit = parseFloat(endValue.split(" ")[2]) || 0; 5478 endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit); 5479 5480 _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue)); 5481 } 5482 5483 continue; 5484 } else if (p === "svgOrigin") { 5485 _applySVGOrigin(target, endValue, 1, smooth, 0, this); 5486 5487 continue; 5488 } else if (p in _rotationalProperties) { 5489 _addRotationalPropTween(this, cache, p, startNum, relative ? _parseRelative(startNum, relative + endValue) : endValue); 5490 5491 continue; 5492 } else if (p === "smoothOrigin") { 5493 _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue); 5494 5495 continue; 5496 } else if (p === "force3D") { 5497 cache[p] = endValue; 5498 continue; 5499 } else if (p === "transform") { 5500 _addRawTransformPTs(this, endValue, target); 5501 5502 continue; 5503 } 5504 } else if (!(p in style)) { 5505 p = _checkPropPrefix(p) || p; 5506 } 5507 5508 if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) { 5509 startUnit = (startValue + "").substr((startNum + "").length); 5510 endNum || (endNum = 0); 5511 endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit); 5512 startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit)); 5513 this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, (relative ? _parseRelative(startNum, relative + endNum) : endNum) - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp); 5514 this._pt.u = endUnit || 0; 5515 5516 if (startUnit !== endUnit && endUnit !== "%") { 5517 this._pt.b = startValue; 5518 this._pt.r = _renderCSSPropWithBeginning; 5519 } 5520 } else if (!(p in style)) { 5521 if (p in target) { 5522 this.add(target, p, startValue || target[p], relative ? relative + endValue : endValue, index, targets); 5523 } else if (p !== "parseTransform") { 5524 _missingPlugin(p, endValue); 5525 5526 continue; 5527 } 5528 } else { 5529 _tweenComplexCSSString.call(this, target, p, startValue, relative ? relative + endValue : endValue); 5530 } 5531 5532 isTransformRelated || (p in style ? inlineProps.push(p, 0, style[p]) : inlineProps.push(p, 1, startValue || target[p])); 5533 props.push(p); 5534 } 5535 } 5536 5537 hasPriority && _sortPropTweensByPriority(this); 5538 }, 5539 render: function render(ratio, data) { 5540 if (data.tween._time || !_reverting$1()) { 5541 var pt = data._pt; 5542 5543 while (pt) { 5544 pt.r(ratio, pt.d); 5545 pt = pt._next; 5546 } 5547 } else { 5548 data.styles.revert(); 5549 } 5550 }, 5551 get: _get, 5552 aliases: _propertyAliases, 5553 getSetter: function getSetter(target, property, plugin) { 5554 var p = _propertyAliases[property]; 5555 p && p.indexOf(",") < 0 && (property = p); 5556 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); 5557 }, 5558 core: { 5559 _removeProperty: _removeProperty, 5560 _getMatrix: _getMatrix 5561 } 5562 };
vendor: 2,056 bytes, lines 5563-5621
5563 gsap.utils.checkPrefix = _checkPropPrefix; 5564 gsap.core.getStyleSaver = _getStyleSaver; 5565 5566 (function (positionAndScale, rotation, others, aliases) { 5567 var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) { 5568 _transformProps[name] = 1; 5569 }); 5570 5571 _forEachName(rotation, function (name) { 5572 _config.units[name] = "deg"; 5573 _rotationalProperties[name] = 1; 5574 }); 5575 5576 _propertyAliases[all[13]] = positionAndScale + "," + rotation; 5577 5578 _forEachName(aliases, function (name) { 5579 var split = name.split(":"); 5580 _propertyAliases[split[1]] = all[split[0]]; 5581 }); 5582 })("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"); 5583 5584 _forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) { 5585 _config.units[name] = "px"; 5586 }); 5587 5588 gsap.registerPlugin(CSSPlugin); 5589 5590 var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap, 5591 TweenMaxWithCSS = gsapWithCSS.core.Tween; 5592 5593 exports.Back = Back; 5594 exports.Bounce = Bounce; 5595 exports.CSSPlugin = CSSPlugin; 5596 exports.Circ = Circ; 5597 exports.Cubic = Cubic; 5598 exports.Elastic = Elastic; 5599 exports.Expo = Expo; 5600 exports.Linear = Linear; 5601 exports.Power0 = Power0; 5602 exports.Power1 = Power1; 5603 exports.Power2 = Power2; 5604 exports.Power3 = Power3; 5605 exports.Power4 = Power4; 5606 exports.Quad = Quad; 5607 exports.Quart = Quart; 5608 exports.Quint = Quint; 5609 exports.Sine = Sine; 5610 exports.SteppedEase = SteppedEase; 5611 exports.Strong = Strong; 5612 exports.TimelineLite = Timeline; 5613 exports.TimelineMax = Timeline; 5614 exports.TweenLite = Tween; 5615 exports.TweenMax = TweenMaxWithCSS; 5616 exports.default = gsapWithCSS; 5617 exports.gsap = gsapWithCSS; 5618 5619 if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;} 5620 5621})));
vendor: 247,641 bytes, lines 5622-13099
5622/*! 5623 * matter-js 0.20.0 by @liabru 5624 * http://brm.io/matter-js/ 5625 * License MIT 5626 * 5627 * The MIT License (MIT) 5628 * 5629 * Copyright (c) Liam Brummitt and contributors. 5630 * 5631 * Permission is hereby granted, free of charge, to any person obtaining a copy 5632 * of this software and associated documentation files (the "Software"), to deal 5633 * in the Software without restriction, including without limitation the rights 5634 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5635 * copies of the Software, and to permit persons to whom the Software is 5636 * furnished to do so, subject to the following conditions: 5637 * 5638 * The above copyright notice and this permission notice shall be included in 5639 * all copies or substantial portions of the Software. 5640 * 5641 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 5642 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 5643 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 5644 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 5645 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 5646 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 5647 * THE SOFTWARE. 5648 */ 5649(function webpackUniversalModuleDefinition(root, factory) { 5650 if(typeof exports === 'object' && typeof module === 'object') 5651 module.exports = factory(); 5652 else if(typeof define === 'function' && define.amd) 5653 define("Matter", [], factory); 5654 else if(typeof exports === 'object') 5655 exports["Matter"] = factory(); 5656 else 5657 root["Matter"] = factory(); 5658})(this, function() { 5659return /******/ (function(modules) { // webpackBootstrap 5660/******/ // The module cache 5661/******/ var installedModules = {}; 5662/******/ 5663/******/ // The require function 5664/******/ function __webpack_require__(moduleId) { 5665/******/ 5666/******/ // Check if module is in cache 5667/******/ if(installedModules[moduleId]) { 5668/******/ return installedModules[moduleId].exports; 5669/******/ } 5670/******/ // Create a new module (and put it into the cache) 5671/******/ var module = installedModules[moduleId] = { 5672/******/ i: moduleId, 5673/******/ l: false, 5674/******/ exports: {} 5675/******/ }; 5676/******/ 5677/******/ // Execute the module function 5678/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 5679/******/ 5680/******/ // Flag the module as loaded 5681/******/ module.l = true; 5682/******/ 5683/******/ // Return the exports of the module 5684/******/ return module.exports; 5685/******/ } 5686/******/ 5687/******/ 5688/******/ // expose the modules object (__webpack_modules__) 5689/******/ __webpack_require__.m = modules; 5690/******/ 5691/******/ // expose the module cache 5692/******/ __webpack_require__.c = installedModules; 5693/******/ 5694/******/ // define getter function for harmony exports 5695/******/ __webpack_require__.d = function(exports, name, getter) { 5696/******/ if(!__webpack_require__.o(exports, name)) { 5697/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 5698/******/ } 5699/******/ }; 5700/******/ 5701/******/ // define __esModule on exports 5702/******/ __webpack_require__.r = function(exports) { 5703/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 5704/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 5705/******/ } 5706/******/ Object.defineProperty(exports, '__esModule', { value: true }); 5707/******/ }; 5708/******/ 5709/******/ // create a fake namespace object 5710/******/ // mode & 1: value is a module id, require it 5711/******/ // mode & 2: merge all properties of value into the ns 5712/******/ // mode & 4: return value when already ns object 5713/******/ // mode & 8|1: behave like require 5714/******/ __webpack_require__.t = function(value, mode) { 5715/******/ if(mode & 1) value = __webpack_require__(value); 5716/******/ if(mode & 8) return value; 5717/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 5718/******/ var ns = Object.create(null); 5719/******/ __webpack_require__.r(ns); 5720/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 5721/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 5722/******/ return ns; 5723/******/ }; 5724/******/ 5725/******/ // getDefaultExport function for compatibility with non-harmony modules 5726/******/ __webpack_require__.n = function(module) { 5727/******/ var getter = module && module.__esModule ? 5728/******/ function getDefault() { return module['default']; } : 5729/******/ function getModuleExports() { return module; }; 5730/******/ __webpack_require__.d(getter, 'a', getter); 5731/******/ return getter; 5732/******/ }; 5733/******/ 5734/******/ // Object.prototype.hasOwnProperty.call 5735/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 5736/******/ 5737/******/ // __webpack_public_path__ 5738/******/ __webpack_require__.p = ""; 5739/******/ 5740/******/ 5741/******/ // Load entry module and return exports 5742/******/ return __webpack_require__(__webpack_require__.s = 20); 5743/******/ }) 5744/************************************************************************/ 5745/******/ ([ 5746/* 0 */ 5747/***/ (function(module, exports) { 5748 5749/** 5750* The `Matter.Common` module contains utility functions that are common to all modules. 5751* 5752* @class Common 5753*/ 5754 5755var Common = {}; 5756 5757module.exports = Common; 5758 5759(function() { 5760 5761 Common._baseDelta = 1000 / 60; 5762 Common._nextId = 0; 5763 Common._seed = 0; 5764 Common._nowStartTime = +(new Date()); 5765 Common._warnedOnce = {}; 5766 Common._decomp = null; 5767 5768 /** 5769 * Extends the object in the first argument using the object in the second argument. 5770 * @method extend 5771 * @param {} obj 5772 * @param {boolean} deep 5773 * @return {} obj extended 5774 */ 5775 Common.extend = function(obj, deep) { 5776 var argsStart, 5777 args, 5778 deepClone; 5779 5780 if (typeof deep === 'boolean') { 5781 argsStart = 2; 5782 deepClone = deep; 5783 } else { 5784 argsStart = 1; 5785 deepClone = true; 5786 } 5787 5788 for (var i = argsStart; i < arguments.length; i++) { 5789 var source = arguments[i]; 5790 5791 if (source) { 5792 for (var prop in source) { 5793 if (deepClone && source[prop] && source[prop].constructor === Object) { 5794 if (!obj[prop] || obj[prop].constructor === Object) { 5795 obj[prop] = obj[prop] || {}; 5796 Common.extend(obj[prop], deepClone, source[prop]); 5797 } else { 5798 obj[prop] = source[prop]; 5799 } 5800 } else { 5801 obj[prop] = source[prop]; 5802 } 5803 } 5804 } 5805 } 5806 5807 return obj; 5808 }; 5809 5810 /** 5811 * Creates a new clone of the object, if deep is true references will also be cloned. 5812 * @method clone 5813 * @param {} obj 5814 * @param {bool} deep 5815 * @return {} obj cloned 5816 */ 5817 Common.clone = function(obj, deep) { 5818 return Common.extend({}, deep, obj); 5819 }; 5820 5821 /** 5822 * Returns the list of keys for the given object. 5823 * @method keys 5824 * @param {} obj 5825 * @return {string[]} keys 5826 */ 5827 Common.keys = function(obj) { 5828 if (Object.keys) 5829 return Object.keys(obj); 5830 5831 // avoid hasOwnProperty for performance 5832 var keys = []; 5833 for (var key in obj) 5834 keys.push(key); 5835 return keys; 5836 }; 5837 5838 /** 5839 * Returns the list of values for the given object. 5840 * @method values 5841 * @param {} obj 5842 * @return {array} Array of the objects property values 5843 */ 5844 Common.values = function(obj) { 5845 var values = []; 5846 5847 if (Object.keys) { 5848 var keys = Object.keys(obj); 5849 for (var i = 0; i < keys.length; i++) { 5850 values.push(obj[keys[i]]); 5851 } 5852 return values; 5853 } 5854 5855 // avoid hasOwnProperty for performance 5856 for (var key in obj) 5857 values.push(obj[key]); 5858 return values; 5859 }; 5860 5861 /** 5862 * Gets a value from `base` relative to the `path` string. 5863 * @method get 5864 * @param {} obj The base object 5865 * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz' 5866 * @param {number} [begin] Path slice begin 5867 * @param {number} [end] Path slice end 5868 * @return {} The object at the given path 5869 */ 5870 Common.get = function(obj, path, begin, end) { 5871 path = path.split('.').slice(begin, end); 5872 5873 for (var i = 0; i < path.length; i += 1) { 5874 obj = obj[path[i]]; 5875 } 5876 5877 return obj; 5878 }; 5879 5880 /** 5881 * Sets a value on `base` relative to the given `path` string. 5882 * @method set 5883 * @param {} obj The base object 5884 * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz' 5885 * @param {} val The value to set 5886 * @param {number} [begin] Path slice begin 5887 * @param {number} [end] Path slice end 5888 * @return {} Pass through `val` for chaining 5889 */ 5890 Common.set = function(obj, path, val, begin, end) { 5891 var parts = path.split('.').slice(begin, end); 5892 Common.get(obj, path, 0, -1)[parts[parts.length - 1]] = val; 5893 return val; 5894 }; 5895 5896 /** 5897 * Shuffles the given array in-place. 5898 * The function uses a seeded random generator. 5899 * @method shuffle 5900 * @param {array} array 5901 * @return {array} array shuffled randomly 5902 */ 5903 Common.shuffle = function(array) { 5904 for (var i = array.length - 1; i > 0; i--) { 5905 var j = Math.floor(Common.random() * (i + 1)); 5906 var temp = array[i]; 5907 array[i] = array[j]; 5908 array[j] = temp; 5909 } 5910 return array; 5911 }; 5912 5913 /** 5914 * Randomly chooses a value from a list with equal probability. 5915 * The function uses a seeded random generator. 5916 * @method choose 5917 * @param {array} choices 5918 * @return {object} A random choice object from the array 5919 */ 5920 Common.choose = function(choices) { 5921 return choices[Math.floor(Common.random() * choices.length)]; 5922 }; 5923 5924 /** 5925 * Returns true if the object is a HTMLElement, otherwise false. 5926 * @method isElement 5927 * @param {object} obj 5928 * @return {boolean} True if the object is a HTMLElement, otherwise false 5929 */ 5930 Common.isElement = function(obj) { 5931 if (typeof HTMLElement !== 'undefined') { 5932 return obj instanceof HTMLElement; 5933 } 5934 5935 return !!(obj && obj.nodeType && obj.nodeName); 5936 }; 5937 5938 /** 5939 * Returns true if the object is an array. 5940 * @method isArray 5941 * @param {object} obj 5942 * @return {boolean} True if the object is an array, otherwise false 5943 */ 5944 Common.isArray = function(obj) { 5945 return Object.prototype.toString.call(obj) === '[object Array]'; 5946 }; 5947 5948 /** 5949 * Returns true if the object is a function. 5950 * @method isFunction 5951 * @param {object} obj 5952 * @return {boolean} True if the object is a function, otherwise false 5953 */ 5954 Common.isFunction = function(obj) { 5955 return typeof obj === "function"; 5956 }; 5957 5958 /** 5959 * Returns true if the object is a plain object. 5960 * @method isPlainObject 5961 * @param {object} obj 5962 * @return {boolean} True if the object is a plain object, otherwise false 5963 */ 5964 Common.isPlainObject = function(obj) { 5965 return typeof obj === 'object' && obj.constructor === Object; 5966 }; 5967 5968 /** 5969 * Returns true if the object is a string. 5970 * @method isString 5971 * @param {object} obj 5972 * @return {boolean} True if the object is a string, otherwise false 5973 */ 5974 Common.isString = function(obj) { 5975 return toString.call(obj) === '[object String]'; 5976 }; 5977 5978 /** 5979 * Returns the given value clamped between a minimum and maximum value. 5980 * @method clamp 5981 * @param {number} value 5982 * @param {number} min 5983 * @param {number} max 5984 * @return {number} The value clamped between min and max inclusive 5985 */ 5986 Common.clamp = function(value, min, max) { 5987 if (value < min) 5988 return min; 5989 if (value > max) 5990 return max; 5991 return value; 5992 }; 5993 5994 /** 5995 * Returns the sign of the given value. 5996 * @method sign 5997 * @param {number} value 5998 * @return {number} -1 if negative, +1 if 0 or positive 5999 */ 6000 Common.sign = function(value) { 6001 return value < 0 ? -1 : 1; 6002 }; 6003 6004 /** 6005 * Returns the current timestamp since the time origin (e.g. from page load). 6006 * The result is in milliseconds and will use high-resolution timing if available. 6007 * @method now 6008 * @return {number} the current timestamp in milliseconds 6009 */ 6010 Common.now = function() { 6011 if (typeof window !== 'undefined' && window.performance) { 6012 if (window.performance.now) { 6013 return window.performance.now(); 6014 } else if (window.performance.webkitNow) { 6015 return window.performance.webkitNow(); 6016 } 6017 } 6018 6019 if (Date.now) { 6020 return Date.now(); 6021 } 6022 6023 return (new Date()) - Common._nowStartTime; 6024 }; 6025 6026 /** 6027 * Returns a random value between a minimum and a maximum value inclusive. 6028 * The function uses a seeded random generator. 6029 * @method random 6030 * @param {number} min 6031 * @param {number} max 6032 * @return {number} A random number between min and max inclusive 6033 */ 6034 Common.random = function(min, max) { 6035 min = (typeof min !== "undefined") ? min : 0; 6036 max = (typeof max !== "undefined") ? max : 1; 6037 return min + _seededRandom() * (max - min); 6038 }; 6039 6040 var _seededRandom = function() { 6041 // https://en.wikipedia.org/wiki/Linear_congruential_generator 6042 Common._seed = (Common._seed * 9301 + 49297) % 233280; 6043 return Common._seed / 233280; 6044 }; 6045 6046 /** 6047 * Converts a CSS hex colour string into an integer. 6048 * @method colorToNumber 6049 * @param {string} colorString 6050 * @return {number} An integer representing the CSS hex string 6051 */ 6052 Common.colorToNumber = function(colorString) { 6053 colorString = colorString.replace('#',''); 6054 6055 if (colorString.length == 3) { 6056 colorString = colorString.charAt(0) + colorString.charAt(0) 6057 + colorString.charAt(1) + colorString.charAt(1) 6058 + colorString.charAt(2) + colorString.charAt(2); 6059 } 6060 6061 return parseInt(colorString, 16); 6062 }; 6063 6064 /** 6065 * The console logging level to use, where each level includes all levels above and excludes the levels below. 6066 * The default level is 'debug' which shows all console messages. 6067 * 6068 * Possible level values are: 6069 * - 0 = None 6070 * - 1 = Debug 6071 * - 2 = Info 6072 * - 3 = Warn 6073 * - 4 = Error 6074 * @static 6075 * @property logLevel 6076 * @type {Number} 6077 * @default 1 6078 */ 6079 Common.logLevel = 1; 6080 6081 /** 6082 * Shows a `console.log` message only if the current `Common.logLevel` allows it. 6083 * The message will be prefixed with 'matter-js' to make it easily identifiable. 6084 * @method log 6085 * @param ...objs {} The objects to log. 6086 */ 6087 Common.log = function() { 6088 if (console && Common.logLevel > 0 && Common.logLevel <= 3) { 6089 console.log.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments))); 6090 } 6091 }; 6092 6093 /** 6094 * Shows a `console.info` message only if the current `Common.logLevel` allows it. 6095 * The message will be prefixed with 'matter-js' to make it easily identifiable. 6096 * @method info 6097 * @param ...objs {} The objects to log. 6098 */ 6099 Common.info = function() { 6100 if (console && Common.logLevel > 0 && Common.logLevel <= 2) { 6101 console.info.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments))); 6102 } 6103 }; 6104 6105 /** 6106 * Shows a `console.warn` message only if the current `Common.logLevel` allows it. 6107 * The message will be prefixed with 'matter-js' to make it easily identifiable. 6108 * @method warn 6109 * @param ...objs {} The objects to log. 6110 */ 6111 Common.warn = function() { 6112 if (console && Common.logLevel > 0 && Common.logLevel <= 3) { 6113 console.warn.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments))); 6114 } 6115 }; 6116 6117 /** 6118 * Uses `Common.warn` to log the given message one time only. 6119 * @method warnOnce 6120 * @param ...objs {} The objects to log. 6121 */ 6122 Common.warnOnce = function() { 6123 var message = Array.prototype.slice.call(arguments).join(' '); 6124 6125 if (!Common._warnedOnce[message]) { 6126 Common.warn(message); 6127 Common._warnedOnce[message] = true; 6128 } 6129 }; 6130 6131 /** 6132 * Shows a deprecated console warning when the function on the given object is called. 6133 * The target function will be replaced with a new function that first shows the warning 6134 * and then calls the original function. 6135 * @method deprecated 6136 * @param {object} obj The object or module 6137 * @param {string} name The property name of the function on obj 6138 * @param {string} warning The one-time message to show if the function is called 6139 */ 6140 Common.deprecated = function(obj, prop, warning) { 6141 obj[prop] = Common.chain(function() { 6142 Common.warnOnce('ð deprecated ð ', warning); 6143 }, obj[prop]); 6144 }; 6145 6146 /** 6147 * Returns the next unique sequential ID. 6148 * @method nextId 6149 * @return {Number} Unique sequential ID 6150 */ 6151 Common.nextId = function() { 6152 return Common._nextId++; 6153 }; 6154 6155 /** 6156 * A cross browser compatible indexOf implementation. 6157 * @method indexOf 6158 * @param {array} haystack 6159 * @param {object} needle 6160 * @return {number} The position of needle in haystack, otherwise -1. 6161 */ 6162 Common.indexOf = function(haystack, needle) { 6163 if (haystack.indexOf) 6164 return haystack.indexOf(needle); 6165 6166 for (var i = 0; i < haystack.length; i++) { 6167 if (haystack[i] === needle) 6168 return i; 6169 } 6170 6171 return -1; 6172 }; 6173 6174 /** 6175 * A cross browser compatible array map implementation. 6176 * @method map 6177 * @param {array} list 6178 * @param {function} func 6179 * @return {array} Values from list transformed by func. 6180 */ 6181 Common.map = function(list, func) { 6182 if (list.map) { 6183 return list.map(func); 6184 } 6185 6186 var mapped = []; 6187 6188 for (var i = 0; i < list.length; i += 1) { 6189 mapped.push(func(list[i])); 6190 } 6191 6192 return mapped; 6193 }; 6194 6195 /** 6196 * Takes a directed graph and returns the partially ordered set of vertices in topological order. 6197 * Circular dependencies are allowed. 6198 * @method topologicalSort 6199 * @param {object} graph 6200 * @return {array} Partially ordered set of vertices in topological order. 6201 */ 6202 Common.topologicalSort = function(graph) { 6203 // https://github.com/mgechev/javascript-algorithms 6204 // Copyright (c) Minko Gechev (MIT license) 6205 // Modifications: tidy formatting and naming 6206 var result = [], 6207 visited = [], 6208 temp = []; 6209 6210 for (var node in graph) { 6211 if (!visited[node] && !temp[node]) { 6212 Common._topologicalSort(node, visited, temp, graph, result); 6213 } 6214 } 6215 6216 return result; 6217 }; 6218 6219 Common._topologicalSort = function(node, visited, temp, graph, result) { 6220 var neighbors = graph[node] || []; 6221 temp[node] = true; 6222 6223 for (var i = 0; i < neighbors.length; i += 1) { 6224 var neighbor = neighbors[i]; 6225 6226 if (temp[neighbor]) { 6227 // skip circular dependencies 6228 continue; 6229 } 6230 6231 if (!visited[neighbor]) { 6232 Common._topologicalSort(neighbor, visited, temp, graph, result); 6233 } 6234 } 6235 6236 temp[node] = false; 6237 visited[node] = true; 6238 6239 result.push(node); 6240 }; 6241 6242 /** 6243 * Takes _n_ functions as arguments and returns a new function that calls them in order. 6244 * The arguments applied when calling the new function will also be applied to every function passed. 6245 * The value of `this` refers to the last value returned in the chain that was not `undefined`. 6246 * Therefore if a passed function does not return a value, the previously returned value is maintained. 6247 * After all passed functions have been called the new function returns the last returned value (if any). 6248 * If any of the passed functions are a chain, then the chain will be flattened. 6249 * @method chain 6250 * @param ...funcs {function} The functions to chain. 6251 * @return {function} A new function that calls the passed functions in order. 6252 */ 6253 Common.chain = function() { 6254 var funcs = []; 6255 6256 for (var i = 0; i < arguments.length; i += 1) { 6257 var func = arguments[i]; 6258 6259 if (func._chained) { 6260 // flatten already chained functions 6261 funcs.push.apply(funcs, func._chained); 6262 } else { 6263 funcs.push(func); 6264 } 6265 } 6266 6267 var chain = function() { 6268 // https://github.com/GoogleChrome/devtools-docs/issues/53#issuecomment-51941358 6269 var lastResult, 6270 args = new Array(arguments.length); 6271 6272 for (var i = 0, l = arguments.length; i < l; i++) { 6273 args[i] = arguments[i]; 6274 } 6275 6276 for (i = 0; i < funcs.length; i += 1) { 6277 var result = funcs[i].apply(lastResult, args); 6278 6279 if (typeof result !== 'undefined') { 6280 lastResult = result; 6281 } 6282 } 6283 6284 return lastResult; 6285 }; 6286 6287 chain._chained = funcs; 6288 6289 return chain; 6290 }; 6291 6292 /** 6293 * Chains a function to excute before the original function on the given `path` relative to `base`. 6294 * See also docs for `Common.chain`. 6295 * @method chainPathBefore 6296 * @param {} base The base object 6297 * @param {string} path The path relative to `base` 6298 * @param {function} func The function to chain before the original 6299 * @return {function} The chained function that replaced the original 6300 */ 6301 Common.chainPathBefore = function(base, path, func) { 6302 return Common.set(base, path, Common.chain( 6303 func, 6304 Common.get(base, path) 6305 )); 6306 }; 6307 6308 /** 6309 * Chains a function to excute after the original function on the given `path` relative to `base`. 6310 * See also docs for `Common.chain`. 6311 * @method chainPathAfter 6312 * @param {} base The base object 6313 * @param {string} path The path relative to `base` 6314 * @param {function} func The function to chain after the original 6315 * @return {function} The chained function that replaced the original 6316 */ 6317 Common.chainPathAfter = function(base, path, func) { 6318 return Common.set(base, path, Common.chain( 6319 Common.get(base, path), 6320 func 6321 )); 6322 }; 6323 6324 /** 6325 * Provide the [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module to enable 6326 * concave vertex decomposition support when using `Bodies.fromVertices` e.g. `Common.setDecomp(require('poly-decomp'))`. 6327 * @method setDecomp 6328 * @param {} decomp The [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module. 6329 */ 6330 Common.setDecomp = function(decomp) { 6331 Common._decomp = decomp; 6332 }; 6333 6334 /** 6335 * Returns the [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module provided through `Common.setDecomp`, 6336 * otherwise returns the global `decomp` if set. 6337 * @method getDecomp 6338 * @return {} The [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module if provided. 6339 */ 6340 Common.getDecomp = function() { 6341 // get user provided decomp if set 6342 var decomp = Common._decomp; 6343 6344 try { 6345 // otherwise from window global 6346 if (!decomp && typeof window !== 'undefined') { 6347 decomp = window.decomp; 6348 } 6349 6350 // otherwise from node global 6351 if (!decomp && typeof global !== 'undefined') { 6352 decomp = global.decomp; 6353 } 6354 } catch (e) { 6355 // decomp not available 6356 decomp = null; 6357 } 6358 6359 return decomp; 6360 }; 6361})(); 6362 6363 6364/***/ }), 6365/* 1 */ 6366/***/ (function(module, exports) { 6367 6368/** 6369* The `Matter.Bounds` module contains methods for creating and manipulating axis-aligned bounding boxes (AABB). 6370* 6371* @class Bounds 6372*/ 6373 6374var Bounds = {}; 6375 6376module.exports = Bounds; 6377 6378(function() { 6379 6380 /** 6381 * Creates a new axis-aligned bounding box (AABB) for the given vertices. 6382 * @method create 6383 * @param {vertices} vertices 6384 * @return {bounds} A new bounds object 6385 */ 6386 Bounds.create = function(vertices) { 6387 var bounds = { 6388 min: { x: 0, y: 0 }, 6389 max: { x: 0, y: 0 } 6390 }; 6391 6392 if (vertices) 6393 Bounds.update(bounds, vertices); 6394 6395 return bounds; 6396 }; 6397 6398 /** 6399 * Updates bounds using the given vertices and extends the bounds given a velocity. 6400 * @method update 6401 * @param {bounds} bounds 6402 * @param {vertices} vertices 6403 * @param {vector} velocity 6404 */ 6405 Bounds.update = function(bounds, vertices, velocity) { 6406 bounds.min.x = Infinity; 6407 bounds.max.x = -Infinity; 6408 bounds.min.y = Infinity; 6409 bounds.max.y = -Infinity; 6410 6411 for (var i = 0; i < vertices.length; i++) { 6412 var vertex = vertices[i]; 6413 if (vertex.x > bounds.max.x) bounds.max.x = vertex.x; 6414 if (vertex.x < bounds.min.x) bounds.min.x = vertex.x; 6415 if (vertex.y > bounds.max.y) bounds.max.y = vertex.y; 6416 if (vertex.y < bounds.min.y) bounds.min.y = vertex.y; 6417 } 6418 6419 if (velocity) { 6420 if (velocity.x > 0) { 6421 bounds.max.x += velocity.x; 6422 } else { 6423 bounds.min.x += velocity.x; 6424 } 6425 6426 if (velocity.y > 0) { 6427 bounds.max.y += velocity.y; 6428 } else { 6429 bounds.min.y += velocity.y; 6430 } 6431 } 6432 }; 6433 6434 /** 6435 * Returns true if the bounds contains the given point. 6436 * @method contains 6437 * @param {bounds} bounds 6438 * @param {vector} point 6439 * @return {boolean} True if the bounds contain the point, otherwise false 6440 */ 6441 Bounds.contains = function(bounds, point) { 6442 return point.x >= bounds.min.x && point.x <= bounds.max.x 6443 && point.y >= bounds.min.y && point.y <= bounds.max.y; 6444 }; 6445 6446 /** 6447 * Returns true if the two bounds intersect. 6448 * @method overlaps 6449 * @param {bounds} boundsA 6450 * @param {bounds} boundsB 6451 * @return {boolean} True if the bounds overlap, otherwise false 6452 */ 6453 Bounds.overlaps = function(boundsA, boundsB) { 6454 return (boundsA.min.x <= boundsB.max.x && boundsA.max.x >= boundsB.min.x 6455 && boundsA.max.y >= boundsB.min.y && boundsA.min.y <= boundsB.max.y); 6456 }; 6457 6458 /** 6459 * Translates the bounds by the given vector. 6460 * @method translate 6461 * @param {bounds} bounds 6462 * @param {vector} vector 6463 */ 6464 Bounds.translate = function(bounds, vector) { 6465 bounds.min.x += vector.x; 6466 bounds.max.x += vector.x; 6467 bounds.min.y += vector.y; 6468 bounds.max.y += vector.y; 6469 }; 6470 6471 /** 6472 * Shifts the bounds to the given position. 6473 * @method shift 6474 * @param {bounds} bounds 6475 * @param {vector} position 6476 */ 6477 Bounds.shift = function(bounds, position) { 6478 var deltaX = bounds.max.x - bounds.min.x, 6479 deltaY = bounds.max.y - bounds.min.y; 6480 6481 bounds.min.x = position.x; 6482 bounds.max.x = position.x + deltaX; 6483 bounds.min.y = position.y; 6484 bounds.max.y = position.y + deltaY; 6485 }; 6486 6487})(); 6488 6489 6490/***/ }), 6491/* 2 */ 6492/***/ (function(module, exports) { 6493 6494/** 6495* The `Matter.Vector` module contains methods for creating and manipulating vectors. 6496* Vectors are the basis of all the geometry related operations in the engine. 6497* A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`. 6498* 6499* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 6500* 6501* @class Vector 6502*/ 6503 6504// TODO: consider params for reusing vector objects 6505 6506var Vector = {}; 6507 6508module.exports = Vector; 6509 6510(function() { 6511 6512 /** 6513 * Creates a new vector. 6514 * @method create 6515 * @param {number} x 6516 * @param {number} y 6517 * @return {vector} A new vector 6518 */ 6519 Vector.create = function(x, y) { 6520 return { x: x || 0, y: y || 0 }; 6521 }; 6522 6523 /** 6524 * Returns a new vector with `x` and `y` copied from the given `vector`. 6525 * @method clone 6526 * @param {vector} vector 6527 * @return {vector} A new cloned vector 6528 */ 6529 Vector.clone = function(vector) { 6530 return { x: vector.x, y: vector.y }; 6531 }; 6532 6533 /** 6534 * Returns the magnitude (length) of a vector. 6535 * @method magnitude 6536 * @param {vector} vector 6537 * @return {number} The magnitude of the vector 6538 */ 6539 Vector.magnitude = function(vector) { 6540 return Math.sqrt((vector.x * vector.x) + (vector.y * vector.y)); 6541 }; 6542 6543 /** 6544 * Returns the magnitude (length) of a vector (therefore saving a `sqrt` operation). 6545 * @method magnitudeSquared 6546 * @param {vector} vector 6547 * @return {number} The squared magnitude of the vector 6548 */ 6549 Vector.magnitudeSquared = function(vector) { 6550 return (vector.x * vector.x) + (vector.y * vector.y); 6551 }; 6552 6553 /** 6554 * Rotates the vector about (0, 0) by specified angle. 6555 * @method rotate 6556 * @param {vector} vector 6557 * @param {number} angle 6558 * @param {vector} [output] 6559 * @return {vector} The vector rotated about (0, 0) 6560 */ 6561 Vector.rotate = function(vector, angle, output) { 6562 var cos = Math.cos(angle), sin = Math.sin(angle); 6563 if (!output) output = {}; 6564 var x = vector.x * cos - vector.y * sin; 6565 output.y = vector.x * sin + vector.y * cos; 6566 output.x = x; 6567 return output; 6568 }; 6569 6570 /** 6571 * Rotates the vector about a specified point by specified angle. 6572 * @method rotateAbout 6573 * @param {vector} vector 6574 * @param {number} angle 6575 * @param {vector} point 6576 * @param {vector} [output] 6577 * @return {vector} A new vector rotated about the point 6578 */ 6579 Vector.rotateAbout = function(vector, angle, point, output) { 6580 var cos = Math.cos(angle), sin = Math.sin(angle); 6581 if (!output) output = {}; 6582 var x = point.x + ((vector.x - point.x) * cos - (vector.y - point.y) * sin); 6583 output.y = point.y + ((vector.x - point.x) * sin + (vector.y - point.y) * cos); 6584 output.x = x; 6585 return output; 6586 }; 6587 6588 /** 6589 * Normalises a vector (such that its magnitude is `1`). 6590 * @method normalise 6591 * @param {vector} vector 6592 * @return {vector} A new vector normalised 6593 */ 6594 Vector.normalise = function(vector) { 6595 var magnitude = Vector.magnitude(vector); 6596 if (magnitude === 0) 6597 return { x: 0, y: 0 }; 6598 return { x: vector.x / magnitude, y: vector.y / magnitude }; 6599 }; 6600 6601 /** 6602 * Returns the dot-product of two vectors. 6603 * @method dot 6604 * @param {vector} vectorA 6605 * @param {vector} vectorB 6606 * @return {number} The dot product of the two vectors 6607 */ 6608 Vector.dot = function(vectorA, vectorB) { 6609 return (vectorA.x * vectorB.x) + (vectorA.y * vectorB.y); 6610 }; 6611 6612 /** 6613 * Returns the cross-product of two vectors. 6614 * @method cross 6615 * @param {vector} vectorA 6616 * @param {vector} vectorB 6617 * @return {number} The cross product of the two vectors 6618 */ 6619 Vector.cross = function(vectorA, vectorB) { 6620 return (vectorA.x * vectorB.y) - (vectorA.y * vectorB.x); 6621 }; 6622 6623 /** 6624 * Returns the cross-product of three vectors. 6625 * @method cross3 6626 * @param {vector} vectorA 6627 * @param {vector} vectorB 6628 * @param {vector} vectorC 6629 * @return {number} The cross product of the three vectors 6630 */ 6631 Vector.cross3 = function(vectorA, vectorB, vectorC) { 6632 return (vectorB.x - vectorA.x) * (vectorC.y - vectorA.y) - (vectorB.y - vectorA.y) * (vectorC.x - vectorA.x); 6633 }; 6634 6635 /** 6636 * Adds the two vectors. 6637 * @method add 6638 * @param {vector} vectorA 6639 * @param {vector} vectorB 6640 * @param {vector} [output] 6641 * @return {vector} A new vector of vectorA and vectorB added 6642 */ 6643 Vector.add = function(vectorA, vectorB, output) { 6644 if (!output) output = {}; 6645 output.x = vectorA.x + vectorB.x; 6646 output.y = vectorA.y + vectorB.y; 6647 return output; 6648 }; 6649 6650 /** 6651 * Subtracts the two vectors. 6652 * @method sub 6653 * @param {vector} vectorA 6654 * @param {vector} vectorB 6655 * @param {vector} [output] 6656 * @return {vector} A new vector of vectorA and vectorB subtracted 6657 */ 6658 Vector.sub = function(vectorA, vectorB, output) { 6659 if (!output) output = {}; 6660 output.x = vectorA.x - vectorB.x; 6661 output.y = vectorA.y - vectorB.y; 6662 return output; 6663 }; 6664 6665 /** 6666 * Multiplies a vector and a scalar. 6667 * @method mult 6668 * @param {vector} vector 6669 * @param {number} scalar 6670 * @return {vector} A new vector multiplied by scalar 6671 */ 6672 Vector.mult = function(vector, scalar) { 6673 return { x: vector.x * scalar, y: vector.y * scalar }; 6674 }; 6675 6676 /** 6677 * Divides a vector and a scalar. 6678 * @method div 6679 * @param {vector} vector 6680 * @param {number} scalar 6681 * @return {vector} A new vector divided by scalar 6682 */ 6683 Vector.div = function(vector, scalar) { 6684 return { x: vector.x / scalar, y: vector.y / scalar }; 6685 }; 6686 6687 /** 6688 * Returns the perpendicular vector. Set `negate` to true for the perpendicular in the opposite direction. 6689 * @method perp 6690 * @param {vector} vector 6691 * @param {bool} [negate=false] 6692 * @return {vector} The perpendicular vector 6693 */ 6694 Vector.perp = function(vector, negate) { 6695 negate = negate === true ? -1 : 1; 6696 return { x: negate * -vector.y, y: negate * vector.x }; 6697 }; 6698 6699 /** 6700 * Negates both components of a vector such that it points in the opposite direction. 6701 * @method neg 6702 * @param {vector} vector 6703 * @return {vector} The negated vector 6704 */ 6705 Vector.neg = function(vector) { 6706 return { x: -vector.x, y: -vector.y }; 6707 }; 6708 6709 /** 6710 * Returns the angle between the vector `vectorB - vectorA` and the x-axis in radians. 6711 * @method angle 6712 * @param {vector} vectorA 6713 * @param {vector} vectorB 6714 * @return {number} The angle in radians 6715 */ 6716 Vector.angle = function(vectorA, vectorB) { 6717 return Math.atan2(vectorB.y - vectorA.y, vectorB.x - vectorA.x); 6718 }; 6719 6720 /** 6721 * Temporary vector pool (not thread-safe). 6722 * @property _temp 6723 * @type {vector[]} 6724 * @private 6725 */ 6726 Vector._temp = [ 6727 Vector.create(), Vector.create(), 6728 Vector.create(), Vector.create(), 6729 Vector.create(), Vector.create() 6730 ]; 6731 6732})(); 6733 6734/***/ }), 6735/* 3 */ 6736/***/ (function(module, exports, __webpack_require__) { 6737 6738/** 6739* The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices. 6740* A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`. 6741* A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull). 6742* 6743* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 6744* 6745* @class Vertices 6746*/ 6747 6748var Vertices = {}; 6749 6750module.exports = Vertices; 6751 6752var Vector = __webpack_require__(2); 6753var Common = __webpack_require__(0); 6754 6755(function() { 6756 6757 /** 6758 * Creates a new set of `Matter.Body` compatible vertices. 6759 * The `points` argument accepts an array of `Matter.Vector` points orientated around the origin `(0, 0)`, for example: 6760 * 6761 * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }] 6762 * 6763 * The `Vertices.create` method returns a new array of vertices, which are similar to Matter.Vector objects, 6764 * but with some additional references required for efficient collision detection routines. 6765 * 6766 * Vertices must be specified in clockwise order. 6767 * 6768 * Note that the `body` argument is not optional, a `Matter.Body` reference must be provided. 6769 * 6770 * @method create 6771 * @param {vector[]} points 6772 * @param {body} body 6773 */ 6774 Vertices.create = function(points, body) { 6775 var vertices = []; 6776 6777 for (var i = 0; i < points.length; i++) { 6778 var point = points[i], 6779 vertex = { 6780 x: point.x, 6781 y: point.y, 6782 index: i, 6783 body: body, 6784 isInternal: false 6785 }; 6786 6787 vertices.push(vertex); 6788 } 6789 6790 return vertices; 6791 }; 6792 6793 /** 6794 * Parses a string containing ordered x y pairs separated by spaces (and optionally commas), 6795 * into a `Matter.Vertices` object for the given `Matter.Body`. 6796 * For parsing SVG paths, see `Svg.pathToVertices`. 6797 * @method fromPath 6798 * @param {string} path 6799 * @param {body} body 6800 * @return {vertices} vertices 6801 */ 6802 Vertices.fromPath = function(path, body) { 6803 var pathPattern = /L?\s*([-\d.e]+)[\s,]*([-\d.e]+)*/ig, 6804 points = []; 6805 6806 path.replace(pathPattern, function(match, x, y) { 6807 points.push({ x: parseFloat(x), y: parseFloat(y) }); 6808 }); 6809 6810 return Vertices.create(points, body); 6811 }; 6812 6813 /** 6814 * Returns the centre (centroid) of the set of vertices. 6815 * @method centre 6816 * @param {vertices} vertices 6817 * @return {vector} The centre point 6818 */ 6819 Vertices.centre = function(vertices) { 6820 var area = Vertices.area(vertices, true), 6821 centre = { x: 0, y: 0 }, 6822 cross, 6823 temp, 6824 j; 6825 6826 for (var i = 0; i < vertices.length; i++) { 6827 j = (i + 1) % vertices.length; 6828 cross = Vector.cross(vertices[i], vertices[j]); 6829 temp = Vector.mult(Vector.add(vertices[i], vertices[j]), cross); 6830 centre = Vector.add(centre, temp); 6831 } 6832 6833 return Vector.div(centre, 6 * area); 6834 }; 6835 6836 /** 6837 * Returns the average (mean) of the set of vertices. 6838 * @method mean 6839 * @param {vertices} vertices 6840 * @return {vector} The average point 6841 */ 6842 Vertices.mean = function(vertices) { 6843 var average = { x: 0, y: 0 }; 6844 6845 for (var i = 0; i < vertices.length; i++) { 6846 average.x += vertices[i].x; 6847 average.y += vertices[i].y; 6848 } 6849 6850 return Vector.div(average, vertices.length); 6851 }; 6852 6853 /** 6854 * Returns the area of the set of vertices. 6855 * @method area 6856 * @param {vertices} vertices 6857 * @param {bool} signed 6858 * @return {number} The area 6859 */ 6860 Vertices.area = function(vertices, signed) { 6861 var area = 0, 6862 j = vertices.length - 1; 6863 6864 for (var i = 0; i < vertices.length; i++) { 6865 area += (vertices[j].x - vertices[i].x) * (vertices[j].y + vertices[i].y); 6866 j = i; 6867 } 6868 6869 if (signed) 6870 return area / 2; 6871 6872 return Math.abs(area) / 2; 6873 }; 6874 6875 /** 6876 * Returns the moment of inertia (second moment of area) of the set of vertices given the total mass. 6877 * @method inertia 6878 * @param {vertices} vertices 6879 * @param {number} mass 6880 * @return {number} The polygon's moment of inertia 6881 */ 6882 Vertices.inertia = function(vertices, mass) { 6883 var numerator = 0, 6884 denominator = 0, 6885 v = vertices, 6886 cross, 6887 j; 6888 6889 // find the polygon's moment of inertia, using second moment of area 6890 // from equations at http://www.physicsforums.com/showthread.php?t=25293 6891 for (var n = 0; n < v.length; n++) { 6892 j = (n + 1) % v.length; 6893 cross = Math.abs(Vector.cross(v[j], v[n])); 6894 numerator += cross * (Vector.dot(v[j], v[j]) + Vector.dot(v[j], v[n]) + Vector.dot(v[n], v[n])); 6895 denominator += cross; 6896 } 6897 6898 return (mass / 6) * (numerator / denominator); 6899 }; 6900 6901 /** 6902 * Translates the set of vertices in-place. 6903 * @method translate 6904 * @param {vertices} vertices 6905 * @param {vector} vector 6906 * @param {number} scalar 6907 */ 6908 Vertices.translate = function(vertices, vector, scalar) { 6909 scalar = typeof scalar !== 'undefined' ? scalar : 1; 6910 6911 var verticesLength = vertices.length, 6912 translateX = vector.x * scalar, 6913 translateY = vector.y * scalar, 6914 i; 6915 6916 for (i = 0; i < verticesLength; i++) { 6917 vertices[i].x += translateX; 6918 vertices[i].y += translateY; 6919 } 6920 6921 return vertices; 6922 }; 6923 6924 /** 6925 * Rotates the set of vertices in-place. 6926 * @method rotate 6927 * @param {vertices} vertices 6928 * @param {number} angle 6929 * @param {vector} point 6930 */ 6931 Vertices.rotate = function(vertices, angle, point) { 6932 if (angle === 0) 6933 return; 6934 6935 var cos = Math.cos(angle), 6936 sin = Math.sin(angle), 6937 pointX = point.x, 6938 pointY = point.y, 6939 verticesLength = vertices.length, 6940 vertex, 6941 dx, 6942 dy, 6943 i; 6944 6945 for (i = 0; i < verticesLength; i++) { 6946 vertex = vertices[i]; 6947 dx = vertex.x - pointX; 6948 dy = vertex.y - pointY; 6949 vertex.x = pointX + (dx * cos - dy * sin); 6950 vertex.y = pointY + (dx * sin + dy * cos); 6951 } 6952 6953 return vertices; 6954 }; 6955 6956 /** 6957 * Returns `true` if the `point` is inside the set of `vertices`. 6958 * @method contains 6959 * @param {vertices} vertices 6960 * @param {vector} point 6961 * @return {boolean} True if the vertices contains point, otherwise false 6962 */ 6963 Vertices.contains = function(vertices, point) { 6964 var pointX = point.x, 6965 pointY = point.y, 6966 verticesLength = vertices.length, 6967 vertex = vertices[verticesLength - 1], 6968 nextVertex; 6969 6970 for (var i = 0; i < verticesLength; i++) { 6971 nextVertex = vertices[i]; 6972 6973 if ((pointX - vertex.x) * (nextVertex.y - vertex.y) 6974 + (pointY - vertex.y) * (vertex.x - nextVertex.x) > 0) { 6975 return false; 6976 } 6977 6978 vertex = nextVertex; 6979 } 6980 6981 return true; 6982 }; 6983 6984 /** 6985 * Scales the vertices from a point (default is centre) in-place. 6986 * @method scale 6987 * @param {vertices} vertices 6988 * @param {number} scaleX 6989 * @param {number} scaleY 6990 * @param {vector} point 6991 */ 6992 Vertices.scale = function(vertices, scaleX, scaleY, point) { 6993 if (scaleX === 1 && scaleY === 1) 6994 return vertices; 6995 6996 point = point || Vertices.centre(vertices); 6997 6998 var vertex, 6999 delta; 7000 7001 for (var i = 0; i < vertices.length; i++) { 7002 vertex = vertices[i]; 7003 delta = Vector.sub(vertex, point); 7004 vertices[i].x = point.x + delta.x * scaleX; 7005 vertices[i].y = point.y + delta.y * scaleY; 7006 } 7007 7008 return vertices; 7009 }; 7010 7011 /** 7012 * Chamfers a set of vertices by giving them rounded corners, returns a new set of vertices. 7013 * The radius parameter is a single number or an array to specify the radius for each vertex. 7014 * @method chamfer 7015 * @param {vertices} vertices 7016 * @param {number[]} radius 7017 * @param {number} quality 7018 * @param {number} qualityMin 7019 * @param {number} qualityMax 7020 */ 7021 Vertices.chamfer = function(vertices, radius, quality, qualityMin, qualityMax) { 7022 if (typeof radius === 'number') { 7023 radius = [radius]; 7024 } else { 7025 radius = radius || [8]; 7026 } 7027 7028 // quality defaults to -1, which is auto 7029 quality = (typeof quality !== 'undefined') ? quality : -1; 7030 qualityMin = qualityMin || 2; 7031 qualityMax = qualityMax || 14; 7032 7033 var newVertices = []; 7034 7035 for (var i = 0; i < vertices.length; i++) { 7036 var prevVertex = vertices[i - 1 >= 0 ? i - 1 : vertices.length - 1], 7037 vertex = vertices[i], 7038 nextVertex = vertices[(i + 1) % vertices.length], 7039 currentRadius = radius[i < radius.length ? i : radius.length - 1]; 7040 7041 if (currentRadius === 0) { 7042 newVertices.push(vertex); 7043 continue; 7044 } 7045 7046 var prevNormal = Vector.normalise({ 7047 x: vertex.y - prevVertex.y, 7048 y: prevVertex.x - vertex.x 7049 }); 7050 7051 var nextNormal = Vector.normalise({ 7052 x: nextVertex.y - vertex.y, 7053 y: vertex.x - nextVertex.x 7054 }); 7055 7056 var diagonalRadius = Math.sqrt(2 * Math.pow(currentRadius, 2)), 7057 radiusVector = Vector.mult(Common.clone(prevNormal), currentRadius), 7058 midNormal = Vector.normalise(Vector.mult(Vector.add(prevNormal, nextNormal), 0.5)), 7059 scaledVertex = Vector.sub(vertex, Vector.mult(midNormal, diagonalRadius)); 7060 7061 var precision = quality; 7062 7063 if (quality === -1) { 7064 // automatically decide precision 7065 precision = Math.pow(currentRadius, 0.32) * 1.75; 7066 } 7067 7068 precision = Common.clamp(precision, qualityMin, qualityMax); 7069 7070 // use an even value for precision, more likely to reduce axes by using symmetry 7071 if (precision % 2 === 1) 7072 precision += 1; 7073 7074 var alpha = Math.acos(Vector.dot(prevNormal, nextNormal)), 7075 theta = alpha / precision; 7076 7077 for (var j = 0; j < precision; j++) { 7078 newVertices.push(Vector.add(Vector.rotate(radiusVector, theta * j), scaledVertex)); 7079 } 7080 } 7081 7082 return newVertices; 7083 }; 7084 7085 /** 7086 * Sorts the input vertices into clockwise order in place. 7087 * @method clockwiseSort 7088 * @param {vertices} vertices 7089 * @return {vertices} vertices 7090 */ 7091 Vertices.clockwiseSort = function(vertices) { 7092 var centre = Vertices.mean(vertices); 7093 7094 vertices.sort(function(vertexA, vertexB) { 7095 return Vector.angle(centre, vertexA) - Vector.angle(centre, vertexB); 7096 }); 7097 7098 return vertices; 7099 }; 7100 7101 /** 7102 * Returns true if the vertices form a convex shape (vertices must be in clockwise order). 7103 * @method isConvex 7104 * @param {vertices} vertices 7105 * @return {bool} `true` if the `vertices` are convex, `false` if not (or `null` if not computable). 7106 */ 7107 Vertices.isConvex = function(vertices) { 7108 // http://paulbourke.net/geometry/polygonmesh/ 7109 // Copyright (c) Paul Bourke (use permitted) 7110 7111 var flag = 0, 7112 n = vertices.length, 7113 i, 7114 j, 7115 k, 7116 z; 7117 7118 if (n < 3) 7119 return null; 7120 7121 for (i = 0; i < n; i++) { 7122 j = (i + 1) % n; 7123 k = (i + 2) % n; 7124 z = (vertices[j].x - vertices[i].x) * (vertices[k].y - vertices[j].y); 7125 z -= (vertices[j].y - vertices[i].y) * (vertices[k].x - vertices[j].x); 7126 7127 if (z < 0) { 7128 flag |= 1; 7129 } else if (z > 0) { 7130 flag |= 2; 7131 } 7132 7133 if (flag === 3) { 7134 return false; 7135 } 7136 } 7137 7138 if (flag !== 0){ 7139 return true; 7140 } else { 7141 return null; 7142 } 7143 }; 7144 7145 /** 7146 * Returns the convex hull of the input vertices as a new array of points. 7147 * @method hull 7148 * @param {vertices} vertices 7149 * @return [vertex] vertices 7150 */ 7151 Vertices.hull = function(vertices) { 7152 // http://geomalgorithms.com/a10-_hull-1.html 7153 7154 var upper = [], 7155 lower = [], 7156 vertex, 7157 i; 7158 7159 // sort vertices on x-axis (y-axis for ties) 7160 vertices = vertices.slice(0); 7161 vertices.sort(function(vertexA, vertexB) { 7162 var dx = vertexA.x - vertexB.x; 7163 return dx !== 0 ? dx : vertexA.y - vertexB.y; 7164 }); 7165 7166 // build lower hull 7167 for (i = 0; i < vertices.length; i += 1) { 7168 vertex = vertices[i]; 7169 7170 while (lower.length >= 2 7171 && Vector.cross3(lower[lower.length - 2], lower[lower.length - 1], vertex) <= 0) { 7172 lower.pop(); 7173 } 7174 7175 lower.push(vertex); 7176 } 7177 7178 // build upper hull 7179 for (i = vertices.length - 1; i >= 0; i -= 1) { 7180 vertex = vertices[i]; 7181 7182 while (upper.length >= 2 7183 && Vector.cross3(upper[upper.length - 2], upper[upper.length - 1], vertex) <= 0) { 7184 upper.pop(); 7185 } 7186 7187 upper.push(vertex); 7188 } 7189 7190 // concatenation of the lower and upper hulls gives the convex hull 7191 // omit last points because they are repeated at the beginning of the other list 7192 upper.pop(); 7193 lower.pop(); 7194 7195 return upper.concat(lower); 7196 }; 7197 7198})(); 7199 7200 7201/***/ }), 7202/* 4 */ 7203/***/ (function(module, exports, __webpack_require__) { 7204 7205/** 7206* The `Matter.Body` module contains methods for creating and manipulating rigid bodies. 7207* For creating bodies with common configurations such as rectangles, circles and other polygons see the module `Matter.Bodies`. 7208* 7209* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 7210 7211* @class Body 7212*/ 7213 7214var Body = {}; 7215 7216module.exports = Body; 7217 7218var Vertices = __webpack_require__(3); 7219var Vector = __webpack_require__(2); 7220var Sleeping = __webpack_require__(7); 7221var Common = __webpack_require__(0); 7222var Bounds = __webpack_require__(1); 7223var Axes = __webpack_require__(11); 7224 7225(function() { 7226 7227 Body._timeCorrection = true; 7228 Body._inertiaScale = 4; 7229 Body._nextCollidingGroupId = 1; 7230 Body._nextNonCollidingGroupId = -1; 7231 Body._nextCategory = 0x0001; 7232 Body._baseDelta = 1000 / 60; 7233 7234 /** 7235 * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults. 7236 * All properties have default values, and many are pre-calculated automatically based on other properties. 7237 * Vertices must be specified in clockwise order. 7238 * See the properties section below for detailed information on what you can pass via the `options` object. 7239 * @method create 7240 * @param {} options 7241 * @return {body} body 7242 */ 7243 Body.create = function(options) { 7244 var defaults = { 7245 id: Common.nextId(), 7246 type: 'body', 7247 label: 'Body', 7248 parts: [], 7249 plugin: {}, 7250 angle: 0, 7251 vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'), 7252 position: { x: 0, y: 0 }, 7253 force: { x: 0, y: 0 }, 7254 torque: 0, 7255 positionImpulse: { x: 0, y: 0 }, 7256 constraintImpulse: { x: 0, y: 0, angle: 0 }, 7257 totalContacts: 0, 7258 speed: 0, 7259 angularSpeed: 0, 7260 velocity: { x: 0, y: 0 }, 7261 angularVelocity: 0, 7262 isSensor: false, 7263 isStatic: false, 7264 isSleeping: false, 7265 motion: 0, 7266 sleepThreshold: 60, 7267 density: 0.001, 7268 restitution: 0, 7269 friction: 0.1, 7270 frictionStatic: 0.5, 7271 frictionAir: 0.01, 7272 collisionFilter: { 7273 category: 0x0001, 7274 mask: 0xFFFFFFFF, 7275 group: 0 7276 }, 7277 slop: 0.05, 7278 timeScale: 1, 7279 render: { 7280 visible: true, 7281 opacity: 1, 7282 strokeStyle: null, 7283 fillStyle: null, 7284 lineWidth: null, 7285 sprite: { 7286 xScale: 1, 7287 yScale: 1, 7288 xOffset: 0, 7289 yOffset: 0 7290 } 7291 }, 7292 events: null, 7293 bounds: null, 7294 chamfer: null, 7295 circleRadius: 0, 7296 positionPrev: null, 7297 anglePrev: 0, 7298 parent: null, 7299 axes: null, 7300 area: 0, 7301 mass: 0, 7302 inertia: 0, 7303 deltaTime: 1000 / 60, 7304 _original: null 7305 }; 7306 7307 var body = Common.extend(defaults, options); 7308 7309 _initProperties(body, options); 7310 7311 return body; 7312 }; 7313 7314 /** 7315 * Returns the next unique group index for which bodies will collide. 7316 * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide. 7317 * See `body.collisionFilter` for more information. 7318 * @method nextGroup 7319 * @param {bool} [isNonColliding=false] 7320 * @return {Number} Unique group index 7321 */ 7322 Body.nextGroup = function(isNonColliding) { 7323 if (isNonColliding) 7324 return Body._nextNonCollidingGroupId--; 7325 7326 return Body._nextCollidingGroupId++; 7327 }; 7328 7329 /** 7330 * Returns the next unique category bitfield (starting after the initial default category `0x0001`). 7331 * There are 32 available. See `body.collisionFilter` for more information. 7332 * @method nextCategory 7333 * @return {Number} Unique category bitfield 7334 */ 7335 Body.nextCategory = function() { 7336 Body._nextCategory = Body._nextCategory << 1; 7337 return Body._nextCategory; 7338 }; 7339 7340 /** 7341 * Initialises body properties. 7342 * @method _initProperties 7343 * @private 7344 * @param {body} body 7345 * @param {} [options] 7346 */ 7347 var _initProperties = function(body, options) { 7348 options = options || {}; 7349 7350 // init required properties (order is important) 7351 Body.set(body, { 7352 bounds: body.bounds || Bounds.create(body.vertices), 7353 positionPrev: body.positionPrev || Vector.clone(body.position), 7354 anglePrev: body.anglePrev || body.angle, 7355 vertices: body.vertices, 7356 parts: body.parts || [body], 7357 isStatic: body.isStatic, 7358 isSleeping: body.isSleeping, 7359 parent: body.parent || body 7360 }); 7361 7362 Vertices.rotate(body.vertices, body.angle, body.position); 7363 Axes.rotate(body.axes, body.angle); 7364 Bounds.update(body.bounds, body.vertices, body.velocity); 7365 7366 // allow options to override the automatically calculated properties 7367 Body.set(body, { 7368 axes: options.axes || body.axes, 7369 area: options.area || body.area, 7370 mass: options.mass || body.mass, 7371 inertia: options.inertia || body.inertia 7372 }); 7373 7374 // render properties 7375 var defaultFillStyle = (body.isStatic ? '#14151f' : Common.choose(['#f19648', '#f5d259', '#f55a3c', '#063e7b', '#ececd1'])), 7376 defaultStrokeStyle = body.isStatic ? '#555' : '#ccc', 7377 defaultLineWidth = body.isStatic && body.render.fillStyle === null ? 1 : 0; 7378 body.render.fillStyle = body.render.fillStyle || defaultFillStyle; 7379 body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle; 7380 body.render.lineWidth = body.render.lineWidth || defaultLineWidth; 7381 body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x); 7382 body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y); 7383 }; 7384 7385 /** 7386 * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist. 7387 * Prefer to use the actual setter functions in performance critical situations. 7388 * @method set 7389 * @param {body} body 7390 * @param {} settings A property name (or map of properties and values) to set on the body. 7391 * @param {} value The value to set if `settings` is a single property name. 7392 */ 7393 Body.set = function(body, settings, value) { 7394 var property; 7395 7396 if (typeof settings === 'string') { 7397 property = settings; 7398 settings = {}; 7399 settings[property] = value; 7400 } 7401 7402 for (property in settings) { 7403 if (!Object.prototype.hasOwnProperty.call(settings, property)) 7404 continue; 7405 7406 value = settings[property]; 7407 switch (property) { 7408 7409 case 'isStatic': 7410 Body.setStatic(body, value); 7411 break; 7412 case 'isSleeping': 7413 Sleeping.set(body, value); 7414 break; 7415 case 'mass': 7416 Body.setMass(body, value); 7417 break; 7418 case 'density': 7419 Body.setDensity(body, value); 7420 break; 7421 case 'inertia': 7422 Body.setInertia(body, value); 7423 break; 7424 case 'vertices': 7425 Body.setVertices(body, value); 7426 break; 7427 case 'position': 7428 Body.setPosition(body, value); 7429 break; 7430 case 'angle': 7431 Body.setAngle(body, value); 7432 break; 7433 case 'velocity': 7434 Body.setVelocity(body, value); 7435 break; 7436 case 'angularVelocity': 7437 Body.setAngularVelocity(body, value); 7438 break; 7439 case 'speed': 7440 Body.setSpeed(body, value); 7441 break; 7442 case 'angularSpeed': 7443 Body.setAngularSpeed(body, value); 7444 break; 7445 case 'parts': 7446 Body.setParts(body, value); 7447 break; 7448 case 'centre': 7449 Body.setCentre(body, value); 7450 break; 7451 default: 7452 body[property] = value; 7453 7454 } 7455 } 7456 }; 7457 7458 /** 7459 * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity. 7460 * @method setStatic 7461 * @param {body} body 7462 * @param {bool} isStatic 7463 */ 7464 Body.setStatic = function(body, isStatic) { 7465 for (var i = 0; i < body.parts.length; i++) { 7466 var part = body.parts[i]; 7467 7468 if (isStatic) { 7469 if (!part.isStatic) { 7470 part._original = { 7471 restitution: part.restitution, 7472 friction: part.friction, 7473 mass: part.mass, 7474 inertia: part.inertia, 7475 density: part.density, 7476 inverseMass: part.inverseMass, 7477 inverseInertia: part.inverseInertia 7478 }; 7479 } 7480 7481 part.restitution = 0; 7482 part.friction = 1; 7483 part.mass = part.inertia = part.density = Infinity; 7484 part.inverseMass = part.inverseInertia = 0; 7485 7486 part.positionPrev.x = part.position.x; 7487 part.positionPrev.y = part.position.y; 7488 part.anglePrev = part.angle; 7489 part.angularVelocity = 0; 7490 part.speed = 0; 7491 part.angularSpeed = 0; 7492 part.motion = 0; 7493 } else if (part._original) { 7494 part.restitution = part._original.restitution; 7495 part.friction = part._original.friction; 7496 part.mass = part._original.mass; 7497 part.inertia = part._original.inertia; 7498 part.density = part._original.density; 7499 part.inverseMass = part._original.inverseMass; 7500 part.inverseInertia = part._original.inverseInertia; 7501 7502 part._original = null; 7503 } 7504 7505 part.isStatic = isStatic; 7506 } 7507 }; 7508 7509 /** 7510 * Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change. 7511 * @method setMass 7512 * @param {body} body 7513 * @param {number} mass 7514 */ 7515 Body.setMass = function(body, mass) { 7516 var moment = body.inertia / (body.mass / 6); 7517 body.inertia = moment * (mass / 6); 7518 body.inverseInertia = 1 / body.inertia; 7519 7520 body.mass = mass; 7521 body.inverseMass = 1 / body.mass; 7522 body.density = body.mass / body.area; 7523 }; 7524 7525 /** 7526 * Sets the density of the body. Mass and inertia are automatically updated to reflect the change. 7527 * @method setDensity 7528 * @param {body} body 7529 * @param {number} density 7530 */ 7531 Body.setDensity = function(body, density) { 7532 Body.setMass(body, density * body.area); 7533 body.density = density; 7534 }; 7535 7536 /** 7537 * Sets the moment of inertia of the body. This is the second moment of area in two dimensions. 7538 * Inverse inertia is automatically updated to reflect the change. Mass is not changed. 7539 * @method setInertia 7540 * @param {body} body 7541 * @param {number} inertia 7542 */ 7543 Body.setInertia = function(body, inertia) { 7544 body.inertia = inertia; 7545 body.inverseInertia = 1 / body.inertia; 7546 }; 7547 7548 /** 7549 * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`). 7550 * Vertices will be automatically transformed to be orientated around their centre of mass as the origin. 7551 * They are then automatically translated to world space based on `body.position`. 7552 * 7553 * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array). 7554 * Vertices must form a convex hull. Concave vertices must be decomposed into convex parts. 7555 * 7556 * @method setVertices 7557 * @param {body} body 7558 * @param {vector[]} vertices 7559 */ 7560 Body.setVertices = function(body, vertices) { 7561 // change vertices 7562 if (vertices[0].body === body) { 7563 body.vertices = vertices; 7564 } else { 7565 body.vertices = Vertices.create(vertices, body); 7566 } 7567 7568 // update properties 7569 body.axes = Axes.fromVertices(body.vertices); 7570 body.area = Vertices.area(body.vertices); 7571 Body.setMass(body, body.density * body.area); 7572 7573 // orient vertices around the centre of mass at origin (0, 0) 7574 var centre = Vertices.centre(body.vertices); 7575 Vertices.translate(body.vertices, centre, -1); 7576 7577 // update inertia while vertices are at origin (0, 0) 7578 Body.setInertia(body, Body._inertiaScale * Vertices.inertia(body.vertices, body.mass)); 7579 7580 // update geometry 7581 Vertices.translate(body.vertices, body.position); 7582 Bounds.update(body.bounds, body.vertices, body.velocity); 7583 }; 7584 7585 /** 7586 * Sets the parts of the `body`. 7587 * 7588 * See `body.parts` for details and requirements on how parts are used. 7589 * 7590 * See Bodies.fromVertices for a related utility. 7591 * 7592 * This function updates `body` mass, inertia and centroid based on the parts geometry. 7593 * Sets each `part.parent` to be this `body`. 7594 * 7595 * The convex hull is computed and set on this `body` (unless `autoHull` is `false`). 7596 * Automatically ensures that the first part in `body.parts` is the `body`. 7597 * @method setParts 7598 * @param {body} body 7599 * @param {body[]} parts 7600 * @param {bool} [autoHull=true] 7601 */ 7602 Body.setParts = function(body, parts, autoHull) { 7603 var i; 7604 7605 // add all the parts, ensuring that the first part is always the parent body 7606 parts = parts.slice(0); 7607 body.parts.length = 0; 7608 body.parts.push(body); 7609 body.parent = body; 7610 7611 for (i = 0; i < parts.length; i++) { 7612 var part = parts[i]; 7613 if (part !== body) { 7614 part.parent = body; 7615 body.parts.push(part); 7616 } 7617 } 7618 7619 if (body.parts.length === 1) 7620 return; 7621 7622 autoHull = typeof autoHull !== 'undefined' ? autoHull : true; 7623 7624 // find the convex hull of all parts to set on the parent body 7625 if (autoHull) { 7626 var vertices = []; 7627 for (i = 0; i < parts.length; i++) { 7628 vertices = vertices.concat(parts[i].vertices); 7629 } 7630 7631 Vertices.clockwiseSort(vertices); 7632 7633 var hull = Vertices.hull(vertices), 7634 hullCentre = Vertices.centre(hull); 7635 7636 Body.setVertices(body, hull); 7637 Vertices.translate(body.vertices, hullCentre); 7638 } 7639 7640 // sum the properties of all compound parts of the parent body 7641 var total = Body._totalProperties(body); 7642 7643 body.area = total.area; 7644 body.parent = body; 7645 body.position.x = total.centre.x; 7646 body.position.y = total.centre.y; 7647 body.positionPrev.x = total.centre.x; 7648 body.positionPrev.y = total.centre.y; 7649 7650 Body.setMass(body, total.mass); 7651 Body.setInertia(body, total.inertia); 7652 Body.setPosition(body, total.centre); 7653 }; 7654 7655 /** 7656 * Set the centre of mass of the body. 7657 * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation. 7658 * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density. 7659 * This is equal to moving `body.position` but not the `body.vertices`. 7660 * Invalid if the `centre` falls outside the body's convex hull. 7661 * @method setCentre 7662 * @param {body} body 7663 * @param {vector} centre 7664 * @param {bool} relative 7665 */ 7666 Body.setCentre = function(body, centre, relative) { 7667 if (!relative) { 7668 body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x); 7669 body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y); 7670 body.position.x = centre.x; 7671 body.position.y = centre.y; 7672 } else { 7673 body.positionPrev.x += centre.x; 7674 body.positionPrev.y += centre.y; 7675 body.position.x += centre.x; 7676 body.position.y += centre.y; 7677 } 7678 }; 7679 7680 /** 7681 * Sets the position of the body. By default velocity is unchanged. 7682 * If `updateVelocity` is `true` then velocity is inferred from the change in position. 7683 * @method setPosition 7684 * @param {body} body 7685 * @param {vector} position 7686 * @param {boolean} [updateVelocity=false] 7687 */ 7688 Body.setPosition = function(body, position, updateVelocity) { 7689 var delta = Vector.sub(position, body.position); 7690 7691 if (updateVelocity) { 7692 body.positionPrev.x = body.position.x; 7693 body.positionPrev.y = body.position.y; 7694 body.velocity.x = delta.x; 7695 body.velocity.y = delta.y; 7696 body.speed = Vector.magnitude(delta); 7697 } else { 7698 body.positionPrev.x += delta.x; 7699 body.positionPrev.y += delta.y; 7700 } 7701 7702 for (var i = 0; i < body.parts.length; i++) { 7703 var part = body.parts[i]; 7704 part.position.x += delta.x; 7705 part.position.y += delta.y; 7706 Vertices.translate(part.vertices, delta); 7707 Bounds.update(part.bounds, part.vertices, body.velocity); 7708 } 7709 }; 7710 7711 /** 7712 * Sets the angle of the body. By default angular velocity is unchanged. 7713 * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle. 7714 * @method setAngle 7715 * @param {body} body 7716 * @param {number} angle 7717 * @param {boolean} [updateVelocity=false] 7718 */ 7719 Body.setAngle = function(body, angle, updateVelocity) { 7720 var delta = angle - body.angle; 7721 7722 if (updateVelocity) { 7723 body.anglePrev = body.angle; 7724 body.angularVelocity = delta; 7725 body.angularSpeed = Math.abs(delta); 7726 } else { 7727 body.anglePrev += delta; 7728 } 7729 7730 for (var i = 0; i < body.parts.length; i++) { 7731 var part = body.parts[i]; 7732 part.angle += delta; 7733 Vertices.rotate(part.vertices, delta, body.position); 7734 Axes.rotate(part.axes, delta); 7735 Bounds.update(part.bounds, part.vertices, body.velocity); 7736 if (i > 0) { 7737 Vector.rotateAbout(part.position, delta, body.position, part.position); 7738 } 7739 } 7740 }; 7741 7742 /** 7743 * Sets the current linear velocity of the body. 7744 * Affects body speed. 7745 * @method setVelocity 7746 * @param {body} body 7747 * @param {vector} velocity 7748 */ 7749 Body.setVelocity = function(body, velocity) { 7750 var timeScale = body.deltaTime / Body._baseDelta; 7751 body.positionPrev.x = body.position.x - velocity.x * timeScale; 7752 body.positionPrev.y = body.position.y - velocity.y * timeScale; 7753 body.velocity.x = (body.position.x - body.positionPrev.x) / timeScale; 7754 body.velocity.y = (body.position.y - body.positionPrev.y) / timeScale; 7755 body.speed = Vector.magnitude(body.velocity); 7756 }; 7757 7758 /** 7759 * Gets the current linear velocity of the body. 7760 * @method getVelocity 7761 * @param {body} body 7762 * @return {vector} velocity 7763 */ 7764 Body.getVelocity = function(body) { 7765 var timeScale = Body._baseDelta / body.deltaTime; 7766 7767 return { 7768 x: (body.position.x - body.positionPrev.x) * timeScale, 7769 y: (body.position.y - body.positionPrev.y) * timeScale 7770 }; 7771 }; 7772 7773 /** 7774 * Gets the current linear speed of the body. 7775 * Equivalent to the magnitude of its velocity. 7776 * @method getSpeed 7777 * @param {body} body 7778 * @return {number} speed 7779 */ 7780 Body.getSpeed = function(body) { 7781 return Vector.magnitude(Body.getVelocity(body)); 7782 }; 7783 7784 /** 7785 * Sets the current linear speed of the body. 7786 * Direction is maintained. Affects body velocity. 7787 * @method setSpeed 7788 * @param {body} body 7789 * @param {number} speed 7790 */ 7791 Body.setSpeed = function(body, speed) { 7792 Body.setVelocity(body, Vector.mult(Vector.normalise(Body.getVelocity(body)), speed)); 7793 }; 7794 7795 /** 7796 * Sets the current rotational velocity of the body. 7797 * Affects body angular speed. 7798 * @method setAngularVelocity 7799 * @param {body} body 7800 * @param {number} velocity 7801 */ 7802 Body.setAngularVelocity = function(body, velocity) { 7803 var timeScale = body.deltaTime / Body._baseDelta; 7804 body.anglePrev = body.angle - velocity * timeScale; 7805 body.angularVelocity = (body.angle - body.anglePrev) / timeScale; 7806 body.angularSpeed = Math.abs(body.angularVelocity); 7807 }; 7808 7809 /** 7810 * Gets the current rotational velocity of the body. 7811 * @method getAngularVelocity 7812 * @param {body} body 7813 * @return {number} angular velocity 7814 */ 7815 Body.getAngularVelocity = function(body) { 7816 return (body.angle - body.anglePrev) * Body._baseDelta / body.deltaTime; 7817 }; 7818 7819 /** 7820 * Gets the current rotational speed of the body. 7821 * Equivalent to the magnitude of its angular velocity. 7822 * @method getAngularSpeed 7823 * @param {body} body 7824 * @return {number} angular speed 7825 */ 7826 Body.getAngularSpeed = function(body) { 7827 return Math.abs(Body.getAngularVelocity(body)); 7828 }; 7829 7830 /** 7831 * Sets the current rotational speed of the body. 7832 * Direction is maintained. Affects body angular velocity. 7833 * @method setAngularSpeed 7834 * @param {body} body 7835 * @param {number} speed 7836 */ 7837 Body.setAngularSpeed = function(body, speed) { 7838 Body.setAngularVelocity(body, Common.sign(Body.getAngularVelocity(body)) * speed); 7839 }; 7840 7841 /** 7842 * Moves a body by a given vector relative to its current position. By default velocity is unchanged. 7843 * If `updateVelocity` is `true` then velocity is inferred from the change in position. 7844 * @method translate 7845 * @param {body} body 7846 * @param {vector} translation 7847 * @param {boolean} [updateVelocity=false] 7848 */ 7849 Body.translate = function(body, translation, updateVelocity) { 7850 Body.setPosition(body, Vector.add(body.position, translation), updateVelocity); 7851 }; 7852 7853 /** 7854 * Rotates a body by a given angle relative to its current angle. By default angular velocity is unchanged. 7855 * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle. 7856 * @method rotate 7857 * @param {body} body 7858 * @param {number} rotation 7859 * @param {vector} [point] 7860 * @param {boolean} [updateVelocity=false] 7861 */ 7862 Body.rotate = function(body, rotation, point, updateVelocity) { 7863 if (!point) { 7864 Body.setAngle(body, body.angle + rotation, updateVelocity); 7865 } else { 7866 var cos = Math.cos(rotation), 7867 sin = Math.sin(rotation), 7868 dx = body.position.x - point.x, 7869 dy = body.position.y - point.y; 7870 7871 Body.setPosition(body, { 7872 x: point.x + (dx * cos - dy * sin), 7873 y: point.y + (dx * sin + dy * cos) 7874 }, updateVelocity); 7875 7876 Body.setAngle(body, body.angle + rotation, updateVelocity); 7877 } 7878 }; 7879 7880 /** 7881 * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre). 7882 * @method scale 7883 * @param {body} body 7884 * @param {number} scaleX 7885 * @param {number} scaleY 7886 * @param {vector} [point] 7887 */ 7888 Body.scale = function(body, scaleX, scaleY, point) { 7889 var totalArea = 0, 7890 totalInertia = 0; 7891 7892 point = point || body.position; 7893 7894 for (var i = 0; i < body.parts.length; i++) { 7895 var part = body.parts[i]; 7896 7897 // scale vertices 7898 Vertices.scale(part.vertices, scaleX, scaleY, point); 7899 7900 // update properties 7901 part.axes = Axes.fromVertices(part.vertices); 7902 part.area = Vertices.area(part.vertices); 7903 Body.setMass(part, body.density * part.area); 7904 7905 // update inertia (requires vertices to be at origin) 7906 Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y }); 7907 Body.setInertia(part, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass)); 7908 Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y }); 7909 7910 if (i > 0) { 7911 totalArea += part.area; 7912 totalInertia += part.inertia; 7913 } 7914 7915 // scale position 7916 part.position.x = point.x + (part.position.x - point.x) * scaleX; 7917 part.position.y = point.y + (part.position.y - point.y) * scaleY; 7918 7919 // update bounds 7920 Bounds.update(part.bounds, part.vertices, body.velocity); 7921 } 7922 7923 // handle parent body 7924 if (body.parts.length > 1) { 7925 body.area = totalArea; 7926 7927 if (!body.isStatic) { 7928 Body.setMass(body, body.density * totalArea); 7929 Body.setInertia(body, totalInertia); 7930 } 7931 } 7932 7933 // handle circles 7934 if (body.circleRadius) { 7935 if (scaleX === scaleY) { 7936 body.circleRadius *= scaleX; 7937 } else { 7938 // body is no longer a circle 7939 body.circleRadius = null; 7940 } 7941 } 7942 }; 7943 7944 /** 7945 * Performs an update by integrating the equations of motion on the `body`. 7946 * This is applied every update by `Matter.Engine` automatically. 7947 * @method update 7948 * @param {body} body 7949 * @param {number} [deltaTime=16.666] 7950 */ 7951 Body.update = function(body, deltaTime) { 7952 deltaTime = (typeof deltaTime !== 'undefined' ? deltaTime : (1000 / 60)) * body.timeScale; 7953 7954 var deltaTimeSquared = deltaTime * deltaTime, 7955 correction = Body._timeCorrection ? deltaTime / (body.deltaTime || deltaTime) : 1; 7956 7957 // from the previous step 7958 var frictionAir = 1 - body.frictionAir * (deltaTime / Common._baseDelta), 7959 velocityPrevX = (body.position.x - body.positionPrev.x) * correction, 7960 velocityPrevY = (body.position.y - body.positionPrev.y) * correction; 7961 7962 // update velocity with Verlet integration 7963 body.velocity.x = (velocityPrevX * frictionAir) + (body.force.x / body.mass) * deltaTimeSquared; 7964 body.velocity.y = (velocityPrevY * frictionAir) + (body.force.y / body.mass) * deltaTimeSquared; 7965 7966 body.positionPrev.x = body.position.x; 7967 body.positionPrev.y = body.position.y; 7968 body.position.x += body.velocity.x; 7969 body.position.y += body.velocity.y; 7970 body.deltaTime = deltaTime; 7971 7972 // update angular velocity with Verlet integration 7973 body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared; 7974 body.anglePrev = body.angle; 7975 body.angle += body.angularVelocity; 7976 7977 // transform the body geometry 7978 for (var i = 0; i < body.parts.length; i++) { 7979 var part = body.parts[i]; 7980 7981 Vertices.translate(part.vertices, body.velocity); 7982 7983 if (i > 0) { 7984 part.position.x += body.velocity.x; 7985 part.position.y += body.velocity.y; 7986 } 7987 7988 if (body.angularVelocity !== 0) { 7989 Vertices.rotate(part.vertices, body.angularVelocity, body.position); 7990 Axes.rotate(part.axes, body.angularVelocity); 7991 if (i > 0) { 7992 Vector.rotateAbout(part.position, body.angularVelocity, body.position, part.position); 7993 } 7994 } 7995 7996 Bounds.update(part.bounds, part.vertices, body.velocity); 7997 } 7998 }; 7999 8000 /** 8001 * Updates properties `body.velocity`, `body.speed`, `body.angularVelocity` and `body.angularSpeed` which are normalised in relation to `Body._baseDelta`. 8002 * @method updateVelocities 8003 * @param {body} body 8004 */ 8005 Body.updateVelocities = function(body) { 8006 var timeScale = Body._baseDelta / body.deltaTime, 8007 bodyVelocity = body.velocity; 8008 8009 bodyVelocity.x = (body.position.x - body.positionPrev.x) * timeScale; 8010 bodyVelocity.y = (body.position.y - body.positionPrev.y) * timeScale; 8011 body.speed = Math.sqrt((bodyVelocity.x * bodyVelocity.x) + (bodyVelocity.y * bodyVelocity.y)); 8012 8013 body.angularVelocity = (body.angle - body.anglePrev) * timeScale; 8014 body.angularSpeed = Math.abs(body.angularVelocity); 8015 }; 8016 8017 /** 8018 * Applies the `force` to the `body` from the force origin `position` in world-space, over a single timestep, including applying any resulting angular torque. 8019 * 8020 * Forces are useful for effects like gravity, wind or rocket thrust, but can be difficult in practice when precise control is needed. In these cases see `Body.setVelocity` and `Body.setPosition` as an alternative. 8021 * 8022 * The force from this function is only applied once for the duration of a single timestep, in other words the duration depends directly on the current engine update `delta` and the rate of calls to this function. 8023 * 8024 * Therefore to account for time, you should apply the force constantly over as many engine updates as equivalent to the intended duration. 8025 * 8026 * If all or part of the force duration is some fraction of a timestep, first multiply the force by `duration / timestep`. 8027 * 8028 * The force origin `position` in world-space must also be specified. Passing `body.position` will result in zero angular effect as the force origin would be at the centre of mass. 8029 * 8030 * The `body` will take time to accelerate under a force, the resulting effect depends on duration of the force, the body mass and other forces on the body including friction combined. 8031 * @method applyForce 8032 * @param {body} body 8033 * @param {vector} position The force origin in world-space. Pass `body.position` to avoid angular torque. 8034 * @param {vector} force 8035 */ 8036 Body.applyForce = function(body, position, force) { 8037 var offset = { x: position.x - body.position.x, y: position.y - body.position.y }; 8038 body.force.x += force.x; 8039 body.force.y += force.y; 8040 body.torque += offset.x * force.y - offset.y * force.x; 8041 }; 8042 8043 /** 8044 * Returns the sums of the properties of all compound parts of the parent body. 8045 * @method _totalProperties 8046 * @private 8047 * @param {body} body 8048 * @return {} 8049 */ 8050 Body._totalProperties = function(body) { 8051 // from equations at: 8052 // https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory 8053 // http://output.to/sideway/default.asp?qno=121100087 8054 8055 var properties = { 8056 mass: 0, 8057 area: 0, 8058 inertia: 0, 8059 centre: { x: 0, y: 0 } 8060 }; 8061 8062 // sum the properties of all compound parts of the parent body 8063 for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) { 8064 var part = body.parts[i], 8065 mass = part.mass !== Infinity ? part.mass : 1; 8066 8067 properties.mass += mass; 8068 properties.area += part.area; 8069 properties.inertia += part.inertia; 8070 properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass)); 8071 } 8072 8073 properties.centre = Vector.div(properties.centre, properties.mass); 8074 8075 return properties; 8076 }; 8077 8078 /* 8079 * 8080 * Events Documentation 8081 * 8082 */ 8083 8084 /** 8085 * Fired when a body starts sleeping (where `this` is the body). 8086 * 8087 * @event sleepStart 8088 * @this {body} The body that has started sleeping 8089 * @param {} event An event object 8090 * @param {} event.source The source object of the event 8091 * @param {} event.name The name of the event 8092 */ 8093 8094 /** 8095 * Fired when a body ends sleeping (where `this` is the body). 8096 * 8097 * @event sleepEnd 8098 * @this {body} The body that has ended sleeping 8099 * @param {} event An event object 8100 * @param {} event.source The source object of the event 8101 * @param {} event.name The name of the event 8102 */ 8103 8104 /* 8105 * 8106 * Properties Documentation 8107 * 8108 */ 8109 8110 /** 8111 * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`. 8112 * 8113 * @property id 8114 * @type number 8115 */ 8116 8117 /** 8118 * _Read only_. Set by `Body.create`. 8119 * 8120 * A `String` denoting the type of object. 8121 * 8122 * @readOnly 8123 * @property type 8124 * @type string 8125 * @default "body" 8126 */ 8127 8128 /** 8129 * An arbitrary `String` name to help the user identify and manage bodies. 8130 * 8131 * @property label 8132 * @type string 8133 * @default "Body" 8134 */ 8135 8136 /** 8137 * _Read only_. Use `Body.setParts` to set. 8138 * 8139 * See `Bodies.fromVertices` for a related utility. 8140 * 8141 * An array of bodies (the 'parts') that make up this body (the 'parent'). The first body in this array must always be a self-reference to this `body`. 8142 * 8143 * The parts are fixed together and therefore perform as a single unified rigid body. 8144 * 8145 * Parts in relation to each other are allowed to overlap, as well as form gaps or holes, so can be used to create complex concave bodies unlike when using a single part. 8146 * 8147 * Use properties and functions on the parent `body` rather than on parts. 8148 * 8149 * Outside of their geometry, most properties on parts are not considered or updated. 8150 * As such 'per-part' material properties among others are not currently considered. 8151 * 8152 * Parts should be created specifically for their parent body. 8153 * Parts should not be shared or reused between bodies, only one parent is supported. 8154 * Parts should not have their own parts, they are not handled recursively. 8155 * Parts should not be added to the world directly or any other composite. 8156 * Parts own vertices must be convex and in clockwise order. 8157 * 8158 * A body with more than one part is sometimes referred to as a 'compound' body. 8159 * 8160 * Use `Body.setParts` when setting parts to ensure correct updates of all properties. 8161 * 8162 * @readOnly 8163 * @property parts 8164 * @type body[] 8165 */ 8166 8167 /** 8168 * An object reserved for storing plugin-specific properties. 8169 * 8170 * @property plugin 8171 * @type {} 8172 */ 8173 8174 /** 8175 * _Read only_. Updated by `Body.setParts`. 8176 * 8177 * A reference to the body that this is a part of. See `body.parts`. 8178 * This is a self reference if the body is not a part of another body. 8179 * 8180 * @readOnly 8181 * @property parent 8182 * @type body 8183 */ 8184 8185 /** 8186 * A `Number` specifying the angle of the body, in radians. 8187 * 8188 * @property angle 8189 * @type number 8190 * @default 0 8191 */ 8192 8193 /** 8194 * _Read only_. Use `Body.setVertices` or `Body.setParts` to set. See also `Bodies.fromVertices`. 8195 * 8196 * An array of `Vector` objects that specify the convex hull of the rigid body. 8197 * These should be provided about the origin `(0, 0)`. E.g. 8198 * 8199 * `[{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]` 8200 * 8201 * Vertices must always be convex, in clockwise order and must not contain any duplicate points. 8202 * 8203 * Concave vertices should be decomposed into convex `parts`, see `Bodies.fromVertices` and `Body.setParts`. 8204 * 8205 * When set the vertices are translated such that `body.position` is at the centre of mass. 8206 * Many other body properties are automatically calculated from these vertices when set including `density`, `area` and `inertia`. 8207 * 8208 * The module `Matter.Vertices` contains useful methods for working with vertices. 8209 * 8210 * @readOnly 8211 * @property vertices 8212 * @type vector[] 8213 */ 8214 8215 /** 8216 * _Read only_. Use `Body.setPosition` to set. 8217 * 8218 * A `Vector` that specifies the current world-space position of the body. 8219 * 8220 * @readOnly 8221 * @property position 8222 * @type vector 8223 * @default { x: 0, y: 0 } 8224 */ 8225 8226 /** 8227 * A `Vector` that accumulates the total force applied to the body for a single update. 8228 * Force is zeroed after every `Engine.update`, so constant forces should be applied for every update they are needed. See also `Body.applyForce`. 8229 * 8230 * @property force 8231 * @type vector 8232 * @default { x: 0, y: 0 } 8233 */ 8234 8235 /** 8236 * A `Number` that accumulates the total torque (turning force) applied to the body for a single update. See also `Body.applyForce`. 8237 * Torque is zeroed after every `Engine.update`, so constant torques should be applied for every update they are needed. 8238 * 8239 * Torques result in angular acceleration on every update, which depends on body inertia and the engine update delta. 8240 * 8241 * @property torque 8242 * @type number 8243 * @default 0 8244 */ 8245 8246 /** 8247 * _Read only_. Use `Body.setSpeed` to set. 8248 * 8249 * See `Body.getSpeed` for details. 8250 * 8251 * Equivalent to the magnitude of `body.velocity` (always positive). 8252 * 8253 * @readOnly 8254 * @property speed 8255 * @type number 8256 * @default 0 8257 */ 8258 8259 /** 8260 * _Read only_. Use `Body.setVelocity` to set. 8261 * 8262 * See `Body.getVelocity` for details. 8263 * 8264 * Equivalent to the magnitude of `body.angularVelocity` (always positive). 8265 * 8266 * @readOnly 8267 * @property velocity 8268 * @type vector 8269 * @default { x: 0, y: 0 } 8270 */ 8271 8272 /** 8273 * _Read only_. Use `Body.setAngularSpeed` to set. 8274 * 8275 * See `Body.getAngularSpeed` for details. 8276 * 8277 * 8278 * @readOnly 8279 * @property angularSpeed 8280 * @type number 8281 * @default 0 8282 */ 8283 8284 /** 8285 * _Read only_. Use `Body.setAngularVelocity` to set. 8286 * 8287 * See `Body.getAngularVelocity` for details. 8288 * 8289 * 8290 * @readOnly 8291 * @property angularVelocity 8292 * @type number 8293 * @default 0 8294 */ 8295 8296 /** 8297 * _Read only_. Use `Body.setStatic` to set. 8298 * 8299 * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed. 8300 * 8301 * @readOnly 8302 * @property isStatic 8303 * @type boolean 8304 * @default false 8305 */ 8306 8307 /** 8308 * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically. 8309 * 8310 * @property isSensor 8311 * @type boolean 8312 * @default false 8313 */ 8314 8315 /** 8316 * _Read only_. Use `Sleeping.set` to set. 8317 * 8318 * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken. 8319 * 8320 * @readOnly 8321 * @property isSleeping 8322 * @type boolean 8323 * @default false 8324 */ 8325 8326 /** 8327 * _Read only_. Calculated during engine update only when sleeping is enabled. 8328 * 8329 * A `Number` that loosely measures the amount of movement a body currently has. 8330 * 8331 * Derived from `body.speed^2 + body.angularSpeed^2`. See `Sleeping.update`. 8332 * 8333 * @readOnly 8334 * @property motion 8335 * @type number 8336 * @default 0 8337 */ 8338 8339 /** 8340 * A `Number` that defines the length of time during which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine). 8341 * 8342 * @property sleepThreshold 8343 * @type number 8344 * @default 60 8345 */ 8346 8347 /** 8348 * _Read only_. Use `Body.setDensity` to set. 8349 * 8350 * A `Number` that defines the density of the body (mass per unit area). 8351 * 8352 * Mass will also be updated when set. 8353 * 8354 * @readOnly 8355 * @property density 8356 * @type number 8357 * @default 0.001 8358 */ 8359 8360 /** 8361 * _Read only_. Use `Body.setMass` to set. 8362 * 8363 * A `Number` that defines the mass of the body. 8364 * 8365 * Density will also be updated when set. 8366 * 8367 * @readOnly 8368 * @property mass 8369 * @type number 8370 */ 8371 8372 /** 8373 * _Read only_. Use `Body.setMass` to set. 8374 * 8375 * A `Number` that defines the inverse mass of the body (`1 / mass`). 8376 * 8377 * @readOnly 8378 * @property inverseMass 8379 * @type number 8380 */ 8381 8382 /** 8383 * _Read only_. Automatically calculated when vertices, mass or density are set or set through `Body.setInertia`. 8384 * 8385 * A `Number` that defines the moment of inertia of the body. This is the second moment of area in two dimensions. 8386 * 8387 * Can be manually set to `Infinity` to prevent rotation of the body. See `Body.setInertia`. 8388 * 8389 * @readOnly 8390 * @property inertia 8391 * @type number 8392 */ 8393 8394 /** 8395 * _Read only_. Automatically calculated when vertices, mass or density are set or calculated by `Body.setInertia`. 8396 * 8397 * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`). 8398 * 8399 * @readOnly 8400 * @property inverseInertia 8401 * @type number 8402 */ 8403 8404 /** 8405 * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`. 8406 * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur. 8407 * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy. 8408 * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula: 8409 * 8410 * `Math.max(bodyA.restitution, bodyB.restitution)` 8411 * 8412 * @property restitution 8413 * @type number 8414 * @default 0 8415 */ 8416 8417 /** 8418 * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`. 8419 * A value of `0` means that the body may slide indefinitely. 8420 * A value of `1` means the body may come to a stop almost instantly after a force is applied. 8421 * 8422 * The effects of the value may be non-linear. 8423 * High values may be unstable depending on the body. 8424 * The engine uses a Coulomb friction model including static and kinetic friction. 8425 * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula: 8426 * 8427 * `Math.min(bodyA.friction, bodyB.friction)` 8428 * 8429 * @property friction 8430 * @type number 8431 * @default 0.1 8432 */ 8433 8434 /** 8435 * A `Number` that defines the static friction of the body (in the Coulomb friction model). 8436 * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used. 8437 * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary. 8438 * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction. 8439 * 8440 * @property frictionStatic 8441 * @type number 8442 * @default 0.5 8443 */ 8444 8445 /** 8446 * A `Number` that defines the air friction of the body (air resistance). 8447 * A value of `0` means the body will never slow as it moves through space. 8448 * The higher the value, the faster a body slows when moving through space. 8449 * The effects of the value are non-linear. 8450 * 8451 * @property frictionAir 8452 * @type number 8453 * @default 0.01 8454 */ 8455 8456 /** 8457 * An `Object` that specifies the collision filtering properties of this body. 8458 * 8459 * Collisions between two bodies will obey the following rules: 8460 * - If the two bodies have the same non-zero value of `collisionFilter.group`, 8461 * they will always collide if the value is positive, and they will never collide 8462 * if the value is negative. 8463 * - If the two bodies have different values of `collisionFilter.group` or if one 8464 * (or both) of the bodies has a value of 0, then the category/mask rules apply as follows: 8465 * 8466 * Each body belongs to a collision category, given by `collisionFilter.category`. This 8467 * value is used as a bit field and the category should have only one bit set, meaning that 8468 * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32 8469 * different collision categories available. 8470 * 8471 * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies 8472 * the categories it collides with (the value is the bitwise AND value of all these categories). 8473 * 8474 * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's 8475 * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0` 8476 * are both true. 8477 * 8478 * @property collisionFilter 8479 * @type object 8480 */ 8481 8482 /** 8483 * An Integer `Number`, that specifies the collision group this body belongs to. 8484 * See `body.collisionFilter` for more information. 8485 * 8486 * @property collisionFilter.group 8487 * @type object 8488 * @default 0 8489 */ 8490 8491 /** 8492 * A bit field that specifies the collision category this body belongs to. 8493 * The category value should have only one bit set, for example `0x0001`. 8494 * This means there are up to 32 unique collision categories available. 8495 * See `body.collisionFilter` for more information. 8496 * 8497 * @property collisionFilter.category 8498 * @type object 8499 * @default 1 8500 */ 8501 8502 /** 8503 * A bit mask that specifies the collision categories this body may collide with. 8504 * See `body.collisionFilter` for more information. 8505 * 8506 * @property collisionFilter.mask 8507 * @type object 8508 * @default -1 8509 */ 8510 8511 /** 8512 * A `Number` that specifies a thin boundary around the body where it is allowed to slightly sink into other bodies. 8513 * 8514 * This is required for proper collision response, including friction and restitution effects. 8515 * 8516 * The default should generally suffice in most cases. You may need to decrease this value for very small bodies that are nearing the default value in scale. 8517 * 8518 * @property slop 8519 * @type number 8520 * @default 0.05 8521 */ 8522 8523 /** 8524 * A `Number` that specifies per-body time scaling. 8525 * 8526 * @property timeScale 8527 * @type number 8528 * @default 1 8529 */ 8530 8531 /** 8532 * _Read only_. Updated during engine update. 8533 * 8534 * A `Number` that records the last delta time value used to update this body. 8535 * Used to calculate speed and velocity. 8536 * 8537 * @readOnly 8538 * @property deltaTime 8539 * @type number 8540 * @default 1000 / 60 8541 */ 8542 8543 /** 8544 * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. 8545 * 8546 * @property render 8547 * @type object 8548 */ 8549 8550 /** 8551 * A flag that indicates if the body should be rendered. 8552 * 8553 * @property render.visible 8554 * @type boolean 8555 * @default true 8556 */ 8557 8558 /** 8559 * Sets the opacity to use when rendering. 8560 * 8561 * @property render.opacity 8562 * @type number 8563 * @default 1 8564 */ 8565 8566 /** 8567 * An `Object` that defines the sprite properties to use when rendering, if any. 8568 * 8569 * @property render.sprite 8570 * @type object 8571 */ 8572 8573 /** 8574 * An `String` that defines the path to the image to use as the sprite texture, if any. 8575 * 8576 * @property render.sprite.texture 8577 * @type string 8578 */ 8579 8580 /** 8581 * A `Number` that defines the scaling in the x-axis for the sprite, if any. 8582 * 8583 * @property render.sprite.xScale 8584 * @type number 8585 * @default 1 8586 */ 8587 8588 /** 8589 * A `Number` that defines the scaling in the y-axis for the sprite, if any. 8590 * 8591 * @property render.sprite.yScale 8592 * @type number 8593 * @default 1 8594 */ 8595 8596 /** 8597 * A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width). 8598 * 8599 * @property render.sprite.xOffset 8600 * @type number 8601 * @default 0 8602 */ 8603 8604 /** 8605 * A `Number` that defines the offset in the y-axis for the sprite (normalised by texture height). 8606 * 8607 * @property render.sprite.yOffset 8608 * @type number 8609 * @default 0 8610 */ 8611 8612 /** 8613 * A `Number` that defines the line width to use when rendering the body outline (if a sprite is not defined). 8614 * A value of `0` means no outline will be rendered. 8615 * 8616 * @property render.lineWidth 8617 * @type number 8618 * @default 0 8619 */ 8620 8621 /** 8622 * A `String` that defines the fill style to use when rendering the body (if a sprite is not defined). 8623 * It is the same as when using a canvas, so it accepts CSS style property values. 8624 * 8625 * @property render.fillStyle 8626 * @type string 8627 * @default a random colour 8628 */ 8629 8630 /** 8631 * A `String` that defines the stroke style to use when rendering the body outline (if a sprite is not defined). 8632 * It is the same as when using a canvas, so it accepts CSS style property values. 8633 * 8634 * @property render.strokeStyle 8635 * @type string 8636 * @default a random colour 8637 */ 8638 8639 /** 8640 * _Read only_. Calculated automatically when vertices are set. 8641 * 8642 * An array of unique axis vectors (edge normals) used for collision detection. 8643 * These are automatically calculated when vertices are set. 8644 * They are constantly updated by `Body.update` during the simulation. 8645 * 8646 * @readOnly 8647 * @property axes 8648 * @type vector[] 8649 */ 8650 8651 /** 8652 * _Read only_. Calculated automatically when vertices are set. 8653 * 8654 * A `Number` that measures the area of the body's convex hull. 8655 * 8656 * @readOnly 8657 * @property area 8658 * @type string 8659 * @default 8660 */ 8661 8662 /** 8663 * A `Bounds` object that defines the AABB region for the body. 8664 * It is automatically calculated when vertices are set and constantly updated by `Body.update` during simulation. 8665 * 8666 * @property bounds 8667 * @type bounds 8668 */ 8669 8670 /** 8671 * Temporarily may hold parameters to be passed to `Vertices.chamfer` where supported by external functions. 8672 * 8673 * See `Vertices.chamfer` for possible parameters this object may hold. 8674 * 8675 * Currently only functions inside `Matter.Bodies` provide a utility using this property as a vertices pre-processing option. 8676 * 8677 * Alternatively consider using `Vertices.chamfer` directly on vertices before passing them to a body creation function. 8678 * 8679 * @property chamfer 8680 * @type object|null|undefined 8681 */ 8682 8683})(); 8684 8685 8686/***/ }), 8687/* 5 */ 8688/***/ (function(module, exports, __webpack_require__) { 8689 8690/** 8691* The `Matter.Events` module contains methods to fire and listen to events on other objects. 8692* 8693* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 8694* 8695* @class Events 8696*/ 8697 8698var Events = {}; 8699 8700module.exports = Events; 8701 8702var Common = __webpack_require__(0); 8703 8704(function() { 8705 8706 /** 8707 * Subscribes a callback function to the given object's `eventName`. 8708 * @method on 8709 * @param {} object 8710 * @param {string} eventNames 8711 * @param {function} callback 8712 */ 8713 Events.on = function(object, eventNames, callback) { 8714 var names = eventNames.split(' '), 8715 name; 8716 8717 for (var i = 0; i < names.length; i++) { 8718 name = names[i]; 8719 object.events = object.events || {}; 8720 object.events[name] = object.events[name] || []; 8721 object.events[name].push(callback); 8722 } 8723 8724 return callback; 8725 }; 8726 8727 /** 8728 * Removes the given event callback. If no callback, clears all callbacks in `eventNames`. If no `eventNames`, clears all events. 8729 * @method off 8730 * @param {} object 8731 * @param {string} eventNames 8732 * @param {function} callback 8733 */ 8734 Events.off = function(object, eventNames, callback) { 8735 if (!eventNames) { 8736 object.events = {}; 8737 return; 8738 } 8739 8740 // handle Events.off(object, callback) 8741 if (typeof eventNames === 'function') { 8742 callback = eventNames; 8743 eventNames = Common.keys(object.events).join(' '); 8744 } 8745 8746 var names = eventNames.split(' '); 8747 8748 for (var i = 0; i < names.length; i++) { 8749 var callbacks = object.events[names[i]], 8750 newCallbacks = []; 8751 8752 if (callback && callbacks) { 8753 for (var j = 0; j < callbacks.length; j++) { 8754 if (callbacks[j] !== callback) 8755 newCallbacks.push(callbacks[j]); 8756 } 8757 } 8758 8759 object.events[names[i]] = newCallbacks; 8760 } 8761 }; 8762 8763 /** 8764 * Fires all the callbacks subscribed to the given object's `eventName`, in the order they subscribed, if any. 8765 * @method trigger 8766 * @param {} object 8767 * @param {string} eventNames 8768 * @param {} event 8769 */ 8770 Events.trigger = function(object, eventNames, event) { 8771 var names, 8772 name, 8773 callbacks, 8774 eventClone; 8775 8776 var events = object.events; 8777 8778 if (events && Common.keys(events).length > 0) { 8779 if (!event) 8780 event = {}; 8781 8782 names = eventNames.split(' '); 8783 8784 for (var i = 0; i < names.length; i++) { 8785 name = names[i]; 8786 callbacks = events[name]; 8787 8788 if (callbacks) { 8789 eventClone = Common.clone(event, false); 8790 eventClone.name = name; 8791 eventClone.source = object; 8792 8793 for (var j = 0; j < callbacks.length; j++) { 8794 callbacks[j].apply(object, [eventClone]); 8795 } 8796 } 8797 } 8798 } 8799 }; 8800 8801})(); 8802 8803 8804/***/ }), 8805/* 6 */ 8806/***/ (function(module, exports, __webpack_require__) { 8807 8808/** 8809* A composite is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite` objects. 8810* 8811* They are a container that can represent complex objects made of multiple parts, even if they are not physically connected. 8812* A composite could contain anything from a single body all the way up to a whole world. 8813* 8814* When making any changes to composites, use the included functions rather than changing their properties directly. 8815* 8816* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 8817* 8818* @class Composite 8819*/ 8820 8821var Composite = {}; 8822 8823module.exports = Composite; 8824 8825var Events = __webpack_require__(5); 8826var Common = __webpack_require__(0); 8827var Bounds = __webpack_require__(1); 8828var Body = __webpack_require__(4); 8829 8830(function() { 8831 8832 /** 8833 * Creates a new composite. The options parameter is an object that specifies any properties you wish to override the defaults. 8834 * See the properites section below for detailed information on what you can pass via the `options` object. 8835 * @method create 8836 * @param {} [options] 8837 * @return {composite} A new composite 8838 */ 8839 Composite.create = function(options) { 8840 return Common.extend({ 8841 id: Common.nextId(), 8842 type: 'composite', 8843 parent: null, 8844 isModified: false, 8845 bodies: [], 8846 constraints: [], 8847 composites: [], 8848 label: 'Composite', 8849 plugin: {}, 8850 cache: { 8851 allBodies: null, 8852 allConstraints: null, 8853 allComposites: null 8854 } 8855 }, options); 8856 }; 8857 8858 /** 8859 * Sets the composite's `isModified` flag. 8860 * If `updateParents` is true, all parents will be set (default: false). 8861 * If `updateChildren` is true, all children will be set (default: false). 8862 * @private 8863 * @method setModified 8864 * @param {composite} composite 8865 * @param {boolean} isModified 8866 * @param {boolean} [updateParents=false] 8867 * @param {boolean} [updateChildren=false] 8868 */ 8869 Composite.setModified = function(composite, isModified, updateParents, updateChildren) { 8870 composite.isModified = isModified; 8871 8872 if (isModified && composite.cache) { 8873 composite.cache.allBodies = null; 8874 composite.cache.allConstraints = null; 8875 composite.cache.allComposites = null; 8876 } 8877 8878 if (updateParents && composite.parent) { 8879 Composite.setModified(composite.parent, isModified, updateParents, updateChildren); 8880 } 8881 8882 if (updateChildren) { 8883 for (var i = 0; i < composite.composites.length; i++) { 8884 var childComposite = composite.composites[i]; 8885 Composite.setModified(childComposite, isModified, updateParents, updateChildren); 8886 } 8887 } 8888 }; 8889 8890 /** 8891 * Generic single or multi-add function. Adds a single or an array of body(s), constraint(s) or composite(s) to the given composite. 8892 * Triggers `beforeAdd` and `afterAdd` events on the `composite`. 8893 * @method add 8894 * @param {composite} composite 8895 * @param {object|array} object A single or an array of body(s), constraint(s) or composite(s) 8896 * @return {composite} The original composite with the objects added 8897 */ 8898 Composite.add = function(composite, object) { 8899 var objects = [].concat(object); 8900 8901 Events.trigger(composite, 'beforeAdd', { object: object }); 8902 8903 for (var i = 0; i < objects.length; i++) { 8904 var obj = objects[i]; 8905 8906 switch (obj.type) { 8907 8908 case 'body': 8909 // skip adding compound parts 8910 if (obj.parent !== obj) { 8911 Common.warn('Composite.add: skipped adding a compound body part (you must add its parent instead)'); 8912 break; 8913 } 8914 8915 Composite.addBody(composite, obj); 8916 break; 8917 case 'constraint': 8918 Composite.addConstraint(composite, obj); 8919 break; 8920 case 'composite': 8921 Composite.addComposite(composite, obj); 8922 break; 8923 case 'mouseConstraint': 8924 Composite.addConstraint(composite, obj.constraint); 8925 break; 8926 8927 } 8928 } 8929 8930 Events.trigger(composite, 'afterAdd', { object: object }); 8931 8932 return composite; 8933 }; 8934 8935 /** 8936 * Generic remove function. Removes one or many body(s), constraint(s) or a composite(s) to the given composite. 8937 * Optionally searching its children recursively. 8938 * Triggers `beforeRemove` and `afterRemove` events on the `composite`. 8939 * @method remove 8940 * @param {composite} composite 8941 * @param {object|array} object 8942 * @param {boolean} [deep=false] 8943 * @return {composite} The original composite with the objects removed 8944 */ 8945 Composite.remove = function(composite, object, deep) { 8946 var objects = [].concat(object); 8947 8948 Events.trigger(composite, 'beforeRemove', { object: object }); 8949 8950 for (var i = 0; i < objects.length; i++) { 8951 var obj = objects[i]; 8952 8953 switch (obj.type) { 8954 8955 case 'body': 8956 Composite.removeBody(composite, obj, deep); 8957 break; 8958 case 'constraint': 8959 Composite.removeConstraint(composite, obj, deep); 8960 break; 8961 case 'composite': 8962 Composite.removeComposite(composite, obj, deep); 8963 break; 8964 case 'mouseConstraint': 8965 Composite.removeConstraint(composite, obj.constraint); 8966 break; 8967 8968 } 8969 } 8970 8971 Events.trigger(composite, 'afterRemove', { object: object }); 8972 8973 return composite; 8974 }; 8975 8976 /** 8977 * Adds a composite to the given composite. 8978 * @private 8979 * @method addComposite 8980 * @param {composite} compositeA 8981 * @param {composite} compositeB 8982 * @return {composite} The original compositeA with the objects from compositeB added 8983 */ 8984 Composite.addComposite = function(compositeA, compositeB) { 8985 compositeA.composites.push(compositeB); 8986 compositeB.parent = compositeA; 8987 Composite.setModified(compositeA, true, true, false); 8988 return compositeA; 8989 }; 8990 8991 /** 8992 * Removes a composite from the given composite, and optionally searching its children recursively. 8993 * @private 8994 * @method removeComposite 8995 * @param {composite} compositeA 8996 * @param {composite} compositeB 8997 * @param {boolean} [deep=false] 8998 * @return {composite} The original compositeA with the composite removed 8999 */ 9000 Composite.removeComposite = function(compositeA, compositeB, deep) { 9001 var position = Common.indexOf(compositeA.composites, compositeB); 9002 9003 if (position !== -1) { 9004 var bodies = Composite.allBodies(compositeB); 9005 9006 Composite.removeCompositeAt(compositeA, position); 9007 9008 for (var i = 0; i < bodies.length; i++) { 9009 bodies[i].sleepCounter = 0; 9010 } 9011 } 9012 9013 if (deep) { 9014 for (var i = 0; i < compositeA.composites.length; i++){ 9015 Composite.removeComposite(compositeA.composites[i], compositeB, true); 9016 } 9017 } 9018 9019 return compositeA; 9020 }; 9021 9022 /** 9023 * Removes a composite from the given composite. 9024 * @private 9025 * @method removeCompositeAt 9026 * @param {composite} composite 9027 * @param {number} position 9028 * @return {composite} The original composite with the composite removed 9029 */ 9030 Composite.removeCompositeAt = function(composite, position) { 9031 composite.composites.splice(position, 1); 9032 Composite.setModified(composite, true, true, false); 9033 return composite; 9034 }; 9035 9036 /** 9037 * Adds a body to the given composite. 9038 * @private 9039 * @method addBody 9040 * @param {composite} composite 9041 * @param {body} body 9042 * @return {composite} The original composite with the body added 9043 */ 9044 Composite.addBody = function(composite, body) { 9045 composite.bodies.push(body); 9046 Composite.setModified(composite, true, true, false); 9047 return composite; 9048 }; 9049 9050 /** 9051 * Removes a body from the given composite, and optionally searching its children recursively. 9052 * @private 9053 * @method removeBody 9054 * @param {composite} composite 9055 * @param {body} body 9056 * @param {boolean} [deep=false] 9057 * @return {composite} The original composite with the body removed 9058 */ 9059 Composite.removeBody = function(composite, body, deep) { 9060 var position = Common.indexOf(composite.bodies, body); 9061 9062 if (position !== -1) { 9063 Composite.removeBodyAt(composite, position); 9064 body.sleepCounter = 0; 9065 } 9066 9067 if (deep) { 9068 for (var i = 0; i < composite.composites.length; i++){ 9069 Composite.removeBody(composite.composites[i], body, true); 9070 } 9071 } 9072 9073 return composite; 9074 }; 9075 9076 /** 9077 * Removes a body from the given composite. 9078 * @private 9079 * @method removeBodyAt 9080 * @param {composite} composite 9081 * @param {number} position 9082 * @return {composite} The original composite with the body removed 9083 */ 9084 Composite.removeBodyAt = function(composite, position) { 9085 composite.bodies.splice(position, 1); 9086 Composite.setModified(composite, true, true, false); 9087 return composite; 9088 }; 9089 9090 /** 9091 * Adds a constraint to the given composite. 9092 * @private 9093 * @method addConstraint 9094 * @param {composite} composite 9095 * @param {constraint} constraint 9096 * @return {composite} The original composite with the constraint added 9097 */ 9098 Composite.addConstraint = function(composite, constraint) { 9099 composite.constraints.push(constraint); 9100 Composite.setModified(composite, true, true, false); 9101 return composite; 9102 }; 9103 9104 /** 9105 * Removes a constraint from the given composite, and optionally searching its children recursively. 9106 * @private 9107 * @method removeConstraint 9108 * @param {composite} composite 9109 * @param {constraint} constraint 9110 * @param {boolean} [deep=false] 9111 * @return {composite} The original composite with the constraint removed 9112 */ 9113 Composite.removeConstraint = function(composite, constraint, deep) { 9114 var position = Common.indexOf(composite.constraints, constraint); 9115 9116 if (position !== -1) { 9117 Composite.removeConstraintAt(composite, position); 9118 } 9119 9120 if (deep) { 9121 for (var i = 0; i < composite.composites.length; i++){ 9122 Composite.removeConstraint(composite.composites[i], constraint, true); 9123 } 9124 } 9125 9126 return composite; 9127 }; 9128 9129 /** 9130 * Removes a body from the given composite. 9131 * @private 9132 * @method removeConstraintAt 9133 * @param {composite} composite 9134 * @param {number} position 9135 * @return {composite} The original composite with the constraint removed 9136 */ 9137 Composite.removeConstraintAt = function(composite, position) { 9138 composite.constraints.splice(position, 1); 9139 Composite.setModified(composite, true, true, false); 9140 return composite; 9141 }; 9142 9143 /** 9144 * Removes all bodies, constraints and composites from the given composite. 9145 * Optionally clearing its children recursively. 9146 * @method clear 9147 * @param {composite} composite 9148 * @param {boolean} keepStatic 9149 * @param {boolean} [deep=false] 9150 */ 9151 Composite.clear = function(composite, keepStatic, deep) { 9152 if (deep) { 9153 for (var i = 0; i < composite.composites.length; i++){ 9154 Composite.clear(composite.composites[i], keepStatic, true); 9155 } 9156 } 9157 9158 if (keepStatic) { 9159 composite.bodies = composite.bodies.filter(function(body) { return body.isStatic; }); 9160 } else { 9161 composite.bodies.length = 0; 9162 } 9163 9164 composite.constraints.length = 0; 9165 composite.composites.length = 0; 9166 9167 Composite.setModified(composite, true, true, false); 9168 9169 return composite; 9170 }; 9171 9172 /** 9173 * Returns all bodies in the given composite, including all bodies in its children, recursively. 9174 * @method allBodies 9175 * @param {composite} composite 9176 * @return {body[]} All the bodies 9177 */ 9178 Composite.allBodies = function(composite) { 9179 if (composite.cache && composite.cache.allBodies) { 9180 return composite.cache.allBodies; 9181 } 9182 9183 var bodies = [].concat(composite.bodies); 9184 9185 for (var i = 0; i < composite.composites.length; i++) 9186 bodies = bodies.concat(Composite.allBodies(composite.composites[i])); 9187 9188 if (composite.cache) { 9189 composite.cache.allBodies = bodies; 9190 } 9191 9192 return bodies; 9193 }; 9194 9195 /** 9196 * Returns all constraints in the given composite, including all constraints in its children, recursively. 9197 * @method allConstraints 9198 * @param {composite} composite 9199 * @return {constraint[]} All the constraints 9200 */ 9201 Composite.allConstraints = function(composite) { 9202 if (composite.cache && composite.cache.allConstraints) { 9203 return composite.cache.allConstraints; 9204 } 9205 9206 var constraints = [].concat(composite.constraints); 9207 9208 for (var i = 0; i < composite.composites.length; i++) 9209 constraints = constraints.concat(Composite.allConstraints(composite.composites[i])); 9210 9211 if (composite.cache) { 9212 composite.cache.allConstraints = constraints; 9213 } 9214 9215 return constraints; 9216 }; 9217 9218 /** 9219 * Returns all composites in the given composite, including all composites in its children, recursively. 9220 * @method allComposites 9221 * @param {composite} composite 9222 * @return {composite[]} All the composites 9223 */ 9224 Composite.allComposites = function(composite) { 9225 if (composite.cache && composite.cache.allComposites) { 9226 return composite.cache.allComposites; 9227 } 9228 9229 var composites = [].concat(composite.composites); 9230 9231 for (var i = 0; i < composite.composites.length; i++) 9232 composites = composites.concat(Composite.allComposites(composite.composites[i])); 9233 9234 if (composite.cache) { 9235 composite.cache.allComposites = composites; 9236 } 9237 9238 return composites; 9239 }; 9240 9241 /** 9242 * Searches the composite recursively for an object matching the type and id supplied, null if not found. 9243 * @method get 9244 * @param {composite} composite 9245 * @param {number} id 9246 * @param {string} type 9247 * @return {object} The requested object, if found 9248 */ 9249 Composite.get = function(composite, id, type) { 9250 var objects, 9251 object; 9252 9253 switch (type) { 9254 case 'body': 9255 objects = Composite.allBodies(composite); 9256 break; 9257 case 'constraint': 9258 objects = Composite.allConstraints(composite); 9259 break; 9260 case 'composite': 9261 objects = Composite.allComposites(composite).concat(composite); 9262 break; 9263 } 9264 9265 if (!objects) 9266 return null; 9267 9268 object = objects.filter(function(object) { 9269 return object.id.toString() === id.toString(); 9270 }); 9271 9272 return object.length === 0 ? null : object[0]; 9273 }; 9274 9275 /** 9276 * Moves the given object(s) from compositeA to compositeB (equal to a remove followed by an add). 9277 * @method move 9278 * @param {compositeA} compositeA 9279 * @param {object[]} objects 9280 * @param {compositeB} compositeB 9281 * @return {composite} Returns compositeA 9282 */ 9283 Composite.move = function(compositeA, objects, compositeB) { 9284 Composite.remove(compositeA, objects); 9285 Composite.add(compositeB, objects); 9286 return compositeA; 9287 }; 9288 9289 /** 9290 * Assigns new ids for all objects in the composite, recursively. 9291 * @method rebase 9292 * @param {composite} composite 9293 * @return {composite} Returns composite 9294 */ 9295 Composite.rebase = function(composite) { 9296 var objects = Composite.allBodies(composite) 9297 .concat(Composite.allConstraints(composite)) 9298 .concat(Composite.allComposites(composite)); 9299 9300 for (var i = 0; i < objects.length; i++) { 9301 objects[i].id = Common.nextId(); 9302 } 9303 9304 return composite; 9305 }; 9306 9307 /** 9308 * Translates all children in the composite by a given vector relative to their current positions, 9309 * without imparting any velocity. 9310 * @method translate 9311 * @param {composite} composite 9312 * @param {vector} translation 9313 * @param {bool} [recursive=true] 9314 */ 9315 Composite.translate = function(composite, translation, recursive) { 9316 var bodies = recursive ? Composite.allBodies(composite) : composite.bodies; 9317 9318 for (var i = 0; i < bodies.length; i++) { 9319 Body.translate(bodies[i], translation); 9320 } 9321 9322 return composite; 9323 }; 9324 9325 /** 9326 * Rotates all children in the composite by a given angle about the given point, without imparting any angular velocity. 9327 * @method rotate 9328 * @param {composite} composite 9329 * @param {number} rotation 9330 * @param {vector} point 9331 * @param {bool} [recursive=true] 9332 */ 9333 Composite.rotate = function(composite, rotation, point, recursive) { 9334 var cos = Math.cos(rotation), 9335 sin = Math.sin(rotation), 9336 bodies = recursive ? Composite.allBodies(composite) : composite.bodies; 9337 9338 for (var i = 0; i < bodies.length; i++) { 9339 var body = bodies[i], 9340 dx = body.position.x - point.x, 9341 dy = body.position.y - point.y; 9342 9343 Body.setPosition(body, { 9344 x: point.x + (dx * cos - dy * sin), 9345 y: point.y + (dx * sin + dy * cos) 9346 }); 9347 9348 Body.rotate(body, rotation); 9349 } 9350 9351 return composite; 9352 }; 9353 9354 /** 9355 * Scales all children in the composite, including updating physical properties (mass, area, axes, inertia), from a world-space point. 9356 * @method scale 9357 * @param {composite} composite 9358 * @param {number} scaleX 9359 * @param {number} scaleY 9360 * @param {vector} point 9361 * @param {bool} [recursive=true] 9362 */ 9363 Composite.scale = function(composite, scaleX, scaleY, point, recursive) { 9364 var bodies = recursive ? Composite.allBodies(composite) : composite.bodies; 9365 9366 for (var i = 0; i < bodies.length; i++) { 9367 var body = bodies[i], 9368 dx = body.position.x - point.x, 9369 dy = body.position.y - point.y; 9370 9371 Body.setPosition(body, { 9372 x: point.x + dx * scaleX, 9373 y: point.y + dy * scaleY 9374 }); 9375 9376 Body.scale(body, scaleX, scaleY); 9377 } 9378 9379 return composite; 9380 }; 9381 9382 /** 9383 * Returns the union of the bounds of all of the composite's bodies. 9384 * @method bounds 9385 * @param {composite} composite The composite. 9386 * @returns {bounds} The composite bounds. 9387 */ 9388 Composite.bounds = function(composite) { 9389 var bodies = Composite.allBodies(composite), 9390 vertices = []; 9391 9392 for (var i = 0; i < bodies.length; i += 1) { 9393 var body = bodies[i]; 9394 vertices.push(body.bounds.min, body.bounds.max); 9395 } 9396 9397 return Bounds.create(vertices); 9398 }; 9399 9400 /* 9401 * 9402 * Events Documentation 9403 * 9404 */ 9405 9406 /** 9407 * Fired when a call to `Composite.add` is made, before objects have been added. 9408 * 9409 * @event beforeAdd 9410 * @param {} event An event object 9411 * @param {} event.object The object(s) to be added (may be a single body, constraint, composite or a mixed array of these) 9412 * @param {} event.source The source object of the event 9413 * @param {} event.name The name of the event 9414 */ 9415 9416 /** 9417 * Fired when a call to `Composite.add` is made, after objects have been added. 9418 * 9419 * @event afterAdd 9420 * @param {} event An event object 9421 * @param {} event.object The object(s) that have been added (may be a single body, constraint, composite or a mixed array of these) 9422 * @param {} event.source The source object of the event 9423 * @param {} event.name The name of the event 9424 */ 9425 9426 /** 9427 * Fired when a call to `Composite.remove` is made, before objects have been removed. 9428 * 9429 * @event beforeRemove 9430 * @param {} event An event object 9431 * @param {} event.object The object(s) to be removed (may be a single body, constraint, composite or a mixed array of these) 9432 * @param {} event.source The source object of the event 9433 * @param {} event.name The name of the event 9434 */ 9435 9436 /** 9437 * Fired when a call to `Composite.remove` is made, after objects have been removed. 9438 * 9439 * @event afterRemove 9440 * @param {} event An event object 9441 * @param {} event.object The object(s) that have been removed (may be a single body, constraint, composite or a mixed array of these) 9442 * @param {} event.source The source object of the event 9443 * @param {} event.name The name of the event 9444 */ 9445 9446 /* 9447 * 9448 * Properties Documentation 9449 * 9450 */ 9451 9452 /** 9453 * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. 9454 * 9455 * @property id 9456 * @type number 9457 */ 9458 9459 /** 9460 * A `String` denoting the type of object. 9461 * 9462 * @property type 9463 * @type string 9464 * @default "composite" 9465 * @readOnly 9466 */ 9467 9468 /** 9469 * An arbitrary `String` name to help the user identify and manage composites. 9470 * 9471 * @property label 9472 * @type string 9473 * @default "Composite" 9474 */ 9475 9476 /** 9477 * A flag that specifies whether the composite has been modified during the current step. 9478 * This is automatically managed when bodies, constraints or composites are added or removed. 9479 * 9480 * @property isModified 9481 * @type boolean 9482 * @default false 9483 */ 9484 9485 /** 9486 * The `Composite` that is the parent of this composite. It is automatically managed by the `Matter.Composite` methods. 9487 * 9488 * @property parent 9489 * @type composite 9490 * @default null 9491 */ 9492 9493 /** 9494 * An array of `Body` that are _direct_ children of this composite. 9495 * To add or remove bodies you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. 9496 * If you wish to recursively find all descendants, you should use the `Composite.allBodies` method. 9497 * 9498 * @property bodies 9499 * @type body[] 9500 * @default [] 9501 */ 9502 9503 /** 9504 * An array of `Constraint` that are _direct_ children of this composite. 9505 * To add or remove constraints you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. 9506 * If you wish to recursively find all descendants, you should use the `Composite.allConstraints` method. 9507 * 9508 * @property constraints 9509 * @type constraint[] 9510 * @default [] 9511 */ 9512 9513 /** 9514 * An array of `Composite` that are _direct_ children of this composite. 9515 * To add or remove composites you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. 9516 * If you wish to recursively find all descendants, you should use the `Composite.allComposites` method. 9517 * 9518 * @property composites 9519 * @type composite[] 9520 * @default [] 9521 */ 9522 9523 /** 9524 * An object reserved for storing plugin-specific properties. 9525 * 9526 * @property plugin 9527 * @type {} 9528 */ 9529 9530 /** 9531 * An object used for storing cached results for performance reasons. 9532 * This is used internally only and is automatically managed. 9533 * 9534 * @private 9535 * @property cache 9536 * @type {} 9537 */ 9538 9539})(); 9540 9541 9542/***/ }), 9543/* 7 */ 9544/***/ (function(module, exports, __webpack_require__) { 9545 9546/** 9547* The `Matter.Sleeping` module contains methods to manage the sleeping state of bodies. 9548* 9549* @class Sleeping 9550*/ 9551 9552var Sleeping = {}; 9553 9554module.exports = Sleeping; 9555 9556var Body = __webpack_require__(4); 9557var Events = __webpack_require__(5); 9558var Common = __webpack_require__(0); 9559 9560(function() { 9561 9562 Sleeping._motionWakeThreshold = 0.18; 9563 Sleeping._motionSleepThreshold = 0.08; 9564 Sleeping._minBias = 0.9; 9565 9566 /** 9567 * Puts bodies to sleep or wakes them up depending on their motion. 9568 * @method update 9569 * @param {body[]} bodies 9570 * @param {number} delta 9571 */ 9572 Sleeping.update = function(bodies, delta) { 9573 var timeScale = delta / Common._baseDelta, 9574 motionSleepThreshold = Sleeping._motionSleepThreshold; 9575 9576 // update bodies sleeping status 9577 for (var i = 0; i < bodies.length; i++) { 9578 var body = bodies[i], 9579 speed = Body.getSpeed(body), 9580 angularSpeed = Body.getAngularSpeed(body), 9581 motion = speed * speed + angularSpeed * angularSpeed; 9582 9583 // wake up bodies if they have a force applied 9584 if (body.force.x !== 0 || body.force.y !== 0) { 9585 Sleeping.set(body, false); 9586 continue; 9587 } 9588 9589 var minMotion = Math.min(body.motion, motion), 9590 maxMotion = Math.max(body.motion, motion); 9591 9592 // biased average motion estimation between frames 9593 body.motion = Sleeping._minBias * minMotion + (1 - Sleeping._minBias) * maxMotion; 9594 9595 if (body.sleepThreshold > 0 && body.motion < motionSleepThreshold) { 9596 body.sleepCounter += 1; 9597 9598 if (body.sleepCounter >= body.sleepThreshold / timeScale) { 9599 Sleeping.set(body, true); 9600 } 9601 } else if (body.sleepCounter > 0) { 9602 body.sleepCounter -= 1; 9603 } 9604 } 9605 }; 9606 9607 /** 9608 * Given a set of colliding pairs, wakes the sleeping bodies involved. 9609 * @method afterCollisions 9610 * @param {pair[]} pairs 9611 */ 9612 Sleeping.afterCollisions = function(pairs) { 9613 var motionSleepThreshold = Sleeping._motionSleepThreshold; 9614 9615 // wake up bodies involved in collisions 9616 for (var i = 0; i < pairs.length; i++) { 9617 var pair = pairs[i]; 9618 9619 // don't wake inactive pairs 9620 if (!pair.isActive) 9621 continue; 9622 9623 var collision = pair.collision, 9624 bodyA = collision.bodyA.parent, 9625 bodyB = collision.bodyB.parent; 9626 9627 // don't wake if at least one body is static 9628 if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic) 9629 continue; 9630 9631 if (bodyA.isSleeping || bodyB.isSleeping) { 9632 var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB, 9633 movingBody = sleepingBody === bodyA ? bodyB : bodyA; 9634 9635 if (!sleepingBody.isStatic && movingBody.motion > motionSleepThreshold) { 9636 Sleeping.set(sleepingBody, false); 9637 } 9638 } 9639 } 9640 }; 9641 9642 /** 9643 * Set a body as sleeping or awake. 9644 * @method set 9645 * @param {body} body 9646 * @param {boolean} isSleeping 9647 */ 9648 Sleeping.set = function(body, isSleeping) { 9649 var wasSleeping = body.isSleeping; 9650 9651 if (isSleeping) { 9652 body.isSleeping = true; 9653 body.sleepCounter = body.sleepThreshold; 9654 9655 body.positionImpulse.x = 0; 9656 body.positionImpulse.y = 0; 9657 9658 body.positionPrev.x = body.position.x; 9659 body.positionPrev.y = body.position.y; 9660 9661 body.anglePrev = body.angle; 9662 body.speed = 0; 9663 body.angularSpeed = 0; 9664 body.motion = 0; 9665 9666 if (!wasSleeping) { 9667 Events.trigger(body, 'sleepStart'); 9668 } 9669 } else { 9670 body.isSleeping = false; 9671 body.sleepCounter = 0; 9672 9673 if (wasSleeping) { 9674 Events.trigger(body, 'sleepEnd'); 9675 } 9676 } 9677 }; 9678 9679})(); 9680 9681 9682/***/ }), 9683/* 8 */ 9684/***/ (function(module, exports, __webpack_require__) { 9685 9686/** 9687* The `Matter.Collision` module contains methods for detecting collisions between a given pair of bodies. 9688* 9689* For efficient detection between a list of bodies, see `Matter.Detector` and `Matter.Query`. 9690* 9691* See `Matter.Engine` for collision events. 9692* 9693* @class Collision 9694*/ 9695 9696var Collision = {}; 9697 9698module.exports = Collision; 9699 9700var Vertices = __webpack_require__(3); 9701var Pair = __webpack_require__(9); 9702 9703(function() { 9704 var _supports = []; 9705 9706 var _overlapAB = { 9707 overlap: 0, 9708 axis: null 9709 }; 9710 9711 var _overlapBA = { 9712 overlap: 0, 9713 axis: null 9714 }; 9715 9716 /** 9717 * Creates a new collision record. 9718 * @method create 9719 * @param {body} bodyA The first body part represented by the collision record 9720 * @param {body} bodyB The second body part represented by the collision record 9721 * @return {collision} A new collision record 9722 */ 9723 Collision.create = function(bodyA, bodyB) { 9724 return { 9725 pair: null, 9726 collided: false, 9727 bodyA: bodyA, 9728 bodyB: bodyB, 9729 parentA: bodyA.parent, 9730 parentB: bodyB.parent, 9731 depth: 0, 9732 normal: { x: 0, y: 0 }, 9733 tangent: { x: 0, y: 0 }, 9734 penetration: { x: 0, y: 0 }, 9735 supports: [null, null], 9736 supportCount: 0 9737 }; 9738 }; 9739 9740 /** 9741 * Detect collision between two bodies. 9742 * @method collides 9743 * @param {body} bodyA 9744 * @param {body} bodyB 9745 * @param {pairs} [pairs] Optionally reuse collision records from existing pairs. 9746 * @return {collision|null} A collision record if detected, otherwise null 9747 */ 9748 Collision.collides = function(bodyA, bodyB, pairs) { 9749 Collision._overlapAxes(_overlapAB, bodyA.vertices, bodyB.vertices, bodyA.axes); 9750 9751 if (_overlapAB.overlap <= 0) { 9752 return null; 9753 } 9754 9755 Collision._overlapAxes(_overlapBA, bodyB.vertices, bodyA.vertices, bodyB.axes); 9756 9757 if (_overlapBA.overlap <= 0) { 9758 return null; 9759 } 9760 9761 // reuse collision records for gc efficiency 9762 var pair = pairs && pairs.table[Pair.id(bodyA, bodyB)], 9763 collision; 9764 9765 if (!pair) { 9766 collision = Collision.create(bodyA, bodyB); 9767 collision.collided = true; 9768 collision.bodyA = bodyA.id < bodyB.id ? bodyA : bodyB; 9769 collision.bodyB = bodyA.id < bodyB.id ? bodyB : bodyA; 9770 collision.parentA = collision.bodyA.parent; 9771 collision.parentB = collision.bodyB.parent; 9772 } else { 9773 collision = pair.collision; 9774 } 9775 9776 bodyA = collision.bodyA; 9777 bodyB = collision.bodyB; 9778 9779 var minOverlap; 9780 9781 if (_overlapAB.overlap < _overlapBA.overlap) { 9782 minOverlap = _overlapAB; 9783 } else { 9784 minOverlap = _overlapBA; 9785 } 9786 9787 var normal = collision.normal, 9788 tangent = collision.tangent, 9789 penetration = collision.penetration, 9790 supports = collision.supports, 9791 depth = minOverlap.overlap, 9792 minAxis = minOverlap.axis, 9793 normalX = minAxis.x, 9794 normalY = minAxis.y, 9795 deltaX = bodyB.position.x - bodyA.position.x, 9796 deltaY = bodyB.position.y - bodyA.position.y; 9797 9798 // ensure normal is facing away from bodyA 9799 if (normalX * deltaX + normalY * deltaY >= 0) { 9800 normalX = -normalX; 9801 normalY = -normalY; 9802 } 9803 9804 normal.x = normalX; 9805 normal.y = normalY; 9806 9807 tangent.x = -normalY; 9808 tangent.y = normalX; 9809 9810 penetration.x = normalX * depth; 9811 penetration.y = normalY * depth; 9812 9813 collision.depth = depth; 9814 9815 // find support points, there is always either exactly one or two 9816 var supportsB = Collision._findSupports(bodyA, bodyB, normal, 1), 9817 supportCount = 0; 9818 9819 // find the supports from bodyB that are inside bodyA 9820 if (Vertices.contains(bodyA.vertices, supportsB[0])) { 9821 supports[supportCount++] = supportsB[0]; 9822 } 9823 9824 if (Vertices.contains(bodyA.vertices, supportsB[1])) { 9825 supports[supportCount++] = supportsB[1]; 9826 } 9827 9828 // find the supports from bodyA that are inside bodyB 9829 if (supportCount < 2) { 9830 var supportsA = Collision._findSupports(bodyB, bodyA, normal, -1); 9831 9832 if (Vertices.contains(bodyB.vertices, supportsA[0])) { 9833 supports[supportCount++] = supportsA[0]; 9834 } 9835 9836 if (supportCount < 2 && Vertices.contains(bodyB.vertices, supportsA[1])) { 9837 supports[supportCount++] = supportsA[1]; 9838 } 9839 } 9840 9841 // account for the edge case of overlapping but no vertex containment 9842 if (supportCount === 0) { 9843 supports[supportCount++] = supportsB[0]; 9844 } 9845 9846 // update support count 9847 collision.supportCount = supportCount; 9848 9849 return collision; 9850 }; 9851 9852 /** 9853 * Find the overlap between two sets of vertices. 9854 * @method _overlapAxes 9855 * @private 9856 * @param {object} result 9857 * @param {vertices} verticesA 9858 * @param {vertices} verticesB 9859 * @param {axes} axes 9860 */ 9861 Collision._overlapAxes = function(result, verticesA, verticesB, axes) { 9862 var verticesALength = verticesA.length, 9863 verticesBLength = verticesB.length, 9864 verticesAX = verticesA[0].x, 9865 verticesAY = verticesA[0].y, 9866 verticesBX = verticesB[0].x, 9867 verticesBY = verticesB[0].y, 9868 axesLength = axes.length, 9869 overlapMin = Number.MAX_VALUE, 9870 overlapAxisNumber = 0, 9871 overlap, 9872 overlapAB, 9873 overlapBA, 9874 dot, 9875 i, 9876 j; 9877 9878 for (i = 0; i < axesLength; i++) { 9879 var axis = axes[i], 9880 axisX = axis.x, 9881 axisY = axis.y, 9882 minA = verticesAX * axisX + verticesAY * axisY, 9883 minB = verticesBX * axisX + verticesBY * axisY, 9884 maxA = minA, 9885 maxB = minB; 9886 9887 for (j = 1; j < verticesALength; j += 1) { 9888 dot = verticesA[j].x * axisX + verticesA[j].y * axisY; 9889 9890 if (dot > maxA) { 9891 maxA = dot; 9892 } else if (dot < minA) { 9893 minA = dot; 9894 } 9895 } 9896 9897 for (j = 1; j < verticesBLength; j += 1) { 9898 dot = verticesB[j].x * axisX + verticesB[j].y * axisY; 9899 9900 if (dot > maxB) { 9901 maxB = dot; 9902 } else if (dot < minB) { 9903 minB = dot; 9904 } 9905 } 9906 9907 overlapAB = maxA - minB; 9908 overlapBA = maxB - minA; 9909 overlap = overlapAB < overlapBA ? overlapAB : overlapBA; 9910 9911 if (overlap < overlapMin) { 9912 overlapMin = overlap; 9913 overlapAxisNumber = i; 9914 9915 if (overlap <= 0) { 9916 // can not be intersecting 9917 break; 9918 } 9919 } 9920 } 9921 9922 result.axis = axes[overlapAxisNumber]; 9923 result.overlap = overlapMin; 9924 }; 9925 9926 /** 9927 * Finds supporting vertices given two bodies along a given direction using hill-climbing. 9928 * @method _findSupports 9929 * @private 9930 * @param {body} bodyA 9931 * @param {body} bodyB 9932 * @param {vector} normal 9933 * @param {number} direction 9934 * @return [vector] 9935 */ 9936 Collision._findSupports = function(bodyA, bodyB, normal, direction) { 9937 var vertices = bodyB.vertices, 9938 verticesLength = vertices.length, 9939 bodyAPositionX = bodyA.position.x, 9940 bodyAPositionY = bodyA.position.y, 9941 normalX = normal.x * direction, 9942 normalY = normal.y * direction, 9943 vertexA = vertices[0], 9944 vertexB = vertexA, 9945 nearestDistance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y), 9946 vertexC, 9947 distance, 9948 j; 9949 9950 // find deepest vertex relative to the axis 9951 for (j = 1; j < verticesLength; j += 1) { 9952 vertexB = vertices[j]; 9953 distance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y); 9954 9955 // convex hill-climbing 9956 if (distance < nearestDistance) { 9957 nearestDistance = distance; 9958 vertexA = vertexB; 9959 } 9960 } 9961 9962 // measure next vertex 9963 vertexC = vertices[(verticesLength + vertexA.index - 1) % verticesLength]; 9964 nearestDistance = normalX * (bodyAPositionX - vertexC.x) + normalY * (bodyAPositionY - vertexC.y); 9965 9966 // compare with previous vertex 9967 vertexB = vertices[(vertexA.index + 1) % verticesLength]; 9968 if (normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y) < nearestDistance) { 9969 _supports[0] = vertexA; 9970 _supports[1] = vertexB; 9971 9972 return _supports; 9973 } 9974 9975 _supports[0] = vertexA; 9976 _supports[1] = vertexC; 9977 9978 return _supports; 9979 }; 9980 9981 /* 9982 * 9983 * Properties Documentation 9984 * 9985 */ 9986 9987 /** 9988 * A reference to the pair using this collision record, if there is one. 9989 * 9990 * @property pair 9991 * @type {pair|null} 9992 * @default null 9993 */ 9994 9995 /** 9996 * A flag that indicates if the bodies were colliding when the collision was last updated. 9997 * 9998 * @property collided 9999 * @type boolean 10000 * @default false 10001 */ 10002 10003 /** 10004 * The first body part represented by the collision (see also `collision.parentA`). 10005 * 10006 * @property bodyA 10007 * @type body 10008 */ 10009 10010 /** 10011 * The second body part represented by the collision (see also `collision.parentB`). 10012 * 10013 * @property bodyB 10014 * @type body 10015 */ 10016 10017 /** 10018 * The first body represented by the collision (i.e. `collision.bodyA.parent`). 10019 * 10020 * @property parentA 10021 * @type body 10022 */ 10023 10024 /** 10025 * The second body represented by the collision (i.e. `collision.bodyB.parent`). 10026 * 10027 * @property parentB 10028 * @type body 10029 */ 10030 10031 /** 10032 * A `Number` that represents the minimum separating distance between the bodies along the collision normal. 10033 * 10034 * @readOnly 10035 * @property depth 10036 * @type number 10037 * @default 0 10038 */ 10039 10040 /** 10041 * A normalised `Vector` that represents the direction between the bodies that provides the minimum separating distance. 10042 * 10043 * @property normal 10044 * @type vector 10045 * @default { x: 0, y: 0 } 10046 */ 10047 10048 /** 10049 * A normalised `Vector` that is the tangent direction to the collision normal. 10050 * 10051 * @property tangent 10052 * @type vector 10053 * @default { x: 0, y: 0 } 10054 */ 10055 10056 /** 10057 * A `Vector` that represents the direction and depth of the collision. 10058 * 10059 * @property penetration 10060 * @type vector 10061 * @default { x: 0, y: 0 } 10062 */ 10063 10064 /** 10065 * An array of body vertices that represent the support points in the collision. 10066 * 10067 * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active. 10068 * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports. 10069 * 10070 * These are the deepest vertices (along the collision normal) of each body that are contained by the other body's vertices. 10071 * 10072 * @property supports 10073 * @type vector[] 10074 * @default [] 10075 */ 10076 10077 /** 10078 * The number of active supports for this collision found in `collision.supports`. 10079 * 10080 * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active. 10081 * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports. 10082 * 10083 * @property supportCount 10084 * @type number 10085 * @default 0 10086 */ 10087 10088})(); 10089 10090 10091/***/ }), 10092/* 9 */ 10093/***/ (function(module, exports, __webpack_require__) { 10094 10095/** 10096* The `Matter.Pair` module contains methods for creating and manipulating collision pairs. 10097* 10098* @class Pair 10099*/ 10100 10101var Pair = {}; 10102 10103module.exports = Pair; 10104 10105var Contact = __webpack_require__(16); 10106 10107(function() { 10108 10109 /** 10110 * Creates a pair. 10111 * @method create 10112 * @param {collision} collision 10113 * @param {number} timestamp 10114 * @return {pair} A new pair 10115 */ 10116 Pair.create = function(collision, timestamp) { 10117 var bodyA = collision.bodyA, 10118 bodyB = collision.bodyB; 10119 10120 var pair = { 10121 id: Pair.id(bodyA, bodyB), 10122 bodyA: bodyA, 10123 bodyB: bodyB, 10124 collision: collision, 10125 contacts: [Contact.create(), Contact.create()], 10126 contactCount: 0, 10127 separation: 0, 10128 isActive: true, 10129 isSensor: bodyA.isSensor || bodyB.isSensor, 10130 timeCreated: timestamp, 10131 timeUpdated: timestamp, 10132 inverseMass: 0, 10133 friction: 0, 10134 frictionStatic: 0, 10135 restitution: 0, 10136 slop: 0 10137 }; 10138 10139 Pair.update(pair, collision, timestamp); 10140 10141 return pair; 10142 }; 10143 10144 /** 10145 * Updates a pair given a collision. 10146 * @method update 10147 * @param {pair} pair 10148 * @param {collision} collision 10149 * @param {number} timestamp 10150 */ 10151 Pair.update = function(pair, collision, timestamp) { 10152 var supports = collision.supports, 10153 supportCount = collision.supportCount, 10154 contacts = pair.contacts, 10155 parentA = collision.parentA, 10156 parentB = collision.parentB; 10157 10158 pair.isActive = true; 10159 pair.timeUpdated = timestamp; 10160 pair.collision = collision; 10161 pair.separation = collision.depth; 10162 pair.inverseMass = parentA.inverseMass + parentB.inverseMass; 10163 pair.friction = parentA.friction < parentB.friction ? parentA.friction : parentB.friction; 10164 pair.frictionStatic = parentA.frictionStatic > parentB.frictionStatic ? parentA.frictionStatic : parentB.frictionStatic; 10165 pair.restitution = parentA.restitution > parentB.restitution ? parentA.restitution : parentB.restitution; 10166 pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop; 10167 10168 pair.contactCount = supportCount; 10169 collision.pair = pair; 10170 10171 var supportA = supports[0], 10172 contactA = contacts[0], 10173 supportB = supports[1], 10174 contactB = contacts[1]; 10175 10176 // match contacts to supports 10177 if (contactB.vertex === supportA || contactA.vertex === supportB) { 10178 contacts[1] = contactA; 10179 contacts[0] = contactA = contactB; 10180 contactB = contacts[1]; 10181 } 10182 10183 // update contacts 10184 contactA.vertex = supportA; 10185 contactB.vertex = supportB; 10186 }; 10187 10188 /** 10189 * Set a pair as active or inactive. 10190 * @method setActive 10191 * @param {pair} pair 10192 * @param {bool} isActive 10193 * @param {number} timestamp 10194 */ 10195 Pair.setActive = function(pair, isActive, timestamp) { 10196 if (isActive) { 10197 pair.isActive = true; 10198 pair.timeUpdated = timestamp; 10199 } else { 10200 pair.isActive = false; 10201 pair.contactCount = 0; 10202 } 10203 }; 10204 10205 /** 10206 * Get the id for the given pair. 10207 * @method id 10208 * @param {body} bodyA 10209 * @param {body} bodyB 10210 * @return {string} Unique pairId 10211 */ 10212 Pair.id = function(bodyA, bodyB) { 10213 return bodyA.id < bodyB.id ? bodyA.id.toString(36) + ':' + bodyB.id.toString(36) 10214 : bodyB.id.toString(36) + ':' + bodyA.id.toString(36); 10215 }; 10216 10217})(); 10218 10219 10220/***/ }), 10221/* 10 */ 10222/***/ (function(module, exports, __webpack_require__) { 10223 10224/** 10225* The `Matter.Constraint` module contains methods for creating and manipulating constraints. 10226* Constraints are used for specifying that a fixed distance must be maintained between two bodies (or a body and a fixed world-space position). 10227* The stiffness of constraints can be modified to create springs or elastic. 10228* 10229* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 10230* 10231* @class Constraint 10232*/ 10233 10234var Constraint = {}; 10235 10236module.exports = Constraint; 10237 10238var Vertices = __webpack_require__(3); 10239var Vector = __webpack_require__(2); 10240var Sleeping = __webpack_require__(7); 10241var Bounds = __webpack_require__(1); 10242var Axes = __webpack_require__(11); 10243var Common = __webpack_require__(0); 10244 10245(function() { 10246 10247 Constraint._warming = 0.4; 10248 Constraint._torqueDampen = 1; 10249 Constraint._minLength = 0.000001; 10250 10251 /** 10252 * Creates a new constraint. 10253 * All properties have default values, and many are pre-calculated automatically based on other properties. 10254 * To simulate a revolute constraint (or pin joint) set `length: 0` and a high `stiffness` value (e.g. `0.7` or above). 10255 * If the constraint is unstable, try lowering the `stiffness` value and / or increasing `engine.constraintIterations`. 10256 * For compound bodies, constraints must be applied to the parent body (not one of its parts). 10257 * See the properties section below for detailed information on what you can pass via the `options` object. 10258 * @method create 10259 * @param {} options 10260 * @return {constraint} constraint 10261 */ 10262 Constraint.create = function(options) { 10263 var constraint = options; 10264 10265 // if bodies defined but no points, use body centre 10266 if (constraint.bodyA && !constraint.pointA) 10267 constraint.pointA = { x: 0, y: 0 }; 10268 if (constraint.bodyB && !constraint.pointB) 10269 constraint.pointB = { x: 0, y: 0 }; 10270 10271 // calculate static length using initial world space points 10272 var initialPointA = constraint.bodyA ? Vector.add(constraint.bodyA.position, constraint.pointA) : constraint.pointA, 10273 initialPointB = constraint.bodyB ? Vector.add(constraint.bodyB.position, constraint.pointB) : constraint.pointB, 10274 length = Vector.magnitude(Vector.sub(initialPointA, initialPointB)); 10275 10276 constraint.length = typeof constraint.length !== 'undefined' ? constraint.length : length; 10277 10278 // option defaults 10279 constraint.id = constraint.id || Common.nextId(); 10280 constraint.label = constraint.label || 'Constraint'; 10281 constraint.type = 'constraint'; 10282 constraint.stiffness = constraint.stiffness || (constraint.length > 0 ? 1 : 0.7); 10283 constraint.damping = constraint.damping || 0; 10284 constraint.angularStiffness = constraint.angularStiffness || 0; 10285 constraint.angleA = constraint.bodyA ? constraint.bodyA.angle : constraint.angleA; 10286 constraint.angleB = constraint.bodyB ? constraint.bodyB.angle : constraint.angleB; 10287 constraint.plugin = {}; 10288 10289 // render 10290 var render = { 10291 visible: true, 10292 lineWidth: 2, 10293 strokeStyle: '#ffffff', 10294 type: 'line', 10295 anchors: true 10296 }; 10297 10298 if (constraint.length === 0 && constraint.stiffness > 0.1) { 10299 render.type = 'pin'; 10300 render.anchors = false; 10301 } else if (constraint.stiffness < 0.9) { 10302 render.type = 'spring'; 10303 } 10304 10305 constraint.render = Common.extend(render, constraint.render); 10306 10307 return constraint; 10308 }; 10309 10310 /** 10311 * Prepares for solving by constraint warming. 10312 * @private 10313 * @method preSolveAll 10314 * @param {body[]} bodies 10315 */ 10316 Constraint.preSolveAll = function(bodies) { 10317 for (var i = 0; i < bodies.length; i += 1) { 10318 var body = bodies[i], 10319 impulse = body.constraintImpulse; 10320 10321 if (body.isStatic || (impulse.x === 0 && impulse.y === 0 && impulse.angle === 0)) { 10322 continue; 10323 } 10324 10325 body.position.x += impulse.x; 10326 body.position.y += impulse.y; 10327 body.angle += impulse.angle; 10328 } 10329 }; 10330 10331 /** 10332 * Solves all constraints in a list of collisions. 10333 * @private 10334 * @method solveAll 10335 * @param {constraint[]} constraints 10336 * @param {number} delta 10337 */ 10338 Constraint.solveAll = function(constraints, delta) { 10339 var timeScale = Common.clamp(delta / Common._baseDelta, 0, 1); 10340 10341 // Solve fixed constraints first. 10342 for (var i = 0; i < constraints.length; i += 1) { 10343 var constraint = constraints[i], 10344 fixedA = !constraint.bodyA || (constraint.bodyA && constraint.bodyA.isStatic), 10345 fixedB = !constraint.bodyB || (constraint.bodyB && constraint.bodyB.isStatic); 10346 10347 if (fixedA || fixedB) { 10348 Constraint.solve(constraints[i], timeScale); 10349 } 10350 } 10351 10352 // Solve free constraints last. 10353 for (i = 0; i < constraints.length; i += 1) { 10354 constraint = constraints[i]; 10355 fixedA = !constraint.bodyA || (constraint.bodyA && constraint.bodyA.isStatic); 10356 fixedB = !constraint.bodyB || (constraint.bodyB && constraint.bodyB.isStatic); 10357 10358 if (!fixedA && !fixedB) { 10359 Constraint.solve(constraints[i], timeScale); 10360 } 10361 } 10362 }; 10363 10364 /** 10365 * Solves a distance constraint with Gauss-Siedel method. 10366 * @private 10367 * @method solve 10368 * @param {constraint} constraint 10369 * @param {number} timeScale 10370 */ 10371 Constraint.solve = function(constraint, timeScale) { 10372 var bodyA = constraint.bodyA, 10373 bodyB = constraint.bodyB, 10374 pointA = constraint.pointA, 10375 pointB = constraint.pointB; 10376 10377 if (!bodyA && !bodyB) 10378 return; 10379 10380 // update reference angle 10381 if (bodyA && !bodyA.isStatic) { 10382 Vector.rotate(pointA, bodyA.angle - constraint.angleA, pointA); 10383 constraint.angleA = bodyA.angle; 10384 } 10385 10386 // update reference angle 10387 if (bodyB && !bodyB.isStatic) { 10388 Vector.rotate(pointB, bodyB.angle - constraint.angleB, pointB); 10389 constraint.angleB = bodyB.angle; 10390 } 10391 10392 var pointAWorld = pointA, 10393 pointBWorld = pointB; 10394 10395 if (bodyA) pointAWorld = Vector.add(bodyA.position, pointA); 10396 if (bodyB) pointBWorld = Vector.add(bodyB.position, pointB); 10397 10398 if (!pointAWorld || !pointBWorld) 10399 return; 10400 10401 var delta = Vector.sub(pointAWorld, pointBWorld), 10402 currentLength = Vector.magnitude(delta); 10403 10404 // prevent singularity 10405 if (currentLength < Constraint._minLength) { 10406 currentLength = Constraint._minLength; 10407 } 10408 10409 // solve distance constraint with Gauss-Siedel method 10410 var difference = (currentLength - constraint.length) / currentLength, 10411 isRigid = constraint.stiffness >= 1 || constraint.length === 0, 10412 stiffness = isRigid ? constraint.stiffness * timeScale 10413 : constraint.stiffness * timeScale * timeScale, 10414 damping = constraint.damping * timeScale, 10415 force = Vector.mult(delta, difference * stiffness), 10416 massTotal = (bodyA ? bodyA.inverseMass : 0) + (bodyB ? bodyB.inverseMass : 0), 10417 inertiaTotal = (bodyA ? bodyA.inverseInertia : 0) + (bodyB ? bodyB.inverseInertia : 0), 10418 resistanceTotal = massTotal + inertiaTotal, 10419 torque, 10420 share, 10421 normal, 10422 normalVelocity, 10423 relativeVelocity; 10424 10425 if (damping > 0) { 10426 var zero = Vector.create(); 10427 normal = Vector.div(delta, currentLength); 10428 10429 relativeVelocity = Vector.sub( 10430 bodyB && Vector.sub(bodyB.position, bodyB.positionPrev) || zero, 10431 bodyA && Vector.sub(bodyA.position, bodyA.positionPrev) || zero 10432 ); 10433 10434 normalVelocity = Vector.dot(normal, relativeVelocity); 10435 } 10436 10437 if (bodyA && !bodyA.isStatic) { 10438 share = bodyA.inverseMass / massTotal; 10439 10440 // keep track of applied impulses for post solving 10441 bodyA.constraintImpulse.x -= force.x * share; 10442 bodyA.constraintImpulse.y -= force.y * share; 10443 10444 // apply forces 10445 bodyA.position.x -= force.x * share; 10446 bodyA.position.y -= force.y * share; 10447 10448 // apply damping 10449 if (damping > 0) { 10450 bodyA.positionPrev.x -= damping * normal.x * normalVelocity * share; 10451 bodyA.positionPrev.y -= damping * normal.y * normalVelocity * share; 10452 } 10453 10454 // apply torque 10455 torque = (Vector.cross(pointA, force) / resistanceTotal) * Constraint._torqueDampen * bodyA.inverseInertia * (1 - constraint.angularStiffness); 10456 bodyA.constraintImpulse.angle -= torque; 10457 bodyA.angle -= torque; 10458 } 10459 10460 if (bodyB && !bodyB.isStatic) { 10461 share = bodyB.inverseMass / massTotal; 10462 10463 // keep track of applied impulses for post solving 10464 bodyB.constraintImpulse.x += force.x * share; 10465 bodyB.constraintImpulse.y += force.y * share; 10466 10467 // apply forces 10468 bodyB.position.x += force.x * share; 10469 bodyB.position.y += force.y * share; 10470 10471 // apply damping 10472 if (damping > 0) { 10473 bodyB.positionPrev.x += damping * normal.x * normalVelocity * share; 10474 bodyB.positionPrev.y += damping * normal.y * normalVelocity * share; 10475 } 10476 10477 // apply torque 10478 torque = (Vector.cross(pointB, force) / resistanceTotal) * Constraint._torqueDampen * bodyB.inverseInertia * (1 - constraint.angularStiffness); 10479 bodyB.constraintImpulse.angle += torque; 10480 bodyB.angle += torque; 10481 } 10482 10483 }; 10484 10485 /** 10486 * Performs body updates required after solving constraints. 10487 * @private 10488 * @method postSolveAll 10489 * @param {body[]} bodies 10490 */ 10491 Constraint.postSolveAll = function(bodies) { 10492 for (var i = 0; i < bodies.length; i++) { 10493 var body = bodies[i], 10494 impulse = body.constraintImpulse; 10495 10496 if (body.isStatic || (impulse.x === 0 && impulse.y === 0 && impulse.angle === 0)) { 10497 continue; 10498 } 10499 10500 Sleeping.set(body, false); 10501 10502 // update geometry and reset 10503 for (var j = 0; j < body.parts.length; j++) { 10504 var part = body.parts[j]; 10505 10506 Vertices.translate(part.vertices, impulse); 10507 10508 if (j > 0) { 10509 part.position.x += impulse.x; 10510 part.position.y += impulse.y; 10511 } 10512 10513 if (impulse.angle !== 0) { 10514 Vertices.rotate(part.vertices, impulse.angle, body.position); 10515 Axes.rotate(part.axes, impulse.angle); 10516 if (j > 0) { 10517 Vector.rotateAbout(part.position, impulse.angle, body.position, part.position); 10518 } 10519 } 10520 10521 Bounds.update(part.bounds, part.vertices, body.velocity); 10522 } 10523 10524 // dampen the cached impulse for warming next step 10525 impulse.angle *= Constraint._warming; 10526 impulse.x *= Constraint._warming; 10527 impulse.y *= Constraint._warming; 10528 } 10529 }; 10530 10531 /** 10532 * Returns the world-space position of `constraint.pointA`, accounting for `constraint.bodyA`. 10533 * @method pointAWorld 10534 * @param {constraint} constraint 10535 * @returns {vector} the world-space position 10536 */ 10537 Constraint.pointAWorld = function(constraint) { 10538 return { 10539 x: (constraint.bodyA ? constraint.bodyA.position.x : 0) 10540 + (constraint.pointA ? constraint.pointA.x : 0), 10541 y: (constraint.bodyA ? constraint.bodyA.position.y : 0) 10542 + (constraint.pointA ? constraint.pointA.y : 0) 10543 }; 10544 }; 10545 10546 /** 10547 * Returns the world-space position of `constraint.pointB`, accounting for `constraint.bodyB`. 10548 * @method pointBWorld 10549 * @param {constraint} constraint 10550 * @returns {vector} the world-space position 10551 */ 10552 Constraint.pointBWorld = function(constraint) { 10553 return { 10554 x: (constraint.bodyB ? constraint.bodyB.position.x : 0) 10555 + (constraint.pointB ? constraint.pointB.x : 0), 10556 y: (constraint.bodyB ? constraint.bodyB.position.y : 0) 10557 + (constraint.pointB ? constraint.pointB.y : 0) 10558 }; 10559 }; 10560 10561 /** 10562 * Returns the current length of the constraint. 10563 * This is the distance between both of the constraint's end points. 10564 * See `constraint.length` for the target rest length. 10565 * @method currentLength 10566 * @param {constraint} constraint 10567 * @returns {number} the current length 10568 */ 10569 Constraint.currentLength = function(constraint) { 10570 var pointAX = (constraint.bodyA ? constraint.bodyA.position.x : 0) 10571 + (constraint.pointA ? constraint.pointA.x : 0); 10572 10573 var pointAY = (constraint.bodyA ? constraint.bodyA.position.y : 0) 10574 + (constraint.pointA ? constraint.pointA.y : 0); 10575 10576 var pointBX = (constraint.bodyB ? constraint.bodyB.position.x : 0) 10577 + (constraint.pointB ? constraint.pointB.x : 0); 10578 10579 var pointBY = (constraint.bodyB ? constraint.bodyB.position.y : 0) 10580 + (constraint.pointB ? constraint.pointB.y : 0); 10581 10582 var deltaX = pointAX - pointBX; 10583 var deltaY = pointAY - pointBY; 10584 10585 return Math.sqrt(deltaX * deltaX + deltaY * deltaY); 10586 }; 10587 10588 /* 10589 * 10590 * Properties Documentation 10591 * 10592 */ 10593 10594 /** 10595 * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. 10596 * 10597 * @property id 10598 * @type number 10599 */ 10600 10601 /** 10602 * A `String` denoting the type of object. 10603 * 10604 * @property type 10605 * @type string 10606 * @default "constraint" 10607 * @readOnly 10608 */ 10609 10610 /** 10611 * An arbitrary `String` name to help the user identify and manage bodies. 10612 * 10613 * @property label 10614 * @type string 10615 * @default "Constraint" 10616 */ 10617 10618 /** 10619 * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. 10620 * 10621 * @property render 10622 * @type object 10623 */ 10624 10625 /** 10626 * A flag that indicates if the constraint should be rendered. 10627 * 10628 * @property render.visible 10629 * @type boolean 10630 * @default true 10631 */ 10632 10633 /** 10634 * A `Number` that defines the line width to use when rendering the constraint outline. 10635 * A value of `0` means no outline will be rendered. 10636 * 10637 * @property render.lineWidth 10638 * @type number 10639 * @default 2 10640 */ 10641 10642 /** 10643 * A `String` that defines the stroke style to use when rendering the constraint outline. 10644 * It is the same as when using a canvas, so it accepts CSS style property values. 10645 * 10646 * @property render.strokeStyle 10647 * @type string 10648 * @default a random colour 10649 */ 10650 10651 /** 10652 * A `String` that defines the constraint rendering type. 10653 * The possible values are 'line', 'pin', 'spring'. 10654 * An appropriate render type will be automatically chosen unless one is given in options. 10655 * 10656 * @property render.type 10657 * @type string 10658 * @default 'line' 10659 */ 10660 10661 /** 10662 * A `Boolean` that defines if the constraint's anchor points should be rendered. 10663 * 10664 * @property render.anchors 10665 * @type boolean 10666 * @default true 10667 */ 10668 10669 /** 10670 * The first possible `Body` that this constraint is attached to. 10671 * 10672 * @property bodyA 10673 * @type body 10674 * @default null 10675 */ 10676 10677 /** 10678 * The second possible `Body` that this constraint is attached to. 10679 * 10680 * @property bodyB 10681 * @type body 10682 * @default null 10683 */ 10684 10685 /** 10686 * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position. 10687 * 10688 * @property pointA 10689 * @type vector 10690 * @default { x: 0, y: 0 } 10691 */ 10692 10693 /** 10694 * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyB` if defined, otherwise a world-space position. 10695 * 10696 * @property pointB 10697 * @type vector 10698 * @default { x: 0, y: 0 } 10699 */ 10700 10701 /** 10702 * A `Number` that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. 10703 * A value of `1` means the constraint should be very stiff. 10704 * A value of `0.2` means the constraint acts like a soft spring. 10705 * 10706 * @property stiffness 10707 * @type number 10708 * @default 1 10709 */ 10710 10711 /** 10712 * A `Number` that specifies the damping of the constraint, 10713 * i.e. the amount of resistance applied to each body based on their velocities to limit the amount of oscillation. 10714 * Damping will only be apparent when the constraint also has a very low `stiffness`. 10715 * A value of `0.1` means the constraint will apply heavy damping, resulting in little to no oscillation. 10716 * A value of `0` means the constraint will apply no damping. 10717 * 10718 * @property damping 10719 * @type number 10720 * @default 0 10721 */ 10722 10723 /** 10724 * A `Number` that specifies the target resting length of the constraint. 10725 * It is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. 10726 * 10727 * @property length 10728 * @type number 10729 */ 10730 10731 /** 10732 * An object reserved for storing plugin-specific properties. 10733 * 10734 * @property plugin 10735 * @type {} 10736 */ 10737 10738})(); 10739 10740 10741/***/ }), 10742/* 11 */ 10743/***/ (function(module, exports, __webpack_require__) { 10744 10745/** 10746* The `Matter.Axes` module contains methods for creating and manipulating sets of axes. 10747* 10748* @class Axes 10749*/ 10750 10751var Axes = {}; 10752 10753module.exports = Axes; 10754 10755var Vector = __webpack_require__(2); 10756var Common = __webpack_require__(0); 10757 10758(function() { 10759 10760 /** 10761 * Creates a new set of axes from the given vertices. 10762 * @method fromVertices 10763 * @param {vertices} vertices 10764 * @return {axes} A new axes from the given vertices 10765 */ 10766 Axes.fromVertices = function(vertices) { 10767 var axes = {}; 10768 10769 // find the unique axes, using edge normal gradients 10770 for (var i = 0; i < vertices.length; i++) { 10771 var j = (i + 1) % vertices.length, 10772 normal = Vector.normalise({ 10773 x: vertices[j].y - vertices[i].y, 10774 y: vertices[i].x - vertices[j].x 10775 }), 10776 gradient = (normal.y === 0) ? Infinity : (normal.x / normal.y); 10777 10778 // limit precision 10779 gradient = gradient.toFixed(3).toString(); 10780 axes[gradient] = normal; 10781 } 10782 10783 return Common.values(axes); 10784 }; 10785 10786 /** 10787 * Rotates a set of axes by the given angle. 10788 * @method rotate 10789 * @param {axes} axes 10790 * @param {number} angle 10791 */ 10792 Axes.rotate = function(axes, angle) { 10793 if (angle === 0) 10794 return; 10795 10796 var cos = Math.cos(angle), 10797 sin = Math.sin(angle); 10798 10799 for (var i = 0; i < axes.length; i++) { 10800 var axis = axes[i], 10801 xx; 10802 xx = axis.x * cos - axis.y * sin; 10803 axis.y = axis.x * sin + axis.y * cos; 10804 axis.x = xx; 10805 } 10806 }; 10807 10808})(); 10809 10810 10811/***/ }), 10812/* 12 */ 10813/***/ (function(module, exports, __webpack_require__) { 10814 10815/** 10816* The `Matter.Bodies` module contains factory methods for creating rigid body models 10817* with commonly used body configurations (such as rectangles, circles and other polygons). 10818* 10819* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 10820* 10821* @class Bodies 10822*/ 10823 10824// TODO: true circle bodies 10825 10826var Bodies = {}; 10827 10828module.exports = Bodies; 10829 10830var Vertices = __webpack_require__(3); 10831var Common = __webpack_require__(0); 10832var Body = __webpack_require__(4); 10833var Bounds = __webpack_require__(1); 10834var Vector = __webpack_require__(2); 10835 10836(function() { 10837 10838 /** 10839 * Creates a new rigid body model with a rectangle hull. 10840 * The options parameter is an object that specifies any properties you wish to override the defaults. 10841 * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. 10842 * @method rectangle 10843 * @param {number} x 10844 * @param {number} y 10845 * @param {number} width 10846 * @param {number} height 10847 * @param {object} [options] 10848 * @return {body} A new rectangle body 10849 */ 10850 Bodies.rectangle = function(x, y, width, height, options) { 10851 options = options || {}; 10852 10853 var rectangle = { 10854 label: 'Rectangle Body', 10855 position: { x: x, y: y }, 10856 vertices: Vertices.fromPath('L 0 0 L ' + width + ' 0 L ' + width + ' ' + height + ' L 0 ' + height) 10857 }; 10858 10859 if (options.chamfer) { 10860 var chamfer = options.chamfer; 10861 rectangle.vertices = Vertices.chamfer(rectangle.vertices, chamfer.radius, 10862 chamfer.quality, chamfer.qualityMin, chamfer.qualityMax); 10863 delete options.chamfer; 10864 } 10865 10866 return Body.create(Common.extend({}, rectangle, options)); 10867 }; 10868 10869 /** 10870 * Creates a new rigid body model with a trapezoid hull. 10871 * The `slope` is parameterised as a fraction of `width` and must be < 1 to form a valid trapezoid. 10872 * The options parameter is an object that specifies any properties you wish to override the defaults. 10873 * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. 10874 * @method trapezoid 10875 * @param {number} x 10876 * @param {number} y 10877 * @param {number} width 10878 * @param {number} height 10879 * @param {number} slope Must be a number < 1. 10880 * @param {object} [options] 10881 * @return {body} A new trapezoid body 10882 */ 10883 Bodies.trapezoid = function(x, y, width, height, slope, options) { 10884 options = options || {}; 10885 10886 if (slope >= 1) { 10887 Common.warn('Bodies.trapezoid: slope parameter must be < 1.'); 10888 } 10889 10890 slope *= 0.5; 10891 var roof = (1 - (slope * 2)) * width; 10892 10893 var x1 = width * slope, 10894 x2 = x1 + roof, 10895 x3 = x2 + x1, 10896 verticesPath; 10897 10898 if (slope < 0.5) { 10899 verticesPath = 'L 0 0 L ' + x1 + ' ' + (-height) + ' L ' + x2 + ' ' + (-height) + ' L ' + x3 + ' 0'; 10900 } else { 10901 verticesPath = 'L 0 0 L ' + x2 + ' ' + (-height) + ' L ' + x3 + ' 0'; 10902 } 10903 10904 var trapezoid = { 10905 label: 'Trapezoid Body', 10906 position: { x: x, y: y }, 10907 vertices: Vertices.fromPath(verticesPath) 10908 }; 10909 10910 if (options.chamfer) { 10911 var chamfer = options.chamfer; 10912 trapezoid.vertices = Vertices.chamfer(trapezoid.vertices, chamfer.radius, 10913 chamfer.quality, chamfer.qualityMin, chamfer.qualityMax); 10914 delete options.chamfer; 10915 } 10916 10917 return Body.create(Common.extend({}, trapezoid, options)); 10918 }; 10919 10920 /** 10921 * Creates a new rigid body model with a circle hull. 10922 * The options parameter is an object that specifies any properties you wish to override the defaults. 10923 * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. 10924 * @method circle 10925 * @param {number} x 10926 * @param {number} y 10927 * @param {number} radius 10928 * @param {object} [options] 10929 * @param {number} [maxSides] 10930 * @return {body} A new circle body 10931 */ 10932 Bodies.circle = function(x, y, radius, options, maxSides) { 10933 options = options || {}; 10934 10935 var circle = { 10936 label: 'Circle Body', 10937 circleRadius: radius 10938 }; 10939 10940 // approximate circles with polygons until true circles implemented in SAT 10941 maxSides = maxSides || 25; 10942 var sides = Math.ceil(Math.max(10, Math.min(maxSides, radius))); 10943 10944 // optimisation: always use even number of sides (half the number of unique axes) 10945 if (sides % 2 === 1) 10946 sides += 1; 10947 10948 return Bodies.polygon(x, y, sides, radius, Common.extend({}, circle, options)); 10949 }; 10950 10951 /** 10952 * Creates a new rigid body model with a regular polygon hull with the given number of sides. 10953 * The options parameter is an object that specifies any properties you wish to override the defaults. 10954 * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. 10955 * @method polygon 10956 * @param {number} x 10957 * @param {number} y 10958 * @param {number} sides 10959 * @param {number} radius 10960 * @param {object} [options] 10961 * @return {body} A new regular polygon body 10962 */ 10963 Bodies.polygon = function(x, y, sides, radius, options) { 10964 options = options || {}; 10965 10966 if (sides < 3) 10967 return Bodies.circle(x, y, radius, options); 10968 10969 var theta = 2 * Math.PI / sides, 10970 path = '', 10971 offset = theta * 0.5; 10972 10973 for (var i = 0; i < sides; i += 1) { 10974 var angle = offset + (i * theta), 10975 xx = Math.cos(angle) * radius, 10976 yy = Math.sin(angle) * radius; 10977 10978 path += 'L ' + xx.toFixed(3) + ' ' + yy.toFixed(3) + ' '; 10979 } 10980 10981 var polygon = { 10982 label: 'Polygon Body', 10983 position: { x: x, y: y }, 10984 vertices: Vertices.fromPath(path) 10985 }; 10986 10987 if (options.chamfer) { 10988 var chamfer = options.chamfer; 10989 polygon.vertices = Vertices.chamfer(polygon.vertices, chamfer.radius, 10990 chamfer.quality, chamfer.qualityMin, chamfer.qualityMax); 10991 delete options.chamfer; 10992 } 10993 10994 return Body.create(Common.extend({}, polygon, options)); 10995 }; 10996 10997 /** 10998 * Utility to create a compound body based on set(s) of vertices. 10999 * 11000 * _Note:_ To optionally enable automatic concave vertices decomposition the [poly-decomp](https://github.com/schteppe/poly-decomp.js) 11001 * package must be first installed and provided see `Common.setDecomp`, otherwise the convex hull of each vertex set will be used. 11002 * 11003 * The resulting vertices are reorientated about their centre of mass, 11004 * and offset such that `body.position` corresponds to this point. 11005 * 11006 * The resulting offset may be found if needed by subtracting `body.bounds` from the original input bounds. 11007 * To later move the centre of mass see `Body.setCentre`. 11008 * 11009 * Note that automatic conconcave decomposition results are not always optimal. 11010 * For best results, simplify the input vertices as much as possible first. 11011 * By default this function applies some addtional simplification to help. 11012 * 11013 * Some outputs may also require further manual processing afterwards to be robust. 11014 * In particular some parts may need to be overlapped to avoid collision gaps. 11015 * Thin parts and sharp points should be avoided or removed where possible. 11016 * 11017 * The options parameter object specifies any `Matter.Body` properties you wish to override the defaults. 11018 * 11019 * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. 11020 * @method fromVertices 11021 * @param {number} x 11022 * @param {number} y 11023 * @param {array} vertexSets One or more arrays of vertex points e.g. `[[{ x: 0, y: 0 }...], ...]`. 11024 * @param {object} [options] The body options. 11025 * @param {bool} [flagInternal=false] Optionally marks internal edges with `isInternal`. 11026 * @param {number} [removeCollinear=0.01] Threshold when simplifying vertices along the same edge. 11027 * @param {number} [minimumArea=10] Threshold when removing small parts. 11028 * @param {number} [removeDuplicatePoints=0.01] Threshold when simplifying nearby vertices. 11029 * @return {body} 11030 */ 11031 Bodies.fromVertices = function(x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea, removeDuplicatePoints) { 11032 var decomp = Common.getDecomp(), 11033 canDecomp, 11034 body, 11035 parts, 11036 isConvex, 11037 isConcave, 11038 vertices, 11039 i, 11040 j, 11041 k, 11042 v, 11043 z; 11044 11045 // check decomp is as expected 11046 canDecomp = Boolean(decomp && decomp.quickDecomp); 11047 11048 options = options || {}; 11049 parts = []; 11050 11051 flagInternal = typeof flagInternal !== 'undefined' ? flagInternal : false; 11052 removeCollinear = typeof removeCollinear !== 'undefined' ? removeCollinear : 0.01; 11053 minimumArea = typeof minimumArea !== 'undefined' ? minimumArea : 10; 11054 removeDuplicatePoints = typeof removeDuplicatePoints !== 'undefined' ? removeDuplicatePoints : 0.01; 11055 11056 // ensure vertexSets is an array of arrays 11057 if (!Common.isArray(vertexSets[0])) { 11058 vertexSets = [vertexSets]; 11059 } 11060 11061 for (v = 0; v < vertexSets.length; v += 1) { 11062 vertices = vertexSets[v]; 11063 isConvex = Vertices.isConvex(vertices); 11064 isConcave = !isConvex; 11065 11066 if (isConcave && !canDecomp) { 11067 Common.warnOnce( 11068 'Bodies.fromVertices: Install the \'poly-decomp\' library and use Common.setDecomp or provide \'decomp\' as a global to decompose concave vertices.' 11069 ); 11070 } 11071 11072 if (isConvex || !canDecomp) { 11073 if (isConvex) { 11074 vertices = Vertices.clockwiseSort(vertices); 11075 } else { 11076 // fallback to convex hull when decomposition is not possible 11077 vertices = Vertices.hull(vertices); 11078 } 11079 11080 parts.push({ 11081 position: { x: x, y: y }, 11082 vertices: vertices 11083 }); 11084 } else { 11085 // initialise a decomposition 11086 var concave = vertices.map(function(vertex) { 11087 return [vertex.x, vertex.y]; 11088 }); 11089 11090 // vertices are concave and simple, we can decompose into parts 11091 decomp.makeCCW(concave); 11092 if (removeCollinear !== false) 11093 decomp.removeCollinearPoints(concave, removeCollinear); 11094 if (removeDuplicatePoints !== false && decomp.removeDuplicatePoints) 11095 decomp.removeDuplicatePoints(concave, removeDuplicatePoints); 11096 11097 // use the quick decomposition algorithm (Bayazit) 11098 var decomposed = decomp.quickDecomp(concave); 11099 11100 // for each decomposed chunk 11101 for (i = 0; i < decomposed.length; i++) { 11102 var chunk = decomposed[i]; 11103 11104 // convert vertices into the correct structure 11105 var chunkVertices = chunk.map(function(vertices) { 11106 return { 11107 x: vertices[0], 11108 y: vertices[1] 11109 }; 11110 }); 11111 11112 // skip small chunks 11113 if (minimumArea > 0 && Vertices.area(chunkVertices) < minimumArea) 11114 continue; 11115 11116 // create a compound part 11117 parts.push({ 11118 position: Vertices.centre(chunkVertices), 11119 vertices: chunkVertices 11120 }); 11121 } 11122 } 11123 } 11124 11125 // create body parts 11126 for (i = 0; i < parts.length; i++) { 11127 parts[i] = Body.create(Common.extend(parts[i], options)); 11128 } 11129 11130 // flag internal edges (coincident part edges) 11131 if (flagInternal) { 11132 var coincident_max_dist = 5; 11133 11134 for (i = 0; i < parts.length; i++) { 11135 var partA = parts[i]; 11136 11137 for (j = i + 1; j < parts.length; j++) { 11138 var partB = parts[j]; 11139 11140 if (Bounds.overlaps(partA.bounds, partB.bounds)) { 11141 var pav = partA.vertices, 11142 pbv = partB.vertices; 11143 11144 // iterate vertices of both parts 11145 for (k = 0; k < partA.vertices.length; k++) { 11146 for (z = 0; z < partB.vertices.length; z++) { 11147 // find distances between the vertices 11148 var da = Vector.magnitudeSquared(Vector.sub(pav[(k + 1) % pav.length], pbv[z])), 11149 db = Vector.magnitudeSquared(Vector.sub(pav[k], pbv[(z + 1) % pbv.length])); 11150 11151 // if both vertices are very close, consider the edge concident (internal) 11152 if (da < coincident_max_dist && db < coincident_max_dist) { 11153 pav[k].isInternal = true; 11154 pbv[z].isInternal = true; 11155 } 11156 } 11157 } 11158 11159 } 11160 } 11161 } 11162 } 11163 11164 if (parts.length > 1) { 11165 // create the parent body to be returned, that contains generated compound parts 11166 body = Body.create(Common.extend({ parts: parts.slice(0) }, options)); 11167 11168 // offset such that body.position is at the centre off mass 11169 Body.setPosition(body, { x: x, y: y }); 11170 11171 return body; 11172 } else { 11173 return parts[0]; 11174 } 11175 }; 11176 11177})(); 11178 11179 11180/***/ }), 11181/* 13 */ 11182/***/ (function(module, exports, __webpack_require__) { 11183 11184/** 11185* The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm. 11186* 11187* @class Detector 11188*/ 11189 11190var Detector = {}; 11191 11192module.exports = Detector; 11193 11194var Common = __webpack_require__(0); 11195var Collision = __webpack_require__(8); 11196 11197(function() { 11198 11199 /** 11200 * Creates a new collision detector. 11201 * @method create 11202 * @param {} options 11203 * @return {detector} A new collision detector 11204 */ 11205 Detector.create = function(options) { 11206 var defaults = { 11207 bodies: [], 11208 collisions: [], 11209 pairs: null 11210 }; 11211 11212 return Common.extend(defaults, options); 11213 }; 11214 11215 /** 11216 * Sets the list of bodies in the detector. 11217 * @method setBodies 11218 * @param {detector} detector 11219 * @param {body[]} bodies 11220 */ 11221 Detector.setBodies = function(detector, bodies) { 11222 detector.bodies = bodies.slice(0); 11223 }; 11224 11225 /** 11226 * Clears the detector including its list of bodies. 11227 * @method clear 11228 * @param {detector} detector 11229 */ 11230 Detector.clear = function(detector) { 11231 detector.bodies = []; 11232 detector.collisions = []; 11233 }; 11234 11235 /** 11236 * Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm. 11237 * 11238 * _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons. 11239 * If a specific ordering is required then apply a sort to the resulting array. 11240 * @method collisions 11241 * @param {detector} detector 11242 * @return {collision[]} collisions 11243 */ 11244 Detector.collisions = function(detector) { 11245 var pairs = detector.pairs, 11246 bodies = detector.bodies, 11247 bodiesLength = bodies.length, 11248 canCollide = Detector.canCollide, 11249 collides = Collision.collides, 11250 collisions = detector.collisions, 11251 collisionIndex = 0, 11252 i, 11253 j; 11254 11255 bodies.sort(Detector._compareBoundsX); 11256 11257 for (i = 0; i < bodiesLength; i++) { 11258 var bodyA = bodies[i], 11259 boundsA = bodyA.bounds, 11260 boundXMax = bodyA.bounds.max.x, 11261 boundYMax = bodyA.bounds.max.y, 11262 boundYMin = bodyA.bounds.min.y, 11263 bodyAStatic = bodyA.isStatic || bodyA.isSleeping, 11264 partsALength = bodyA.parts.length, 11265 partsASingle = partsALength === 1; 11266 11267 for (j = i + 1; j < bodiesLength; j++) { 11268 var bodyB = bodies[j], 11269 boundsB = bodyB.bounds; 11270 11271 if (boundsB.min.x > boundXMax) { 11272 break; 11273 } 11274 11275 if (boundYMax < boundsB.min.y || boundYMin > boundsB.max.y) { 11276 continue; 11277 } 11278 11279 if (bodyAStatic && (bodyB.isStatic || bodyB.isSleeping)) { 11280 continue; 11281 } 11282 11283 if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) { 11284 continue; 11285 } 11286 11287 var partsBLength = bodyB.parts.length; 11288 11289 if (partsASingle && partsBLength === 1) { 11290 var collision = collides(bodyA, bodyB, pairs); 11291 11292 if (collision) { 11293 collisions[collisionIndex++] = collision; 11294 } 11295 } else { 11296 var partsAStart = partsALength > 1 ? 1 : 0, 11297 partsBStart = partsBLength > 1 ? 1 : 0; 11298 11299 for (var k = partsAStart; k < partsALength; k++) { 11300 var partA = bodyA.parts[k], 11301 boundsA = partA.bounds; 11302 11303 for (var z = partsBStart; z < partsBLength; z++) { 11304 var partB = bodyB.parts[z], 11305 boundsB = partB.bounds; 11306 11307 if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x 11308 || boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) { 11309 continue; 11310 } 11311 11312 var collision = collides(partA, partB, pairs); 11313 11314 if (collision) { 11315 collisions[collisionIndex++] = collision; 11316 } 11317 } 11318 } 11319 } 11320 } 11321 } 11322 11323 if (collisions.length !== collisionIndex) { 11324 collisions.length = collisionIndex; 11325 } 11326 11327 return collisions; 11328 }; 11329 11330 /** 11331 * Returns `true` if both supplied collision filters will allow a collision to occur. 11332 * See `body.collisionFilter` for more information. 11333 * @method canCollide 11334 * @param {} filterA 11335 * @param {} filterB 11336 * @return {bool} `true` if collision can occur 11337 */ 11338 Detector.canCollide = function(filterA, filterB) { 11339 if (filterA.group === filterB.group && filterA.group !== 0) 11340 return filterA.group > 0; 11341 11342 return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0; 11343 }; 11344 11345 /** 11346 * The comparison function used in the broadphase algorithm. 11347 * Returns the signed delta of the bodies bounds on the x-axis. 11348 * @private 11349 * @method _sortCompare 11350 * @param {body} bodyA 11351 * @param {body} bodyB 11352 * @return {number} The signed delta used for sorting 11353 */ 11354 Detector._compareBoundsX = function(bodyA, bodyB) { 11355 return bodyA.bounds.min.x - bodyB.bounds.min.x; 11356 }; 11357 11358 /* 11359 * 11360 * Properties Documentation 11361 * 11362 */ 11363 11364 /** 11365 * The array of `Matter.Body` between which the detector finds collisions. 11366 * 11367 * _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector. 11368 * @property bodies 11369 * @type body[] 11370 * @default [] 11371 */ 11372 11373 /** 11374 * The array of `Matter.Collision` found in the last call to `Detector.collisions` on this detector. 11375 * @property collisions 11376 * @type collision[] 11377 * @default [] 11378 */ 11379 11380 /** 11381 * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage. 11382 * @property pairs 11383 * @type {pairs|null} 11384 * @default null 11385 */ 11386 11387})(); 11388 11389 11390/***/ }), 11391/* 14 */ 11392/***/ (function(module, exports, __webpack_require__) { 11393 11394/** 11395* The `Matter.Mouse` module contains methods for creating and manipulating mouse inputs. 11396* 11397* @class Mouse 11398*/ 11399 11400var Mouse = {}; 11401 11402module.exports = Mouse; 11403 11404var Common = __webpack_require__(0); 11405 11406(function() { 11407 11408 /** 11409 * Creates a mouse input. 11410 * @method create 11411 * @param {HTMLElement} element 11412 * @return {mouse} A new mouse 11413 */ 11414 Mouse.create = function(element) { 11415 var mouse = {}; 11416 11417 if (!element) { 11418 Common.log('Mouse.create: element was undefined, defaulting to document.body', 'warn'); 11419 } 11420 11421 mouse.element = element || document.body; 11422 mouse.absolute = { x: 0, y: 0 }; 11423 mouse.position = { x: 0, y: 0 }; 11424 mouse.mousedownPosition = { x: 0, y: 0 }; 11425 mouse.mouseupPosition = { x: 0, y: 0 }; 11426 mouse.offset = { x: 0, y: 0 }; 11427 mouse.scale = { x: 1, y: 1 }; 11428 mouse.wheelDelta = 0; 11429 mouse.button = -1; 11430 mouse.pixelRatio = parseInt(mouse.element.getAttribute('data-pixel-ratio'), 10) || 1; 11431 11432 mouse.sourceEvents = { 11433 mousemove: null, 11434 mousedown: null, 11435 mouseup: null, 11436 mousewheel: null 11437 }; 11438 11439 mouse.mousemove = function(event) { 11440 var position = Mouse._getRelativeMousePosition(event, mouse.element, mouse.pixelRatio), 11441 touches = event.changedTouches; 11442 11443 if (touches) { 11444 mouse.button = 0; 11445 event.preventDefault(); 11446 } 11447 11448 mouse.absolute.x = position.x; 11449 mouse.absolute.y = position.y; 11450 mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x; 11451 mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y; 11452 mouse.sourceEvents.mousemove = event; 11453 }; 11454 11455 mouse.mousedown = function(event) { 11456 var position = Mouse._getRelativeMousePosition(event, mouse.element, mouse.pixelRatio), 11457 touches = event.changedTouches; 11458 11459 if (touches) { 11460 mouse.button = 0; 11461 event.preventDefault(); 11462 } else { 11463 mouse.button = event.button; 11464 } 11465 11466 mouse.absolute.x = position.x; 11467 mouse.absolute.y = position.y; 11468 mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x; 11469 mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y; 11470 mouse.mousedownPosition.x = mouse.position.x; 11471 mouse.mousedownPosition.y = mouse.position.y; 11472 mouse.sourceEvents.mousedown = event; 11473 }; 11474 11475 mouse.mouseup = function(event) { 11476 var position = Mouse._getRelativeMousePosition(event, mouse.element, mouse.pixelRatio), 11477 touches = event.changedTouches; 11478 11479 if (touches) { 11480 event.preventDefault(); 11481 } 11482 11483 mouse.button = -1; 11484 mouse.absolute.x = position.x; 11485 mouse.absolute.y = position.y; 11486 mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x; 11487 mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y; 11488 mouse.mouseupPosition.x = mouse.position.x; 11489 mouse.mouseupPosition.y = mouse.position.y; 11490 mouse.sourceEvents.mouseup = event; 11491 }; 11492 11493 mouse.mousewheel = function(event) { 11494 mouse.wheelDelta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail)); 11495 event.preventDefault(); 11496 mouse.sourceEvents.mousewheel = event; 11497 }; 11498 11499 Mouse.setElement(mouse, mouse.element); 11500 11501 return mouse; 11502 }; 11503 11504 /** 11505 * Sets the element the mouse is bound to (and relative to). 11506 * @method setElement 11507 * @param {mouse} mouse 11508 * @param {HTMLElement} element 11509 */ 11510 Mouse.setElement = function(mouse, element) { 11511 mouse.element = element; 11512 11513 element.addEventListener('mousemove', mouse.mousemove, { passive: true }); 11514 element.addEventListener('mousedown', mouse.mousedown, { passive: true }); 11515 element.addEventListener('mouseup', mouse.mouseup, { passive: true }); 11516 11517 element.addEventListener('wheel', mouse.mousewheel, { passive: false }); 11518 11519 element.addEventListener('touchmove', mouse.mousemove, { passive: false }); 11520 element.addEventListener('touchstart', mouse.mousedown, { passive: false }); 11521 element.addEventListener('touchend', mouse.mouseup, { passive: false }); 11522 }; 11523 11524 /** 11525 * Clears all captured source events. 11526 * @method clearSourceEvents 11527 * @param {mouse} mouse 11528 */ 11529 Mouse.clearSourceEvents = function(mouse) { 11530 mouse.sourceEvents.mousemove = null; 11531 mouse.sourceEvents.mousedown = null; 11532 mouse.sourceEvents.mouseup = null; 11533 mouse.sourceEvents.mousewheel = null; 11534 mouse.wheelDelta = 0; 11535 }; 11536 11537 /** 11538 * Sets the mouse position offset. 11539 * @method setOffset 11540 * @param {mouse} mouse 11541 * @param {vector} offset 11542 */ 11543 Mouse.setOffset = function(mouse, offset) { 11544 mouse.offset.x = offset.x; 11545 mouse.offset.y = offset.y; 11546 mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x; 11547 mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y; 11548 }; 11549 11550 /** 11551 * Sets the mouse position scale. 11552 * @method setScale 11553 * @param {mouse} mouse 11554 * @param {vector} scale 11555 */ 11556 Mouse.setScale = function(mouse, scale) { 11557 mouse.scale.x = scale.x; 11558 mouse.scale.y = scale.y; 11559 mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x; 11560 mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y; 11561 }; 11562 11563 /** 11564 * Gets the mouse position relative to an element given a screen pixel ratio. 11565 * @method _getRelativeMousePosition 11566 * @private 11567 * @param {} event 11568 * @param {} element 11569 * @param {number} pixelRatio 11570 * @return {} 11571 */ 11572 Mouse._getRelativeMousePosition = function(event, element, pixelRatio) { 11573 var elementBounds = element.getBoundingClientRect(), 11574 rootNode = (document.documentElement || document.body.parentNode || document.body), 11575 scrollX = (window.pageXOffset !== undefined) ? window.pageXOffset : rootNode.scrollLeft, 11576 scrollY = (window.pageYOffset !== undefined) ? window.pageYOffset : rootNode.scrollTop, 11577 touches = event.changedTouches, 11578 x, y; 11579 11580 if (touches) { 11581 x = touches[0].pageX - elementBounds.left - scrollX; 11582 y = touches[0].pageY - elementBounds.top - scrollY; 11583 } else { 11584 x = event.pageX - elementBounds.left - scrollX; 11585 y = event.pageY - elementBounds.top - scrollY; 11586 } 11587 11588 return { 11589 x: x / (element.clientWidth / (element.width || element.clientWidth) * pixelRatio), 11590 y: y / (element.clientHeight / (element.height || element.clientHeight) * pixelRatio) 11591 }; 11592 }; 11593 11594})(); 11595 11596 11597/***/ }), 11598/* 15 */ 11599/***/ (function(module, exports, __webpack_require__) { 11600 11601/** 11602* The `Matter.Plugin` module contains functions for registering and installing plugins on modules. 11603* 11604* @class Plugin 11605*/ 11606 11607var Plugin = {}; 11608 11609module.exports = Plugin; 11610 11611var Common = __webpack_require__(0); 11612 11613(function() { 11614 11615 Plugin._registry = {}; 11616 11617 /** 11618 * Registers a plugin object so it can be resolved later by name. 11619 * @method register 11620 * @param plugin {} The plugin to register. 11621 * @return {object} The plugin. 11622 */ 11623 Plugin.register = function(plugin) { 11624 if (!Plugin.isPlugin(plugin)) { 11625 Common.warn('Plugin.register:', Plugin.toString(plugin), 'does not implement all required fields.'); 11626 } 11627 11628 if (plugin.name in Plugin._registry) { 11629 var registered = Plugin._registry[plugin.name], 11630 pluginVersion = Plugin.versionParse(plugin.version).number, 11631 registeredVersion = Plugin.versionParse(registered.version).number; 11632 11633 if (pluginVersion > registeredVersion) { 11634 Common.warn('Plugin.register:', Plugin.toString(registered), 'was upgraded to', Plugin.toString(plugin)); 11635 Plugin._registry[plugin.name] = plugin; 11636 } else if (pluginVersion < registeredVersion) { 11637 Common.warn('Plugin.register:', Plugin.toString(registered), 'can not be downgraded to', Plugin.toString(plugin)); 11638 } else if (plugin !== registered) { 11639 Common.warn('Plugin.register:', Plugin.toString(plugin), 'is already registered to different plugin object'); 11640 } 11641 } else { 11642 Plugin._registry[plugin.name] = plugin; 11643 } 11644 11645 return plugin; 11646 }; 11647 11648 /** 11649 * Resolves a dependency to a plugin object from the registry if it exists. 11650 * The `dependency` may contain a version, but only the name matters when resolving. 11651 * @method resolve 11652 * @param dependency {string} The dependency. 11653 * @return {object} The plugin if resolved, otherwise `undefined`. 11654 */ 11655 Plugin.resolve = function(dependency) { 11656 return Plugin._registry[Plugin.dependencyParse(dependency).name]; 11657 }; 11658 11659 /** 11660 * Returns a pretty printed plugin name and version. 11661 * @method toString 11662 * @param plugin {} The plugin. 11663 * @return {string} Pretty printed plugin name and version. 11664 */ 11665 Plugin.toString = function(plugin) { 11666 return typeof plugin === 'string' ? plugin : (plugin.name || 'anonymous') + '@' + (plugin.version || plugin.range || '0.0.0'); 11667 }; 11668 11669 /** 11670 * Returns `true` if the object meets the minimum standard to be considered a plugin. 11671 * This means it must define the following properties: 11672 * - `name` 11673 * - `version` 11674 * - `install` 11675 * @method isPlugin 11676 * @param obj {} The obj to test. 11677 * @return {boolean} `true` if the object can be considered a plugin otherwise `false`. 11678 */ 11679 Plugin.isPlugin = function(obj) { 11680 return obj && obj.name && obj.version && obj.install; 11681 }; 11682 11683 /** 11684 * Returns `true` if a plugin with the given `name` been installed on `module`. 11685 * @method isUsed 11686 * @param module {} The module. 11687 * @param name {string} The plugin name. 11688 * @return {boolean} `true` if a plugin with the given `name` been installed on `module`, otherwise `false`. 11689 */ 11690 Plugin.isUsed = function(module, name) { 11691 return module.used.indexOf(name) > -1; 11692 }; 11693 11694 /** 11695 * Returns `true` if `plugin.for` is applicable to `module` by comparing against `module.name` and `module.version`. 11696 * If `plugin.for` is not specified then it is assumed to be applicable. 11697 * The value of `plugin.for` is a string of the format `'module-name'` or `'module-name@version'`. 11698 * @method isFor 11699 * @param plugin {} The plugin. 11700 * @param module {} The module. 11701 * @return {boolean} `true` if `plugin.for` is applicable to `module`, otherwise `false`. 11702 */ 11703 Plugin.isFor = function(plugin, module) { 11704 var parsed = plugin.for && Plugin.dependencyParse(plugin.for); 11705 return !plugin.for || (module.name === parsed.name && Plugin.versionSatisfies(module.version, parsed.range)); 11706 }; 11707 11708 /** 11709 * Installs the plugins by calling `plugin.install` on each plugin specified in `plugins` if passed, otherwise `module.uses`. 11710 * For installing plugins on `Matter` see the convenience function `Matter.use`. 11711 * Plugins may be specified either by their name or a reference to the plugin object. 11712 * Plugins themselves may specify further dependencies, but each plugin is installed only once. 11713 * Order is important, a topological sort is performed to find the best resulting order of installation. 11714 * This sorting attempts to satisfy every dependency's requested ordering, but may not be exact in all cases. 11715 * This function logs the resulting status of each dependency in the console, along with any warnings. 11716 * - A green tick â indicates a dependency was resolved and installed. 11717 * - An orange diamond ð¶ indicates a dependency was resolved but a warning was thrown for it or one if its dependencies. 11718 * - A red cross â indicates a dependency could not be resolved. 11719 * Avoid calling this function multiple times on the same module unless you intend to manually control installation order. 11720 * @method use 11721 * @param module {} The module install plugins on. 11722 * @param [plugins=module.uses] {} The plugins to install on module (optional, defaults to `module.uses`). 11723 */ 11724 Plugin.use = function(module, plugins) { 11725 module.uses = (module.uses || []).concat(plugins || []); 11726 11727 if (module.uses.length === 0) { 11728 Common.warn('Plugin.use:', Plugin.toString(module), 'does not specify any dependencies to install.'); 11729 return; 11730 } 11731 11732 var dependencies = Plugin.dependencies(module), 11733 sortedDependencies = Common.topologicalSort(dependencies), 11734 status = []; 11735 11736 for (var i = 0; i < sortedDependencies.length; i += 1) { 11737 if (sortedDependencies[i] === module.name) { 11738 continue; 11739 } 11740 11741 var plugin = Plugin.resolve(sortedDependencies[i]); 11742 11743 if (!plugin) { 11744 status.push('â ' + sortedDependencies[i]); 11745 continue; 11746 } 11747 11748 if (Plugin.isUsed(module, plugin.name)) { 11749 continue; 11750 } 11751 11752 if (!Plugin.isFor(plugin, module)) { 11753 Common.warn('Plugin.use:', Plugin.toString(plugin), 'is for', plugin.for, 'but installed on', Plugin.toString(module) + '.'); 11754 plugin._warned = true; 11755 } 11756 11757 if (plugin.install) { 11758 plugin.install(module); 11759 } else { 11760 Common.warn('Plugin.use:', Plugin.toString(plugin), 'does not specify an install function.'); 11761 plugin._warned = true; 11762 } 11763 11764 if (plugin._warned) { 11765 status.push('ð¶ ' + Plugin.toString(plugin)); 11766 delete plugin._warned; 11767 } else { 11768 status.push('â ' + Plugin.toString(plugin)); 11769 } 11770 11771 module.used.push(plugin.name); 11772 } 11773 11774 if (status.length > 0) { 11775 Common.info(status.join(' ')); 11776 } 11777 }; 11778 11779 /** 11780 * Recursively finds all of a module's dependencies and returns a flat dependency graph. 11781 * @method dependencies 11782 * @param module {} The module. 11783 * @return {object} A dependency graph. 11784 */ 11785 Plugin.dependencies = function(module, tracked) { 11786 var parsedBase = Plugin.dependencyParse(module), 11787 name = parsedBase.name; 11788 11789 tracked = tracked || {}; 11790 11791 if (name in tracked) { 11792 return; 11793 } 11794 11795 module = Plugin.resolve(module) || module; 11796 11797 tracked[name] = Common.map(module.uses || [], function(dependency) { 11798 if (Plugin.isPlugin(dependency)) { 11799 Plugin.register(dependency); 11800 } 11801 11802 var parsed = Plugin.dependencyParse(dependency), 11803 resolved = Plugin.resolve(dependency); 11804 11805 if (resolved && !Plugin.versionSatisfies(resolved.version, parsed.range)) { 11806 Common.warn( 11807 'Plugin.dependencies:', Plugin.toString(resolved), 'does not satisfy', 11808 Plugin.toString(parsed), 'used by', Plugin.toString(parsedBase) + '.' 11809 ); 11810 11811 resolved._warned = true; 11812 module._warned = true; 11813 } else if (!resolved) { 11814 Common.warn( 11815 'Plugin.dependencies:', Plugin.toString(dependency), 'used by', 11816 Plugin.toString(parsedBase), 'could not be resolved.' 11817 ); 11818 11819 module._warned = true; 11820 } 11821 11822 return parsed.name; 11823 }); 11824 11825 for (var i = 0; i < tracked[name].length; i += 1) { 11826 Plugin.dependencies(tracked[name][i], tracked); 11827 } 11828 11829 return tracked; 11830 }; 11831 11832 /** 11833 * Parses a dependency string into its components. 11834 * The `dependency` is a string of the format `'module-name'` or `'module-name@version'`. 11835 * See documentation for `Plugin.versionParse` for a description of the format. 11836 * This function can also handle dependencies that are already resolved (e.g. a module object). 11837 * @method dependencyParse 11838 * @param dependency {string} The dependency of the format `'module-name'` or `'module-name@version'`. 11839 * @return {object} The dependency parsed into its components. 11840 */ 11841 Plugin.dependencyParse = function(dependency) { 11842 if (Common.isString(dependency)) { 11843 var pattern = /^[\w-]+(@(\*|[\^~]?\d+\.\d+\.\d+(-[0-9A-Za-z-+]+)?))?$/; 11844 11845 if (!pattern.test(dependency)) { 11846 Common.warn('Plugin.dependencyParse:', dependency, 'is not a valid dependency string.'); 11847 } 11848 11849 return { 11850 name: dependency.split('@')[0], 11851 range: dependency.split('@')[1] || '*' 11852 }; 11853 } 11854 11855 return { 11856 name: dependency.name, 11857 range: dependency.range || dependency.version 11858 }; 11859 }; 11860 11861 /** 11862 * Parses a version string into its components. 11863 * Versions are strictly of the format `x.y.z` (as in [semver](http://semver.org/)). 11864 * Versions may optionally have a prerelease tag in the format `x.y.z-alpha`. 11865 * Ranges are a strict subset of [npm ranges](https://docs.npmjs.com/misc/semver#advanced-range-syntax). 11866 * Only the following range types are supported: 11867 * - Tilde ranges e.g. `~1.2.3` 11868 * - Caret ranges e.g. `^1.2.3` 11869 * - Greater than ranges e.g. `>1.2.3` 11870 * - Greater than or equal ranges e.g. `>=1.2.3` 11871 * - Exact version e.g. `1.2.3` 11872 * - Any version `*` 11873 * @method versionParse 11874 * @param range {string} The version string. 11875 * @return {object} The version range parsed into its components. 11876 */ 11877 Plugin.versionParse = function(range) { 11878 var pattern = /^(\*)|(\^|~|>=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-+]+)?$/; 11879 11880 if (!pattern.test(range)) { 11881 Common.warn('Plugin.versionParse:', range, 'is not a valid version or range.'); 11882 } 11883 11884 var parts = pattern.exec(range); 11885 var major = Number(parts[4]); 11886 var minor = Number(parts[5]); 11887 var patch = Number(parts[6]); 11888 11889 return { 11890 isRange: Boolean(parts[1] || parts[2]), 11891 version: parts[3], 11892 range: range, 11893 operator: parts[1] || parts[2] || '', 11894 major: major, 11895 minor: minor, 11896 patch: patch, 11897 parts: [major, minor, patch], 11898 prerelease: parts[7], 11899 number: major * 1e8 + minor * 1e4 + patch 11900 }; 11901 }; 11902 11903 /** 11904 * Returns `true` if `version` satisfies the given `range`. 11905 * See documentation for `Plugin.versionParse` for a description of the format. 11906 * If a version or range is not specified, then any version (`*`) is assumed to satisfy. 11907 * @method versionSatisfies 11908 * @param version {string} The version string. 11909 * @param range {string} The range string. 11910 * @return {boolean} `true` if `version` satisfies `range`, otherwise `false`. 11911 */ 11912 Plugin.versionSatisfies = function(version, range) { 11913 range = range || '*'; 11914 11915 var r = Plugin.versionParse(range), 11916 v = Plugin.versionParse(version); 11917 11918 if (r.isRange) { 11919 if (r.operator === '*' || version === '*') { 11920 return true; 11921 } 11922 11923 if (r.operator === '>') { 11924 return v.number > r.number; 11925 } 11926 11927 if (r.operator === '>=') { 11928 return v.number >= r.number; 11929 } 11930 11931 if (r.operator === '~') { 11932 return v.major === r.major && v.minor === r.minor && v.patch >= r.patch; 11933 } 11934 11935 if (r.operator === '^') { 11936 if (r.major > 0) { 11937 return v.major === r.major && v.number >= r.number; 11938 } 11939 11940 if (r.minor > 0) { 11941 return v.minor === r.minor && v.patch >= r.patch; 11942 } 11943 11944 return v.patch === r.patch; 11945 } 11946 } 11947 11948 return version === range || version === '*'; 11949 }; 11950 11951})(); 11952 11953 11954/***/ }), 11955/* 16 */ 11956/***/ (function(module, exports) { 11957 11958/** 11959* The `Matter.Contact` module contains methods for creating and manipulating collision contacts. 11960* 11961* @class Contact 11962*/ 11963 11964var Contact = {}; 11965 11966module.exports = Contact; 11967 11968(function() { 11969 11970 /** 11971 * Creates a new contact. 11972 * @method create 11973 * @param {vertex} [vertex] 11974 * @return {contact} A new contact 11975 */ 11976 Contact.create = function(vertex) { 11977 return { 11978 vertex: vertex, 11979 normalImpulse: 0, 11980 tangentImpulse: 0 11981 }; 11982 }; 11983 11984})(); 11985 11986 11987/***/ }), 11988/* 17 */ 11989/***/ (function(module, exports, __webpack_require__) { 11990 11991/** 11992* The `Matter.Engine` module contains methods for creating and manipulating engines. 11993* An engine is a controller that manages updating the simulation of the world. 11994* See `Matter.Runner` for an optional game loop utility. 11995* 11996* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 11997* 11998* @class Engine 11999*/ 12000 12001var Engine = {}; 12002 12003module.exports = Engine; 12004 12005var Sleeping = __webpack_require__(7); 12006var Resolver = __webpack_require__(18); 12007var Detector = __webpack_require__(13); 12008var Pairs = __webpack_require__(19); 12009var Events = __webpack_require__(5); 12010var Composite = __webpack_require__(6); 12011var Constraint = __webpack_require__(10); 12012var Common = __webpack_require__(0); 12013var Body = __webpack_require__(4); 12014 12015(function() { 12016 12017 Engine._deltaMax = 1000 / 60; 12018 12019 /** 12020 * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults. 12021 * All properties have default values, and many are pre-calculated automatically based on other properties. 12022 * See the properties section below for detailed information on what you can pass via the `options` object. 12023 * @method create 12024 * @param {object} [options] 12025 * @return {engine} engine 12026 */ 12027 Engine.create = function(options) { 12028 options = options || {}; 12029 12030 var defaults = { 12031 positionIterations: 6, 12032 velocityIterations: 4, 12033 constraintIterations: 2, 12034 enableSleeping: false, 12035 events: [], 12036 plugin: {}, 12037 gravity: { 12038 x: 0, 12039 y: 1, 12040 scale: 0.001 12041 }, 12042 timing: { 12043 timestamp: 0, 12044 timeScale: 1, 12045 lastDelta: 0, 12046 lastElapsed: 0, 12047 lastUpdatesPerFrame: 0 12048 } 12049 }; 12050 12051 var engine = Common.extend(defaults, options); 12052 12053 engine.world = options.world || Composite.create({ label: 'World' }); 12054 engine.pairs = options.pairs || Pairs.create(); 12055 engine.detector = options.detector || Detector.create(); 12056 engine.detector.pairs = engine.pairs; 12057 12058 // for temporary back compatibility only 12059 engine.grid = { buckets: [] }; 12060 engine.world.gravity = engine.gravity; 12061 engine.broadphase = engine.grid; 12062 engine.metrics = {}; 12063 12064 return engine; 12065 }; 12066 12067 /** 12068 * Moves the simulation forward in time by `delta` milliseconds. 12069 * Triggers `beforeUpdate`, `beforeSolve` and `afterUpdate` events. 12070 * Triggers `collisionStart`, `collisionActive` and `collisionEnd` events. 12071 * @method update 12072 * @param {engine} engine 12073 * @param {number} [delta=16.666] 12074 */ 12075 Engine.update = function(engine, delta) { 12076 var startTime = Common.now(); 12077 12078 var world = engine.world, 12079 detector = engine.detector, 12080 pairs = engine.pairs, 12081 timing = engine.timing, 12082 timestamp = timing.timestamp, 12083 i; 12084 12085 // warn if high delta 12086 if (delta > Engine._deltaMax) { 12087 Common.warnOnce( 12088 'Matter.Engine.update: delta argument is recommended to be less than or equal to', Engine._deltaMax.toFixed(3), 'ms.' 12089 ); 12090 } 12091 12092 delta = typeof delta !== 'undefined' ? delta : Common._baseDelta; 12093 delta *= timing.timeScale; 12094 12095 // increment timestamp 12096 timing.timestamp += delta; 12097 timing.lastDelta = delta; 12098 12099 // create an event object 12100 var event = { 12101 timestamp: timing.timestamp, 12102 delta: delta 12103 }; 12104 12105 Events.trigger(engine, 'beforeUpdate', event); 12106 12107 // get all bodies and all constraints in the world 12108 var allBodies = Composite.allBodies(world), 12109 allConstraints = Composite.allConstraints(world); 12110 12111 // if the world has changed 12112 if (world.isModified) { 12113 // update the detector bodies 12114 Detector.setBodies(detector, allBodies); 12115 12116 // reset all composite modified flags 12117 Composite.setModified(world, false, false, true); 12118 } 12119 12120 // update sleeping if enabled 12121 if (engine.enableSleeping) 12122 Sleeping.update(allBodies, delta); 12123 12124 // apply gravity to all bodies 12125 Engine._bodiesApplyGravity(allBodies, engine.gravity); 12126 12127 // update all body position and rotation by integration 12128 if (delta > 0) { 12129 Engine._bodiesUpdate(allBodies, delta); 12130 } 12131 12132 Events.trigger(engine, 'beforeSolve', event); 12133 12134 // update all constraints (first pass) 12135 Constraint.preSolveAll(allBodies); 12136 for (i = 0; i < engine.constraintIterations; i++) { 12137 Constraint.solveAll(allConstraints, delta); 12138 } 12139 Constraint.postSolveAll(allBodies); 12140 12141 // find all collisions 12142 var collisions = Detector.collisions(detector); 12143 12144 // update collision pairs 12145 Pairs.update(pairs, collisions, timestamp); 12146 12147 // wake up bodies involved in collisions 12148 if (engine.enableSleeping) 12149 Sleeping.afterCollisions(pairs.list); 12150 12151 // trigger collision events 12152 if (pairs.collisionStart.length > 0) { 12153 Events.trigger(engine, 'collisionStart', { 12154 pairs: pairs.collisionStart, 12155 timestamp: timing.timestamp, 12156 delta: delta 12157 }); 12158 } 12159 12160 // iteratively resolve position between collisions 12161 var positionDamping = Common.clamp(20 / engine.positionIterations, 0, 1); 12162 12163 Resolver.preSolvePosition(pairs.list); 12164 for (i = 0; i < engine.positionIterations; i++) { 12165 Resolver.solvePosition(pairs.list, delta, positionDamping); 12166 } 12167 Resolver.postSolvePosition(allBodies); 12168 12169 // update all constraints (second pass) 12170 Constraint.preSolveAll(allBodies); 12171 for (i = 0; i < engine.constraintIterations; i++) { 12172 Constraint.solveAll(allConstraints, delta); 12173 } 12174 Constraint.postSolveAll(allBodies); 12175 12176 // iteratively resolve velocity between collisions 12177 Resolver.preSolveVelocity(pairs.list); 12178 for (i = 0; i < engine.velocityIterations; i++) { 12179 Resolver.solveVelocity(pairs.list, delta); 12180 } 12181 12182 // update body speed and velocity properties 12183 Engine._bodiesUpdateVelocities(allBodies); 12184 12185 // trigger collision events 12186 if (pairs.collisionActive.length > 0) { 12187 Events.trigger(engine, 'collisionActive', { 12188 pairs: pairs.collisionActive, 12189 timestamp: timing.timestamp, 12190 delta: delta 12191 }); 12192 } 12193 12194 if (pairs.collisionEnd.length > 0) { 12195 Events.trigger(engine, 'collisionEnd', { 12196 pairs: pairs.collisionEnd, 12197 timestamp: timing.timestamp, 12198 delta: delta 12199 }); 12200 } 12201 12202 // clear force buffers 12203 Engine._bodiesClearForces(allBodies); 12204 12205 Events.trigger(engine, 'afterUpdate', event); 12206 12207 // log the time elapsed computing this update 12208 engine.timing.lastElapsed = Common.now() - startTime; 12209 12210 return engine; 12211 }; 12212 12213 /** 12214 * Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`. 12215 * @method merge 12216 * @param {engine} engineA 12217 * @param {engine} engineB 12218 */ 12219 Engine.merge = function(engineA, engineB) { 12220 Common.extend(engineA, engineB); 12221 12222 if (engineB.world) { 12223 engineA.world = engineB.world; 12224 12225 Engine.clear(engineA); 12226 12227 var bodies = Composite.allBodies(engineA.world); 12228 12229 for (var i = 0; i < bodies.length; i++) { 12230 var body = bodies[i]; 12231 Sleeping.set(body, false); 12232 body.id = Common.nextId(); 12233 } 12234 } 12235 }; 12236 12237 /** 12238 * Clears the engine pairs and detector. 12239 * @method clear 12240 * @param {engine} engine 12241 */ 12242 Engine.clear = function(engine) { 12243 Pairs.clear(engine.pairs); 12244 Detector.clear(engine.detector); 12245 }; 12246 12247 /** 12248 * Zeroes the `body.force` and `body.torque` force buffers. 12249 * @method _bodiesClearForces 12250 * @private 12251 * @param {body[]} bodies 12252 */ 12253 Engine._bodiesClearForces = function(bodies) { 12254 var bodiesLength = bodies.length; 12255 12256 for (var i = 0; i < bodiesLength; i++) { 12257 var body = bodies[i]; 12258 12259 // reset force buffers 12260 body.force.x = 0; 12261 body.force.y = 0; 12262 body.torque = 0; 12263 } 12264 }; 12265 12266 /** 12267 * Applies gravitational acceleration to all `bodies`. 12268 * This models a [uniform gravitational field](https://en.wikipedia.org/wiki/Gravity_of_Earth), similar to near the surface of a planet. 12269 * 12270 * @method _bodiesApplyGravity 12271 * @private 12272 * @param {body[]} bodies 12273 * @param {vector} gravity 12274 */ 12275 Engine._bodiesApplyGravity = function(bodies, gravity) { 12276 var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001, 12277 bodiesLength = bodies.length; 12278 12279 if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) { 12280 return; 12281 } 12282 12283 for (var i = 0; i < bodiesLength; i++) { 12284 var body = bodies[i]; 12285 12286 if (body.isStatic || body.isSleeping) 12287 continue; 12288 12289 // add the resultant force of gravity 12290 body.force.y += body.mass * gravity.y * gravityScale; 12291 body.force.x += body.mass * gravity.x * gravityScale; 12292 } 12293 }; 12294 12295 /** 12296 * Applies `Body.update` to all given `bodies`. 12297 * @method _bodiesUpdate 12298 * @private 12299 * @param {body[]} bodies 12300 * @param {number} delta The amount of time elapsed between updates 12301 */ 12302 Engine._bodiesUpdate = function(bodies, delta) { 12303 var bodiesLength = bodies.length; 12304 12305 for (var i = 0; i < bodiesLength; i++) { 12306 var body = bodies[i]; 12307 12308 if (body.isStatic || body.isSleeping) 12309 continue; 12310 12311 Body.update(body, delta); 12312 } 12313 }; 12314 12315 /** 12316 * Applies `Body.updateVelocities` to all given `bodies`. 12317 * @method _bodiesUpdateVelocities 12318 * @private 12319 * @param {body[]} bodies 12320 */ 12321 Engine._bodiesUpdateVelocities = function(bodies) { 12322 var bodiesLength = bodies.length; 12323 12324 for (var i = 0; i < bodiesLength; i++) { 12325 Body.updateVelocities(bodies[i]); 12326 } 12327 }; 12328 12329 /** 12330 * A deprecated alias for `Runner.run`, use `Matter.Runner.run(engine)` instead and see `Matter.Runner` for more information. 12331 * @deprecated use Matter.Runner.run(engine) instead 12332 * @method run 12333 * @param {engine} engine 12334 */ 12335 12336 /** 12337 * Fired just before an update 12338 * 12339 * @event beforeUpdate 12340 * @param {object} event An event object 12341 * @param {number} event.timestamp The engine.timing.timestamp of the event 12342 * @param {number} event.delta The delta time in milliseconds value used in the update 12343 * @param {engine} event.source The source object of the event 12344 * @param {string} event.name The name of the event 12345 */ 12346 12347 /** 12348 * Fired after bodies updated based on their velocity and forces, but before any collision detection, constraints and resolving etc. 12349 * 12350 * @event beforeSolve 12351 * @param {object} event An event object 12352 * @param {number} event.timestamp The engine.timing.timestamp of the event 12353 * @param {number} event.delta The delta time in milliseconds value used in the update 12354 * @param {engine} event.source The source object of the event 12355 * @param {string} event.name The name of the event 12356 */ 12357 12358 /** 12359 * Fired after engine update and all collision events 12360 * 12361 * @event afterUpdate 12362 * @param {object} event An event object 12363 * @param {number} event.timestamp The engine.timing.timestamp of the event 12364 * @param {number} event.delta The delta time in milliseconds value used in the update 12365 * @param {engine} event.source The source object of the event 12366 * @param {string} event.name The name of the event 12367 */ 12368 12369 /** 12370 * Fired after engine update, provides a list of all pairs that have started to collide in the current tick (if any) 12371 * 12372 * @event collisionStart 12373 * @param {object} event An event object 12374 * @param {pair[]} event.pairs List of affected pairs 12375 * @param {number} event.timestamp The engine.timing.timestamp of the event 12376 * @param {number} event.delta The delta time in milliseconds value used in the update 12377 * @param {engine} event.source The source object of the event 12378 * @param {string} event.name The name of the event 12379 */ 12380 12381 /** 12382 * Fired after engine update, provides a list of all pairs that are colliding in the current tick (if any) 12383 * 12384 * @event collisionActive 12385 * @param {object} event An event object 12386 * @param {pair[]} event.pairs List of affected pairs 12387 * @param {number} event.timestamp The engine.timing.timestamp of the event 12388 * @param {number} event.delta The delta time in milliseconds value used in the update 12389 * @param {engine} event.source The source object of the event 12390 * @param {string} event.name The name of the event 12391 */ 12392 12393 /** 12394 * Fired after engine update, provides a list of all pairs that have ended collision in the current tick (if any) 12395 * 12396 * @event collisionEnd 12397 * @param {object} event An event object 12398 * @param {pair[]} event.pairs List of affected pairs 12399 * @param {number} event.timestamp The engine.timing.timestamp of the event 12400 * @param {number} event.delta The delta time in milliseconds value used in the update 12401 * @param {engine} event.source The source object of the event 12402 * @param {string} event.name The name of the event 12403 */ 12404 12405 /* 12406 * 12407 * Properties Documentation 12408 * 12409 */ 12410 12411 /** 12412 * An integer `Number` that specifies the number of position iterations to perform each update. 12413 * The higher the value, the higher quality the simulation will be at the expense of performance. 12414 * 12415 * @property positionIterations 12416 * @type number 12417 * @default 6 12418 */ 12419 12420 /** 12421 * An integer `Number` that specifies the number of velocity iterations to perform each update. 12422 * The higher the value, the higher quality the simulation will be at the expense of performance. 12423 * 12424 * @property velocityIterations 12425 * @type number 12426 * @default 4 12427 */ 12428 12429 /** 12430 * An integer `Number` that specifies the number of constraint iterations to perform each update. 12431 * The higher the value, the higher quality the simulation will be at the expense of performance. 12432 * The default value of `2` is usually very adequate. 12433 * 12434 * @property constraintIterations 12435 * @type number 12436 * @default 2 12437 */ 12438 12439 /** 12440 * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module. 12441 * Sleeping can improve stability and performance, but often at the expense of accuracy. 12442 * 12443 * @property enableSleeping 12444 * @type boolean 12445 * @default false 12446 */ 12447 12448 /** 12449 * An `Object` containing properties regarding the timing systems of the engine. 12450 * 12451 * @property timing 12452 * @type object 12453 */ 12454 12455 /** 12456 * A `Number` that specifies the global scaling factor of time for all bodies. 12457 * A value of `0` freezes the simulation. 12458 * A value of `0.1` gives a slow-motion effect. 12459 * A value of `1.2` gives a speed-up effect. 12460 * 12461 * @property timing.timeScale 12462 * @type number 12463 * @default 1 12464 */ 12465 12466 /** 12467 * A `Number` that specifies the current simulation-time in milliseconds starting from `0`. 12468 * It is incremented on every `Engine.update` by the given `delta` argument. 12469 * 12470 * @property timing.timestamp 12471 * @type number 12472 * @default 0 12473 */ 12474 12475 /** 12476 * A `Number` that represents the total execution time elapsed during the last `Engine.update` in milliseconds. 12477 * It is updated by timing from the start of the last `Engine.update` call until it ends. 12478 * 12479 * This value will also include the total execution time of all event handlers directly or indirectly triggered by the engine update. 12480 * 12481 * @property timing.lastElapsed 12482 * @type number 12483 * @default 0 12484 */ 12485 12486 /** 12487 * A `Number` that represents the `delta` value used in the last engine update. 12488 * 12489 * @property timing.lastDelta 12490 * @type number 12491 * @default 0 12492 */ 12493 12494 /** 12495 * A `Matter.Detector` instance. 12496 * 12497 * @property detector 12498 * @type detector 12499 * @default a Matter.Detector instance 12500 */ 12501 12502 /** 12503 * A `Matter.Grid` instance. 12504 * 12505 * @deprecated replaced by `engine.detector` 12506 * @property grid 12507 * @type grid 12508 * @default a Matter.Grid instance 12509 */ 12510 12511 /** 12512 * Replaced by and now alias for `engine.grid`. 12513 * 12514 * @deprecated replaced by `engine.detector` 12515 * @property broadphase 12516 * @type grid 12517 * @default a Matter.Grid instance 12518 */ 12519 12520 /** 12521 * The root `Matter.Composite` instance that will contain all bodies, constraints and other composites to be simulated by this engine. 12522 * 12523 * @property world 12524 * @type composite 12525 * @default a Matter.Composite instance 12526 */ 12527 12528 /** 12529 * An object reserved for storing plugin-specific properties. 12530 * 12531 * @property plugin 12532 * @type {} 12533 */ 12534 12535 /** 12536 * An optional gravitational acceleration applied to all bodies in `engine.world` on every update. 12537 * 12538 * This models a [uniform gravitational field](https://en.wikipedia.org/wiki/Gravity_of_Earth), similar to near the surface of a planet. For gravity in other contexts, disable this and apply forces as needed. 12539 * 12540 * To disable set the `scale` component to `0`. 12541 * 12542 * This is split into three components for ease of use: 12543 * a normalised direction (`x` and `y`) and magnitude (`scale`). 12544 * 12545 * @property gravity 12546 * @type object 12547 */ 12548 12549 /** 12550 * The gravitational direction normal `x` component, to be multiplied by `gravity.scale`. 12551 * 12552 * @property gravity.x 12553 * @type object 12554 * @default 0 12555 */ 12556 12557 /** 12558 * The gravitational direction normal `y` component, to be multiplied by `gravity.scale`. 12559 * 12560 * @property gravity.y 12561 * @type object 12562 * @default 1 12563 */ 12564 12565 /** 12566 * The magnitude of the gravitational acceleration. 12567 * 12568 * @property gravity.scale 12569 * @type object 12570 * @default 0.001 12571 */ 12572 12573})(); 12574 12575 12576/***/ }), 12577/* 18 */ 12578/***/ (function(module, exports, __webpack_require__) { 12579 12580/** 12581* The `Matter.Resolver` module contains methods for resolving collision pairs. 12582* 12583* @class Resolver 12584*/ 12585 12586var Resolver = {}; 12587 12588module.exports = Resolver; 12589 12590var Vertices = __webpack_require__(3); 12591var Common = __webpack_require__(0); 12592var Bounds = __webpack_require__(1); 12593 12594(function() { 12595 12596 Resolver._restingThresh = 2; 12597 Resolver._restingThreshTangent = Math.sqrt(6); 12598 Resolver._positionDampen = 0.9; 12599 Resolver._positionWarming = 0.8; 12600 Resolver._frictionNormalMultiplier = 5; 12601 Resolver._frictionMaxStatic = Number.MAX_VALUE; 12602 12603 /** 12604 * Prepare pairs for position solving. 12605 * @method preSolvePosition 12606 * @param {pair[]} pairs 12607 */ 12608 Resolver.preSolvePosition = function(pairs) { 12609 var i, 12610 pair, 12611 contactCount, 12612 pairsLength = pairs.length; 12613 12614 // find total contacts on each body 12615 for (i = 0; i < pairsLength; i++) { 12616 pair = pairs[i]; 12617 12618 if (!pair.isActive) 12619 continue; 12620 12621 contactCount = pair.contactCount; 12622 pair.collision.parentA.totalContacts += contactCount; 12623 pair.collision.parentB.totalContacts += contactCount; 12624 } 12625 }; 12626 12627 /** 12628 * Find a solution for pair positions. 12629 * @method solvePosition 12630 * @param {pair[]} pairs 12631 * @param {number} delta 12632 * @param {number} [damping=1] 12633 */ 12634 Resolver.solvePosition = function(pairs, delta, damping) { 12635 var i, 12636 pair, 12637 collision, 12638 bodyA, 12639 bodyB, 12640 normal, 12641 contactShare, 12642 positionImpulse, 12643 positionDampen = Resolver._positionDampen * (damping || 1), 12644 slopDampen = Common.clamp(delta / Common._baseDelta, 0, 1), 12645 pairsLength = pairs.length; 12646 12647 // find impulses required to resolve penetration 12648 for (i = 0; i < pairsLength; i++) { 12649 pair = pairs[i]; 12650 12651 if (!pair.isActive || pair.isSensor) 12652 continue; 12653 12654 collision = pair.collision; 12655 bodyA = collision.parentA; 12656 bodyB = collision.parentB; 12657 normal = collision.normal; 12658 12659 // get current separation between body edges involved in collision 12660 pair.separation = 12661 collision.depth + normal.x * (bodyB.positionImpulse.x - bodyA.positionImpulse.x) 12662 + normal.y * (bodyB.positionImpulse.y - bodyA.positionImpulse.y); 12663 } 12664 12665 for (i = 0; i < pairsLength; i++) { 12666 pair = pairs[i]; 12667 12668 if (!pair.isActive || pair.isSensor) 12669 continue; 12670 12671 collision = pair.collision; 12672 bodyA = collision.parentA; 12673 bodyB = collision.parentB; 12674 normal = collision.normal; 12675 positionImpulse = pair.separation - pair.slop * slopDampen; 12676 12677 if (bodyA.isStatic || bodyB.isStatic) 12678 positionImpulse *= 2; 12679 12680 if (!(bodyA.isStatic || bodyA.isSleeping)) { 12681 contactShare = positionDampen / bodyA.totalContacts; 12682 bodyA.positionImpulse.x += normal.x * positionImpulse * contactShare; 12683 bodyA.positionImpulse.y += normal.y * positionImpulse * contactShare; 12684 } 12685 12686 if (!(bodyB.isStatic || bodyB.isSleeping)) { 12687 contactShare = positionDampen / bodyB.totalContacts; 12688 bodyB.positionImpulse.x -= normal.x * positionImpulse * contactShare; 12689 bodyB.positionImpulse.y -= normal.y * positionImpulse * contactShare; 12690 } 12691 } 12692 }; 12693 12694 /** 12695 * Apply position resolution. 12696 * @method postSolvePosition 12697 * @param {body[]} bodies 12698 */ 12699 Resolver.postSolvePosition = function(bodies) { 12700 var positionWarming = Resolver._positionWarming, 12701 bodiesLength = bodies.length, 12702 verticesTranslate = Vertices.translate, 12703 boundsUpdate = Bounds.update; 12704 12705 for (var i = 0; i < bodiesLength; i++) { 12706 var body = bodies[i], 12707 positionImpulse = body.positionImpulse, 12708 positionImpulseX = positionImpulse.x, 12709 positionImpulseY = positionImpulse.y, 12710 velocity = body.velocity; 12711 12712 // reset contact count 12713 body.totalContacts = 0; 12714 12715 if (positionImpulseX !== 0 || positionImpulseY !== 0) { 12716 // update body geometry 12717 for (var j = 0; j < body.parts.length; j++) { 12718 var part = body.parts[j]; 12719 verticesTranslate(part.vertices, positionImpulse); 12720 boundsUpdate(part.bounds, part.vertices, velocity); 12721 part.position.x += positionImpulseX; 12722 part.position.y += positionImpulseY; 12723 } 12724 12725 // move the body without changing velocity 12726 body.positionPrev.x += positionImpulseX; 12727 body.positionPrev.y += positionImpulseY; 12728 12729 if (positionImpulseX * velocity.x + positionImpulseY * velocity.y < 0) { 12730 // reset cached impulse if the body has velocity along it 12731 positionImpulse.x = 0; 12732 positionImpulse.y = 0; 12733 } else { 12734 // warm the next iteration 12735 positionImpulse.x *= positionWarming; 12736 positionImpulse.y *= positionWarming; 12737 } 12738 } 12739 } 12740 }; 12741 12742 /** 12743 * Prepare pairs for velocity solving. 12744 * @method preSolveVelocity 12745 * @param {pair[]} pairs 12746 */ 12747 Resolver.preSolveVelocity = function(pairs) { 12748 var pairsLength = pairs.length, 12749 i, 12750 j; 12751 12752 for (i = 0; i < pairsLength; i++) { 12753 var pair = pairs[i]; 12754 12755 if (!pair.isActive || pair.isSensor) 12756 continue; 12757 12758 var contacts = pair.contacts, 12759 contactCount = pair.contactCount, 12760 collision = pair.collision, 12761 bodyA = collision.parentA, 12762 bodyB = collision.parentB, 12763 normal = collision.normal, 12764 tangent = collision.tangent; 12765 12766 // resolve each contact 12767 for (j = 0; j < contactCount; j++) { 12768 var contact = contacts[j], 12769 contactVertex = contact.vertex, 12770 normalImpulse = contact.normalImpulse, 12771 tangentImpulse = contact.tangentImpulse; 12772 12773 if (normalImpulse !== 0 || tangentImpulse !== 0) { 12774 // total impulse from contact 12775 var impulseX = normal.x * normalImpulse + tangent.x * tangentImpulse, 12776 impulseY = normal.y * normalImpulse + tangent.y * tangentImpulse; 12777 12778 // apply impulse from contact 12779 if (!(bodyA.isStatic || bodyA.isSleeping)) { 12780 bodyA.positionPrev.x += impulseX * bodyA.inverseMass; 12781 bodyA.positionPrev.y += impulseY * bodyA.inverseMass; 12782 bodyA.anglePrev += bodyA.inverseInertia * ( 12783 (contactVertex.x - bodyA.position.x) * impulseY 12784 - (contactVertex.y - bodyA.position.y) * impulseX 12785 ); 12786 } 12787 12788 if (!(bodyB.isStatic || bodyB.isSleeping)) { 12789 bodyB.positionPrev.x -= impulseX * bodyB.inverseMass; 12790 bodyB.positionPrev.y -= impulseY * bodyB.inverseMass; 12791 bodyB.anglePrev -= bodyB.inverseInertia * ( 12792 (contactVertex.x - bodyB.position.x) * impulseY 12793 - (contactVertex.y - bodyB.position.y) * impulseX 12794 ); 12795 } 12796 } 12797 } 12798 } 12799 }; 12800 12801 /** 12802 * Find a solution for pair velocities. 12803 * @method solveVelocity 12804 * @param {pair[]} pairs 12805 * @param {number} delta 12806 */ 12807 Resolver.solveVelocity = function(pairs, delta) { 12808 var timeScale = delta / Common._baseDelta, 12809 timeScaleSquared = timeScale * timeScale, 12810 timeScaleCubed = timeScaleSquared * timeScale, 12811 restingThresh = -Resolver._restingThresh * timeScale, 12812 restingThreshTangent = Resolver._restingThreshTangent, 12813 frictionNormalMultiplier = Resolver._frictionNormalMultiplier * timeScale, 12814 frictionMaxStatic = Resolver._frictionMaxStatic, 12815 pairsLength = pairs.length, 12816 tangentImpulse, 12817 maxFriction, 12818 i, 12819 j; 12820 12821 for (i = 0; i < pairsLength; i++) { 12822 var pair = pairs[i]; 12823 12824 if (!pair.isActive || pair.isSensor) 12825 continue; 12826 12827 var collision = pair.collision, 12828 bodyA = collision.parentA, 12829 bodyB = collision.parentB, 12830 normalX = collision.normal.x, 12831 normalY = collision.normal.y, 12832 tangentX = collision.tangent.x, 12833 tangentY = collision.tangent.y, 12834 inverseMassTotal = pair.inverseMass, 12835 friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier, 12836 contacts = pair.contacts, 12837 contactCount = pair.contactCount, 12838 contactShare = 1 / contactCount; 12839 12840 // get body velocities 12841 var bodyAVelocityX = bodyA.position.x - bodyA.positionPrev.x, 12842 bodyAVelocityY = bodyA.position.y - bodyA.positionPrev.y, 12843 bodyAAngularVelocity = bodyA.angle - bodyA.anglePrev, 12844 bodyBVelocityX = bodyB.position.x - bodyB.positionPrev.x, 12845 bodyBVelocityY = bodyB.position.y - bodyB.positionPrev.y, 12846 bodyBAngularVelocity = bodyB.angle - bodyB.anglePrev; 12847 12848 // resolve each contact 12849 for (j = 0; j < contactCount; j++) { 12850 var contact = contacts[j], 12851 contactVertex = contact.vertex; 12852 12853 var offsetAX = contactVertex.x - bodyA.position.x, 12854 offsetAY = contactVertex.y - bodyA.position.y, 12855 offsetBX = contactVertex.x - bodyB.position.x, 12856 offsetBY = contactVertex.y - bodyB.position.y; 12857 12858 var velocityPointAX = bodyAVelocityX - offsetAY * bodyAAngularVelocity, 12859 velocityPointAY = bodyAVelocityY + offsetAX * bodyAAngularVelocity, 12860 velocityPointBX = bodyBVelocityX - offsetBY * bodyBAngularVelocity, 12861 velocityPointBY = bodyBVelocityY + offsetBX * bodyBAngularVelocity; 12862 12863 var relativeVelocityX = velocityPointAX - velocityPointBX, 12864 relativeVelocityY = velocityPointAY - velocityPointBY; 12865 12866 var normalVelocity = normalX * relativeVelocityX + normalY * relativeVelocityY, 12867 tangentVelocity = tangentX * relativeVelocityX + tangentY * relativeVelocityY; 12868 12869 // coulomb friction 12870 var normalOverlap = pair.separation + normalVelocity; 12871 var normalForce = Math.min(normalOverlap, 1); 12872 normalForce = normalOverlap < 0 ? 0 : normalForce; 12873 12874 var frictionLimit = normalForce * friction; 12875 12876 if (tangentVelocity < -frictionLimit || tangentVelocity > frictionLimit) { 12877 maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity); 12878 tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScaleCubed; 12879 12880 if (tangentImpulse < -maxFriction) { 12881 tangentImpulse = -maxFriction; 12882 } else if (tangentImpulse > maxFriction) { 12883 tangentImpulse = maxFriction; 12884 } 12885 } else { 12886 tangentImpulse = tangentVelocity; 12887 maxFriction = frictionMaxStatic; 12888 } 12889 12890 // account for mass, inertia and contact offset 12891 var oAcN = offsetAX * normalY - offsetAY * normalX, 12892 oBcN = offsetBX * normalY - offsetBY * normalX, 12893 share = contactShare / (inverseMassTotal + bodyA.inverseInertia * oAcN * oAcN + bodyB.inverseInertia * oBcN * oBcN); 12894 12895 // raw impulses 12896 var normalImpulse = (1 + pair.restitution) * normalVelocity * share; 12897 tangentImpulse *= share; 12898 12899 // handle high velocity and resting collisions separately 12900 if (normalVelocity < restingThresh) { 12901 // high normal velocity so clear cached contact normal impulse 12902 contact.normalImpulse = 0; 12903 } else { 12904 // solve resting collision constraints using Erin Catto's method (GDC08) 12905 // impulse constraint tends to 0 12906 var contactNormalImpulse = contact.normalImpulse; 12907 contact.normalImpulse += normalImpulse; 12908 if (contact.normalImpulse > 0) contact.normalImpulse = 0; 12909 normalImpulse = contact.normalImpulse - contactNormalImpulse; 12910 } 12911 12912 // handle high velocity and resting collisions separately 12913 if (tangentVelocity < -restingThreshTangent || tangentVelocity > restingThreshTangent) { 12914 // high tangent velocity so clear cached contact tangent impulse 12915 contact.tangentImpulse = 0; 12916 } else { 12917 // solve resting collision constraints using Erin Catto's method (GDC08) 12918 // tangent impulse tends to -tangentSpeed or +tangentSpeed 12919 var contactTangentImpulse = contact.tangentImpulse; 12920 contact.tangentImpulse += tangentImpulse; 12921 if (contact.tangentImpulse < -maxFriction) contact.tangentImpulse = -maxFriction; 12922 if (contact.tangentImpulse > maxFriction) contact.tangentImpulse = maxFriction; 12923 tangentImpulse = contact.tangentImpulse - contactTangentImpulse; 12924 } 12925 12926 // total impulse from contact 12927 var impulseX = normalX * normalImpulse + tangentX * tangentImpulse, 12928 impulseY = normalY * normalImpulse + tangentY * tangentImpulse; 12929 12930 // apply impulse from contact 12931 if (!(bodyA.isStatic || bodyA.isSleeping)) { 12932 bodyA.positionPrev.x += impulseX * bodyA.inverseMass; 12933 bodyA.positionPrev.y += impulseY * bodyA.inverseMass; 12934 bodyA.anglePrev += (offsetAX * impulseY - offsetAY * impulseX) * bodyA.inverseInertia; 12935 } 12936 12937 if (!(bodyB.isStatic || bodyB.isSleeping)) { 12938 bodyB.positionPrev.x -= impulseX * bodyB.inverseMass; 12939 bodyB.positionPrev.y -= impulseY * bodyB.inverseMass; 12940 bodyB.anglePrev -= (offsetBX * impulseY - offsetBY * impulseX) * bodyB.inverseInertia; 12941 } 12942 } 12943 } 12944 }; 12945 12946})(); 12947 12948 12949/***/ }), 12950/* 19 */ 12951/***/ (function(module, exports, __webpack_require__) { 12952 12953/** 12954* The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets. 12955* 12956* @class Pairs 12957*/ 12958 12959var Pairs = {}; 12960 12961module.exports = Pairs; 12962 12963var Pair = __webpack_require__(9); 12964var Common = __webpack_require__(0); 12965 12966(function() { 12967 12968 /** 12969 * Creates a new pairs structure. 12970 * @method create 12971 * @param {object} options 12972 * @return {pairs} A new pairs structure 12973 */ 12974 Pairs.create = function(options) { 12975 return Common.extend({ 12976 table: {}, 12977 list: [], 12978 collisionStart: [], 12979 collisionActive: [], 12980 collisionEnd: [] 12981 }, options); 12982 }; 12983 12984 /** 12985 * Updates pairs given a list of collisions. 12986 * @method update 12987 * @param {object} pairs 12988 * @param {collision[]} collisions 12989 * @param {number} timestamp 12990 */ 12991 Pairs.update = function(pairs, collisions, timestamp) { 12992 var pairUpdate = Pair.update, 12993 pairCreate = Pair.create, 12994 pairSetActive = Pair.setActive, 12995 pairsTable = pairs.table, 12996 pairsList = pairs.list, 12997 pairsListLength = pairsList.length, 12998 pairsListIndex = pairsListLength, 12999 collisionStart = pairs.collisionStart, 13000 collisionEnd = pairs.collisionEnd, 13001 collisionActive = pairs.collisionActive, 13002 collisionsLength = collisions.length, 13003 collisionStartIndex = 0, 13004 collisionEndIndex = 0, 13005 collisionActiveIndex = 0, 13006 collision, 13007 pair, 13008 i; 13009 13010 for (i = 0; i < collisionsLength; i++) { 13011 collision = collisions[i]; 13012 pair = collision.pair; 13013 13014 if (pair) { 13015 // pair already exists (but may or may not be active) 13016 if (pair.isActive) { 13017 // pair exists and is active 13018 collisionActive[collisionActiveIndex++] = pair; 13019 } 13020 13021 // update the pair 13022 pairUpdate(pair, collision, timestamp); 13023 } else { 13024 // pair did not exist, create a new pair 13025 pair = pairCreate(collision, timestamp); 13026 pairsTable[pair.id] = pair; 13027 13028 // add the new pair 13029 collisionStart[collisionStartIndex++] = pair; 13030 pairsList[pairsListIndex++] = pair; 13031 } 13032 } 13033 13034 // find pairs that are no longer active 13035 pairsListIndex = 0; 13036 pairsListLength = pairsList.length; 13037 13038 for (i = 0; i < pairsListLength; i++) { 13039 pair = pairsList[i]; 13040 13041 // pair is active if updated this timestep 13042 if (pair.timeUpdated >= timestamp) { 13043 // keep active pairs 13044 pairsList[pairsListIndex++] = pair; 13045 } else { 13046 pairSetActive(pair, false, timestamp); 13047 13048 // keep inactive pairs if both bodies may be sleeping 13049 if (pair.collision.bodyA.sleepCounter > 0 && pair.collision.bodyB.sleepCounter > 0) { 13050 pairsList[pairsListIndex++] = pair; 13051 } else { 13052 // remove inactive pairs if either body awake 13053 collisionEnd[collisionEndIndex++] = pair; 13054 delete pairsTable[pair.id]; 13055 } 13056 } 13057 } 13058 13059 // update array lengths if changed 13060 if (pairsList.length !== pairsListIndex) { 13061 pairsList.length = pairsListIndex; 13062 } 13063 13064 if (collisionStart.length !== collisionStartIndex) { 13065 collisionStart.length = collisionStartIndex; 13066 } 13067 13068 if (collisionEnd.length !== collisionEndIndex) { 13069 collisionEnd.length = collisionEndIndex; 13070 } 13071 13072 if (collisionActive.length !== collisionActiveIndex) { 13073 collisionActive.length = collisionActiveIndex; 13074 } 13075 }; 13076 13077 /** 13078 * Clears the given pairs structure. 13079 * @method clear 13080 * @param {pairs} pairs 13081 * @return {pairs} pairs 13082 */ 13083 Pairs.clear = function(pairs) { 13084 pairs.table = {}; 13085 pairs.list.length = 0; 13086 pairs.collisionStart.length = 0; 13087 pairs.collisionActive.length = 0; 13088 pairs.collisionEnd.length = 0; 13089 return pairs; 13090 }; 13091 13092})(); 13093 13094 13095/***/ }), 13096/* 20 */ 13097/***/ (function(module, exports, __webpack_require__) { 13098 13099var Matter = module.exports = __webpack_require__(21);
vendor: 2,660 bytes, lines 13099-13189
13099 13100 13101Matter.Axes = __webpack_require__(11); 13102Matter.Bodies = __webpack_require__(12); 13103Matter.Body = __webpack_require__(4); 13104Matter.Bounds = __webpack_require__(1); 13105Matter.Collision = __webpack_require__(8); 13106Matter.Common = __webpack_require__(0); 13107Matter.Composite = __webpack_require__(6); 13108Matter.Composites = __webpack_require__(22); 13109Matter.Constraint = __webpack_require__(10); 13110Matter.Contact = __webpack_require__(16); 13111Matter.Detector = __webpack_require__(13); 13112Matter.Engine = __webpack_require__(17); 13113Matter.Events = __webpack_require__(5); 13114Matter.Grid = __webpack_require__(23); 13115Matter.Mouse = __webpack_require__(14); 13116Matter.MouseConstraint = __webpack_require__(24); 13117Matter.Pair = __webpack_require__(9); 13118Matter.Pairs = __webpack_require__(19); 13119Matter.Plugin = __webpack_require__(15); 13120Matter.Query = __webpack_require__(25); 13121Matter.Render = __webpack_require__(26); 13122Matter.Resolver = __webpack_require__(18); 13123Matter.Runner = __webpack_require__(27); 13124Matter.SAT = __webpack_require__(28); 13125Matter.Sleeping = __webpack_require__(7); 13126Matter.Svg = __webpack_require__(29); 13127Matter.Vector = __webpack_require__(2); 13128Matter.Vertices = __webpack_require__(3); 13129Matter.World = __webpack_require__(30); 13130 13131// temporary back compatibility 13132Matter.Engine.run = Matter.Runner.run; 13133Matter.Common.deprecated(Matter.Engine, 'run', 'Engine.run ⤠use Matter.Runner.run(engine) instead'); 13134 13135 13136/***/ }), 13137/* 21 */ 13138/***/ (function(module, exports, __webpack_require__) { 13139 13140/** 13141* The `Matter` module is the top level namespace. It also includes a function for installing plugins on top of the library. 13142* 13143* @class Matter 13144*/ 13145 13146var Matter = {}; 13147 13148module.exports = Matter; 13149 13150var Plugin = __webpack_require__(15); 13151var Common = __webpack_require__(0); 13152 13153(function() { 13154 13155 /** 13156 * The library name. 13157 * @property name 13158 * @readOnly 13159 * @type {String} 13160 */ 13161 Matter.name = 'matter-js'; 13162 13163 /** 13164 * The library version. 13165 * @property version 13166 * @readOnly 13167 * @type {String} 13168 */ 13169 Matter.version = true ? "0.20.0" : undefined; 13170 13171 /** 13172 * A list of plugin dependencies to be installed. These are normally set and installed through `Matter.use`. 13173 * Alternatively you may set `Matter.uses` manually and install them by calling `Plugin.use(Matter)`. 13174 * @property uses 13175 * @type {Array} 13176 */ 13177 Matter.uses = []; 13178 13179 /** 13180 * The plugins that have been installed through `Matter.Plugin.install`. Read only. 13181 * @property used 13182 * @readOnly 13183 * @type {Array} 13184 */ 13185 Matter.used = []; 13186 13187 /** 13188 * Installs the given plugins on the `Matter` namespace. 13189 * This is a short-hand for `Plugin.use`, see it for more information.
13190 * Call this function once at the start of your code, with all of the plugins you wish to install as arguments. 13191 * Avoid calling this function multiple times unless you intend to manually control installation order. 13192 * @method use 13193 * @param ...plugin {Function} The plugin(s) to install on `base` (multi-argument). 13194 */ 13195 Matter.use = function() { 13196 Plugin.use(Matter, Array.prototype.slice.call(arguments)); 13197 }; 13198 13199 /** 13200 * Chains a function to excute before the original function on the given `path` relative to `Matter`. 13201 * See also docs for `Common.chain`. 13202 * @method before 13203 * @param {string} path The path relative to `Matter` 13204 * @param {function} func The function to chain before the original 13205 * @return {function} The chained function that replaced the original 13206 */ 13207 Matter.before = function(path, func) { 13208 path = path.replace(/^Matter./, ''); 13209 return Common.chainPathBefore(Matter, path, func); 13210 }; 13211 13212 /** 13213 * Chains a function to excute after the original function on the given `path` relative to `Matter`. 13214 * See also docs for `Common.chain`. 13215 * @method after 13216 * @param {string} path The path relative to `Matter` 13217 * @param {function} func The function to chain after the original 13218 * @return {function} The chained function that replaced the original 13219 */ 13220 Matter.after = function(path, func) { 13221 path = path.replace(/^Matter./, ''); 13222 return Common.chainPathAfter(Matter, path, func); 13223 }; 13224 13225})();
vendor: 122,435 bytes, lines 13225-17001
13225 13226 13227 13228/***/ }), 13229/* 22 */ 13230/***/ (function(module, exports, __webpack_require__) { 13231 13232/** 13233* The `Matter.Composites` module contains factory methods for creating composite bodies 13234* with commonly used configurations (such as stacks and chains). 13235* 13236* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 13237* 13238* @class Composites 13239*/ 13240 13241var Composites = {}; 13242 13243module.exports = Composites; 13244 13245var Composite = __webpack_require__(6); 13246var Constraint = __webpack_require__(10); 13247var Common = __webpack_require__(0); 13248var Body = __webpack_require__(4); 13249var Bodies = __webpack_require__(12); 13250var deprecated = Common.deprecated; 13251 13252(function() { 13253 13254 /** 13255 * Create a new composite containing bodies created in the callback in a grid arrangement. 13256 * This function uses the body's bounds to prevent overlaps. 13257 * @method stack 13258 * @param {number} x Starting position in X. 13259 * @param {number} y Starting position in Y. 13260 * @param {number} columns 13261 * @param {number} rows 13262 * @param {number} columnGap 13263 * @param {number} rowGap 13264 * @param {function} callback 13265 * @return {composite} A new composite containing objects created in the callback 13266 */ 13267 Composites.stack = function(x, y, columns, rows, columnGap, rowGap, callback) { 13268 var stack = Composite.create({ label: 'Stack' }), 13269 currentX = x, 13270 currentY = y, 13271 lastBody, 13272 i = 0; 13273 13274 for (var row = 0; row < rows; row++) { 13275 var maxHeight = 0; 13276 13277 for (var column = 0; column < columns; column++) { 13278 var body = callback(currentX, currentY, column, row, lastBody, i); 13279 13280 if (body) { 13281 var bodyHeight = body.bounds.max.y - body.bounds.min.y, 13282 bodyWidth = body.bounds.max.x - body.bounds.min.x; 13283 13284 if (bodyHeight > maxHeight) 13285 maxHeight = bodyHeight; 13286 13287 Body.translate(body, { x: bodyWidth * 0.5, y: bodyHeight * 0.5 }); 13288 13289 currentX = body.bounds.max.x + columnGap; 13290 13291 Composite.addBody(stack, body); 13292 13293 lastBody = body; 13294 i += 1; 13295 } else { 13296 currentX += columnGap; 13297 } 13298 } 13299 13300 currentY += maxHeight + rowGap; 13301 currentX = x; 13302 } 13303 13304 return stack; 13305 }; 13306 13307 /** 13308 * Chains all bodies in the given composite together using constraints. 13309 * @method chain 13310 * @param {composite} composite 13311 * @param {number} xOffsetA 13312 * @param {number} yOffsetA 13313 * @param {number} xOffsetB 13314 * @param {number} yOffsetB 13315 * @param {object} options 13316 * @return {composite} A new composite containing objects chained together with constraints 13317 */ 13318 Composites.chain = function(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options) { 13319 var bodies = composite.bodies; 13320 13321 for (var i = 1; i < bodies.length; i++) { 13322 var bodyA = bodies[i - 1], 13323 bodyB = bodies[i], 13324 bodyAHeight = bodyA.bounds.max.y - bodyA.bounds.min.y, 13325 bodyAWidth = bodyA.bounds.max.x - bodyA.bounds.min.x, 13326 bodyBHeight = bodyB.bounds.max.y - bodyB.bounds.min.y, 13327 bodyBWidth = bodyB.bounds.max.x - bodyB.bounds.min.x; 13328 13329 var defaults = { 13330 bodyA: bodyA, 13331 pointA: { x: bodyAWidth * xOffsetA, y: bodyAHeight * yOffsetA }, 13332 bodyB: bodyB, 13333 pointB: { x: bodyBWidth * xOffsetB, y: bodyBHeight * yOffsetB } 13334 }; 13335 13336 var constraint = Common.extend(defaults, options); 13337 13338 Composite.addConstraint(composite, Constraint.create(constraint)); 13339 } 13340 13341 composite.label += ' Chain'; 13342 13343 return composite; 13344 }; 13345 13346 /** 13347 * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces. 13348 * @method mesh 13349 * @param {composite} composite 13350 * @param {number} columns 13351 * @param {number} rows 13352 * @param {boolean} crossBrace 13353 * @param {object} options 13354 * @return {composite} The composite containing objects meshed together with constraints 13355 */ 13356 Composites.mesh = function(composite, columns, rows, crossBrace, options) { 13357 var bodies = composite.bodies, 13358 row, 13359 col, 13360 bodyA, 13361 bodyB, 13362 bodyC; 13363 13364 for (row = 0; row < rows; row++) { 13365 for (col = 1; col < columns; col++) { 13366 bodyA = bodies[(col - 1) + (row * columns)]; 13367 bodyB = bodies[col + (row * columns)]; 13368 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options))); 13369 } 13370 13371 if (row > 0) { 13372 for (col = 0; col < columns; col++) { 13373 bodyA = bodies[col + ((row - 1) * columns)]; 13374 bodyB = bodies[col + (row * columns)]; 13375 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options))); 13376 13377 if (crossBrace && col > 0) { 13378 bodyC = bodies[(col - 1) + ((row - 1) * columns)]; 13379 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options))); 13380 } 13381 13382 if (crossBrace && col < columns - 1) { 13383 bodyC = bodies[(col + 1) + ((row - 1) * columns)]; 13384 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options))); 13385 } 13386 } 13387 } 13388 } 13389 13390 composite.label += ' Mesh'; 13391 13392 return composite; 13393 }; 13394 13395 /** 13396 * Create a new composite containing bodies created in the callback in a pyramid arrangement. 13397 * This function uses the body's bounds to prevent overlaps. 13398 * @method pyramid 13399 * @param {number} x Starting position in X. 13400 * @param {number} y Starting position in Y. 13401 * @param {number} columns 13402 * @param {number} rows 13403 * @param {number} columnGap 13404 * @param {number} rowGap 13405 * @param {function} callback 13406 * @return {composite} A new composite containing objects created in the callback 13407 */ 13408 Composites.pyramid = function(x, y, columns, rows, columnGap, rowGap, callback) { 13409 return Composites.stack(x, y, columns, rows, columnGap, rowGap, function(stackX, stackY, column, row, lastBody, i) { 13410 var actualRows = Math.min(rows, Math.ceil(columns / 2)), 13411 lastBodyWidth = lastBody ? lastBody.bounds.max.x - lastBody.bounds.min.x : 0; 13412 13413 if (row > actualRows) 13414 return; 13415 13416 // reverse row order 13417 row = actualRows - row; 13418 13419 var start = row, 13420 end = columns - 1 - row; 13421 13422 if (column < start || column > end) 13423 return; 13424 13425 // retroactively fix the first body's position, since width was unknown 13426 if (i === 1) { 13427 Body.translate(lastBody, { x: (column + (columns % 2 === 1 ? 1 : -1)) * lastBodyWidth, y: 0 }); 13428 } 13429 13430 var xOffset = lastBody ? column * lastBodyWidth : 0; 13431 13432 return callback(x + xOffset + column * columnGap, stackY, column, row, lastBody, i); 13433 }); 13434 }; 13435 13436 /** 13437 * This has now moved to the [newtonsCradle example](https://github.com/liabru/matter-js/blob/master/examples/newtonsCradle.js), follow that instead as this function is deprecated here. 13438 * @deprecated moved to newtonsCradle example 13439 * @method newtonsCradle 13440 * @param {number} x Starting position in X. 13441 * @param {number} y Starting position in Y. 13442 * @param {number} number 13443 * @param {number} size 13444 * @param {number} length 13445 * @return {composite} A new composite newtonsCradle body 13446 */ 13447 Composites.newtonsCradle = function(x, y, number, size, length) { 13448 var newtonsCradle = Composite.create({ label: 'Newtons Cradle' }); 13449 13450 for (var i = 0; i < number; i++) { 13451 var separation = 1.9, 13452 circle = Bodies.circle(x + i * (size * separation), y + length, size, 13453 { inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }), 13454 constraint = Constraint.create({ pointA: { x: x + i * (size * separation), y: y }, bodyB: circle }); 13455 13456 Composite.addBody(newtonsCradle, circle); 13457 Composite.addConstraint(newtonsCradle, constraint); 13458 } 13459 13460 return newtonsCradle; 13461 }; 13462 13463 deprecated(Composites, 'newtonsCradle', 'Composites.newtonsCradle ⤠moved to newtonsCradle example'); 13464 13465 /** 13466 * This has now moved to the [car example](https://github.com/liabru/matter-js/blob/master/examples/car.js), follow that instead as this function is deprecated here. 13467 * @deprecated moved to car example 13468 * @method car 13469 * @param {number} x Starting position in X. 13470 * @param {number} y Starting position in Y. 13471 * @param {number} width 13472 * @param {number} height 13473 * @param {number} wheelSize 13474 * @return {composite} A new composite car body 13475 */ 13476 Composites.car = function(x, y, width, height, wheelSize) { 13477 var group = Body.nextGroup(true), 13478 wheelBase = 20, 13479 wheelAOffset = -width * 0.5 + wheelBase, 13480 wheelBOffset = width * 0.5 - wheelBase, 13481 wheelYOffset = 0; 13482 13483 var car = Composite.create({ label: 'Car' }), 13484 body = Bodies.rectangle(x, y, width, height, { 13485 collisionFilter: { 13486 group: group 13487 }, 13488 chamfer: { 13489 radius: height * 0.5 13490 }, 13491 density: 0.0002 13492 }); 13493 13494 var wheelA = Bodies.circle(x + wheelAOffset, y + wheelYOffset, wheelSize, { 13495 collisionFilter: { 13496 group: group 13497 }, 13498 friction: 0.8 13499 }); 13500 13501 var wheelB = Bodies.circle(x + wheelBOffset, y + wheelYOffset, wheelSize, { 13502 collisionFilter: { 13503 group: group 13504 }, 13505 friction: 0.8 13506 }); 13507 13508 var axelA = Constraint.create({ 13509 bodyB: body, 13510 pointB: { x: wheelAOffset, y: wheelYOffset }, 13511 bodyA: wheelA, 13512 stiffness: 1, 13513 length: 0 13514 }); 13515 13516 var axelB = Constraint.create({ 13517 bodyB: body, 13518 pointB: { x: wheelBOffset, y: wheelYOffset }, 13519 bodyA: wheelB, 13520 stiffness: 1, 13521 length: 0 13522 }); 13523 13524 Composite.addBody(car, body); 13525 Composite.addBody(car, wheelA); 13526 Composite.addBody(car, wheelB); 13527 Composite.addConstraint(car, axelA); 13528 Composite.addConstraint(car, axelB); 13529 13530 return car; 13531 }; 13532 13533 deprecated(Composites, 'car', 'Composites.car ⤠moved to car example'); 13534 13535 /** 13536 * This has now moved to the [softBody example](https://github.com/liabru/matter-js/blob/master/examples/softBody.js) 13537 * and the [cloth example](https://github.com/liabru/matter-js/blob/master/examples/cloth.js), follow those instead as this function is deprecated here. 13538 * @deprecated moved to softBody and cloth examples 13539 * @method softBody 13540 * @param {number} x Starting position in X. 13541 * @param {number} y Starting position in Y. 13542 * @param {number} columns 13543 * @param {number} rows 13544 * @param {number} columnGap 13545 * @param {number} rowGap 13546 * @param {boolean} crossBrace 13547 * @param {number} particleRadius 13548 * @param {} particleOptions 13549 * @param {} constraintOptions 13550 * @return {composite} A new composite softBody 13551 */ 13552 Composites.softBody = function(x, y, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) { 13553 particleOptions = Common.extend({ inertia: Infinity }, particleOptions); 13554 constraintOptions = Common.extend({ stiffness: 0.2, render: { type: 'line', anchors: false } }, constraintOptions); 13555 13556 var softBody = Composites.stack(x, y, columns, rows, columnGap, rowGap, function(stackX, stackY) { 13557 return Bodies.circle(stackX, stackY, particleRadius, particleOptions); 13558 }); 13559 13560 Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions); 13561 13562 softBody.label = 'Soft Body'; 13563 13564 return softBody; 13565 }; 13566 13567 deprecated(Composites, 'softBody', 'Composites.softBody ⤠moved to softBody and cloth examples'); 13568})(); 13569 13570 13571/***/ }), 13572/* 23 */ 13573/***/ (function(module, exports, __webpack_require__) { 13574 13575/** 13576* This module has now been replaced by `Matter.Detector`. 13577* 13578* All usage should be migrated to `Matter.Detector` or another alternative. 13579* For back-compatibility purposes this module will remain for a short term and then later removed in a future release. 13580* 13581* The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures. 13582* 13583* @class Grid 13584* @deprecated 13585*/ 13586 13587var Grid = {}; 13588 13589module.exports = Grid; 13590 13591var Pair = __webpack_require__(9); 13592var Common = __webpack_require__(0); 13593var deprecated = Common.deprecated; 13594 13595(function() { 13596 13597 /** 13598 * Creates a new grid. 13599 * @deprecated replaced by Matter.Detector 13600 * @method create 13601 * @param {} options 13602 * @return {grid} A new grid 13603 */ 13604 Grid.create = function(options) { 13605 var defaults = { 13606 buckets: {}, 13607 pairs: {}, 13608 pairsList: [], 13609 bucketWidth: 48, 13610 bucketHeight: 48 13611 }; 13612 13613 return Common.extend(defaults, options); 13614 }; 13615 13616 /** 13617 * The width of a single grid bucket. 13618 * 13619 * @property bucketWidth 13620 * @type number 13621 * @default 48 13622 */ 13623 13624 /** 13625 * The height of a single grid bucket. 13626 * 13627 * @property bucketHeight 13628 * @type number 13629 * @default 48 13630 */ 13631 13632 /** 13633 * Updates the grid. 13634 * @deprecated replaced by Matter.Detector 13635 * @method update 13636 * @param {grid} grid 13637 * @param {body[]} bodies 13638 * @param {engine} engine 13639 * @param {boolean} forceUpdate 13640 */ 13641 Grid.update = function(grid, bodies, engine, forceUpdate) { 13642 var i, col, row, 13643 world = engine.world, 13644 buckets = grid.buckets, 13645 bucket, 13646 bucketId, 13647 gridChanged = false; 13648 13649 for (i = 0; i < bodies.length; i++) { 13650 var body = bodies[i]; 13651 13652 if (body.isSleeping && !forceUpdate) 13653 continue; 13654 13655 // temporary back compatibility bounds check 13656 if (world.bounds && (body.bounds.max.x < world.bounds.min.x || body.bounds.min.x > world.bounds.max.x 13657 || body.bounds.max.y < world.bounds.min.y || body.bounds.min.y > world.bounds.max.y)) 13658 continue; 13659 13660 var newRegion = Grid._getRegion(grid, body); 13661 13662 // if the body has changed grid region 13663 if (!body.region || newRegion.id !== body.region.id || forceUpdate) { 13664 13665 if (!body.region || forceUpdate) 13666 body.region = newRegion; 13667 13668 var union = Grid._regionUnion(newRegion, body.region); 13669 13670 // update grid buckets affected by region change 13671 // iterate over the union of both regions 13672 for (col = union.startCol; col <= union.endCol; col++) { 13673 for (row = union.startRow; row <= union.endRow; row++) { 13674 bucketId = Grid._getBucketId(col, row); 13675 bucket = buckets[bucketId]; 13676 13677 var isInsideNewRegion = (col >= newRegion.startCol && col <= newRegion.endCol 13678 && row >= newRegion.startRow && row <= newRegion.endRow); 13679 13680 var isInsideOldRegion = (col >= body.region.startCol && col <= body.region.endCol 13681 && row >= body.region.startRow && row <= body.region.endRow); 13682 13683 // remove from old region buckets 13684 if (!isInsideNewRegion && isInsideOldRegion) { 13685 if (isInsideOldRegion) { 13686 if (bucket) 13687 Grid._bucketRemoveBody(grid, bucket, body); 13688 } 13689 } 13690 13691 // add to new region buckets 13692 if (body.region === newRegion || (isInsideNewRegion && !isInsideOldRegion) || forceUpdate) { 13693 if (!bucket) 13694 bucket = Grid._createBucket(buckets, bucketId); 13695 Grid._bucketAddBody(grid, bucket, body); 13696 } 13697 } 13698 } 13699 13700 // set the new region 13701 body.region = newRegion; 13702 13703 // flag changes so we can update pairs 13704 gridChanged = true; 13705 } 13706 } 13707 13708 // update pairs list only if pairs changed (i.e. a body changed region) 13709 if (gridChanged) 13710 grid.pairsList = Grid._createActivePairsList(grid); 13711 }; 13712 13713 deprecated(Grid, 'update', 'Grid.update ⤠replaced by Matter.Detector'); 13714 13715 /** 13716 * Clears the grid. 13717 * @deprecated replaced by Matter.Detector 13718 * @method clear 13719 * @param {grid} grid 13720 */ 13721 Grid.clear = function(grid) { 13722 grid.buckets = {}; 13723 grid.pairs = {}; 13724 grid.pairsList = []; 13725 }; 13726 13727 deprecated(Grid, 'clear', 'Grid.clear ⤠replaced by Matter.Detector'); 13728 13729 /** 13730 * Finds the union of two regions. 13731 * @method _regionUnion 13732 * @deprecated replaced by Matter.Detector 13733 * @private 13734 * @param {} regionA 13735 * @param {} regionB 13736 * @return {} region 13737 */ 13738 Grid._regionUnion = function(regionA, regionB) { 13739 var startCol = Math.min(regionA.startCol, regionB.startCol), 13740 endCol = Math.max(regionA.endCol, regionB.endCol), 13741 startRow = Math.min(regionA.startRow, regionB.startRow), 13742 endRow = Math.max(regionA.endRow, regionB.endRow); 13743 13744 return Grid._createRegion(startCol, endCol, startRow, endRow); 13745 }; 13746 13747 /** 13748 * Gets the region a given body falls in for a given grid. 13749 * @method _getRegion 13750 * @deprecated replaced by Matter.Detector 13751 * @private 13752 * @param {} grid 13753 * @param {} body 13754 * @return {} region 13755 */ 13756 Grid._getRegion = function(grid, body) { 13757 var bounds = body.bounds, 13758 startCol = Math.floor(bounds.min.x / grid.bucketWidth), 13759 endCol = Math.floor(bounds.max.x / grid.bucketWidth), 13760 startRow = Math.floor(bounds.min.y / grid.bucketHeight), 13761 endRow = Math.floor(bounds.max.y / grid.bucketHeight); 13762 13763 return Grid._createRegion(startCol, endCol, startRow, endRow); 13764 }; 13765 13766 /** 13767 * Creates a region. 13768 * @method _createRegion 13769 * @deprecated replaced by Matter.Detector 13770 * @private 13771 * @param {} startCol 13772 * @param {} endCol 13773 * @param {} startRow 13774 * @param {} endRow 13775 * @return {} region 13776 */ 13777 Grid._createRegion = function(startCol, endCol, startRow, endRow) { 13778 return { 13779 id: startCol + ',' + endCol + ',' + startRow + ',' + endRow, 13780 startCol: startCol, 13781 endCol: endCol, 13782 startRow: startRow, 13783 endRow: endRow 13784 }; 13785 }; 13786 13787 /** 13788 * Gets the bucket id at the given position. 13789 * @method _getBucketId 13790 * @deprecated replaced by Matter.Detector 13791 * @private 13792 * @param {} column 13793 * @param {} row 13794 * @return {string} bucket id 13795 */ 13796 Grid._getBucketId = function(column, row) { 13797 return 'C' + column + 'R' + row; 13798 }; 13799 13800 /** 13801 * Creates a bucket. 13802 * @method _createBucket 13803 * @deprecated replaced by Matter.Detector 13804 * @private 13805 * @param {} buckets 13806 * @param {} bucketId 13807 * @return {} bucket 13808 */ 13809 Grid._createBucket = function(buckets, bucketId) { 13810 var bucket = buckets[bucketId] = []; 13811 return bucket; 13812 }; 13813 13814 /** 13815 * Adds a body to a bucket. 13816 * @method _bucketAddBody 13817 * @deprecated replaced by Matter.Detector 13818 * @private 13819 * @param {} grid 13820 * @param {} bucket 13821 * @param {} body 13822 */ 13823 Grid._bucketAddBody = function(grid, bucket, body) { 13824 var gridPairs = grid.pairs, 13825 pairId = Pair.id, 13826 bucketLength = bucket.length, 13827 i; 13828 13829 // add new pairs 13830 for (i = 0; i < bucketLength; i++) { 13831 var bodyB = bucket[i]; 13832 13833 if (body.id === bodyB.id || (body.isStatic && bodyB.isStatic)) 13834 continue; 13835 13836 // keep track of the number of buckets the pair exists in 13837 // important for Grid.update to work 13838 var id = pairId(body, bodyB), 13839 pair = gridPairs[id]; 13840 13841 if (pair) { 13842 pair[2] += 1; 13843 } else { 13844 gridPairs[id] = [body, bodyB, 1]; 13845 } 13846 } 13847 13848 // add to bodies (after pairs, otherwise pairs with self) 13849 bucket.push(body); 13850 }; 13851 13852 /** 13853 * Removes a body from a bucket. 13854 * @method _bucketRemoveBody 13855 * @deprecated replaced by Matter.Detector 13856 * @private 13857 * @param {} grid 13858 * @param {} bucket 13859 * @param {} body 13860 */ 13861 Grid._bucketRemoveBody = function(grid, bucket, body) { 13862 var gridPairs = grid.pairs, 13863 pairId = Pair.id, 13864 i; 13865 13866 // remove from bucket 13867 bucket.splice(Common.indexOf(bucket, body), 1); 13868 13869 var bucketLength = bucket.length; 13870 13871 // update pair counts 13872 for (i = 0; i < bucketLength; i++) { 13873 // keep track of the number of buckets the pair exists in 13874 // important for _createActivePairsList to work 13875 var pair = gridPairs[pairId(body, bucket[i])]; 13876 13877 if (pair) 13878 pair[2] -= 1; 13879 } 13880 }; 13881 13882 /** 13883 * Generates a list of the active pairs in the grid. 13884 * @method _createActivePairsList 13885 * @deprecated replaced by Matter.Detector 13886 * @private 13887 * @param {} grid 13888 * @return [] pairs 13889 */ 13890 Grid._createActivePairsList = function(grid) { 13891 var pair, 13892 gridPairs = grid.pairs, 13893 pairKeys = Common.keys(gridPairs), 13894 pairKeysLength = pairKeys.length, 13895 pairs = [], 13896 k; 13897 13898 // iterate over grid.pairs 13899 for (k = 0; k < pairKeysLength; k++) { 13900 pair = gridPairs[pairKeys[k]]; 13901 13902 // if pair exists in at least one bucket 13903 // it is a pair that needs further collision testing so push it 13904 if (pair[2] > 0) { 13905 pairs.push(pair); 13906 } else { 13907 delete gridPairs[pairKeys[k]]; 13908 } 13909 } 13910 13911 return pairs; 13912 }; 13913 13914})(); 13915 13916 13917/***/ }), 13918/* 24 */ 13919/***/ (function(module, exports, __webpack_require__) { 13920 13921/** 13922* The `Matter.MouseConstraint` module contains methods for creating mouse constraints. 13923* Mouse constraints are used for allowing user interaction, providing the ability to move bodies via the mouse or touch. 13924* 13925* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 13926* 13927* @class MouseConstraint 13928*/ 13929 13930var MouseConstraint = {}; 13931 13932module.exports = MouseConstraint; 13933 13934var Vertices = __webpack_require__(3); 13935var Sleeping = __webpack_require__(7); 13936var Mouse = __webpack_require__(14); 13937var Events = __webpack_require__(5); 13938var Detector = __webpack_require__(13); 13939var Constraint = __webpack_require__(10); 13940var Composite = __webpack_require__(6); 13941var Common = __webpack_require__(0); 13942var Bounds = __webpack_require__(1); 13943 13944(function() { 13945 13946 /** 13947 * Creates a new mouse constraint. 13948 * All properties have default values, and many are pre-calculated automatically based on other properties. 13949 * See the properties section below for detailed information on what you can pass via the `options` object. 13950 * @method create 13951 * @param {engine} engine 13952 * @param {} options 13953 * @return {MouseConstraint} A new MouseConstraint 13954 */ 13955 MouseConstraint.create = function(engine, options) { 13956 var mouse = (engine ? engine.mouse : null) || (options ? options.mouse : null); 13957 13958 if (!mouse) { 13959 if (engine && engine.render && engine.render.canvas) { 13960 mouse = Mouse.create(engine.render.canvas); 13961 } else if (options && options.element) { 13962 mouse = Mouse.create(options.element); 13963 } else { 13964 mouse = Mouse.create(); 13965 Common.warn('MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected'); 13966 } 13967 } 13968 13969 var constraint = Constraint.create({ 13970 label: 'Mouse Constraint', 13971 pointA: mouse.position, 13972 pointB: { x: 0, y: 0 }, 13973 length: 0.01, 13974 stiffness: 0.1, 13975 angularStiffness: 1, 13976 render: { 13977 strokeStyle: '#90EE90', 13978 lineWidth: 3 13979 } 13980 }); 13981 13982 var defaults = { 13983 type: 'mouseConstraint', 13984 mouse: mouse, 13985 element: null, 13986 body: null, 13987 constraint: constraint, 13988 collisionFilter: { 13989 category: 0x0001, 13990 mask: 0xFFFFFFFF, 13991 group: 0 13992 } 13993 }; 13994 13995 var mouseConstraint = Common.extend(defaults, options); 13996 13997 Events.on(engine, 'beforeUpdate', function() { 13998 var allBodies = Composite.allBodies(engine.world); 13999 MouseConstraint.update(mouseConstraint, allBodies); 14000 MouseConstraint._triggerEvents(mouseConstraint); 14001 }); 14002 14003 return mouseConstraint; 14004 }; 14005 14006 /** 14007 * Updates the given mouse constraint. 14008 * @private 14009 * @method update 14010 * @param {MouseConstraint} mouseConstraint 14011 * @param {body[]} bodies 14012 */ 14013 MouseConstraint.update = function(mouseConstraint, bodies) { 14014 var mouse = mouseConstraint.mouse, 14015 constraint = mouseConstraint.constraint, 14016 body = mouseConstraint.body; 14017 14018 if (mouse.button === 0) { 14019 if (!constraint.bodyB) { 14020 for (var i = 0; i < bodies.length; i++) { 14021 body = bodies[i]; 14022 if (Bounds.contains(body.bounds, mouse.position) 14023 && Detector.canCollide(body.collisionFilter, mouseConstraint.collisionFilter)) { 14024 for (var j = body.parts.length > 1 ? 1 : 0; j < body.parts.length; j++) { 14025 var part = body.parts[j]; 14026 if (Vertices.contains(part.vertices, mouse.position)) { 14027 constraint.pointA = mouse.position; 14028 constraint.bodyB = mouseConstraint.body = body; 14029 constraint.pointB = { x: mouse.position.x - body.position.x, y: mouse.position.y - body.position.y }; 14030 constraint.angleB = body.angle; 14031 14032 Sleeping.set(body, false); 14033 Events.trigger(mouseConstraint, 'startdrag', { mouse: mouse, body: body }); 14034 14035 break; 14036 } 14037 } 14038 } 14039 } 14040 } else { 14041 Sleeping.set(constraint.bodyB, false); 14042 constraint.pointA = mouse.position; 14043 } 14044 } else { 14045 constraint.bodyB = mouseConstraint.body = null; 14046 constraint.pointB = null; 14047 14048 if (body) 14049 Events.trigger(mouseConstraint, 'enddrag', { mouse: mouse, body: body }); 14050 } 14051 }; 14052 14053 /** 14054 * Triggers mouse constraint events. 14055 * @method _triggerEvents 14056 * @private 14057 * @param {mouse} mouseConstraint 14058 */ 14059 MouseConstraint._triggerEvents = function(mouseConstraint) { 14060 var mouse = mouseConstraint.mouse, 14061 mouseEvents = mouse.sourceEvents; 14062 14063 if (mouseEvents.mousemove) 14064 Events.trigger(mouseConstraint, 'mousemove', { mouse: mouse }); 14065 14066 if (mouseEvents.mousedown) 14067 Events.trigger(mouseConstraint, 'mousedown', { mouse: mouse }); 14068 14069 if (mouseEvents.mouseup) 14070 Events.trigger(mouseConstraint, 'mouseup', { mouse: mouse }); 14071 14072 // reset the mouse state ready for the next step 14073 Mouse.clearSourceEvents(mouse); 14074 }; 14075 14076 /* 14077 * 14078 * Events Documentation 14079 * 14080 */ 14081 14082 /** 14083 * Fired when the mouse has moved (or a touch moves) during the last step 14084 * 14085 * @event mousemove 14086 * @param {} event An event object 14087 * @param {mouse} event.mouse The engine's mouse instance 14088 * @param {} event.source The source object of the event 14089 * @param {} event.name The name of the event 14090 */ 14091 14092 /** 14093 * Fired when the mouse is down (or a touch has started) during the last step 14094 * 14095 * @event mousedown 14096 * @param {} event An event object 14097 * @param {mouse} event.mouse The engine's mouse instance 14098 * @param {} event.source The source object of the event 14099 * @param {} event.name The name of the event 14100 */ 14101 14102 /** 14103 * Fired when the mouse is up (or a touch has ended) during the last step 14104 * 14105 * @event mouseup 14106 * @param {} event An event object 14107 * @param {mouse} event.mouse The engine's mouse instance 14108 * @param {} event.source The source object of the event 14109 * @param {} event.name The name of the event 14110 */ 14111 14112 /** 14113 * Fired when the user starts dragging a body 14114 * 14115 * @event startdrag 14116 * @param {} event An event object 14117 * @param {mouse} event.mouse The engine's mouse instance 14118 * @param {body} event.body The body being dragged 14119 * @param {} event.source The source object of the event 14120 * @param {} event.name The name of the event 14121 */ 14122 14123 /** 14124 * Fired when the user ends dragging a body 14125 * 14126 * @event enddrag 14127 * @param {} event An event object 14128 * @param {mouse} event.mouse The engine's mouse instance 14129 * @param {body} event.body The body that has stopped being dragged 14130 * @param {} event.source The source object of the event 14131 * @param {} event.name The name of the event 14132 */ 14133 14134 /* 14135 * 14136 * Properties Documentation 14137 * 14138 */ 14139 14140 /** 14141 * A `String` denoting the type of object. 14142 * 14143 * @property type 14144 * @type string 14145 * @default "constraint" 14146 * @readOnly 14147 */ 14148 14149 /** 14150 * The `Mouse` instance in use. If not supplied in `MouseConstraint.create`, one will be created. 14151 * 14152 * @property mouse 14153 * @type mouse 14154 * @default mouse 14155 */ 14156 14157 /** 14158 * The `Body` that is currently being moved by the user, or `null` if no body. 14159 * 14160 * @property body 14161 * @type body 14162 * @default null 14163 */ 14164 14165 /** 14166 * The `Constraint` object that is used to move the body during interaction. 14167 * 14168 * @property constraint 14169 * @type constraint 14170 */ 14171 14172 /** 14173 * An `Object` that specifies the collision filter properties. 14174 * The collision filter allows the user to define which types of body this mouse constraint can interact with. 14175 * See `body.collisionFilter` for more information. 14176 * 14177 * @property collisionFilter 14178 * @type object 14179 */ 14180 14181})(); 14182 14183 14184/***/ }), 14185/* 25 */ 14186/***/ (function(module, exports, __webpack_require__) { 14187 14188/** 14189* The `Matter.Query` module contains methods for performing collision queries. 14190* 14191* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 14192* 14193* @class Query 14194*/ 14195 14196var Query = {}; 14197 14198module.exports = Query; 14199 14200var Vector = __webpack_require__(2); 14201var Collision = __webpack_require__(8); 14202var Bounds = __webpack_require__(1); 14203var Bodies = __webpack_require__(12); 14204var Vertices = __webpack_require__(3); 14205 14206(function() { 14207 14208 /** 14209 * Returns a list of collisions between `body` and `bodies`. 14210 * @method collides 14211 * @param {body} body 14212 * @param {body[]} bodies 14213 * @return {collision[]} Collisions 14214 */ 14215 Query.collides = function(body, bodies) { 14216 var collisions = [], 14217 bodiesLength = bodies.length, 14218 bounds = body.bounds, 14219 collides = Collision.collides, 14220 overlaps = Bounds.overlaps; 14221 14222 for (var i = 0; i < bodiesLength; i++) { 14223 var bodyA = bodies[i], 14224 partsALength = bodyA.parts.length, 14225 partsAStart = partsALength === 1 ? 0 : 1; 14226 14227 if (overlaps(bodyA.bounds, bounds)) { 14228 for (var j = partsAStart; j < partsALength; j++) { 14229 var part = bodyA.parts[j]; 14230 14231 if (overlaps(part.bounds, bounds)) { 14232 var collision = collides(part, body); 14233 14234 if (collision) { 14235 collisions.push(collision); 14236 break; 14237 } 14238 } 14239 } 14240 } 14241 } 14242 14243 return collisions; 14244 }; 14245 14246 /** 14247 * Casts a ray segment against a set of bodies and returns all collisions, ray width is optional. Intersection points are not provided. 14248 * @method ray 14249 * @param {body[]} bodies 14250 * @param {vector} startPoint 14251 * @param {vector} endPoint 14252 * @param {number} [rayWidth] 14253 * @return {collision[]} Collisions 14254 */ 14255 Query.ray = function(bodies, startPoint, endPoint, rayWidth) { 14256 rayWidth = rayWidth || 1e-100; 14257 14258 var rayAngle = Vector.angle(startPoint, endPoint), 14259 rayLength = Vector.magnitude(Vector.sub(startPoint, endPoint)), 14260 rayX = (endPoint.x + startPoint.x) * 0.5, 14261 rayY = (endPoint.y + startPoint.y) * 0.5, 14262 ray = Bodies.rectangle(rayX, rayY, rayLength, rayWidth, { angle: rayAngle }), 14263 collisions = Query.collides(ray, bodies); 14264 14265 for (var i = 0; i < collisions.length; i += 1) { 14266 var collision = collisions[i]; 14267 collision.body = collision.bodyB = collision.bodyA; 14268 } 14269 14270 return collisions; 14271 }; 14272 14273 /** 14274 * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies. 14275 * @method region 14276 * @param {body[]} bodies 14277 * @param {bounds} bounds 14278 * @param {bool} [outside=false] 14279 * @return {body[]} The bodies matching the query 14280 */ 14281 Query.region = function(bodies, bounds, outside) { 14282 var result = []; 14283 14284 for (var i = 0; i < bodies.length; i++) { 14285 var body = bodies[i], 14286 overlaps = Bounds.overlaps(body.bounds, bounds); 14287 if ((overlaps && !outside) || (!overlaps && outside)) 14288 result.push(body); 14289 } 14290 14291 return result; 14292 }; 14293 14294 /** 14295 * Returns all bodies whose vertices contain the given point, from the given set of bodies. 14296 * @method point 14297 * @param {body[]} bodies 14298 * @param {vector} point 14299 * @return {body[]} The bodies matching the query 14300 */ 14301 Query.point = function(bodies, point) { 14302 var result = []; 14303 14304 for (var i = 0; i < bodies.length; i++) { 14305 var body = bodies[i]; 14306 14307 if (Bounds.contains(body.bounds, point)) { 14308 for (var j = body.parts.length === 1 ? 0 : 1; j < body.parts.length; j++) { 14309 var part = body.parts[j]; 14310 14311 if (Bounds.contains(part.bounds, point) 14312 && Vertices.contains(part.vertices, point)) { 14313 result.push(body); 14314 break; 14315 } 14316 } 14317 } 14318 } 14319 14320 return result; 14321 }; 14322 14323})(); 14324 14325 14326/***/ }), 14327/* 26 */ 14328/***/ (function(module, exports, __webpack_require__) { 14329 14330/** 14331* The `Matter.Render` module is a lightweight, optional utility which provides a simple canvas based renderer for visualising instances of `Matter.Engine`. 14332* It is intended for development and debugging purposes, but may also be suitable for simple games. 14333* It includes a number of drawing options including wireframe, vector with support for sprites and viewports. 14334* 14335* @class Render 14336*/ 14337 14338var Render = {}; 14339 14340module.exports = Render; 14341 14342var Body = __webpack_require__(4); 14343var Common = __webpack_require__(0); 14344var Composite = __webpack_require__(6); 14345var Bounds = __webpack_require__(1); 14346var Events = __webpack_require__(5); 14347var Vector = __webpack_require__(2); 14348var Mouse = __webpack_require__(14); 14349 14350(function() { 14351 14352 var _requestAnimationFrame, 14353 _cancelAnimationFrame; 14354 14355 if (typeof window !== 'undefined') { 14356 _requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame 14357 || window.mozRequestAnimationFrame || window.msRequestAnimationFrame 14358 || function(callback){ window.setTimeout(function() { callback(Common.now()); }, 1000 / 60); }; 14359 14360 _cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame 14361 || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame; 14362 } 14363 14364 Render._goodFps = 30; 14365 Render._goodDelta = 1000 / 60; 14366 14367 /** 14368 * Creates a new renderer. The options parameter is an object that specifies any properties you wish to override the defaults. 14369 * All properties have default values, and many are pre-calculated automatically based on other properties. 14370 * See the properties section below for detailed information on what you can pass via the `options` object. 14371 * @method create 14372 * @param {object} [options] 14373 * @return {render} A new renderer 14374 */ 14375 Render.create = function(options) { 14376 var defaults = { 14377 engine: null, 14378 element: null, 14379 canvas: null, 14380 mouse: null, 14381 frameRequestId: null, 14382 timing: { 14383 historySize: 60, 14384 delta: 0, 14385 deltaHistory: [], 14386 lastTime: 0, 14387 lastTimestamp: 0, 14388 lastElapsed: 0, 14389 timestampElapsed: 0, 14390 timestampElapsedHistory: [], 14391 engineDeltaHistory: [], 14392 engineElapsedHistory: [], 14393 engineUpdatesHistory: [], 14394 elapsedHistory: [] 14395 }, 14396 options: { 14397 width: 800, 14398 height: 600, 14399 pixelRatio: 1, 14400 background: '#14151f', 14401 wireframeBackground: '#14151f', 14402 wireframeStrokeStyle: '#bbb', 14403 hasBounds: !!options.bounds, 14404 enabled: true, 14405 wireframes: true, 14406 showSleeping: true, 14407 showDebug: false, 14408 showStats: false, 14409 showPerformance: false, 14410 showBounds: false, 14411 showVelocity: false, 14412 showCollisions: false, 14413 showSeparations: false, 14414 showAxes: false, 14415 showPositions: false, 14416 showAngleIndicator: false, 14417 showIds: false, 14418 showVertexNumbers: false, 14419 showConvexHulls: false, 14420 showInternalEdges: false, 14421 showMousePosition: false 14422 } 14423 }; 14424 14425 var render = Common.extend(defaults, options); 14426 14427 if (render.canvas) { 14428 render.canvas.width = render.options.width || render.canvas.width; 14429 render.canvas.height = render.options.height || render.canvas.height; 14430 } 14431 14432 render.mouse = options.mouse; 14433 render.engine = options.engine; 14434 render.canvas = render.canvas || _createCanvas(render.options.width, render.options.height); 14435 render.context = render.canvas.getContext('2d'); 14436 render.textures = {}; 14437 14438 render.bounds = render.bounds || { 14439 min: { 14440 x: 0, 14441 y: 0 14442 }, 14443 max: { 14444 x: render.canvas.width, 14445 y: render.canvas.height 14446 } 14447 }; 14448 14449 // for temporary back compatibility only 14450 render.controller = Render; 14451 render.options.showBroadphase = false; 14452 14453 if (render.options.pixelRatio !== 1) { 14454 Render.setPixelRatio(render, render.options.pixelRatio); 14455 } 14456 14457 if (Common.isElement(render.element)) { 14458 render.element.appendChild(render.canvas); 14459 } 14460 14461 return render; 14462 }; 14463 14464 /** 14465 * Continuously updates the render canvas on the `requestAnimationFrame` event. 14466 * @method run 14467 * @param {render} render 14468 */ 14469 Render.run = function(render) { 14470 (function loop(time){ 14471 render.frameRequestId = _requestAnimationFrame(loop); 14472 14473 _updateTiming(render, time); 14474 14475 Render.world(render, time); 14476 14477 render.context.setTransform(render.options.pixelRatio, 0, 0, render.options.pixelRatio, 0, 0); 14478 14479 if (render.options.showStats || render.options.showDebug) { 14480 Render.stats(render, render.context, time); 14481 } 14482 14483 if (render.options.showPerformance || render.options.showDebug) { 14484 Render.performance(render, render.context, time); 14485 } 14486 14487 render.context.setTransform(1, 0, 0, 1, 0, 0); 14488 })(); 14489 }; 14490 14491 /** 14492 * Ends execution of `Render.run` on the given `render`, by canceling the animation frame request event loop. 14493 * @method stop 14494 * @param {render} render 14495 */ 14496 Render.stop = function(render) { 14497 _cancelAnimationFrame(render.frameRequestId); 14498 }; 14499 14500 /** 14501 * Sets the pixel ratio of the renderer and updates the canvas. 14502 * To automatically detect the correct ratio, pass the string `'auto'` for `pixelRatio`. 14503 * @method setPixelRatio 14504 * @param {render} render 14505 * @param {number} pixelRatio 14506 */ 14507 Render.setPixelRatio = function(render, pixelRatio) { 14508 var options = render.options, 14509 canvas = render.canvas; 14510 14511 if (pixelRatio === 'auto') { 14512 pixelRatio = _getPixelRatio(canvas); 14513 } 14514 14515 options.pixelRatio = pixelRatio; 14516 canvas.setAttribute('data-pixel-ratio', pixelRatio); 14517 canvas.width = options.width * pixelRatio; 14518 canvas.height = options.height * pixelRatio; 14519 canvas.style.width = options.width + 'px'; 14520 canvas.style.height = options.height + 'px'; 14521 }; 14522 14523 /** 14524 * Sets the render `width` and `height`. 14525 * 14526 * Updates the canvas accounting for `render.options.pixelRatio`. 14527 * 14528 * Updates the bottom right render bound `render.bounds.max` relative to the provided `width` and `height`. 14529 * The top left render bound `render.bounds.min` isn't changed. 14530 * 14531 * Follow this call with `Render.lookAt` if you need to change the render bounds. 14532 * 14533 * See also `Render.setPixelRatio`. 14534 * @method setSize 14535 * @param {render} render 14536 * @param {number} width The width (in CSS pixels) 14537 * @param {number} height The height (in CSS pixels) 14538 */ 14539 Render.setSize = function(render, width, height) { 14540 render.options.width = width; 14541 render.options.height = height; 14542 render.bounds.max.x = render.bounds.min.x + width; 14543 render.bounds.max.y = render.bounds.min.y + height; 14544 14545 if (render.options.pixelRatio !== 1) { 14546 Render.setPixelRatio(render, render.options.pixelRatio); 14547 } else { 14548 render.canvas.width = width; 14549 render.canvas.height = height; 14550 } 14551 }; 14552 14553 /** 14554 * Positions and sizes the viewport around the given object bounds. 14555 * Objects must have at least one of the following properties: 14556 * - `object.bounds` 14557 * - `object.position` 14558 * - `object.min` and `object.max` 14559 * - `object.x` and `object.y` 14560 * @method lookAt 14561 * @param {render} render 14562 * @param {object[]} objects 14563 * @param {vector} [padding] 14564 * @param {bool} [center=true] 14565 */ 14566 Render.lookAt = function(render, objects, padding, center) { 14567 center = typeof center !== 'undefined' ? center : true; 14568 objects = Common.isArray(objects) ? objects : [objects]; 14569 padding = padding || { 14570 x: 0, 14571 y: 0 14572 }; 14573 14574 // find bounds of all objects 14575 var bounds = { 14576 min: { x: Infinity, y: Infinity }, 14577 max: { x: -Infinity, y: -Infinity } 14578 }; 14579 14580 for (var i = 0; i < objects.length; i += 1) { 14581 var object = objects[i], 14582 min = object.bounds ? object.bounds.min : (object.min || object.position || object), 14583 max = object.bounds ? object.bounds.max : (object.max || object.position || object); 14584 14585 if (min && max) { 14586 if (min.x < bounds.min.x) 14587 bounds.min.x = min.x; 14588 14589 if (max.x > bounds.max.x) 14590 bounds.max.x = max.x; 14591 14592 if (min.y < bounds.min.y) 14593 bounds.min.y = min.y; 14594 14595 if (max.y > bounds.max.y) 14596 bounds.max.y = max.y; 14597 } 14598 } 14599 14600 // find ratios 14601 var width = (bounds.max.x - bounds.min.x) + 2 * padding.x, 14602 height = (bounds.max.y - bounds.min.y) + 2 * padding.y, 14603 viewHeight = render.canvas.height, 14604 viewWidth = render.canvas.width, 14605 outerRatio = viewWidth / viewHeight, 14606 innerRatio = width / height, 14607 scaleX = 1, 14608 scaleY = 1; 14609 14610 // find scale factor 14611 if (innerRatio > outerRatio) { 14612 scaleY = innerRatio / outerRatio; 14613 } else { 14614 scaleX = outerRatio / innerRatio; 14615 } 14616 14617 // enable bounds 14618 render.options.hasBounds = true; 14619 14620 // position and size 14621 render.bounds.min.x = bounds.min.x; 14622 render.bounds.max.x = bounds.min.x + width * scaleX; 14623 render.bounds.min.y = bounds.min.y; 14624 render.bounds.max.y = bounds.min.y + height * scaleY; 14625 14626 // center 14627 if (center) { 14628 render.bounds.min.x += width * 0.5 - (width * scaleX) * 0.5; 14629 render.bounds.max.x += width * 0.5 - (width * scaleX) * 0.5; 14630 render.bounds.min.y += height * 0.5 - (height * scaleY) * 0.5; 14631 render.bounds.max.y += height * 0.5 - (height * scaleY) * 0.5; 14632 } 14633 14634 // padding 14635 render.bounds.min.x -= padding.x; 14636 render.bounds.max.x -= padding.x; 14637 render.bounds.min.y -= padding.y; 14638 render.bounds.max.y -= padding.y; 14639 14640 // update mouse 14641 if (render.mouse) { 14642 Mouse.setScale(render.mouse, { 14643 x: (render.bounds.max.x - render.bounds.min.x) / render.canvas.width, 14644 y: (render.bounds.max.y - render.bounds.min.y) / render.canvas.height 14645 }); 14646 14647 Mouse.setOffset(render.mouse, render.bounds.min); 14648 } 14649 }; 14650 14651 /** 14652 * Applies viewport transforms based on `render.bounds` to a render context. 14653 * @method startViewTransform 14654 * @param {render} render 14655 */ 14656 Render.startViewTransform = function(render) { 14657 var boundsWidth = render.bounds.max.x - render.bounds.min.x, 14658 boundsHeight = render.bounds.max.y - render.bounds.min.y, 14659 boundsScaleX = boundsWidth / render.options.width, 14660 boundsScaleY = boundsHeight / render.options.height; 14661 14662 render.context.setTransform( 14663 render.options.pixelRatio / boundsScaleX, 0, 0, 14664 render.options.pixelRatio / boundsScaleY, 0, 0 14665 ); 14666 14667 render.context.translate(-render.bounds.min.x, -render.bounds.min.y); 14668 }; 14669 14670 /** 14671 * Resets all transforms on the render context. 14672 * @method endViewTransform 14673 * @param {render} render 14674 */ 14675 Render.endViewTransform = function(render) { 14676 render.context.setTransform(render.options.pixelRatio, 0, 0, render.options.pixelRatio, 0, 0); 14677 }; 14678 14679 /** 14680 * Renders the given `engine`'s `Matter.World` object. 14681 * This is the entry point for all rendering and should be called every time the scene changes. 14682 * @method world 14683 * @param {render} render 14684 */ 14685 Render.world = function(render, time) { 14686 var startTime = Common.now(), 14687 engine = render.engine, 14688 world = engine.world, 14689 canvas = render.canvas, 14690 context = render.context, 14691 options = render.options, 14692 timing = render.timing; 14693 14694 var allBodies = Composite.allBodies(world), 14695 allConstraints = Composite.allConstraints(world), 14696 background = options.wireframes ? options.wireframeBackground : options.background, 14697 bodies = [], 14698 constraints = [], 14699 i; 14700 14701 var event = { 14702 timestamp: engine.timing.timestamp 14703 }; 14704 14705 Events.trigger(render, 'beforeRender', event); 14706 14707 // apply background if it has changed 14708 if (render.currentBackground !== background) 14709 _applyBackground(render, background); 14710 14711 // clear the canvas with a transparent fill, to allow the canvas background to show 14712 context.globalCompositeOperation = 'source-in'; 14713 context.fillStyle = "transparent"; 14714 context.fillRect(0, 0, canvas.width, canvas.height); 14715 context.globalCompositeOperation = 'source-over'; 14716 14717 // handle bounds 14718 if (options.hasBounds) { 14719 // filter out bodies that are not in view 14720 for (i = 0; i < allBodies.length; i++) { 14721 var body = allBodies[i]; 14722 if (Bounds.overlaps(body.bounds, render.bounds)) 14723 bodies.push(body); 14724 } 14725 14726 // filter out constraints that are not in view 14727 for (i = 0; i < allConstraints.length; i++) { 14728 var constraint = allConstraints[i], 14729 bodyA = constraint.bodyA, 14730 bodyB = constraint.bodyB, 14731 pointAWorld = constraint.pointA, 14732 pointBWorld = constraint.pointB; 14733 14734 if (bodyA) pointAWorld = Vector.add(bodyA.position, constraint.pointA); 14735 if (bodyB) pointBWorld = Vector.add(bodyB.position, constraint.pointB); 14736 14737 if (!pointAWorld || !pointBWorld) 14738 continue; 14739 14740 if (Bounds.contains(render.bounds, pointAWorld) || Bounds.contains(render.bounds, pointBWorld)) 14741 constraints.push(constraint); 14742 } 14743 14744 // transform the view 14745 Render.startViewTransform(render); 14746 14747 // update mouse 14748 if (render.mouse) { 14749 Mouse.setScale(render.mouse, { 14750 x: (render.bounds.max.x - render.bounds.min.x) / render.options.width, 14751 y: (render.bounds.max.y - render.bounds.min.y) / render.options.height 14752 }); 14753 14754 Mouse.setOffset(render.mouse, render.bounds.min); 14755 } 14756 } else { 14757 constraints = allConstraints; 14758 bodies = allBodies; 14759 14760 if (render.options.pixelRatio !== 1) { 14761 render.context.setTransform(render.options.pixelRatio, 0, 0, render.options.pixelRatio, 0, 0); 14762 } 14763 } 14764 14765 if (!options.wireframes || (engine.enableSleeping && options.showSleeping)) { 14766 // fully featured rendering of bodies 14767 Render.bodies(render, bodies, context); 14768 } else { 14769 if (options.showConvexHulls) 14770 Render.bodyConvexHulls(render, bodies, context); 14771 14772 // optimised method for wireframes only 14773 Render.bodyWireframes(render, bodies, context); 14774 } 14775 14776 if (options.showBounds) 14777 Render.bodyBounds(render, bodies, context); 14778 14779 if (options.showAxes || options.showAngleIndicator) 14780 Render.bodyAxes(render, bodies, context); 14781 14782 if (options.showPositions) 14783 Render.bodyPositions(render, bodies, context); 14784 14785 if (options.showVelocity) 14786 Render.bodyVelocity(render, bodies, context); 14787 14788 if (options.showIds) 14789 Render.bodyIds(render, bodies, context); 14790 14791 if (options.showSeparations) 14792 Render.separations(render, engine.pairs.list, context); 14793 14794 if (options.showCollisions) 14795 Render.collisions(render, engine.pairs.list, context); 14796 14797 if (options.showVertexNumbers) 14798 Render.vertexNumbers(render, bodies, context); 14799 14800 if (options.showMousePosition) 14801 Render.mousePosition(render, render.mouse, context); 14802 14803 Render.constraints(constraints, context); 14804 14805 if (options.hasBounds) { 14806 // revert view transforms 14807 Render.endViewTransform(render); 14808 } 14809 14810 Events.trigger(render, 'afterRender', event); 14811 14812 // log the time elapsed computing this update 14813 timing.lastElapsed = Common.now() - startTime; 14814 }; 14815 14816 /** 14817 * Renders statistics about the engine and world useful for debugging. 14818 * @private 14819 * @method stats 14820 * @param {render} render 14821 * @param {RenderingContext} context 14822 * @param {Number} time 14823 */ 14824 Render.stats = function(render, context, time) { 14825 var engine = render.engine, 14826 world = engine.world, 14827 bodies = Composite.allBodies(world), 14828 parts = 0, 14829 width = 55, 14830 height = 44, 14831 x = 0, 14832 y = 0; 14833 14834 // count parts 14835 for (var i = 0; i < bodies.length; i += 1) { 14836 parts += bodies[i].parts.length; 14837 } 14838 14839 // sections 14840 var sections = { 14841 'Part': parts, 14842 'Body': bodies.length, 14843 'Cons': Composite.allConstraints(world).length, 14844 'Comp': Composite.allComposites(world).length, 14845 'Pair': engine.pairs.list.length 14846 }; 14847 14848 // background 14849 context.fillStyle = '#0e0f19'; 14850 context.fillRect(x, y, width * 5.5, height); 14851 14852 context.font = '12px Arial'; 14853 context.textBaseline = 'top'; 14854 context.textAlign = 'right'; 14855 14856 // sections 14857 for (var key in sections) { 14858 var section = sections[key]; 14859 // label 14860 context.fillStyle = '#aaa'; 14861 context.fillText(key, x + width, y + 8); 14862 14863 // value 14864 context.fillStyle = '#eee'; 14865 context.fillText(section, x + width, y + 26); 14866 14867 x += width; 14868 } 14869 }; 14870 14871 /** 14872 * Renders engine and render performance information. 14873 * @private 14874 * @method performance 14875 * @param {render} render 14876 * @param {RenderingContext} context 14877 */ 14878 Render.performance = function(render, context) { 14879 var engine = render.engine, 14880 timing = render.timing, 14881 deltaHistory = timing.deltaHistory, 14882 elapsedHistory = timing.elapsedHistory, 14883 timestampElapsedHistory = timing.timestampElapsedHistory, 14884 engineDeltaHistory = timing.engineDeltaHistory, 14885 engineUpdatesHistory = timing.engineUpdatesHistory, 14886 engineElapsedHistory = timing.engineElapsedHistory, 14887 lastEngineUpdatesPerFrame = engine.timing.lastUpdatesPerFrame, 14888 lastEngineDelta = engine.timing.lastDelta; 14889 14890 var deltaMean = _mean(deltaHistory), 14891 elapsedMean = _mean(elapsedHistory), 14892 engineDeltaMean = _mean(engineDeltaHistory), 14893 engineUpdatesMean = _mean(engineUpdatesHistory), 14894 engineElapsedMean = _mean(engineElapsedHistory), 14895 timestampElapsedMean = _mean(timestampElapsedHistory), 14896 rateMean = (timestampElapsedMean / deltaMean) || 0, 14897 neededUpdatesPerFrame = Math.round(deltaMean / lastEngineDelta), 14898 fps = (1000 / deltaMean) || 0; 14899 14900 var graphHeight = 4, 14901 gap = 12, 14902 width = 60, 14903 height = 34, 14904 x = 10, 14905 y = 69; 14906 14907 // background 14908 context.fillStyle = '#0e0f19'; 14909 context.fillRect(0, 50, gap * 5 + width * 6 + 22, height); 14910 14911 // show FPS 14912 Render.status( 14913 context, x, y, width, graphHeight, deltaHistory.length, 14914 Math.round(fps) + ' fps', 14915 fps / Render._goodFps, 14916 function(i) { return (deltaHistory[i] / deltaMean) - 1; } 14917 ); 14918 14919 // show engine delta 14920 Render.status( 14921 context, x + gap + width, y, width, graphHeight, engineDeltaHistory.length, 14922 lastEngineDelta.toFixed(2) + ' dt', 14923 Render._goodDelta / lastEngineDelta, 14924 function(i) { return (engineDeltaHistory[i] / engineDeltaMean) - 1; } 14925 ); 14926 14927 // show engine updates per frame 14928 Render.status( 14929 context, x + (gap + width) * 2, y, width, graphHeight, engineUpdatesHistory.length, 14930 lastEngineUpdatesPerFrame + ' upf', 14931 Math.pow(Common.clamp((engineUpdatesMean / neededUpdatesPerFrame) || 1, 0, 1), 4), 14932 function(i) { return (engineUpdatesHistory[i] / engineUpdatesMean) - 1; } 14933 ); 14934 14935 // show engine update time 14936 Render.status( 14937 context, x + (gap + width) * 3, y, width, graphHeight, engineElapsedHistory.length, 14938 engineElapsedMean.toFixed(2) + ' ut', 14939 1 - (lastEngineUpdatesPerFrame * engineElapsedMean / Render._goodFps), 14940 function(i) { return (engineElapsedHistory[i] / engineElapsedMean) - 1; } 14941 ); 14942 14943 // show render time 14944 Render.status( 14945 context, x + (gap + width) * 4, y, width, graphHeight, elapsedHistory.length, 14946 elapsedMean.toFixed(2) + ' rt', 14947 1 - (elapsedMean / Render._goodFps), 14948 function(i) { return (elapsedHistory[i] / elapsedMean) - 1; } 14949 ); 14950 14951 // show effective speed 14952 Render.status( 14953 context, x + (gap + width) * 5, y, width, graphHeight, timestampElapsedHistory.length, 14954 rateMean.toFixed(2) + ' x', 14955 rateMean * rateMean * rateMean, 14956 function(i) { return (((timestampElapsedHistory[i] / deltaHistory[i]) / rateMean) || 0) - 1; } 14957 ); 14958 }; 14959 14960 /** 14961 * Renders a label, indicator and a chart. 14962 * @private 14963 * @method status 14964 * @param {RenderingContext} context 14965 * @param {number} x 14966 * @param {number} y 14967 * @param {number} width 14968 * @param {number} height 14969 * @param {number} count 14970 * @param {string} label 14971 * @param {string} indicator 14972 * @param {function} plotY 14973 */ 14974 Render.status = function(context, x, y, width, height, count, label, indicator, plotY) { 14975 // background 14976 context.strokeStyle = '#888'; 14977 context.fillStyle = '#444'; 14978 context.lineWidth = 1; 14979 context.fillRect(x, y + 7, width, 1); 14980 14981 // chart 14982 context.beginPath(); 14983 context.moveTo(x, y + 7 - height * Common.clamp(0.4 * plotY(0), -2, 2)); 14984 for (var i = 0; i < width; i += 1) { 14985 context.lineTo(x + i, y + 7 - (i < count ? height * Common.clamp(0.4 * plotY(i), -2, 2) : 0)); 14986 } 14987 context.stroke(); 14988 14989 // indicator 14990 context.fillStyle = 'hsl(' + Common.clamp(25 + 95 * indicator, 0, 120) + ',100%,60%)'; 14991 context.fillRect(x, y - 7, 4, 4); 14992 14993 // label 14994 context.font = '12px Arial'; 14995 context.textBaseline = 'middle'; 14996 context.textAlign = 'right'; 14997 context.fillStyle = '#eee'; 14998 context.fillText(label, x + width, y - 5); 14999 }; 15000 15001 /** 15002 * Description 15003 * @private 15004 * @method constraints 15005 * @param {constraint[]} constraints 15006 * @param {RenderingContext} context 15007 */ 15008 Render.constraints = function(constraints, context) { 15009 var c = context; 15010 15011 for (var i = 0; i < constraints.length; i++) { 15012 var constraint = constraints[i]; 15013 15014 if (!constraint.render.visible || !constraint.pointA || !constraint.pointB) 15015 continue; 15016 15017 var bodyA = constraint.bodyA, 15018 bodyB = constraint.bodyB, 15019 start, 15020 end; 15021 15022 if (bodyA) { 15023 start = Vector.add(bodyA.position, constraint.pointA); 15024 } else { 15025 start = constraint.pointA; 15026 } 15027 15028 if (constraint.render.type === 'pin') { 15029 c.beginPath(); 15030 c.arc(start.x, start.y, 3, 0, 2 * Math.PI); 15031 c.closePath(); 15032 } else { 15033 if (bodyB) { 15034 end = Vector.add(bodyB.position, constraint.pointB); 15035 } else { 15036 end = constraint.pointB; 15037 } 15038 15039 c.beginPath(); 15040 c.moveTo(start.x, start.y); 15041 15042 if (constraint.render.type === 'spring') { 15043 var delta = Vector.sub(end, start), 15044 normal = Vector.perp(Vector.normalise(delta)), 15045 coils = Math.ceil(Common.clamp(constraint.length / 5, 12, 20)), 15046 offset; 15047 15048 for (var j = 1; j < coils; j += 1) { 15049 offset = j % 2 === 0 ? 1 : -1; 15050 15051 c.lineTo( 15052 start.x + delta.x * (j / coils) + normal.x * offset * 4, 15053 start.y + delta.y * (j / coils) + normal.y * offset * 4 15054 ); 15055 } 15056 } 15057 15058 c.lineTo(end.x, end.y); 15059 } 15060 15061 if (constraint.render.lineWidth) { 15062 c.lineWidth = constraint.render.lineWidth; 15063 c.strokeStyle = constraint.render.strokeStyle; 15064 c.stroke(); 15065 } 15066 15067 if (constraint.render.anchors) { 15068 c.fillStyle = constraint.render.strokeStyle; 15069 c.beginPath(); 15070 c.arc(start.x, start.y, 3, 0, 2 * Math.PI); 15071 c.arc(end.x, end.y, 3, 0, 2 * Math.PI); 15072 c.closePath(); 15073 c.fill(); 15074 } 15075 } 15076 }; 15077 15078 /** 15079 * Description 15080 * @private 15081 * @method bodies 15082 * @param {render} render 15083 * @param {body[]} bodies 15084 * @param {RenderingContext} context 15085 */ 15086 Render.bodies = function(render, bodies, context) { 15087 var c = context, 15088 engine = render.engine, 15089 options = render.options, 15090 showInternalEdges = options.showInternalEdges || !options.wireframes, 15091 body, 15092 part, 15093 i, 15094 k; 15095 15096 for (i = 0; i < bodies.length; i++) { 15097 body = bodies[i]; 15098 15099 if (!body.render.visible) 15100 continue; 15101 15102 // handle compound parts 15103 for (k = body.parts.length > 1 ? 1 : 0; k < body.parts.length; k++) { 15104 part = body.parts[k]; 15105 15106 if (!part.render.visible) 15107 continue; 15108 15109 if (options.showSleeping && body.isSleeping) { 15110 c.globalAlpha = 0.5 * part.render.opacity; 15111 } else if (part.render.opacity !== 1) { 15112 c.globalAlpha = part.render.opacity; 15113 } 15114 15115 if (part.render.sprite && part.render.sprite.texture && !options.wireframes) { 15116 // part sprite 15117 var sprite = part.render.sprite, 15118 texture = _getTexture(render, sprite.texture); 15119 15120 c.translate(part.position.x, part.position.y); 15121 c.rotate(part.angle); 15122 15123 c.drawImage( 15124 texture, 15125 texture.width * -sprite.xOffset * sprite.xScale, 15126 texture.height * -sprite.yOffset * sprite.yScale, 15127 texture.width * sprite.xScale, 15128 texture.height * sprite.yScale 15129 ); 15130 15131 // revert translation, hopefully faster than save / restore 15132 c.rotate(-part.angle); 15133 c.translate(-part.position.x, -part.position.y); 15134 } else { 15135 // part polygon 15136 if (part.circleRadius) { 15137 c.beginPath(); 15138 c.arc(part.position.x, part.position.y, part.circleRadius, 0, 2 * Math.PI); 15139 } else { 15140 c.beginPath(); 15141 c.moveTo(part.vertices[0].x, part.vertices[0].y); 15142 15143 for (var j = 1; j < part.vertices.length; j++) { 15144 if (!part.vertices[j - 1].isInternal || showInternalEdges) { 15145 c.lineTo(part.vertices[j].x, part.vertices[j].y); 15146 } else { 15147 c.moveTo(part.vertices[j].x, part.vertices[j].y); 15148 } 15149 15150 if (part.vertices[j].isInternal && !showInternalEdges) { 15151 c.moveTo(part.vertices[(j + 1) % part.vertices.length].x, part.vertices[(j + 1) % part.vertices.length].y); 15152 } 15153 } 15154 15155 c.lineTo(part.vertices[0].x, part.vertices[0].y); 15156 c.closePath(); 15157 } 15158 15159 if (!options.wireframes) { 15160 c.fillStyle = part.render.fillStyle; 15161 15162 if (part.render.lineWidth) { 15163 c.lineWidth = part.render.lineWidth; 15164 c.strokeStyle = part.render.strokeStyle; 15165 c.stroke(); 15166 } 15167 15168 c.fill(); 15169 } else { 15170 c.lineWidth = 1; 15171 c.strokeStyle = render.options.wireframeStrokeStyle; 15172 c.stroke(); 15173 } 15174 } 15175 15176 c.globalAlpha = 1; 15177 } 15178 } 15179 }; 15180 15181 /** 15182 * Optimised method for drawing body wireframes in one pass 15183 * @private 15184 * @method bodyWireframes 15185 * @param {render} render 15186 * @param {body[]} bodies 15187 * @param {RenderingContext} context 15188 */ 15189 Render.bodyWireframes = function(render, bodies, context) { 15190 var c = context, 15191 showInternalEdges = render.options.showInternalEdges, 15192 body, 15193 part, 15194 i, 15195 j, 15196 k; 15197 15198 c.beginPath(); 15199 15200 // render all bodies 15201 for (i = 0; i < bodies.length; i++) { 15202 body = bodies[i]; 15203 15204 if (!body.render.visible) 15205 continue; 15206 15207 // handle compound parts 15208 for (k = body.parts.length > 1 ? 1 : 0; k < body.parts.length; k++) { 15209 part = body.parts[k]; 15210 15211 c.moveTo(part.vertices[0].x, part.vertices[0].y); 15212 15213 for (j = 1; j < part.vertices.length; j++) { 15214 if (!part.vertices[j - 1].isInternal || showInternalEdges) { 15215 c.lineTo(part.vertices[j].x, part.vertices[j].y); 15216 } else { 15217 c.moveTo(part.vertices[j].x, part.vertices[j].y); 15218 } 15219 15220 if (part.vertices[j].isInternal && !showInternalEdges) { 15221 c.moveTo(part.vertices[(j + 1) % part.vertices.length].x, part.vertices[(j + 1) % part.vertices.length].y); 15222 } 15223 } 15224 15225 c.lineTo(part.vertices[0].x, part.vertices[0].y); 15226 } 15227 } 15228 15229 c.lineWidth = 1; 15230 c.strokeStyle = render.options.wireframeStrokeStyle; 15231 c.stroke(); 15232 }; 15233 15234 /** 15235 * Optimised method for drawing body convex hull wireframes in one pass 15236 * @private 15237 * @method bodyConvexHulls 15238 * @param {render} render 15239 * @param {body[]} bodies 15240 * @param {RenderingContext} context 15241 */ 15242 Render.bodyConvexHulls = function(render, bodies, context) { 15243 var c = context, 15244 body, 15245 part, 15246 i, 15247 j, 15248 k; 15249 15250 c.beginPath(); 15251 15252 // render convex hulls 15253 for (i = 0; i < bodies.length; i++) { 15254 body = bodies[i]; 15255 15256 if (!body.render.visible || body.parts.length === 1) 15257 continue; 15258 15259 c.moveTo(body.vertices[0].x, body.vertices[0].y); 15260 15261 for (j = 1; j < body.vertices.length; j++) { 15262 c.lineTo(body.vertices[j].x, body.vertices[j].y); 15263 } 15264 15265 c.lineTo(body.vertices[0].x, body.vertices[0].y); 15266 } 15267 15268 c.lineWidth = 1; 15269 c.strokeStyle = 'rgba(255,255,255,0.2)'; 15270 c.stroke(); 15271 }; 15272 15273 /** 15274 * Renders body vertex numbers. 15275 * @private 15276 * @method vertexNumbers 15277 * @param {render} render 15278 * @param {body[]} bodies 15279 * @param {RenderingContext} context 15280 */ 15281 Render.vertexNumbers = function(render, bodies, context) { 15282 var c = context, 15283 i, 15284 j, 15285 k; 15286 15287 for (i = 0; i < bodies.length; i++) { 15288 var parts = bodies[i].parts; 15289 for (k = parts.length > 1 ? 1 : 0; k < parts.length; k++) { 15290 var part = parts[k]; 15291 for (j = 0; j < part.vertices.length; j++) { 15292 c.fillStyle = 'rgba(255,255,255,0.2)'; 15293 c.fillText(i + '_' + j, part.position.x + (part.vertices[j].x - part.position.x) * 0.8, part.position.y + (part.vertices[j].y - part.position.y) * 0.8); 15294 } 15295 } 15296 } 15297 }; 15298 15299 /** 15300 * Renders mouse position. 15301 * @private 15302 * @method mousePosition 15303 * @param {render} render 15304 * @param {mouse} mouse 15305 * @param {RenderingContext} context 15306 */ 15307 Render.mousePosition = function(render, mouse, context) { 15308 var c = context; 15309 c.fillStyle = 'rgba(255,255,255,0.8)'; 15310 c.fillText(mouse.position.x + ' ' + mouse.position.y, mouse.position.x + 5, mouse.position.y - 5); 15311 }; 15312 15313 /** 15314 * Draws body bounds 15315 * @private 15316 * @method bodyBounds 15317 * @param {render} render 15318 * @param {body[]} bodies 15319 * @param {RenderingContext} context 15320 */ 15321 Render.bodyBounds = function(render, bodies, context) { 15322 var c = context, 15323 engine = render.engine, 15324 options = render.options; 15325 15326 c.beginPath(); 15327 15328 for (var i = 0; i < bodies.length; i++) { 15329 var body = bodies[i]; 15330 15331 if (body.render.visible) { 15332 var parts = bodies[i].parts; 15333 for (var j = parts.length > 1 ? 1 : 0; j < parts.length; j++) { 15334 var part = parts[j]; 15335 c.rect(part.bounds.min.x, part.bounds.min.y, part.bounds.max.x - part.bounds.min.x, part.bounds.max.y - part.bounds.min.y); 15336 } 15337 } 15338 } 15339 15340 if (options.wireframes) { 15341 c.strokeStyle = 'rgba(255,255,255,0.08)'; 15342 } else { 15343 c.strokeStyle = 'rgba(0,0,0,0.1)'; 15344 } 15345 15346 c.lineWidth = 1; 15347 c.stroke(); 15348 }; 15349 15350 /** 15351 * Draws body angle indicators and axes 15352 * @private 15353 * @method bodyAxes 15354 * @param {render} render 15355 * @param {body[]} bodies 15356 * @param {RenderingContext} context 15357 */ 15358 Render.bodyAxes = function(render, bodies, context) { 15359 var c = context, 15360 engine = render.engine, 15361 options = render.options, 15362 part, 15363 i, 15364 j, 15365 k; 15366 15367 c.beginPath(); 15368 15369 for (i = 0; i < bodies.length; i++) { 15370 var body = bodies[i], 15371 parts = body.parts; 15372 15373 if (!body.render.visible) 15374 continue; 15375 15376 if (options.showAxes) { 15377 // render all axes 15378 for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) { 15379 part = parts[j]; 15380 for (k = 0; k < part.axes.length; k++) { 15381 var axis = part.axes[k]; 15382 c.moveTo(part.position.x, part.position.y); 15383 c.lineTo(part.position.x + axis.x * 20, part.position.y + axis.y * 20); 15384 } 15385 } 15386 } else { 15387 for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) { 15388 part = parts[j]; 15389 for (k = 0; k < part.axes.length; k++) { 15390 // render a single axis indicator 15391 c.moveTo(part.position.x, part.position.y); 15392 c.lineTo((part.vertices[0].x + part.vertices[part.vertices.length-1].x) / 2, 15393 (part.vertices[0].y + part.vertices[part.vertices.length-1].y) / 2); 15394 } 15395 } 15396 } 15397 } 15398 15399 if (options.wireframes) { 15400 c.strokeStyle = 'indianred'; 15401 c.lineWidth = 1; 15402 } else { 15403 c.strokeStyle = 'rgba(255, 255, 255, 0.4)'; 15404 c.globalCompositeOperation = 'overlay'; 15405 c.lineWidth = 2; 15406 } 15407 15408 c.stroke(); 15409 c.globalCompositeOperation = 'source-over'; 15410 }; 15411 15412 /** 15413 * Draws body positions 15414 * @private 15415 * @method bodyPositions 15416 * @param {render} render 15417 * @param {body[]} bodies 15418 * @param {RenderingContext} context 15419 */ 15420 Render.bodyPositions = function(render, bodies, context) { 15421 var c = context, 15422 engine = render.engine, 15423 options = render.options, 15424 body, 15425 part, 15426 i, 15427 k; 15428 15429 c.beginPath(); 15430 15431 // render current positions 15432 for (i = 0; i < bodies.length; i++) { 15433 body = bodies[i]; 15434 15435 if (!body.render.visible) 15436 continue; 15437 15438 // handle compound parts 15439 for (k = 0; k < body.parts.length; k++) { 15440 part = body.parts[k]; 15441 c.arc(part.position.x, part.position.y, 3, 0, 2 * Math.PI, false); 15442 c.closePath(); 15443 } 15444 } 15445 15446 if (options.wireframes) { 15447 c.fillStyle = 'indianred'; 15448 } else { 15449 c.fillStyle = 'rgba(0,0,0,0.5)'; 15450 } 15451 c.fill(); 15452 15453 c.beginPath(); 15454 15455 // render previous positions 15456 for (i = 0; i < bodies.length; i++) { 15457 body = bodies[i]; 15458 if (body.render.visible) { 15459 c.arc(body.positionPrev.x, body.positionPrev.y, 2, 0, 2 * Math.PI, false); 15460 c.closePath(); 15461 } 15462 } 15463 15464 c.fillStyle = 'rgba(255,165,0,0.8)'; 15465 c.fill(); 15466 }; 15467 15468 /** 15469 * Draws body velocity 15470 * @private 15471 * @method bodyVelocity 15472 * @param {render} render 15473 * @param {body[]} bodies 15474 * @param {RenderingContext} context 15475 */ 15476 Render.bodyVelocity = function(render, bodies, context) { 15477 var c = context; 15478 15479 c.beginPath(); 15480 15481 for (var i = 0; i < bodies.length; i++) { 15482 var body = bodies[i]; 15483 15484 if (!body.render.visible) 15485 continue; 15486 15487 var velocity = Body.getVelocity(body); 15488 15489 c.moveTo(body.position.x, body.position.y); 15490 c.lineTo(body.position.x + velocity.x, body.position.y + velocity.y); 15491 } 15492 15493 c.lineWidth = 3; 15494 c.strokeStyle = 'cornflowerblue'; 15495 c.stroke(); 15496 }; 15497 15498 /** 15499 * Draws body ids 15500 * @private 15501 * @method bodyIds 15502 * @param {render} render 15503 * @param {body[]} bodies 15504 * @param {RenderingContext} context 15505 */ 15506 Render.bodyIds = function(render, bodies, context) { 15507 var c = context, 15508 i, 15509 j; 15510 15511 for (i = 0; i < bodies.length; i++) { 15512 if (!bodies[i].render.visible) 15513 continue; 15514 15515 var parts = bodies[i].parts; 15516 for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) { 15517 var part = parts[j]; 15518 c.font = "12px Arial"; 15519 c.fillStyle = 'rgba(255,255,255,0.5)'; 15520 c.fillText(part.id, part.position.x + 10, part.position.y - 10); 15521 } 15522 } 15523 }; 15524 15525 /** 15526 * Description 15527 * @private 15528 * @method collisions 15529 * @param {render} render 15530 * @param {pair[]} pairs 15531 * @param {RenderingContext} context 15532 */ 15533 Render.collisions = function(render, pairs, context) { 15534 var c = context, 15535 options = render.options, 15536 pair, 15537 collision, 15538 corrected, 15539 bodyA, 15540 bodyB, 15541 i, 15542 j; 15543 15544 c.beginPath(); 15545 15546 // render collision positions 15547 for (i = 0; i < pairs.length; i++) { 15548 pair = pairs[i]; 15549 15550 if (!pair.isActive) 15551 continue; 15552 15553 collision = pair.collision; 15554 for (j = 0; j < pair.contactCount; j++) { 15555 var contact = pair.contacts[j], 15556 vertex = contact.vertex; 15557 c.rect(vertex.x - 1.5, vertex.y - 1.5, 3.5, 3.5); 15558 } 15559 } 15560 15561 if (options.wireframes) { 15562 c.fillStyle = 'rgba(255,255,255,0.7)'; 15563 } else { 15564 c.fillStyle = 'orange'; 15565 } 15566 c.fill(); 15567 15568 c.beginPath(); 15569 15570 // render collision normals 15571 for (i = 0; i < pairs.length; i++) { 15572 pair = pairs[i]; 15573 15574 if (!pair.isActive) 15575 continue; 15576 15577 collision = pair.collision; 15578 15579 if (pair.contactCount > 0) { 15580 var normalPosX = pair.contacts[0].vertex.x, 15581 normalPosY = pair.contacts[0].vertex.y; 15582 15583 if (pair.contactCount === 2) { 15584 normalPosX = (pair.contacts[0].vertex.x + pair.contacts[1].vertex.x) / 2; 15585 normalPosY = (pair.contacts[0].vertex.y + pair.contacts[1].vertex.y) / 2; 15586 } 15587 15588 if (collision.bodyB === collision.supports[0].body || collision.bodyA.isStatic === true) { 15589 c.moveTo(normalPosX - collision.normal.x * 8, normalPosY - collision.normal.y * 8); 15590 } else { 15591 c.moveTo(normalPosX + collision.normal.x * 8, normalPosY + collision.normal.y * 8); 15592 } 15593 15594 c.lineTo(normalPosX, normalPosY); 15595 } 15596 } 15597 15598 if (options.wireframes) { 15599 c.strokeStyle = 'rgba(255,165,0,0.7)'; 15600 } else { 15601 c.strokeStyle = 'orange'; 15602 } 15603 15604 c.lineWidth = 1; 15605 c.stroke(); 15606 }; 15607 15608 /** 15609 * Description 15610 * @private 15611 * @method separations 15612 * @param {render} render 15613 * @param {pair[]} pairs 15614 * @param {RenderingContext} context 15615 */ 15616 Render.separations = function(render, pairs, context) { 15617 var c = context, 15618 options = render.options, 15619 pair, 15620 collision, 15621 corrected, 15622 bodyA, 15623 bodyB, 15624 i, 15625 j; 15626 15627 c.beginPath(); 15628 15629 // render separations 15630 for (i = 0; i < pairs.length; i++) { 15631 pair = pairs[i]; 15632 15633 if (!pair.isActive) 15634 continue; 15635 15636 collision = pair.collision; 15637 bodyA = collision.bodyA; 15638 bodyB = collision.bodyB; 15639 15640 var k = 1; 15641 15642 if (!bodyB.isStatic && !bodyA.isStatic) k = 0.5; 15643 if (bodyB.isStatic) k = 0; 15644 15645 c.moveTo(bodyB.position.x, bodyB.position.y); 15646 c.lineTo(bodyB.position.x - collision.penetration.x * k, bodyB.position.y - collision.penetration.y * k); 15647 15648 k = 1; 15649 15650 if (!bodyB.isStatic && !bodyA.isStatic) k = 0.5; 15651 if (bodyA.isStatic) k = 0; 15652 15653 c.moveTo(bodyA.position.x, bodyA.position.y); 15654 c.lineTo(bodyA.position.x + collision.penetration.x * k, bodyA.position.y + collision.penetration.y * k); 15655 } 15656 15657 if (options.wireframes) { 15658 c.strokeStyle = 'rgba(255,165,0,0.5)'; 15659 } else { 15660 c.strokeStyle = 'orange'; 15661 } 15662 c.stroke(); 15663 }; 15664 15665 /** 15666 * Description 15667 * @private 15668 * @method inspector 15669 * @param {inspector} inspector 15670 * @param {RenderingContext} context 15671 */ 15672 Render.inspector = function(inspector, context) { 15673 var engine = inspector.engine, 15674 selected = inspector.selected, 15675 render = inspector.render, 15676 options = render.options, 15677 bounds; 15678 15679 if (options.hasBounds) { 15680 var boundsWidth = render.bounds.max.x - render.bounds.min.x, 15681 boundsHeight = render.bounds.max.y - render.bounds.min.y, 15682 boundsScaleX = boundsWidth / render.options.width, 15683 boundsScaleY = boundsHeight / render.options.height; 15684 15685 context.scale(1 / boundsScaleX, 1 / boundsScaleY); 15686 context.translate(-render.bounds.min.x, -render.bounds.min.y); 15687 } 15688 15689 for (var i = 0; i < selected.length; i++) { 15690 var item = selected[i].data; 15691 15692 context.translate(0.5, 0.5); 15693 context.lineWidth = 1; 15694 context.strokeStyle = 'rgba(255,165,0,0.9)'; 15695 context.setLineDash([1,2]); 15696 15697 switch (item.type) { 15698 15699 case 'body': 15700 15701 // render body selections 15702 bounds = item.bounds; 15703 context.beginPath(); 15704 context.rect(Math.floor(bounds.min.x - 3), Math.floor(bounds.min.y - 3), 15705 Math.floor(bounds.max.x - bounds.min.x + 6), Math.floor(bounds.max.y - bounds.min.y + 6)); 15706 context.closePath(); 15707 context.stroke(); 15708 15709 break; 15710 15711 case 'constraint': 15712 15713 // render constraint selections 15714 var point = item.pointA; 15715 if (item.bodyA) 15716 point = item.pointB; 15717 context.beginPath(); 15718 context.arc(point.x, point.y, 10, 0, 2 * Math.PI); 15719 context.closePath(); 15720 context.stroke(); 15721 15722 break; 15723 15724 } 15725 15726 context.setLineDash([]); 15727 context.translate(-0.5, -0.5); 15728 } 15729 15730 // render selection region 15731 if (inspector.selectStart !== null) { 15732 context.translate(0.5, 0.5); 15733 context.lineWidth = 1; 15734 context.strokeStyle = 'rgba(255,165,0,0.6)'; 15735 context.fillStyle = 'rgba(255,165,0,0.1)'; 15736 bounds = inspector.selectBounds; 15737 context.beginPath(); 15738 context.rect(Math.floor(bounds.min.x), Math.floor(bounds.min.y), 15739 Math.floor(bounds.max.x - bounds.min.x), Math.floor(bounds.max.y - bounds.min.y)); 15740 context.closePath(); 15741 context.stroke(); 15742 context.fill(); 15743 context.translate(-0.5, -0.5); 15744 } 15745 15746 if (options.hasBounds) 15747 context.setTransform(1, 0, 0, 1, 0, 0); 15748 }; 15749 15750 /** 15751 * Updates render timing. 15752 * @method _updateTiming 15753 * @private 15754 * @param {render} render 15755 * @param {number} time 15756 */ 15757 var _updateTiming = function(render, time) { 15758 var engine = render.engine, 15759 timing = render.timing, 15760 historySize = timing.historySize, 15761 timestamp = engine.timing.timestamp; 15762 15763 timing.delta = time - timing.lastTime || Render._goodDelta; 15764 timing.lastTime = time; 15765 15766 timing.timestampElapsed = timestamp - timing.lastTimestamp || 0; 15767 timing.lastTimestamp = timestamp; 15768 15769 timing.deltaHistory.unshift(timing.delta); 15770 timing.deltaHistory.length = Math.min(timing.deltaHistory.length, historySize); 15771 15772 timing.engineDeltaHistory.unshift(engine.timing.lastDelta); 15773 timing.engineDeltaHistory.length = Math.min(timing.engineDeltaHistory.length, historySize); 15774 15775 timing.timestampElapsedHistory.unshift(timing.timestampElapsed); 15776 timing.timestampElapsedHistory.length = Math.min(timing.timestampElapsedHistory.length, historySize); 15777 15778 timing.engineUpdatesHistory.unshift(engine.timing.lastUpdatesPerFrame); 15779 timing.engineUpdatesHistory.length = Math.min(timing.engineUpdatesHistory.length, historySize); 15780 15781 timing.engineElapsedHistory.unshift(engine.timing.lastElapsed); 15782 timing.engineElapsedHistory.length = Math.min(timing.engineElapsedHistory.length, historySize); 15783 15784 timing.elapsedHistory.unshift(timing.lastElapsed); 15785 timing.elapsedHistory.length = Math.min(timing.elapsedHistory.length, historySize); 15786 }; 15787 15788 /** 15789 * Returns the mean value of the given numbers. 15790 * @method _mean 15791 * @private 15792 * @param {Number[]} values 15793 * @return {Number} the mean of given values 15794 */ 15795 var _mean = function(values) { 15796 var result = 0; 15797 for (var i = 0; i < values.length; i += 1) { 15798 result += values[i]; 15799 } 15800 return (result / values.length) || 0; 15801 }; 15802 15803 /** 15804 * @method _createCanvas 15805 * @private 15806 * @param {} width 15807 * @param {} height 15808 * @return canvas 15809 */ 15810 var _createCanvas = function(width, height) { 15811 var canvas = document.createElement('canvas'); 15812 canvas.width = width; 15813 canvas.height = height; 15814 canvas.oncontextmenu = function() { return false; }; 15815 canvas.onselectstart = function() { return false; }; 15816 return canvas; 15817 }; 15818 15819 /** 15820 * Gets the pixel ratio of the canvas. 15821 * @method _getPixelRatio 15822 * @private 15823 * @param {HTMLElement} canvas 15824 * @return {Number} pixel ratio 15825 */ 15826 var _getPixelRatio = function(canvas) { 15827 var context = canvas.getContext('2d'), 15828 devicePixelRatio = window.devicePixelRatio || 1, 15829 backingStorePixelRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio 15830 || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio 15831 || context.backingStorePixelRatio || 1; 15832 15833 return devicePixelRatio / backingStorePixelRatio; 15834 }; 15835 15836 /** 15837 * Gets the requested texture (an Image) via its path 15838 * @method _getTexture 15839 * @private 15840 * @param {render} render 15841 * @param {string} imagePath 15842 * @return {Image} texture 15843 */ 15844 var _getTexture = function(render, imagePath) { 15845 var image = render.textures[imagePath]; 15846 15847 if (image) 15848 return image; 15849 15850 image = render.textures[imagePath] = new Image(); 15851 image.src = imagePath; 15852 15853 return image; 15854 }; 15855 15856 /** 15857 * Applies the background to the canvas using CSS. 15858 * @method applyBackground 15859 * @private 15860 * @param {render} render 15861 * @param {string} background 15862 */ 15863 var _applyBackground = function(render, background) { 15864 var cssBackground = background; 15865 15866 if (/(jpg|gif|png)$/.test(background)) 15867 cssBackground = 'url(' + background + ')'; 15868 15869 render.canvas.style.background = cssBackground; 15870 render.canvas.style.backgroundSize = "contain"; 15871 render.currentBackground = background; 15872 }; 15873 15874 /* 15875 * 15876 * Events Documentation 15877 * 15878 */ 15879 15880 /** 15881 * Fired before rendering 15882 * 15883 * @event beforeRender 15884 * @param {} event An event object 15885 * @param {number} event.timestamp The engine.timing.timestamp of the event 15886 * @param {} event.source The source object of the event 15887 * @param {} event.name The name of the event 15888 */ 15889 15890 /** 15891 * Fired after rendering 15892 * 15893 * @event afterRender 15894 * @param {} event An event object 15895 * @param {number} event.timestamp The engine.timing.timestamp of the event 15896 * @param {} event.source The source object of the event 15897 * @param {} event.name The name of the event 15898 */ 15899 15900 /* 15901 * 15902 * Properties Documentation 15903 * 15904 */ 15905 15906 /** 15907 * A back-reference to the `Matter.Render` module. 15908 * 15909 * @deprecated 15910 * @property controller 15911 * @type render 15912 */ 15913 15914 /** 15915 * A reference to the `Matter.Engine` instance to be used. 15916 * 15917 * @property engine 15918 * @type engine 15919 */ 15920 15921 /** 15922 * A reference to the element where the canvas is to be inserted (if `render.canvas` has not been specified) 15923 * 15924 * @property element 15925 * @type HTMLElement 15926 * @default null 15927 */ 15928 15929 /** 15930 * The canvas element to render to. If not specified, one will be created if `render.element` has been specified. 15931 * 15932 * @property canvas 15933 * @type HTMLCanvasElement 15934 * @default null 15935 */ 15936 15937 /** 15938 * A `Bounds` object that specifies the drawing view region. 15939 * Rendering will be automatically transformed and scaled to fit within the canvas size (`render.options.width` and `render.options.height`). 15940 * This allows for creating views that can pan or zoom around the scene. 15941 * You must also set `render.options.hasBounds` to `true` to enable bounded rendering. 15942 * 15943 * @property bounds 15944 * @type bounds 15945 */ 15946 15947 /** 15948 * The 2d rendering context from the `render.canvas` element. 15949 * 15950 * @property context 15951 * @type CanvasRenderingContext2D 15952 */ 15953 15954 /** 15955 * The sprite texture cache. 15956 * 15957 * @property textures 15958 * @type {} 15959 */ 15960 15961 /** 15962 * The mouse to render if `render.options.showMousePosition` is enabled. 15963 * 15964 * @property mouse 15965 * @type mouse 15966 * @default null 15967 */ 15968 15969 /** 15970 * The configuration options of the renderer. 15971 * 15972 * @property options 15973 * @type {} 15974 */ 15975 15976 /** 15977 * The target width in pixels of the `render.canvas` to be created. 15978 * See also the `options.pixelRatio` property to change render quality. 15979 * 15980 * @property options.width 15981 * @type number 15982 * @default 800 15983 */ 15984 15985 /** 15986 * The target height in pixels of the `render.canvas` to be created. 15987 * See also the `options.pixelRatio` property to change render quality. 15988 * 15989 * @property options.height 15990 * @type number 15991 * @default 600 15992 */ 15993 15994 /** 15995 * The [pixel ratio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio) to use when rendering. 15996 * 15997 * @property options.pixelRatio 15998 * @type number 15999 * @default 1 16000 */ 16001 16002 /** 16003 * A CSS background color string to use when `render.options.wireframes` is disabled. 16004 * This may be also set to `'transparent'` or equivalent. 16005 * 16006 * @property options.background 16007 * @type string 16008 * @default '#14151f' 16009 */ 16010 16011 /** 16012 * A CSS color string to use for background when `render.options.wireframes` is enabled. 16013 * This may be also set to `'transparent'` or equivalent. 16014 * 16015 * @property options.wireframeBackground 16016 * @type string 16017 * @default '#14151f' 16018 */ 16019 16020 /** 16021 * A CSS color string to use for stroke when `render.options.wireframes` is enabled. 16022 * This may be also set to `'transparent'` or equivalent. 16023 * 16024 * @property options.wireframeStrokeStyle 16025 * @type string 16026 * @default '#bbb' 16027 */ 16028 16029 /** 16030 * A flag that specifies if `render.bounds` should be used when rendering. 16031 * 16032 * @property options.hasBounds 16033 * @type boolean 16034 * @default false 16035 */ 16036 16037 /** 16038 * A flag to enable or disable all debug information overlays together. 16039 * This includes and has priority over the values of: 16040 * 16041 * - `render.options.showStats` 16042 * - `render.options.showPerformance` 16043 * 16044 * @property options.showDebug 16045 * @type boolean 16046 * @default false 16047 */ 16048 16049 /** 16050 * A flag to enable or disable the engine stats info overlay. 16051 * From left to right, the values shown are: 16052 * 16053 * - body parts total 16054 * - body total 16055 * - constraints total 16056 * - composites total 16057 * - collision pairs total 16058 * 16059 * @property options.showStats 16060 * @type boolean 16061 * @default false 16062 */ 16063 16064 /** 16065 * A flag to enable or disable performance charts. 16066 * From left to right, the values shown are: 16067 * 16068 * - average render frequency (e.g. 60 fps) 16069 * - exact engine delta time used for last update (e.g. 16.66ms) 16070 * - average updates per frame (e.g. 1) 16071 * - average engine execution duration (e.g. 5.00ms) 16072 * - average render execution duration (e.g. 0.40ms) 16073 * - average effective play speed (e.g. '1.00x' is 'real-time') 16074 * 16075 * Each value is recorded over a fixed sample of past frames (60 frames). 16076 * 16077 * A chart shown below each value indicates the variance from the average over the sample. 16078 * The more stable or fixed the value is the flatter the chart will appear. 16079 * 16080 * @property options.showPerformance 16081 * @type boolean 16082 * @default false 16083 */ 16084 16085 /** 16086 * A flag to enable or disable rendering entirely. 16087 * 16088 * @property options.enabled 16089 * @type boolean 16090 * @default false 16091 */ 16092 16093 /** 16094 * A flag to toggle wireframe rendering otherwise solid fill rendering is used. 16095 * 16096 * @property options.wireframes 16097 * @type boolean 16098 * @default true 16099 */ 16100 16101 /** 16102 * A flag to enable or disable sleeping bodies indicators. 16103 * 16104 * @property options.showSleeping 16105 * @type boolean 16106 * @default true 16107 */ 16108 16109 /** 16110 * A flag to enable or disable the debug information overlay. 16111 * 16112 * @property options.showDebug 16113 * @type boolean 16114 * @default false 16115 */ 16116 16117 /** 16118 * A flag to enable or disable the collision broadphase debug overlay. 16119 * 16120 * @deprecated no longer implemented 16121 * @property options.showBroadphase 16122 * @type boolean 16123 * @default false 16124 */ 16125 16126 /** 16127 * A flag to enable or disable the body bounds debug overlay. 16128 * 16129 * @property options.showBounds 16130 * @type boolean 16131 * @default false 16132 */ 16133 16134 /** 16135 * A flag to enable or disable the body velocity debug overlay. 16136 * 16137 * @property options.showVelocity 16138 * @type boolean 16139 * @default false 16140 */ 16141 16142 /** 16143 * A flag to enable or disable the body collisions debug overlay. 16144 * 16145 * @property options.showCollisions 16146 * @type boolean 16147 * @default false 16148 */ 16149 16150 /** 16151 * A flag to enable or disable the collision resolver separations debug overlay. 16152 * 16153 * @property options.showSeparations 16154 * @type boolean 16155 * @default false 16156 */ 16157 16158 /** 16159 * A flag to enable or disable the body axes debug overlay. 16160 * 16161 * @property options.showAxes 16162 * @type boolean 16163 * @default false 16164 */ 16165 16166 /** 16167 * A flag to enable or disable the body positions debug overlay. 16168 * 16169 * @property options.showPositions 16170 * @type boolean 16171 * @default false 16172 */ 16173 16174 /** 16175 * A flag to enable or disable the body angle debug overlay. 16176 * 16177 * @property options.showAngleIndicator 16178 * @type boolean 16179 * @default false 16180 */ 16181 16182 /** 16183 * A flag to enable or disable the body and part ids debug overlay. 16184 * 16185 * @property options.showIds 16186 * @type boolean 16187 * @default false 16188 */ 16189 16190 /** 16191 * A flag to enable or disable the body vertex numbers debug overlay. 16192 * 16193 * @property options.showVertexNumbers 16194 * @type boolean 16195 * @default false 16196 */ 16197 16198 /** 16199 * A flag to enable or disable the body convex hulls debug overlay. 16200 * 16201 * @property options.showConvexHulls 16202 * @type boolean 16203 * @default false 16204 */ 16205 16206 /** 16207 * A flag to enable or disable the body internal edges debug overlay. 16208 * 16209 * @property options.showInternalEdges 16210 * @type boolean 16211 * @default false 16212 */ 16213 16214 /** 16215 * A flag to enable or disable the mouse position debug overlay. 16216 * 16217 * @property options.showMousePosition 16218 * @type boolean 16219 * @default false 16220 */ 16221 16222})(); 16223 16224 16225/***/ }), 16226/* 27 */ 16227/***/ (function(module, exports, __webpack_require__) { 16228 16229/** 16230* The `Matter.Runner` module is an optional utility that provides a game loop for running a `Matter.Engine` inside a browser environment. 16231* A runner will continuously update a `Matter.Engine` whilst synchronising engine updates with the browser frame rate. 16232* This runner favours a smoother user experience over perfect time keeping. 16233* This runner is optional and is used for development and debugging but could be useful as a starting point for implementing some games and experiences. 16234* Alternatively see `Engine.update` to step the engine directly inside your own game loop implementation as may be needed inside other environments. 16235* 16236* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 16237* 16238* @class Runner 16239*/ 16240 16241var Runner = {}; 16242 16243module.exports = Runner; 16244 16245var Events = __webpack_require__(5); 16246var Engine = __webpack_require__(17); 16247var Common = __webpack_require__(0); 16248 16249(function() { 16250 16251 Runner._maxFrameDelta = 1000 / 15; 16252 Runner._frameDeltaFallback = 1000 / 60; 16253 Runner._timeBufferMargin = 1.5; 16254 Runner._elapsedNextEstimate = 1; 16255 Runner._smoothingLowerBound = 0.1; 16256 Runner._smoothingUpperBound = 0.9; 16257 16258 /** 16259 * Creates a new Runner. 16260 * See the properties section below for detailed information on what you can pass via the `options` object. 16261 * @method create 16262 * @param {} options 16263 */ 16264 Runner.create = function(options) { 16265 var defaults = { 16266 delta: 1000 / 60, 16267 frameDelta: null, 16268 frameDeltaSmoothing: true, 16269 frameDeltaSnapping: true, 16270 frameDeltaHistory: [], 16271 frameDeltaHistorySize: 100, 16272 frameRequestId: null, 16273 timeBuffer: 0, 16274 timeLastTick: null, 16275 maxUpdates: null, 16276 maxFrameTime: 1000 / 30, 16277 lastUpdatesDeferred: 0, 16278 enabled: true 16279 }; 16280 16281 var runner = Common.extend(defaults, options); 16282 16283 // for temporary back compatibility only 16284 runner.fps = 0; 16285 16286 return runner; 16287 }; 16288 16289 /** 16290 * Runs a `Matter.Engine` whilst synchronising engine updates with the browser frame rate. 16291 * See module and properties descriptions for more information on this runner. 16292 * Alternatively see `Engine.update` to step the engine directly inside your own game loop implementation. 16293 * @method run 16294 * @param {runner} runner 16295 * @param {engine} [engine] 16296 * @return {runner} runner 16297 */ 16298 Runner.run = function(runner, engine) { 16299 // initial time buffer for the first frame 16300 runner.timeBuffer = Runner._frameDeltaFallback; 16301 16302 (function onFrame(time){ 16303 runner.frameRequestId = Runner._onNextFrame(runner, onFrame); 16304 16305 if (time && runner.enabled) { 16306 Runner.tick(runner, engine, time); 16307 } 16308 })(); 16309 16310 return runner; 16311 }; 16312 16313 /** 16314 * Performs a single runner tick as used inside `Runner.run`. 16315 * See module and properties descriptions for more information on this runner. 16316 * Alternatively see `Engine.update` to step the engine directly inside your own game loop implementation. 16317 * @method tick 16318 * @param {runner} runner 16319 * @param {engine} engine 16320 * @param {number} time 16321 */ 16322 Runner.tick = function(runner, engine, time) { 16323 var tickStartTime = Common.now(), 16324 engineDelta = runner.delta, 16325 updateCount = 0; 16326 16327 // find frame delta time since last call 16328 var frameDelta = time - runner.timeLastTick; 16329 16330 // fallback for unusable frame delta values (e.g. 0, NaN, on first frame or long pauses) 16331 if (!frameDelta || !runner.timeLastTick || frameDelta > Math.max(Runner._maxFrameDelta, runner.maxFrameTime)) { 16332 // reuse last accepted frame delta else fallback 16333 frameDelta = runner.frameDelta || Runner._frameDeltaFallback; 16334 } 16335 16336 if (runner.frameDeltaSmoothing) { 16337 // record frame delta over a number of frames 16338 runner.frameDeltaHistory.push(frameDelta); 16339 runner.frameDeltaHistory = runner.frameDeltaHistory.slice(-runner.frameDeltaHistorySize); 16340 16341 // sort frame delta history 16342 var deltaHistorySorted = runner.frameDeltaHistory.slice(0).sort(); 16343 16344 // sample a central window to limit outliers 16345 var deltaHistoryWindow = runner.frameDeltaHistory.slice( 16346 deltaHistorySorted.length * Runner._smoothingLowerBound, 16347 deltaHistorySorted.length * Runner._smoothingUpperBound 16348 ); 16349 16350 // take the mean of the central window 16351 var frameDeltaSmoothed = _mean(deltaHistoryWindow); 16352 frameDelta = frameDeltaSmoothed || frameDelta; 16353 } 16354 16355 if (runner.frameDeltaSnapping) { 16356 // snap frame delta to the nearest 1 Hz 16357 frameDelta = 1000 / Math.round(1000 / frameDelta); 16358 } 16359 16360 // update runner values for next call 16361 runner.frameDelta = frameDelta; 16362 runner.timeLastTick = time; 16363 16364 // accumulate elapsed time 16365 runner.timeBuffer += runner.frameDelta; 16366 16367 // limit time buffer size to a single frame of updates 16368 runner.timeBuffer = Common.clamp( 16369 runner.timeBuffer, 0, runner.frameDelta + engineDelta * Runner._timeBufferMargin 16370 ); 16371 16372 // reset count of over budget updates 16373 runner.lastUpdatesDeferred = 0; 16374 16375 // get max updates per frame 16376 var maxUpdates = runner.maxUpdates || Math.ceil(runner.maxFrameTime / engineDelta); 16377 16378 // create event object 16379 var event = { 16380 timestamp: engine.timing.timestamp 16381 }; 16382 16383 // tick events before update 16384 Events.trigger(runner, 'beforeTick', event); 16385 Events.trigger(runner, 'tick', event); 16386 16387 var updateStartTime = Common.now(); 16388 16389 // simulate time elapsed between calls 16390 while (engineDelta > 0 && runner.timeBuffer >= engineDelta * Runner._timeBufferMargin) { 16391 // update the engine 16392 Events.trigger(runner, 'beforeUpdate', event); 16393 Engine.update(engine, engineDelta); 16394 Events.trigger(runner, 'afterUpdate', event); 16395 16396 // consume time simulated from buffer 16397 runner.timeBuffer -= engineDelta; 16398 updateCount += 1; 16399 16400 // find elapsed time during this tick 16401 var elapsedTimeTotal = Common.now() - tickStartTime, 16402 elapsedTimeUpdates = Common.now() - updateStartTime, 16403 elapsedNextEstimate = elapsedTimeTotal + Runner._elapsedNextEstimate * elapsedTimeUpdates / updateCount; 16404 16405 // defer updates if over performance budgets for this frame 16406 if (updateCount >= maxUpdates || elapsedNextEstimate > runner.maxFrameTime) { 16407 runner.lastUpdatesDeferred = Math.round(Math.max(0, (runner.timeBuffer / engineDelta) - Runner._timeBufferMargin)); 16408 break; 16409 } 16410 } 16411 16412 // track timing metrics 16413 engine.timing.lastUpdatesPerFrame = updateCount; 16414 16415 // tick events after update 16416 Events.trigger(runner, 'afterTick', event); 16417 16418 // show useful warnings if needed 16419 if (runner.frameDeltaHistory.length >= 100) { 16420 if (runner.lastUpdatesDeferred && Math.round(runner.frameDelta / engineDelta) > maxUpdates) { 16421 Common.warnOnce('Matter.Runner: runner reached runner.maxUpdates, see docs.'); 16422 } else if (runner.lastUpdatesDeferred) { 16423 Common.warnOnce('Matter.Runner: runner reached runner.maxFrameTime, see docs.'); 16424 } 16425 16426 if (typeof runner.isFixed !== 'undefined') { 16427 Common.warnOnce('Matter.Runner: runner.isFixed is now redundant, see docs.'); 16428 } 16429 16430 if (runner.deltaMin || runner.deltaMax) { 16431 Common.warnOnce('Matter.Runner: runner.deltaMin and runner.deltaMax were removed, see docs.'); 16432 } 16433 16434 if (runner.fps !== 0) { 16435 Common.warnOnce('Matter.Runner: runner.fps was replaced by runner.delta, see docs.'); 16436 } 16437 } 16438 }; 16439 16440 /** 16441 * Ends execution of `Runner.run` on the given `runner` by canceling the frame loop. 16442 * Alternatively to temporarily pause the runner, see `runner.enabled`. 16443 * @method stop 16444 * @param {runner} runner 16445 */ 16446 Runner.stop = function(runner) { 16447 Runner._cancelNextFrame(runner); 16448 }; 16449 16450 /** 16451 * Schedules the `callback` on this `runner` for the next animation frame. 16452 * @private 16453 * @method _onNextFrame 16454 * @param {runner} runner 16455 * @param {function} callback 16456 * @return {number} frameRequestId 16457 */ 16458 Runner._onNextFrame = function(runner, callback) { 16459 if (typeof window !== 'undefined' && window.requestAnimationFrame) { 16460 runner.frameRequestId = window.requestAnimationFrame(callback); 16461 } else { 16462 throw new Error('Matter.Runner: missing required global window.requestAnimationFrame.'); 16463 } 16464 16465 return runner.frameRequestId; 16466 }; 16467 16468 /** 16469 * Cancels the last callback scheduled by `Runner._onNextFrame` on this `runner`. 16470 * @private 16471 * @method _cancelNextFrame 16472 * @param {runner} runner 16473 */ 16474 Runner._cancelNextFrame = function(runner) { 16475 if (typeof window !== 'undefined' && window.cancelAnimationFrame) { 16476 window.cancelAnimationFrame(runner.frameRequestId); 16477 } else { 16478 throw new Error('Matter.Runner: missing required global window.cancelAnimationFrame.'); 16479 } 16480 }; 16481 16482 /** 16483 * Returns the mean of the given numbers. 16484 * @method _mean 16485 * @private 16486 * @param {Number[]} values 16487 * @return {Number} the mean of given values. 16488 */ 16489 var _mean = function(values) { 16490 var result = 0, 16491 valuesLength = values.length; 16492 16493 for (var i = 0; i < valuesLength; i += 1) { 16494 result += values[i]; 16495 } 16496 16497 return (result / valuesLength) || 0; 16498 }; 16499 16500 /* 16501 * 16502 * Events Documentation 16503 * 16504 */ 16505 16506 /** 16507 * Fired once at the start of the browser frame, before any engine updates. 16508 * 16509 * @event beforeTick 16510 * @param {} event An event object 16511 * @param {number} event.timestamp The engine.timing.timestamp of the event 16512 * @param {} event.source The source object of the event 16513 * @param {} event.name The name of the event 16514 */ 16515 16516 /** 16517 * Fired once at the start of the browser frame, after `beforeTick`. 16518 * 16519 * @event tick 16520 * @param {} event An event object 16521 * @param {number} event.timestamp The engine.timing.timestamp of the event 16522 * @param {} event.source The source object of the event 16523 * @param {} event.name The name of the event 16524 */ 16525 16526 /** 16527 * Fired once at the end of the browser frame, after `beforeTick`, `tick` and after any engine updates. 16528 * 16529 * @event afterTick 16530 * @param {} event An event object 16531 * @param {number} event.timestamp The engine.timing.timestamp of the event 16532 * @param {} event.source The source object of the event 16533 * @param {} event.name The name of the event 16534 */ 16535 16536 /** 16537 * Fired before each and every engine update in this browser frame (if any). 16538 * There may be multiple engine update calls per browser frame (or none) depending on framerate and timestep delta. 16539 * 16540 * @event beforeUpdate 16541 * @param {} event An event object 16542 * @param {number} event.timestamp The engine.timing.timestamp of the event 16543 * @param {} event.source The source object of the event 16544 * @param {} event.name The name of the event 16545 */ 16546 16547 /** 16548 * Fired after each and every engine update in this browser frame (if any). 16549 * There may be multiple engine update calls per browser frame (or none) depending on framerate and timestep delta. 16550 * 16551 * @event afterUpdate 16552 * @param {} event An event object 16553 * @param {number} event.timestamp The engine.timing.timestamp of the event 16554 * @param {} event.source The source object of the event 16555 * @param {} event.name The name of the event 16556 */ 16557 16558 /* 16559 * 16560 * Properties Documentation 16561 * 16562 */ 16563 16564 /** 16565 * The fixed timestep size used for `Engine.update` calls in milliseconds, known as `delta`. 16566 * 16567 * This value is recommended to be `1000 / 60` ms or smaller (i.e. equivalent to at least 60hz). 16568 * 16569 * Smaller `delta` values provide higher quality results at the cost of performance. 16570 * 16571 * You should usually avoid changing `delta` during running, otherwise quality may be affected. 16572 * 16573 * For smoother frame pacing choose a `delta` that is an even multiple of each display FPS you target, i.e. `1000 / (n * fps)` as this helps distribute an equal number of updates over each display frame. 16574 * 16575 * For example with a 60 Hz `delta` i.e. `1000 / 60` the runner will on average perform one update per frame on displays running 60 FPS and one update every two frames on displays running 120 FPS, etc. 16576 * 16577 * Where as e.g. using a 240 Hz `delta` i.e. `1000 / 240` the runner will on average perform four updates per frame on displays running 60 FPS and two updates per frame on displays running 120 FPS, etc. 16578 * 16579 * Therefore `Runner.run` will call multiple engine updates (or none) as needed to simulate the time elapsed between browser frames. 16580 * 16581 * In practice the number of updates in any particular frame may be restricted to respect the runner's performance budgets. These are specified by `runner.maxFrameTime` and `runner.maxUpdates`, see those properties for details. 16582 * 16583 * @property delta 16584 * @type number 16585 * @default 1000 / 60 16586 */ 16587 16588 /** 16589 * A flag that can be toggled to enable or disable tick calls on this runner, therefore pausing engine updates and events while the runner loop remains running. 16590 * 16591 * @property enabled 16592 * @type boolean 16593 * @default true 16594 */ 16595 16596 /** 16597 * The accumulated time elapsed that has yet to be simulated in milliseconds. 16598 * This value is clamped within certain limits (see `Runner.tick` code). 16599 * 16600 * @private 16601 * @property timeBuffer 16602 * @type number 16603 * @default 0 16604 */ 16605 16606 /** 16607 * The measured time elapsed between the last two browser frames measured in milliseconds. 16608 * This is useful e.g. to estimate the current browser FPS using `1000 / runner.frameDelta`. 16609 * 16610 * @readonly 16611 * @property frameDelta 16612 * @type number 16613 */ 16614 16615 /** 16616 * Enables averaging to smooth frame rate measurements and therefore stabilise play rate. 16617 * 16618 * @property frameDeltaSmoothing 16619 * @type boolean 16620 * @default true 16621 */ 16622 16623 /** 16624 * Rounds measured browser frame delta to the nearest 1 Hz. 16625 * This option can help smooth frame rate measurements and simplify handling hardware timing differences e.g. 59.94Hz and 60Hz displays. 16626 * For best results you should also round your `runner.delta` equivalent to the nearest 1 Hz. 16627 * 16628 * @property frameDeltaSnapping 16629 * @type boolean 16630 * @default true 16631 */ 16632 16633 /** 16634 * A performance budget that limits execution time allowed for this runner per browser frame in milliseconds. 16635 * 16636 * To calculate the effective browser FPS at which this throttle is applied use `1000 / runner.maxFrameTime`. 16637 * 16638 * This performance budget is intended to help maintain browser interactivity and help improve framerate recovery during temporary high CPU usage. 16639 * 16640 * This budget only covers the measured time elapsed executing the functions called in the scope of the runner tick, including `Engine.update` and its related user event callbacks. 16641 * 16642 * You may also reduce this budget to allow for any significant additional processing you perform on the same thread outside the scope of this runner tick, e.g. rendering time. 16643 * 16644 * See also `runner.maxUpdates`. 16645 * 16646 * @property maxFrameTime 16647 * @type number 16648 * @default 1000 / 30 16649 */ 16650 16651 /** 16652 * An optional limit for maximum engine update count allowed per frame tick in addition to `runner.maxFrameTime`. 16653 * 16654 * Unless you set a value it is automatically chosen based on `runner.delta` and `runner.maxFrameTime`. 16655 * 16656 * See also `runner.maxFrameTime`. 16657 * 16658 * @property maxUpdates 16659 * @type number 16660 * @default null 16661 */ 16662 16663 /** 16664 * The timestamp of the last call to `Runner.tick` used to measure `frameDelta`. 16665 * 16666 * @private 16667 * @property timeLastTick 16668 * @type number 16669 * @default 0 16670 */ 16671 16672 /** 16673 * The id of the last call to `Runner._onNextFrame`. 16674 * 16675 * @private 16676 * @property frameRequestId 16677 * @type number 16678 * @default null 16679 */ 16680 16681})(); 16682 16683 16684/***/ }), 16685/* 28 */ 16686/***/ (function(module, exports, __webpack_require__) { 16687 16688/** 16689* This module has now been replaced by `Matter.Collision`. 16690* 16691* All usage should be migrated to `Matter.Collision`. 16692* For back-compatibility purposes this module will remain for a short term and then later removed in a future release. 16693* 16694* The `Matter.SAT` module contains methods for detecting collisions using the Separating Axis Theorem. 16695* 16696* @class SAT 16697* @deprecated 16698*/ 16699 16700var SAT = {}; 16701 16702module.exports = SAT; 16703 16704var Collision = __webpack_require__(8); 16705var Common = __webpack_require__(0); 16706var deprecated = Common.deprecated; 16707 16708(function() { 16709 16710 /** 16711 * Detect collision between two bodies using the Separating Axis Theorem. 16712 * @deprecated replaced by Collision.collides 16713 * @method collides 16714 * @param {body} bodyA 16715 * @param {body} bodyB 16716 * @return {collision} collision 16717 */ 16718 SAT.collides = function(bodyA, bodyB) { 16719 return Collision.collides(bodyA, bodyB); 16720 }; 16721 16722 deprecated(SAT, 'collides', 'SAT.collides ⤠replaced by Collision.collides'); 16723 16724})(); 16725 16726 16727/***/ }), 16728/* 29 */ 16729/***/ (function(module, exports, __webpack_require__) { 16730 16731/** 16732* The `Matter.Svg` module contains methods for converting SVG images into an array of vector points. 16733* 16734* To use this module you also need the SVGPathSeg polyfill: https://github.com/progers/pathseg 16735* 16736* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). 16737* 16738* @class Svg 16739*/ 16740 16741var Svg = {}; 16742 16743module.exports = Svg; 16744 16745var Bounds = __webpack_require__(1); 16746var Common = __webpack_require__(0); 16747 16748(function() { 16749 16750 /** 16751 * Converts an SVG path into an array of vector points. 16752 * If the input path forms a concave shape, you must decompose the result into convex parts before use. 16753 * See `Bodies.fromVertices` which provides support for this. 16754 * Note that this function is not guaranteed to support complex paths (such as those with holes). 16755 * You must load the `pathseg.js` polyfill on newer browsers. 16756 * @method pathToVertices 16757 * @param {SVGPathElement} path 16758 * @param {Number} [sampleLength=15] 16759 * @return {Vector[]} points 16760 */ 16761 Svg.pathToVertices = function(path, sampleLength) { 16762 if (typeof window !== 'undefined' && !('SVGPathSeg' in window)) { 16763 Common.warn('Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.'); 16764 } 16765 16766 // https://github.com/wout/svg.topoly.js/blob/master/svg.topoly.js 16767 var i, il, total, point, segment, segments, 16768 segmentsQueue, lastSegment, 16769 lastPoint, segmentIndex, points = [], 16770 lx, ly, length = 0, x = 0, y = 0; 16771 16772 sampleLength = sampleLength || 15; 16773 16774 var addPoint = function(px, py, pathSegType) { 16775 // all odd-numbered path types are relative except PATHSEG_CLOSEPATH (1) 16776 var isRelative = pathSegType % 2 === 1 && pathSegType > 1; 16777 16778 // when the last point doesn't equal the current point add the current point 16779 if (!lastPoint || px != lastPoint.x || py != lastPoint.y) { 16780 if (lastPoint && isRelative) { 16781 lx = lastPoint.x; 16782 ly = lastPoint.y; 16783 } else { 16784 lx = 0; 16785 ly = 0; 16786 } 16787 16788 var point = { 16789 x: lx + px, 16790 y: ly + py 16791 }; 16792 16793 // set last point 16794 if (isRelative || !lastPoint) { 16795 lastPoint = point; 16796 } 16797 16798 points.push(point); 16799 16800 x = lx + px; 16801 y = ly + py; 16802 } 16803 }; 16804 16805 var addSegmentPoint = function(segment) { 16806 var segType = segment.pathSegTypeAsLetter.toUpperCase(); 16807 16808 // skip path ends 16809 if (segType === 'Z') 16810 return; 16811 16812 // map segment to x and y 16813 switch (segType) { 16814 16815 case 'M': 16816 case 'L': 16817 case 'T': 16818 case 'C': 16819 case 'S': 16820 case 'Q': 16821 x = segment.x; 16822 y = segment.y; 16823 break; 16824 case 'H': 16825 x = segment.x; 16826 break; 16827 case 'V': 16828 y = segment.y; 16829 break; 16830 } 16831 16832 addPoint(x, y, segment.pathSegType); 16833 }; 16834 16835 // ensure path is absolute 16836 Svg._svgPathToAbsolute(path); 16837 16838 // get total length 16839 total = path.getTotalLength(); 16840 16841 // queue segments 16842 segments = []; 16843 for (i = 0; i < path.pathSegList.numberOfItems; i += 1) 16844 segments.push(path.pathSegList.getItem(i)); 16845 16846 segmentsQueue = segments.concat(); 16847 16848 // sample through path 16849 while (length < total) { 16850 // get segment at position 16851 segmentIndex = path.getPathSegAtLength(length); 16852 segment = segments[segmentIndex]; 16853 16854 // new segment 16855 if (segment != lastSegment) { 16856 while (segmentsQueue.length && segmentsQueue[0] != segment) 16857 addSegmentPoint(segmentsQueue.shift()); 16858 16859 lastSegment = segment; 16860 } 16861 16862 // add points in between when curving 16863 // TODO: adaptive sampling 16864 switch (segment.pathSegTypeAsLetter.toUpperCase()) { 16865 16866 case 'C': 16867 case 'T': 16868 case 'S': 16869 case 'Q': 16870 case 'A': 16871 point = path.getPointAtLength(length); 16872 addPoint(point.x, point.y, 0); 16873 break; 16874 16875 } 16876 16877 // increment by sample value 16878 length += sampleLength; 16879 } 16880 16881 // add remaining segments not passed by sampling 16882 for (i = 0, il = segmentsQueue.length; i < il; ++i) 16883 addSegmentPoint(segmentsQueue[i]); 16884 16885 return points; 16886 }; 16887 16888 Svg._svgPathToAbsolute = function(path) { 16889 // http://phrogz.net/convert-svg-path-to-all-absolute-commands 16890 // Copyright (c) Gavin Kistner 16891 // http://phrogz.net/js/_ReuseLicense.txt 16892 // Modifications: tidy formatting and naming 16893 var x0, y0, x1, y1, x2, y2, segs = path.pathSegList, 16894 x = 0, y = 0, len = segs.numberOfItems; 16895 16896 for (var i = 0; i < len; ++i) { 16897 var seg = segs.getItem(i), 16898 segType = seg.pathSegTypeAsLetter; 16899 16900 if (/[MLHVCSQTA]/.test(segType)) { 16901 if ('x' in seg) x = seg.x; 16902 if ('y' in seg) y = seg.y; 16903 } else { 16904 if ('x1' in seg) x1 = x + seg.x1; 16905 if ('x2' in seg) x2 = x + seg.x2; 16906 if ('y1' in seg) y1 = y + seg.y1; 16907 if ('y2' in seg) y2 = y + seg.y2; 16908 if ('x' in seg) x += seg.x; 16909 if ('y' in seg) y += seg.y; 16910 16911 switch (segType) { 16912 16913 case 'm': 16914 segs.replaceItem(path.createSVGPathSegMovetoAbs(x, y), i); 16915 break; 16916 case 'l': 16917 segs.replaceItem(path.createSVGPathSegLinetoAbs(x, y), i); 16918 break; 16919 case 'h': 16920 segs.replaceItem(path.createSVGPathSegLinetoHorizontalAbs(x), i); 16921 break; 16922 case 'v': 16923 segs.replaceItem(path.createSVGPathSegLinetoVerticalAbs(y), i); 16924 break; 16925 case 'c': 16926 segs.replaceItem(path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2), i); 16927 break; 16928 case 's': 16929 segs.replaceItem(path.createSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2), i); 16930 break; 16931 case 'q': 16932 segs.replaceItem(path.createSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1), i); 16933 break; 16934 case 't': 16935 segs.replaceItem(path.createSVGPathSegCurvetoQuadraticSmoothAbs(x, y), i); 16936 break; 16937 case 'a': 16938 segs.replaceItem(path.createSVGPathSegArcAbs(x, y, seg.r1, seg.r2, seg.angle, seg.largeArcFlag, seg.sweepFlag), i); 16939 break; 16940 case 'z': 16941 case 'Z': 16942 x = x0; 16943 y = y0; 16944 break; 16945 16946 } 16947 } 16948 16949 if (segType == 'M' || segType == 'm') { 16950 x0 = x; 16951 y0 = y; 16952 } 16953 } 16954 }; 16955 16956})(); 16957 16958/***/ }), 16959/* 30 */ 16960/***/ (function(module, exports, __webpack_require__) { 16961 16962/** 16963* This module has now been replaced by `Matter.Composite`. 16964* 16965* All usage should be migrated to the equivalent functions found on `Matter.Composite`. 16966* For example `World.add(world, body)` now becomes `Composite.add(world, body)`. 16967* 16968* The property `world.gravity` has been moved to `engine.gravity`. 16969* 16970* For back-compatibility purposes this module will remain as a direct alias to `Matter.Composite` in the short term during migration. 16971* Eventually this alias module will be marked as deprecated and then later removed in a future release. 16972* 16973* @class World 16974*/ 16975 16976var World = {}; 16977 16978module.exports = World; 16979 16980var Composite = __webpack_require__(6); 16981var Common = __webpack_require__(0); 16982 16983(function() { 16984 16985 /** 16986 * See above, aliases for back compatibility only 16987 */ 16988 World.create = Composite.create; 16989 World.add = Composite.add; 16990 World.remove = Composite.remove; 16991 World.clear = Composite.clear; 16992 World.addComposite = Composite.addComposite; 16993 World.addBody = Composite.addBody; 16994 World.addConstraint = Composite.addConstraint; 16995 16996})(); 16997 16998 16999/***/ }) 17000/******/ ]); 17001});
17001 17002/** 17003 * fitty v2.4.2 (beautified + ECMA5-compatible) 17004 * Snugly resizes text to fit its parent container 17005 * Copyright (c) 2023 Rik Schennink 17006 */ 17007 17008(function (root, factory) { 17009 if (typeof exports === "object" && typeof module !== "undefined") { 17010 module.exports = factory(); 17011 } else if (typeof define === "function" && define.amd) { 17012 define(factory); 17013 } else { 17014 root.fitty = factory(); 17015 } 17016})(typeof self !== "undefined" ? self : this, function () { 17017 "use strict"; 17018 17019 return function (win) { 17020 if (!win) return; 17021 17022 // ------------------------------------------------------------------------- 17023 // Helpers (ES5-safe) 17024 // ------------------------------------------------------------------------- 17025 17026 function toArray(list) { 17027 return [].slice.call(list); 17028 } 17029 17030 function extend(target) { 17031 target = target || {}; 17032 for (var i = 1; i < arguments.length; i++) { 17033 var src = arguments[i]; 17034 if (!src) continue; 17035 for (var k in src) { 17036 if (Object.prototype.hasOwnProperty.call(src, k)) { 17037 target[k] = src[k]; 17038 } 17039 } 17040 } 17041 return target; 17042 } 17043 17044 function createCustomEvent(name, detail) { 17045 // CustomEvent is not supported in older browsers, fallback to document.createEvent 17046 try { 17047 return new CustomEvent(name, { detail: detail }); 17048 } catch (e) { 17049 var ev = document.createEvent("CustomEvent"); 17050 ev.initCustomEvent(name, false, false, detail); 17051 return ev; 17052 } 17053 } 17054 17055 // ------------------------------------------------------------------------- 17056 // Internal state 17057 // ------------------------------------------------------------------------- 17058 17059 var DIRTY_INIT = 0; 17060 var DIRTY_MUTATION = 1; 17061 var DIRTY_LAYOUT = 2; 17062 var DIRTY_FORCE = 3; 17063 17064 var instances = []; 17065 var rafId = null; 17066 17067 // requestAnimationFrame wrapper 17068 var requestTick = 17069 "requestAnimationFrame" in win 17070 ? function (opts) { 17071 opts = opts || { sync: false }; 17072 17073 win.cancelAnimationFrame(rafId); 17074 17075 function run() { 17076 var activeDirty = instances.filter(function (item) { 17077 return item.dirty && item.active; 17078 }); 17079 return process(activeDirty); 17080 } 17081 17082 if (opts.sync) return run(); 17083 17084 rafId = win.requestAnimationFrame(run); 17085 } 17086 : function () {}; 17087 17088 // Marks all instances as dirty (type) and triggers a tick 17089 function markAllDirty(type) { 17090 return function (opts) { 17091 instances.forEach(function (item) { 17092 item.dirty = type; 17093 }); 17094 requestTick(opts); 17095 }; 17096 } 17097 17098 // Process a batch of instances 17099 function process(batch) { 17100 // Compute styles once 17101 batch 17102 .filter(function (item) { 17103 return !item.styleComputed; 17104 }) 17105 .forEach(function (item) { 17106 item.styleComputed = computeStyle(item); 17107 }); 17108 17109 // Pre-style test and apply fixes if needed 17110 batch.filter(needsPreStyleFix).forEach(applyStyles); 17111 17112 // Items that need layout recalculation 17113 var toLayout = batch.filter(needsLayout); 17114 toLayout.forEach(calcLayout); 17115 toLayout.forEach(function (item) { 17116 applyStyles(item); 17117 clean(item); 17118 }); 17119 toLayout.forEach(dispatchFitEvent); 17120 } 17121 17122 function clean(item) { 17123 item.dirty = DIRTY_INIT; 17124 return item.dirty; 17125 } 17126 17127 function calcLayout(item) { 17128 item.availableWidth = item.element.parentNode.clientWidth; 17129 item.currentWidth = item.element.scrollWidth; 17130 17131 item.previousFontSize = item.currentFontSize; 17132 17133 // Scale font size into [minSize, maxSize] 17134 var scaled = (item.availableWidth / item.currentWidth) * item.previousFontSize; 17135 var clamped = Math.min(Math.max(item.minSize, scaled), item.maxSize); 17136 item.currentFontSize = clamped; 17137 17138 item.whiteSpace = 17139 item.multiLine && item.currentFontSize === item.minSize ? "normal" : "nowrap"; 17140 } 17141 17142 function needsLayout(item) { 17143 return ( 17144 item.dirty !== DIRTY_LAYOUT || 17145 (item.dirty === DIRTY_LAYOUT && 17146 item.element.parentNode.clientWidth !== item.availableWidth) 17147 ); 17148 } 17149 17150 function computeStyle(item) { 17151 var cs = win.getComputedStyle(item.element, null); 17152 item.currentFontSize = parseFloat(cs.getPropertyValue("font-size")); 17153 item.display = cs.getPropertyValue("display"); 17154 item.whiteSpace = cs.getPropertyValue("white-space"); 17155 return true; 17156 } 17157 17158 function needsPreStyleFix(item) { 17159 var changed = false;
17160 17161 if (!item.preStyleTestCompleted) { 17162 // Force a measurable layout for inline elements 17163 if (/inline-/.test(item.display)) { 17164 changed = true; 17165 item.display = "inline-block"; 17166 } 17167 17168 // Force nowrap while measuring 17169 if (item.whiteSpace !== "nowrap") { 17170 changed = true; 17171 item.whiteSpace = "nowrap"; 17172 } 17173 17174 item.preStyleTestCompleted = true; 17175 } 17176 17177 return changed; 17178 } 17179 17180 function applyStyles(item) { 17181 item.element.style.whiteSpace = item.whiteSpace; 17182 item.element.style.display = item.display; 17183 item.element.style.fontSize = item.currentFontSize + "px"; 17184 } 17185 17186 function dispatchFitEvent(item) { 17187 var detail = { 17188 oldValue: item.previousFontSize, 17189 newValue: item.currentFontSize, 17190 scaleFactor: item.currentFontSize / item.previousFontSize 17191 }; 17192 17193 item.element.dispatchEvent(createCustomEvent("fit", detail)); 17194 } 17195 17196 function onMutation(item, dirtyType) { 17197 return function (opts) { 17198 item.dirty = dirtyType; 17199 if (item.active) requestTick(opts); 17200 }; 17201 } 17202 17203 function unsubscribe(item) { 17204 return function () { 17205 instances = instances.filter(function (x) { 17206 return x.element !== item.element; 17207 }); 17208 17209 if (item.observeMutations && item.observer) { 17210 item.observer.disconnect(); 17211 } 17212 17213 item.element.style.whiteSpace = item.originalStyle.whiteSpace; 17214 item.element.style.display = item.originalStyle.display; 17215 item.element.style.fontSize = item.originalStyle.fontSize; 17216 }; 17217 } 17218 17219 function unfreeze(item) { 17220 return function () { 17221 if (!item.active) { 17222 item.active = true; 17223 requestTick(); 17224 } 17225 }; 17226 } 17227 17228 function freeze(item) { 17229 return function () { 17230 item.active = false; 17231 }; 17232 } 17233 17234 function observeMutations(item) { 17235 if (item.observeMutations) { 17236 item.observer = new MutationObserver(onMutation(item, DIRTY_MUTATION)); 17237 item.observer.observe(item.element, item.observeMutations); 17238 } 17239 } 17240 17241 // ------------------------------------------------------------------------- 17242 // Defaults + public API 17243 // ------------------------------------------------------------------------- 17244 17245 var defaults = { 17246 minSize: 16, 17247 maxSize: 512, 17248 multiLine: true, 17249 observeMutations: 17250 "MutationObserver" in win && { 17251 subtree: true, 17252 childList: true, 17253 characterData: true 17254 } 17255 }; 17256 17257 var windowDelayTimer = null; 17258 17259 function onWindowResize() { 17260 win.clearTimeout(windowDelayTimer); 17261 windowDelayTimer = win.setTimeout(markAllDirty(DIRTY_LAYOUT), api.observeWindowDelay); 17262 } 17263 17264 var windowEvents = ["resize", "orientationchange"]; 17265 17266 function createInstances(elements, options) { 17267 var config = extend({}, defaults, options); 17268 17269 var result = elements.map(function (el) { 17270 var item = extend({}, config, { element: el, active: true }); 17271 17272 // Init 17273 item.originalStyle = { 17274 whiteSpace: item.element.style.whiteSpace, 17275 display: item.element.style.display, 17276 fontSize: item.element.style.fontSize 17277 }; 17278 17279 observeMutations(item); 17280 17281 item.newbie = true; 17282 item.dirty = true; 17283 17284 instances.push(item); 17285 17286 return { 17287 element: el, 17288 fit: onMutation(item, DIRTY_FORCE), 17289 unfreeze: unfreeze(item), 17290 freeze: freeze(item), 17291 unsubscribe: unsubscribe(item) 17292 }; 17293 }); 17294 17295 requestTick(); 17296 return result; 17297 } 17298 17299 function api(input, options) { 17300 options = options || {}; 17301 17302 if (typeof input === "string") { 17303 return createInstances(toArray(document.querySelectorAll(input)), options); 17304 } 17305 17306 // Single element 17307 return createInstances([input], options)[0]; 17308 } 17309 17310 // Observe window changes (setter) 17311 Object.defineProperty(api, "observeWindow", { 17312 set: function (enabled) { 17313 var method = (enabled ? "add" : "remove") + "EventListener";
17314 windowEvents.forEach(function (evt) { 17315 win[method](evt, onWindowResize); 17316 }); 17317 } 17318 }); 17319 17320 api.observeWindow = true; 17321 api.observeWindowDelay = 100; 17322 17323 api.fitAll = markAllDirty(DIRTY_FORCE); 17324 17325 return api; 17326 }(typeof window === "undefined" ? null : window); 17327}); 17328"use strict"; 17329 17330function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 17331function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 17332function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 17333function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } 17334function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 17335function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } 17336(function (global, factory) { 17337 (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Lenis = factory()); 17338})(void 0, function () { 17339 'use strict'; 17340 17341 var version = "1.1.9"; 17342 17343 // Clamp a value between a minimum and maximum value 17344 function clamp(min, input, max) { 17345 return Math.max(min, Math.min(input, max)); 17346 } 17347 17348 // Linearly interpolate between two values using an amount (0 <= t <= 1) 17349 function lerp(x, y, t) { 17350 return (1 - t) * x + t * y; 17351 } 17352 17353 // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ 17354 function damp(x, y, lambda, dt) { 17355 return lerp(x, y, 1 - Math.exp(-lambda * dt)); 17356 } 17357 17358 // Calculate the modulo of the dividend and divisor while keeping the result within the same sign as the divisor 17359 // https://anguscroll.com/just/just-modulo 17360 function modulo(n, d) { 17361 return (n % d + d) % d; 17362 } 17363 var Animate = /*#__PURE__*/function () { 17364 function Animate() { 17365 _classCallCheck(this, Animate); 17366 this.isRunning = false; 17367 this.value = 0; 17368 this.from = 0; 17369 this.to = 0; 17370 this.duration = 0; 17371 this.currentTime = 0; 17372 } 17373 _createClass(Animate, [{ 17374 key: "advance", 17375 value: function advance(deltaTime) { 17376 var _a; 17377 if (!this.isRunning) return; 17378 var completed = false; 17379 if (this.duration && this.easing) { 17380 this.currentTime += deltaTime; 17381 var linearProgress = clamp(0, this.currentTime / this.duration, 1); 17382 completed = linearProgress >= 1; 17383 var easedProgress = completed ? 1 : this.easing(linearProgress); 17384 this.value = this.from + (this.to - this.from) * easedProgress; 17385 } else if (this.lerp) { 17386 this.value = damp(this.value, this.to, this.lerp * 60, deltaTime); 17387 if (Math.round(this.value) === this.to) { 17388 this.value = this.to; 17389 completed = true; 17390 } 17391 } else { 17392 this.value = this.to; 17393 completed = true; 17394 } 17395 if (completed) { 17396 this.stop(); 17397 } 17398 (_a = this.onUpdate) === null || _a === void 0 ? void 0 : _a.call(this, this.value, completed); 17399 } 17400 }, {
17401 key: "stop", 17402 value: function stop() { 17403 this.isRunning = false; 17404 } 17405 }, { 17406 key: "fromTo", 17407 value: function fromTo(from, to, _ref) { 17408 var lerp = _ref.lerp, 17409 duration = _ref.duration, 17410 easing = _ref.easing, 17411 onStart = _ref.onStart, 17412 onUpdate = _ref.onUpdate; 17413 this.from = this.value = from; 17414 this.to = to; 17415 this.lerp = lerp; 17416 this.duration = duration; 17417 this.easing = easing; 17418 this.currentTime = 0; 17419 this.isRunning = true; 17420 onStart === null || onStart === void 0 ? void 0 : onStart(); 17421 this.onUpdate = onUpdate; 17422 } 17423 }]); 17424 return Animate; 17425 }(); 17426 function debounce(callback, delay) { 17427 var timer; 17428 return function () { 17429 var args = arguments; 17430 var context = this; 17431 clearTimeout(timer); 17432 timer = setTimeout(function () { 17433 callback.apply(context, args); 17434 }, delay); 17435 }; 17436 } 17437 var Dimensions = /*#__PURE__*/function () { 17438 function Dimensions() { 17439 var _this = this; 17440 var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, 17441 wrapper = _ref2.wrapper, 17442 content = _ref2.content, 17443 _ref2$autoResize = _ref2.autoResize, 17444 autoResize = _ref2$autoResize === void 0 ? true : _ref2$autoResize, 17445 _ref2$debounce = _ref2.debounce, 17446 debounceValue = _ref2$debounce === void 0 ? 250 : _ref2$debounce; 17447 _classCallCheck(this, Dimensions); 17448 this.width = 0; 17449 this.height = 0; 17450 this.scrollWidth = 0; 17451 this.scrollHeight = 0; 17452 this.resize = function () { 17453 _this.onWrapperResize(); 17454 _this.onContentResize(); 17455 }; 17456 this.onWrapperResize = function () { 17457 if (_this.wrapper === window) { 17458 _this.width = window.innerWidth; 17459 _this.height = window.innerHeight; 17460 } else if (_this.wrapper instanceof HTMLElement) { 17461 _this.width = _this.wrapper.clientWidth; 17462 _this.height = _this.wrapper.clientHeight; 17463 } 17464 }; 17465 this.onContentResize = function () { 17466 if (_this.wrapper === window) { 17467 _this.scrollHeight = _this.content.scrollHeight; 17468 _this.scrollWidth = _this.content.scrollWidth; 17469 } else if (_this.wrapper instanceof HTMLElement) { 17470 _this.scrollHeight = _this.wrapper.scrollHeight; 17471 _this.scrollWidth = _this.wrapper.scrollWidth; 17472 } 17473 }; 17474 this.wrapper = wrapper; 17475 this.content = content; 17476 if (autoResize) { 17477 this.debouncedResize = debounce(this.resize, debounceValue); 17478 if (this.wrapper === window) { 17479 window.addEventListener('resize', this.debouncedResize, false); 17480 } else { 17481 this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize); 17482 this.wrapperResizeObserver.observe(this.wrapper); 17483 } 17484 this.contentResizeObserver = new ResizeObserver(this.debouncedResize); 17485 this.contentResizeObserver.observe(this.content); 17486 } 17487 this.resize(); 17488 } 17489 _createClass(Dimensions, [{ 17490 key: "destroy", 17491 value: function destroy() { 17492 var _a, _b; 17493 (_a = this.wrapperResizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect(); 17494 (_b = this.contentResizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect(); 17495 window.removeEventListener('resize', this.debouncedResize, false); 17496 } 17497 }, { 17498 key: "limit", 17499 get: function get() { 17500 return { 17501 x: this.scrollWidth - this.width, 17502 y: this.scrollHeight - this.height 17503 }; 17504 } 17505 }]); 17506 return Dimensions; 17507 }(); 17508 var Emitter = /*#__PURE__*/function () { 17509 function Emitter() { 17510 _classCallCheck(this, Emitter); 17511 this.events = {}; 17512 } 17513 _createClass(Emitter, [{ 17514 key: "emit", 17515 value: function emit(event) { 17516 var callbacks = this.events[event] || []; 17517 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 17518 args[_key - 1] = arguments[_key]; 17519 } 17520 for (var i = 0, length = callbacks.length; i < length; i++) { 17521 callbacks[i].apply(callbacks, args); 17522 } 17523 } 17524 }, {
17525 key: "on", 17526 value: function on(event, callback) { 17527 var _this2 = this; 17528 var _a; 17529 ((_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.push(callback)) || (this.events[event] = [callback]); 17530 return function () { 17531 var _a; 17532 _this2.events[event] = (_a = _this2.events[event]) === null || _a === void 0 ? void 0 : _a.filter(function (i) { 17533 return callback !== i; 17534 }); 17535 }; 17536 } 17537 }, { 17538 key: "off", 17539 value: function off(event, callback) { 17540 var _a; 17541 this.events[event] = (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.filter(function (i) { 17542 return callback !== i; 17543 }); 17544 } 17545 }, { 17546 key: "destroy", 17547 value: function destroy() { 17548 this.events = {}; 17549 } 17550 }]); 17551 return Emitter; 17552 }(); 17553 var LINE_HEIGHT = 100 / 6; 17554 var VirtualScroll = /*#__PURE__*/function () { 17555 function VirtualScroll(element, _ref3) { 17556 var _this3 = this; 17557 var _ref3$wheelMultiplier = _ref3.wheelMultiplier, 17558 wheelMultiplier = _ref3$wheelMultiplier === void 0 ? 1 : _ref3$wheelMultiplier, 17559 _ref3$touchMultiplier = _ref3.touchMultiplier, 17560 touchMultiplier = _ref3$touchMultiplier === void 0 ? 1 : _ref3$touchMultiplier; 17561 _classCallCheck(this, VirtualScroll); 17562 this.lastDelta = { 17563 x: 0, 17564 y: 0 17565 }; 17566 this.windowWidth = 0; 17567 this.windowHeight = 0; 17568 this.onTouchStart = function (event) { 17569 var _ref4 = event.targetTouches ? event.targetTouches[0] : event, 17570 clientX = _ref4.clientX, 17571 clientY = _ref4.clientY; 17572 _this3.touchStart.x = clientX; 17573 _this3.touchStart.y = clientY; 17574 _this3.lastDelta = { 17575 x: 0, 17576 y: 0 17577 }; 17578 _this3.emitter.emit('scroll', { 17579 deltaX: 0, 17580 deltaY: 0, 17581 event: event 17582 }); 17583 }; 17584 this.onTouchMove = function (event) { 17585 var _a, _b, _c, _d; 17586 var _ref5 = event.targetTouches ? event.targetTouches[0] : event, 17587 clientX = _ref5.clientX, 17588 clientY = _ref5.clientY; 17589 var deltaX = -(clientX - ((_b = (_a = _this3.touchStart) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0)) * _this3.touchMultiplier; 17590 var deltaY = -(clientY - ((_d = (_c = _this3.touchStart) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0)) * _this3.touchMultiplier; 17591 _this3.touchStart.x = clientX; 17592 _this3.touchStart.y = clientY; 17593 _this3.lastDelta = { 17594 x: deltaX, 17595 y: deltaY 17596 }; 17597 _this3.emitter.emit('scroll', { 17598 deltaX: deltaX, 17599 deltaY: deltaY, 17600 event: event 17601 }); 17602 }; 17603 this.onTouchEnd = function (event) { 17604 _this3.emitter.emit('scroll', { 17605 deltaX: _this3.lastDelta.x, 17606 deltaY: _this3.lastDelta.y, 17607 event: event 17608 }); 17609 }; 17610 this.onWheel = function (event) { 17611 var deltaX = event.deltaX, 17612 deltaY = event.deltaY, 17613 deltaMode = event.deltaMode; 17614 var multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? _this3.windowWidth : 1; 17615 var multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? _this3.windowHeight : 1; 17616 deltaX *= multiplierX; 17617 deltaY *= multiplierY; 17618 deltaX *= _this3.wheelMultiplier; 17619 deltaY *= _this3.wheelMultiplier; 17620 _this3.emitter.emit('scroll', { 17621 deltaX: deltaX, 17622 deltaY: deltaY, 17623 event: event 17624 }); 17625 }; 17626 this.onWindowResize = function () { 17627 _this3.windowWidth = window.innerWidth; 17628 _this3.windowHeight = window.innerHeight; 17629 }; 17630 this.element = element; 17631 this.wheelMultiplier = wheelMultiplier; 17632 this.touchMultiplier = touchMultiplier; 17633 this.touchStart = { 17634 x: null, 17635 y: null 17636 }; 17637 this.emitter = new Emitter(); 17638 window.addEventListener('resize', this.onWindowResize, false); 17639 this.onWindowResize(); 17640 this.element.addEventListener('wheel', this.onWheel, { 17641 passive: false 17642 }); 17643 this.element.addEventListener('touchstart', this.onTouchStart, { 17644 passive: false 17645 }); 17646 this.element.addEventListener('touchmove', this.onTouchMove, { 17647 passive: false 17648 }); 17649 this.element.addEventListener('touchend', this.onTouchEnd, { 17650 passive: false 17651 }); 17652 } 17653 _createClass(VirtualScroll, [{ 17654 key: "on", 17655 value: function on(event, callback) { 17656 return this.emitter.on(event, callback); 17657 } 17658 }, {
17659 key: "destroy", 17660 value: function destroy() { 17661 this.emitter.destroy(); 17662 window.removeEventListener('resize', this.onWindowResize, false); 17663 this.element.removeEventListener('wheel', this.onWheel); 17664 this.element.removeEventListener('touchstart', this.onTouchStart); 17665 this.element.removeEventListener('touchmove', this.onTouchMove); 17666 this.element.removeEventListener('touchend', this.onTouchEnd); 17667 } 17668 }]); 17669 return VirtualScroll; 17670 }(); 17671 var Lenis = /*#__PURE__*/function () { 17672 function Lenis() { 17673 var _this4 = this; 17674 var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, 17675 _ref6$wrapper = _ref6.wrapper, 17676 wrapper = _ref6$wrapper === void 0 ? window : _ref6$wrapper, 17677 _ref6$content = _ref6.content, 17678 content = _ref6$content === void 0 ? document.documentElement : _ref6$content, 17679 _ref6$wheelEventsTarg = _ref6.wheelEventsTarget, 17680 wheelEventsTarget = _ref6$wheelEventsTarg === void 0 ? wrapper : _ref6$wheelEventsTarg, 17681 _ref6$eventsTarget = _ref6.eventsTarget, 17682 eventsTarget = _ref6$eventsTarget === void 0 ? wheelEventsTarget : _ref6$eventsTarget, 17683 _ref6$smoothWheel = _ref6.smoothWheel, 17684 smoothWheel = _ref6$smoothWheel === void 0 ? true : _ref6$smoothWheel, 17685 _ref6$syncTouch = _ref6.syncTouch, 17686 syncTouch = _ref6$syncTouch === void 0 ? false : _ref6$syncTouch, 17687 _ref6$syncTouchLerp = _ref6.syncTouchLerp, 17688 syncTouchLerp = _ref6$syncTouchLerp === void 0 ? 0.075 : _ref6$syncTouchLerp, 17689 _ref6$touchInertiaMul = _ref6.touchInertiaMultiplier, 17690 touchInertiaMultiplier = _ref6$touchInertiaMul === void 0 ? 35 : _ref6$touchInertiaMul, 17691 duration = _ref6.duration, 17692 _ref6$easing = _ref6.easing, 17693 easing = _ref6$easing === void 0 ? function (t) { 17694 return Math.min(1, 1.001 - Math.pow(2, -10 * t)); 17695 } : _ref6$easing, 17696 _ref6$lerp = _ref6.lerp, 17697 lerp = _ref6$lerp === void 0 ? 0.1 : _ref6$lerp, 17698 _ref6$infinite = _ref6.infinite, 17699 infinite = _ref6$infinite === void 0 ? false : _ref6$infinite, 17700 _ref6$orientation = _ref6.orientation, 17701 orientation = _ref6$orientation === void 0 ? 'vertical' : _ref6$orientation, 17702 _ref6$gestureOrientat = _ref6.gestureOrientation, 17703 gestureOrientation = _ref6$gestureOrientat === void 0 ? 'vertical' : _ref6$gestureOrientat, 17704 _ref6$touchMultiplier = _ref6.touchMultiplier, 17705 touchMultiplier = _ref6$touchMultiplier === void 0 ? 1 : _ref6$touchMultiplier, 17706 _ref6$wheelMultiplier = _ref6.wheelMultiplier, 17707 wheelMultiplier = _ref6$wheelMultiplier === void 0 ? 1 : _ref6$wheelMultiplier, 17708 _ref6$autoResize = _ref6.autoResize, 17709 autoResize = _ref6$autoResize === void 0 ? true : _ref6$autoResize, 17710 prevent = _ref6.prevent, 17711 virtualScroll = _ref6.virtualScroll, 17712 _ref6$__experimental_ = _ref6.__experimental__naiveDimensions, 17713 __experimental__naiveDimensions = _ref6$__experimental_ === void 0 ? false : _ref6$__experimental_; 17714 _classCallCheck(this, Lenis); 17715 this.__isScrolling = false; 17716 this.__isStopped = false; 17717 this.__isLocked = false; 17718 this.userData = {}; 17719 this.lastVelocity = 0; 17720 this.velocity = 0; 17721 this.direction = 0; 17722 this.onPointerDown = function (event) { 17723 if (event.button === 1) { 17724 _this4.reset(); 17725 } 17726 }; 17727 this.onVirtualScroll = function (data) { 17728 if (typeof _this4.options.virtualScroll === 'function' && _this4.options.virtualScroll(data) === false) return; 17729 var deltaX = data.deltaX, 17730 deltaY = data.deltaY, 17731 event = data.event; 17732 _this4.emitter.emit('virtual-scroll', { 17733 deltaX: deltaX, 17734 deltaY: deltaY, 17735 event: event 17736 }); 17737 if (event.ctrlKey) return; 17738 var isTouch = event.type.includes('touch'); 17739 var isWheel = event.type.includes('wheel'); 17740 _this4.isTouching = event.type === 'touchstart' || event.type === 'touchmove'; 17741 var isTapToStop = _this4.options.syncTouch && isTouch && event.type === 'touchstart' && !_this4.isStopped && !_this4.isLocked; 17742 if (isTapToStop) { 17743 _this4.reset(); 17744 return; 17745 }
17746 var isClick = deltaX === 0 && deltaY === 0; 17747 var isUnknownGesture = _this4.options.gestureOrientation === 'vertical' && deltaY === 0 || _this4.options.gestureOrientation === 'horizontal' && deltaX === 0; 17748 if (isClick || isUnknownGesture) { 17749 return; 17750 } 17751 var composedPath = event.composedPath(); 17752 composedPath = composedPath.slice(0, composedPath.indexOf(_this4.rootElement)); 17753 var prevent = _this4.options.prevent; 17754 if (!!composedPath.find(function (node) { 17755 var _a, _b, _c, _d, _e; 17756 return node instanceof Element && (typeof prevent === 'function' && (prevent === null || prevent === void 0 ? void 0 : prevent(node)) || ((_a = node.hasAttribute) === null || _a === void 0 ? void 0 : _a.call(node, 'data-lenis-prevent')) || isTouch && ((_b = node.hasAttribute) === null || _b === void 0 ? void 0 : _b.call(node, 'data-lenis-prevent-touch')) || isWheel && ((_c = node.hasAttribute) === null || _c === void 0 ? void 0 : _c.call(node, 'data-lenis-prevent-wheel')) || ((_d = node.classList) === null || _d === void 0 ? void 0 : _d.contains('lenis')) && !((_e = node.classList) === null || _e === void 0 ? void 0 : _e.contains('lenis-stopped'))); 17757 })) return; 17758 if (_this4.isStopped || _this4.isLocked) { 17759 event.preventDefault(); 17760 return; 17761 } 17762 var isSmooth = _this4.options.syncTouch && isTouch || _this4.options.smoothWheel && isWheel; 17763 if (!isSmooth) { 17764 _this4.isScrolling = 'native'; 17765 _this4.animate.stop(); 17766 return; 17767 } 17768 event.preventDefault(); 17769 var delta = deltaY; 17770 if (_this4.options.gestureOrientation === 'both') { 17771 delta = Math.abs(deltaY) > Math.abs(deltaX) ? deltaY : deltaX; 17772 } else if (_this4.options.gestureOrientation === 'horizontal') { 17773 delta = deltaX; 17774 } 17775 var syncTouch = isTouch && _this4.options.syncTouch; 17776 var isTouchEnd = isTouch && event.type === 'touchend'; 17777 var hasTouchInertia = isTouchEnd && Math.abs(delta) > 5; 17778 if (hasTouchInertia) { 17779 delta = _this4.velocity * _this4.options.touchInertiaMultiplier; 17780 } 17781 _this4.scrollTo(_this4.targetScroll + delta, Object.assign({ 17782 programmatic: false 17783 }, syncTouch ? { 17784 lerp: hasTouchInertia ? _this4.options.syncTouchLerp : 1 17785 } : { 17786 lerp: _this4.options.lerp, 17787 duration: _this4.options.duration, 17788 easing: _this4.options.easing 17789 })); 17790 }; 17791 this.onNativeScroll = function () { 17792 clearTimeout(_this4.__resetVelocityTimeout); 17793 delete _this4.__resetVelocityTimeout; 17794 if (_this4.__preventNextNativeScrollEvent) { 17795 delete _this4.__preventNextNativeScrollEvent; 17796 return; 17797 } 17798 if (_this4.isScrolling === false || _this4.isScrolling === 'native') { 17799 var lastScroll = _this4.animatedScroll; 17800 _this4.animatedScroll = _this4.targetScroll = _this4.actualScroll; 17801 _this4.lastVelocity = _this4.velocity; 17802 _this4.velocity = _this4.animatedScroll - lastScroll; 17803 _this4.direction = Math.sign(_this4.animatedScroll - lastScroll); 17804 _this4.isScrolling = 'native'; 17805 _this4.emit(); 17806 if (_this4.velocity !== 0) { 17807 _this4.__resetVelocityTimeout = setTimeout(function () { 17808 _this4.lastVelocity = _this4.velocity; 17809 _this4.velocity = 0; 17810 _this4.isScrolling = false; 17811 _this4.emit(); 17812 }, 400); 17813 } 17814 } 17815 }; 17816 window.lenisVersion = version; 17817 if (!wrapper || wrapper === document.documentElement || wrapper === document.body) { 17818 wrapper = window; 17819 } 17820 this.options = { 17821 wrapper: wrapper, 17822 content: content, 17823 wheelEventsTarget: wheelEventsTarget, 17824 eventsTarget: eventsTarget, 17825 smoothWheel: smoothWheel, 17826 syncTouch: syncTouch, 17827 syncTouchLerp: syncTouchLerp, 17828 touchInertiaMultiplier: touchInertiaMultiplier, 17829 duration: duration, 17830 easing: easing, 17831 lerp: lerp, 17832 infinite: infinite, 17833 gestureOrientation: gestureOrientation, 17834 orientation: orientation, 17835 touchMultiplier: touchMultiplier, 17836 wheelMultiplier: wheelMultiplier, 17837 autoResize: autoResize, 17838 prevent: prevent, 17839 virtualScroll: virtualScroll, 17840 __experimental__naiveDimensions: __experimental__naiveDimensions 17841 }; 17842 this.animate = new Animate(); 17843 this.emitter = new Emitter(); 17844 this.dimensions = new Dimensions({ 17845 wrapper: wrapper, 17846 content: content, 17847 autoResize: autoResize 17848 }); 17849 this.updateClassName(); 17850 this.userData = {}; 17851 this.time = 0; 17852 this.velocity = this.lastVelocity = 0;
17853 this.isLocked = false; 17854 this.isStopped = false; 17855 this.isScrolling = false; 17856 this.targetScroll = this.animatedScroll = this.actualScroll; 17857 this.options.wrapper.addEventListener('scroll', this.onNativeScroll, false); 17858 this.options.wrapper.addEventListener('pointerdown', this.onPointerDown, false); 17859 this.virtualScroll = new VirtualScroll(eventsTarget, { 17860 touchMultiplier: touchMultiplier, 17861 wheelMultiplier: wheelMultiplier 17862 }); 17863 this.virtualScroll.on('scroll', this.onVirtualScroll); 17864 } 17865 _createClass(Lenis, [{ 17866 key: "destroy", 17867 value: function destroy() { 17868 this.emitter.destroy(); 17869 this.options.wrapper.removeEventListener('scroll', this.onNativeScroll, false); 17870 this.options.wrapper.removeEventListener('pointerdown', this.onPointerDown, false); 17871 this.virtualScroll.destroy(); 17872 this.dimensions.destroy(); 17873 this.cleanUpClassName(); 17874 } 17875 }, { 17876 key: "on", 17877 value: function on(event, callback) { 17878 return this.emitter.on(event, callback); 17879 } 17880 }, { 17881 key: "off", 17882 value: function off(event, callback) { 17883 return this.emitter.off(event, callback); 17884 } 17885 }, { 17886 key: "setScroll", 17887 value: function setScroll(scroll) { 17888 if (this.isHorizontal) { 17889 this.rootElement.scrollLeft = scroll; 17890 } else { 17891 this.rootElement.scrollTop = scroll; 17892 } 17893 } 17894 }, { 17895 key: "resize", 17896 value: function resize() { 17897 this.dimensions.resize(); 17898 } 17899 }, { 17900 key: "emit", 17901 value: function emit() { 17902 this.emitter.emit('scroll', this); 17903 } 17904 }, { 17905 key: "reset", 17906 value: function reset() { 17907 this.isLocked = false; 17908 this.isScrolling = false; 17909 this.animatedScroll = this.targetScroll = this.actualScroll; 17910 this.lastVelocity = this.velocity = 0; 17911 this.animate.stop(); 17912 } 17913 }, { 17914 key: "start", 17915 value: function start() { 17916 if (!this.isStopped) return; 17917 this.isStopped = false; 17918 this.reset(); 17919 } 17920 }, { 17921 key: "stop", 17922 value: function stop() { 17923 if (this.isStopped) return; 17924 this.isStopped = true; 17925 this.animate.stop(); 17926 this.reset(); 17927 } 17928 }, { 17929 key: "raf", 17930 value: function raf(time) { 17931 var deltaTime = time - (this.time || time); 17932 this.time = time; 17933 this.animate.advance(deltaTime * 0.001); 17934 } 17935 }, { 17936 key: "scrollTo", 17937 value: function scrollTo(target) { 17938 var _this5 = this; 17939 var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, 17940 _ref7$offset = _ref7.offset, 17941 offset = _ref7$offset === void 0 ? 0 : _ref7$offset, 17942 _ref7$immediate = _ref7.immediate, 17943 immediate = _ref7$immediate === void 0 ? false : _ref7$immediate, 17944 _ref7$lock = _ref7.lock, 17945 lock = _ref7$lock === void 0 ? false : _ref7$lock, 17946 _ref7$duration = _ref7.duration, 17947 duration = _ref7$duration === void 0 ? this.options.duration : _ref7$duration, 17948 _ref7$easing = _ref7.easing, 17949 easing = _ref7$easing === void 0 ? this.options.easing : _ref7$easing, 17950 _ref7$lerp = _ref7.lerp, 17951 lerp = _ref7$lerp === void 0 ? this.options.lerp : _ref7$lerp, 17952 _onStart = _ref7.onStart, 17953 onComplete = _ref7.onComplete, 17954 _ref7$force = _ref7.force, 17955 force = _ref7$force === void 0 ? false : _ref7$force, 17956 _ref7$programmatic = _ref7.programmatic, 17957 programmatic = _ref7$programmatic === void 0 ? true : _ref7$programmatic, 17958 _ref7$userData = _ref7.userData, 17959 userData = _ref7$userData === void 0 ? {} : _ref7$userData; 17960 if ((this.isStopped || this.isLocked) && !force) return; 17961 if (typeof target === 'string' && ['top', 'left', 'start'].includes(target)) { 17962 target = 0; 17963 } else if (typeof target === 'string' && ['bottom', 'right', 'end'].includes(target)) { 17964 target = this.limit; 17965 } else { 17966 var node; 17967 if (typeof target === 'string') { 17968 node = document.querySelector(target); 17969 } else if (target instanceof HTMLElement && (target === null || target === void 0 ? void 0 : target.nodeType)) { 17970 node = target; 17971 } 17972 if (node) { 17973 if (this.options.wrapper !== window) { 17974 var wrapperRect = this.rootElement.getBoundingClientRect(); 17975 offset -= this.isHorizontal ? wrapperRect.left : wrapperRect.top; 17976 }
17977 var rect = node.getBoundingClientRect(); 17978 target = (this.isHorizontal ? rect.left : rect.top) + this.animatedScroll; 17979 } 17980 } 17981 if (typeof target !== 'number') return; 17982 target += offset; 17983 target = Math.round(target); 17984 if (this.options.infinite) { 17985 if (programmatic) { 17986 this.targetScroll = this.animatedScroll = this.scroll; 17987 } 17988 } else { 17989 target = clamp(0, target, this.limit); 17990 } 17991 if (target === this.targetScroll) return; 17992 this.userData = userData; 17993 if (immediate) { 17994 this.animatedScroll = this.targetScroll = target; 17995 this.setScroll(this.scroll); 17996 this.reset(); 17997 this.preventNextNativeScrollEvent(); 17998 this.emit(); 17999 onComplete === null || onComplete === void 0 ? void 0 : onComplete(this); 18000 this.userData = {}; 18001 return; 18002 } 18003 if (!programmatic) { 18004 this.targetScroll = target; 18005 } 18006 this.animate.fromTo(this.animatedScroll, target, { 18007 duration: duration, 18008 easing: easing, 18009 lerp: lerp, 18010 onStart: function onStart() { 18011 if (lock) _this5.isLocked = true; 18012 _this5.isScrolling = 'smooth'; 18013 _onStart === null || _onStart === void 0 ? void 0 : _onStart(_this5); 18014 }, 18015 onUpdate: function onUpdate(value, completed) { 18016 _this5.isScrolling = 'smooth'; 18017 _this5.lastVelocity = _this5.velocity; 18018 _this5.velocity = value - _this5.animatedScroll; 18019 _this5.direction = Math.sign(_this5.velocity); 18020 _this5.animatedScroll = value; 18021 _this5.setScroll(_this5.scroll); 18022 if (programmatic) { 18023 _this5.targetScroll = value; 18024 } 18025 if (!completed) _this5.emit(); 18026 if (completed) { 18027 _this5.reset(); 18028 _this5.emit(); 18029 onComplete === null || onComplete === void 0 ? void 0 : onComplete(_this5); 18030 _this5.userData = {}; 18031 _this5.preventNextNativeScrollEvent(); 18032 } 18033 } 18034 }); 18035 } 18036 }, { 18037 key: "preventNextNativeScrollEvent", 18038 value: function preventNextNativeScrollEvent() { 18039 var _this6 = this; 18040 this.__preventNextNativeScrollEvent = true; 18041 requestAnimationFrame(function () { 18042 delete _this6.__preventNextNativeScrollEvent; 18043 }); 18044 } 18045 }, { 18046 key: "rootElement", 18047 get: function get() { 18048 return this.options.wrapper === window ? document.documentElement : this.options.wrapper; 18049 } 18050 }, { 18051 key: "limit", 18052 get: function get() { 18053 if (this.options.__experimental__naiveDimensions) { 18054 if (this.isHorizontal) { 18055 return this.rootElement.scrollWidth - this.rootElement.clientWidth; 18056 } else { 18057 return this.rootElement.scrollHeight - this.rootElement.clientHeight; 18058 } 18059 } else { 18060 return this.dimensions.limit[this.isHorizontal ? 'x' : 'y']; 18061 } 18062 } 18063 }, { 18064 key: "isHorizontal", 18065 get: function get() { 18066 return this.options.orientation === 'horizontal'; 18067 } 18068 }, { 18069 key: "actualScroll", 18070 get: function get() { 18071 return this.isHorizontal ? this.rootElement.scrollLeft : this.rootElement.scrollTop; 18072 } 18073 }, { 18074 key: "scroll", 18075 get: function get() { 18076 return this.options.infinite ? modulo(this.animatedScroll, this.limit) : this.animatedScroll; 18077 } 18078 }, { 18079 key: "progress", 18080 get: function get() { 18081 return this.limit === 0 ? 1 : this.scroll / this.limit; 18082 } 18083 }, { 18084 key: "isScrolling", 18085 get: function get() { 18086 return this.__isScrolling; 18087 }, 18088 set: function set(value) { 18089 if (this.__isScrolling !== value) { 18090 this.__isScrolling = value; 18091 this.updateClassName(); 18092 } 18093 } 18094 }, { 18095 key: "isStopped", 18096 get: function get() { 18097 return this.__isStopped; 18098 }, 18099 set: function set(value) { 18100 if (this.__isStopped !== value) { 18101 this.__isStopped = value; 18102 this.updateClassName(); 18103 } 18104 } 18105 }, {
18106 key: "isLocked", 18107 get: function get() { 18108 return this.__isLocked; 18109 }, 18110 set: function set(value) { 18111 if (this.__isLocked !== value) { 18112 this.__isLocked = value; 18113 this.updateClassName(); 18114 } 18115 } 18116 }, { 18117 key: "isSmooth", 18118 get: function get() { 18119 return this.isScrolling === 'smooth'; 18120 } 18121 }, { 18122 key: "className", 18123 get: function get() { 18124 var className = 'lenis'; 18125 if (this.isStopped) className += ' lenis-stopped'; 18126 if (this.isLocked) className += ' lenis-locked'; 18127 if (this.isScrolling) className += ' lenis-scrolling'; 18128 if (this.isScrolling === 'smooth') className += ' lenis-smooth'; 18129 return className; 18130 } 18131 }, { 18132 key: "updateClassName", 18133 value: function updateClassName() { 18134 this.cleanUpClassName(); 18135 this.rootElement.className = "".concat(this.rootElement.className, " ").concat(this.className).trim(); 18136 } 18137 }, { 18138 key: "cleanUpClassName", 18139 value: function cleanUpClassName() { 18140 this.rootElement.className = this.rootElement.className.replace(/lenis(-\w+)?/g, '').trim(); 18141 } 18142 }]); 18143 return Lenis; 18144 }(); 18145 return Lenis; 18146}); 18147(function(window, $) { 18148 "use strict"; 18149 18150 var counter = 0, 18151 $headCache = $('head'), 18152 oldBigText = window.BigText, 18153 oldjQueryMethod = $.fn.bigtext, 18154 BigText = { 18155 DEBUG_MODE: false, 18156 DEFAULT_MIN_FONT_SIZE_PX: null, 18157 DEFAULT_MAX_FONT_SIZE_PX: 1056, 18158 GLOBAL_STYLE_ID: 'bigtext-style', 18159 STYLE_ID: 'bigtext-id', 18160 LINE_CLASS_PREFIX: 'bigtext-line', 18161 EXEMPT_CLASS: 'bigtext-exempt', 18162 noConflict: function(restore) 18163 { 18164 if(restore) { 18165 $.fn.bigtext = oldjQueryMethod; 18166 window.BigText = oldBigText; 18167 } 18168 return BigText; 18169 }, 18170 supports: { 18171 wholeNumberFontSizeOnly: (function() { 18172 if( !( 'getComputedStyle' in window ) ) { 18173 return true; 18174 } 18175 var test = $('<div/>').css({ 18176 position: 'absolute', 18177 'font-size': '14.1px' 18178 }).insertBefore( $('script').eq(0) ), 18179 computedStyle = window.getComputedStyle( test[0], null ); 18180 18181 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 18182 test.remove(); 18183 return ret; 18184 })() 18185 }, 18186 init: function() { 18187 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 18188 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 18189 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 18190 } 18191 }, 18192 bindResize: function(eventName, resizeFunction) { 18193 var timeoutId; 18194 $(window).off(eventName).on(eventName, function() { 18195 if( timeoutId ) { 18196 clearTimeout( timeoutId ); 18197 } 18198 timeoutId = setTimeout( resizeFunction, 100 ); 18199 }); 18200 }, 18201 getStyleId: function(id) 18202 { 18203 return BigText.STYLE_ID + '-' + id; 18204 }, 18205 generateStyleTag: function(id, css) 18206 { 18207 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 18208 }, 18209 clearCss: function(id) 18210 { 18211 var styleId = BigText.getStyleId(id); 18212 $('#' + styleId).remove(); 18213 }, 18214 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 18215 { 18216 var css = []; 18217 18218 BigText.clearCss(id); 18219 18220 for(var j=0, k=linesFontSizes.length; j<k; j++) { 18221 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 18222 (minFontSizes[j] ? ' white-space: normal;' : '') + 18223 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 18224 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 18225 '}'); 18226 } 18227 18228 return BigText.generateStyleTag(BigText.getStyleId(id), css); 18229 }, 18230 jQueryMethod: function(options) 18231 {
18232 BigText.init(); 18233 18234 options = $.extend({ 18235 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 18236 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 18237 childSelector: '', 18238 resize: true 18239 }, options || {}); 18240 18241 this.each(function() 18242 { 18243 var $t = $(this).addClass('bigtext'), 18244 maxWidth = $t.width(), 18245 id = $t.attr('id'), 18246 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 18247 18248 if(!id) { 18249 id = 'bigtext-id' + (counter++); 18250 $t.attr('id', id); 18251 } 18252 18253 if(options.resize) { 18254 BigText.bindResize('resize.bigtext-event-' + id, function() 18255 { 18256 // TODO only call this if the width has changed. 18257 BigText.jQueryMethod.call($('#' + id), options); 18258 }); 18259 } 18260 18261 BigText.clearCss(id); 18262 18263 $children.addClass(function(lineNumber, className) 18264 { 18265 // remove existing line classes. 18266 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 18267 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 18268 }); 18269 18270 var sizes = BigText.calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 18271 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 18272 }); 18273 18274 return this.trigger('bigtext:complete'); 18275 }, 18276 testLineDimensions: function($line, maxWidth, property, size, interval, units, previousWidth) 18277 { 18278 var width; 18279 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 18280 $line.css(property, size + units); 18281 18282 width = $line.width(); 18283 18284 if(width >= maxWidth) { 18285 // console.log(width, ' previous: ' + previousWidth, property + ' at ' + interval, 'prior: ' + (parseFloat(size) - interval), 'new:' + parseFloat(size)); 18286 $line.css(property, ''); 18287 18288 if(width === maxWidth) { 18289 return { 18290 match: 'exact', 18291 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 18292 }; 18293 } 18294 18295 // Since this is an estimate, we calculate how far over the width we went with the new value. 18296 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 18297 // Otherwise, we revert to the underestimate. 18298 var under = maxWidth - previousWidth, 18299 over = width - maxWidth; 18300 18301 return { 18302 match: 'estimate', 18303 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 18304 }; 18305 } 18306 18307 return width; 18308 }, 18309 calculateSizes: function($t, $children, maxWidth, maxFontSize, minFontSize) 18310 { 18311 var $c = $t.clone(true) 18312 .addClass('bigtext-cloned') 18313 .css({ 18314 fontFamily: $t.css('font-family'), 18315 textTransform: $t.css('text-transform'), 18316 wordSpacing: $t.css('word-spacing'), 18317 letterSpacing: $t.css('letter-spacing'), 18318 position: 'absolute', 18319 left: BigText.DEBUG_MODE ? 0 : -9999, 18320 top: BigText.DEBUG_MODE ? 0 : -9999 18321 }) 18322 .appendTo(document.body); 18323 18324 // font-size isn't the only thing we can modify, we can also mess with: 18325 // word-spacing and letter-spacing. WebKit does not respect subpixel 18326 // letter-spacing, word-spacing, or font-size. 18327 // TODO try -webkit-transform: scale() as a workaround. 18328 var fontSizes = [], 18329 wordSpacings = [], 18330 minFontSizes = [], 18331 ratios = []; 18332 18333 $children.css('float', 'left').each(function() { 18334 var $line = $(this), 18335 // TODO replace 8, 4 with a proportional size to the calculated font-size. 18336 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 18337 lineMax, 18338 newFontSize; 18339 18340 if($line.hasClass(BigText.EXEMPT_CLASS)) { 18341 fontSizes.push(null); 18342 ratios.push(null); 18343 minFontSizes.push(false); 18344 return; 18345 } 18346 18347 // TODO we can cache this ratio? 18348 var autoGuessSubtraction = 32, // font size in px 18349 currentFontSize = parseFloat($line.css('font-size')), 18350 ratio = ( $line.width() / currentFontSize ).toFixed(6); 18351 18352 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 18353 18354 outer: for(var m=0, n=intervals.length; m<n; m++) { 18355 inner: for(var j=1, k=10; j<=k; j++) { 18356 if(newFontSize + j*intervals[m] > maxFontSize) { 18357 newFontSize = maxFontSize; 18358 break outer; 18359 } 18360 18361 lineMax = BigText.testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 18362 if(typeof lineMax !== 'number') { 18363 newFontSize = lineMax.size; 18364 18365 if(lineMax.match === 'exact') { 18366 break outer; 18367 } 18368 break inner; 18369 } 18370 } 18371 } 18372 18373 ratios.push(maxWidth / newFontSize); 18374 18375 if(newFontSize > maxFontSize) { 18376 fontSizes.push(maxFontSize); 18377 minFontSizes.push(false); 18378 } else if(!!minFontSize && newFontSize < minFontSize) { 18379 fontSizes.push(minFontSize); 18380 minFontSizes.push(true); 18381 } else { 18382 fontSizes.push(newFontSize); 18383 minFontSizes.push(false); 18384 } 18385 }).each(function(lineNumber) { 18386 var $line = $(this), 18387 wordSpacing = 0, 18388 interval = 1, 18389 maxWordSpacing; 18390 18391 if($line.hasClass(BigText.EXEMPT_CLASS)) { 18392 wordSpacings.push(null); 18393 return; 18394 } 18395 18396 // must re-use font-size, even though it was removed above. 18397 $line.css('font-size', fontSizes[lineNumber] + 'px'); 18398 18399 for(var m=1, n=3; m<n; m+=interval) { 18400 maxWordSpacing = BigText.testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 18401 if(typeof maxWordSpacing !== 'number') { 18402 wordSpacing = maxWordSpacing.size; 18403 break; 18404 } 18405 } 18406 18407 $line.css('font-size', ''); 18408 wordSpacings.push(wordSpacing); 18409 }).removeAttr('style'); 18410 18411 if( !BigText.DEBUG_MODE ) { 18412 $c.remove(); 18413 } else { 18414 $c.css({ 18415 'background-color': 'rgba(255,255,255,.4)' 18416 }); 18417 } 18418 18419 return { 18420 fontSizes: fontSizes, 18421 wordSpacings: wordSpacings, 18422 ratios: ratios, 18423 minFontSizes: minFontSizes 18424 }; 18425 } 18426 }; 18427 18428 $.fn.bigtext = BigText.jQueryMethod; 18429 window.BigText = BigText; 18430 18431})(this, jQuery);
vendor: 16,093 bytes, lines 18432-19089
18432/*! 18433 * Isotope PACKAGED v3.0.6 18434 * 18435 * Licensed GPLv3 for open source use 18436 * or Isotope Commercial License for commercial use 18437 * 18438 * https://isotope.metafizzy.co 18439 * Copyright 2010-2018 Metafizzy 18440 */ 18441 18442/** 18443 * Bridget makes jQuery widgets 18444 * v2.0.1 18445 * MIT license 18446 */ 18447 18448/* jshint browser: true, strict: true, undef: true, unused: true */ 18449 18450( function( window, factory ) { 18451 // universal module definition 18452 /*jshint strict: false */ /* globals define, module, require */ 18453 if ( typeof define == 'function' && define.amd ) { 18454 // AMD 18455 define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) { 18456 return factory( window, jQuery ); 18457 }); 18458 } else if ( typeof module == 'object' && module.exports ) { 18459 // CommonJS 18460 module.exports = factory( 18461 window, 18462 require('jquery') 18463 ); 18464 } else { 18465 // browser global 18466 window.jQueryBridget = factory( 18467 window, 18468 window.jQuery 18469 ); 18470 } 18471 18472}( window, function factory( window, jQuery ) { 18473'use strict'; 18474 18475// ----- utils ----- // 18476 18477var arraySlice = Array.prototype.slice; 18478 18479// helper function for logging errors 18480// $.error breaks jQuery chaining 18481var console = window.console; 18482var logError = typeof console == 'undefined' ? function() {} : 18483 function( message ) { 18484 console.error( message ); 18485 }; 18486 18487// ----- jQueryBridget ----- // 18488 18489function jQueryBridget( namespace, PluginClass, $ ) { 18490 $ = $ || jQuery || window.jQuery; 18491 if ( !$ ) { 18492 return; 18493 } 18494 18495 // add option method -> $().plugin('option', {...}) 18496 if ( !PluginClass.prototype.option ) { 18497 // option setter 18498 PluginClass.prototype.option = function( opts ) { 18499 // bail out if not an object 18500 if ( !$.isPlainObject( opts ) ){ 18501 return; 18502 } 18503 this.options = $.extend( true, this.options, opts ); 18504 }; 18505 } 18506 18507 // make jQuery plugin 18508 $.fn[ namespace ] = function( arg0 /*, arg1 */ ) { 18509 if ( typeof arg0 == 'string' ) { 18510 // method call $().plugin( 'methodName', { options } ) 18511 // shift arguments by 1 18512 var args = arraySlice.call( arguments, 1 ); 18513 return methodCall( this, arg0, args ); 18514 } 18515 // just $().plugin({ options }) 18516 plainCall( this, arg0 ); 18517 return this; 18518 }; 18519 18520 // $().plugin('methodName') 18521 function methodCall( $elems, methodName, args ) { 18522 var returnValue; 18523 var pluginMethodStr = '$().' + namespace + '("' + methodName + '")'; 18524 18525 $elems.each( function( i, elem ) { 18526 // get instance 18527 var instance = $.data( elem, namespace ); 18528 if ( !instance ) { 18529 logError( namespace + ' not initialized. Cannot call methods, i.e. ' + 18530 pluginMethodStr ); 18531 return; 18532 } 18533 18534 var method = instance[ methodName ]; 18535 if ( !method || methodName.charAt(0) == '_' ) { 18536 logError( pluginMethodStr + ' is not a valid method' ); 18537 return; 18538 } 18539 18540 // apply method, get return value 18541 var value = method.apply( instance, args ); 18542 // set return value if value is returned, use only first value 18543 returnValue = returnValue === undefined ? value : returnValue; 18544 }); 18545 18546 return returnValue !== undefined ? returnValue : $elems; 18547 } 18548 18549 function plainCall( $elems, options ) { 18550 $elems.each( function( i, elem ) { 18551 var instance = $.data( elem, namespace ); 18552 if ( instance ) { 18553 // set options & init 18554 instance.option( options ); 18555 instance._init(); 18556 } else { 18557 // initialize new instance 18558 instance = new PluginClass( elem, options ); 18559 $.data( elem, namespace, instance ); 18560 } 18561 }); 18562 } 18563 18564 updateJQuery( $ ); 18565 18566} 18567 18568// ----- updateJQuery ----- // 18569 18570// set $.bridget for v1 backwards compatibility 18571function updateJQuery( $ ) { 18572 if ( !$ || ( $ && $.bridget ) ) { 18573 return; 18574 } 18575 $.bridget = jQueryBridget; 18576} 18577 18578updateJQuery( jQuery || window.jQuery ); 18579 18580// ----- ----- // 18581 18582return jQueryBridget; 18583 18584})); 18585 18586/** 18587 * EvEmitter v1.1.0 18588 * Lil' event emitter 18589 * MIT License 18590 */ 18591 18592/* jshint unused: true, undef: true, strict: true */ 18593 18594( function( global, factory ) { 18595 // universal module definition 18596 /* jshint strict: false */ /* globals define, module, window */ 18597 if ( typeof define == 'function' && define.amd ) { 18598 // AMD - RequireJS 18599 define( 'ev-emitter/ev-emitter',factory ); 18600 } else if ( typeof module == 'object' && module.exports ) { 18601 // CommonJS - Browserify, Webpack 18602 module.exports = factory(); 18603 } else { 18604 // Browser globals 18605 global.EvEmitter = factory(); 18606 } 18607 18608}( typeof window != 'undefined' ? window : this, function() { 18609 18610 18611 18612function EvEmitter() {} 18613 18614var proto = EvEmitter.prototype; 18615 18616proto.on = function( eventName, listener ) { 18617 if ( !eventName || !listener ) { 18618 return; 18619 } 18620 // set events hash 18621 var events = this._events = this._events || {}; 18622 // set listeners array 18623 var listeners = events[ eventName ] = events[ eventName ] || []; 18624 // only add once 18625 if ( listeners.indexOf( listener ) == -1 ) { 18626 listeners.push( listener ); 18627 } 18628 18629 return this; 18630}; 18631 18632proto.once = function( eventName, listener ) { 18633 if ( !eventName || !listener ) { 18634 return; 18635 } 18636 // add event 18637 this.on( eventName, listener ); 18638 // set once flag 18639 // set onceEvents hash 18640 var onceEvents = this._onceEvents = this._onceEvents || {}; 18641 // set onceListeners object 18642 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 18643 // set flag 18644 onceListeners[ listener ] = true; 18645 18646 return this; 18647}; 18648 18649proto.off = function( eventName, listener ) { 18650 var listeners = this._events && this._events[ eventName ]; 18651 if ( !listeners || !listeners.length ) { 18652 return; 18653 } 18654 var index = listeners.indexOf( listener ); 18655 if ( index != -1 ) { 18656 listeners.splice( index, 1 ); 18657 } 18658 18659 return this; 18660}; 18661 18662proto.emitEvent = function( eventName, args ) { 18663 var listeners = this._events && this._events[ eventName ]; 18664 if ( !listeners || !listeners.length ) { 18665 return; 18666 } 18667 // copy over to avoid interference if .off() in listener 18668 listeners = listeners.slice(0); 18669 args = args || []; 18670 // once stuff 18671 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 18672 18673 for ( var i=0; i < listeners.length; i++ ) { 18674 var listener = listeners[i] 18675 var isOnce = onceListeners && onceListeners[ listener ]; 18676 if ( isOnce ) { 18677 // remove listener 18678 // remove before trigger to prevent recursion 18679 this.off( eventName, listener ); 18680 // unset once flag 18681 delete onceListeners[ listener ]; 18682 } 18683 // trigger listener 18684 listener.apply( this, args ); 18685 } 18686 18687 return this; 18688}; 18689 18690proto.allOff = function() { 18691 delete this._events; 18692 delete this._onceEvents; 18693}; 18694 18695return EvEmitter; 18696 18697})); 18698 18699/*! 18700 * getSize v2.0.3 18701 * measure size of elements 18702 * MIT license 18703 */ 18704 18705/* jshint browser: true, strict: true, undef: true, unused: true */ 18706/* globals console: false */ 18707 18708( function( window, factory ) { 18709 /* jshint strict: false */ /* globals define, module */ 18710 if ( typeof define == 'function' && define.amd ) { 18711 // AMD 18712 define( 'get-size/get-size',factory ); 18713 } else if ( typeof module == 'object' && module.exports ) { 18714 // CommonJS 18715 module.exports = factory(); 18716 } else { 18717 // browser global 18718 window.getSize = factory(); 18719 } 18720 18721})( window, function factory() { 18722'use strict'; 18723 18724// -------------------------- helpers -------------------------- // 18725 18726// get a number from a string, not a percentage 18727function getStyleSize( value ) { 18728 var num = parseFloat( value ); 18729 // not a percent like '100%', and a number 18730 var isValid = value.indexOf('%') == -1 && !isNaN( num ); 18731 return isValid && num; 18732} 18733 18734function noop() {} 18735 18736var logError = typeof console == 'undefined' ? noop : 18737 function( message ) { 18738 console.error( message ); 18739 }; 18740 18741// -------------------------- measurements -------------------------- // 18742 18743var measurements = [ 18744 'paddingLeft', 18745 'paddingRight', 18746 'paddingTop', 18747 'paddingBottom', 18748 'marginLeft', 18749 'marginRight', 18750 'marginTop', 18751 'marginBottom', 18752 'borderLeftWidth', 18753 'borderRightWidth', 18754 'borderTopWidth', 18755 'borderBottomWidth' 18756]; 18757 18758var measurementsLength = measurements.length; 18759 18760function getZeroSize() { 18761 var size = { 18762 width: 0, 18763 height: 0, 18764 innerWidth: 0, 18765 innerHeight: 0, 18766 outerWidth: 0, 18767 outerHeight: 0 18768 }; 18769 for ( var i=0; i < measurementsLength; i++ ) { 18770 var measurement = measurements[i]; 18771 size[ measurement ] = 0; 18772 } 18773 return size; 18774} 18775 18776// -------------------------- getStyle -------------------------- // 18777 18778/** 18779 * getStyle, get style of element, check for Firefox bug 18780 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 18781 */ 18782function getStyle( elem ) { 18783 var style = getComputedStyle( elem ); 18784 if ( !style ) { 18785 logError( 'Style returned ' + style + 18786 '. Are you running this code in a hidden iframe on Firefox? ' + 18787 'See https://bit.ly/getsizebug1' ); 18788 } 18789 return style; 18790} 18791 18792// -------------------------- setup -------------------------- // 18793 18794var isSetup = false; 18795 18796var isBoxSizeOuter; 18797 18798/** 18799 * setup 18800 * check isBoxSizerOuter 18801 * do on first getSize() rather than on page load for Firefox bug 18802 */ 18803function setup() { 18804 // setup once 18805 if ( isSetup ) { 18806 return; 18807 } 18808 isSetup = true; 18809 18810 // -------------------------- box sizing -------------------------- // 18811 18812 /** 18813 * Chrome & Safari measure the outer-width on style.width on border-box elems 18814 * IE11 & Firefox<29 measures the inner-width 18815 */ 18816 var div = document.createElement('div'); 18817 div.style.width = '200px'; 18818 div.style.padding = '1px 2px 3px 4px'; 18819 div.style.borderStyle = 'solid'; 18820 div.style.borderWidth = '1px 2px 3px 4px'; 18821 div.style.boxSizing = 'border-box'; 18822 18823 var body = document.body || document.documentElement; 18824 body.appendChild( div ); 18825 var style = getStyle( div ); 18826 // round value for browser zoom. desandro/masonry#928 18827 isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200; 18828 getSize.isBoxSizeOuter = isBoxSizeOuter; 18829 18830 body.removeChild( div ); 18831} 18832 18833// -------------------------- getSize -------------------------- // 18834 18835function getSize( elem ) { 18836 setup(); 18837 18838 // use querySeletor if elem is string 18839 if ( typeof elem == 'string' ) { 18840 elem = document.querySelector( elem ); 18841 } 18842 18843 // do not proceed on non-objects 18844 if ( !elem || typeof elem != 'object' || !elem.nodeType ) { 18845 return; 18846 } 18847 18848 var style = getStyle( elem ); 18849 18850 // if hidden, everything is 0 18851 if ( style.display == 'none' ) { 18852 return getZeroSize(); 18853 } 18854 18855 var size = {}; 18856 size.width = elem.offsetWidth; 18857 size.height = elem.offsetHeight; 18858 18859 var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; 18860 18861 // get all measurements 18862 for ( var i=0; i < measurementsLength; i++ ) { 18863 var measurement = measurements[i]; 18864 var value = style[ measurement ]; 18865 var num = parseFloat( value ); 18866 // any 'auto', 'medium' value will be 0 18867 size[ measurement ] = !isNaN( num ) ? num : 0; 18868 } 18869 18870 var paddingWidth = size.paddingLeft + size.paddingRight; 18871 var paddingHeight = size.paddingTop + size.paddingBottom; 18872 var marginWidth = size.marginLeft + size.marginRight; 18873 var marginHeight = size.marginTop + size.marginBottom; 18874 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 18875 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 18876 18877 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 18878 18879 // overwrite width and height if we can get it from style 18880 var styleWidth = getStyleSize( style.width ); 18881 if ( styleWidth !== false ) { 18882 size.width = styleWidth + 18883 // add padding and border unless it's already including it 18884 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 18885 } 18886 18887 var styleHeight = getStyleSize( style.height ); 18888 if ( styleHeight !== false ) { 18889 size.height = styleHeight + 18890 // add padding and border unless it's already including it 18891 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 18892 } 18893 18894 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 18895 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 18896 18897 size.outerWidth = size.width + marginWidth; 18898 size.outerHeight = size.height + marginHeight; 18899 18900 return size; 18901} 18902 18903return getSize; 18904 18905}); 18906 18907/** 18908 * matchesSelector v2.0.2 18909 * matchesSelector( element, '.selector' ) 18910 * MIT license 18911 */ 18912 18913/*jshint browser: true, strict: true, undef: true, unused: true */ 18914 18915( function( window, factory ) { 18916 /*global define: false, module: false */ 18917 'use strict'; 18918 // universal module definition 18919 if ( typeof define == 'function' && define.amd ) { 18920 // AMD 18921 define( 'desandro-matches-selector/matches-selector',factory ); 18922 } else if ( typeof module == 'object' && module.exports ) { 18923 // CommonJS 18924 module.exports = factory(); 18925 } else { 18926 // browser global 18927 window.matchesSelector = factory(); 18928 } 18929 18930}( window, function factory() { 18931 'use strict'; 18932 18933 var matchesMethod = ( function() { 18934 var ElemProto = window.Element.prototype; 18935 // check for the standard method name first 18936 if ( ElemProto.matches ) { 18937 return 'matches'; 18938 } 18939 // check un-prefixed 18940 if ( ElemProto.matchesSelector ) { 18941 return 'matchesSelector'; 18942 } 18943 // check vendor prefixes 18944 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 18945 18946 for ( var i=0; i < prefixes.length; i++ ) { 18947 var prefix = prefixes[i]; 18948 var method = prefix + 'MatchesSelector'; 18949 if ( ElemProto[ method ] ) { 18950 return method; 18951 } 18952 } 18953 })(); 18954 18955 return function matchesSelector( elem, selector ) { 18956 return elem[ matchesMethod ]( selector ); 18957 }; 18958 18959})); 18960 18961/** 18962 * Fizzy UI utils v2.0.7 18963 * MIT license 18964 */ 18965 18966/*jshint browser: true, undef: true, unused: true, strict: true */ 18967 18968( function( window, factory ) { 18969 // universal module definition 18970 /*jshint strict: false */ /*globals define, module, require */ 18971 18972 if ( typeof define == 'function' && define.amd ) { 18973 // AMD 18974 define( 'fizzy-ui-utils/utils',[ 18975 'desandro-matches-selector/matches-selector' 18976 ], function( matchesSelector ) { 18977 return factory( window, matchesSelector ); 18978 }); 18979 } else if ( typeof module == 'object' && module.exports ) { 18980 // CommonJS 18981 module.exports = factory( 18982 window, 18983 require('desandro-matches-selector') 18984 ); 18985 } else { 18986 // browser global 18987 window.fizzyUIUtils = factory( 18988 window, 18989 window.matchesSelector 18990 ); 18991 } 18992 18993}( window, function factory( window, matchesSelector ) { 18994 18995 18996 18997var utils = {}; 18998 18999// ----- extend ----- // 19000 19001// extends objects 19002utils.extend = function( a, b ) { 19003 for ( var prop in b ) { 19004 a[ prop ] = b[ prop ]; 19005 } 19006 return a; 19007}; 19008 19009// ----- modulo ----- // 19010 19011utils.modulo = function( num, div ) { 19012 return ( ( num % div ) + div ) % div; 19013}; 19014 19015// ----- makeArray ----- // 19016 19017var arraySlice = Array.prototype.slice; 19018 19019// turn element or nodeList into an array 19020utils.makeArray = function( obj ) { 19021 if ( Array.isArray( obj ) ) { 19022 // use object if already an array 19023 return obj; 19024 } 19025 // return empty array if undefined or null. #6 19026 if ( obj === null || obj === undefined ) { 19027 return []; 19028 } 19029 19030 var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; 19031 if ( isArrayLike ) { 19032 // convert nodeList to array 19033 return arraySlice.call( obj ); 19034 } 19035 19036 // array of single index 19037 return [ obj ]; 19038}; 19039 19040// ----- removeFrom ----- // 19041 19042utils.removeFrom = function( ary, obj ) { 19043 var index = ary.indexOf( obj ); 19044 if ( index != -1 ) { 19045 ary.splice( index, 1 ); 19046 } 19047}; 19048 19049// ----- getParent ----- // 19050 19051utils.getParent = function( elem, selector ) { 19052 while ( elem.parentNode && elem != document.body ) { 19053 elem = elem.parentNode; 19054 if ( matchesSelector( elem, selector ) ) { 19055 return elem; 19056 } 19057 } 19058}; 19059 19060// ----- getQueryElement ----- // 19061 19062// use element as selector string 19063utils.getQueryElement = function( elem ) { 19064 if ( typeof elem == 'string' ) { 19065 return document.querySelector( elem ); 19066 } 19067 return elem; 19068}; 19069 19070// ----- handleEvent ----- // 19071 19072// enable .ontype to trigger from .addEventListener( elem, 'type' ) 19073utils.handleEvent = function( event ) { 19074 var method = 'on' + event.type; 19075 if ( this[ method ] ) { 19076 this[ method ]( event ); 19077 } 19078}; 19079 19080// ----- filterFindElements ----- // 19081 19082utils.filterFindElements = function( elems, selector ) { 19083 // make array of elems 19084 elems = utils.makeArray( elems ); 19085 var ffElems = []; 19086 19087 elems.forEach( function( elem ) { 19088 // check that elem is an actual element 19089
19089// START UNCODE EDIT 19090 // if ( !( elem instanceof HTMLElement ) ) { 19091 if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) { 19092 // END UNCODE EDIT
vendor: 75,264 bytes, lines 19092-21997
19092 19093 return; 19094 } 19095 // add elem if no selector 19096 if ( !selector ) { 19097 ffElems.push( elem ); 19098 return; 19099 } 19100 // filter & find items if we have a selector 19101 // filter 19102 if ( matchesSelector( elem, selector ) ) { 19103 ffElems.push( elem ); 19104 } 19105 // find children 19106 var childElems = elem.querySelectorAll( selector ); 19107 // concat childElems to filterFound array 19108 for ( var i=0; i < childElems.length; i++ ) { 19109 ffElems.push( childElems[i] ); 19110 } 19111 }); 19112 19113 return ffElems; 19114}; 19115 19116// ----- debounceMethod ----- // 19117 19118utils.debounceMethod = function( _class, methodName, threshold ) { 19119 threshold = threshold || 100; 19120 // original method 19121 var method = _class.prototype[ methodName ]; 19122 var timeoutName = methodName + 'Timeout'; 19123 19124 _class.prototype[ methodName ] = function() { 19125 var timeout = this[ timeoutName ]; 19126 clearTimeout( timeout ); 19127 19128 var args = arguments; 19129 var _this = this; 19130 this[ timeoutName ] = setTimeout( function() { 19131 method.apply( _this, args ); 19132 delete _this[ timeoutName ]; 19133 }, threshold ); 19134 }; 19135}; 19136 19137// ----- docReady ----- // 19138 19139utils.docReady = function( callback ) { 19140 var readyState = document.readyState; 19141 if ( readyState == 'complete' || readyState == 'interactive' ) { 19142 // do async to allow for other scripts to run. metafizzy/flickity#441 19143 setTimeout( callback ); 19144 } else { 19145 document.addEventListener( 'DOMContentLoaded', callback ); 19146 } 19147}; 19148 19149// ----- htmlInit ----- // 19150 19151// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 19152utils.toDashed = function( str ) { 19153 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 19154 return $1 + '-' + $2; 19155 }).toLowerCase(); 19156}; 19157 19158var console = window.console; 19159/** 19160 * allow user to initialize classes via [data-namespace] or .js-namespace class 19161 * htmlInit( Widget, 'widgetName' ) 19162 * options are parsed from data-namespace-options 19163 */ 19164utils.htmlInit = function( WidgetClass, namespace ) { 19165 utils.docReady( function() { 19166 var dashedNamespace = utils.toDashed( namespace ); 19167 var dataAttr = 'data-' + dashedNamespace; 19168 var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); 19169 var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); 19170 var elems = utils.makeArray( dataAttrElems ) 19171 .concat( utils.makeArray( jsDashElems ) ); 19172 var dataOptionsAttr = dataAttr + '-options'; 19173 var jQuery = window.jQuery; 19174 19175 elems.forEach( function( elem ) { 19176 var attr = elem.getAttribute( dataAttr ) || 19177 elem.getAttribute( dataOptionsAttr ); 19178 var options; 19179 try { 19180 options = attr && JSON.parse( attr ); 19181 } catch ( error ) { 19182 // log error, do not initialize 19183 if ( console ) { 19184 console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + 19185 ': ' + error ); 19186 } 19187 return; 19188 } 19189 // initialize 19190 var instance = new WidgetClass( elem, options ); 19191 // make available via $().data('namespace') 19192 if ( jQuery ) { 19193 jQuery.data( elem, namespace, instance ); 19194 } 19195 }); 19196 19197 }); 19198}; 19199 19200// ----- ----- // 19201 19202return utils; 19203 19204})); 19205 19206/** 19207 * Outlayer Item 19208 */ 19209 19210( function( window, factory ) { 19211 // universal module definition 19212 /* jshint strict: false */ /* globals define, module, require */ 19213 if ( typeof define == 'function' && define.amd ) { 19214 // AMD - RequireJS 19215 define( 'outlayer/item',[ 19216 'ev-emitter/ev-emitter', 19217 'get-size/get-size' 19218 ], 19219 factory 19220 ); 19221 } else if ( typeof module == 'object' && module.exports ) { 19222 // CommonJS - Browserify, Webpack 19223 module.exports = factory( 19224 require('ev-emitter'), 19225 require('get-size') 19226 ); 19227 } else { 19228 // browser global 19229 window.Outlayer = {}; 19230 window.Outlayer.Item = factory( 19231 window.EvEmitter, 19232 window.getSize 19233 ); 19234 } 19235 19236}( window, function factory( EvEmitter, getSize ) { 19237'use strict'; 19238 19239// ----- helpers ----- // 19240 19241function isEmptyObj( obj ) { 19242 for ( var prop in obj ) { 19243 return false; 19244 } 19245 prop = null; 19246 return true; 19247} 19248 19249// -------------------------- CSS3 support -------------------------- // 19250 19251 19252var docElemStyle = document.documentElement.style; 19253 19254var transitionProperty = typeof docElemStyle.transition == 'string' ? 19255 'transition' : 'WebkitTransition'; 19256var transformProperty = typeof docElemStyle.transform == 'string' ? 19257 'transform' : 'WebkitTransform'; 19258 19259var transitionEndEvent = { 19260 WebkitTransition: 'webkitTransitionEnd', 19261 transition: 'transitionend' 19262}[ transitionProperty ]; 19263 19264// cache all vendor properties that could have vendor prefix 19265var vendorProperties = { 19266 transform: transformProperty, 19267 transition: transitionProperty, 19268 transitionDuration: transitionProperty + 'Duration', 19269 transitionProperty: transitionProperty + 'Property', 19270 transitionDelay: transitionProperty + 'Delay' 19271}; 19272 19273// -------------------------- Item -------------------------- // 19274 19275function Item( element, layout ) { 19276 if ( !element ) { 19277 return; 19278 } 19279 19280 this.element = element; 19281 // parent layout class, i.e. Masonry, Isotope, or Packery 19282 this.layout = layout; 19283 this.position = { 19284 x: 0, 19285 y: 0 19286 }; 19287 19288 this._create(); 19289} 19290 19291// inherit EvEmitter 19292var proto = Item.prototype = Object.create( EvEmitter.prototype ); 19293proto.constructor = Item; 19294 19295proto._create = function() { 19296 // transition objects 19297 this._transn = { 19298 ingProperties: {}, 19299 clean: {}, 19300 onEnd: {} 19301 }; 19302 19303 this.css({ 19304 position: 'absolute' 19305 }); 19306}; 19307 19308// trigger specified handler for event type 19309proto.handleEvent = function( event ) { 19310 var method = 'on' + event.type; 19311 if ( this[ method ] ) { 19312 this[ method ]( event ); 19313 } 19314}; 19315 19316proto.getSize = function() { 19317 this.size = getSize( this.element ); 19318}; 19319 19320/** 19321 * apply CSS styles to element 19322 * @param {Object} style 19323 */ 19324proto.css = function( style ) { 19325 var elemStyle = this.element.style; 19326 19327 for ( var prop in style ) { 19328 // use vendor property if available 19329 var supportedProp = vendorProperties[ prop ] || prop; 19330 elemStyle[ supportedProp ] = style[ prop ]; 19331 } 19332}; 19333 19334 // measure position, and sets it 19335proto.getPosition = function() { 19336 var style = getComputedStyle( this.element ); 19337 var isOriginLeft = this.layout._getOption('originLeft'); 19338 var isOriginTop = this.layout._getOption('originTop'); 19339 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 19340 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 19341 var x = parseFloat( xValue ); 19342 var y = parseFloat( yValue ); 19343 // convert percent to pixels 19344 var layoutSize = this.layout.size; 19345 if ( xValue.indexOf('%') != -1 ) { 19346 x = ( x / 100 ) * layoutSize.width; 19347 } 19348 if ( yValue.indexOf('%') != -1 ) { 19349 y = ( y / 100 ) * layoutSize.height; 19350 } 19351 // clean up 'auto' or other non-integer values 19352 x = isNaN( x ) ? 0 : x; 19353 y = isNaN( y ) ? 0 : y; 19354 // remove padding from measurement 19355 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 19356 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 19357 19358 this.position.x = x; 19359 this.position.y = y; 19360}; 19361 19362// set settled position, apply padding 19363proto.layoutPosition = function() { 19364 var layoutSize = this.layout.size; 19365 var style = {}; 19366 var isOriginLeft = this.layout._getOption('originLeft'); 19367 var isOriginTop = this.layout._getOption('originTop'); 19368 19369 // x 19370 var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; 19371 var xProperty = isOriginLeft ? 'left' : 'right'; 19372 var xResetProperty = isOriginLeft ? 'right' : 'left'; 19373 19374 var x = this.position.x + layoutSize[ xPadding ]; 19375 // set in percentage or pixels 19376 style[ xProperty ] = this.getXValue( x ); 19377 // reset other property 19378 style[ xResetProperty ] = ''; 19379 19380 // y 19381 var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; 19382 var yProperty = isOriginTop ? 'top' : 'bottom'; 19383 var yResetProperty = isOriginTop ? 'bottom' : 'top'; 19384 19385 var y = this.position.y + layoutSize[ yPadding ]; 19386 // set in percentage or pixels 19387 style[ yProperty ] = this.getYValue( y ); 19388 // reset other property 19389 style[ yResetProperty ] = ''; 19390 19391 this.css( style ); 19392 this.emitEvent( 'layout', [ this ] ); 19393}; 19394 19395proto.getXValue = function( x ) { 19396 var isHorizontal = this.layout._getOption('horizontal'); 19397 return this.layout.options.percentPosition && !isHorizontal ? 19398 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 19399}; 19400 19401proto.getYValue = function( y ) { 19402 var isHorizontal = this.layout._getOption('horizontal'); 19403 return this.layout.options.percentPosition && isHorizontal ? 19404 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 19405}; 19406 19407proto._transitionTo = function( x, y ) { 19408 this.getPosition(); 19409 // get current x & y from top/left 19410 var curX = this.position.x; 19411 var curY = this.position.y; 19412 19413 var didNotMove = x == this.position.x && y == this.position.y; 19414 19415 // save end position 19416 this.setPosition( x, y ); 19417 19418 // if did not move and not transitioning, just go to layout 19419 if ( didNotMove && !this.isTransitioning ) { 19420 this.layoutPosition(); 19421 return; 19422 } 19423 19424 var transX = x - curX; 19425 var transY = y - curY; 19426 var transitionStyle = {}; 19427 transitionStyle.transform = this.getTranslate( transX, transY ); 19428 19429 this.transition({ 19430 to: transitionStyle, 19431 onTransitionEnd: { 19432 transform: this.layoutPosition 19433 }, 19434 isCleaning: true 19435 }); 19436}; 19437 19438proto.getTranslate = function( x, y ) { 19439 // flip cooridinates if origin on right or bottom 19440 var isOriginLeft = this.layout._getOption('originLeft'); 19441 var isOriginTop = this.layout._getOption('originTop'); 19442 x = isOriginLeft ? x : -x; 19443 y = isOriginTop ? y : -y; 19444 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 19445}; 19446 19447// non transition + transform support 19448proto.goTo = function( x, y ) { 19449 this.setPosition( x, y ); 19450 this.layoutPosition(); 19451}; 19452 19453proto.moveTo = proto._transitionTo; 19454 19455proto.setPosition = function( x, y ) { 19456 this.position.x = parseFloat( x ); 19457 this.position.y = parseFloat( y ); 19458}; 19459 19460// ----- transition ----- // 19461 19462/** 19463 * @param {Object} style - CSS 19464 * @param {Function} onTransitionEnd 19465 */ 19466 19467// non transition, just trigger callback 19468proto._nonTransition = function( args ) { 19469 this.css( args.to ); 19470 if ( args.isCleaning ) { 19471 this._removeStyles( args.to ); 19472 } 19473 for ( var prop in args.onTransitionEnd ) { 19474 args.onTransitionEnd[ prop ].call( this ); 19475 } 19476}; 19477 19478/** 19479 * proper transition 19480 * @param {Object} args - arguments 19481 * @param {Object} to - style to transition to 19482 * @param {Object} from - style to start transition from 19483 * @param {Boolean} isCleaning - removes transition styles after transition 19484 * @param {Function} onTransitionEnd - callback 19485 */ 19486proto.transition = function( args ) { 19487 // redirect to nonTransition if no transition duration 19488 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 19489 this._nonTransition( args ); 19490 return; 19491 } 19492 19493 var _transition = this._transn; 19494 // keep track of onTransitionEnd callback by css property 19495 for ( var prop in args.onTransitionEnd ) { 19496 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 19497 } 19498 // keep track of properties that are transitioning 19499 for ( prop in args.to ) { 19500 _transition.ingProperties[ prop ] = true; 19501 // keep track of properties to clean up when transition is done 19502 if ( args.isCleaning ) { 19503 _transition.clean[ prop ] = true; 19504 } 19505 } 19506 19507 // set from styles 19508 if ( args.from ) { 19509 this.css( args.from ); 19510 // force redraw. http://blog.alexmaccaw.com/css-transitions 19511 var h = this.element.offsetHeight; 19512 // hack for JSHint to hush about unused var 19513 h = null; 19514 } 19515 // enable transition 19516 this.enableTransition( args.to ); 19517 // set styles that are transitioning 19518 this.css( args.to ); 19519 19520 this.isTransitioning = true; 19521 19522}; 19523 19524// dash before all cap letters, including first for 19525// WebkitTransform => -webkit-transform 19526function toDashedAll( str ) { 19527 return str.replace( /([A-Z])/g, function( $1 ) { 19528 return '-' + $1.toLowerCase(); 19529 }); 19530} 19531 19532var transitionProps = 'opacity,' + toDashedAll( transformProperty ); 19533 19534proto.enableTransition = function(/* style */) { 19535 // HACK changing transitionProperty during a transition 19536 // will cause transition to jump 19537 if ( this.isTransitioning ) { 19538 return; 19539 } 19540 19541 // make `transition: foo, bar, baz` from style object 19542 // HACK un-comment this when enableTransition can work 19543 // while a transition is happening 19544 // var transitionValues = []; 19545 // for ( var prop in style ) { 19546 // // dash-ify camelCased properties like WebkitTransition 19547 // prop = vendorProperties[ prop ] || prop; 19548 // transitionValues.push( toDashedAll( prop ) ); 19549 // } 19550 // munge number to millisecond, to match stagger 19551 var duration = this.layout.options.transitionDuration; 19552 duration = typeof duration == 'number' ? duration + 'ms' : duration; 19553 // enable transition styles 19554 this.css({ 19555 transitionProperty: transitionProps, 19556 transitionDuration: duration, 19557 transitionDelay: this.staggerDelay || 0 19558 }); 19559 // listen for transition end event 19560 this.element.addEventListener( transitionEndEvent, this, false ); 19561}; 19562 19563// ----- events ----- // 19564 19565proto.onwebkitTransitionEnd = function( event ) { 19566 this.ontransitionend( event ); 19567}; 19568 19569proto.onotransitionend = function( event ) { 19570 this.ontransitionend( event ); 19571}; 19572 19573// properties that I munge to make my life easier 19574var dashedVendorProperties = { 19575 '-webkit-transform': 'transform' 19576}; 19577 19578proto.ontransitionend = function( event ) { 19579 // disregard bubbled events from children 19580 if ( event.target !== this.element ) { 19581 return; 19582 } 19583 var _transition = this._transn; 19584 // get property name of transitioned property, convert to prefix-free 19585 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 19586 19587 // remove property that has completed transitioning 19588 delete _transition.ingProperties[ propertyName ]; 19589 // check if any properties are still transitioning 19590 if ( isEmptyObj( _transition.ingProperties ) ) { 19591 // all properties have completed transitioning 19592 this.disableTransition(); 19593 } 19594 // clean style 19595 if ( propertyName in _transition.clean ) { 19596 // clean up style 19597 this.element.style[ event.propertyName ] = ''; 19598 delete _transition.clean[ propertyName ]; 19599 } 19600 // trigger onTransitionEnd callback 19601 if ( propertyName in _transition.onEnd ) { 19602 var onTransitionEnd = _transition.onEnd[ propertyName ]; 19603 onTransitionEnd.call( this ); 19604 delete _transition.onEnd[ propertyName ]; 19605 } 19606 19607 this.emitEvent( 'transitionEnd', [ this ] ); 19608}; 19609 19610proto.disableTransition = function() { 19611 this.removeTransitionStyles(); 19612 this.element.removeEventListener( transitionEndEvent, this, false ); 19613 this.isTransitioning = false; 19614}; 19615 19616/** 19617 * removes style property from element 19618 * @param {Object} style 19619**/ 19620proto._removeStyles = function( style ) { 19621 // clean up transition styles 19622 var cleanStyle = {}; 19623 for ( var prop in style ) { 19624 cleanStyle[ prop ] = ''; 19625 } 19626 this.css( cleanStyle ); 19627}; 19628 19629var cleanTransitionStyle = { 19630 transitionProperty: '', 19631 transitionDuration: '', 19632 transitionDelay: '' 19633}; 19634 19635proto.removeTransitionStyles = function() { 19636 // remove transition 19637 this.css( cleanTransitionStyle ); 19638}; 19639 19640// ----- stagger ----- // 19641 19642proto.stagger = function( delay ) { 19643 delay = isNaN( delay ) ? 0 : delay; 19644 this.staggerDelay = delay + 'ms'; 19645}; 19646 19647// ----- show/hide/remove ----- // 19648 19649// remove element from DOM 19650proto.removeElem = function() { 19651 this.element.parentNode.removeChild( this.element ); 19652 // remove display: none 19653 this.css({ display: '' }); 19654 this.emitEvent( 'remove', [ this ] ); 19655}; 19656 19657proto.remove = function() { 19658 // just remove element if no transition support or no transition 19659 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 19660 this.removeElem(); 19661 return; 19662 } 19663 19664 // start transition 19665 this.once( 'transitionEnd', function() { 19666 this.removeElem(); 19667 }); 19668 this.hide(); 19669}; 19670 19671proto.reveal = function() { 19672 delete this.isHidden; 19673 // remove display: none 19674 this.css({ display: '' }); 19675 19676 var options = this.layout.options; 19677 19678 var onTransitionEnd = {}; 19679 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 19680 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 19681 19682 this.transition({ 19683 from: options.hiddenStyle, 19684 to: options.visibleStyle, 19685 isCleaning: true, 19686 onTransitionEnd: onTransitionEnd 19687 }); 19688}; 19689 19690proto.onRevealTransitionEnd = function() { 19691 // check if still visible 19692 // during transition, item may have been hidden 19693 if ( !this.isHidden ) { 19694 this.emitEvent('reveal'); 19695 } 19696}; 19697 19698/** 19699 * get style property use for hide/reveal transition end 19700 * @param {String} styleProperty - hiddenStyle/visibleStyle 19701 * @returns {String} 19702 */ 19703proto.getHideRevealTransitionEndProperty = function( styleProperty ) { 19704 var optionStyle = this.layout.options[ styleProperty ]; 19705 // use opacity 19706 if ( optionStyle.opacity ) { 19707 return 'opacity'; 19708 } 19709 // get first property 19710 for ( var prop in optionStyle ) { 19711 return prop; 19712 } 19713}; 19714 19715proto.hide = function() { 19716 // set flag 19717 this.isHidden = true; 19718 // remove display: none 19719 this.css({ display: '' }); 19720 19721 var options = this.layout.options; 19722 19723 var onTransitionEnd = {}; 19724 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 19725 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 19726 19727 this.transition({ 19728 from: options.visibleStyle, 19729 to: options.hiddenStyle, 19730 // keep hidden stuff hidden 19731 isCleaning: true, 19732 onTransitionEnd: onTransitionEnd 19733 }); 19734}; 19735 19736proto.onHideTransitionEnd = function() { 19737 // check if still hidden 19738 // during transition, item may have been un-hidden 19739 if ( this.isHidden ) { 19740 this.css({ display: 'none' }); 19741 this.emitEvent('hide'); 19742 } 19743}; 19744 19745proto.destroy = function() { 19746 this.css({ 19747 position: '', 19748 left: '', 19749 right: '', 19750 top: '', 19751 bottom: '', 19752 transition: '', 19753 transform: '' 19754 }); 19755}; 19756 19757return Item; 19758 19759})); 19760 19761/*! 19762 * Outlayer v2.1.1 19763 * the brains and guts of a layout library 19764 * MIT license 19765 */ 19766 19767( function( window, factory ) { 19768 'use strict'; 19769 // universal module definition 19770 /* jshint strict: false */ /* globals define, module, require */ 19771 if ( typeof define == 'function' && define.amd ) { 19772 // AMD - RequireJS 19773 define( 'outlayer/outlayer',[ 19774 'ev-emitter/ev-emitter', 19775 'get-size/get-size', 19776 'fizzy-ui-utils/utils', 19777 './item' 19778 ], 19779 function( EvEmitter, getSize, utils, Item ) { 19780 return factory( window, EvEmitter, getSize, utils, Item); 19781 } 19782 ); 19783 } else if ( typeof module == 'object' && module.exports ) { 19784 // CommonJS - Browserify, Webpack 19785 module.exports = factory( 19786 window, 19787 require('ev-emitter'), 19788 require('get-size'), 19789 require('fizzy-ui-utils'), 19790 require('./item') 19791 ); 19792 } else { 19793 // browser global 19794 window.Outlayer = factory( 19795 window, 19796 window.EvEmitter, 19797 window.getSize, 19798 window.fizzyUIUtils, 19799 window.Outlayer.Item 19800 ); 19801 } 19802 19803}( window, function factory( window, EvEmitter, getSize, utils, Item ) { 19804'use strict'; 19805 19806// ----- vars ----- // 19807 19808var console = window.console; 19809var jQuery = window.jQuery; 19810var noop = function() {}; 19811 19812// -------------------------- Outlayer -------------------------- // 19813 19814// globally unique identifiers 19815var GUID = 0; 19816// internal store of all Outlayer intances 19817var instances = {}; 19818 19819 19820/** 19821 * @param {Element, String} element 19822 * @param {Object} options 19823 * @constructor 19824 */ 19825function Outlayer( element, options ) { 19826 var queryElement = utils.getQueryElement( element ); 19827 if ( !queryElement ) { 19828 if ( console ) { 19829 console.error( 'Bad element for ' + this.constructor.namespace + 19830 ': ' + ( queryElement || element ) ); 19831 } 19832 return; 19833 } 19834 this.element = queryElement; 19835 // add jQuery 19836 if ( jQuery ) { 19837 this.$element = jQuery( this.element ); 19838 } 19839 19840 // options 19841 this.options = utils.extend( {}, this.constructor.defaults ); 19842 this.option( options ); 19843 19844 // add id for Outlayer.getFromElement 19845 var id = ++GUID; 19846 this.element.outlayerGUID = id; // expando 19847 instances[ id ] = this; // associate via id 19848 19849 // kick it off 19850 this._create(); 19851 19852 var isInitLayout = this._getOption('initLayout'); 19853 if ( isInitLayout ) { 19854 this.layout(); 19855 } 19856} 19857 19858// settings are for internal use only 19859Outlayer.namespace = 'outlayer'; 19860Outlayer.Item = Item; 19861 19862// default options 19863Outlayer.defaults = { 19864 containerStyle: { 19865 position: 'relative' 19866 }, 19867 initLayout: true, 19868 originLeft: true, 19869 originTop: true, 19870 resize: true, 19871 resizeContainer: true, 19872 // item options 19873 transitionDuration: '0.4s', 19874 hiddenStyle: { 19875 opacity: 0, 19876 transform: 'scale(0.001)' 19877 }, 19878 visibleStyle: { 19879 opacity: 1, 19880 transform: 'scale(1)' 19881 } 19882}; 19883 19884var proto = Outlayer.prototype; 19885// inherit EvEmitter 19886utils.extend( proto, EvEmitter.prototype ); 19887 19888/** 19889 * set options 19890 * @param {Object} opts 19891 */ 19892proto.option = function( opts ) { 19893 utils.extend( this.options, opts ); 19894}; 19895 19896/** 19897 * get backwards compatible option value, check old name 19898 */ 19899proto._getOption = function( option ) { 19900 var oldOption = this.constructor.compatOptions[ option ]; 19901 return oldOption && this.options[ oldOption ] !== undefined ? 19902 this.options[ oldOption ] : this.options[ option ]; 19903}; 19904 19905Outlayer.compatOptions = { 19906 // currentName: oldName 19907 initLayout: 'isInitLayout', 19908 horizontal: 'isHorizontal', 19909 layoutInstant: 'isLayoutInstant', 19910 originLeft: 'isOriginLeft', 19911 originTop: 'isOriginTop', 19912 resize: 'isResizeBound', 19913 resizeContainer: 'isResizingContainer' 19914}; 19915 19916proto._create = function() { 19917 // get items from children 19918 this.reloadItems(); 19919 // elements that affect layout, but are not laid out 19920 this.stamps = []; 19921 this.stamp( this.options.stamp ); 19922 // set container style 19923 utils.extend( this.element.style, this.options.containerStyle ); 19924 19925 // bind resize method 19926 var canBindResize = this._getOption('resize'); 19927 if ( canBindResize ) { 19928 this.bindResize(); 19929 } 19930}; 19931 19932// goes through all children again and gets bricks in proper order 19933proto.reloadItems = function() { 19934 // collection of item elements 19935 this.items = this._itemize( this.element.children ); 19936}; 19937 19938 19939/** 19940 * turn elements into Outlayer.Items to be used in layout 19941 * @param {Array or NodeList or HTMLElement} elems 19942 * @returns {Array} items - collection of new Outlayer Items 19943 */ 19944proto._itemize = function( elems ) { 19945 19946 var itemElems = this._filterFindItemElements( elems ); 19947 var Item = this.constructor.Item; 19948 19949 // create new Outlayer Items for collection 19950 var items = []; 19951 for ( var i=0; i < itemElems.length; i++ ) { 19952 var elem = itemElems[i]; 19953 var item = new Item( elem, this ); 19954 items.push( item ); 19955 } 19956 19957 return items; 19958}; 19959 19960/** 19961 * get item elements to be used in layout 19962 * @param {Array or NodeList or HTMLElement} elems 19963 * @returns {Array} items - item elements 19964 */ 19965proto._filterFindItemElements = function( elems ) { 19966 return utils.filterFindElements( elems, this.options.itemSelector ); 19967}; 19968 19969/** 19970 * getter method for getting item elements 19971 * @returns {Array} elems - collection of item elements 19972 */ 19973proto.getItemElements = function() { 19974 return this.items.map( function( item ) { 19975 return item.element; 19976 }); 19977}; 19978 19979// ----- init & layout ----- // 19980 19981/** 19982 * lays out all items 19983 */ 19984proto.layout = function() { 19985 this._resetLayout(); 19986 this._manageStamps(); 19987 19988 // don't animate first layout 19989 var layoutInstant = this._getOption('layoutInstant'); 19990 var isInstant = layoutInstant !== undefined ? 19991 layoutInstant : !this._isLayoutInited; 19992 this.layoutItems( this.items, isInstant ); 19993 19994 // flag for initalized 19995 this._isLayoutInited = true; 19996}; 19997 19998// _init is alias for layout 19999proto._init = proto.layout; 20000 20001/** 20002 * logic before any new layout 20003 */ 20004proto._resetLayout = function() { 20005 this.getSize(); 20006}; 20007 20008 20009proto.getSize = function() { 20010 this.size = getSize( this.element ); 20011}; 20012 20013/** 20014 * get measurement from option, for columnWidth, rowHeight, gutter 20015 * if option is String -> get element from selector string, & get size of element 20016 * if option is Element -> get size of element 20017 * else use option as a number 20018 * 20019 * @param {String} measurement 20020 * @param {String} size - width or height 20021 * @private 20022 */ 20023proto._getMeasurement = function( measurement, size ) { 20024 var option = this.options[ measurement ]; 20025 var elem; 20026 if ( !option ) { 20027 // default to 0 20028 this[ measurement ] = 0; 20029 } else { 20030 // use option as an element 20031 if ( typeof option == 'string' ) { 20032 elem = this.element.querySelector( option ); 20033 } else if ( option instanceof HTMLElement ) { 20034 elem = option; 20035 } 20036 // use size of element, if element 20037 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 20038 } 20039}; 20040 20041/** 20042 * layout a collection of item elements 20043 * @api public 20044 */ 20045proto.layoutItems = function( items, isInstant ) { 20046 items = this._getItemsForLayout( items ); 20047 20048 this._layoutItems( items, isInstant ); 20049 20050 this._postLayout(); 20051}; 20052 20053/** 20054 * get the items to be laid out 20055 * you may want to skip over some items 20056 * @param {Array} items 20057 * @returns {Array} items 20058 */ 20059proto._getItemsForLayout = function( items ) { 20060 return items.filter( function( item ) { 20061 return !item.isIgnored; 20062 }); 20063}; 20064 20065/** 20066 * layout items 20067 * @param {Array} items 20068 * @param {Boolean} isInstant 20069 */ 20070proto._layoutItems = function( items, isInstant ) { 20071 this._emitCompleteOnItems( 'layout', items ); 20072 20073 if ( !items || !items.length ) { 20074 // no items, emit event with empty array 20075 return; 20076 } 20077 20078 var queue = []; 20079 20080 items.forEach( function( item ) { 20081 // get x/y object from method 20082 var position = this._getItemLayoutPosition( item ); 20083 // enqueue 20084 position.item = item; 20085 position.isInstant = isInstant || item.isLayoutInstant; 20086 queue.push( position ); 20087 }, this ); 20088 20089 this._processLayoutQueue( queue ); 20090}; 20091 20092/** 20093 * get item layout position 20094 * @param {Outlayer.Item} item 20095 * @returns {Object} x and y position 20096 */ 20097proto._getItemLayoutPosition = function( /* item */ ) { 20098 return { 20099 x: 0, 20100 y: 0 20101 }; 20102}; 20103 20104/** 20105 * iterate over array and position each item 20106 * Reason being - separating this logic prevents 'layout invalidation' 20107 * thx @paul_irish 20108 * @param {Array} queue 20109 */ 20110proto._processLayoutQueue = function( queue ) { 20111 this.updateStagger(); 20112 queue.forEach( function( obj, i ) { 20113 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); 20114 }, this ); 20115}; 20116 20117// set stagger from option in milliseconds number 20118proto.updateStagger = function() { 20119 var stagger = this.options.stagger; 20120 if ( stagger === null || stagger === undefined ) { 20121 this.stagger = 0; 20122 return; 20123 } 20124 this.stagger = getMilliseconds( stagger ); 20125 return this.stagger; 20126}; 20127 20128/** 20129 * Sets position of item in DOM 20130 * @param {Outlayer.Item} item 20131 * @param {Number} x - horizontal position 20132 * @param {Number} y - vertical position 20133 * @param {Boolean} isInstant - disables transitions 20134 */ 20135proto._positionItem = function( item, x, y, isInstant, i ) { 20136 if ( isInstant ) { 20137 // if not transition, just set CSS 20138 item.goTo( x, y ); 20139 } else { 20140 item.stagger( i * this.stagger ); 20141 item.moveTo( x, y ); 20142 } 20143}; 20144 20145/** 20146 * Any logic you want to do after each layout, 20147 * i.e. size the container 20148 */ 20149proto._postLayout = function() { 20150 this.resizeContainer(); 20151}; 20152 20153proto.resizeContainer = function() { 20154 var isResizingContainer = this._getOption('resizeContainer'); 20155 if ( !isResizingContainer ) { 20156 return; 20157 } 20158 var size = this._getContainerSize(); 20159 if ( size ) { 20160 this._setContainerMeasure( size.width, true ); 20161 this._setContainerMeasure( size.height, false ); 20162 } 20163}; 20164 20165/** 20166 * Sets width or height of container if returned 20167 * @returns {Object} size 20168 * @param {Number} width 20169 * @param {Number} height 20170 */ 20171proto._getContainerSize = noop; 20172 20173/** 20174 * @param {Number} measure - size of width or height 20175 * @param {Boolean} isWidth 20176 */ 20177proto._setContainerMeasure = function( measure, isWidth ) { 20178 if ( measure === undefined ) { 20179 return; 20180 } 20181 20182 var elemSize = this.size; 20183 // add padding and border width if border box 20184 if ( elemSize.isBorderBox ) { 20185 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 20186 elemSize.borderLeftWidth + elemSize.borderRightWidth : 20187 elemSize.paddingBottom + elemSize.paddingTop + 20188 elemSize.borderTopWidth + elemSize.borderBottomWidth; 20189 } 20190 20191 measure = Math.max( measure, 0 ); 20192 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 20193}; 20194 20195/** 20196 * emit eventComplete on a collection of items events 20197 * @param {String} eventName 20198 * @param {Array} items - Outlayer.Items 20199 */ 20200proto._emitCompleteOnItems = function( eventName, items ) { 20201 var _this = this; 20202 function onComplete() { 20203 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 20204 } 20205 20206 var count = items.length; 20207 if ( !items || !count ) { 20208 onComplete(); 20209 return; 20210 } 20211 20212 var doneCount = 0; 20213 function tick() { 20214 doneCount++; 20215 if ( doneCount == count ) { 20216 onComplete(); 20217 } 20218 } 20219 20220 // bind callback 20221 items.forEach( function( item ) { 20222 item.once( eventName, tick ); 20223 }); 20224}; 20225 20226/** 20227 * emits events via EvEmitter and jQuery events 20228 * @param {String} type - name of event 20229 * @param {Event} event - original event 20230 * @param {Array} args - extra arguments 20231 */ 20232proto.dispatchEvent = function( type, event, args ) { 20233 // add original event to arguments 20234 var emitArgs = event ? [ event ].concat( args ) : args; 20235 this.emitEvent( type, emitArgs ); 20236 20237 if ( jQuery ) { 20238 // set this.$element 20239 this.$element = this.$element || jQuery( this.element ); 20240 if ( event ) { 20241 // create jQuery event 20242 var $event = jQuery.Event( event ); 20243 $event.type = type; 20244 this.$element.trigger( $event, args ); 20245 } else { 20246 // just trigger with type if no event available 20247 this.$element.trigger( type, args ); 20248 } 20249 } 20250}; 20251 20252// -------------------------- ignore & stamps -------------------------- // 20253 20254 20255/** 20256 * keep item in collection, but do not lay it out 20257 * ignored items do not get skipped in layout 20258 * @param {Element} elem 20259 */ 20260proto.ignore = function( elem ) { 20261 var item = this.getItem( elem ); 20262 if ( item ) { 20263 item.isIgnored = true; 20264 } 20265}; 20266 20267/** 20268 * return item to layout collection 20269 * @param {Element} elem 20270 */ 20271proto.unignore = function( elem ) { 20272 var item = this.getItem( elem ); 20273 if ( item ) { 20274 delete item.isIgnored; 20275 } 20276}; 20277 20278/** 20279 * adds elements to stamps 20280 * @param {NodeList, Array, Element, or String} elems 20281 */ 20282proto.stamp = function( elems ) { 20283 elems = this._find( elems ); 20284 if ( !elems ) { 20285 return; 20286 } 20287 20288 this.stamps = this.stamps.concat( elems ); 20289 // ignore 20290 elems.forEach( this.ignore, this ); 20291}; 20292 20293/** 20294 * removes elements to stamps 20295 * @param {NodeList, Array, or Element} elems 20296 */ 20297proto.unstamp = function( elems ) { 20298 elems = this._find( elems ); 20299 if ( !elems ){ 20300 return; 20301 } 20302 20303 elems.forEach( function( elem ) { 20304 // filter out removed stamp elements 20305 utils.removeFrom( this.stamps, elem ); 20306 this.unignore( elem ); 20307 }, this ); 20308}; 20309 20310/** 20311 * finds child elements 20312 * @param {NodeList, Array, Element, or String} elems 20313 * @returns {Array} elems 20314 */ 20315proto._find = function( elems ) { 20316 if ( !elems ) { 20317 return; 20318 } 20319 // if string, use argument as selector string 20320 if ( typeof elems == 'string' ) { 20321 elems = this.element.querySelectorAll( elems ); 20322 } 20323 elems = utils.makeArray( elems ); 20324 return elems; 20325}; 20326 20327proto._manageStamps = function() { 20328 if ( !this.stamps || !this.stamps.length ) { 20329 return; 20330 } 20331 20332 this._getBoundingRect(); 20333 20334 this.stamps.forEach( this._manageStamp, this ); 20335}; 20336 20337// update boundingLeft / Top 20338proto._getBoundingRect = function() { 20339 // get bounding rect for container element 20340 var boundingRect = this.element.getBoundingClientRect(); 20341 var size = this.size; 20342 this._boundingRect = { 20343 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 20344 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 20345 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 20346 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 20347 }; 20348}; 20349 20350/** 20351 * @param {Element} stamp 20352**/ 20353proto._manageStamp = noop; 20354 20355/** 20356 * get x/y position of element relative to container element 20357 * @param {Element} elem 20358 * @returns {Object} offset - has left, top, right, bottom 20359 */ 20360proto._getElementOffset = function( elem ) { 20361 var boundingRect = elem.getBoundingClientRect(); 20362 var thisRect = this._boundingRect; 20363 var size = getSize( elem ); 20364 var offset = { 20365 left: boundingRect.left - thisRect.left - size.marginLeft, 20366 top: boundingRect.top - thisRect.top - size.marginTop, 20367 right: thisRect.right - boundingRect.right - size.marginRight, 20368 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 20369 }; 20370 return offset; 20371}; 20372 20373// -------------------------- resize -------------------------- // 20374 20375// enable event handlers for listeners 20376// i.e. resize -> onresize 20377proto.handleEvent = utils.handleEvent; 20378 20379/** 20380 * Bind layout to window resizing 20381 */ 20382proto.bindResize = function() { 20383 window.addEventListener( 'resize', this ); 20384 this.isResizeBound = true; 20385}; 20386 20387/** 20388 * Unbind layout to window resizing 20389 */ 20390proto.unbindResize = function() { 20391 window.removeEventListener( 'resize', this ); 20392 this.isResizeBound = false; 20393}; 20394 20395proto.onresize = function() { 20396 this.resize(); 20397}; 20398 20399utils.debounceMethod( Outlayer, 'onresize', 100 ); 20400 20401proto.resize = function() { 20402 // don't trigger if size did not change 20403 // or if resize was unbound. See #9 20404 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 20405 return; 20406 } 20407 20408 this.layout(); 20409}; 20410 20411/** 20412 * check if layout is needed post layout 20413 * @returns Boolean 20414 */ 20415proto.needsResizeLayout = function() { 20416 var size = getSize( this.element ); 20417 // check that this.size and size are there 20418 // IE8 triggers resize on body size change, so they might not be 20419 var hasSizes = this.size && size; 20420 return hasSizes && size.innerWidth !== this.size.innerWidth; 20421}; 20422 20423// -------------------------- methods -------------------------- // 20424 20425/** 20426 * add items to Outlayer instance 20427 * @param {Array or NodeList or Element} elems 20428 * @returns {Array} items - Outlayer.Items 20429**/ 20430proto.addItems = function( elems ) { 20431 var items = this._itemize( elems ); 20432 // add items to collection 20433 if ( items.length ) { 20434 this.items = this.items.concat( items ); 20435 } 20436 return items; 20437}; 20438 20439/** 20440 * Layout newly-appended item elements 20441 * @param {Array or NodeList or Element} elems 20442 */ 20443proto.appended = function( elems ) { 20444 var items = this.addItems( elems ); 20445 if ( !items.length ) { 20446 return; 20447 } 20448 // layout and reveal just the new items 20449 this.layoutItems( items, true ); 20450 this.reveal( items ); 20451}; 20452 20453/** 20454 * Layout prepended elements 20455 * @param {Array or NodeList or Element} elems 20456 */ 20457proto.prepended = function( elems ) { 20458 var items = this._itemize( elems ); 20459 if ( !items.length ) { 20460 return; 20461 } 20462 // add items to beginning of collection 20463 var previousItems = this.items.slice(0); 20464 this.items = items.concat( previousItems ); 20465 // start new layout 20466 this._resetLayout(); 20467 this._manageStamps(); 20468 // layout new stuff without transition 20469 this.layoutItems( items, true ); 20470 this.reveal( items ); 20471 // layout previous items 20472 this.layoutItems( previousItems ); 20473}; 20474 20475/** 20476 * reveal a collection of items 20477 * @param {Array of Outlayer.Items} items 20478 */ 20479proto.reveal = function( items ) { 20480 this._emitCompleteOnItems( 'reveal', items ); 20481 if ( !items || !items.length ) { 20482 return; 20483 } 20484 var stagger = this.updateStagger(); 20485 items.forEach( function( item, i ) { 20486 item.stagger( i * stagger ); 20487 item.reveal(); 20488 }); 20489}; 20490 20491/** 20492 * hide a collection of items 20493 * @param {Array of Outlayer.Items} items 20494 */ 20495proto.hide = function( items ) { 20496 this._emitCompleteOnItems( 'hide', items ); 20497 if ( !items || !items.length ) { 20498 return; 20499 } 20500 var stagger = this.updateStagger(); 20501 items.forEach( function( item, i ) { 20502 item.stagger( i * stagger ); 20503 item.hide(); 20504 }); 20505}; 20506 20507/** 20508 * reveal item elements 20509 * @param {Array}, {Element}, {NodeList} items 20510 */ 20511proto.revealItemElements = function( elems ) { 20512 var items = this.getItems( elems ); 20513 this.reveal( items ); 20514}; 20515 20516/** 20517 * hide item elements 20518 * @param {Array}, {Element}, {NodeList} items 20519 */ 20520proto.hideItemElements = function( elems ) { 20521 var items = this.getItems( elems ); 20522 this.hide( items ); 20523}; 20524 20525/** 20526 * get Outlayer.Item, given an Element 20527 * @param {Element} elem 20528 * @param {Function} callback 20529 * @returns {Outlayer.Item} item 20530 */ 20531proto.getItem = function( elem ) { 20532 // loop through items to get the one that matches 20533 for ( var i=0; i < this.items.length; i++ ) { 20534 var item = this.items[i]; 20535 if ( item.element == elem ) { 20536 // return item 20537 return item; 20538 } 20539 } 20540}; 20541 20542/** 20543 * get collection of Outlayer.Items, given Elements 20544 * @param {Array} elems 20545 * @returns {Array} items - Outlayer.Items 20546 */ 20547proto.getItems = function( elems ) { 20548 elems = utils.makeArray( elems ); 20549 var items = []; 20550 elems.forEach( function( elem ) { 20551 var item = this.getItem( elem ); 20552 if ( item ) { 20553 items.push( item ); 20554 } 20555 }, this ); 20556 20557 return items; 20558}; 20559 20560/** 20561 * remove element(s) from instance and DOM 20562 * @param {Array or NodeList or Element} elems 20563 */ 20564proto.remove = function( elems ) { 20565 var removeItems = this.getItems( elems ); 20566 20567 this._emitCompleteOnItems( 'remove', removeItems ); 20568 20569 // bail if no items to remove 20570 if ( !removeItems || !removeItems.length ) { 20571 return; 20572 } 20573 20574 removeItems.forEach( function( item ) { 20575 item.remove(); 20576 // remove item from collection 20577 utils.removeFrom( this.items, item ); 20578 }, this ); 20579}; 20580 20581// ----- destroy ----- // 20582 20583// remove and disable Outlayer instance 20584proto.destroy = function() { 20585 // clean up dynamic styles 20586 var style = this.element.style; 20587 style.height = ''; 20588 style.position = ''; 20589 style.width = ''; 20590 // destroy items 20591 this.items.forEach( function( item ) { 20592 item.destroy(); 20593 }); 20594 20595 this.unbindResize(); 20596 20597 var id = this.element.outlayerGUID; 20598 delete instances[ id ]; // remove reference to instance by id 20599 delete this.element.outlayerGUID; 20600 // remove data for jQuery 20601 if ( jQuery ) { 20602 jQuery.removeData( this.element, this.constructor.namespace ); 20603 } 20604 20605}; 20606 20607// -------------------------- data -------------------------- // 20608 20609/** 20610 * get Outlayer instance from element 20611 * @param {Element} elem 20612 * @returns {Outlayer} 20613 */ 20614Outlayer.data = function( elem ) { 20615 elem = utils.getQueryElement( elem ); 20616 var id = elem && elem.outlayerGUID; 20617 return id && instances[ id ]; 20618}; 20619 20620 20621// -------------------------- create Outlayer class -------------------------- // 20622 20623/** 20624 * create a layout class 20625 * @param {String} namespace 20626 */ 20627Outlayer.create = function( namespace, options ) { 20628 // sub-class Outlayer 20629 var Layout = subclass( Outlayer ); 20630 // apply new options and compatOptions 20631 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 20632 utils.extend( Layout.defaults, options ); 20633 Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); 20634 20635 Layout.namespace = namespace; 20636 20637 Layout.data = Outlayer.data; 20638 20639 // sub-class Item 20640 Layout.Item = subclass( Item ); 20641 20642 // -------------------------- declarative -------------------------- // 20643 20644 utils.htmlInit( Layout, namespace ); 20645 20646 // -------------------------- jQuery bridge -------------------------- // 20647 20648 // make into jQuery plugin 20649 if ( jQuery && jQuery.bridget ) { 20650 jQuery.bridget( namespace, Layout ); 20651 } 20652 20653 return Layout; 20654}; 20655 20656function subclass( Parent ) { 20657 function SubClass() { 20658 Parent.apply( this, arguments ); 20659 } 20660 20661 SubClass.prototype = Object.create( Parent.prototype ); 20662 SubClass.prototype.constructor = SubClass; 20663 20664 return SubClass; 20665} 20666 20667// ----- helpers ----- // 20668 20669// how many milliseconds are in each unit 20670var msUnits = { 20671 ms: 1, 20672 s: 1000 20673}; 20674 20675// munge time-like parameter into millisecond number 20676// '0.4s' -> 40 20677function getMilliseconds( time ) { 20678 if ( typeof time == 'number' ) { 20679 return time; 20680 } 20681 var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); 20682 var num = matches && matches[1]; 20683 var unit = matches && matches[2]; 20684 if ( !num.length ) { 20685 return 0; 20686 } 20687 num = parseFloat( num ); 20688 var mult = msUnits[ unit ] || 1; 20689 return num * mult; 20690} 20691 20692// ----- fin ----- // 20693 20694// back in global 20695Outlayer.Item = Item; 20696 20697return Outlayer; 20698 20699})); 20700 20701/** 20702 * Isotope Item 20703**/ 20704 20705( function( window, factory ) { 20706 // universal module definition 20707 /* jshint strict: false */ /*globals define, module, require */ 20708 if ( typeof define == 'function' && define.amd ) { 20709 // AMD 20710 define( 'isotope-layout/js/item',[ 20711 'outlayer/outlayer' 20712 ], 20713 factory ); 20714 } else if ( typeof module == 'object' && module.exports ) { 20715 // CommonJS 20716 module.exports = factory( 20717 require('outlayer') 20718 ); 20719 } else { 20720 // browser global 20721 window.Isotope = window.Isotope || {}; 20722 window.Isotope.Item = factory( 20723 window.Outlayer 20724 ); 20725 } 20726 20727}( window, function factory( Outlayer ) { 20728'use strict'; 20729 20730// -------------------------- Item -------------------------- // 20731 20732// sub-class Outlayer Item 20733function Item() { 20734 Outlayer.Item.apply( this, arguments ); 20735} 20736 20737var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 20738 20739var _create = proto._create; 20740proto._create = function() { 20741 // assign id, used for original-order sorting 20742 this.id = this.layout.itemGUID++; 20743 _create.call( this ); 20744 this.sortData = {}; 20745}; 20746 20747proto.updateSortData = function() { 20748 if ( this.isIgnored ) { 20749 return; 20750 } 20751 // default sorters 20752 this.sortData.id = this.id; 20753 // for backward compatibility 20754 this.sortData['original-order'] = this.id; 20755 this.sortData.random = Math.random(); 20756 // go thru getSortData obj and apply the sorters 20757 var getSortData = this.layout.options.getSortData; 20758 var sorters = this.layout._sorters; 20759 for ( var key in getSortData ) { 20760 var sorter = sorters[ key ]; 20761 this.sortData[ key ] = sorter( this.element, this ); 20762 } 20763}; 20764 20765var _destroy = proto.destroy; 20766proto.destroy = function() { 20767 // call super 20768 _destroy.apply( this, arguments ); 20769 // reset display, #741 20770 this.css({ 20771 display: '' 20772 }); 20773}; 20774 20775return Item; 20776 20777})); 20778 20779/** 20780 * Isotope LayoutMode 20781 */ 20782 20783( function( window, factory ) { 20784 // universal module definition 20785 /* jshint strict: false */ /*globals define, module, require */ 20786 if ( typeof define == 'function' && define.amd ) { 20787 // AMD 20788 define( 'isotope-layout/js/layout-mode',[ 20789 'get-size/get-size', 20790 'outlayer/outlayer' 20791 ], 20792 factory ); 20793 } else if ( typeof module == 'object' && module.exports ) { 20794 // CommonJS 20795 module.exports = factory( 20796 require('get-size'), 20797 require('outlayer') 20798 ); 20799 } else { 20800 // browser global 20801 window.Isotope = window.Isotope || {}; 20802 window.Isotope.LayoutMode = factory( 20803 window.getSize, 20804 window.Outlayer 20805 ); 20806 } 20807 20808}( window, function factory( getSize, Outlayer ) { 20809 'use strict'; 20810 20811 // layout mode class 20812 function LayoutMode( isotope ) { 20813 this.isotope = isotope; 20814 // link properties 20815 if ( isotope ) { 20816 this.options = isotope.options[ this.namespace ]; 20817 this.element = isotope.element; 20818 this.items = isotope.filteredItems; 20819 this.size = isotope.size; 20820 } 20821 } 20822 20823 var proto = LayoutMode.prototype; 20824 20825 /** 20826 * some methods should just defer to default Outlayer method 20827 * and reference the Isotope instance as `this` 20828 **/ 20829 var facadeMethods = [ 20830 '_resetLayout', 20831 '_getItemLayoutPosition', 20832 '_manageStamp', 20833 '_getContainerSize', 20834 '_getElementOffset', 20835 'needsResizeLayout', 20836 '_getOption' 20837 ]; 20838 20839 facadeMethods.forEach( function( methodName ) { 20840 proto[ methodName ] = function() { 20841 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 20842 }; 20843 }); 20844 20845 // ----- ----- // 20846 20847 // for horizontal layout modes, check vertical size 20848 proto.needsVerticalResizeLayout = function() { 20849 // don't trigger if size did not change 20850 var size = getSize( this.isotope.element ); 20851 // check that this.size and size are there 20852 // IE8 triggers resize on body size change, so they might not be 20853 var hasSizes = this.isotope.size && size; 20854 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 20855 }; 20856 20857 // ----- measurements ----- // 20858 20859 proto._getMeasurement = function() { 20860 this.isotope._getMeasurement.apply( this, arguments ); 20861 }; 20862 20863 proto.getColumnWidth = function() { 20864 this.getSegmentSize( 'column', 'Width' ); 20865 }; 20866 20867 proto.getRowHeight = function() { 20868 this.getSegmentSize( 'row', 'Height' ); 20869 }; 20870 20871 /** 20872 * get columnWidth or rowHeight 20873 * segment: 'column' or 'row' 20874 * size 'Width' or 'Height' 20875 **/ 20876 proto.getSegmentSize = function( segment, size ) { 20877 var segmentName = segment + size; 20878 var outerSize = 'outer' + size; 20879 // columnWidth / outerWidth // rowHeight / outerHeight 20880 this._getMeasurement( segmentName, outerSize ); 20881 // got rowHeight or columnWidth, we can chill 20882 if ( this[ segmentName ] ) { 20883 return; 20884 } 20885 // fall back to item of first element 20886 var firstItemSize = this.getFirstItemSize(); 20887 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 20888 // or size of container 20889 this.isotope.size[ 'inner' + size ]; 20890 }; 20891 20892 proto.getFirstItemSize = function() { 20893 var firstItem = this.isotope.filteredItems[0]; 20894 return firstItem && firstItem.element && getSize( firstItem.element ); 20895 }; 20896 20897 // ----- methods that should reference isotope ----- // 20898 20899 proto.layout = function() { 20900 this.isotope.layout.apply( this.isotope, arguments ); 20901 }; 20902 20903 proto.getSize = function() { 20904 this.isotope.getSize(); 20905 this.size = this.isotope.size; 20906 }; 20907 20908 // -------------------------- create -------------------------- // 20909 20910 LayoutMode.modes = {}; 20911 20912 LayoutMode.create = function( namespace, options ) { 20913 20914 function Mode() { 20915 LayoutMode.apply( this, arguments ); 20916 } 20917 20918 Mode.prototype = Object.create( proto ); 20919 Mode.prototype.constructor = Mode; 20920 20921 // default options 20922 if ( options ) { 20923 Mode.options = options; 20924 } 20925 20926 Mode.prototype.namespace = namespace; 20927 // register in Isotope 20928 LayoutMode.modes[ namespace ] = Mode; 20929 20930 return Mode; 20931 }; 20932 20933 return LayoutMode; 20934 20935})); 20936 20937/*! 20938 * Masonry v4.2.1 20939 * Cascading grid layout library 20940 * https://masonry.desandro.com 20941 * MIT License 20942 * by David DeSandro 20943 */ 20944 20945( function( window, factory ) { 20946 // universal module definition 20947 /* jshint strict: false */ /*globals define, module, require */ 20948 if ( typeof define == 'function' && define.amd ) { 20949 // AMD 20950 define( 'masonry-layout/masonry',[ 20951 'outlayer/outlayer', 20952 'get-size/get-size' 20953 ], 20954 factory ); 20955 } else if ( typeof module == 'object' && module.exports ) { 20956 // CommonJS 20957 module.exports = factory( 20958 require('outlayer'), 20959 require('get-size') 20960 ); 20961 } else { 20962 // browser global 20963 window.Masonry = factory( 20964 window.Outlayer, 20965 window.getSize 20966 ); 20967 } 20968 20969}( window, function factory( Outlayer, getSize ) { 20970 20971 20972 20973// -------------------------- masonryDefinition -------------------------- // 20974 20975 // create an Outlayer layout class 20976 var Masonry = Outlayer.create('masonry'); 20977 // isFitWidth -> fitWidth 20978 Masonry.compatOptions.fitWidth = 'isFitWidth'; 20979 20980 var proto = Masonry.prototype; 20981 20982 proto._resetLayout = function() { 20983 this.getSize(); 20984 this._getMeasurement( 'columnWidth', 'outerWidth' ); 20985 this._getMeasurement( 'gutter', 'outerWidth' ); 20986 this.measureColumns(); 20987 20988 // reset column Y 20989 this.colYs = []; 20990 for ( var i=0; i < this.cols; i++ ) { 20991 this.colYs.push( 0 ); 20992 } 20993 20994 this.maxY = 0; 20995 this.horizontalColIndex = 0; 20996 }; 20997 20998 proto.measureColumns = function() { 20999 this.getContainerWidth(); 21000 // if columnWidth is 0, default to outerWidth of first item 21001 if ( !this.columnWidth ) { 21002 var firstItem = this.items[0]; 21003 var firstItemElem = firstItem && firstItem.element; 21004 // columnWidth fall back to item of first element 21005 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 21006 // if first elem has no width, default to size of container 21007 this.containerWidth; 21008 } 21009 21010 var columnWidth = this.columnWidth += this.gutter; 21011 21012 // calculate columns 21013 var containerWidth = this.containerWidth + this.gutter; 21014 var cols = containerWidth / columnWidth; 21015 // fix rounding errors, typically with gutters 21016 var excess = columnWidth - containerWidth % columnWidth; 21017 // if overshoot is less than a pixel, round up, otherwise floor it 21018 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 21019 cols = Math[ mathMethod ]( cols ); 21020 this.cols = Math.max( cols, 1 ); 21021 }; 21022 21023 proto.getContainerWidth = function() { 21024 // container is parent if fit width 21025 var isFitWidth = this._getOption('fitWidth'); 21026 var container = isFitWidth ? this.element.parentNode : this.element; 21027 // check that this.size and size are there 21028 // IE8 triggers resize on body size change, so they might not be 21029 var size = getSize( container ); 21030 this.containerWidth = size && size.innerWidth; 21031 }; 21032 21033 proto._getItemLayoutPosition = function( item ) { 21034 item.getSize(); 21035 // how many columns does this brick span 21036 var remainder = item.size.outerWidth % this.columnWidth; 21037 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 21038 // round if off by 1 pixel, otherwise use ceil 21039 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 21040 colSpan = Math.min( colSpan, this.cols ); 21041 // use horizontal or top column position 21042 var colPosMethod = this.options.horizontalOrder ? 21043 '_getHorizontalColPosition' : '_getTopColPosition'; 21044 var colPosition = this[ colPosMethod ]( colSpan, item ); 21045 // position the brick 21046 var position = { 21047 x: this.columnWidth * colPosition.col, 21048 y: colPosition.y 21049 }; 21050 // apply setHeight to necessary columns 21051 var setHeight = colPosition.y + item.size.outerHeight; 21052 var setMax = colSpan + colPosition.col; 21053 for ( var i = colPosition.col; i < setMax; i++ ) { 21054 this.colYs[i] = setHeight; 21055 } 21056 21057 return position; 21058 }; 21059 21060 proto._getTopColPosition = function( colSpan ) { 21061 var colGroup = this._getTopColGroup( colSpan ); 21062 // get the minimum Y value from the columns 21063 var minimumY = Math.min.apply( Math, colGroup ); 21064 21065 return { 21066 col: colGroup.indexOf( minimumY ), 21067 y: minimumY, 21068 }; 21069 }; 21070 21071 /** 21072 * @param {Number} colSpan - number of columns the element spans 21073 * @returns {Array} colGroup 21074 */ 21075 proto._getTopColGroup = function( colSpan ) { 21076 if ( colSpan < 2 ) { 21077 // if brick spans only one column, use all the column Ys 21078 return this.colYs; 21079 } 21080 21081 var colGroup = []; 21082 // how many different places could this brick fit horizontally 21083 var groupCount = this.cols + 1 - colSpan; 21084 // for each group potential horizontal position 21085 for ( var i = 0; i < groupCount; i++ ) { 21086 colGroup[i] = this._getColGroupY( i, colSpan ); 21087 } 21088 return colGroup; 21089 }; 21090 21091 proto._getColGroupY = function( col, colSpan ) { 21092 if ( colSpan < 2 ) { 21093 return this.colYs[ col ]; 21094 } 21095 // make an array of colY values for that one group 21096 var groupColYs = this.colYs.slice( col, col + colSpan ); 21097 // and get the max value of the array 21098 return Math.max.apply( Math, groupColYs ); 21099 }; 21100 21101 // get column position based on horizontal index. #873 21102 proto._getHorizontalColPosition = function( colSpan, item ) { 21103 var col = this.horizontalColIndex % this.cols; 21104 var isOver = colSpan > 1 && col + colSpan > this.cols; 21105 // shift to next row if item can't fit on current row 21106 col = isOver ? 0 : col; 21107 // don't let zero-size items take up space 21108 var hasSize = item.size.outerWidth && item.size.outerHeight; 21109 this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex; 21110 21111 return { 21112 col: col, 21113 y: this._getColGroupY( col, colSpan ), 21114 }; 21115 }; 21116 21117 proto._manageStamp = function( stamp ) { 21118 var stampSize = getSize( stamp ); 21119 var offset = this._getElementOffset( stamp ); 21120 // get the columns that this stamp affects 21121 var isOriginLeft = this._getOption('originLeft'); 21122 var firstX = isOriginLeft ? offset.left : offset.right; 21123 var lastX = firstX + stampSize.outerWidth; 21124 var firstCol = Math.floor( firstX / this.columnWidth ); 21125 firstCol = Math.max( 0, firstCol ); 21126 var lastCol = Math.floor( lastX / this.columnWidth ); 21127 // lastCol should not go over if multiple of columnWidth #425 21128 lastCol -= lastX % this.columnWidth ? 0 : 1; 21129 lastCol = Math.min( this.cols - 1, lastCol ); 21130 // set colYs to bottom of the stamp 21131 21132 var isOriginTop = this._getOption('originTop'); 21133 var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + 21134 stampSize.outerHeight; 21135 for ( var i = firstCol; i <= lastCol; i++ ) { 21136 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 21137 } 21138 }; 21139 21140 proto._getContainerSize = function() { 21141 this.maxY = Math.max.apply( Math, this.colYs ); 21142 var size = { 21143 height: this.maxY 21144 }; 21145 21146 if ( this._getOption('fitWidth') ) { 21147 size.width = this._getContainerFitWidth(); 21148 } 21149 21150 return size; 21151 }; 21152 21153 proto._getContainerFitWidth = function() { 21154 var unusedCols = 0; 21155 // count unused columns 21156 var i = this.cols; 21157 while ( --i ) { 21158 if ( this.colYs[i] !== 0 ) { 21159 break; 21160 } 21161 unusedCols++; 21162 } 21163 // fit container to columns that have been used 21164 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 21165 }; 21166 21167 proto.needsResizeLayout = function() { 21168 var previousWidth = this.containerWidth; 21169 this.getContainerWidth(); 21170 return previousWidth != this.containerWidth; 21171 }; 21172 21173 return Masonry; 21174 21175})); 21176 21177/*! 21178 * Masonry layout mode 21179 * sub-classes Masonry 21180 * https://masonry.desandro.com 21181 */ 21182 21183( function( window, factory ) { 21184 // universal module definition 21185 /* jshint strict: false */ /*globals define, module, require */ 21186 if ( typeof define == 'function' && define.amd ) { 21187 // AMD 21188 define( 'isotope-layout/js/layout-modes/masonry',[ 21189 '../layout-mode', 21190 'masonry-layout/masonry' 21191 ], 21192 factory ); 21193 } else if ( typeof module == 'object' && module.exports ) { 21194 // CommonJS 21195 module.exports = factory( 21196 require('../layout-mode'), 21197 require('masonry-layout') 21198 ); 21199 } else { 21200 // browser global 21201 factory( 21202 window.Isotope.LayoutMode, 21203 window.Masonry 21204 ); 21205 } 21206 21207}( window, function factory( LayoutMode, Masonry ) { 21208'use strict'; 21209 21210// -------------------------- masonryDefinition -------------------------- // 21211 21212 // create an Outlayer layout class 21213 var MasonryMode = LayoutMode.create('masonry'); 21214 21215 var proto = MasonryMode.prototype; 21216 21217 var keepModeMethods = { 21218 _getElementOffset: true, 21219 layout: true, 21220 _getMeasurement: true 21221 }; 21222 21223 // inherit Masonry prototype 21224 for ( var method in Masonry.prototype ) { 21225 // do not inherit mode methods 21226 if ( !keepModeMethods[ method ] ) { 21227 proto[ method ] = Masonry.prototype[ method ]; 21228 } 21229 } 21230 21231 var measureColumns = proto.measureColumns; 21232 proto.measureColumns = function() { 21233 // set items, used if measuring first item 21234 this.items = this.isotope.filteredItems; 21235 measureColumns.call( this ); 21236 }; 21237 21238 // point to mode options for fitWidth 21239 var _getOption = proto._getOption; 21240 proto._getOption = function( option ) { 21241 if ( option == 'fitWidth' ) { 21242 return this.options.isFitWidth !== undefined ? 21243 this.options.isFitWidth : this.options.fitWidth; 21244 } 21245 return _getOption.apply( this.isotope, arguments ); 21246 }; 21247 21248 return MasonryMode; 21249 21250})); 21251 21252/** 21253 * fitRows layout mode 21254 */ 21255 21256( function( window, factory ) { 21257 // universal module definition 21258 /* jshint strict: false */ /*globals define, module, require */ 21259 if ( typeof define == 'function' && define.amd ) { 21260 // AMD 21261 define( 'isotope-layout/js/layout-modes/fit-rows',[ 21262 '../layout-mode' 21263 ], 21264 factory ); 21265 } else if ( typeof exports == 'object' ) { 21266 // CommonJS 21267 module.exports = factory( 21268 require('../layout-mode') 21269 ); 21270 } else { 21271 // browser global 21272 factory( 21273 window.Isotope.LayoutMode 21274 ); 21275 } 21276 21277}( window, function factory( LayoutMode ) { 21278'use strict'; 21279 21280var FitRows = LayoutMode.create('fitRows'); 21281 21282var proto = FitRows.prototype; 21283 21284proto._resetLayout = function() { 21285 this.x = 0; 21286 this.y = 0; 21287 this.maxY = 0; 21288 this._getMeasurement( 'gutter', 'outerWidth' ); 21289}; 21290 21291proto._getItemLayoutPosition = function( item ) { 21292 item.getSize(); 21293 21294 var itemWidth = item.size.outerWidth + this.gutter; 21295 // if this element cannot fit in the current row 21296 var containerWidth = this.isotope.size.innerWidth + this.gutter; 21297 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 21298 this.x = 0; 21299 this.y = this.maxY; 21300 } 21301 21302 var position = { 21303 x: this.x, 21304 y: this.y 21305 }; 21306 21307 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 21308 this.x += itemWidth; 21309 21310 return position; 21311}; 21312 21313proto._getContainerSize = function() { 21314 return { height: this.maxY }; 21315}; 21316 21317return FitRows; 21318 21319})); 21320 21321/** 21322 * vertical layout mode 21323 */ 21324 21325( function( window, factory ) { 21326 // universal module definition 21327 /* jshint strict: false */ /*globals define, module, require */ 21328 if ( typeof define == 'function' && define.amd ) { 21329 // AMD 21330 define( 'isotope-layout/js/layout-modes/vertical',[ 21331 '../layout-mode' 21332 ], 21333 factory ); 21334 } else if ( typeof module == 'object' && module.exports ) { 21335 // CommonJS 21336 module.exports = factory( 21337 require('../layout-mode') 21338 ); 21339 } else { 21340 // browser global 21341 factory( 21342 window.Isotope.LayoutMode 21343 ); 21344 } 21345 21346}( window, function factory( LayoutMode ) { 21347'use strict'; 21348 21349var Vertical = LayoutMode.create( 'vertical', { 21350 horizontalAlignment: 0 21351}); 21352 21353var proto = Vertical.prototype; 21354 21355proto._resetLayout = function() { 21356 this.y = 0; 21357}; 21358 21359proto._getItemLayoutPosition = function( item ) { 21360 item.getSize(); 21361 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 21362 this.options.horizontalAlignment; 21363 var y = this.y; 21364 this.y += item.size.outerHeight; 21365 return { x: x, y: y }; 21366}; 21367 21368proto._getContainerSize = function() { 21369 return { height: this.y }; 21370}; 21371 21372return Vertical; 21373 21374})); 21375 21376/*! 21377 * Isotope v3.0.6 21378 * 21379 * Licensed GPLv3 for open source use 21380 * or Isotope Commercial License for commercial use 21381 * 21382 * https://isotope.metafizzy.co 21383 * Copyright 2010-2018 Metafizzy 21384 */ 21385 21386( function( window, factory ) { 21387 // universal module definition 21388 /* jshint strict: false */ /*globals define, module, require */ 21389 if ( typeof define == 'function' && define.amd ) { 21390 // AMD 21391 define( [ 21392 'outlayer/outlayer', 21393 'get-size/get-size', 21394 'desandro-matches-selector/matches-selector', 21395 'fizzy-ui-utils/utils', 21396 'isotope-layout/js/item', 21397 'isotope-layout/js/layout-mode', 21398 // include default layout modes 21399 'isotope-layout/js/layout-modes/masonry', 21400 'isotope-layout/js/layout-modes/fit-rows', 21401 'isotope-layout/js/layout-modes/vertical' 21402 ], 21403 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 21404 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 21405 }); 21406 } else if ( typeof module == 'object' && module.exports ) { 21407 // CommonJS 21408 module.exports = factory( 21409 window, 21410 require('outlayer'), 21411 require('get-size'), 21412 require('desandro-matches-selector'), 21413 require('fizzy-ui-utils'), 21414 require('isotope-layout/js/item'), 21415 require('isotope-layout/js/layout-mode'), 21416 // include default layout modes 21417 require('isotope-layout/js/layout-modes/masonry'), 21418 require('isotope-layout/js/layout-modes/fit-rows'), 21419 require('isotope-layout/js/layout-modes/vertical') 21420 ); 21421 } else { 21422 // browser global 21423 window.Isotope = factory( 21424 window, 21425 window.Outlayer, 21426 window.getSize, 21427 window.matchesSelector, 21428 window.fizzyUIUtils, 21429 window.Isotope.Item, 21430 window.Isotope.LayoutMode 21431 ); 21432 } 21433 21434}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 21435 Item, LayoutMode ) { 21436 21437 21438 21439// -------------------------- vars -------------------------- // 21440 21441var jQuery = window.jQuery; 21442 21443// -------------------------- helpers -------------------------- // 21444 21445var trim = String.prototype.trim ? 21446 function( str ) { 21447 return str.trim(); 21448 } : 21449 function( str ) { 21450 return str.replace( /^\s+|\s+$/g, '' ); 21451 }; 21452 21453// -------------------------- isotopeDefinition -------------------------- // 21454 21455 // create an Outlayer layout class 21456 var Isotope = Outlayer.create( 'isotope', { 21457 layoutMode: 'masonry', 21458 isJQueryFiltering: true, 21459 sortAscending: true 21460 }); 21461 21462 Isotope.Item = Item; 21463 Isotope.LayoutMode = LayoutMode; 21464 21465 var proto = Isotope.prototype; 21466 21467 proto._create = function() { 21468 this.itemGUID = 0; 21469 // functions that sort items 21470 this._sorters = {}; 21471 this._getSorters(); 21472 // call super 21473 Outlayer.prototype._create.call( this ); 21474 21475 // create layout modes 21476 this.modes = {}; 21477 // start filteredItems with all items 21478 this.filteredItems = this.items; 21479 // keep of track of sortBys 21480 this.sortHistory = [ 'original-order' ]; 21481 // create from registered layout modes 21482 for ( var name in LayoutMode.modes ) { 21483 this._initLayoutMode( name ); 21484 } 21485 }; 21486 21487 proto.reloadItems = function() { 21488 // reset item ID counter 21489 this.itemGUID = 0; 21490 // call super 21491 Outlayer.prototype.reloadItems.call( this ); 21492 }; 21493 21494 proto._itemize = function() { 21495 var items = Outlayer.prototype._itemize.apply( this, arguments ); 21496 // assign ID for original-order 21497 for ( var i=0; i < items.length; i++ ) { 21498 var item = items[i]; 21499 item.id = this.itemGUID++; 21500 } 21501 this._updateItemsSortData( items ); 21502 return items; 21503 }; 21504 21505 21506 // -------------------------- layout -------------------------- // 21507 21508 proto._initLayoutMode = function( name ) { 21509 var Mode = LayoutMode.modes[ name ]; 21510 // set mode options 21511 // HACK extend initial options, back-fill in default options 21512 var initialOpts = this.options[ name ] || {}; 21513 this.options[ name ] = Mode.options ? 21514 utils.extend( Mode.options, initialOpts ) : initialOpts; 21515 // init layout mode instance 21516 this.modes[ name ] = new Mode( this ); 21517 }; 21518 21519 21520 proto.layout = function() { 21521 // if first time doing layout, do all magic 21522 if ( !this._isLayoutInited && this._getOption('initLayout') ) { 21523 this.arrange(); 21524 return; 21525 } 21526 this._layout(); 21527 }; 21528 21529 // private method to be used in layout() & magic() 21530 proto._layout = function() { 21531 // don't animate first layout 21532 var isInstant = this._getIsInstant(); 21533 // layout flow 21534 this._resetLayout(); 21535 this._manageStamps(); 21536 this.layoutItems( this.filteredItems, isInstant ); 21537 21538 // flag for initalized 21539 this._isLayoutInited = true; 21540 }; 21541 21542 // filter + sort + layout 21543 proto.arrange = function( opts ) { 21544 // set any options pass 21545 this.option( opts ); 21546 this._getIsInstant(); 21547 // filter, sort, and layout 21548 21549 // filter 21550 var filtered = this._filter( this.items ); 21551 this.filteredItems = filtered.matches; 21552 21553 this._bindArrangeComplete(); 21554 21555 if ( this._isInstant ) { 21556 this._noTransition( this._hideReveal, [ filtered ] ); 21557 } else { 21558 this._hideReveal( filtered ); 21559 } 21560 21561 this._sort(); 21562 this._layout(); 21563 }; 21564 // alias to _init for main plugin method 21565 proto._init = proto.arrange; 21566 21567 proto._hideReveal = function( filtered ) { 21568 this.reveal( filtered.needReveal ); 21569 this.hide( filtered.needHide ); 21570 }; 21571 21572 // HACK 21573 // Don't animate/transition first layout 21574 // Or don't animate/transition other layouts 21575 proto._getIsInstant = function() { 21576 var isLayoutInstant = this._getOption('layoutInstant'); 21577 var isInstant = isLayoutInstant !== undefined ? isLayoutInstant : 21578 !this._isLayoutInited; 21579 this._isInstant = isInstant; 21580 return isInstant; 21581 }; 21582 21583 // listen for layoutComplete, hideComplete and revealComplete 21584 // to trigger arrangeComplete 21585 proto._bindArrangeComplete = function() { 21586 // listen for 3 events to trigger arrangeComplete 21587 var isLayoutComplete, isHideComplete, isRevealComplete; 21588 var _this = this; 21589 function arrangeParallelCallback() { 21590 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 21591 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 21592 } 21593 } 21594 this.once( 'layoutComplete', function() { 21595 isLayoutComplete = true; 21596 arrangeParallelCallback(); 21597 }); 21598 this.once( 'hideComplete', function() { 21599 isHideComplete = true; 21600 arrangeParallelCallback(); 21601 }); 21602 this.once( 'revealComplete', function() { 21603 isRevealComplete = true; 21604 arrangeParallelCallback(); 21605 }); 21606 }; 21607 21608 // -------------------------- filter -------------------------- // 21609 21610 proto._filter = function( items ) { 21611 var filter = this.options.filter; 21612 filter = filter || '*'; 21613 var matches = []; 21614 var hiddenMatched = []; 21615 var visibleUnmatched = []; 21616 21617 var test = this._getFilterTest( filter ); 21618 21619 // test each item 21620 for ( var i=0; i < items.length; i++ ) { 21621 var item = items[i]; 21622 if ( item.isIgnored ) { 21623 continue; 21624 } 21625 // add item to either matched or unmatched group 21626 var isMatched = test( item ); 21627 // item.isFilterMatched = isMatched; 21628 // add to matches if its a match 21629 if ( isMatched ) { 21630 matches.push( item ); 21631 } 21632 // add to additional group if item needs to be hidden or revealed 21633 if ( isMatched && item.isHidden ) { 21634 hiddenMatched.push( item ); 21635 } else if ( !isMatched && !item.isHidden ) { 21636 visibleUnmatched.push( item ); 21637 } 21638 } 21639 21640 // return collections of items to be manipulated 21641 return { 21642 matches: matches, 21643 needReveal: hiddenMatched, 21644 needHide: visibleUnmatched 21645 }; 21646 }; 21647 21648 // get a jQuery, function, or a matchesSelector test given the filter 21649 proto._getFilterTest = function( filter ) { 21650 if ( jQuery && this.options.isJQueryFiltering ) { 21651 // use jQuery 21652 return function( item ) { 21653 return jQuery( item.element ).is( filter ); 21654 }; 21655 } 21656 if ( typeof filter == 'function' ) { 21657 // use filter as function 21658 return function( item ) { 21659 return filter( item.element ); 21660 }; 21661 } 21662 // default, use filter as selector string 21663 return function( item ) { 21664 return matchesSelector( item.element, filter ); 21665 }; 21666 }; 21667 21668 // -------------------------- sorting -------------------------- // 21669 21670 /** 21671 * @params {Array} elems 21672 * @public 21673 */ 21674 proto.updateSortData = function( elems ) { 21675 // get items 21676 var items; 21677 if ( elems ) { 21678 elems = utils.makeArray( elems ); 21679 items = this.getItems( elems ); 21680 } else { 21681 // update all items if no elems provided 21682 items = this.items; 21683 } 21684 21685 this._getSorters(); 21686 this._updateItemsSortData( items ); 21687 }; 21688 21689 proto._getSorters = function() { 21690 var getSortData = this.options.getSortData; 21691 for ( var key in getSortData ) { 21692 var sorter = getSortData[ key ]; 21693 this._sorters[ key ] = mungeSorter( sorter ); 21694 } 21695 }; 21696 21697 /** 21698 * @params {Array} items - of Isotope.Items 21699 * @private 21700 */ 21701 proto._updateItemsSortData = function( items ) { 21702 // do not update if no items 21703 var len = items && items.length; 21704 21705 for ( var i=0; len && i < len; i++ ) { 21706 var item = items[i]; 21707 item.updateSortData(); 21708 } 21709 }; 21710 21711 // ----- munge sorter ----- // 21712 21713 // encapsulate this, as we just need mungeSorter 21714 // other functions in here are just for munging 21715 var mungeSorter = ( function() { 21716 // add a magic layer to sorters for convienent shorthands 21717 // `.foo-bar` will use the text of .foo-bar querySelector 21718 // `[foo-bar]` will use attribute 21719 // you can also add parser 21720 // `.foo-bar parseInt` will parse that as a number 21721 function mungeSorter( sorter ) { 21722 // if not a string, return function or whatever it is 21723 if ( typeof sorter != 'string' ) { 21724 return sorter; 21725 } 21726 // parse the sorter string 21727 var args = trim( sorter ).split(' '); 21728 var query = args[0]; 21729 // check if query looks like [an-attribute] 21730 var attrMatch = query.match( /^\[(.+)\]$/ ); 21731 var attr = attrMatch && attrMatch[1]; 21732 var getValue = getValueGetter( attr, query ); 21733 // use second argument as a parser 21734 var parser = Isotope.sortDataParsers[ args[1] ]; 21735 // parse the value, if there was a parser 21736 sorter = parser ? function( elem ) { 21737 return elem && parser( getValue( elem ) ); 21738 } : 21739 // otherwise just return value 21740 function( elem ) { 21741 return elem && getValue( elem ); 21742 }; 21743 21744 return sorter; 21745 } 21746 21747 // get an attribute getter, or get text of the querySelector 21748 function getValueGetter( attr, query ) { 21749 // if query looks like [foo-bar], get attribute 21750 if ( attr ) { 21751 return function getAttribute( elem ) { 21752 return elem.getAttribute( attr ); 21753 }; 21754 } 21755 21756 // otherwise, assume its a querySelector, and get its text 21757 return function getChildText( elem ) { 21758 var child = elem.querySelector( query ); 21759 return child && child.textContent; 21760 }; 21761 } 21762 21763 return mungeSorter; 21764 })(); 21765 21766 // parsers used in getSortData shortcut strings 21767 Isotope.sortDataParsers = { 21768 'parseInt': function( val ) { 21769 return parseInt( val, 10 ); 21770 }, 21771 'parseFloat': function( val ) { 21772 return parseFloat( val ); 21773 } 21774 }; 21775 21776 // ----- sort method ----- // 21777 21778 // sort filteredItem order 21779 proto._sort = function() { 21780 if ( !this.options.sortBy ) { 21781 return; 21782 } 21783 // keep track of sortBy History 21784 var sortBys = utils.makeArray( this.options.sortBy ); 21785 if ( !this._getIsSameSortBy( sortBys ) ) { 21786 // concat all sortBy and sortHistory, add to front, oldest goes in last 21787 this.sortHistory = sortBys.concat( this.sortHistory ); 21788 } 21789 // sort magic 21790 var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending ); 21791 this.filteredItems.sort( itemSorter ); 21792 }; 21793 21794 // check if sortBys is same as start of sortHistory 21795 proto._getIsSameSortBy = function( sortBys ) { 21796 for ( var i=0; i < sortBys.length; i++ ) { 21797 if ( sortBys[i] != this.sortHistory[i] ) { 21798 return false; 21799 } 21800 } 21801 return true; 21802 }; 21803 21804 // returns a function used for sorting 21805 function getItemSorter( sortBys, sortAsc ) { 21806 return function sorter( itemA, itemB ) { 21807 // cycle through all sortKeys 21808 for ( var i = 0; i < sortBys.length; i++ ) { 21809 var sortBy = sortBys[i]; 21810 var a = itemA.sortData[ sortBy ]; 21811 var b = itemB.sortData[ sortBy ]; 21812 if ( a > b || a < b ) { 21813 // if sortAsc is an object, use the value given the sortBy key 21814 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 21815 var direction = isAscending ? 1 : -1; 21816 return ( a > b ? 1 : -1 ) * direction; 21817 } 21818 } 21819 return 0; 21820 }; 21821 } 21822 21823 // -------------------------- methods -------------------------- // 21824 21825 // get layout mode 21826 proto._mode = function() { 21827 var layoutMode = this.options.layoutMode; 21828 var mode = this.modes[ layoutMode ]; 21829 if ( !mode ) { 21830 // TODO console.error 21831 throw new Error( 'No layout mode: ' + layoutMode ); 21832 } 21833 // HACK sync mode's options 21834 // any options set after init for layout mode need to be synced 21835 mode.options = this.options[ layoutMode ]; 21836 return mode; 21837 }; 21838 21839 proto._resetLayout = function() { 21840 // trigger original reset layout 21841 Outlayer.prototype._resetLayout.call( this ); 21842 this._mode()._resetLayout(); 21843 }; 21844 21845 proto._getItemLayoutPosition = function( item ) { 21846 return this._mode()._getItemLayoutPosition( item ); 21847 }; 21848 21849 proto._manageStamp = function( stamp ) { 21850 this._mode()._manageStamp( stamp ); 21851 }; 21852 21853 proto._getContainerSize = function() { 21854 return this._mode()._getContainerSize(); 21855 }; 21856 21857 proto.needsResizeLayout = function() { 21858 return this._mode().needsResizeLayout(); 21859 }; 21860 21861 // -------------------------- adding & removing -------------------------- // 21862 21863 // HEADS UP overwrites default Outlayer appended 21864 proto.appended = function( elems ) { 21865 var items = this.addItems( elems ); 21866 if ( !items.length ) { 21867 return; 21868 } 21869 // filter, layout, reveal new items 21870 var filteredItems = this._filterRevealAdded( items ); 21871 // add to filteredItems 21872 this.filteredItems = this.filteredItems.concat( filteredItems ); 21873 }; 21874 21875 // HEADS UP overwrites default Outlayer prepended 21876 proto.prepended = function( elems ) { 21877 var items = this._itemize( elems ); 21878 if ( !items.length ) { 21879 return; 21880 } 21881 // start new layout 21882 this._resetLayout(); 21883 this._manageStamps(); 21884 // filter, layout, reveal new items 21885 var filteredItems = this._filterRevealAdded( items ); 21886 // layout previous items 21887 this.layoutItems( this.filteredItems ); 21888 // add to items and filteredItems 21889 this.filteredItems = filteredItems.concat( this.filteredItems ); 21890 this.items = items.concat( this.items ); 21891 }; 21892 21893 proto._filterRevealAdded = function( items ) { 21894 var filtered = this._filter( items ); 21895 this.hide( filtered.needHide ); 21896 // reveal all new items 21897 this.reveal( filtered.matches ); 21898 // layout new items, no transition 21899 this.layoutItems( filtered.matches, true ); 21900 return filtered.matches; 21901 }; 21902 21903 /** 21904 * Filter, sort, and layout newly-appended item elements 21905 * @param {Array or NodeList or Element} elems 21906 */ 21907 proto.insert = function( elems ) { 21908 var items = this.addItems( elems ); 21909 if ( !items.length ) { 21910 return; 21911 } 21912 // append item elements 21913 var i, item; 21914 var len = items.length; 21915 for ( i=0; i < len; i++ ) { 21916 item = items[i]; 21917 this.element.appendChild( item.element ); 21918 } 21919 // filter new stuff 21920 var filteredInsertItems = this._filter( items ).matches; 21921 // set flag 21922 for ( i=0; i < len; i++ ) { 21923 items[i].isLayoutInstant = true; 21924 } 21925 this.arrange(); 21926 // reset flag 21927 for ( i=0; i < len; i++ ) { 21928 delete items[i].isLayoutInstant; 21929 } 21930 this.reveal( filteredInsertItems ); 21931 }; 21932 21933 var _remove = proto.remove; 21934 proto.remove = function( elems ) { 21935 elems = utils.makeArray( elems ); 21936 var removeItems = this.getItems( elems ); 21937 // do regular thing 21938 _remove.call( this, elems ); 21939 // bail if no items to remove 21940 var len = removeItems && removeItems.length; 21941 // remove elems from filteredItems 21942 for ( var i=0; len && i < len; i++ ) { 21943 var item = removeItems[i]; 21944 // remove item from collection 21945 utils.removeFrom( this.filteredItems, item ); 21946 } 21947 }; 21948 21949 proto.shuffle = function() { 21950 // update random sortData 21951 for ( var i=0; i < this.items.length; i++ ) { 21952 var item = this.items[i]; 21953 item.sortData.random = Math.random(); 21954 } 21955 this.options.sortBy = 'random'; 21956 this._sort(); 21957 this._layout(); 21958 }; 21959 21960 /** 21961 * trigger fn without transition 21962 * kind of hacky to have this in the first place 21963 * @param {Function} fn 21964 * @param {Array} args 21965 * @returns ret 21966 * @private 21967 */ 21968 proto._noTransition = function( fn, args ) { 21969 // save transitionDuration before disabling 21970 var transitionDuration = this.options.transitionDuration; 21971 // disable transition 21972 this.options.transitionDuration = 0; 21973 // do it 21974 var returnValue = fn.apply( this, args ); 21975 // re-enable transition for reveal 21976 this.options.transitionDuration = transitionDuration; 21977 return returnValue; 21978 }; 21979 21980 // ----- helper methods ----- // 21981 21982 /** 21983 * getter method for getting filtered item elements 21984 * @returns {Array} elems - collection of item elements 21985 */ 21986 proto.getFilteredItemElements = function() { 21987 return this.filteredItems.map( function( item ) { 21988 return item.element; 21989 }); 21990 }; 21991 21992 // ----- ----- // 21993 21994 return Isotope; 21995 21996})); 21997
21998/*! 21999 * Packery layout mode PACKAGED v2.0.1 22000 * sub-classes Packery 22001 */ 22002 22003/** 22004 * Rect 22005 * low-level utility class for basic geometry 22006 */ 22007 22008( function( window, factory ) { 22009 // universal module definition 22010 /* jshint strict: false */ /* globals define, module */ 22011 if ( typeof define == 'function' && define.amd ) { 22012 // AMD 22013 define( 'packery/js/rect',factory ); 22014 } else if ( typeof module == 'object' && module.exports ) { 22015 // CommonJS 22016 module.exports = factory(); 22017 } else { 22018 // browser global 22019 window.Packery = window.Packery || {}; 22020 window.Packery.Rect = factory(); 22021 } 22022 22023}( window, function factory() { 22024 22025 22026// -------------------------- Rect -------------------------- // 22027 22028function Rect( props ) { 22029 // extend properties from defaults 22030 for ( var prop in Rect.defaults ) { 22031 this[ prop ] = Rect.defaults[ prop ]; 22032 } 22033 22034 for ( prop in props ) { 22035 this[ prop ] = props[ prop ]; 22036 } 22037 22038} 22039 22040Rect.defaults = { 22041 x: 0, 22042 y: 0, 22043 width: 0, 22044 height: 0 22045}; 22046 22047var proto = Rect.prototype; 22048 22049/** 22050 * Determines whether or not this rectangle wholly encloses another rectangle or point. 22051 * @param {Rect} rect 22052 * @returns {Boolean} 22053**/ 22054proto.contains = function( rect ) { 22055 // points don't have width or height 22056 var otherWidth = rect.width || 0; 22057 var otherHeight = rect.height || 0; 22058 return this.x <= rect.x && 22059 this.y <= rect.y && 22060 this.x + this.width >= rect.x + otherWidth && 22061 this.y + this.height >= rect.y + otherHeight; 22062}; 22063 22064/** 22065 * Determines whether or not the rectangle intersects with another. 22066 * @param {Rect} rect 22067 * @returns {Boolean} 22068**/ 22069proto.overlaps = function( rect ) { 22070 var thisRight = this.x + this.width; 22071 var thisBottom = this.y + this.height; 22072 var rectRight = rect.x + rect.width; 22073 var rectBottom = rect.y + rect.height; 22074 22075 // http://stackoverflow.com/a/306332 22076 return this.x < rectRight && 22077 thisRight > rect.x && 22078 this.y < rectBottom && 22079 thisBottom > rect.y; 22080}; 22081 22082/** 22083 * @param {Rect} rect - the overlapping rect 22084 * @returns {Array} freeRects - rects representing the area around the rect 22085**/ 22086proto.getMaximalFreeRects = function( rect ) { 22087 22088 // if no intersection, return false 22089 if ( !this.overlaps( rect ) ) { 22090 return false; 22091 } 22092 22093 var freeRects = []; 22094 var freeRect; 22095 22096 var thisRight = this.x + this.width; 22097 var thisBottom = this.y + this.height; 22098 var rectRight = rect.x + rect.width; 22099 var rectBottom = rect.y + rect.height; 22100 22101 // top 22102 if ( this.y < rect.y ) { 22103 freeRect = new Rect({ 22104 x: this.x, 22105 y: this.y, 22106 width: this.width, 22107 height: rect.y - this.y 22108 }); 22109 freeRects.push( freeRect ); 22110 } 22111 22112 // right 22113 if ( thisRight > rectRight ) { 22114 freeRect = new Rect({ 22115 x: rectRight, 22116 y: this.y, 22117 width: thisRight - rectRight, 22118 height: this.height 22119 }); 22120 freeRects.push( freeRect ); 22121 } 22122 22123 // bottom 22124 if ( thisBottom > rectBottom ) { 22125 freeRect = new Rect({ 22126 x: this.x, 22127 y: rectBottom, 22128 width: this.width, 22129 height: thisBottom - rectBottom 22130 }); 22131 freeRects.push( freeRect ); 22132 } 22133 22134 // left 22135 if ( this.x < rect.x ) { 22136 freeRect = new Rect({ 22137 x: this.x, 22138 y: this.y, 22139 width: rect.x - this.x, 22140 height: this.height 22141 }); 22142 freeRects.push( freeRect ); 22143 } 22144 22145 return freeRects; 22146}; 22147 22148proto.canFit = function( rect ) { 22149 return this.width >= rect.width && this.height >= rect.height; 22150}; 22151 22152return Rect; 22153 22154})); 22155 22156/** 22157 * Packer 22158 * bin-packing algorithm 22159 */ 22160 22161( function( window, factory ) { 22162 // universal module definition 22163 /* jshint strict: false */ /* globals define, module, require */ 22164 if ( typeof define == 'function' && define.amd ) { 22165 // AMD 22166 define( 'packery/js/packer',[ './rect' ], factory ); 22167 } else if ( typeof module == 'object' && module.exports ) { 22168 // CommonJS 22169 module.exports = factory( 22170 require('./rect') 22171 ); 22172 } else { 22173 // browser global 22174 var Packery = window.Packery = window.Packery || {}; 22175 Packery.Packer = factory( Packery.Rect ); 22176 } 22177 22178}( window, function factory( Rect ) { 22179 22180 22181// -------------------------- Packer -------------------------- // 22182 22183/** 22184 * @param {Number} width 22185 * @param {Number} height 22186 * @param {String} sortDirection 22187 * topLeft for vertical, leftTop for horizontal 22188 */ 22189function Packer( width, height, sortDirection ) { 22190 this.width = width || 0; 22191 this.height = height || 0; 22192 this.sortDirection = sortDirection || 'downwardLeftToRight'; 22193 22194 this.reset(); 22195} 22196 22197var proto = Packer.prototype; 22198 22199proto.reset = function() { 22200 this.spaces = []; 22201 22202 var initialSpace = new Rect({ 22203 x: 0, 22204 y: 0, 22205 width: this.width, 22206 height: this.height 22207 }); 22208 22209 this.spaces.push( initialSpace ); 22210 // set sorter 22211 this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight; 22212}; 22213 22214// change x and y of rect to fit with in Packer's available space
22214s 22215proto.pack = function( rect ) { 22216 for ( var i=0; i < this.spaces.length; i++ ) { 22217 var space = this.spaces[i]; 22218 if ( space.canFit( rect ) ) { 22219 this.placeInSpace( rect, space ); 22220 break; 22221 } 22222 } 22223}; 22224 22225proto.columnPack = function( rect ) { 22226 for ( var i=0; i < this.spaces.length; i++ ) { 22227 var space = this.spaces[i]; 22228 var canFitInSpaceColumn = space.x <= rect.x && 22229 space.x + space.width >= rect.x + rect.width && 22230 space.height >= rect.height - 0.01; // fudge number for rounding error 22231 if ( canFitInSpaceColumn ) { 22232 rect.y = space.y; 22233 this.placed( rect ); 22234 break; 22235 } 22236 } 22237}; 22238 22239proto.rowPack = function( rect ) { 22240 for ( var i=0; i < this.spaces.length; i++ ) { 22241 var space = this.spaces[i]; 22242 var canFitInSpaceRow = space.y <= rect.y && 22243 space.y + space.height >= rect.y + rect.height && 22244 space.width >= rect.width - 0.01; // fudge number for rounding error 22245 if ( canFitInSpaceRow ) { 22246 rect.x = space.x; 22247 this.placed( rect ); 22248 break; 22249 } 22250 } 22251}; 22252 22253proto.placeInSpace = function( rect, space ) { 22254 // place rect in space 22255 rect.x = space.x; 22256 rect.y = space.y; 22257 22258 this.placed( rect ); 22259}; 22260 22261// update spaces with placed rect 22262proto.placed = function( rect ) { 22263 // update spaces 22264 var revisedSpaces = []; 22265 for ( var i=0; i < this.spaces.length; i++ ) { 22266 var space = this.spaces[i]; 22267 var newSpaces = space.getMaximalFreeRects( rect ); 22268 // add either the original space or the new spaces to the revised spaces 22269 if ( newSpaces ) { 22270 revisedSpaces.push.apply( revisedSpaces, newSpaces ); 22271 } else { 22272 revisedSpaces.push( space ); 22273 } 22274 } 22275 22276 this.spaces = revisedSpaces; 22277 22278 this.mergeSortSpaces(); 22279}; 22280 22281proto.mergeSortSpaces = function() { 22282 // remove redundant spaces 22283 Packer.mergeRects( this.spaces ); 22284 this.spaces.sort( this.sorter ); 22285}; 22286 22287// add a space back 22288proto.addSpace = function( rect ) { 22289 this.spaces.push( rect ); 22290 this.mergeSortSpaces(); 22291}; 22292 22293// -------------------------- utility functions -------------------------- // 22294 22295/** 22296 * Remove redundant rectangle from array of rectangles 22297 * @param {Array} rects: an array of Rects 22298 * @returns {Array} rects: an array of Rects 22299**/ 22300Packer.mergeRects = function( rects ) { 22301 var i = 0; 22302 var rect = rects[i]; 22303 22304 rectLoop: 22305 while ( rect ) { 22306 var j = 0; 22307 var compareRect = rects[ i + j ]; 22308 22309 while ( compareRect ) { 22310 if ( compareRect == rect ) { 22311 j++; // next 22312 } else if ( compareRect.contains( rect ) ) { 22313 // remove rect 22314 rects.splice( i, 1 ); 22315 rect = rects[i]; // set next rect 22316 continue rectLoop; // bail on compareLoop 22317 } else if ( rect.contains( compareRect ) ) { 22318 // remove compareRect 22319 rects.splice( i + j, 1 ); 22320 } else { 22321 j++; 22322 } 22323 compareRect = rects[ i + j ]; // set next compareRect 22324 } 22325 i++; 22326 rect = rects[i]; 22327 } 22328 22329 return rects; 22330}; 22331 22332 22333// -------------------------- sorters -------------------------- // 22334 22335// functions for sorting rects in order 22336var sorters = { 22337 // top down, then left to right 22338 downwardLeftToRight: function( a, b ) { 22339 return a.y - b.y || a.x - b.x; 22340 }, 22341 // left to right, then top down 22342 rightwardTopToBottom: function( a, b ) { 22343 return a.x - b.x || a.y - b.y; 22344 } 22345}; 22346 22347 22348// -------------------------- -------------------------- // 22349 22350return Packer; 22351 22352})); 22353 22354/** 22355 * Packery Item Element 22356**/ 22357 22358( function( window, factory ) { 22359 // universal module definition 22360 /* jshint strict: false */ /* globals define, module, require */ 22361 if ( typeof define == 'function' && define.amd ) { 22362 // AMD 22363 define( 'packery/js/item',[ 22364 'outlayer/outlayer', 22365 './rect' 22366 ], 22367 factory ); 22368 } else if ( typeof module == 'object' && module.exports ) { 22369 // CommonJS 22370 module.exports = factory( 22371 require('outlayer'), 22372 require('./rect') 22373 ); 22374 } else { 22375 // browser global 22376 window.Packery.Item = factory( 22377 window.Outlayer, 22378 window.Packery.Rect 22379 ); 22380 } 22381 22382}( window, function factory( Outlayer, Rect ) { 22383 22384 22385// -------------------------- Item -------------------------- // 22386 22387var docElemStyle = document.documentElement.style; 22388 22389var transformProperty = typeof docElemStyle.transform == 'string' ? 22390 'transform' : 'WebkitTransform'; 22391 22392// sub-class Item 22393var Item = function PackeryItem() { 22394 Outlayer.Item.apply( this, arguments ); 22395}; 22396 22397var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 22398 22399var __create = proto._create; 22400proto._create = function() { 22401 // call default _create logic 22402 __create.call( this ); 22403 this.rect = new Rect(); 22404}; 22405 22406var _moveTo = proto.moveTo; 22407proto.moveTo = function( x, y ) {
22408 // don't shift 1px while dragging 22409 var dx = Math.abs( this.position.x - x ); 22410 var dy = Math.abs( this.position.y - y ); 22411 22412 var canHackGoTo = this.layout.dragItemCount && !this.isPlacing && 22413 !this.isTransitioning && dx < 1 && dy < 1; 22414 if ( canHackGoTo ) { 22415 this.goTo( x, y ); 22416 return; 22417 } 22418 _moveTo.apply( this, arguments ); 22419}; 22420 22421// -------------------------- placing -------------------------- // 22422 22423proto.enablePlacing = function() { 22424 this.removeTransitionStyles(); 22425 // remove transform property from transition 22426 if ( this.isTransitioning && transformProperty ) { 22427 this.element.style[ transformProperty ] = 'none'; 22428 } 22429 this.isTransitioning = false; 22430 this.getSize(); 22431 this.layout._setRectSize( this.element, this.rect ); 22432 this.isPlacing = true; 22433}; 22434 22435proto.disablePlacing = function() { 22436 this.isPlacing = false; 22437}; 22438 22439// ----- ----- // 22440 22441// remove element from DOM 22442proto.removeElem = function() { 22443 this.element.parentNode.removeChild( this.element ); 22444 // add space back to packer 22445 this.layout.packer.addSpace( this.rect ); 22446 this.emitEvent( 'remove', [ this ] ); 22447}; 22448 22449// ----- dropPlaceholder ----- // 22450 22451proto.showDropPlaceholder = function() { 22452 var dropPlaceholder = this.dropPlaceholder; 22453 if ( !dropPlaceholder ) { 22454 // create dropPlaceholder 22455 dropPlaceholder = this.dropPlaceholder = document.createElement('div'); 22456 dropPlaceholder.className = 'packery-drop-placeholder'; 22457 dropPlaceholder.style.position = 'absolute'; 22458 } 22459 22460 dropPlaceholder.style.width = this.size.width + 'px'; 22461 dropPlaceholder.style.height = this.size.height + 'px'; 22462 this.positionDropPlaceholder(); 22463 this.layout.element.appendChild( dropPlaceholder ); 22464}; 22465 22466proto.positionDropPlaceholder = function() { 22467 this.dropPlaceholder.style[ transformProperty ] = 'translate(' + 22468 this.rect.x + 'px, ' + this.rect.y + 'px)'; 22469}; 22470 22471proto.hideDropPlaceholder = function() { 22472 this.layout.element.removeChild( this.dropPlaceholder ); 22473}; 22474 22475// ----- ----- // 22476 22477return Item; 22478 22479})); 22480 22481/*! 22482 * Packery v2.0.0 22483 * Gapless, draggable grid layouts 22484 * 22485 * Licensed GPLv3 for open source use 22486 * or Packery Commercial License for commercial use 22487 * 22488 * http://packery.metafizzy.co 22489 * Copyright 2016 Metafizzy 22490 */ 22491 22492( function( window, factory ) { 22493 // universal module definition 22494 /* jshint strict: false */ /* globals define, module, require */ 22495 if ( typeof define == 'function' && define.amd ) { 22496 // AMD 22497 define( 'packery/js/packery',[ 22498 'get-size/get-size', 22499 'outlayer/outlayer', 22500 './rect', 22501 './packer', 22502 './item' 22503 ], 22504 factory ); 22505 } else if ( typeof module == 'object' && module.exports ) { 22506 // CommonJS 22507 module.exports = factory( 22508 require('get-size'), 22509 require('outlayer'), 22510 require('./rect'), 22511 require('./packer'), 22512 require('./item') 22513 ); 22514 } else { 22515 // browser global 22516 window.Packery = factory( 22517 window.getSize, 22518 window.Outlayer, 22519 window.Packery.Rect, 22520 window.Packery.Packer, 22521 window.Packery.Item 22522 ); 22523 } 22524 22525}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) { 22526 22527 22528// ----- Rect ----- // 22529 22530// allow for pixel rounding errors IE8-IE11 & Firefox; #227 22531Rect.prototype.canFit = function( rect ) { 22532 return this.width >= rect.width - 1 && this.height >= rect.height - 1; 22533}; 22534 22535// -------------------------- Packery -------------------------- // 22536 22537// create an Outlayer layout class 22538var Packery = Outlayer.create('packery'); 22539Packery.Item = Item; 22540 22541var proto = Packery.prototype; 22542 22543proto._create = function() { 22544 // call super 22545 Outlayer.prototype._create.call( this ); 22546 22547 // initial properties 22548 this.packer = new Packer(); 22549 // packer for drop targets 22550 this.shiftPacker = new Packer(); 22551 this.isEnabled = true; 22552 22553 this.dragItemCount = 0; 22554 22555 // create drag handlers 22556 var _this = this; 22557 this.handleDraggabilly = { 22558 dragStart: function() { 22559 _this.itemDragStart( this.element ); 22560 }, 22561 dragMove: function() { 22562 _this.itemDragMove( this.element, this.position.x, this.position.y ); 22563 }, 22564 dragEnd: function() { 22565 _this.itemDragEnd( this.element ); 22566 } 22567 }; 22568 22569 this.handleUIDraggable = { 22570 start: function handleUIDraggableStart( event, ui ) { 22571 // HTML5 may trigger dragstart, dismiss HTML5 dragging 22572 if ( !ui ) { 22573 return; 22574 } 22575 _this.itemDragStart( event.currentTarget ); 22576 }, 22577 drag: function handleUIDraggableDrag( event, ui ) { 22578 if ( !ui ) { 22579 return; 22580 } 22581 _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top ); 22582 }, 22583 stop: function handleUIDraggableStop( event, ui ) { 22584 if ( !ui ) { 22585 return; 22586 } 22587 _this.itemDragEnd( event.currentTarget ); 22588 } 22589 }; 22590 22591}; 22592 22593 22594// ----- init & layout ----- // 22595 22596/** 22597 * logic before any new layout 22598 */ 22599proto._resetLayout = function() {
22600 this.getSize(); 22601 22602 this._getMeasurements(); 22603 22604 // reset packer 22605 var width, height, sortDirection; 22606 // packer settings, if horizontal or vertical 22607 if ( this._getOption('horizontal') ) { 22608 width = Infinity; 22609 height = this.size.innerHeight + this.gutter; 22610 sortDirection = 'rightwardTopToBottom'; 22611 } else { 22612 width = this.size.innerWidth + this.gutter; 22613 height = Infinity; 22614 sortDirection = 'downwardLeftToRight'; 22615 } 22616 22617 this.packer.width = this.shiftPacker.width = width; 22618 this.packer.height = this.shiftPacker.height = height; 22619 this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection; 22620 22621 this.packer.reset(); 22622 22623 // layout 22624 this.maxY = 0; 22625 this.maxX = 0; 22626}; 22627 22628/** 22629 * update columnWidth, rowHeight, & gutter 22630 * @private 22631 */ 22632proto._getMeasurements = function() { 22633 this._getMeasurement( 'columnWidth', 'width' ); 22634 this._getMeasurement( 'rowHeight', 'height' ); 22635 this._getMeasurement( 'gutter', 'width' ); 22636}; 22637 22638proto._getItemLayoutPosition = function( item ) { 22639 this._setRectSize( item.element, item.rect ); 22640 if ( this.isShifting || this.dragItemCount > 0 ) { 22641 var packMethod = this._getPackMethod(); 22642 this.packer[ packMethod ]( item.rect ); 22643 } else { 22644 this.packer.pack( item.rect ); 22645 } 22646 22647 this._setMaxXY( item.rect ); 22648 return item.rect; 22649}; 22650 22651proto.shiftLayout = function() { 22652 this.isShifting = true; 22653 this.layout(); 22654 delete this.isShifting; 22655}; 22656 22657proto._getPackMethod = function() { 22658 return this._getOption('horizontal') ? 'rowPack' : 'columnPack'; 22659}; 22660 22661 22662/** 22663 * set max X and Y value, for size of container 22664 * @param {Packery.Rect} rect 22665 * @private 22666 */ 22667proto._setMaxXY = function( rect ) { 22668 this.maxX = Math.max( rect.x + rect.width, this.maxX ); 22669 this.maxY = Math.max( rect.y + rect.height, this.maxY ); 22670}; 22671 22672/** 22673 * set the width and height of a rect, applying columnWidth and rowHeight 22674 * @param {Element} elem 22675 * @param {Packery.Rect} rect 22676 */ 22677proto._setRectSize = function( elem, rect ) { 22678 var size = getSize( elem ); 22679 var w = size.outerWidth; 22680 var h = size.outerHeight; 22681 // size for columnWidth and rowHeight, if available 22682 // only check if size is non-zero, #177 22683 if ( w || h ) { 22684 w = this._applyGridGutter( w, this.columnWidth ); 22685 h = this._applyGridGutter( h, this.rowHeight ); 22686 } 22687 // rect must fit in packer 22688 rect.width = Math.min( w, this.packer.width ); 22689 rect.height = Math.min( h, this.packer.height ); 22690}; 22691 22692/** 22693 * fits item to columnWidth/rowHeight and adds gutter 22694 * @param {Number} measurement - item width or height 22695 * @param {Number} gridSize - columnWidth or rowHeight 22696 * @returns measurement 22697 */ 22698proto._applyGridGutter = function( measurement, gridSize ) { 22699 // just add gutter if no gridSize 22700 if ( !gridSize ) { 22701 return measurement + this.gutter; 22702 } 22703 gridSize += this.gutter; 22704 // fit item to columnWidth/rowHeight 22705 var remainder = measurement % gridSize; 22706 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 22707 measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize; 22708 return measurement; 22709}; 22710 22711proto._getContainerSize = function() { 22712 if ( this._getOption('horizontal') ) { 22713 return { 22714 width: this.maxX - this.gutter 22715 }; 22716 } else { 22717 return { 22718 height: this.maxY - this.gutter 22719 }; 22720 } 22721}; 22722 22723 22724// -------------------------- stamp -------------------------- // 22725 22726/** 22727 * makes space for element 22728 * @param {Element} elem 22729 */ 22730proto._manageStamp = function( elem ) { 22731 22732 var item = this.getItem( elem ); 22733 var rect; 22734 if ( item && item.isPlacing ) { 22735 rect = item.rect; 22736 } else { 22737 var offset = this._getElementOffset( elem ); 22738 rect = new Rect({ 22739 x: this._getOption('originLeft') ? offset.left : offset.right, 22740 y: this._getOption('originTop') ? offset.top : offset.bottom 22741 }); 22742 } 22743 22744 this._setRectSize( elem, rect ); 22745 // save its space in the packer 22746 this.packer.placed( rect ); 22747 this._setMaxXY( rect ); 22748}; 22749 22750// -------------------------- methods -------------------------- // 22751 22752function verticalSorter( a, b ) { 22753 return a.position.y - b.position.y || a.position.x - b.position.x; 22754} 22755 22756function horizontalSorter( a, b ) { 22757 return a.position.x - b.position.x || a.position.y - b.position.y; 22758} 22759
22760proto.sortItemsByPosition = function() { 22761 var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter; 22762 this.items.sort( sorter ); 22763}; 22764 22765/** 22766 * Fit item element in its current position 22767 * Packery will position elements around it 22768 * useful for expanding elements 22769 * 22770 * @param {Element} elem 22771 * @param {Number} x - horizontal destination position, optional 22772 * @param {Number} y - vertical destination position, optional 22773 */ 22774proto.fit = function( elem, x, y ) { 22775 var item = this.getItem( elem ); 22776 if ( !item ) { 22777 return; 22778 } 22779 22780 // stamp item to get it out of layout 22781 this.stamp( item.element ); 22782 // set placing flag 22783 item.enablePlacing(); 22784 this.updateShiftTargets( item ); 22785 // fall back to current position for fitting 22786 x = x === undefined ? item.rect.x: x; 22787 y = y === undefined ? item.rect.y: y; 22788 // position it best at its destination 22789 this.shift( item, x, y ); 22790 this._bindFitEvents( item ); 22791 item.moveTo( item.rect.x, item.rect.y ); 22792 // layout everything else 22793 this.shiftLayout(); 22794 // return back to regularly scheduled programming 22795 this.unstamp( item.element ); 22796 this.sortItemsByPosition(); 22797 item.disablePlacing(); 22798}; 22799 22800/** 22801 * emit event when item is fit and other items are laid out 22802 * @param {Packery.Item} item 22803 * @private 22804 */ 22805proto._bindFitEvents = function( item ) { 22806 var _this = this; 22807 var ticks = 0; 22808 function onLayout() { 22809 ticks++; 22810 if ( ticks != 2 ) { 22811 return; 22812 } 22813 _this.dispatchEvent( 'fitComplete', null, [ item ] ); 22814 } 22815 // when item is laid out 22816 item.once( 'layout', onLayout ); 22817 // when all items are laid out 22818 this.once( 'layoutComplete', onLayout ); 22819}; 22820 22821// -------------------------- resize -------------------------- // 22822 22823// debounced, layout on resize 22824proto.resize = function() { 22825 // don't trigger if size did not change 22826 // or if resize was unbound. See #285, outlayer#9 22827 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 22828 return; 22829 } 22830 22831 if ( this.options.shiftPercentResize ) { 22832 this.resizeShiftPercentLayout(); 22833 } else { 22834 this.layout(); 22835 } 22836}; 22837 22838/** 22839 * check if layout is needed post layout 22840 * @returns Boolean 22841 */ 22842proto.needsResizeLayout = function() { 22843 var size = getSize( this.element ); 22844 var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth'; 22845 return size[ innerSize ] != this.size[ innerSize ]; 22846}; 22847 22848proto.resizeShiftPercentLayout = function() { 22849 var items = this._getItemsForLayout( this.items ); 22850 22851 var isHorizontal = this._getOption('horizontal'); 22852 var coord = isHorizontal ? 'y' : 'x'; 22853 var measure = isHorizontal ? 'height' : 'width'; 22854 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 22855 var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth'; 22856 22857 // proportional re-align items 22858 var previousSegment = this[ segmentName ]; 22859 previousSegment = previousSegment && previousSegment + this.gutter; 22860 22861 if ( previousSegment ) { 22862 this._getMeasurements(); 22863 var currentSegment = this[ segmentName ] + this.gutter; 22864 items.forEach( function( item ) { 22865 var seg = Math.round( item.rect[ coord ] / previousSegment ); 22866 item.rect[ coord ] = seg * currentSegment; 22867 }); 22868 } else { 22869 var currentSize = getSize( this.element )[ innerSize ] + this.gutter; 22870 var previousSize = this.packer[ measure ]; 22871 items.forEach( function( item ) { 22872 item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize; 22873 }); 22874 } 22875 22876 this.shiftLayout(); 22877}; 22878 22879// -------------------------- drag -------------------------- // 22880 22881/** 22882 * handle an item drag start event 22883 * @param {Element} elem 22884 */ 22885proto.itemDragStart = function( elem ) { 22886 if ( !this.isEnabled ) { 22887 return; 22888 } 22889 this.stamp( elem ); 22890 // this.ignore( elem ); 22891 var item = this.getItem( elem ); 22892 if ( !item ) { 22893 return; 22894 } 22895 22896 item.enablePlacing(); 22897 item.showDropPlaceholder(); 22898 this.dragItemCount++; 22899 this.updateShiftTargets( item ); 22900}; 22901 22902proto.updateShiftTargets = function( dropItem ) { 22903 this.shiftPacker.reset(); 22904 22905 // pack stamps 22906 this._getBoundingRect(); 22907 var isOriginLeft = this._getOption('originLeft'); 22908 var isOriginTop = this._getOption('originTop'); 22909 this.stamps.forEach( function( stamp ) { 22910 // ignore dragged item 22911 var item = this.getItem( stamp ); 22912 if ( item && item.isPlacing ) { 22913 return; 22914 } 22915 var offset = this._getElementOffset( stamp ); 22916 var rect = new Rect({ 22917 x: isOriginLeft ? offset.left : offset.right, 22918 y: isOriginTop ? offset.top : offset.bottom 22919 }); 22920 this._setRectSize( stamp, rect ); 22921 // save its space in the packer 22922 this.shiftPacker.placed( rect ); 22923 }, this ); 22924 22925 // reset shiftTargets 22926 var isHorizontal = this._getOption('horizontal'); 22927 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 22928 var measure = isHorizontal ? 'height' : 'width'; 22929 22930 this.shiftTargetKeys = []; 22931 this.shiftTargets = []; 22932 var boundsSize; 22933 var segment = this[ segmentName ]; 22934 segment = segment && segment + this.gutter; 22935 22936 if ( segment ) { 22937 var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment ); 22938 var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment ); 22939 boundsSize = ( segs - segmentSpan ) * segment; 22940 // add targets on top 22941 for ( var i=0; i < segs; i++ ) { 22942 this._addShiftTarget( i * segment, 0, boundsSize ); 22943 } 22944 } else { 22945 boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ]; 22946 this._addShiftTarget( 0, 0, boundsSize ); 22947 } 22948 22949 // pack each item to measure where shiftTargets are 22950 var items = this._getItemsForLayout( this.items ); 22951 var packMethod = this._getPackMethod();
22952 items.forEach( function( item ) { 22953 var rect = item.rect; 22954 this._setRectSize( item.element, rect ); 22955 this.shiftPacker[ packMethod ]( rect ); 22956 22957 // add top left corner 22958 this._addShiftTarget( rect.x, rect.y, boundsSize ); 22959 // add bottom left / top right corner 22960 var cornerX = isHorizontal ? rect.x + rect.width : rect.x; 22961 var cornerY = isHorizontal ? rect.y : rect.y + rect.height; 22962 this._addShiftTarget( cornerX, cornerY, boundsSize ); 22963 22964 if ( segment ) { 22965 // add targets for each column on bottom / row on right 22966 var segSpan = Math.round( rect[ measure ] / segment ); 22967 for ( var i=1; i < segSpan; i++ ) { 22968 var segX = isHorizontal ? cornerX : rect.x + segment * i; 22969 var segY = isHorizontal ? rect.y + segment * i : cornerY; 22970 this._addShiftTarget( segX, segY, boundsSize ); 22971 } 22972 } 22973 }, this ); 22974 22975}; 22976 22977proto._addShiftTarget = function( x, y, boundsSize ) { 22978 var checkCoord = this._getOption('horizontal') ? y : x; 22979 if ( checkCoord !== 0 && checkCoord > boundsSize ) { 22980 return; 22981 } 22982 // create string for a key, easier to keep track of what targets 22983 var key = x + ',' + y; 22984 var hasKey = this.shiftTargetKeys.indexOf( key ) != -1; 22985 if ( hasKey ) { 22986 return; 22987 } 22988 this.shiftTargetKeys.push( key ); 22989 this.shiftTargets.push({ x: x, y: y }); 22990}; 22991 22992// -------------------------- drop -------------------------- // 22993 22994proto.shift = function( item, x, y ) { 22995 var shiftPosition; 22996 var minDistance = Infinity; 22997 var position = { x: x, y: y }; 22998 this.shiftTargets.forEach( function( target ) { 22999 var distance = getDistance( target, position ); 23000 if ( distance < minDistance ) { 23001 shiftPosition = target; 23002 minDistance = distance; 23003 } 23004 }); 23005 item.rect.x = shiftPosition.x; 23006 item.rect.y = shiftPosition.y; 23007}; 23008 23009function getDistance( a, b ) { 23010 var dx = b.x - a.x; 23011 var dy = b.y - a.y; 23012 return Math.sqrt( dx * dx + dy * dy ); 23013} 23014 23015// -------------------------- drag move -------------------------- // 23016 23017var DRAG_THROTTLE_TIME = 120; 23018 23019/** 23020 * handle an item drag move event 23021 * @param {Element} elem 23022 * @param {Number} x - horizontal change in position 23023 * @param {Number} y - vertical change in position 23024 */ 23025proto.itemDragMove = function( elem, x, y ) { 23026 var item = this.isEnabled && this.getItem( elem ); 23027 if ( !item ) { 23028 return; 23029 } 23030 23031 x -= this.size.paddingLeft; 23032 y -= this.size.paddingTop; 23033 23034 var _this = this; 23035 function onDrag() { 23036 _this.shift( item, x, y ); 23037 item.positionDropPlaceholder(); 23038 _this.layout(); 23039 } 23040 23041 // throttle 23042 var now = new Date(); 23043 if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) { 23044 clearTimeout( this.dragTimeout ); 23045 this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME ); 23046 } else { 23047 onDrag(); 23048 this._itemDragTime = now; 23049 } 23050}; 23051 23052// -------------------------- drag end -------------------------- // 23053 23054/** 23055 * handle an item drag end event 23056 * @param {Element} elem 23057 */ 23058proto.itemDragEnd = function( elem ) { 23059 var item = this.isEnabled && this.getItem( elem ); 23060 if ( !item ) { 23061 return; 23062 } 23063 23064 clearTimeout( this.dragTimeout ); 23065 item.element.classList.add('is-positioning-post-drag'); 23066 23067 var completeCount = 0; 23068 var _this = this; 23069 function onDragEndLayoutComplete() { 23070 completeCount++; 23071 if ( completeCount != 2 ) { 23072 return; 23073 } 23074 // reset drag item 23075 item.element.classList.remove('is-positioning-post-drag'); 23076 item.hideDropPlaceholder(); 23077 _this.dispatchEvent( 'dragItemPositioned', null, [ item ] ); 23078 } 23079 23080 item.once( 'layout', onDragEndLayoutComplete ); 23081 this.once( 'layoutComplete', onDragEndLayoutComplete ); 23082 item.moveTo( item.rect.x, item.rect.y ); 23083 this.layout(); 23084 this.dragItemCount = Math.max( 0, this.dragItemCount - 1 ); 23085 this.sortItemsByPosition(); 23086 item.disablePlacing(); 23087 this.unstamp( item.element ); 23088}; 23089 23090/** 23091 * binds Draggabilly events 23092 * @param {Draggabilly} draggie 23093 */ 23094proto.bindDraggabillyEvents = function( draggie ) { 23095 this._bindDraggabillyEvents( draggie, 'on' ); 23096}; 23097 23098proto.unbindDraggabillyEvents = function( draggie ) { 23099 this._bindDraggabillyEvents( draggie, 'off' ); 23100}; 23101 23102proto._bindDraggabillyEvents = function( draggie, method ) { 23103 var handlers = this.handleDraggabilly; 23104 draggie[ method ]( 'dragStart', handlers.dragStart ); 23105 draggie[ method ]( 'dragMove', handlers.dragMove ); 23106 draggie[ method ]( 'dragEnd', handlers.dragEnd ); 23107}; 23108 23109/** 23110 * binds jQuery UI Draggable events 23111 * @param {jQuery} $elems 23112 */ 23113proto.bindUIDraggableEvents = function( $elems ) { 23114 this._bindUIDraggableEvents( $elems, 'on' ); 23115}; 23116 23117proto.unbindUIDraggableEvents = function( $elems ) { 23118 this._bindUIDraggableEvents( $elems, 'off' ); 23119}; 23120 23121proto._bindUIDraggableEvents = function( $elems, method ) { 23122 var handlers = this.handleUIDraggable; 23123 $elems 23124 [ method ]( 'dragstart', handlers.start ) 23125 [ method ]( 'drag', handlers.drag ) 23126 [ method ]( 'dragstop', handlers.stop ); 23127}; 23128 23129// ----- destroy ----- // 23130 23131var _destroy = proto.destroy; 23132proto.destroy = function() { 23133 _destroy.apply( this, arguments ); 23134 // disable flag; prevent drag events from triggering. #72 23135 this.isEnabled = false;
23136}; 23137 23138// ----- ----- // 23139 23140Packery.Rect = Rect; 23141Packery.Packer = Packer; 23142 23143return Packery; 23144 23145})); 23146 23147/*! 23148 * Packery layout mode v2.0.1 23149 * sub-classes Packery 23150 */ 23151 23152/*jshint browser: true, strict: true, undef: true, unused: true */ 23153 23154( function( window, factory ) { 23155 23156 // universal module definition 23157 if ( typeof define == 'function' && define.amd ) { 23158 // AMD 23159 define( [ 23160 'isotope-layout/js/layout-mode', 23161 'packery/js/packery' 23162 ], 23163 factory ); 23164 } else if ( typeof module == 'object' && module.exports ) { 23165 // CommonJS 23166 module.exports = factory( 23167 require('isotope-layout/js/layout-mode'), 23168 require('packery') 23169 ); 23170 } else { 23171 // browser global 23172 factory( 23173 window.Isotope.LayoutMode, 23174 window.Packery 23175 ); 23176 } 23177 23178}( window, function factor( LayoutMode, Packery ) { 23179 23180 23181 // create an Outlayer layout class 23182 var PackeryMode = LayoutMode.create('packery'); 23183 var proto = PackeryMode.prototype; 23184 23185 var keepModeMethods = { 23186 _getElementOffset: true, 23187 _getMeasurement: true 23188 }; 23189 23190 // inherit Packery prototype 23191 for ( var method in Packery.prototype ) { 23192 // do not inherit mode methods 23193 if ( !keepModeMethods[ method ] ) { 23194 proto[ method ] = Packery.prototype[ method ]; 23195 } 23196 } 23197 23198 // set packer in _resetLayout 23199 var _resetLayout = proto._resetLayout; 23200 proto._resetLayout = function() { 23201 this.packer = this.packer || new Packery.Packer(); 23202 this.shiftPacker = this.shiftPacker || new Packery.Packer(); 23203 _resetLayout.apply( this, arguments ); 23204 }; 23205 23206 var _getItemLayoutPosition = proto._getItemLayoutPosition; 23207 proto._getItemLayoutPosition = function( item ) { 23208 // set packery rect 23209 item.rect = item.rect || new Packery.Rect(); 23210 return _getItemLayoutPosition.call( this, item ); 23211 }; 23212 23213 // needsResizeLayout for vertical or horizontal 23214 var _needsResizeLayout = proto.needsResizeLayout; 23215 proto.needsResizeLayout = function() { 23216 if ( this._getOption('horizontal') ) { 23217 return this.needsVerticalResizeLayout(); 23218 } else { 23219 return _needsResizeLayout.call( this ); 23220 } 23221 }; 23222 23223 // point to mode options for horizontal 23224 var _getOption = proto._getOption; 23225 proto._getOption = function( option ) { 23226 if ( option == 'horizontal' ) { 23227 return this.options.isHorizontal !== undefined ? 23228 this.options.isHorizontal : this.options.horizontal; 23229 } 23230 return _getOption.apply( this.isotope, arguments ); 23231 }; 23232 23233 return PackeryMode; 23234 23235})); 23236 23237/*! 23238 * cellsByRows layout mode for Isotope 23239 * v1.1.3 23240 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 23241 */ 23242 23243/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 23244 23245( function( window, factory ) { 23246 // universal module definition 23247 /* jshint strict: false */ /*globals define, module, require */ 23248 if ( typeof define === 'function' && define.amd ) { 23249 // AMD 23250 define( [ 23251 'isotope/js/layout-mode' 23252 ], 23253 factory ); 23254 } else if ( typeof exports === 'object' ) { 23255 // CommonJS 23256 module.exports = factory( 23257 require('isotope-layout/js/layout-mode') 23258 ); 23259 } else { 23260 // browser global 23261 factory( 23262 window.Isotope.LayoutMode 23263 ); 23264 } 23265 23266}( window, function factory( LayoutMode ) { 23267 'use strict'; 23268 23269 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 23270 var proto = CellsByRow.prototype; 23271 23272 proto._resetLayout = function() { 23273 // reset properties 23274 this.itemIndex = 0; 23275 // measurements 23276 this.getColumnWidth(); 23277 this.getRowHeight(); 23278 // set cols 23279 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 23280 this.cols = Math.max( this.cols, 1 ); 23281 }; 23282 23283 proto._getItemLayoutPosition = function( item ) { 23284 item.getSize(); 23285 var col = this.itemIndex % this.cols; 23286 var row = Math.floor( this.itemIndex / this.cols ); 23287 // center item within cell 23288 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 23289 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 23290 this.itemIndex++; 23291 return { x: x, y: y }; 23292 }; 23293 23294 proto._getContainerSize = function() { 23295 return { 23296 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 23297 }; 23298 }; 23299 23300 return CellsByRow; 23301 23302})); 23303/*global jQuery: true */ 23304 23305/*! 23306 -------------------------------- 23307 Infinite Scroll 23308 -------------------------------- 23309 + https://github.com/paulirish/infinite-scroll 23310 + version 2.1.0 23311 + Copyright 2011/12 Paul Irish & Luke Shumard 23312 + Licensed under the MIT license 23313 23314 + Documentation: http://infinite-scroll.com/ 23315*/ 23316 23317// Uses AMD or browser globals to create a jQuery plugin. 23318(function (factory) { 23319 if (typeof define === 'function' && define.amd) { 23320 // AMD. Register as an anonymous module. 23321 define(['jquery'], factory); 23322 } else { 23323 // Browser globals 23324 factory(jQuery); 23325 } 23326}(function ($, undefined) { 23327 'use strict'; 23328
23329 $.infinitescroll = function infscr(options, callback, element) { 23330 this.element = $(element); 23331 23332 // Flag the object in the event of a failed creation 23333 if (!this._create(options, callback)) { 23334 this.failed = true; 23335 } 23336 }; 23337 23338 $.infinitescroll.defaults = { 23339 loading: { 23340 finished: undefined, 23341 finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>", 23342 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
23342MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
23342iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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', 23343 msg: null, 23344 msgText: '<em>Loading the next set of posts...</em>', 23345 selector: null, 23346 speed: 'fast', 23347 start: undefined 23348 }, 23349 state: { 23350 isDuringAjax: false, 23351 isInvalidPage: false,
23352 isDestroyed: false, 23353 isDone: false, // For when it goes all the way through the archive. 23354 isPaused: false, 23355 isBeyondMaxPage: false, 23356 currPage: 1 23357 }, 23358 debug: false, 23359 behavior: undefined, 23360 binder: $(window), // used to cache the selector 23361 nextSelector: 'div.navigation a:first', 23362 navSelector: 'div.navigation', 23363 contentSelector: null, // rename to pageFragment 23364 extraScrollPx: 150, 23365 itemSelector: 'div.post', 23366 animate: false, 23367 pathParse: undefined, 23368 dataType: 'html', 23369 appendCallback: true, 23370 bufferPx: 40, 23371 errorCallback: function () { }, 23372 infid: 0, //Instance ID 23373 pixelsFromNavToBottom: undefined, 23374 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 23375 prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted 23376 maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work) 23377 }; 23378 23379 $.infinitescroll.prototype = { 23380 23381 /* 23382 ---------------------------- 23383 Private methods 23384 ---------------------------- 23385 */ 23386 23387 // Bind or unbind from scroll 23388 _binding: function infscr_binding(binding) { 23389 23390 var instance = this, 23391 opts = instance.options; 23392 23393 opts.v = '2.0b2.120520'; 23394 23395 // if behavior is defined and this function is extended, call that instead of default 23396 if (!!opts.behavior && this['_binding_' + opts.behavior] !== undefined) { 23397 this['_binding_' + opts.behavior].call(this); 23398 return; 23399 } 23400 23401 if (binding !== 'bind' && binding !== 'unbind') { 23402 this._debug('Binding value ' + binding + ' not valid'); 23403 return false; 23404 } 23405 23406 if (binding === 'unbind') { 23407 (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid); 23408 } else { 23409 (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () { 23410 instance.scroll(); 23411 }); 23412 } 23413 23414 this._debug('Binding', binding); 23415 }, 23416 23417 // Fundamental aspects of the plugin are initialized 23418 _create: function infscr_create(options, callback) { 23419 23420 // Add custom options to defaults 23421 var opts = $.extend(true, {}, $.infinitescroll.defaults, options); 23422 this.options = opts; 23423 var $window = $(window); 23424 var instance = this; 23425 23426 // Validate selectors 23427 if (!instance._validate(options)) { 23428 return false; 23429 } 23430 23431 // Validate page fragment path 23432 var path = $(opts.nextSelector).attr('href'); 23433 if (!path) { 23434 this._debug('Navigation selector not found'); 23435 return false; 23436 } 23437 23438 // Set the path to be a relative URL from root. 23439 opts.path = opts.path || this._determinepath(path); 23440 23441 // contentSelector is 'page fragment' option for .load() / .ajax() calls 23442 opts.contentSelector = opts.contentSelector || this.element; 23443 23444 // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector 23445 opts.loading.selector = opts.loading.selector || opts.contentSelector; 23446 23447 // Define loading.msg 23448 opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>'); 23449 23450 // Preload loading.img 23451 (new Image()).src = opts.loading.img; 23452 23453 // distance from nav links to bottom 23454 // computed as: height of the document + top offset of container - top offset of nav link 23455 if (opts.pixelsFromNavToBottom === undefined) { 23456 opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top; 23457 this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom); 23458 } 23459 23460 var self = this; 23461 23462 // determine loading.start actions 23463 opts.loading.start = opts.loading.start || function () { 23464 $(opts.navSelector).hide(); 23465 opts.loading.msg 23466 .appendTo(opts.loading.selector) 23467 .show(opts.loading.speed, $.proxy(function () { 23468 this.beginAjax(opts); 23469 }, self)); 23470 }; 23471 23472 // determine loading.finished actions 23473 opts.loading.finished = opts.loading.finished || function () { 23474 if (!opts.state.isBeyondMaxPage) 23475 opts.loading.msg.fadeOut(opts.loading.speed); 23476 }; 23477 23478 // callback loading 23479 opts.callback = function (instance, data, url) { 23480 if (!!opts.behavior && instance['_callback_' + opts.behavior] !== undefined) { 23481 instance['_callback_' + opts.behavior].call($(opts.contentSelector)[0], data, url); 23482 } 23483 23484 if (callback) { 23485 callback.call($(opts.contentSelector)[0], data, opts, url); 23486 } 23487 23488 if (opts.prefill) { 23489 $window.bind('resize.infinite-scroll', instance._prefill); 23490 } 23491 }; 23492 23493 if (options.debug) { 23494 // Tell IE9 to use its built-in console 23495 if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') { 23496 ['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd'] 23497 .forEach(function (method) { 23498 console[method] = this.call(console[method], console); 23499 }, Function.prototype.bind); 23500 } 23501 } 23502 23503 this._setup(); 23504 23505 // Setups the prefill method for use 23506 if (opts.prefill) { 23507 this._prefill(); 23508 } 23509 23510 // Return true to indicate successful creation 23511 return true; 23512 }, 23513 23514 _prefill: function infscr_prefill() { 23515 var instance = this; 23516 var $window = $(window); 23517 23518 function needsPrefill() { 23519 return ($(instance.options.contentSelector).height() <= $window.height()); 23520 } 23521 23522 this._prefill = function () { 23523 if (needsPrefill()) { 23524 instance.scroll(); 23525 } 23526 23527 $window.bind('resize.infinite-scroll', function () { 23528 if (needsPrefill()) { 23529 $window.unbind('resize.infinite-scroll'); 23530 instance.scroll(); 23531 } 23532 }); 23533 }; 23534 23535 // Call self after setting up the new function 23536 this._prefill(); 23537 }, 23538 23539 // Console log wrapper 23540 _debug: function infscr_debug() { 23541 if (true !== this.options.debug) { 23542 return; 23543 } 23544 23545 if (typeof console !== 'undefined' && typeof console.log === 'function') { 23546 // Modern browsers 23547 // Single argument, which is a string 23548 if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') { 23549 console.log((Array.prototype.slice.call(arguments)).toString()); 23550 } else { 23551 console.log(Array.prototype.slice.call(arguments)); 23552 } 23553 } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') { 23554 // IE8 23555 Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments)); 23556 } 23557 }, 23558 23559 // find the number to increment in the path.
23560 _determinepath: function infscr_determinepath(path) { 23561 23562 var opts = this.options; 23563 23564 // if behavior is defined and this function is extended, call that instead of default 23565 if (!!opts.behavior && this['_determinepath_' + opts.behavior] !== undefined) { 23566 return this['_determinepath_' + opts.behavior].call(this, path); 23567 } 23568 23569 var url = new URL(path); 23570 var pathname = url.pathname; 23571 var hasNumber = /\d/.test(pathname); 23572 23573 if (!!opts.pathParse) { 23574 this._debug('pathParse manual'); 23575 return opts.pathParse(path, this.options.state.currPage + 1); 23576 } else if (hasNumber && path.match(/(\?|\&)(upage=)(\d+)/)) { 23577 var parts = path.split(/(\?|\&)(upage=)(\d+)/); 23578 return [parts[0] + parts[1] + parts[2], parts[4]]; 23579 } else if (path.match(/^(.*?)\b2\b(.*?$)/)) { 23580 path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 23581 23582 // if there is any 2 in the url at all. 23583 } else if (path.match(/^(.*?)2(.*?$)/)) { 23584 // page= is used in django: 23585 // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127 23586 if (path.match(/^(.*?page=)2(\/.*|$)/)) { 23587 path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 23588 return path; 23589 } 23590 23591 path = path.match(/^(.*?)2(.*?$)/).slice(1); 23592 23593 } else { 23594 // page= is used in drupal too but second page is page=1 not page=2: 23595 // thx Jerod Fritz, vladikoff 23596 if (path.match(/^(.*?page=)1(\/.*|$)/)) { 23597 path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 23598 return path; 23599 } else { 23600 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."); 23601 // Get rid of isInvalidPage to allow permalink to state 23602 opts.state.isInvalidPage = true; //prevent it from running on this page. 23603 } 23604 } 23605 this._debug('determinePath', path); 23606 return path; 23607 23608 }, 23609 23610 // Custom error 23611 _error: function infscr_error(xhr) { 23612 23613 var opts = this.options; 23614 23615 // if behavior is defined and this function is extended, call that instead of default 23616 if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) { 23617 this['_error_'+opts.behavior].call(this,xhr); 23618 return; 23619 } 23620 23621 if (xhr !== 'destroy' && xhr !== 'end') { 23622 xhr = 'unknown'; 23623 } 23624 23625 this._debug('Error', xhr); 23626 23627 if (xhr === 'end' || opts.state.isBeyondMaxPage) { 23628 this._showdonemsg(); 23629 } 23630 23631 opts.state.isDone = true; 23632 opts.state.currPage = 1; // if you need to go back to this instance 23633 opts.state.isPaused = false; 23634 opts.state.isBeyondMaxPage = false; 23635 this._binding('unbind'); 23636 23637 }, 23638 23639 // Load Callback 23640 _loadcallback: function infscr_loadcallback(box, data, url) { 23641 var opts = this.options, 23642 callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK 23643 result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append', 23644 frag; 23645 23646 // if behavior is defined and this function is extended, call that instead of default 23647 if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) { 23648 this['_loadcallback_'+opts.behavior].call(this,box,data); 23649 return; 23650 } 23651 23652 switch (result) { 23653 case 'done': 23654 this._showdonemsg(); 23655 return false; 23656 23657 case 'no-append': 23658 if (opts.dataType === 'html') { 23659 data = '<div>' + data + '</div>'; 23660 data = $(data).find(opts.itemSelector); 23661 } 23662 23663 // if it didn't return anything 23664 if (data.length === 0) { 23665 return this._error('end'); 23666 } 23667 23668 break; 23669 23670 case 'append': 23671 var children = box.children(); 23672 // if it didn't return anything 23673 if (children.length === 0) { 23674 return this._error('end'); 23675 } 23676 23677 // use a documentFragment because it works when content is going into a table or UL 23678 frag = document.createDocumentFragment(); 23679 while (box[0].firstChild) { 23680 frag.appendChild(box[0].firstChild); 23681 } 23682 23683 this._debug('contentSelector', $(opts.contentSelector)[0]); 23684 $(opts.contentSelector)[0].appendChild(frag); 23685 // previously, we would pass in the new DOM element as context for the callback 23686 // however we're now using a documentfragment, which doesn't have parents or children, 23687 // so the context is the contentContainer guy, and we pass in an array 23688 // of the elements collected as the first argument. 23689 23690 data = children.get(); 23691 break; 23692 } 23693 23694 // loadingEnd function 23695 opts.loading.finished.call($(opts.contentSelector)[0],opts); 23696 23697 // smooth scroll to ease in the new content 23698 if (opts.animate) { 23699 var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px'; 23700 $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; }); 23701 } 23702 23703 if (!opts.animate) { 23704 // once the call is done, we can allow it again. 23705 opts.state.isDuringAjax = false;
23706 } 23707 23708 callback(this, data, url); 23709 23710 if (opts.prefill) { 23711 this._prefill(); 23712 } 23713 }, 23714 23715 _nearbottom: function infscr_nearbottom() { 23716 23717 var opts = this.options, 23718 pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height(); 23719 23720 // if behavior is defined and this function is extended, call that instead of default 23721 if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) { 23722 return this['_nearbottom_'+opts.behavior].call(this); 23723 } 23724 23725 this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom); 23726 23727 // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom.... 23728 return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom); 23729 23730 }, 23731 23732 // Pause / temporarily disable plugin from firing 23733 _pausing: function infscr_pausing(pause) { 23734 23735 var opts = this.options; 23736 23737 // if behavior is defined and this function is extended, call that instead of default 23738 if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) { 23739 this['_pausing_'+opts.behavior].call(this,pause); 23740 return; 23741 } 23742 23743 // If pause is not 'pause' or 'resume', toggle it's value 23744 if (pause !== 'pause' && pause !== 'resume' && pause !== null) { 23745 this._debug('Invalid argument. Toggling pause value instead'); 23746 } 23747 23748 pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle'; 23749 23750 switch (pause) { 23751 case 'pause': 23752 opts.state.isPaused = true; 23753 break; 23754 23755 case 'resume': 23756 opts.state.isPaused = false; 23757 break; 23758 23759 case 'toggle': 23760 opts.state.isPaused = !opts.state.isPaused; 23761 break; 23762 } 23763 23764 this._debug('Paused', opts.state.isPaused); 23765 return false; 23766 23767 }, 23768 23769 // Behavior is determined 23770 // If the behavior option is undefined, it will set to default and bind to scroll 23771 _setup: function infscr_setup() { 23772 23773 var opts = this.options; 23774 23775 // if behavior is defined and this function is extended, call that instead of default 23776 if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) { 23777 this['_setup_'+opts.behavior].call(this); 23778 return; 23779 } 23780 23781 this._binding('bind'); 23782 23783 return false; 23784 23785 }, 23786 23787 // Show done message 23788 _showdonemsg: function infscr_showdonemsg() { 23789 23790 var opts = this.options; 23791 23792 // if behavior is defined and this function is extended, call that instead of default 23793 if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) { 23794 this['_showdonemsg_'+opts.behavior].call(this); 23795 return; 23796 } 23797 23798 opts.loading.msg 23799 .find('img') 23800 .hide() 23801 .parent() 23802 .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () { 23803 $(this).parent().fadeOut(opts.loading.speed); 23804 }); 23805 23806 // user provided callback when done 23807 opts.errorCallback.call($(opts.contentSelector)[0],'done'); 23808 }, 23809 23810 // grab each selector option and see if any fail 23811 _validate: function infscr_validate(opts) { 23812 for (var key in opts) { 23813 if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) { 23814 this._debug('Your ' + key + ' found no elements.'); 23815 return false; 23816 } 23817 } 23818 23819 return true; 23820 }, 23821 23822 /* 23823 ---------------------------- 23824 Public methods 23825 ---------------------------- 23826 */ 23827 23828 // Bind to scroll 23829 bind: function infscr_bind() { 23830 this._binding('bind'); 23831 }, 23832 23833 // Destroy current instance of plugin 23834 destroy: function infscr_destroy() { 23835 this.options.state.isDestroyed = true; 23836 this.options.loading.finished(); 23837 return this._error('destroy'); 23838 }, 23839 23840 // Set pause value to false 23841 pause: function infscr_pause() { 23842 this._pausing('pause'); 23843 }, 23844 23845 // Set pause value to false 23846 resume: function infscr_resume() { 23847 this._pausing('resume'); 23848 }, 23849 23850 beginAjax: function infscr_ajax(opts) { 23851 var instance = this, 23852 path = opts.path, 23853 box, desturl, method, condition; 23854 23855 // increment the URL bit. e.g. /page/3/ 23856 opts.state.currPage++; 23857 23858 // Manually control maximum page 23859 if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){ 23860 opts.state.isBeyondMaxPage = true; 23861 this.destroy(); 23862 return; 23863 } 23864 23865 // if we're dealing with a table we can't use DIVs 23866 box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>'); 23867 23868 desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage); 23869 23870 instance._debug('heading into ajax', desturl); 23871 23872 method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback'; 23873 if (opts.appendCallback && opts.dataType === 'html') { 23874 method += '+callback'; 23875 } 23876 23877 switch (method) { 23878 case 'html+callback': 23879 instance._debug('Using HTML via .load() method'); 23880 box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) { 23881 instance._loadcallback(box, responseText, desturl); 23882 }); 23883 23884 break; 23885 23886 case 'html': 23887 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 23888 $.ajax({ 23889 // params 23890 url: desturl, 23891 dataType: opts.dataType, 23892 complete: function infscr_ajax_callback(jqXHR, textStatus) { 23893 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 23894 if (condition) { 23895 instance._loadcallback(box, jqXHR.responseText, desturl); 23896 } else { 23897 instance._error('end'); 23898 } 23899 } 23900 }); 23901 23902 break; 23903 case 'json': 23904 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 23905 $.ajax({ 23906 dataType: 'json', 23907 type: 'GET', 23908 url: desturl, 23909 success: function (data, textStatus, jqXHR) { 23910 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 23911 if (opts.appendCallback) { 23912 // if appendCallback is true, you must defined template in options. 23913 // note that data passed into _loadcallback is already an html (after processed in opts.template(data)). 23914 if (opts.template !== undefined) { 23915 var theData = opts.template(data); 23916 box.append(theData); 23917 if (condition) { 23918 instance._loadcallback(box, theData); 23919 } else { 23920 instance._error('end'); 23921 } 23922 } else { 23923 instance._debug('template must be defined.'); 23924 instance._error('end'); 23925 } 23926 } else { 23927 // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback. 23928 if (condition) { 23929 instance._loadcallback(box, data, desturl); 23930 } else { 23931 instance._error('end'); 23932 } 23933 } 23934 }, 23935 error: function() { 23936 instance._debug('JSON ajax request failed.'); 23937 instance._error('end'); 23938 } 23939 }); 23940 23941 break; 23942 } 23943 }, 23944 23945 // Retrieve next set of content items 23946 retrieve: function infscr_retrieve(pageNum) { 23947 pageNum = pageNum || null; 23948 23949 var instance = this, 23950 opts = instance.options; 23951 23952 // if behavior is defined and this function is extended, call that instead of default 23953 if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) { 23954 this['retrieve_'+opts.behavior].call(this,pageNum); 23955 return; 23956 } 23957 23958 // for manual triggers, if destroyed, get out of here 23959 if (opts.state.isDestroyed) { 23960 this._debug('Instance is destroyed'); 23961 return false;
23962 } 23963 23964 // we dont want to fire the ajax multiple times 23965 opts.state.isDuringAjax = true; 23966 23967 opts.loading.start.call($(opts.contentSelector)[0],opts); 23968 }, 23969 23970 // Check to see next page is needed 23971 scroll: function infscr_scroll() { 23972 23973 var opts = this.options, 23974 state = opts.state; 23975 23976 // if behavior is defined and this function is extended, call that instead of default 23977 if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) { 23978 this['scroll_'+opts.behavior].call(this); 23979 return; 23980 } 23981 23982 if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) { 23983 return; 23984 } 23985 23986 if (!this._nearbottom()) { 23987 return; 23988 } 23989 23990 this.retrieve(); 23991 23992 }, 23993 23994 // Toggle pause value 23995 toggle: function infscr_toggle() { 23996 this._pausing(); 23997 }, 23998 23999 // Unbind from scroll 24000 unbind: function infscr_unbind() { 24001 this._binding('unbind'); 24002 }, 24003 24004 // update options 24005 update: function infscr_options(key) { 24006 if ($.isPlainObject(key)) { 24007 this.options = $.extend(true,this.options,key); 24008 } 24009 } 24010 }; 24011 24012 24013 /* 24014 ---------------------------- 24015 Infinite Scroll function 24016 ---------------------------- 24017 24018 Borrowed logic from the following... 24019 24020 jQuery UI 24021 - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js 24022 24023 jCarousel 24024 - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js 24025 24026 Masonry 24027 - https://github.com/desandro/masonry/blob/master/jquery.masonry.js 24028 24029*/ 24030 24031 $.fn.infinitescroll = function infscr_init(options, callback) { 24032 24033 24034 var thisCall = typeof options; 24035 24036 switch (thisCall) { 24037 24038 // method 24039 case 'string': 24040 var args = Array.prototype.slice.call(arguments, 1); 24041 24042 this.each(function () { 24043 var instance = $.data(this, 'infinitescroll'); 24044 24045 if (!instance) { 24046 // not setup yet 24047 // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup'); 24048 return false; 24049 } 24050 24051 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') { 24052 // return $.error('No such method ' + options + ' for Infinite Scroll'); 24053 return false; 24054 } 24055 24056 // no errors! 24057 instance[options].apply(instance, args); 24058 }); 24059 24060 break; 24061 24062 // creation 24063 case 'object': 24064 24065 this.each(function () { 24066 24067 var instance = $.data(this, 'infinitescroll'); 24068 24069 if (instance) { 24070 24071 // update options of current instance 24072 instance.update(options); 24073 24074 } else { 24075 24076 // initialize new instance 24077 instance = new $.infinitescroll(options, callback, this); 24078 24079 // don't attach if instantiation failed 24080 if (!instance.failed) { 24081 $.data(this, 'infinitescroll', instance); 24082 } 24083 24084 } 24085 24086 }); 24087 24088 break; 24089 24090 } 24091 24092 return this; 24093 }; 24094 24095 24096 24097 /* 24098 * smartscroll: debounced scroll event for jQuery * 24099 * https://github.com/lukeshumard/smartscroll 24100 * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js * 24101 * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. * 24102 */ 24103 24104 var event = $.event, 24105 scrollTimeout; 24106 24107 event.special.smartscroll = { 24108 setup: function () { 24109 $(this).bind('scroll', event.special.smartscroll.handler); 24110 }, 24111 teardown: function () { 24112 $(this).unbind('scroll', event.special.smartscroll.handler); 24113 }, 24114 handler: function (event, execAsap) { 24115 // Save the context 24116 var context = this, 24117 args = arguments; 24118 24119 // set correct event type 24120 event.type = 'smartscroll'; 24121 24122 if (scrollTimeout) { clearTimeout(scrollTimeout); } 24123 scrollTimeout = setTimeout(function () { 24124 $(context).trigger('smartscroll', args); 24125 }, execAsap === 'execAsap' ? 0 : 100); 24126 } 24127 }; 24128 24129 $.fn.smartscroll = function (fn) {
24130 return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']); 24131 }; 24132 24133})); 24134 24135/*! 24136Waypoints - 4.0.1 24137Copyright © 2011-2016 Caleb Troughton 24138Licensed under the MIT license. 24139https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 24140*/ 24141(function() { 24142 'use strict' 24143 24144 var keyCounter = 0 24145 var allWaypoints = {} 24146 24147 /* http://imakewebthings.com/waypoints/api/waypoint */ 24148 function Waypoint(options) { 24149 if (!options) { 24150 throw new Error('No options passed to Waypoint constructor') 24151 } 24152 if (!options.element) { 24153 throw new Error('No element option passed to Waypoint constructor') 24154 } 24155 if (!options.handler) { 24156 throw new Error('No handler option passed to Waypoint constructor') 24157 } 24158 24159 this.key = 'waypoint-' + keyCounter 24160 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 24161 this.element = this.options.element 24162 this.adapter = new Waypoint.Adapter(this.element) 24163 this.callback = options.handler 24164 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 24165 this.enabled = this.options.enabled 24166 this.triggerPoint = null 24167 this.group = Waypoint.Group.findOrCreate({ 24168 name: this.options.group, 24169 axis: this.axis 24170 }) 24171 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 24172 24173 if (Waypoint.offsetAliases[this.options.offset]) { 24174 this.options.offset = Waypoint.offsetAliases[this.options.offset] 24175 } 24176 this.group.add(this) 24177 this.context.add(this) 24178 allWaypoints[this.key] = this 24179 keyCounter += 1 24180 } 24181 24182 /* Private */ 24183 Waypoint.prototype.queueTrigger = function(direction) { 24184 this.group.queueTrigger(this, direction) 24185 } 24186 24187 /* Private */ 24188 Waypoint.prototype.trigger = function(args) { 24189 if (!this.enabled) { 24190 return 24191 } 24192 if (this.callback) { 24193 this.callback.apply(this, args) 24194 } 24195 } 24196 24197 /* Public */ 24198 /* http://imakewebthings.com/waypoints/api/destroy */ 24199 Waypoint.prototype.destroy = function() { 24200 this.context.remove(this) 24201 this.group.remove(this) 24202 delete allWaypoints[this.key] 24203 } 24204 24205 /* Public */ 24206 /* http://imakewebthings.com/waypoints/api/disable */ 24207 Waypoint.prototype.disable = function() { 24208 this.enabled = false 24209 return this 24210 } 24211 24212 /* Public */ 24213 /* http://imakewebthings.com/waypoints/api/enable */ 24214 Waypoint.prototype.enable = function() { 24215 this.context.refresh() 24216 this.enabled = true 24217 return this 24218 } 24219 24220 /* Public */ 24221 /* http://imakewebthings.com/waypoints/api/next */ 24222 Waypoint.prototype.next = function() { 24223 return this.group.next(this) 24224 } 24225 24226 /* Public */ 24227 /* http://imakewebthings.com/waypoints/api/previous */ 24228 Waypoint.prototype.previous = function() { 24229 return this.group.previous(this) 24230 } 24231 24232 /* Private */ 24233 Waypoint.invokeAll = function(method) { 24234 var allWaypointsArray = []
24235 for (var waypointKey in allWaypoints) { 24236 allWaypointsArray.push(allWaypoints[waypointKey]) 24237 } 24238 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 24239 allWaypointsArray[i][method]() 24240 } 24241 } 24242 24243 /* Public */ 24244 /* http://imakewebthings.com/waypoints/api/destroy-all */ 24245 Waypoint.destroyAll = function() { 24246 Waypoint.invokeAll('destroy') 24247 } 24248 24249 /* Public */ 24250 /* http://imakewebthings.com/waypoints/api/disable-all */ 24251 Waypoint.disableAll = function() { 24252 Waypoint.invokeAll('disable') 24253 } 24254 24255 /* Public */ 24256 /* http://imakewebthings.com/waypoints/api/enable-all */ 24257 Waypoint.enableAll = function() { 24258 Waypoint.Context.refreshAll() 24259 for (var waypointKey in allWaypoints) { 24260 allWaypoints[waypointKey].enabled = true 24261 } 24262 return this 24263 } 24264 24265 /* Public */ 24266 /* http://imakewebthings.com/waypoints/api/refresh-all */ 24267 Waypoint.refreshAll = function() { 24268 Waypoint.Context.refreshAll() 24269 } 24270 24271 /* Public */ 24272 /* http://imakewebthings.com/waypoints/api/viewport-height */ 24273 Waypoint.viewportHeight = function() { 24274 return window.innerHeight || document.documentElement.clientHeight 24275 } 24276 24277 /* Public */ 24278 /* http://imakewebthings.com/waypoints/api/viewport-width */ 24279 Waypoint.viewportWidth = function() { 24280 return document.documentElement.clientWidth 24281 } 24282 24283 Waypoint.adapters = [] 24284 24285 Waypoint.defaults = { 24286 context: window, 24287 continuous: true, 24288 enabled: true, 24289 group: 'default', 24290 horizontal: false, 24291 offset: 0 24292 } 24293 24294 Waypoint.offsetAliases = { 24295 'bottom-in-view': function() { 24296 return this.context.innerHeight() - this.adapter.outerHeight() 24297 }, 24298 'right-in-view': function() { 24299 return this.context.innerWidth() - this.adapter.outerWidth() 24300 } 24301 } 24302 24303 window.Waypoint = Waypoint 24304}()) 24305;(function() { 24306 'use strict' 24307 24308 function requestAnimationFrameShim(callback) { 24309 window.setTimeout(callback, 1000 / 60) 24310 } 24311 24312 var keyCounter = 0 24313 var contexts = {} 24314 var Waypoint = window.Waypoint 24315 var oldWindowLoad = window.onload 24316 24317 /* http://imakewebthings.com/waypoints/api/context */ 24318 function Context(element) { 24319 this.element = element 24320 this.Adapter = Waypoint.Adapter 24321 this.adapter = new this.Adapter(element) 24322 this.key = 'waypoint-context-' + keyCounter 24323 this.didScroll = false 24324 this.didResize = false 24325 this.oldScroll = { 24326 x: this.adapter.scrollLeft(), 24327 y: this.adapter.scrollTop() 24328 } 24329 this.waypoints = { 24330 vertical: {}, 24331 horizontal: {} 24332 } 24333 24334 element.waypointContextKey = this.key 24335 contexts[element.waypointContextKey] = this 24336 keyCounter += 1 24337 if (!Waypoint.windowContext) { 24338 Waypoint.windowContext = true 24339 Waypoint.windowContext = new Context(window) 24340 } 24341 24342 this.createThrottledScrollHandler() 24343 this.createThrottledResizeHandler() 24344 } 24345 24346 /* Private */ 24347 Context.prototype.add = function(waypoint) { 24348 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 24349 this.waypoints[axis][waypoint.key] = waypoint 24350 this.refresh() 24351 } 24352 24353 /* Private */ 24354 Context.prototype.checkEmpty = function() { 24355 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 24356 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 24357 var isWindow = this.element == this.element.window 24358 if (horizontalEmpty && verticalEmpty && !isWindow) { 24359 this.adapter.off('.waypoints') 24360 delete contexts[this.key] 24361 } 24362 } 24363 24364 /* Private */ 24365 Context.prototype.createThrottledResizeHandler = function() { 24366 var self = this 24367 24368 function resizeHandler() { 24369 self.handleResize() 24370 self.didResize = false 24371 } 24372 24373 this.adapter.on('resize.waypoints', function() { 24374 if (!self.didResize) { 24375 self.didResize = true 24376 Waypoint.requestAnimationFrame(resizeHandler) 24377 } 24378 }) 24379 } 24380 24381 /* Private */ 24382 Context.prototype.createThrottledScrollHandler = function() { 24383 var self = this 24384 function scrollHandler() { 24385 self.handleScroll() 24386 self.didScroll = false 24387 } 24388 24389 this.adapter.on('scroll.waypoints', function() { 24390 if (!self.didScroll || Waypoint.isTouch) { 24391 self.didScroll = true 24392 Waypoint.requestAnimationFrame(scrollHandler) 24393 } 24394 }) 24395 } 24396 24397 /* Private */ 24398 Context.prototype.handleResize = function() { 24399 Waypoint.Context.refreshAll() 24400 } 24401 24402 /* Private */ 24403 Context.prototype.handleScroll = function() { 24404 var triggeredGroups = {} 24405 var axes = { 24406 horizontal: { 24407 newScroll: this.adapter.scrollLeft(), 24408 oldScroll: this.oldScroll.x, 24409 forward: 'right', 24410 backward: 'left' 24411 }, 24412 vertical: { 24413 newScroll: this.adapter.scrollTop(), 24414 oldScroll: this.oldScroll.y, 24415 forward: 'down', 24416 backward: 'up' 24417 } 24418 } 24419 24420 for (var axisKey in axes) { 24421 var axis = axes[axisKey] 24422 var isForward = axis.newScroll > axis.oldScroll 24423 var direction = isForward ? axis.forward : axis.backward 24424
24425 for (var waypointKey in this.waypoints[axisKey]) { 24426 var waypoint = this.waypoints[axisKey][waypointKey] 24427 if (waypoint.triggerPoint === null) { 24428 continue 24429 } 24430 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 24431 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 24432 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 24433 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 24434 if (crossedForward || crossedBackward) { 24435 waypoint.queueTrigger(direction) 24436 triggeredGroups[waypoint.group.id] = waypoint.group 24437 } 24438 } 24439 } 24440 24441 for (var groupKey in triggeredGroups) { 24442 triggeredGroups[groupKey].flushTriggers() 24443 } 24444 24445 this.oldScroll = { 24446 x: axes.horizontal.newScroll, 24447 y: axes.vertical.newScroll 24448 } 24449 } 24450 24451 /* Private */ 24452 Context.prototype.innerHeight = function() { 24453 /*eslint-disable eqeqeq */ 24454 if (this.element == this.element.window) { 24455 return Waypoint.viewportHeight() 24456 } 24457 /*eslint-enable eqeqeq */ 24458 return this.adapter.innerHeight() 24459 } 24460 24461 /* Private */ 24462 Context.prototype.remove = function(waypoint) { 24463 delete this.waypoints[waypoint.axis][waypoint.key] 24464 this.checkEmpty() 24465 } 24466 24467 /* Private */ 24468 Context.prototype.innerWidth = function() { 24469 /*eslint-disable eqeqeq */ 24470 if (this.element == this.element.window) { 24471 return Waypoint.viewportWidth() 24472 } 24473 /*eslint-enable eqeqeq */ 24474 return this.adapter.innerWidth() 24475 } 24476 24477 /* Public */ 24478 /* http://imakewebthings.com/waypoints/api/context-destroy */ 24479 Context.prototype.destroy = function() { 24480 var allWaypoints = [] 24481 for (var axis in this.waypoints) {
24482 for (var waypointKey in this.waypoints[axis]) { 24483 allWaypoints.push(this.waypoints[axis][waypointKey]) 24484 } 24485 } 24486 for (var i = 0, end = allWaypoints.length; i < end; i++) { 24487 allWaypoints[i].destroy() 24488 } 24489 } 24490 24491 /* Public */ 24492 /* http://imakewebthings.com/waypoints/api/context-refresh */ 24493 Context.prototype.refresh = function() { 24494 /*eslint-disable eqeqeq */ 24495 var isWindow = this.element == this.element.window 24496 /*eslint-enable eqeqeq */ 24497 var contextOffset = isWindow ? undefined : this.adapter.offset() 24498 var triggeredGroups = {} 24499 var axes 24500 24501 this.handleScroll() 24502 axes = { 24503 horizontal: { 24504 contextOffset: isWindow ? 0 : contextOffset.left, 24505 contextScroll: isWindow ? 0 : this.oldScroll.x, 24506 contextDimension: this.innerWidth(), 24507 oldScroll: this.oldScroll.x, 24508 forward: 'right', 24509 backward: 'left', 24510 offsetProp: 'left' 24511 }, 24512 vertical: { 24513 contextOffset: isWindow ? 0 : contextOffset.top, 24514 contextScroll: isWindow ? 0 : this.oldScroll.y, 24515 contextDimension: this.innerHeight(), 24516 oldScroll: this.oldScroll.y, 24517 forward: 'down', 24518 backward: 'up', 24519 offsetProp: 'top' 24520 } 24521 } 24522 24523 for (var axisKey in axes) { 24524 var axis = axes[axisKey]
24525 for (var waypointKey in this.waypoints[axisKey]) { 24526 var waypoint = this.waypoints[axisKey][waypointKey] 24527 var adjustment = waypoint.options.offset 24528 var oldTriggerPoint = waypoint.triggerPoint 24529 var elementOffset = 0 24530 var freshWaypoint = oldTriggerPoint == null 24531 var contextModifier, wasBeforeScroll, nowAfterScroll 24532 var triggeredBackward, triggeredForward 24533 24534 if (waypoint.element !== waypoint.element.window) { 24535 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 24536 } 24537 24538 if (typeof adjustment === 'function') { 24539 adjustment = adjustment.apply(waypoint) 24540 } 24541 else if (typeof adjustment === 'string') { 24542 adjustment = parseFloat(adjustment) 24543 if (waypoint.options.offset.indexOf('%') > - 1) { 24544 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 24545 } 24546 } 24547 24548 contextModifier = axis.contextScroll - axis.contextOffset 24549 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 24550 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 24551 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 24552 triggeredBackward = wasBeforeScroll && nowAfterScroll 24553 triggeredForward = !wasBeforeScroll && !nowAfterScroll 24554 24555 if (!freshWaypoint && triggeredBackward) { 24556 waypoint.queueTrigger(axis.backward) 24557 triggeredGroups[waypoint.group.id] = waypoint.group 24558 } 24559 else if (!freshWaypoint && triggeredForward) { 24560 waypoint.queueTrigger(axis.forward) 24561 triggeredGroups[waypoint.group.id] = waypoint.group 24562 } 24563 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 24564 waypoint.queueTrigger(axis.forward) 24565 triggeredGroups[waypoint.group.id] = waypoint.group 24566 } 24567 } 24568 } 24569 24570 Waypoint.requestAnimationFrame(function() { 24571 for (var groupKey in triggeredGroups) { 24572 triggeredGroups[groupKey].flushTriggers() 24573 } 24574 }) 24575 24576 return this 24577 } 24578 24579 /* Private */ 24580 Context.findOrCreateByElement = function(element) { 24581 return Context.findByElement(element) || new Context(element) 24582 } 24583 24584 /* Private */ 24585 Context.refreshAll = function() { 24586 for (var contextId in contexts) { 24587 contexts[contextId].refresh() 24588 } 24589 } 24590 24591 /* Public */ 24592 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 24593 Context.findByElement = function(element) { 24594 return contexts[element.waypointContextKey] 24595 } 24596 24597 window.onload = function() { 24598 if (oldWindowLoad) { 24599 oldWindowLoad() 24600 } 24601 Context.refreshAll() 24602 } 24603 24604 24605 Waypoint.requestAnimationFrame = function(callback) { 24606 var requestFn = window.requestAnimationFrame || 24607 window.mozRequestAnimationFrame || 24608 window.webkitRequestAnimationFrame || 24609 requestAnimationFrameShim 24610 requestFn.call(window, callback) 24611 } 24612 Waypoint.Context = Context 24613}()) 24614;(function() { 24615 'use strict' 24616 24617 function byTriggerPoint(a, b) { 24618 return a.triggerPoint - b.triggerPoint 24619 } 24620 24621 function byReverseTriggerPoint(a, b) { 24622 return b.triggerPoint - a.triggerPoint 24623 } 24624 24625 var groups = { 24626 vertical: {}, 24627 horizontal: {} 24628 } 24629 var Waypoint = window.Waypoint 24630 24631 /* http://imakewebthings.com/waypoints/api/group */ 24632 function Group(options) { 24633 this.name = options.name 24634 this.axis = options.axis 24635 this.id = this.name + '-' + this.axis 24636 this.waypoints = [] 24637 this.clearTriggerQueues() 24638 groups[this.axis][this.name] = this 24639 } 24640 24641 /* Private */ 24642 Group.prototype.add = function(waypoint) { 24643 this.waypoints.push(waypoint) 24644 } 24645 24646 /* Private */ 24647 Group.prototype.clearTriggerQueues = function() { 24648 this.triggerQueues = { 24649 up: [], 24650 down: [], 24651 left: [], 24652 right: [] 24653 } 24654 } 24655 24656 /* Private */ 24657 Group.prototype.flushTriggers = function() { 24658 for (var direction in this.triggerQueues) { 24659 var waypoints = this.triggerQueues[direction] 24660 var reverse = direction === 'up' || direction === 'left' 24661 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 24662 for (var i = 0, end = waypoints.length; i < end; i += 1) { 24663 var waypoint = waypoints[i] 24664 if (waypoint.options.continuous || i === waypoints.length - 1) { 24665 waypoint.trigger([direction]) 24666 } 24667 } 24668 } 24669 this.clearTriggerQueues() 24670 } 24671 24672 /* Private */ 24673 Group.prototype.next = function(waypoint) { 24674 this.waypoints.sort(byTriggerPoint) 24675 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 24676 var isLast = index === this.waypoints.length - 1 24677 return isLast ? null : this.waypoints[index + 1] 24678 } 24679 24680 /* Private */ 24681 Group.prototype.previous = function(waypoint) { 24682 this.waypoints.sort(byTriggerPoint) 24683 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 24684 return index ? this.waypoints[index - 1] : null 24685 } 24686 24687 /* Private */ 24688 Group.prototype.queueTrigger = function(waypoint, direction) { 24689 this.triggerQueues[direction].push(waypoint) 24690 } 24691 24692 /* Private */ 24693 Group.prototype.remove = function(waypoint) { 24694 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 24695 if (index > -1) { 24696 this.waypoints.splice(index, 1) 24697 } 24698 } 24699 24700 /* Public */ 24701 /* http://imakewebthings.com/waypoints/api/first */ 24702 Group.prototype.first = function() { 24703 return this.waypoints[0] 24704 } 24705 24706 /* Public */ 24707 /* http://imakewebthings.com/waypoints/api/last */ 24708 Group.prototype.last = function() { 24709 return this.waypoints[this.waypoints.length - 1] 24710 } 24711 24712 /* Private */ 24713 Group.findOrCreate = function(options) { 24714 return groups[options.axis][options.name] || new Group(options) 24715 } 24716 24717 Waypoint.Group = Group 24718}()) 24719;(function() { 24720 'use strict' 24721 24722 var $ = window.jQuery 24723 var Waypoint = window.Waypoint 24724 24725 function JQueryAdapter(element) { 24726 this.$element = $(element) 24727 } 24728 24729 $.each([
24730 'innerHeight', 24731 'innerWidth', 24732 'off', 24733 'offset', 24734 'on', 24735 'outerHeight', 24736 'outerWidth', 24737 'scrollLeft', 24738 'scrollTop' 24739 ], function(i, method) { 24740 JQueryAdapter.prototype[method] = function() { 24741 var args = Array.prototype.slice.call(arguments) 24742 return this.$element[method].apply(this.$element, args) 24743 } 24744 }) 24745 24746 $.each([ 24747 'extend', 24748 'inArray', 24749 'isEmptyObject' 24750 ], function(i, method) { 24751 JQueryAdapter[method] = $[method] 24752 }) 24753 24754 Waypoint.adapters.push({ 24755 name: 'jquery', 24756 Adapter: JQueryAdapter 24757 }) 24758 Waypoint.Adapter = JQueryAdapter 24759}()) 24760;(function() { 24761 'use strict' 24762 24763 var Waypoint = window.Waypoint 24764 24765 function createExtension(framework) { 24766 return function() { 24767 var waypoints = [] 24768 var overrides = arguments[0] 24769 24770 if (framework.isFunction(arguments[0])) { 24771 overrides = framework.extend({}, arguments[1]) 24772 overrides.handler = arguments[0] 24773 } 24774 24775 this.each(function() { 24776 var options = framework.extend({}, overrides, { 24777 element: this 24778 }) 24779 if (typeof options.context === 'string') { 24780 options.context = framework(this).closest(options.context)[0] 24781 } 24782 waypoints.push(new Waypoint(options)) 24783 }) 24784 24785 return waypoints 24786 } 24787 } 24788 24789 if (window.jQuery) { 24790 window.jQuery.fn.waypoint = createExtension(window.jQuery) 24791 } 24792 if (window.Zepto) { 24793 window.Zepto.fn.waypoint = createExtension(window.Zepto) 24794 } 24795}()) 24796; 24797/*! 24798Waypoints Inview Shortcut - 4.0.1 24799Copyright © 2011-2016 Caleb Troughton 24800Licensed under the MIT license. 24801https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 24802*/ 24803(function() { 24804 'use strict' 24805 24806 function noop() {} 24807 24808 var Waypoint = window.Waypoint 24809 24810 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 24811 function Inview(options) { 24812 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 24813 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 24814 this.waypoints = [] 24815 this.element = this.options.element 24816 this.createWaypoints() 24817 } 24818 24819 /* Private */ 24820 Inview.prototype.createWaypoints = function() { 24821 var configs = { 24822 vertical: [{ 24823 down: 'enter', 24824 up: 'exited', 24825 offset: '100%' 24826 }, { 24827 down: 'entered', 24828 up: 'exit', 24829 offset: 'bottom-in-view' 24830 }, { 24831 down: 'exit', 24832 up: 'entered', 24833 offset: 0 24834 }, { 24835 down: 'exited', 24836 up: 'enter', 24837 offset: function() { 24838 return -this.adapter.outerHeight() 24839 } 24840 }], 24841 horizontal: [{ 24842 right: 'enter', 24843 left: 'exited', 24844 offset: '100%' 24845 }, { 24846 right: 'entered', 24847 left: 'exit', 24848 offset: 'right-in-view' 24849 }, { 24850 right: 'exit', 24851 left: 'entered', 24852 offset: 0 24853 }, { 24854 right: 'exited', 24855 left: 'enter', 24856 offset: function() { 24857 return -this.adapter.outerWidth() 24858 } 24859 }] 24860 } 24861 24862 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 24863 var config = configs[this.axis][i] 24864 this.createWaypoint(config) 24865 } 24866 } 24867 24868 /* Private */ 24869 Inview.prototype.createWaypoint = function(config) { 24870 var self = this 24871 this.waypoints.push(new Waypoint({ 24872 context: this.options.context, 24873 element: this.options.element, 24874 enabled: this.options.enabled, 24875 handler: (function(config) { 24876 return function(direction) { 24877 self.options[config[direction]].call(self, direction) 24878 } 24879 }(config)), 24880 offset: config.offset, 24881 horizontal: this.options.horizontal 24882 })) 24883 } 24884 24885 /* Public */ 24886 Inview.prototype.destroy = function() { 24887 for (var i = 0, end = this.waypoints.length; i < end; i++) { 24888 this.waypoints[i].destroy() 24889 } 24890 this.waypoints = [] 24891 } 24892 24893 Inview.prototype.disable = function() { 24894 for (var i = 0, end = this.waypoints.length; i < end; i++) { 24895 this.waypoints[i].disable() 24896 } 24897 } 24898 24899 Inview.prototype.enable = function() { 24900 for (var i = 0, end = this.waypoints.length; i < end; i++) { 24901 this.waypoints[i].enable() 24902 } 24903 } 24904 24905 Inview.defaults = { 24906 context: window, 24907 enabled: true, 24908 enter: noop, 24909 entered: noop,
24910 exit: noop, 24911 exited: noop 24912 } 24913 24914 Waypoint.Inview = Inview 24915}()) 24916; 24917 24918/* 24919 * SmartMenus jQuery v0.9.6 24920 * http://www.smartmenus.org/ 24921 * 24922 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 24923 * http://vadikom.com/ 24924 * 24925 * Released under the MIT license: 24926 * http://www.opensource.org/licenses/MIT 24927 */ 24928 24929(function($) { 24930 24931 var menuTrees = [], 24932 IE = !!window.createPopup, // we need to detect it, unfortunately 24933 IElt9 = IE && !document.defaultView, 24934 IElt8 = IE && !document.querySelector, 24935 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 24936 mouse = false, // optimize for touch by default - we will detect for mouse input 24937 mouseDetectionEnabled = false; 24938 24939 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 24940 function initMouseDetection(disable) { 24941 if (!mouseDetectionEnabled && !disable) { 24942 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 24943 // 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) 24944 var firstTime = true, 24945 lastMove = null; 24946 $(document).bind({ 24947 'mousemove.smartmenus_mouse': function(e) { 24948 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 24949 if (lastMove) { 24950 var deltaX = Math.abs(lastMove.x - thisMove.x), 24951 deltaY = Math.abs(lastMove.y - thisMove.y); 24952 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 24953 mouse = true; 24954 // 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 24955 if (firstTime) { 24956 var $a = $(e.target).closest('a'); 24957 if ($a.is('a')) { 24958 $.each(menuTrees, function() { 24959 if ($.contains(this.$root[0], $a[0])) { 24960 this.itemEnter({ currentTarget: $a[0] }); 24961 return false; 24962 } 24963 }); 24964 } 24965 firstTime = false; 24966 } 24967 } 24968 } 24969 lastMove = thisMove; 24970 }, 24971 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 24972 if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) { 24973 mouse = false; 24974 } 24975 } 24976 }); 24977 mouseDetectionEnabled = true; 24978 } else if (mouseDetectionEnabled && disable) { 24979 $(document).unbind('.smartmenus_mouse'); 24980 mouseDetectionEnabled = false; 24981 } 24982 }; 24983 24984 $.SmartMenus = function(elm, options) { 24985 this.$root = $(elm); 24986 this.opts = options; 24987 this.rootId = ''; // internal 24988 this.$subArrow = null; 24989 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) 24990 this.activatedItems = []; // stores last activated A's for each level 24991 this.visibleSubMenus = []; // stores visible sub menus UL's 24992 this.showTimeout = 0; 24993 this.hideTimeout = 0; 24994 this.scrollTimeout = 0; 24995 this.clickActivated = false; 24996 this.zIndexInc = 0; 24997 this.$firstLink = null; // we'll use these for some tests 24998 this.$firstSub = null; // at runtime so we'll cache them 24999 this.disabled = false; 25000 this.$disableOverlay = null; 25001 this.lastLevel = 0; 25002 this.init(); 25003 }; 25004 25005 $.extend($.SmartMenus, { 25006 hideAll: function() { 25007 $.each(menuTrees, function() { 25008 this.menuHideAll(); 25009 }); 25010 }, 25011 destroy: function() { 25012 while (menuTrees.length) { 25013 menuTrees[0].destroy(); 25014 } 25015 initMouseDetection(true); 25016 }, 25017 prototype: { 25018 init: function(refresh) { 25019 var self = this; 25020 25021 if (!refresh) { 25022 menuTrees.push(this); 25023 25024 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 25025 25026 if (this.$root.hasClass('sm-rtl')) { 25027 this.opts.rightToLeftSubMenus = true; 25028 } 25029 25030 // init root (main menu) 25031 this.$root 25032 .data('smartmenus', this) 25033 .attr('data-smartmenus-id', this.rootId) 25034 .dataSM('level', 1) 25035 .bind({ 25036 // 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
25037 // 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 25038 'mouseover.smartmenus': $.proxy(this.rootOver, this), 25039 'mouseout.smartmenus': $.proxy(this.rootOut, this) 25040 }) 25041 .delegate('a, div.logo-container', { 25042 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 25043 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 25044 'mousedown.smartmenus': $.proxy(this.itemDown, this), 25045 'focus.smartmenus': $.proxy(this.itemFocus, this), 25046 'blur.smartmenus': $.proxy(this.itemBlur, this), 25047 'click.smartmenus': $.proxy(this.itemClick, this), 25048 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 25049 }); 25050 25051 var eNamespace = '.smartmenus' + this.rootId; 25052 // hide menus on tap or click outside the root UL 25053 if (this.opts.hideOnClick) { 25054 $(document).on('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 25055 .on('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 25056 .on('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 25057 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 25058 .on('click' + eNamespace, $.proxy(this.docClick, this)); 25059 } 25060 // hide sub menus on resize 25061 $(window).on('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 25062 var $vmenu = $('body.vmenu .vmenu-container'); 25063 if ( ! $vmenu.length && UNCODE.wwidth > UNCODE.mediaQuery ) { 25064 $(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 25065 } 25066 25067 if (this.opts.subIndicators) { 25068 this.$subArrow = $('<span/>').addClass('sub-arrow'); 25069 if (this.opts.subIndicatorsText) { 25070 this.$subArrow.html(this.opts.subIndicatorsText); 25071 } 25072 } 25073 25074 // make sure mouse detection is enabled 25075 initMouseDetection(); 25076 } 25077 25078 // init sub menus 25079 this.$firstSub = this.$root.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').each(function() { self.menuInit($(this)); }).eq(0); 25080 25081 this.$firstLink = this.$root.find('a').eq(0); 25082 25083 // find current item 25084 if (this.opts.markCurrentItem) { 25085 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 25086 reHash = /#.*/, 25087 locHref = window.location.href.replace(reDefaultDoc, ''), 25088 locHrefNoHash = locHref.replace(reHash, ''); 25089 this.$root.find('a').each(function() { 25090 var href = this.href.replace(reDefaultDoc, ''), 25091 $this = $(this); 25092 if (href == locHref || href == locHrefNoHash) { 25093 $this.addClass('current'); 25094 if (self.opts.markCurrentTree) { 25095 $this.parents('li').each(function() { 25096 var $this = $(this); 25097 if ($this.dataSM('sub')) { 25098 $this.children('a').addClass('current'); 25099 } 25100 }); 25101 } 25102 } 25103 }); 25104 } 25105 }, 25106 destroy: function() { 25107 this.menuHideAll(); 25108 this.$root 25109 .removeData('smartmenus') 25110 .removeAttr('data-smartmenus-id') 25111 .removeDataSM('level') 25112 .unbind('.smartmenus') 25113 .undelegate('.smartmenus'); 25114 var eNamespace = '.smartmenus' + this.rootId; 25115 $(document).unbind(eNamespace); 25116 $(window).unbind(eNamespace); 25117 if (this.opts.subIndicators) { 25118 this.$subArrow = null; 25119 } 25120 var self = this; 25121 $.each(this.subMenus, function() { 25122 if (this.hasClass('mega-menu')) { 25123 this.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').removeDataSM('in-mega'); 25124 } 25125 if (this.dataSM('shown-before')) { 25126 if (IElt8) { 25127 this.children().css({ styleFloat: '', width: '' }); 25128 } 25129 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 25130 if (!IE6) { 25131 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 25132 } else { 25133 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 25134 } 25135 } 25136 if (this.dataSM('scroll-arrows')) { 25137 this.dataSM('scroll-arrows').remove(); 25138 } 25139 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 25140 } 25141 if (self.opts.subIndicators) { 25142 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 25143 } 25144 this.removeDataSM('shown-before') 25145 .removeDataSM('ie-shim') 25146 .removeDataSM('scroll-arrows') 25147 .removeDataSM('parent-a') 25148 .removeDataSM('level') 25149 .removeDataSM('beforefirstshowfired') 25150 .parent().removeDataSM('sub'); 25151 }); 25152 if (this.opts.markCurrentItem) { 25153 this.$root.find('a.current').removeClass('current'); 25154 } 25155 this.$root = null; 25156 this.$firstLink = null; 25157 this.$firstSub = null; 25158 if (this.$disableOverlay) { 25159 this.$disableOverlay.remove(); 25160 this.$disableOverlay = null; 25161 } 25162 menuTrees.splice($.inArray(this, menuTrees), 1); 25163 }, 25164 disable: function(noOverlay) { 25165 if (!this.disabled) { 25166 this.menuHideAll(); 25167 // display overlay over the menu to prevent interaction 25168 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 25169 var pos = this.$root.offset(); 25170 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 25171 position: 'absolute', 25172 top: pos.top, 25173 left: pos.left, 25174 width: this.$root.outerWidth(), 25175 height: this.$root.outerHeight(),
25176 zIndex: this.getStartZIndex() + 1, 25177 opacity: 0 25178 }).appendTo(document.body); 25179 } 25180 this.disabled = true; 25181 } 25182 }, 25183 docClick: function(e) { 25184 // hide on any click outside the menu or on a menu link 25185 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a:not([data-filter])')) { 25186 this.menuHideAll($(e.target)); 25187 } 25188 }, 25189 docTouchEnd: function(e) { 25190 if (!this.lastTouch) { 25191 return; 25192 } 25193 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))) { 25194 if (this.hideTimeout) { 25195 clearTimeout(this.hideTimeout); 25196 this.hideTimeout = 0; 25197 } 25198 // hide with a delay to prevent triggering accidental unwanted click on some page element 25199 var self = this; 25200 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 25201 } 25202 this.lastTouch = null; 25203 }, 25204 docTouchMove: function(e) { 25205 if (!this.lastTouch) { 25206 return; 25207 } 25208 var touchPoint = e.originalEvent.touches[0]; 25209 this.lastTouch.x2 = touchPoint.pageX; 25210 this.lastTouch.y2 = touchPoint.pageY; 25211 }, 25212 docTouchStart: function(e) { 25213 var touchPoint = e.originalEvent.touches[0]; 25214 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 25215 }, 25216 enable: function() { 25217 if (this.disabled) { 25218 if (this.$disableOverlay) { 25219 this.$disableOverlay.remove(); 25220 this.$disableOverlay = null; 25221 } 25222 this.disabled = false; 25223 } 25224 }, 25225 getHeight: function($elm) { 25226 return this.getOffset($elm, true); 25227 }, 25228 // returns precise width/height float values in IE9+, FF4+, recent WebKit 25229 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 25230 getOffset: function($elm, height) { 25231 var old, 25232 $win = $(window), 25233 winW = $win.width(); 25234 if ($elm.css('display') == 'none') { 25235 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 25236 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 25237 if ( 25238 ($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length) 25239 || 25240 (( $('body').hasClass('vmenu-offcanvas-overlay') || $('body').hasClass('vmenu') ) && winW >= 960 && $elm.closest('.main-menu-container').length && !$elm.closest('.menu-horizontal-inner').length) 25241 ) { 25242 $elm.closest('li').addClass('smartmenu-open-item'); 25243 } 25244 } 25245 var defaultView = $elm[0].ownerDocument.defaultView, 25246 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 25247 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 25248 if (val) { 25249 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 25250 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 25251 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 25252 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 25253 } else { 25254 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 25255 } 25256 if (old) { 25257 $elm.hide().css(old); 25258 } 25259 return val; 25260 }, 25261 getWidth: function($elm) { 25262 return this.getOffset($elm); 25263 }, 25264 getStartZIndex: function() { 25265 var zIndex = parseInt(this.$root.css('z-index')); 25266 return !isNaN(zIndex) ? zIndex : 1; 25267 }, 25268 handleEvents: function() { 25269 return !this.disabled && this.isCSSOn(); 25270 }, 25271 handleItemEvents: function($a) { 25272 return this.handleEvents() && !this.isLinkInMegaMenu($a); 25273 }, 25274 isCollapsible: function() { 25275 return this.$firstSub.css('position') == 'static'; 25276 }, 25277 isCSSOn: function() { 25278 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'; 25279 }, 25280 isFixed: function() { 25281 return this.$root.css('position') == 'fixed'; 25282 }, 25283 isLinkInMegaMenu: function($a) { 25284 return !$a.parent().parent().dataSM('level'); 25285 }, 25286 isTouchMode: function() { 25287 return !mouse || this.isCollapsible(); 25288 }, 25289 itemActivate: function($a, $show) { 25290 var $li = $a.parent(), 25291 $ul = $li.parent(), 25292 level = $ul.dataSM('level'), 25293 winh = $(window).height(); 25294 // 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 25295 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 25296 var self = this; 25297 $($ul.parentsUntil('[data-smartmenus-id]', 'ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').get().reverse()).add($ul).each(function() { 25298 self.itemActivate($(this).dataSM('parent-a')); 25299 }); 25300 } 25301 // hide any visible deeper level sub menus 25302 if (this.visibleSubMenus.length > level) { 25303 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--) { 25304 this.lastLevel = level; 25305 if ( typeof $show === 'undefined' && this.isCollapsible() ) { 25306 this.menuHide(this.visibleSubMenus[i], $a); 25307 return; 25308 } else { 25309 this.menuHide(this.visibleSubMenus[i]); 25310 } 25311 } 25312 } 25313 // save new active item and sub menu for this level 25314 this.activatedItems[level - 1] = $a; 25315 this.visibleSubMenus[level - 1] = $ul; 25316 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 25317 return; 25318 } 25319 // show the sub menu if this item has one 25320 var $sub = $li.dataSM('sub'); 25321 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 25322 // if ($sub && (this.isTouchMode() || (!this.opts.showOnClick))) { 25323 var aRect = $a[0].getBoundingClientRect(); 25324 if ( (aRect.y < 0 || aRect.y > winh) && this.isCollapsible() && (this.lastLevel === this.activatedItems.length) ) { 25325 setTimeout(function(){ 25326 var currentScroll = $a.closest('.main-menu-container').scrollTop(); 25327 $a.closest('.main-menu-container').scrollTop(currentScroll + aRect.y); 25328 }, 1); 25329 } 25330 this.menuShow($sub); 25331 } 25332 }, 25333 itemBlur: function(e) { 25334 var $a = $(e.currentTarget); 25335 if (!this.handleItemEvents($a)) { 25336 return; 25337 } 25338 this.$root.triggerHandler('blur.smapi', $a[0]); 25339 }, 25340 itemClick: function(e) { 25341 var $a = $(e.currentTarget); 25342 25343 if (!this.handleItemEvents($a)) { 25344 return; 25345 } 25346 $a.removeDataSM('mousedown'); 25347 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 25348 return false;
25349 } 25350 var $sub = $a.parent().dataSM('sub'); 25351 if (this.isTouchMode()) { 25352 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 25353 if ($a.dataSM('href')) { 25354 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 25355 } 25356 // if the sub is not visible 25357 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 25358 // try to activate the item and show the sub 25359 this.itemActivate($a); 25360 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 25361 // 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 25362 if ($sub.is(':visible')) { 25363 return false; 25364 } 25365 } 25366 // } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub && !$sub.is(':visible')) { 25367 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 25368 this.clickActivated = true; 25369 this.menuShow($sub); 25370 return false; 25371 } 25372 if ($a.hasClass('disabled')) { 25373 return false; 25374 } 25375 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 25376 return false; 25377 } 25378 }, 25379 itemDown: function(e) { 25380 var $a = $(e.currentTarget); 25381 if (!this.handleItemEvents($a)) { 25382 return; 25383 } 25384 $a.dataSM('mousedown', true); 25385 }, 25386 itemEnter: function(e) { 25387 // if ( this.opts.showOnClick ) { 25388 // return 25389 // } 25390 var $a = $(e.currentTarget); 25391 if (!this.handleItemEvents($a)) { 25392 return; 25393 } 25394 if (!this.isTouchMode()) { 25395 if (this.showTimeout) { 25396 clearTimeout(this.showTimeout); 25397 this.showTimeout = 0; 25398 } 25399 var self = this; 25400 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 25401 } 25402 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 25403 }, 25404 itemFocus: function(e) { 25405 var $a = $(e.currentTarget); 25406 if (!this.handleItemEvents($a)) { 25407 return; 25408 } 25409 // 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 25410 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 25411 this.itemActivate($a); 25412 } 25413 this.$root.triggerHandler('focus.smapi', $a[0]); 25414 }, 25415 itemLeave: function(e) { 25416 // if ( this.opts.showOnClick ) { 25417 // return 25418 // } 25419 var $a = $(e.currentTarget); 25420 if (!this.handleItemEvents($a)) { 25421 return; 25422 } 25423 if (!this.isTouchMode()) { 25424 if ($a[0].blur) { 25425 $a[0].blur(); 25426 } 25427 if (this.showTimeout) { 25428 clearTimeout(this.showTimeout); 25429 this.showTimeout = 0; 25430 } 25431 } 25432 $a.removeDataSM('mousedown'); 25433 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 25434 }, 25435 itemTouchEnd: function(e) { 25436 var $a = $(e.currentTarget); 25437 if (!this.handleItemEvents($a)) { 25438 return; 25439 } 25440 // prevent the address bar on iPhone from sliding down when expanding a sub menu 25441 var $sub = $a.parent().dataSM('sub'); 25442 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 25443 $a.dataSM('href', $a.attr('href')); 25444 $a.attr('href', '#'); 25445 } 25446 }, 25447 menuFixLayout: function($ul) { 25448 // fixes a menu that is being shown for the first time 25449 if (!$ul.dataSM('shown-before')) { 25450 $ul.hide().dataSM('shown-before', true); 25451 // fix the layout of the items in IE<8 25452 if (IElt8) { 25453 $ul.children().css({ styleFloat: 'left', width: '100%' }); 25454 } 25455 } 25456 }, 25457 menuHide: function($sub, $show) { 25458 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 25459 return; 25460 } 25461 $sub.stop(true, true); 25462 if ($sub.is(':visible')) { 25463 var self = this; 25464 var complete = function() { 25465 // unset z-index 25466 if (IElt9) { 25467 $sub.parent().css('z-index', ''); 25468 } else { 25469 $sub.css('z-index', ''); 25470 } 25471 if ( typeof $show !== 'undefined' ) { 25472 self.itemActivate($show, true) 25473 } 25474 }; 25475 // if sub is collapsible (mobile view) 25476 if (this.isCollapsible()) { 25477 if (this.opts.collapsibleHideFunction) { 25478 this.opts.collapsibleHideFunction.call(this, $sub, complete); 25479 } else { 25480 $sub.hide(this.opts.collapsibleHideDuration, complete); 25481 } 25482 } else { 25483 if (this.opts.hideFunction) { 25484 this.opts.hideFunction.call(this, $sub, complete); 25485 } else { 25486 $sub.hide(this.opts.hideDuration, complete); 25487 } 25488 } 25489 // remove IE iframe shim 25490 if ($sub.dataSM('ie-shim')) { 25491 $sub.dataSM('ie-shim').remove(); 25492 } 25493 // deactivate scrolling if it is activated for this sub 25494 if ($sub.dataSM('scroll')) { 25495 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 25496 } 25497 // unhighlight parent item 25498 $sub.dataSM('parent-a').removeClass('highlighted'); 25499 var level = $sub.dataSM('level'); 25500 this.activatedItems.splice(level - 1, 1); 25501 this.visibleSubMenus.splice(level - 1, 1); 25502 this.$root.triggerHandler('hide.smapi', $sub[0]); 25503 } 25504 }, 25505 menuHideAll: function($item) { 25506 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 25507 var $win = $(window), 25508 winW = $win.width(); 25509 if (this.showTimeout) { 25510 clearTimeout(this.showTimeout); 25511 this.showTimeout = 0; 25512 } 25513 // hide all subs 25514 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 25515 if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) { 25516 if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) { 25517 this.menuHide(this.visibleSubMenus[i]); 25518 $(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item'); 25519 } else { 25520 return; 25521 } 25522 } else { 25523 //if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) { 25524 this.menuHide(this.visibleSubMenus[i]); 25525 //} 25526 } 25527 } 25528 // hide root if it's popup 25529 if (this.opts.isPopup) { 25530 this.$root.stop(true, true); 25531 if (this.$root.is(':visible')) { 25532 if (this.opts.hideFunction) { 25533 this.opts.hideFunction.call(this, this.$root); 25534 } else { 25535 this.$root.hide(this.opts.hideDuration); 25536 } 25537 // remove IE iframe shim 25538 if (this.$root.dataSM('ie-shim')) { 25539 this.$root.dataSM('ie-shim').remove(); 25540 } 25541 } 25542 } 25543 this.activatedItems = []; 25544 this.visibleSubMenus = []; 25545 this.clickActivated = false;
25546 // reset z-index increment 25547 this.zIndexInc = 0; 25548 }, 25549 menuIframeShim: function($ul) { 25550 // create iframe shim for the menu 25551 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 25552 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 25553 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 25554 ); 25555 } 25556 }, 25557 menuInit: function($ul) { 25558 if (!$ul.dataSM('in-mega')) { 25559 this.subMenus.push($ul); 25560 // mark UL's in mega drop downs (if any) so we can neglect them 25561 if ($ul.hasClass('mega-menu')) { 25562 $ul.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').dataSM('in-mega', true); 25563 } 25564 // get level (much faster than, for example, using parentsUntil) 25565 var level = 2, 25566 par = $ul[0]; 25567 while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) { 25568 level++; 25569 } 25570 // cache stuff 25571 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 25572 .dataSM('level', level) 25573 .parent().dataSM('sub', $ul); 25574 // add sub indicator to parent item 25575 if (this.opts.subIndicators) { 25576 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 25577 } 25578 } 25579 if ( $('.vc_row[data-parent].has-bg', $ul).length && !$('.vc_row[data-parent]:not(.has-bg)', $ul).length ) { 25580 $ul.addClass('has-bg-items'); 25581 } 25582 }, 25583 menuPosition: function($sub) { 25584 var fixIE = $('html.ie').length; 25585 // if (fixIE) { 25586 // var $rowParent = $($sub).closest('.main-menu-container'); 25587 // $rowParent.height($rowParent.height()); 25588 // } 25589 var $a = $sub.dataSM('parent-a'), 25590 $li = $sub.parent(), 25591 $ul = $sub.parent().parent(), 25592 // $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'), 25593 $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'), 25594 level = $sub.dataSM('level'), 25595 subW = this.getWidth($sub), 25596 subH = this.getHeight($sub), 25597 itemOffset = $a.offset(), 25598 itemX = itemOffset.left, 25599 itemY = itemOffset.top, 25600 itemW = this.getWidth($a), 25601 itemH = this.getHeight($a), 25602 $win = $(window), 25603 winX = $win.scrollLeft(), 25604 winY = $win.scrollTop(), 25605 winW = $win.width(), 25606 winH = $win.height(), 25607 containerW = $container.width(), 25608 containerOffsetX = containerW + ((winW - containerW) / 2), 25609 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 25610 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 25611 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 25612 x, y, leftPos; 25613 25614 if (horizontalParent) { 25615 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 25616 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 25617 } else { 25618 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX; 25619 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 25620 } 25621 if (this.opts.keepInViewport && !this.isCollapsible()) { 25622 if (this.isFixed()) { 25623 itemX -= winX; 25624 itemY -= winY; 25625 winX = winY = 0; 25626 } 25627 var absX = itemX + x, 25628 absY = itemY + y; 25629 if (this.opts.rightToLeftSubMenus && absX < winX) { 25630 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 25631 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 25632 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 25633 } 25634 if (!horizontalParent) { 25635 if (subH < winH && absY + subH > winY + winH) { 25636 y += winY + winH - subH - absY; 25637 } else if (subH >= winH || absY < winY) { 25638 y += winY - absY; 25639 } 25640 } 25641 // do we need scrolling? 25642 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 25643 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 25644 var self = this; 25645 if (!$sub.dataSM('scroll-arrows')) { 25646 $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]]) 25647 .bind({ 25648 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 25649 mouseleave: function(e) { 25650 self.menuScrollStop($sub); 25651 self.menuScrollOut($sub, e); 25652 }, 25653 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 25654 }) 25655 .insertAfter($sub) 25656 ); 25657 } 25658 // bind events to show/hide arrows on hover and save scrolling data for this sub 25659 var vportY = winY - (itemY + itemH); 25660 $sub.dataSM('scroll', { 25661 vportY: vportY, 25662 subH: subH, 25663 winH: winH, 25664 step: 1 25665 }) 25666 .bind({ 25667 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 25668 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 25669 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 25670 }) 25671 .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
25671StartZIndex() + this.zIndexInc }) 25672 .eq(0).css('margin-top', vportY).end() 25673 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 25674 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 25675 } 25676 } 25677 if ( !$sub.closest('.menu-accordion').length ) { 25678 var rightPos = 'auto'; 25679 if ( $sub.closest('.grid-filters').length ) { 25680 if ( $sub.closest('.text-right').length ) { 25681 leftPos = '0px'; 25682 rightPos = 'auto'; 25683 } else { 25684 leftPos = 'auto'; 25685 rightPos = '0px'; 25686 } 25687 x = 0; 25688 } else { 25689 if ( $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)').length && $sub.closest('.row-menu').is('.limit-width') && level === 2) { 25690 var parentContW = $sub.closest('.menu-container').width(); 25691 $sub.css({ width: parentContW}); 25692 $sub.addClass('need-focus'); 25693 leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.menu-container').offset().left)); 25694 x = 0; 25695 } else if ( $sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)').length ) { 25696 $sub.css({ width: containerW}); 25697 $sub.addClass('need-focus'); 25698 leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left)); 25699 if ( ! $('body').hasClass('megamenu-side-to-side') ) { 25700 leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft')); 25701 } 25702 x = 0; 25703 } else { 25704 if ( $sub.is('.block-wrapper-parent') && !$sub.find('.col-custom-width').length && !$sub.find('.row-parent-limit').length && level === 2 ) { 25705 leftPos = ( $li.position().left - ( (UNCODE.wwidth - $sub.outerWidth() )/2) ) + 'px'; 25706 } else { 25707 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').css('paddingLeft')) : $li.position().left ) + 'px'; 25708 } 25709 x = (level > 2 && x >= 0) ? x + 1 : x - 1; 25710 } 25711 } 25712 } 25713 25714 // $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) }); 25715 $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) }); 25716 // IE iframe shim 25717 this.menuIframeShim($sub); 25718 if ($sub.dataSM('ie-shim')) { 25719 $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) }); 25720 } 25721 }, 25722 menuScroll: function($sub, up, wheel) { 25723 var y = parseFloat($sub.css('margin-top')), 25724 scroll = $sub.dataSM('scroll'), 25725 navH = $('.navbar-main').outerHeight(), 25726 end = scroll.vportY + (up ? navH + 54 : scroll.winH - scroll.subH), 25727 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 25728 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 25729 y = parseFloat($sub.css('margin-top')); 25730 // show opposite arrow if appropriate 25731 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 25732 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 25733 } 25734 // accelerate when not using mousewheel to scroll 25735 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 25736 $sub.dataSM('scroll').step += 0.5; 25737 } 25738 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 25739 if (Math.abs(y - end) < 1) { 25740 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 25741 $sub.dataSM('scroll').step = 1; 25742 } else if (!wheel) { 25743 var self = this; 25744 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 25745 } 25746 }, 25747 menuScrollMousewheel: function($sub, e) { 25748 var $closestSub = $(e.target).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25749 while ($closestSub.dataSM('in-mega')) { 25750 $closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25751 } 25752 if ($closestSub[0] == $sub[0]) { 25753 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 25754 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 25755 this.menuScroll($sub, up, true); 25756 } 25757 } 25758 if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) { 25759 e.preventDefault(); 25760 } 25761 }, 25762 menuScrollOut: function($sub, e) { 25763 var reClass = /^scroll-(up|down)/, 25764 $closestSub = $(e.relatedTarget).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25765 while ($closestSub.dataSM('in-mega')) { 25766 $closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25767 } 25768 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 25769 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 25770 } 25771 }, 25772 menuScrollOver: function($sub, e) { 25773 var reClass = /^scroll-(up|down)/, 25774 $closestSub = $(e.target).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25775 while ($closestSub.dataSM('in-mega')) { 25776 $closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25777 } 25778 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 25779 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 25780 } 25781 }, 25782 menuScrollStop: function($sub) { 25783 if (this.scrollTimeout) { 25784 clearTimeout(this.scrollTimeout); 25785 this.scrollTimeout = 0; 25786 $sub.dataSM('scroll').step = 1; 25787 } 25788 }, 25789 menuShow: function($sub) { 25790 if (!$sub.dataSM('beforefirstshowfired')) { 25791 $sub.dataSM('beforefirstshowfired', true); 25792 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 25793 return; 25794 } 25795 } 25796 if ( this.isCollapsible() ) {
25797 this.$root.triggerHandler('beforecollapse.smapi', $sub[0]); 25798 } 25799 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 25800 return; 25801 } 25802 this.menuFixLayout($sub); 25803 $sub.stop(true, true); 25804 if (!$sub.is(':visible')) { 25805 $sub.css({ 25806 'visibility': 'visible', 25807 'pointer-events': 'auto', 25808 }); 25809 // set z-index - for IE < 9 set it to the parent LI 25810 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 25811 if (IElt9) { 25812 $sub.parent().css('z-index', zIndex); 25813 } else { 25814 $sub.css('z-index', zIndex); 25815 } 25816 // highlight parent item 25817 if (this.opts.keepHighlighted || this.isCollapsible()) { 25818 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 25819 $sub.dataSM('parent-a').addClass('highlighted'); 25820 } 25821 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 25822 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 25823 if (!IElt8) { 25824 $sub.css({ width: ($sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 25825 if (this.opts.subMenusMinWidth) { 25826 $sub.css('min-width', this.opts.subMenusMinWidth); 25827 } 25828 if (this.opts.subMenusMaxWidth) { 25829 var noMaxWidth = this.getWidth($sub); 25830 if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) { 25831 $sub.css('max-width', this.opts.subMenusMaxWidth); 25832 } 25833 if (noMaxWidth > this.getWidth($sub)) { 25834 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 25835 } 25836 } 25837 // IE6,7 25838 } else { 25839 $sub.children().css('styleFloat', 'none'); 25840 if (IE6) { 25841 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 25842 .children().children('a').css('white-space', 'nowrap'); 25843 } else { // IE7 25844 $sub.css({ width: ($sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 25845 if (this.opts.subMenusMinWidth) { 25846 $sub.css('min-width', this.opts.subMenusMinWidth); 25847 } 25848 } 25849 if (this.opts.subMenusMaxWidth) { 25850 var noMaxWidth = $sub.width(); 25851 if (IE6) { 25852 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 25853 if (noMaxWidth > maxWidth) { 25854 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 25855 } else { 25856 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 25857 } 25858 } else { // IE7 25859 if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) { 25860 $sub.css('max-width', this.opts.subMenusMaxWidth); 25861 } 25862 if (noMaxWidth > $sub.width()) { 25863 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 25864 } else { 25865 $sub.width(noMaxWidth); 25866 } 25867 } 25868 } else { 25869 $sub.width($sub.width()); 25870 } 25871 $sub.children().css('styleFloat', 'left'); 25872 } 25873 } 25874 if ( ( ( ($sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)')) && $('body').hasClass('scrollable-megamenu') ) ) && UNCODE.wwidth > UNCODE.mediaQuery ) { 25875 var $nav = $('.navbar-main'), 25876 navH = 0, 25877 navTop = 0, 25878 $vmenu = $('body.vmenu .vmenu-container, body.menu-overlay .vmenu-container, body.menu-offcanvas .vmenu-container'); 25879 if ( $nav.length && typeof $nav[0] !== 'undefined' ) { 25880 var navRect = $nav[0].getBoundingClientRect(); 25881 navH = navRect.height; 25882 navTop = navRect.top; 25883 } 25884 if ( ! $vmenu.length ) { 25885 $sub.css({ maxHeight: UNCODE.wheight - navH }); 25886 if ( $('.megamenu-block-wrapper', $sub).length ) { 25887 $sub.find('> li').addClass('has-scroll').css({ maxHeight: UNCODE.wheight - navH }); 25888 } 25889 } 25890 } 25891 this.menuPosition($sub); 25892 // insert IE iframe shim 25893 if ($sub.dataSM('ie-shim')) { 25894 $sub.dataSM('ie-shim').insertBefore($sub); 25895 } 25896 var complete = function() { 25897 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 25898 $sub.css('overflow', ''); 25899 }; 25900 // if sub is collapsible (mobile view) 25901 if (this.isCollapsible()) { 25902 if (this.opts.collapsibleShowFunction) { 25903 this.opts.collapsibleShowFunction.call(this, $sub, complete); 25904 } else { 25905 $sub.show(this.opts.collapsibleShowDuration, complete); 25906 } 25907 } else { 25908 if (this.opts.showFunction) { 25909 this.opts.showFunction.call(this, $sub, complete); 25910 } else { 25911 $sub.show(this.opts.showDuration, complete); 25912 } 25913 } 25914 // save new sub menu for this level 25915 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 25916 this.$root.triggerHandler('show.smapi', $sub[0]); 25917 } 25918 }, 25919 popupHide: function(noHideTimeout) { 25920 if (this.hideTimeout) { 25921 clearTimeout(this.hideTimeout); 25922 this.hideTimeout = 0; 25923 } 25924 var self = this; 25925 this.hideTimeout = setTimeout(function() { 25926 self.menuHideAll(); 25927 }, noHideTimeout ? 1 : this.opts.hideTimeout); 25928 }, 25929 popupShow: function(left, top) { 25930 if (!this.opts.isPopup) { 25931 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 25932 return; 25933 } 25934 if (this.hideTimeout) { 25935 clearTimeout(this.hideTimeout); 25936 this.hideTimeout = 0; 25937 } 25938 this.menuFixLayout(this.$root); 25939 this.$root.stop(true, true); 25940 if (!this.$root.is(':visible')) { 25941 this.$root.css({ left: left, top: top }); 25942 // IE iframe shim 25943 this.menuIframeShim(this.$root); 25944 if (this.$root.dataSM('ie-shim')) { 25945 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
25945: left, top: top }).insertBefore(this.$root); 25946 } 25947 // show menu 25948 if (this.opts.showFunction) { 25949 this.opts.showFunction.call(this, this.$root); 25950 } else { 25951 this.$root.show(this.opts.showDuration); 25952 } 25953 this.visibleSubMenus[0] = this.$root; 25954 } 25955 }, 25956 refresh: function() { 25957 this.menuHideAll(); 25958 this.$root.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').each(function() { 25959 var $this = $(this); 25960 if ($this.dataSM('scroll-arrows')) { 25961 $this.dataSM('scroll-arrows').remove(); 25962 } 25963 }) 25964 .removeDataSM('in-mega') 25965 .removeDataSM('shown-before') 25966 .removeDataSM('ie-shim') 25967 .removeDataSM('scroll-arrows') 25968 .removeDataSM('parent-a') 25969 .removeDataSM('level') 25970 .removeDataSM('beforefirstshowfired'); 25971 this.$root.find('a.has-submenu').removeClass('has-submenu') 25972 .parent().removeDataSM('sub'); 25973 if (this.opts.subIndicators) { 25974 this.$root.find('span.sub-arrow').remove(); 25975 } 25976 if (this.opts.markCurrentItem) { 25977 this.$root.find('a.current').removeClass('current'); 25978 } 25979 this.subMenus = []; 25980 this.init(true); 25981 }, 25982 rootOut: function(e) { 25983 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 25984 return; 25985 } 25986 if (this.hideTimeout) { 25987 clearTimeout(this.hideTimeout); 25988 this.hideTimeout = 0; 25989 } 25990 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 25991 var self = this; 25992 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 25993 } 25994 }, 25995 rootOver: function(e) { 25996 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 25997 return; 25998 } 25999 if (this.hideTimeout) { 26000 clearTimeout(this.hideTimeout); 26001 this.hideTimeout = 0; 26002 } 26003 }, 26004 winResize: function(e) { 26005 if (!this.handleEvents()) { 26006 // we still need to resize the disable overlay if it's visible 26007 if (this.$disableOverlay) { 26008 var pos = this.$root.offset(); 26009 this.$disableOverlay.css({ 26010 top: pos.top, 26011 left: pos.left, 26012 width: this.$root.outerWidth(), 26013 height: this.$root.outerHeight() 26014 }); 26015 } 26016 return; 26017 } 26018 // hide sub menus on resize - on mobile do it only on orientation change 26019 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 26020 if (this.activatedItems.length) { 26021 this.activatedItems[this.activatedItems.length - 1][0].blur(); 26022 } 26023 this.menuHideAll(); 26024 } 26025 } 26026 } 26027 }); 26028 26029 $.fn.dataSM = function(key, val) { 26030 if (val) { 26031 return this.data(key + '_smartmenus', val); 26032 } 26033 return this.data(key + '_smartmenus'); 26034 } 26035 26036 $.fn.removeDataSM = function(key) { 26037 return this.removeData(key + '_smartmenus'); 26038 } 26039 26040 $.fn.smartmenus = function(options) { 26041 if (typeof options == 'string') { 26042 var args = arguments, 26043 method = options; 26044 Array.prototype.shift.call(args); 26045 return this.each(function() { 26046 var smartmenus = $(this).data('smartmenus'); 26047 if (smartmenus && smartmenus[method]) { 26048 smartmenus[method].apply(smartmenus, args); 26049 } 26050 }); 26051 } 26052 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 26053 return this.each(function() { 26054 new $.SmartMenus(this, opts); 26055 }); 26056 } 26057 26058 // default settings 26059 $.fn.smartmenus.defaults = { 26060 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 26061 mainMenuSubOffsetX: 0, // pixels offset from default position
26062 mainMenuSubOffsetY: 0, // pixels offset from default position 26063 subMenusSubOffsetX: 0, // pixels offset from default position 26064 subMenusSubOffsetY: 0, // pixels offset from default position 26065 subMenusMinWidth: false, //'10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 26066 subMenusMaxWidth: false, //'20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 26067 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 26068 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 26069 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 26070 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 26071 scrollInterval: 30, // interval between each scrolling step 26072 scrollAccelerate: true, // accelerate scrolling or use a fixed step 26073 showTimeout: 250, // timeout before showing the sub menus 26074 hideTimeout: 500, // timeout before hiding the sub menus 26075 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 26076 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 26077 // don't forget to call complete() at the end of whatever you do 26078 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 26079 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 26080 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 26081 // don't forget to call complete() at the end of whatever you do 26082 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 26083 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 26084 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 26085 // (i.e. when mobile styles are used to make the sub menus collapsible) 26086 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 26087 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 26088 // (i.e. when mobile styles are used to make the sub menus collapsible) 26089 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 26090 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 26091 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 26092 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 26093 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 26094 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 26095 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 26096 bottomToTopSubMenus: false, // bottom to top display of the sub menus 26097 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 26098 }; 26099 26100})(jQuery); 26101/* 26102 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/ 26103 * Open source under the BSD License. 26104 * Copyright © 2008 George McGinley Smith 26105 * All rights reserved. 26106 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE 26107*/ 26108 26109/* globals jQuery, define, module, require */ 26110(function (factory) { 26111 if (typeof define === "function" && define.amd) { 26112 define(['jquery'], function ($) { 26113 return factory($); 26114 }); 26115 } else if (typeof module === "object" && typeof module.exports === "object") { 26116 module.exports = factory(require('jquery')); 26117 } else { 26118 factory(jQuery); 26119 } 26120})(function($){ 26121 26122 // Preserve the original jQuery "swing" easing as "jswing" 26123 if (typeof $.easing !== 'undefined') { 26124 $.easing['jswing'] = $.easing['swing']; 26125 } 26126 26127 var pow = Math.pow, 26128 sqrt = Math.sqrt, 26129 sin = Math.sin, 26130 cos = Math.cos, 26131 PI = Math.PI,
26132 c1 = 1.70158, 26133 c2 = c1 * 1.525, 26134 c3 = c1 + 1, 26135 c4 = ( 2 * PI ) / 3, 26136 c5 = ( 2 * PI ) / 4.5; 26137 26138 // x is the fraction of animation progress, in the range 0..1 26139 function bounceOut(x) { 26140 var n1 = 7.5625, 26141 d1 = 2.75; 26142 if ( x < 1/d1 ) { 26143 return n1*x*x; 26144 } else if ( x < 2/d1 ) { 26145 return n1*(x-=(1.5/d1))*x + .75; 26146 } else if ( x < 2.5/d1 ) { 26147 return n1*(x-=(2.25/d1))*x + .9375; 26148 } else { 26149 return n1*(x-=(2.625/d1))*x + .984375; 26150 } 26151 } 26152 26153 $.extend( $.easing, { 26154 def: 'easeOutQuad', 26155 swing: function (x) { 26156 return $.easing[$.easing.def](x); 26157 }, 26158 easeInQuad: function (x) { 26159 return x * x; 26160 }, 26161 easeOutQuad: function (x) { 26162 return 1 - ( 1 - x ) * ( 1 - x ); 26163 }, 26164 easeInOutQuad: function (x) { 26165 return x < 0.5 ? 26166 2 * x * x : 26167 1 - pow( -2 * x + 2, 2 ) / 2; 26168 }, 26169 easeInCubic: function (x) { 26170 return x * x * x; 26171 }, 26172 easeOutCubic: function (x) { 26173 return 1 - pow( 1 - x, 3 ); 26174 }, 26175 easeInOutCubic: function (x) { 26176 return x < 0.5 ? 26177 4 * x * x * x : 26178 1 - pow( -2 * x + 2, 3 ) / 2; 26179 }, 26180 easeInQuart: function (x) { 26181 return x * x * x * x; 26182 }, 26183 easeOutQuart: function (x) { 26184 return 1 - pow( 1 - x, 4 ); 26185 }, 26186 easeInOutQuart: function (x) { 26187 return x < 0.5 ? 26188 8 * x * x * x * x : 26189 1 - pow( -2 * x + 2, 4 ) / 2; 26190 }, 26191 easeInQuint: function (x) { 26192 return x * x * x * x * x; 26193 }, 26194 easeOutQuint: function (x) { 26195 return 1 - pow( 1 - x, 5 ); 26196 }, 26197 easeInOutQuint: function (x) { 26198 return x < 0.5 ? 26199 16 * x * x * x * x * x : 26200 1 - pow( -2 * x + 2, 5 ) / 2; 26201 }, 26202 easeInSine: function (x) { 26203 return 1 - cos( x * PI/2 ); 26204 }, 26205 easeOutSine: function (x) { 26206 return sin( x * PI/2 ); 26207 }, 26208 easeInOutSine: function (x) { 26209 return -( cos( PI * x ) - 1 ) / 2; 26210 }, 26211 easeInExpo: function (x) { 26212 return x === 0 ? 0 : pow( 2, 10 * x - 10 ); 26213 }, 26214 easeOutExpo: function (x) { 26215 return x === 1 ? 1 : 1 - pow( 2, -10 * x ); 26216 }, 26217 easeInOutExpo: function (x) { 26218 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 26219 pow( 2, 20 * x - 10 ) / 2 : 26220 ( 2 - pow( 2, -20 * x + 10 ) ) / 2; 26221 }, 26222 easeInCirc: function (x) { 26223 return 1 - sqrt( 1 - pow( x, 2 ) ); 26224 }, 26225 easeOutCirc: function (x) { 26226 return sqrt( 1 - pow( x - 1, 2 ) ); 26227 }, 26228 easeInOutCirc: function (x) { 26229 return x < 0.5 ? 26230 ( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 : 26231 ( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2; 26232 }, 26233 easeInElastic: function (x) { 26234 return x === 0 ? 0 : x === 1 ? 1 : 26235 -pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 ); 26236 }, 26237 easeOutElastic: function (x) { 26238 return x === 0 ? 0 : x === 1 ? 1 : 26239 pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1; 26240 }, 26241 easeInOutElastic: function (x) { 26242 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 26243 -( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 : 26244 pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1; 26245 }, 26246 easeInBack: function (x) { 26247 return c3 * x * x * x - c1 * x * x; 26248 }, 26249 easeOutBack: function (x) { 26250 return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 ); 26251 }, 26252 easeInOutBack: function (x) { 26253 return x < 0.5 ? 26254 ( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 : 26255 ( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2; 26256 }, 26257 easeInBounce: function (x) { 26258 return 1 - bounceOut( 1 - x ); 26259 }, 26260 easeOutBounce: bounceOut, 26261 easeInOutBounce: function (x) { 26262 return x < 0.5 ? 26263 ( 1 - bounceOut( 1 - 2 * x ) ) / 2 : 26264 ( 1 + bounceOut( 2 * x - 1 ) ) / 2; 26265 } 26266 }); 26267 return $; 26268}); 26269 26270/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 26271 * Licensed under the MIT License (LICENSE.txt). 26272 * 26273 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 26274 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 26275 * Thanks to: Seamus Leahy for adding deltaX and deltaY 26276 * 26277 * Version: 3.0.6 26278 * 26279 * Requires: 1.2.2+ 26280 */ 26281(function($) { 26282 var types = ['DOMMouseScroll', 'mousewheel']; 26283 if ($.event.fixHooks) { 26284 for (var i = types.length; i;) { 26285 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 26286 } 26287 } 26288 $.event.special.mousewheel = { 26289 setup: function() { 26290 if (this.addEventListener) { 26291 for (var i = types.length; i;) { 26292 this.addEventListener(types[--i], handler, false); 26293 } 26294 } else { 26295 this.onmousewheel = handler; 26296 } 26297 }, 26298 teardown: function() { 26299 if (this.removeEventListener) { 26300 for (var i = types.length; i;) { 26301 this.removeEventListener(types[--i], handler, false); 26302 } 26303 } else { 26304 this.onmousewheel = null; 26305 } 26306 } 26307 }; 26308 $.fn.extend({ 26309 mousewheel: function(fn) { 26310 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 26311 }, 26312 unmousewheel: function(fn) { 26313 return this.unbind("mousewheel", fn); 26314 } 26315 }); 26316 26317 function handler(event) { 26318 var orgEvent = event || window.event, 26319 args = [].slice.call(arguments, 1), 26320 delta = 0, 26321 returnValue = true, 26322 deltaX = 0, 26323 deltaY = 0; 26324 event = $.event.fix(orgEvent); 26325 event.type = "mousewheel"; 26326 // Old school scrollwheel delta 26327 if (orgEvent.wheelDelta) { 26328 delta = orgEvent.wheelDelta / 120; 26329 } 26330 if (orgEvent.detail) { 26331 delta = -orgEvent.detail / 3; 26332 } 26333 // New school multidimensional scroll (touchpads) deltas 26334 deltaY = delta; 26335 // Gecko 26336 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 26337 deltaY = 0; 26338 deltaX = -1 * delta; 26339 } 26340 // Webkit 26341 if (orgEvent.wheelDeltaY !== undefined) { 26342 deltaY = orgEvent.wheelDeltaY / 120; 26343 } 26344 if (orgEvent.wheelDeltaX !== undefined) { 26345 deltaX = -1 * orgEvent.wheelDeltaX / 120; 26346 } 26347 // Add event and delta to the front of the arguments 26348 args.unshift(event, delta, deltaX, deltaY); 26349 return ($.event.dispatch || $.event.handle).apply(this, args); 26350 } 26351})(jQuery); 26352/** 26353 * jQuery iLightBox - Revolutionary Lightbox Plugin 26354 * http://www.ilightbox.net/ 26355 * 26356 * @version: 2.2.4 - October 14, 2017 26357 * 26358 * @author: iProDev (Hemn Chawroka) 26359 * http://www.iprodev.com/ 26360 * 26361 */ 26362(function($, window, undefined) { 26363 26364 var extensions = { 26365 flash: ['swf'], 26366 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'], 26367 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 26368 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 26369 }, 26370 26371 // Global DOM elements 26372 $win = $(window), 26373 $doc = $(document), 26374
26375 // Support indicators 26376 browser, 26377 transform, 26378 gpuAcceleration, 26379 fullScreenApi = '', 26380 userAgent = navigator.userAgent || navigator.vendor || window.opera, 26381 supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1), 26382 ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1, 26383 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)), 26384 26385 // Events 26386 clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox", 26387 touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 26388 touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 26389 touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 26390 26391 // Math shorthands 26392 abs = Math.abs, 26393 sqrt = Math.sqrt, 26394 round = Math.round, 26395 max = Math.max, 26396 min = Math.min, 26397 floor = Math.floor, 26398 random = Math.random, 26399 26400 pluginspages = { 26401 quicktime: 'http://www.apple.com/quicktime/download', 26402 flash: 'http://www.adobe.com/go/getflash' 26403 }, 26404 26405 iLightBox = function(el, options, items, instant) { 26406 var iL = this; 26407 26408 iL.options = options, 26409 iL.selector = options.selector || el, 26410 iL.context = document, 26411 iL.instant = instant; 26412 26413 if (items.length < 1) iL.attachItems(); 26414 else iL.items = items; 26415 26416 iL.vars = { 26417 total: iL.items.length, 26418 start: 0, 26419 current: null, 26420 next: null, 26421 prev: null, 26422 BODY: $('body'), 26423 loadRequests: 0, 26424 overlay: $('<div class="ilightbox-overlay"></div>'), 26425 loader: $('<div class="ilightbox-loader"><div></div></div>'), 26426 toolbar: $('<div class="ilightbox-toolbar"></div>'), 26427 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 26428 title: $('<div class="ilightbox-title"></div>'), 26429 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 26430 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 26431 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 26432 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 26433 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 26434 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 26435 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 26436 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 26437 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 26438 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
26439 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>'), 26440 thumbs: false, 26441 nextLock: false, 26442 prevLock: false, 26443 hashLock: false, 26444 isMobile: false, 26445 mobileMaxWidth: 980, 26446 isInFullScreen: false, 26447 isSwipe: false, 26448 mouseID: 0, 26449 cycleID: 0, 26450 isPaused: 0, 26451 captionHeight: 39, 26452 }; 26453 26454 // Hideable elements with mousemove event 26455 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 26456 26457 iL.normalizeItems(); 26458 26459 //Check necessary plugins 26460 iL.availPlugins(); 26461 26462 //Set startFrom 26463 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 26464 26465 //If randomStart 26466 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 26467 iL.vars.start = iL.options.startFrom; 26468 26469 if (instant) iL.instantCall(); 26470 else iL.patchItemsEvents(); 26471 26472 if (iL.options.linkId) { 26473 iL.hashChangeHandler(); 26474 $win.iLightBoxHashChange(function() { 26475 iL.hashChangeHandler(); 26476 }); 26477 } 26478 26479 if (supportTouch) { 26480 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 26481 replace = "itap"; 26482 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 26483 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 26484 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 26485 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 26486 } 26487 26488 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 26489 $.extend(iL.options.styles, { 26490 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 26491 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 26492 nextOpacity: 0, 26493 prevOpacity: 0 26494 }); 26495 } 26496 }; 26497 26498 //iLightBox helpers 26499 iLightBox.prototype = { 26500 showLoader: function() { 26501 var iL = this; 26502 iL.vars.loadRequests += 1; 26503 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 26504 //top: '-30px' 26505 opacity: '1' 26506 }, iL.options.show.speed, 'easeOutCirc'); 26507 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 26508 //left: '-30px' 26509 opacity: '1' 26510 }, iL.options.show.speed, 'easeOutCirc'); 26511 }, 26512 26513 hideLoader: function() { 26514 var iL = this; 26515 iL.vars.loadRequests -= 1; 26516 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 26517 if (iL.options.path.toLowerCase() == "horizontal") { 26518 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 26519 //top: '-192px' 26520 opacity: '0' 26521 }, iL.options.show.speed, 'easeInCirc'); 26522 } else { 26523 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 26524 //left: '-192px' 26525 opacity: '0' 26526 }, iL.options.show.speed, 'easeInCirc'); 26527 } 26528 }, 26529 26530 createUI: function() { 26531 var iL = this; 26532 26533 iL.ui = { 26534 currentElement: iL.vars.holder, 26535 nextElement: iL.vars.nextPhoto, 26536 prevElement: iL.vars.prevPhoto, 26537 currentItem: iL.vars.current, 26538 nextItem: iL.vars.next, 26539 prevItem: iL.vars.prev, 26540 hide: function() { 26541 iL.closeAction(); 26542 }, 26543 refresh: function() { 26544 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 26545 }, 26546 fullscreen: function() { 26547 iL.fullScreenAction(); 26548 } 26549 }; 26550 }, 26551 26552 attachItems: function() { 26553 var iL = this, 26554 itemsObject = new Array(), 26555 items = new Array(); 26556 26557 $(iL.selector, iL.context).each(function() { 26558 var t = $(this), 26559 URL = t.attr(iL.options.attr) || null, 26560 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 26561 caption = t.data('caption'), 26562 title = t.data('title'), 26563 type = t.data('type') || getTypeByExtension(URL), 26564 clone = t.data('lbox-clone') || false; 26565 26566 //Uncode addition ##START## 26567 if (type === false) { 26568 return; 26569 } 26570 //Uncode addition ##END## 26571 26572 if (t.data('lbox-clone') != undefined) return; 26573 26574 //Uncode addition ##START## 26575 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 26576 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 26577 URL_i, 26578 URLS_LENGHT = ALBUM_URLS.length; 26579 26580 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 26581 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 26582 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 26583 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 26584 items.push({ 26585 URL: ALBUM_URLS[URL_i].url, 26586 caption: ALBUM_URLS[URL_i].caption, 26587 title: ALBUM_URLS[URL_i].title, 26588 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 26589 options: item_opts, 26590 clone: clone 26591 }); 26592 var newT = t; 26593 newT.attr('href',ALBUM_URLS[URL_i].url); 26594 if (!iL.instant) itemsObject.push(newT); 26595 } 26596 } 26597 } else { 26598 //Uncode addition ##END## 26599 items.push({ 26600 URL: URL, 26601 caption: caption, 26602 title: title, 26603 type: type, 26604 options: options, 26605 clone: clone 26606 }); 26607 } 26608 26609 26610 if (iL.vars != undefined) iL.vars.total = items.length; 26611 26612 if (!iL.instant) itemsObject.push(t); 26613 }); 26614 26615 iL.items = items, 26616 iL.itemsObject = itemsObject; 26617 26618 }, 26619 26620 normalizeItems: function() { 26621 var iL = this, 26622 newItems = new Array(); 26623 26624 $.each(iL.items, function(key, val) { 26625 26626 if (typeof val == "string") val = { 26627 url: val 26628 }; 26629 26630 var URL = val.url || val.URL || null, 26631 options = val.options || {}, 26632 caption = val.caption || null, 26633 title = val.title || null, 26634 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 26635 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 26636 26637 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
26638 options.videoType = options.videoType || null, 26639 options.skin = options.skin || iL.options.skin, 26640 options.width = options.width || null, 26641 options.height = options.height || null, 26642 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 26643 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 26644 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 26645 26646 if (type == "video") { 26647 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 26648 26649 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 26650 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 26651 options.html5video.preload = options.html5video.preload || "metadata"; 26652 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 26653 //UNCODE addition 26654 options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false; 26655 } 26656 26657 if (!options.width || !options.height) { 26658 if (type == "video") options.width = 1280, options.height = 720; 26659 else if (type == "iframe") options.width = '100%', options.height = '90%'; 26660 else if (type == "flash") options.width = 1280, options.height = 720; 26661 } 26662 26663 delete val.url; 26664 val.index = key; 26665 val.URL = URL; 26666 val.caption = caption; 26667 val.title = title; 26668 val.type = type; 26669 val.options = options; 26670 val.ext = ext; 26671 26672 newItems.push(val); 26673 }); 26674 26675 iL.items = newItems; 26676 }, 26677 26678 instantCall: function() { 26679 var iL = this, 26680 key = iL.vars.start; 26681 26682 iL.vars.current = key; 26683 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 26684 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 26685 26686 iL.addContents(); 26687 iL.patchEvents(); 26688 }, 26689 26690 addContents: function() { 26691 var iL = this, 26692 vars = iL.vars, 26693 opts = iL.options, 26694 viewport = getViewport(), 26695 path = opts.path.toLowerCase(), 26696 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 26697 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 26698 }), 26699 needRecognition = recognizingItems.length > 0; 26700 26701 if (opts.mobileOptimizer && !opts.innerToolbar) 26702 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 26703 26704 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 26705 26706 if (opts.linkId) 26707 vars.overlay[0].setAttribute('linkid', opts.linkId); 26708 26709 //Add Toolbar Buttons 26710 if (opts.controls.toolbar) { 26711 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 26712 if (opts.controls.fullscreen) 26713 vars.toolbar.append(vars.fullScreenButton); 26714 if (opts.controls.slideshow) 26715 vars.toolbar.append(vars.innerPlayButton); 26716 if (vars.total > 1) 26717 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 26718 } 26719 26720 //Append elements to body 26721 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 26722 26723 if (!opts.innerToolbar) 26724 vars.BODY.append(vars.toolbar); 26725 if (opts.controls.arrows) 26726 vars.BODY.append(vars.nextButton).append(vars.prevButton); 26727 26728 if (opts.controls.thumbnail && vars.total > 1) { 26729 vars.BODY.append(vars.thumbnails); 26730 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 26731 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 26732 vars.thumbs = true; 26733 } 26734 26735 //Configure loader and arrows 26736 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 26737 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 26738 } : { 26739 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 26740 }; 26741 vars.loader.addClass(opts.skin).css(loaderCss); 26742 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 26743 if (path == "horizontal") 26744 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 26745 26746 // Configure arrow buttons 26747 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 26748 26749 if (!opts.infinite) { 26750 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 26751 26752 if (vars.current == 0) 26753 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 26754 if (vars.current >= vars.total - 1) 26755 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 26756 } 26757 26758 if (opts.show.effect) { 26759 vars.overlay.stop().fadeIn(opts.show.speed); 26760 vars.toolbar.stop().fadeIn(opts.show.speed); 26761 } else { 26762 vars.overlay.show(); 26763 vars.toolbar.show(); 26764 } 26765 26766 var length = recognizingItems.length; 26767 if (needRecognition) { 26768 iL.showLoader(); 26769 26770 $.each(recognizingItems, function(key, val) { 26771 var resultFnc = function(result) { 26772 var key = -1, 26773 filter = iL.items.filter(function(e, i, arr) { 26774 if (e.URL == result.url) 26775 key = i; 26776 26777 return e.URL == result.url; 26778 }), 26779 self = iL.items[key]; 26780 26781 if (result) 26782 $.extend(true, self, { 26783 URL: result.source, 26784 type: result.type, 26785 recognized: true, 26786 options: { 26787 html5video: result.html5video, 26788 width: (result.type == "image") ? 0 : (result.width || self.width), 26789 height: (result.type == "image") ? 0 : (result.height || self.height), 26790 thumbnail: self.options.thumbnail || result.thumbnail 26791 } 26792 }); 26793 26794 length--; 26795 26796 if (length == 0) { 26797 iL.hideLoader(); 26798 26799 vars.dontGenerateThumbs = false;
26800 iL.generateThumbnails(); 26801 26802 if (opts.show.effect) 26803 setTimeout(function() { 26804 iL.generateBoxes(); 26805 }, opts.show.speed); 26806 else 26807 iL.generateBoxes(); 26808 } 26809 }; 26810 26811 iL.ogpRecognition(this, resultFnc); 26812 }); 26813 } 26814 else { 26815 if (opts.show.effect) 26816 setTimeout(function() { 26817 iL.generateBoxes(); 26818 }, opts.show.speed); 26819 else 26820 iL.generateBoxes(); 26821 } 26822 26823 iL.createUI(); 26824 26825 window.iLightBox = { 26826 close: function() { 26827 iL.closeAction(); 26828 }, 26829 fullscreen: function() { 26830 iL.fullScreenAction(); 26831 }, 26832 moveNext: function() { 26833 iL.moveTo('next'); 26834 }, 26835 movePrev: function() { 26836 iL.moveTo('prev'); 26837 }, 26838 goTo: function(index) { 26839 iL.goTo(index); 26840 }, 26841 refresh: function() { 26842 iL.refresh(); 26843 }, 26844 reposition: function() { 26845 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 26846 }, 26847 setOption: function(options) { 26848 iL.setOption(options); 26849 }, 26850 destroy: function() { 26851 iL.closeAction(); 26852 iL.dispatchItemsEvents(); 26853 } 26854 }; 26855 26856 if (opts.linkId) { 26857 vars.hashLock = true; 26858 window.location.hash = opts.linkId + '/' + vars.current; 26859 setTimeout(function() { 26860 vars.hashLock = false; 26861 }, 55); 26862 } 26863 26864 if (!opts.slideshow.startPaused) { 26865 iL.resume(); 26866 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 26867 } 26868 26869 //Trigger the onOpen callback 26870 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 26871 }, 26872 26873 loadContent: function(obj, opt, speed) { 26874 var iL = this, 26875 holder, item; 26876 26877 iL.createUI(); 26878 26879 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 26880 26881 if (opt == 'current') { 26882 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 26883 else iL.vars.lockWheel = false; 26884 26885 if (!obj.options.swipe) iL.vars.lockSwipe = true; 26886 else iL.vars.lockSwipe = false; 26887 } 26888 26889 switch (opt) { 26890 case 'current': 26891 holder = iL.vars.holder, item = iL.vars.current; 26892 break; 26893 case 'next': 26894 holder = iL.vars.nextPhoto, item = iL.vars.next; 26895 break; 26896 case 'prev': 26897 holder = iL.vars.prevPhoto, item = iL.vars.prev; 26898 break; 26899 } 26900 26901 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 26902 $('div.ilightbox-inner-toolbar', holder).remove(); 26903 26904 if (obj.title || iL.options.innerToolbar) { 26905 var innerToolbar = iL.vars.innerToolbar.clone(); 26906 if (obj.title && iL.options.show.title) { 26907 var title = iL.vars.title.clone(); 26908 title.empty().html(obj.title); 26909 innerToolbar.append(title); 26910 } 26911 if (iL.options.innerToolbar) { 26912 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 26913 } 26914 holder.prepend(innerToolbar); 26915 } 26916 26917 //console.warn('loadContent', arguments); 26918 26919 iL.loadSwitcher(obj, holder, item, opt); 26920 }, 26921 26922 loadSwitcher: function(obj, holder, item, opt) { 26923 var iL = this, 26924 opts = iL.options, 26925 api = { 26926 element: holder, 26927 position: item 26928 }; 26929 26930 switch (obj.type) { 26931 case 'image': 26932 //Trigger the onBeforeLoad callback 26933 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 26934 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 26935 26936 iL.loadImage(obj.URL, function(img) { 26937 //Trigger the onAfterLoad callback 26938 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 26939 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 26940 26941 var width = (img) ? img.width : 400, 26942 height = (img) ? img.height : 200; 26943 26944 holder.data({ 26945 naturalWidth: width, 26946 naturalHeight: height 26947 }); 26948 26949 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 26950 26951 //Trigger the onRender callback 26952 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 26953 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 26954 26955 iL.configureHolder(obj, opt, holder); 26956 }); 26957 26958 break; 26959
26960 case 'video': 26961 holder.data({ 26962 naturalWidth: obj.options.width, 26963 naturalHeight: obj.options.height 26964 }); 26965 26966 if (opt === 'current') { 26967 iL.addContent(holder, obj); 26968 26969 //Trigger the onRender callback 26970 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 26971 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 26972 } else { 26973 $('div.ilightbox-container', holder).empty(); 26974 } 26975 26976 iL.configureHolder(obj, opt, holder); 26977 26978 break; 26979 26980 case 'iframe': 26981 //iL.showLoader(); 26982 holder.data({ 26983 naturalWidth: obj.options.width, 26984 naturalHeight: obj.options.height 26985 }); 26986 26987 iL.configureHolder(obj, opt, holder); 26988 26989 if (opt === 'current') { 26990 var el = iL.addContent(holder, obj); 26991 26992 //Trigger the onRender callback 26993 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 26994 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 26995 26996 //Trigger the onBeforeLoad callback 26997 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 26998 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 26999 27000 el.bind('load', function() { 27001 //Trigger the onAfterLoad callback 27002 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27003 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27004 27005 //iL.hideLoader(); 27006 el.unbind('load'); 27007 }); 27008 } else { 27009 $('div.ilightbox-container', holder).empty(); 27010 } 27011 27012 break; 27013 27014 case 'inline': 27015 var el = $(obj.URL), 27016 content = iL.addContent(holder, obj), 27017 images = findImageInElement(holder); 27018 27019 holder.data({ 27020 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 27021 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 27022 }); 27023 content.children().eq(0).show(); 27024 27025 //Trigger the onRender callback 27026 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27027 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27028 27029 //Trigger the onBeforeLoad callback 27030 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 27031 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 27032 27033 iL.loadImage(images, function() { 27034 //Trigger the onAfterLoad callback 27035 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27036 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27037 27038 iL.configureHolder(obj, opt, holder); 27039 }); 27040 27041 break; 27042 27043 case 'flash': 27044 var el = iL.addContent(holder, obj); 27045 27046 holder.data({ 27047 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 27048 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 27049 }); 27050 27051 //Trigger the onRender callback 27052 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27053 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27054 27055 iL.configureHolder(obj, opt, holder); 27056 27057 break; 27058 27059 case 'ajax': 27060 var ajax = obj.options.ajax || {}; 27061 //Trigger the onBeforeLoad callback 27062 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 27063 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 27064 27065 iL.showLoader(); 27066 $.ajax({ 27067 url: obj.URL || opts.ajaxSetup.url, 27068 data: ajax.data || null, 27069 dataType: ajax.dataType || "html", 27070 type: ajax.type || opts.ajaxSetup.type, 27071 cache: ajax.cache || opts.ajaxSetup.cache, 27072 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 27073 global: ajax.global || opts.ajaxSetup.global, 27074 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 27075 username: ajax.username || opts.ajaxSetup.username, 27076 password: ajax.password || opts.ajaxSetup.password, 27077 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 27078 complete: ajax.complete || opts.ajaxSetup.complete, 27079 success: function(data, textStatus, jqXHR) { 27080 iL.hideLoader(); 27081 27082 var el = $(data), 27083 container = $('div.ilightbox-container', holder), 27084 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 27085 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 27086 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 27087 'overflow': 'hidden' 27088 } : {}; 27089 27090 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 27091 holder.show().data({
27092 naturalWidth: (elWidth || container.outerWidth()), 27093 naturalHeight: (elHeight || container.outerHeight()) 27094 }).hide(); 27095 27096 //Trigger the onRender callback 27097 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27098 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27099 27100 var images = findImageInElement(holder); 27101 iL.loadImage(images, function() { 27102 //Trigger the onAfterLoad callback 27103 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27104 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27105 27106 iL.configureHolder(obj, opt, holder); 27107 }); 27108 27109 opts.ajaxSetup.success(data, textStatus, jqXHR); 27110 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 27111 }, 27112 error: function(jqXHR, textStatus, errorThrown) { 27113 //Trigger the onAfterLoad callback 27114 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27115 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27116 27117 iL.hideLoader(); 27118 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 27119 iL.configureHolder(obj, opt, holder); 27120 27121 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 27122 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 27123 } 27124 }); 27125 27126 break; 27127 27128 case 'html': 27129 var object = obj.URL, 27130 el 27131 container = $('div.ilightbox-container', holder); 27132 27133 if (object[0].nodeName) el = object.clone(); 27134 else { 27135 var dom = $(object); 27136 if (dom.selector) el = $('<div>' + dom + '</div>'); 27137 else el = dom; 27138 } 27139 27140 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 27141 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 27142 27143 iL.addContent(holder, obj); 27144 27145 el.appendTo(document.documentElement).hide(); 27146 27147 //Trigger the onRender callback 27148 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27149 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27150 27151 var images = findImageInElement(holder); 27152 27153 //Trigger the onBeforeLoad callback 27154 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 27155 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 27156 27157 iL.loadImage(images, function() { 27158 //Trigger the onAfterLoad callback 27159 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27160 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27161 27162 holder.show().data({ 27163 naturalWidth: (elWidth || container.outerWidth()), 27164 naturalHeight: (elHeight || container.outerHeight()) 27165 }).hide(); 27166 el.remove(); 27167 27168 iL.configureHolder(obj, opt, holder); 27169 }); 27170 27171 break; 27172 } 27173 }, 27174 27175 configureHolder: function(obj, opt, holder) { 27176 var iL = this, 27177 vars = iL.vars, 27178 opts = iL.options; 27179 27180 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 27181 27182 if (opt == "current") 27183 var item = vars.current; 27184 else if (opt == "next") 27185 var opacity = opts.styles.nextOpacity, 27186 item = vars.next; 27187 else 27188 var opacity = opts.styles.prevOpacity, 27189 item = vars.prev; 27190 27191 var api = { 27192 element: holder, 27193 position: item 27194 }; 27195 27196 iL.items[item].options.width = iL.items[item].options.width || 0, 27197 iL.items[item].options.height = iL.items[item].options.height || 0; 27198 27199 if (opt == "current") { 27200 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 27201 holder.css(transform, ''); 27202 if (obj.caption) { 27203 iL.setCaption(obj, holder); 27204 var caption = $('div.ilightbox-caption', holder), 27205 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 27206 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
27206Speed); 27207 } 27208 27209 var social = obj.options.social; 27210 if (social) { 27211 iL.setSocial(social, obj.URL, holder); 27212 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 27213 } 27214 27215 //Generate thumbnails 27216 iL.generateThumbnails(); 27217 27218 //Trigger the onShow callback 27219 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27220 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27221 }); 27222 else { 27223 holder.show(); 27224 27225 //Generate thumbnails 27226 iL.generateThumbnails(); 27227 27228 //Trigger the onShow callback 27229 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27230 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27231 } 27232 } else { 27233 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 27234 if (opt == "next") vars.nextLock = false; 27235 else vars.prevLock = false; 27236 27237 //Generate thumbnails 27238 iL.generateThumbnails(); 27239 27240 //Trigger the onShow callback 27241 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27242 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27243 }); 27244 else { 27245 holder.css({ 27246 opacity: opacity 27247 }).show(); 27248 if (opt == "next") vars.nextLock = false; 27249 else vars.prevLock = false; 27250 27251 //Generate thumbnails 27252 iL.generateThumbnails(); 27253 27254 //Trigger the onShow callback 27255 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27256 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27257 } 27258 } 27259 27260 setTimeout(function() { 27261 iL.repositionPhoto(); 27262 }, 0); 27263 }, 27264 27265 generateBoxes: function() { 27266 var iL = this, 27267 vars = iL.vars, 27268 opts = iL.options; 27269 27270 if (opts.infinite && vars.total >= 3) { 27271 if (vars.current == vars.total - 1) vars.next = 0; 27272 if (vars.current == 0) vars.prev = vars.total - 1; 27273 } else opts.infinite = false; 27274 27275 //UNCODE addition 27276 if ( typeof iL.items[vars.current] == 'undefined' ) 27277 vars.current = 0; 27278 27279 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 27280 27281 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 27282 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 27283 }, 27284 27285 generateThumbnails: function() { 27286 var iL = this, 27287 vars = iL.vars, 27288 opts = iL.options, 27289 timeOut = null; 27290 27291 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 27292 var thumbnails = vars.thumbnails, 27293 container = $('div.ilightbox-thumbnails-container', thumbnails), 27294 grid = $('div.ilightbox-thumbnails-grid', container), 27295 i = 0; 27296 27297 grid.removeAttr('style').empty(); 27298 27299 $.each(iL.items, function(key, val) { 27300 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 27301 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 27302 thumb = val.options.thumbnail, 27303 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 27304 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 27305 27306 thumbnail.css({ 27307 opacity: 0 27308 }).addClass(isActive); 27309 27310 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 27311 icon.addClass('ilightbox-thumbnail-video'); 27312 thumbnail.append(icon); 27313 } else if (val.options.icon) { 27314 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 27315 thumbnail.append(icon); 27316 } 27317 27318 if (thumb) iL.loadImage(thumb, function(img) { 27319 i++; 27320 if (img) thumbnail.data({ 27321 naturalWidth: img.width, 27322 naturalHeight: img.height 27323 }).append('<img src="' + thumb + '" border="0" />'); 27324 else thumbnail.data({ 27325 naturalWidth: opts.thumbnails.maxWidth, 27326 naturalHeight: opts.thumbnails.maxHeight 27327 }); 27328 27329 clearTimeout(timeOut); 27330 timeOut = setTimeout(function() { 27331 iL.positionThumbnails(thumbnails, container, grid); 27332 }, 20); 27333 setTimeout(function() { 27334 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 27335 }, i * 20); 27336 }); 27337 27338 grid.append(thumbnail); 27339 }); 27340 iL.vars.dontGenerateThumbs = true; 27341 } 27342 }, 27343
27344 positionThumbnails: function(thumbnails, container, grid) { 27345 var iL = this, 27346 vars = iL.vars, 27347 opts = iL.options, 27348 viewport = getViewport(), 27349 path = opts.path.toLowerCase(); 27350 27351 if (!thumbnails) thumbnails = vars.thumbnails; 27352 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 27353 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 27354 27355 var thumbs = $('.ilightbox-thumbnail', grid), 27356 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 27357 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 27358 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 27359 gridHeight = (path == 'horizontal') ? heightAvail : 0, 27360 active = $('.ilightbox-active', grid), 27361 gridCss = {}, 27362 css = {}; 27363 27364 if (arguments.length < 3) { 27365 thumbs.css({ 27366 opacity: opts.thumbnails.normalOpacity 27367 }); 27368 active.css({ 27369 opacity: opts.thumbnails.activeOpacity 27370 }); 27371 } 27372 27373 thumbs.each(function(i) { 27374 var t = $(this), 27375 data = t.data(), 27376 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 27377 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 27378 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 27379 27380 t.css({ 27381 width: dims.width, 27382 height: dims.height 27383 }); 27384 if (path == 'horizontal') t.css({ 27385 'float': 'left' 27386 }); 27387 27388 (path == 'horizontal') ? ( 27389 gridWidth += t.outerWidth() 27390 ) : ( 27391 gridHeight += t.outerHeight() 27392 ); 27393 }); 27394 27395 gridCss = { 27396 width: gridWidth, 27397 height: gridHeight 27398 }; 27399 27400 grid.css(gridCss); 27401 27402 gridCss = {}; 27403 27404 var gridOffset = grid.offset(), 27405 activeOffset = (active.length) ? active.offset() : { 27406 top: parseInt(heightAvail / 2), 27407 left: parseInt(widthAvail / 2) 27408 }; 27409 27410 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 27411 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 27412 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 27413 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 27414 27415 (path == 'horizontal') ? ( 27416 gridCss.top = 0, 27417 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 27418 ) : ( 27419 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 27420 gridCss.left = 0 27421 ); 27422 27423 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 27424 else grid.css(gridCss); 27425 }, 27426 27427 loadImage: function(image, callback) { 27428 if (!$.isArray(image)) image = [image]; 27429 27430 var iL = this, 27431 length = image.length; 27432 27433 if (length > 0) { 27434 iL.showLoader(); 27435 $.each(image, function(index, value) { 27436 var img = new Image(); 27437 img.onload = function() { 27438 length -= 1; 27439 if (length == 0) { 27440 iL.hideLoader(); 27441 callback(img); 27442 } 27443 }; 27444 img.onerror = img.onabort = function() { 27445 length -= 1; 27446 if (length == 0) { 27447 iL.hideLoader(); 27448 callback(false); 27449 } 27450 }; 27451 img.src = image[index]; 27452 }); 27453 } else callback(false); 27454 }, 27455 27456 patchItemsEvents: function() { 27457 var iL = this, 27458 vars = iL.vars, 27459 clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL", 27460 vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL"; 27461 27462 if (iL.context && iL.selector) { 27463 var $items = $(iL.selector, iL.context); 27464 27465 $(iL.context).on(clickEvent, iL.selector, function() { 27466 var $this = $(this), 27467 //UNCODE addition 27468 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 27469 if (UNCODE.isMobile) { 27470 var isCarousel = $this.closest('.owl-carousel'); 27471 if (isCarousel.length) { 27472 if (isCarousel.hasClass('owl-translating')) return false; 27473 } 27474 } 27475 27476 vars.current = key; 27477 vars.next = iL.items[key + 1] ? key + 1 : null; 27478 vars.prev = iL.items[key - 1] ? key - 1 : null; 27479 27480 //UNCODE addition 27481 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 27482 return false;
27483 27484 iL.addContents(); 27485 iL.patchEvents(); 27486 27487 return false; 27488 }).on(vEvent, iL.selector, function() { 27489 return false; 27490 }); 27491 } else 27492 $.each(iL.itemsObject, function(key, val) { 27493 val.on(clickEvent, function() { 27494 vars.current = key; 27495 vars.next = iL.items[key + 1] ? key + 1 : null; 27496 vars.prev = iL.items[key - 1] ? key - 1 : null; 27497 27498 iL.addContents(); 27499 iL.patchEvents(); 27500 27501 return false; 27502 }).on(vEvent, function() { 27503 return false; 27504 }); 27505 }); 27506 }, 27507 27508 dispatchItemsEvents: function() { 27509 var iL = this, 27510 vars = iL.vars, 27511 opts = iL.options; 27512 27513 if (iL.context && iL.selector) 27514 $(iL.context).off('.iL', iL.selector); 27515 else 27516 $.each(iL.itemsObject, function(key, val) { 27517 val.off('.iL'); 27518 }); 27519 }, 27520 27521 refresh: function() { 27522 var iL = this; 27523 27524 iL.dispatchItemsEvents(); 27525 iL.attachItems(); 27526 iL.normalizeItems(); 27527 iL.patchItemsEvents(); 27528 }, 27529 27530 patchEvents: function() { 27531 var iL = this, 27532 vars = iL.vars, 27533 opts = iL.options, 27534 path = opts.path.toLowerCase(), 27535 holders = $('.ilightbox-holder'), 27536 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 27537 durationThreshold = 1000, 27538 horizontalDistanceThreshold = 27539 verticalDistanceThreshold = 100, 27540 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 27541 27542 $win.bind('resize.iLightBox', function() { 27543 var viewport = getViewport(); 27544 27545 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 27546 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 27547 27548 iL.repositionPhoto(null); 27549 if (supportTouch) { 27550 clearTimeout(vars.setTime); 27551 vars.setTime = setTimeout(function() { 27552 var scrollTop = getScrollXY().y; 27553 window.scrollTo(0, scrollTop - 30); 27554 window.scrollTo(0, scrollTop + 30); 27555 window.scrollTo(0, scrollTop); 27556 }, 2000); 27557 } 27558 if (vars.thumbs) iL.positionThumbnails(); 27559 }).bind('keydown.iLightBox', function(event) { 27560 if (opts.controls.keyboard) { 27561 switch (event.keyCode) { 27562 case 13: 27563 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 27564 break; 27565 case 27: 27566 if (opts.keyboard.esc) iL.closeAction(); 27567 break; 27568 case 37: 27569 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 27570 break; 27571 case 38: 27572 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 27573 break; 27574 case 39: 27575 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 27576 break; 27577 case 40: 27578 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 27579 break; 27580 } 27581 } 27582 }); 27583 27584 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 27585 iL.doFullscreen(); 27586 }); 27587 27588 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 27589 return arr.lastIndexOf(e) === i; 27590 }), 27591 holderEvents = ""; 27592 27593 $.each(holderEventsArr, function(key, val) { 27594 if (key != 0) holderEvents += ' '; 27595 holderEvents += val; 27596 }); 27597 27598 $doc.on(clickEvent, '.ilightbox-overlay', function() { 27599 if (opts.overlay.blur) iL.closeAction(); 27600 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 27601 iL.moveTo('next'); 27602 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 27603 iL.moveTo('prev'); 27604 }).on(clickEvent, '.ilightbox-thumbnail', function() { 27605 var t = $(this), 27606 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 27607 index = thumbs.index(t); 27608 27609 if (index != vars.current) iL.goTo(index); 27610 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 27611 var caption = $('div.ilightbox-caption', vars.holder), 27612 social = $('div.ilightbox-social', vars.holder), 27613 fadeSpeed = opts.effects.fadeSpeed; 27614 27615 if (vars.nextLock || vars.prevLock) { 27616 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 27617 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 27618 27619 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 27620 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 27621 } else { 27622 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 27623 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 27624 27625 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 27626 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 27627 } 27628 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 27629 if (e.type == 'mouseenter') vars.lockWheel = true; 27630 else vars.lockWheel = false;
27631 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 27632 var t = $(this); 27633 27634 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 27635 else if (t.hasClass('ilightbox-play')) { 27636 iL.resume(); 27637 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 27638 } else if (t.hasClass('ilightbox-pause')) { 27639 iL.pause(); 27640 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 27641 } else iL.closeAction(); 27642 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 27643 // prevent scrolling 27644 e.preventDefault(); 27645 }); 27646 27647 function mouseMoveHandler(e) { 27648 if (!vars.isMobile) { 27649 if (!vars.mouseID) { 27650 vars.hideableElements.show(); 27651 } 27652 27653 vars.mouseID = clearTimeout(vars.mouseID); 27654 27655 if (buttonsArray.indexOf(e.target) === -1) 27656 vars.mouseID = setTimeout(function() { 27657 vars.hideableElements.hide(); 27658 vars.mouseID = clearTimeout(vars.mouseID); 27659 }, 3000); 27660 } 27661 } 27662 27663 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 27664 27665 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 27666 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 27667 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 27668 }); 27669 27670 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'), 27671 delay = false; 27672 27673 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 27674 event.preventDefault(); 27675 if (delay) return; 27676 delay = true; 27677 if (!vars.lockWheel) { 27678 event.preventDefault(); 27679 if (delta < 0) { 27680 iL.moveTo('next'); 27681 } else if (delta > 0) { 27682 iL.moveTo('prev'); 27683 } 27684 } 27685 setTimeout(function(){
27686 delay = false; 27687 }, 2000); 27688 }); 27689 27690 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 27691 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 27692 27693 vars.BODY.addClass('ilightbox-closedhand'); 27694 27695 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 27696 scrollTop = $doc.scrollTop(), 27697 scrollLeft = $doc.scrollLeft(), 27698 offsets = [ 27699 holders.eq(0).offset(), 27700 holders.eq(1).offset(), 27701 holders.eq(2).offset() 27702 ], 27703 offSet = [{ 27704 top: offsets[0].top - scrollTop, 27705 left: offsets[0].left - scrollLeft 27706 }, { 27707 top: offsets[1].top - scrollTop, 27708 left: offsets[1].left - scrollLeft 27709 }, { 27710 top: offsets[2].top - scrollTop, 27711 left: offsets[2].left - scrollLeft 27712 }], 27713 start = { 27714 time: (new Date()).getTime(), 27715 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 27716 }, 27717 stop; 27718 27719 function moveEachHandler(i) { 27720 var t = $(this), 27721 offset = offSet[i], 27722 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 27723 27724 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 27725 } 27726 27727 function moveHandler(event) { 27728 27729 if (!start) return; 27730 27731 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 27732 27733 stop = { 27734 time: (new Date()).getTime(), 27735 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 27736 }; 27737 27738 holders.each(moveEachHandler); 27739 27740 // prevent scrolling 27741 event.preventDefault(); 27742 } 27743 27744 function repositionHolders() { 27745 holders.each(function() { 27746 var t = $(this), 27747 offset = t.data('offset') || { 27748 top: t.offset().top - scrollTop, 27749 left: t.offset().left - scrollLeft 27750 }, 27751 top = offset.top, 27752 left = offset.left; 27753 27754 t.css(transform, gpuAcceleration).stop().animate({ 27755 top: top, 27756 left: left 27757 }, 500, 'easeOutCirc', function() { 27758 t.css(transform, ''); 27759 }); 27760 }); 27761 } 27762 27763 holders.bind(touchMoveEvent, moveHandler); 27764 $doc.one(touchStopEvent, function(event) { 27765 holders.unbind(touchMoveEvent, moveHandler); 27766 27767 vars.BODY.removeClass('ilightbox-closedhand'); 27768 27769 if (start && stop) { 27770 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 27771 if (start.coords[0] > stop.coords[0]) { 27772 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 27773 else { 27774 vars.isSwipe = true; 27775 iL.moveTo('next'); 27776 } 27777 } else { 27778 if (vars.current == 0 && !opts.infinite) repositionHolders(); 27779 else { 27780 vars.isSwipe = true; 27781 iL.moveTo('prev'); 27782 } 27783 } 27784 } 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) { 27785 if (start.coords[1] > stop.coords[1]) { 27786 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 27787 else { 27788 vars.isSwipe = true; 27789 iL.moveTo('next'); 27790 } 27791 } else { 27792 if (vars.current == 0 && !opts.infinite) repositionHolders(); 27793 else { 27794 vars.isSwipe = true; 27795 iL.moveTo('prev'); 27796 } 27797 } 27798 } else repositionHolders(); 27799 } 27800 start = stop = undefined; 27801 }); 27802 }); 27803 27804 }, 27805 27806 goTo: function(index) { 27807 var iL = this, 27808 vars = iL.vars, 27809 opts = iL.options, 27810 diff = (index - vars.current); 27811 27812 if (opts.infinite) { 27813 if (index == vars.total - 1 && vars.current == 0) diff = -1; 27814 if (vars.current == vars.total - 1 && index == 0) diff = 1; 27815 } 27816 27817 if (diff == 1) iL.moveTo('next'); 27818 else if (diff == -1) iL.moveTo('prev'); 27819 else { 27820 27821 if (vars.nextLock || vars.prevLock) return false; 27822 27823 //Trigger the onBeforeChange callback 27824 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 27825 27826 if (opts.linkId) { 27827 vars.hashLock = true; 27828 window.location.hash = opts.linkId + '/' + index; 27829 } 27830 27831 if (iL.items[index]) { 27832 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 27833 else iL.vars.lockWheel = false;
27834 27835 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 27836 else vars.lockSwipe = false; 27837 } 27838 27839 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 27840 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 27841 }); 27842 27843 vars.current = index; 27844 vars.next = index + 1; 27845 vars.prev = index - 1; 27846 27847 iL.createUI(); 27848 27849 setTimeout(function() { 27850 iL.generateBoxes(); 27851 }, opts.effects.loadedFadeSpeed + 50); 27852 27853 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 27854 iL.positionThumbnails(); 27855 27856 if (opts.linkId) setTimeout(function() { 27857 vars.hashLock = false; 27858 }, 55); 27859 27860 // Configure arrow buttons 27861 if (!opts.infinite) { 27862 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 27863 27864 if (vars.current == 0) { 27865 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 27866 } 27867 if (vars.current >= vars.total - 1) { 27868 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 27869 } 27870 } 27871 27872 // Reset next cycle timeout 27873 iL.resetCycle(); 27874 27875 //Trigger the onAfterChange callback 27876 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 27877 } 27878 }, 27879 27880 moveTo: function(side) { 27881 var iL = this, 27882 vars = iL.vars, 27883 opts = iL.options, 27884 path = opts.path.toLowerCase(), 27885 viewport = getViewport(), 27886 switchSpeed = opts.effects.switchSpeed; 27887 27888 if (vars.nextLock || vars.prevLock) return false; 27889 else { 27890 27891 var item = (side == "next") ? vars.next : vars.prev; 27892 27893 if (opts.linkId) { 27894 vars.hashLock = true; 27895 window.location.hash = opts.linkId + '/' + item; 27896 } 27897 27898 if (side == "next") { 27899 if (!iL.items[item]) return false; 27900 var firstHolder = vars.nextPhoto, 27901 secondHolder = vars.holder, 27902 lastHolder = vars.prevPhoto, 27903 firstClass = 'ilightbox-prev', 27904 secondClass = 'ilightbox-next'; 27905 } else if (side == "prev") { 27906 if (!iL.items[item]) return false; 27907 var firstHolder = vars.prevPhoto, 27908 secondHolder = vars.holder, 27909 lastHolder = vars.nextPhoto, 27910 firstClass = 'ilightbox-next', 27911 secondClass = 'ilightbox-prev'; 27912 } 27913 27914 //Trigger the onBeforeChange callback 27915 if (typeof opts.callback.onBeforeChange == 'function') 27916 opts.callback.onBeforeChange.call(iL, iL.ui); 27917 27918 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 27919 27920 var captionFirst = $('div.ilightbox-caption', secondHolder), 27921 socialFirst = $('div.ilightbox-social', secondHolder); 27922 27923 if (captionFirst.length) 27924 captionFirst.stop().fadeOut(switchSpeed, function() { 27925 $(this).remove(); 27926 }); 27927 if (socialFirst.length) 27928 socialFirst.stop().fadeOut(switchSpeed, function() { 27929 $(this).remove(); 27930 }); 27931 27932 if (iL.items[item].caption) { 27933 iL.setCaption(iL.items[item], firstHolder); 27934 var caption = $('div.ilightbox-caption', firstHolder), 27935 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 27936 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 27937 } 27938 27939 var social = iL.items[item].options.social; 27940 if (social) { 27941 iL.setSocial(social, iL.items[item].URL, firstHolder); 27942 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 27943 } 27944 27945 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 27946 val.removeClass('ilightbox-next ilightbox-prev'); 27947 }); 27948 27949 var firstOffset = firstHolder.data('offset'), 27950 winW = (viewport.width - (opts.styles.pageOffsetX)), 27951 winH = (viewport.height - (opts.styles.pageOffsetY)), 27952 width = firstOffset.newDims.width, 27953 height = firstOffset.newDims.height, 27954 thumbsOffset = firstOffset.thumbsOffset, 27955 diff = firstOffset.diff, 27956 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 27957 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 27958 27959 var secondOffset = secondHolder.data('offset'), 27960 object = secondOffset.object; 27961 27962 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 27963 var objRatio = width / height; 27964 height = height - vars.captionHeight; 27965 width = height * objRatio; 27966 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 27967 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 27968 }*/ 27969 27970 firstHolder.show().css(transform, gpuAcceleration).animate({ 27971 top: top, 27972 left: left, 27973 opacity: 1 27974 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 27975 firstHolder.css(transform, ''); 27976 }); 27977 27978 $('div.ilightbox-container', firstHolder).animate({ 27979 width: width, 27980 height: height 27981 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 27982 27983 diff = secondOffset.diff; 27984 27985 width = secondOffset.newDims.width, 27986 height = secondOffset.newDims.height; 27987 27988 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 27989 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 27990 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 27991 27992 if (side == 'prev') 27993 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 27994 else { 27995 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 27996 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 27997 } 27998 27999 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 28000 var objRatio = width / height; 28001 height = height - vars.captionHeight; 28002 width = height * objRatio; 28003 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 28004 }*/ 28005 28006 $('div.ilightbox-container', secondHolder).animate({ 28007 width: width, 28008 height: height 28009 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 28010 28011 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 28012 top: top, 28013 left: left, 28014 opacity: opts.styles.prevOpacity, 28015 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 28016 secondHolder.css(transform, ''); 28017
28018 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 28019 iL.positionThumbnails(); 28020 28021 if (iL.items[item]) { 28022 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 28023 else vars.lockWheel = false; 28024 28025 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 28026 else vars.lockSwipe = false; 28027 } 28028 28029 vars.isSwipe = false; 28030 28031 // Remove iframe & video from previous slide 28032 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 28033 $('div.ilightbox-container', secondHolder).empty(); 28034 } 28035 28036 if (side == "next") { 28037 vars.nextPhoto = lastHolder, 28038 vars.prevPhoto = secondHolder, 28039 vars.holder = firstHolder; 28040 28041 vars.nextPhoto.hide(); 28042 28043 vars.next = vars.next + 1, 28044 vars.prev = vars.current, 28045 vars.current = vars.current + 1; 28046 28047 if (opts.infinite) { 28048 if (vars.current > vars.total - 1) vars.current = 0; 28049 if (vars.current == vars.total - 1) vars.next = 0; 28050 if (vars.current == 0) vars.prev = vars.total - 1; 28051 } 28052 28053 iL.createUI(); 28054 28055 if (!iL.items[vars.next]) 28056 vars.nextLock = false; 28057 else 28058 iL.loadContent(iL.items[vars.next], 'next'); 28059 } else { 28060 vars.prevPhoto = lastHolder; 28061 vars.nextPhoto = secondHolder; 28062 vars.holder = firstHolder; 28063 28064 vars.prevPhoto.hide(); 28065 28066 vars.next = vars.current; 28067 vars.current = vars.prev; 28068 vars.prev = vars.current - 1; 28069 28070 if (opts.infinite) { 28071 if (vars.current == vars.total - 1) vars.next = 0; 28072 if (vars.current == 0) vars.prev = vars.total - 1; 28073 } 28074 28075 iL.createUI(); 28076 28077 if (!iL.items[vars.prev]) 28078 vars.prevLock = false; 28079 else 28080 iL.loadContent(iL.items[vars.prev], 'prev'); 28081 } 28082 28083 // Add iframe & video content for current slide 28084 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 28085 iL.loadContent(iL.items[vars.current], 'current'); 28086 } 28087 28088 if (opts.linkId) setTimeout(function() { 28089 vars.hashLock = false; 28090 }, 55); 28091 28092 // Configure arrow buttons 28093 if (!opts.infinite) { 28094 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 28095 28096 if (vars.current == 0) 28097 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 28098 if (vars.current >= vars.total - 1) 28099 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 28100 } 28101 28102 iL.repositionPhoto(); 28103 28104 // Reset next cycle timeout 28105 iL.resetCycle(); 28106 28107 //Trigger the onAfterChange callback 28108 if (typeof opts.callback.onAfterChange == 'function') 28109 opts.callback.onAfterChange.call(iL, iL.ui); 28110 }); 28111 28112 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 28113 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 28114 28115 lastHolder.css(transform, gpuAcceleration).animate({ 28116 top: top, 28117 left: left, 28118 opacity: opts.styles.nextOpacity 28119 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 28120 lastHolder.css(transform, ''); 28121 }).addClass(secondClass); 28122 } 28123 }, 28124 28125 setCaption: function(obj, target) { 28126 var iL = this, 28127 caption = $('<div class="ilightbox-caption"></div>'); 28128 28129 if (obj.caption) { 28130 caption.html(obj.caption); 28131 $('div.ilightbox-container', target).append(caption); 28132 } 28133 }, 28134 28135 normalizeSocial: function(obj, url) { 28136 var iL = this, 28137 vars = iL.vars, 28138 opts = iL.options, 28139 baseURL = window.location.href; 28140 28141 $.each(obj, function(key, value) { 28142 if (!value) 28143 return true; 28144 28145 var item = key.toLowerCase(), 28146 source, text; 28147 28148 switch (item) { 28149 case 'facebook': 28150 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 28151 text = "Share on Facebook"; 28152 break; 28153 case 'twitter': 28154 source = "http://twitter.com/home?status={URL}", 28155 text = "Share on Twitter"; 28156 break; 28157 case 'digg': 28158 source = "http://digg.com/submit?phase=2&url={URL}", 28159 text = "Share on Digg"; 28160 break; 28161 case 'reddit': 28162 source = "http://reddit.com/submit?url={URL}", 28163 text = "Share on reddit"; 28164 break; 28165 } 28166 28167 obj[key] = { 28168 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 28169 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 28170 text: value.text || text || "Share on " + key, 28171 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 28172 height: value.height || 360 28173 }; 28174 28175 }); 28176 28177 return obj; 28178 }, 28179 28180 setSocial: function(obj, url, target) { 28181 var iL = this, 28182 socialBar = $('<div class="ilightbox-social"></div>'), 28183 buttons = '<ul>'; 28184 28185 obj = iL.normalizeSocial(obj, url); 28186 28187 $.each(obj, function(key, value) { 28188 var item = key.toLowerCase(), 28189 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, '+')); 28190 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>'; 28191 }); 28192 28193 buttons += '</ul>'; 28194 28195 socialBar.html(buttons); 28196 $('div.ilightbox-container', target).append(socialBar); 28197 }, 28198 28199 fullScreenAction: function() { 28200 var iL = this, 28201 vars = iL.vars; 28202 28203 if (fullScreenApi.supportsFullScreen) { 28204 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 28205 else fullScreenApi.requestFullScreen(document.documentElement); 28206 } else { 28207 iL.doFullscreen(); 28208 } 28209 }, 28210 28211 doFullscreen: function() { 28212 var iL = this, 28213 vars = iL.vars, 28214 viewport = getViewport(), 28215 opts = iL.options; 28216 28217 if (opts.fullAlone) { 28218 var currentHolder = vars.holder, 28219 current = iL.items[vars.current], 28220 windowWidth = viewport.width, 28221 windowHeight = viewport.height, 28222 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 28223 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 28224 28225 if (!vars.isInFullScreen) { 28226 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 28227 vars.overlay.css({ 28228 opacity: 1 28229 }); 28230 28231 $.each(hideElements, function(i, element) { 28232 element.hide(); 28233 }); 28234 28235 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 28236 28237 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
28238 naturalWidthOld: currentHolder.data('naturalWidth'), 28239 naturalHeightOld: currentHolder.data('naturalHeight'), 28240 naturalWidth: windowWidth, 28241 naturalHeight: windowHeight 28242 }); 28243 else { 28244 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 28245 newWidth = windowWidth, 28246 newHeight = windowHeight, 28247 width = currentHolder.data('naturalWidth'), 28248 height = currentHolder.data('naturalHeight'); 28249 28250 if (viewport.toLowerCase() == 'fill') { 28251 newHeight = (newWidth / width) * height; 28252 28253 if (newHeight < windowHeight) { 28254 newWidth = (windowHeight / height) * width, 28255 newHeight = windowHeight; 28256 } 28257 } else if (viewport.toLowerCase() == 'fit') { 28258 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 28259 28260 newWidth = dims.width, 28261 newHeight = dims.height; 28262 } else if (viewport.toLowerCase() == 'stretch') { 28263 newWidth = newWidth, 28264 newHeight = newHeight; 28265 } else { 28266 var scale = (width > newWidth || height > newHeight) ? true : false, 28267 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 28268 newWidth = dims.width, 28269 newHeight = dims.height; 28270 } 28271 28272 currentHolder.data({ 28273 naturalWidthOld: currentHolder.data('naturalWidth'), 28274 naturalHeightOld: currentHolder.data('naturalHeight'), 28275 naturalWidth: newWidth, 28276 naturalHeight: newHeight 28277 }); 28278 } 28279 28280 $.each(elements, function(key, val) { 28281 val.addClass('ilightbox-fullscreen'); 28282 }); 28283 28284 //Trigger the onEnterFullScreen callback 28285 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 28286 } else { 28287 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 28288 vars.overlay.css({ 28289 opacity: iL.options.overlay.opacity 28290 }); 28291 28292 $.each(hideElements, function(i, element) { 28293 element.show(); 28294 }); 28295 28296 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 28297 28298 currentHolder.data({ 28299 naturalWidth: currentHolder.data('naturalWidthOld'), 28300 naturalHeight: currentHolder.data('naturalHeightOld'), 28301 naturalWidthOld: null, 28302 naturalHeightOld: null 28303 }); 28304 28305 $.each(elements, function(key, val) { 28306 val.removeClass('ilightbox-fullscreen'); 28307 }); 28308 28309 //Trigger the onExitFullScreen callback 28310 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 28311 } 28312 } else { 28313 if (!vars.isInFullScreen) vars.isInFullScreen = true; 28314 else vars.isInFullScreen = false; 28315 } 28316 iL.repositionPhoto(true); 28317 }, 28318 28319 closeAction: function() { 28320 var iL = this, 28321 vars = iL.vars, 28322 opts = iL.options; 28323 28324 $win.unbind('.iLightBox'); 28325 $doc.off('.iLightBox'); 28326 28327 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 28328 28329 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 28330 28331 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 28332 vars.overlay.remove(); 28333 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 28334 }); 28335 else { 28336 vars.overlay.remove(); 28337 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 28338 } 28339 28340 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 28341 28342 $.each(fadeOuts, function(i, element) { 28343 element.removeAttr('style').remove(); 28344 }); 28345 28346 vars.dontGenerateThumbs = vars.isInFullScreen = false; 28347 28348 window.iLightBox = null; 28349 28350 if (opts.linkId) { 28351 vars.hashLock = true; 28352 removeHash(); 28353 setTimeout(function() { 28354 vars.hashLock = false; 28355 }, 55); 28356 } 28357 28358 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 28359 28360 //Trigger the onHide callback 28361 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 28362 }, 28363 28364 repositionPhoto: function() { 28365 var iL = this, 28366 vars = iL.vars, 28367 opts = iL.options, 28368 path = opts.path.toLowerCase(), 28369 viewport = getViewport(), 28370 winWidth = viewport.width, 28371 winHeight = viewport.height; 28372 28373 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 28374 28375 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 28376 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 28377 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 28378 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 28379 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, 28380 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))); 28381 28382 var elObject = { 28383 type: 'current', 28384 width: width, 28385 height: height, 28386 item: iL.items[vars.current], 28387 offsetW: offsetW, 28388 offsetH: offsetH,
28389 thumbsOffsetW: thumbsOffsetW, 28390 thumbsOffsetH: thumbsOffsetH, 28391 animate: arguments.length, 28392 holder: vars.holder 28393 }; 28394 28395 iL.repositionEl(elObject); 28396 28397 if (iL.items[vars.next]) { 28398 elObject = $.extend(elObject, { 28399 type: 'next', 28400 item: iL.items[vars.next], 28401 offsetX: opts.styles.nextOffsetX, 28402 offsetY: opts.styles.nextOffsetY, 28403 holder: vars.nextPhoto 28404 }); 28405 28406 iL.repositionEl(elObject); 28407 } 28408 28409 if (iL.items[vars.prev]) { 28410 elObject = $.extend(elObject, { 28411 type: 'prev', 28412 item: iL.items[vars.prev], 28413 offsetX: opts.styles.nextOffsetX, 28414 offsetY: opts.styles.prevOffsetY, 28415 holder: vars.prevPhoto 28416 }); 28417 28418 iL.repositionEl(elObject); 28419 } 28420 28421 var loaderCss = (path == "horizontal") ? { 28422 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 28423 } : { 28424 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 28425 }; 28426 vars.loader.css(loaderCss); 28427 }, 28428 28429 repositionEl: function(obj) { 28430 var iL = this, 28431 vars = iL.vars, 28432 opts = iL.options, 28433 path = opts.path.toLowerCase(), 28434 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 28435 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 28436 itemParent = obj.item, 28437 item = obj.item.options, 28438 holder = obj.holder, 28439 offsetX = obj.offsetX || 0, 28440 offsetY = obj.offsetY || 0, 28441 //Uncode change ##START## 28442 toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0, 28443 //Uncode change ##END## 28444 thumbsOffsetW = obj.thumbsOffsetW, 28445 thumbsOffsetH = obj.thumbsOffsetH; 28446 28447 if (obj.type == 'current') { 28448 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); 28449 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); 28450 } else { 28451 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 28452 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 28453 } 28454 28455 28456 //Uncode change ##START## 28457 heightAvail = parseInt(heightAvail - toolbarHeight); 28458 // heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 28459 //Uncode change ##END## 28460 28461 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 28462 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 28463 28464 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 28465 width: width, 28466 height: height 28467 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 28468 newDims = $.extend({}, dims, {}); 28469 28470 if (obj.type == 'prev' || obj.type == 'next') 28471 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 28472 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 28473 else 28474 width = dims.width, 28475 height = dims.height; 28476 28477 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 28478 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); 28479 28480 switch (obj.type) { 28481 case 'current': 28482 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 28483 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 28484 break; 28485
28486 case 'next': 28487 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 28488 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 28489 break; 28490 28491 case 'prev': 28492 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 28493 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 28494 break; 28495 } 28496 28497 holder.data('offset', { 28498 top: top, 28499 left: left, 28500 newDims: newDims, 28501 diff: { 28502 W: widthDiff, 28503 H: heightDiff 28504 }, 28505 thumbsOffset: { 28506 W: thumbsOffsetW, 28507 H: thumbsOffsetH 28508 }, 28509 object: obj 28510 }); 28511 28512 var opacityMobile; 28513 if ( isMobile ) { 28514 opacityMobile = { 28515 opacity: 1, 28516 top: top, 28517 left: left 28518 }; 28519 } else { 28520 opacityMobile = { 28521 top: top, 28522 left: left 28523 }; 28524 } 28525 28526 if (obj.animate > 0 && opts.effects.reposition) { 28527 holder.css(transform, gpuAcceleration).stop().animate( 28528 opacityMobile, 28529 opts.effects.repositionSpeed, 'easeOutCirc', function() { 28530 holder.css(transform, ''); 28531 }); 28532 $('div.ilightbox-container', holder).stop().animate({ 28533 width: width, 28534 height: height 28535 }, opts.effects.repositionSpeed, 'easeOutCirc'); 28536 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 28537 width: width 28538 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 28539 $(this).css('overflow', 'visible'); 28540 }); 28541 } else { 28542 holder.css(opacityMobile); 28543 $('div.ilightbox-container', holder).css({ 28544 width: width, 28545 height: height 28546 }); 28547 $('div.ilightbox-inner-toolbar', holder).css({ 28548 width: width 28549 }); 28550 } 28551 }, 28552 28553 28554 resume: function(priority) { 28555 var iL = this, 28556 vars = iL.vars, 28557 opts = iL.options; 28558 28559 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 28560 return; 28561 } 28562 28563 vars.isPaused = 0; 28564 28565 if (vars.cycleID) { 28566 vars.cycleID = clearTimeout(vars.cycleID); 28567 } 28568 28569 vars.cycleID = setTimeout(function() { 28570 if (vars.current == vars.total - 1) iL.goTo(0); 28571 else iL.moveTo('next'); 28572 }, opts.slideshow.pauseTime); 28573 }, 28574 28575 pause: function(priority) { 28576 var iL = this, 28577 vars = iL.vars, 28578 opts = iL.options; 28579 28580 if (priority < vars.isPaused) { 28581 return; 28582 } 28583 28584 vars.isPaused = priority || 100; 28585 28586 if (vars.cycleID) { 28587 vars.cycleID = clearTimeout(vars.cycleID); 28588 } 28589 }, 28590 28591 resetCycle: function() { 28592 var iL = this, 28593 vars = iL.vars, 28594 opts = iL.options; 28595 28596 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 28597 iL.resume(); 28598 } 28599 }, 28600 28601 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 28602 var iL = this; 28603 28604 if (!width) factor = height / height_old; 28605 else if (!height) factor = width / width_old; 28606 else factor = min(width / width_old, height / height_old); 28607 28608 if (!thumb) { 28609 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 28610 else if (factor < iL.options.minScale) factor = iL.options.minScale; 28611 } 28612 28613 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 28614 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 28615 28616 return { 28617 width: final_width, 28618 height: final_height, 28619 ratio: factor 28620 }; 28621 }, 28622 28623 setOption: function(options) { 28624 var iL = this; 28625 28626 iL.options = $.extend(true, iL.options, options || {}); 28627 iL.refresh(); 28628 }, 28629 28630 availPlugins: function() { 28631 var iL = this, 28632 testEl = document.createElement("video"); 28633 28634 iL.plugins = { 28635 flash: !isMobile, 28636 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 28637 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 28638 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 28639 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 28640 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 28641 }; 28642 }, 28643 28644 addContent: function(element, obj) { 28645 var iL = this, 28646 el; 28647 28648 switch (obj.type) { 28649 case 'video': 28650 var HTML5 = false, 28651 videoType = obj.videoType, 28652 html5video = obj.options.html5video; 28653 28654 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 28655 obj.ext = 'mp4', 28656 obj.URL = html5video.h264 || obj.URL; 28657 else if (html5video.webm && iL.plugins.html5WebM) 28658 obj.ext = 'webm', 28659 obj.URL = html5video.webm || obj.URL; 28660 else if (html5video.ogg && iL.plugins.html5Vorbis) 28661 obj.ext = 'ogv', 28662 obj.URL = html5video.ogg || obj.URL; 28663 28664 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 28665 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 28666 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 28667 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 28668 28669 if (HTML5) { 28670 el = $('<video />
28670', { 28671 "width": "100%", 28672 "height": "100%", 28673 "preload": html5video.preload, 28674 "autoplay": html5video.autoplay, 28675 "loop": html5video.loop, 28676 "poster": html5video.poster, 28677 "controls": html5video.controls, 28678 "controlslist": "nodownload" 28679 }).append($('<source />', { 28680 "src": obj.URL, 28681 "type": videoType 28682 })); 28683 } else { 28684 if (!iL.plugins.quicktime) el = $('<span />', { 28685 "class": "ilightbox-alert", 28686 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 28687 }); 28688 else { 28689 28690 el = $('<object />', { 28691 "type": "video/quicktime", 28692 "pluginspage": pluginspages.quicktime 28693 }).attr({ 28694 "data": obj.URL, 28695 "width": "100%", 28696 "height": "100%" 28697 }).append($('<param />', { 28698 "name": "src", 28699 "value": obj.URL 28700 })).append($('<param />', { 28701 "name": "autoplay", 28702 "value": "false" 28703 })).append($('<param />', { 28704 "name": "loop", 28705 "value": "false" 28706 })).append($('<param />', { 28707 "name": "scale", 28708 "value": "tofit" 28709 })); 28710 28711 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 28712 } 28713 } 28714 28715 break; 28716 28717 case 'flash': 28718 if (!iL.plugins.flash) el = $('<span />', { 28719 "class": "ilightbox-alert", 28720 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 28721 }); 28722 else { 28723 var flashvars = "", 28724 i = 0; 28725 28726 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 28727 if (i != 0) flashvars += "&"; 28728 flashvars += k + "=" + encodeURIComponent(v); 28729 i++; 28730 }); 28731 else flashvars = null; 28732 28733 el = $('<embed />').attr({ 28734 "type": "application/x-shockwave-flash", 28735 "src": obj.URL, 28736 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 28737 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 28738 "quality": "high", 28739 "bgcolor": "#000000", 28740 "play": "true", 28741 "loop": "true", 28742 "menu": "true", 28743 "wmode": "transparent", 28744 "scale": "showall", 28745 "allowScriptAccess": "always", 28746 "allowFullScreen": "true", 28747 "flashvars": flashvars, 28748 "fullscreen": "yes" 28749 }); 28750 } 28751 28752 break; 28753 28754 case 'iframe': 28755 el = $('<iframe />').attr({ 28756 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 28757 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 28758 src: obj.URL, 28759 frameborder: 0, 28760 'hspace': 0, 28761 'vspace': 0, 28762 'scrolling': supportTouch ? 'auto' : 'scroll', 28763 'webkitAllowFullScreen': '', 28764 'mozallowfullscreen': '', 28765 'allowFullScreen': '' 28766 }); 28767 28768 break; 28769 28770 case 'inline': 28771 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 28772 28773 break; 28774 28775 case 'html': 28776 var object = obj.URL, 28777 el; 28778 28779 if (object[0].nodeName) { 28780 el = $('<div class="ilightbox-wrapper"></div>').html(object); 28781 } else { 28782 var dom = $(obj.URL), 28783 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 28784 el = $('<div class="ilightbox-wrapper"></div>').html(html); 28785 } 28786 28787 break; 28788 } 28789 28790 $('div.ilightbox-container', element).empty().html(el); 28791 28792 // For fixing Chrome about just playing the video for first time 28793 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 28794 var src = el[0].currentSrc + '?' + floor(random() * 30000); 28795 el[0].currentSrc = src; 28796 el[0].src = src; 28797 }); 28798 28799 return el; 28800 }, 28801 28802 ogpRecognition: function(obj, callback) { 28803 var iL = this, 28804 url = obj.URL; 28805 28806 iL.showLoader(); 28807 doAjax(url, function(data) { 28808 iL.hideLoader(); 28809 if (data) { 28810 var object = new Object(); 28811 28812 object.length = false, 28813 object.url = data.url; 28814 28815 if (data.status == 200) { 28816 var result = data.results, 28817 type = result.type, 28818 source = result.source; 28819 28820 object.source = source.src, 28821 object.width = source.width && parseInt(source.width) || 0, 28822 object.height = source.height && parseInt(source.height) || 0, 28823 object.type = type, 28824 object.thumbnail = source.thumbnail || result.images && result.images[0], 28825 object.html5video = result.html5video || {}, 28826 object.length = true; 28827 28828 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 28829 else if (source.type.indexOf("video/") != -1) object.type = "video"; 28830 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 28831 else if (source.type.indexOf("image/") != -1) object.type = "image"; 28832 28833 } else if (typeof data.response != 'undefined') 28834 throw data.response; 28835 28836 callback.call(this, object.length ? object : false); 28837 } 28838 }); 28839 }, 28840 28841 hashChangeHandler: function(url) { 28842 var iL = this, 28843 vars = iL.vars, 28844 opts = iL.options, 28845 URL = url || window.location.href, 28846 hash = parseURI(URL).hash, 28847 split = hash.split('/'), 28848 index = split[1]; 28849 28850 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 28851 28852 if (index) { 28853 var target = split[1] || 0; 28854 if (iL.items[target]) {
28855 var overlay = $('.ilightbox-overlay'); 28856 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 28857 iL.goTo(target); 28858 } else { 28859 iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click'); 28860 //iL.goTo(target); 28861 } 28862 } else { 28863 var overlay = $('.ilightbox-overlay'); 28864 if (overlay.length) iL.closeAction(); 28865 } 28866 } else { 28867 var overlay = $('.ilightbox-overlay'); 28868 if (overlay.length) iL.closeAction(); 28869 } 28870 } 28871 }; 28872 28873 /** 28874 * Parse style to pixels. 28875 * 28876 * @param {Object} $element jQuery object with element. 28877 * @param {Property} property CSS property to get the pixels from. 28878 * 28879 * @return {Int} 28880 */ 28881 function getPixel($element, property) { 28882 return parseInt($element.css(property), 10) || 0; 28883 } 28884 28885 /** 28886 * Make sure that number is within the limits. 28887 * 28888 * @param {Number} number 28889 * @param {Number} min 28890 * @param {Number} max 28891 * 28892 * @return {Number} 28893 */ 28894 function within(number, min, max) { 28895 return number < min ? min : number > max ? max : number; 28896 } 28897 28898 /** 28899 * Get viewport/window size (width and height). 28900 * 28901 * @return {Object} 28902 */ 28903 function getViewport() { 28904 var e = window, 28905 a = 'inner'; 28906 if (!('innerWidth' in window)) { 28907 a = 'client'; 28908 e = document.documentElement || document.body; 28909 } 28910 return { 28911 width: e[a + 'Width'], 28912 height: e[a + 'Height'] 28913 } 28914 } 28915 28916 /** 28917 * Remove hash tag from the URL 28918 * 28919 * @return {Void} 28920 */ 28921 function removeHash() { 28922 var scroll = getScrollXY(); 28923 28924 //UNCODE change 28925 // window.location.hash = ""; 28926 // history.pushState("", document.title, window.location.pathname + window.location.search); 28927 history.replaceState({}, document.title, window.location.pathname + window.location.search); 28928 28929 // Restore the scroll offset, should be flicker free 28930 window.scrollTo(scroll.x, scroll.y); 28931 } 28932 28933 /** 28934 * Do the ajax requests with callback. 28935 * 28936 * @param {String} url 28937 * @param {Function} callback 28938 * 28939 * @return {Void} 28940 */ 28941 function doAjax(url, callback) { 28942 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'); 28943 $.ajax({ 28944 url: url, 28945 dataType: 'jsonp' 28946 }); 28947 28948 iLCallback = function(data) { 28949 callback.call(this, data); 28950 }; 28951 } 28952 28953 /** 28954 * Find image from DOM elements 28955 * 28956 * @param {Element} element 28957 * 28958 * @return {Void} 28959 */ 28960 function findImageInElement(element) { 28961 var elements = $('*', element), 28962 imagesArr = new Array(); 28963 28964 elements.each(function() { 28965 var url = "", 28966 element = this; 28967 28968 if ($(element).css("background-image") != "none") { 28969 url = $(element).css("background-image"); 28970 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 28971 url = $(element).attr("src"); 28972 } 28973 28974 if (url.indexOf("gradient") == -1) { 28975 url = url.replace(/url\(\"/g, ""); 28976 url = url.replace(/url\(/g, ""); 28977 url = url.replace(/\"\)/g, ""); 28978 url = url.replace(/\)/g, ""); 28979 28980 var urls = url.split(","); 28981 28982 for (var i = 0; i < urls.length; i++) { 28983 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 28984 var extra = ""; 28985 if (browser.msie && browser.version < 9) { 28986 extra = "?" + floor(random() * 3000); 28987 } 28988 imagesArr.push(urls[i] + extra); 28989 } 28990 } 28991 } 28992 }); 28993 28994 return imagesArr; 28995 } 28996 28997 /** 28998 * Get file extension. 28999 * 29000 * @param {String} URL 29001 * 29002 * @return {String} 29003 */ 29004 function getExtension(URL) { 29005 if (URL !== null) { 29006 //UNCODE: fix issue to detect media type with query strings 29007 var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL; 29008 ext = ext.split('.').pop().toLowerCase(); 29009 29010 return ext; 29011 } 29012 } 29013 29014 /** 29015 * Get type via extension. 29016 * 29017 * @param {String} URL 29018 * 29019 * @return {String} 29020 */ 29021 function getTypeByExtension(URL) { 29022 var type, 29023 ext = getExtension(URL); 29024 29025 //Uncode addition ##START## 29026 if (URL == undefined) { 29027 return false; 29028 } 29029 //Uncode addition ##END## 29030 29031 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 29032 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 29033 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 29034 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 29035 else type = 'iframe'; 29036 29037 return type; 29038 } 29039 29040 /** 29041 * Return value from percent of a number. 29042 * 29043 * @param {Number} percent 29044 * @param {Number} total 29045 * 29046 * @return {Number} 29047 */ 29048 function percentToValue(percent, total) { 29049 return parseInt((total / 100) * percent); 29050 } 29051 29052 /** 29053 * A JavaScript equivalent of PHPâs parse_url. 29054 * 29055 * @param {String} url The URL to parse. 29056 * 29057 * @return {Mixed} 29058 */ 29059 function parseURI(url) { 29060 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 29061 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 29062 return (m ? { 29063 href: m[0] || '', 29064 protocol: m[1] || '', 29065 authority: m[2] || '', 29066 host: m[3] || '', 29067 hostname: m[4] || '', 29068 port: m[5] || '', 29069 pathname: m[6] || '', 29070 search: m[7] || '', 29071 hash: m[8] || '' 29072 } : null); 29073 } 29074 29075 /** 29076 * Gets the absolute URI. 29077 * 29078 * @param {String} href The relative URL. 29079 * @param {String} base The base URL. 29080 * 29081 * @return {String} The absolute URL. 29082 */ 29083 function absolutizeURI(base, href) { // RFC 3986 29084 var iL = this; 29085 29086 function removeDotSegments(input) { 29087 var output = []; 29088 input.replace(/^(\.\.?(\/|$))+/, '') 29089 .replace(/\/(\.(\/|$))+/g, '/') 29090 .replace(/\/\.\.$/, '/../') 29091 .replace(/\/?[^\/]*/g, function(p) { 29092 if (p === '/..') { 29093 output.pop(); 29094 } else { 29095 output.push(p); 29096 } 29097 }); 29098 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 29099 } 29100 29101 href = parseURI(href || ''); 29102 base = parseURI(base || ''); 29103 29104 return !href || !base ? null : (href.protocol || base.protocol) + 29105 (href.protocol || href.authority ? href.authority : base.authority) + 29106 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)) + 29107 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 29108 href.hash; 29109 } 29110 29111 /** 29112 * A JavaScript equivalent of PHPâs version_compare. 29113 * 29114 * @param {String} v1 29115 * @param {String} v2 29116 * @param {String} operator
29117 * 29118 * @return {Boolean} 29119 */ 29120 function version_compare(v1, v2, operator) { 29121 this.php_js = this.php_js || {}; 29122 this.php_js.ENV = this.php_js.ENV || {}; 29123 var i = 0, 29124 x = 0, 29125 compare = 0, 29126 vm = { 29127 'dev': -6, 29128 'alpha': -5, 29129 'a': -5, 29130 'beta': -4, 29131 'b': -4, 29132 'RC': -3, 29133 'rc': -3, 29134 '#': -2, 29135 'p': 1, 29136 'pl': 1 29137 }, 29138 prepVersion = function(v) { 29139 v = ('' + v).replace(/[_\-+]/g, '.'); 29140 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 29141 return (!v.length ? [-8] : v.split('.')); 29142 }, 29143 numVersion = function(v) { 29144 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 29145 }; 29146 v1 = prepVersion(v1); 29147 v2 = prepVersion(v2); 29148 x = max(v1.length, v2.length); 29149 for (i = 0; i < x; i++) { 29150 if (v1[i] == v2[i]) { 29151 continue; 29152 } 29153 v1[i] = numVersion(v1[i]); 29154 v2[i] = numVersion(v2[i]); 29155 if (v1[i] < v2[i]) { 29156 compare = -1; 29157 break; 29158 } else if (v1[i] > v2[i]) { 29159 compare = 1; 29160 break; 29161 } 29162 } 29163 if (!operator) { 29164 return compare; 29165 } 29166 29167 switch (operator) { 29168 case '>': 29169 case 'gt': 29170 return (compare > 0); 29171 case '>=': 29172 case 'ge': 29173 return (compare >= 0); 29174 case '<=': 29175 case 'le': 29176 return (compare <= 0); 29177 case '==': 29178 case '=': 29179 case 'eq': 29180 return (compare === 0); 29181 case '<>': 29182 case '!=': 29183 case 'ne': 29184 return (compare !== 0); 29185 case '': 29186 case '<': 29187 case 'lt': 29188 return (compare < 0); 29189 default: 29190 return null; 29191 } 29192 } 29193 29194 29195 // Begin the iLightBox plugin 29196 $.fn.iLightBox = function() { 29197 29198 var args = arguments, 29199 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 29200 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 29201 29202 if (!opt) opt = {}; 29203 29204 // Default options. Play carefully. 29205 var options = $.extend(true, { 29206 attr: 'href', 29207 path: 'vertical', 29208 skin: 'dark', 29209 linkId: false, 29210 infinite: false, 29211 startFrom: 0, 29212 randomStart: false, 29213 keepAspectRatio: true, 29214 maxScale: 1, 29215 minScale: .2, 29216 innerToolbar: false, 29217 smartRecognition: false, 29218 mobileOptimizer: true, 29219 fullAlone: true, 29220 fullViewPort: null, 29221 fullStretchTypes: 'flash, video', 29222 overlay: { 29223 blur: true, 29224 opacity: .85 29225 }, 29226 controls: { 29227 arrows: false, 29228 slideshow: false, 29229 toolbar: true, 29230 fullscreen: true, 29231 thumbnail: true, 29232 keyboard: true, 29233 mousewheel: true, 29234 swipe: true 29235 }, 29236 keyboard: { 29237 left: true, // previous 29238 right: true, // next 29239 up: true, // previous 29240 down: true, // next 29241 esc: true, // close 29242 shift_enter: true // fullscreen 29243 }, 29244 show: { 29245 effect: true, 29246 speed: 300, 29247 title: true 29248 }, 29249 hide: { 29250 effect: true, 29251 speed: 300 29252 }, 29253 caption: { 29254 start: true, 29255 show: 'mouseenter', 29256 hide: 'mouseleave' 29257 }, 29258 social: { 29259 start: true, 29260 show: 'mouseenter', 29261 hide: 'mouseleave',
29262 buttons: false 29263 }, 29264 styles: { 29265 pageOffsetX: 0, 29266 pageOffsetY: 0, 29267 nextOffsetX: 45, 29268 nextOffsetY: 0, 29269 nextOpacity: 1, 29270 nextScale: 1, 29271 prevOffsetX: 45, 29272 prevOffsetY: 0, 29273 prevOpacity: 1, 29274 prevScale: 1 29275 }, 29276 thumbnails: { 29277 maxWidth: 120, 29278 maxHeight: 80, 29279 normalOpacity: 1, 29280 activeOpacity: .6 29281 }, 29282 effects: { 29283 reposition: true, 29284 repositionSpeed: 200, 29285 switchSpeed: 500, 29286 loadedFadeSpeed: 180, 29287 fadeSpeed: 200 29288 }, 29289 slideshow: { 29290 pauseTime: 5000, 29291 pauseOnHover: false, 29292 startPaused: true 29293 }, 29294 text: { 29295 close: "Press Esc to close", 29296 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 29297 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 29298 slideShow: "Slideshow", 29299 next: "Next", 29300 previous: "Previous" 29301 }, 29302 errors: { 29303 loadImage: "An error occurred when trying to load photo.", 29304 loadContents: "An error occurred when trying to load contents.", 29305 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 29306 }, 29307 ajaxSetup: { 29308 url: '', 29309 beforeSend: function(jqXHR, settings) {}, 29310 cache: false, 29311 complete: function(jqXHR, textStatus) {}, 29312 crossDomain: false, 29313 error: function(jqXHR, textStatus, errorThrown) {}, 29314 success: function(data, textStatus, jqXHR) {}, 29315 global: true, 29316 ifModified: false, 29317 username: null, 29318 password: null, 29319 type: 'GET' 29320 }, 29321 callback: {} 29322 }, opt); 29323 29324 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 29325 29326 items = $.isArray(items) ? items : new Array(); 29327 29328 if (typeof args[0] == 'string') items[0] = args[0]; 29329 29330 if (version_compare($.fn.jquery, '1.8', '>=')) { 29331 var iLB = new iLightBox($(this), options, items, instant); 29332 return { 29333 close: function() { 29334 iLB.closeAction(); 29335 }, 29336 fullscreen: function() { 29337 iLB.fullScreenAction(); 29338 }, 29339 moveNext: function() { 29340 iLB.moveTo('next'); 29341 }, 29342 movePrev: function() { 29343 iLB.moveTo('prev'); 29344 }, 29345 goTo: function(index) { 29346 iLB.goTo(index); 29347 }, 29348 refresh: function() { 29349 iLB.refresh(); 29350 }, 29351 reposition: function() { 29352 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 29353 }, 29354 setOption: function(options) { 29355 iLB.setOption(options); 29356 }, 29357 destroy: function() { 29358 iLB.closeAction(); 29359 iLB.dispatchItemsEvents(); 29360 } 29361 }; 29362 } else { 29363 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 29364 } 29365 29366 }; 29367 29368 29369 $.iLightBox = function() { 29370 return $.fn.iLightBox(arguments[0], arguments[1]); 29371 }; 29372 29373 function getScrollXY() { 29374 var scrOfX = 0, 29375 scrOfY = 0; 29376 if (typeof(window.pageYOffset) == 'number') { 29377 //Netscape compliant 29378 scrOfY = window.pageYOffset; 29379 scrOfX = window.pageXOffset; 29380 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 29381 //DOM compliant 29382 scrOfY = document.body.scrollTop; 29383 scrOfX = document.body.scrollLeft; 29384 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 29385 //IE6 standards compliant mode 29386 scrOfY = document.documentElement.scrollTop; 29387 scrOfX = document.documentElement.scrollLeft; 29388 } 29389 return { 29390 x: scrOfX, 29391 y: scrOfY 29392 }; 29393 } 29394 29395 (function() { 29396 // add new event shortcuts 29397 $.each(("touchstart touchmove touchend " + 29398 "tap taphold " + 29399 "swipe swipeleft swiperight " + 29400 "scrollstart scrollstop").split(" "), function(i, name) { 29401 29402 $.fn[name] = function(fn) { 29403 return fn ? this.bind(name, fn) : this.trigger(name); 29404 }; 29405 29406 // jQuery < 1.8 29407 // if ($.attrFn) { 29408 // $.attrFn[name] = true; 29409 // } 29410 }); 29411 29412 var tapSettings = { 29413 startEvent: 'touchstart.iTap', 29414 endEvent: 'touchend.iTap' 29415 }; 29416 29417 // tap Event: 29418 $.event.special.itap = { 29419 setup: function() { 29420 29421 var self = this, 29422 $self = $(this), 29423 start, stop; 29424 29425 $self.bind(tapSettings.startEvent, function(event) { 29426 start = getScrollXY(); 29427 29428 $self.one(tapSettings.endEvent, function(event) { 29429 stop = getScrollXY(); 29430 29431 var orgEvent = event || window.event; 29432 event = $.event.fix(orgEvent); 29433 event.type = "itap"; 29434 29435 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 29436 29437 start = stop = undefined; 29438 }); 29439 }); 29440 }, 29441 29442 teardown: function() { 29443 $(this).unbind(tapSettings.startEvent); 29444 } 29445 }; 29446 }()); 29447 29448 29449 //Fullscreen API 29450 (function() { 29451 fullScreenApi = { 29452 supportsFullScreen: false, 29453 isFullScreen: function() { 29454 return false;
29455 }, 29456 requestFullScreen: function() {}, 29457 cancelFullScreen: function() {}, 29458 fullScreenEventName: '', 29459 prefix: '' 29460 }, 29461 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 29462 29463 // check for native support 29464 if (typeof document.cancelFullScreen != 'undefined') { 29465 fullScreenApi.supportsFullScreen = true; 29466 } else { 29467 // check for fullscreen support by vendor prefix 29468 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 29469 fullScreenApi.prefix = browserPrefixes[i]; 29470 29471 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 29472 fullScreenApi.supportsFullScreen = true; 29473 29474 break; 29475 } 29476 } 29477 } 29478 29479 // update methods to do something useful 29480 if (fullScreenApi.supportsFullScreen) { 29481 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 29482 29483 fullScreenApi.isFullScreen = function() { 29484 switch (this.prefix) { 29485 case '': 29486 return document.fullScreen; 29487 case 'webkit': 29488 return document.webkitIsFullScreen; 29489 default: 29490 return document[this.prefix + 'FullScreen']; 29491 } 29492 } 29493 fullScreenApi.requestFullScreen = function(el) { 29494 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 29495 } 29496 fullScreenApi.cancelFullScreen = function(el) { 29497 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 29498 } 29499 } 29500 }()); 29501 29502 // Browser detect 29503 (function() { 29504 function uaMatch(ua) { 29505 ua = ua.toLowerCase(); 29506 29507 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 29508 /(webkit)[ \/]([\w.]+)/.exec(ua) || 29509 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 29510 /(msie) ([\w.]+)/.exec(ua) || 29511 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 29512 29513 return { 29514 browser: match[1] || "", 29515 version: match[2] || "0" 29516 }; 29517 } 29518 29519 var matched = uaMatch(navigator.userAgent); 29520 browser = {}; 29521 29522 if (matched.browser) { 29523 browser[matched.browser] = true; 29524 browser.version = matched.version; 29525 } 29526 29527 // Chrome is Webkit, but Webkit is also Safari. 29528 if (browser.chrome) { 29529 browser.webkit = true; 29530 } else if (browser.webkit) { 29531 browser.safari = true; 29532 } 29533 }()); 29534 29535 // Feature detects 29536 (function() { 29537 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 29538 var el = document.createElement('div'); 29539 29540 function testProp(prop) { 29541 for (var p = 0, pl = prefixes.length; p < pl; p++) { 29542 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 29543 if (el.style[prefixedProp] !== undefined) { 29544 return prefixedProp; 29545 } 29546 } 29547 } 29548 29549 // Global support indicators 29550 transform = testProp('transform') || ''; 29551 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 29552 }()); 29553 29554 29555 /* 29556 PluginDetect v0.7.9 29557 www.pinlady.net/PluginDetect/license/ 29558 [ getVersion onWindowLoaded BetterIE ] 29559 [ Flash QuickTime Shockwave ] 29560 */ 29561 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;
29561d++){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);
29561d.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)}
29561c.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;
29561if(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(); 29562 29563 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)}; 29564 29565 29566 /* 29567 jQuery hashchange event v1.3 29568 https://github.com/cowboy/jquery-hashchange 29569 Copyright (c) 2010 "Cowboy" Ben Alman 29570 Dual licensed under the MIT and GPL licenses. 29571 */ 29572 (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= 29573 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|| 29574 "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;
29574a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 29575 29576 if (!Array.prototype.filter) { 29577 Array.prototype.filter = function(fun /*, thisp */ ) { 29578 "use strict"; 29579 29580 if (this == null) 29581 throw new TypeError(); 29582 29583 var t = Object(this); 29584 var len = t.length >>> 0; 29585 if (typeof fun != "function") 29586 throw new TypeError(); 29587 29588 var res = []; 29589 var thisp = arguments[1]; 29590 for (var i = 0; i < len; i++) { 29591 if (i in t) { 29592 var val = t[i]; // in case fun mutates this 29593 if (fun.call(thisp, val, i, t)) 29594 res.push(val); 29595 } 29596 } 29597 29598 return res; 29599 }; 29600 } 29601 29602 if (!Array.prototype.indexOf) { 29603 Array.prototype.indexOf = function(searchElement, fromIndex) { 29604 var k; 29605 29606 if (this == null) { 29607 throw new TypeError('"this" is null or not defined'); 29608 } 29609 29610 var O = Object(this); 29611 29612 var len = O.length >>> 0; 29613 29614 if (len === 0) { 29615 return -1; 29616 } 29617 29618 var n = +fromIndex || 0; 29619 29620 if (abs(n) === Infinity) { 29621 n = 0; 29622 } 29623 29624 if (n >= len) { 29625 return -1; 29626 } 29627 29628 k = max(n >= 0 ? n : len - abs(n), 0); 29629 29630 while (k < len) { 29631 var kValue; 29632 if (k in O && O[k] === searchElement) { 29633 return k; 29634 } 29635 k++; 29636 } 29637 return -1; 29638 }; 29639 } 29640 29641 if (!Array.prototype.lastIndexOf) { 29642 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 29643 "use strict"; 29644 29645 if (this == null) 29646 throw new TypeError(); 29647 29648 var t = Object(this); 29649 var len = t.length >>> 0; 29650 if (len === 0) 29651 return -1; 29652 29653 var n = len; 29654 if (arguments.length > 1) { 29655 n = Number(arguments[1]); 29656 if (n != n) 29657 n = 0; 29658 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 29659 n = (n > 0 || -1) * floor(abs(n)); 29660 } 29661 29662 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 29663 29664 for (; k >= 0; k--) { 29665 if (k in t && t[k] === searchElement) 29666 return k; 29667 } 29668 return -1; 29669 }; 29670 } 29671})(jQuery, this); 29672 29673/*! 29674 * lightgallery | 2.5.0 | June 13th 2022 29675 * http://www.lightgalleryjs.com/ 29676 * Copyright (c) 2020 Sachin Neravath; 29677 * @license GPLv3 29678 */ 29679 29680(function (global, factory) { 29681 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 29682 typeof define === 'function' && define.amd ? define(factory) : 29683 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory()); 29684}(this, (function () { 'use strict'; 29685 29686 /*! ***************************************************************************** 29687 Copyright (c) Microsoft Corporation. 29688 29689 Permission to use, copy, modify, and/or distribute this software for any 29690 purpose with or without fee is hereby granted. 29691 29692 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 29693 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 29694 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 29695 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 29696 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 29697 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29698 PERFORMANCE OF THIS SOFTWARE. 29699 ***************************************************************************** */ 29700 29701 var __assign = function() { 29702 __assign = Object.assign || function __assign(t) { 29703 for (var s, i = 1, n = arguments.length; i < n; i++) { 29704 s = arguments[i]; 29705 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 29706 } 29707 return t; 29708 }; 29709 return __assign.apply(this, arguments); 29710 }; 29711 29712 function __spreadArrays() { 29713 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 29714 for (var r = Array(s), k = 0, i = 0; i < il; i++) 29715 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 29716 r[k] = a[j]; 29717 return r; 29718 } 29719 29720 /** 29721 * List of lightGallery events 29722 * All events should be documented here 29723 * Below interfaces are used to build the website documentations 29724 * */ 29725 var lGEvents = { 29726 afterAppendSlide: 'lgAfterAppendSlide', 29727 init: 'lgInit', 29728 hasVideo: 'lgHasVideo', 29729 containerResize: 'lgContainerResize', 29730 updateSlides: 'lgUpdateSlides', 29731 afterAppendSubHtml: 'lgAfterAppendSubHtml', 29732 beforeOpen: 'lgBeforeOpen', 29733 afterOpen: 'lgAfterOpen', 29734 slideItemLoad: 'lgSlideItemLoad', 29735 beforeSlide: 'lgBeforeSlide', 29736 afterSlide: 'lgAfterSlide', 29737 posterClick: 'lgPosterClick', 29738 dragStart: 'lgDragStart', 29739 dragMove: 'lgDragMove', 29740 dragEnd: 'lgDragEnd', 29741 beforeNextSlide: 'lgBeforeNextSlide', 29742 beforePrevSlide: 'lgBeforePrevSlide', 29743 beforeClose: 'lgBeforeClose', 29744 afterClose: 'lgAfterClose', 29745 rotateLeft: 'lgRotateLeft', 29746 rotateRight: 'lgRotateRight', 29747 flipHorizontal: 'lgFlipHorizontal', 29748 flipVertical: 'lgFlipVertical', 29749 autoplay: 'lgAutoplay', 29750 autoplayStart: 'lgAutoplayStart', 29751 autoplayStop: 'lgAutoplayStop', 29752 }; 29753 29754 var lightGalleryCoreSettings = { 29755 mode: 'lg-slide', 29756 easing: 'ease', 29757 speed: 400, 29758 licenseKey: '0000-0000-000-0000', 29759 height: '100%', 29760 width: '100%', 29761 addClass: '', 29762 startClass: 'lg-start-zoom', 29763 backdropDuration: 300, 29764 container: '', 29765 startAnimationDuration: 400, 29766 zoomFromOrigin: true, 29767 hideBarsDelay: 0, 29768 showBarsAfter: 10000, 29769 slideDelay: 0, 29770 supportLegacyBrowser: true, 29771 allowMediaOverlap: false, 29772 videoMaxSize: '1280-720', 29773 loadYouTubePoster: true, 29774 defaultCaptionHeight: 0, 29775 ariaLabelledby: '', 29776 ariaDescribedby: '', 29777 resetScrollPosition: true, 29778 hideScrollbar: false, 29779 closable: true, 29780 swipeToClose: true, 29781 closeOnTap: true, 29782 showCloseIcon: true, 29783 showMaximizeIcon: false, 29784 loop: true, 29785 escKey: true, 29786 keyPress: true, 29787 trapFocus: true, 29788 controls: true, 29789 slideEndAnimation: true, 29790 hideControlOnEnd: false,
vendor: 17,869 bytes, lines 29791-30410
29791 mousewheel: false, 29792 getCaptionFromTitleOrAlt: true, 29793 appendSubHtmlTo: '.lg-sub-html', 29794 subHtmlSelectorRelative: false, 29795 preload: 2, 29796 numberOfSlideItemsInDom: 10, 29797 selector: '', 29798 selectWithin: '', 29799 nextHtml: '', 29800 prevHtml: '', 29801 index: 0, 29802 iframeWidth: '100%', 29803 iframeHeight: '100%', 29804 iframeMaxWidth: '100%', 29805 iframeMaxHeight: '100%', 29806 download: true, 29807 counter: true, 29808 appendCounterTo: '.lg-toolbar', 29809 swipeThreshold: 50, 29810 enableSwipe: true, 29811 enableDrag: true, 29812 dynamic: false, 29813 dynamicEl: [], 29814 extraProps: [], 29815 exThumbImage: '', 29816 isMobile: undefined, 29817 mobileSettings: { 29818 controls: false, 29819 showCloseIcon: false, 29820 download: false, 29821 }, 29822 plugins: [], 29823 strings: { 29824 closeGallery: 'Close gallery', 29825 toggleMaximize: 'Toggle maximize', 29826 previousSlide: 'Previous slide', 29827 nextSlide: 'Next slide', 29828 download: 'Download', 29829 playVideo: 'Play video', 29830 }, 29831 }; 29832 29833 function initLgPolyfills() { 29834 (function () { 29835 if (typeof window.CustomEvent === 'function') 29836 return false; 29837 function CustomEvent(event, params) { 29838 params = params || { 29839 bubbles: false, 29840 cancelable: false, 29841 detail: null, 29842 }; 29843 var evt = document.createEvent('CustomEvent'); 29844 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 29845 return evt; 29846 } 29847 window.CustomEvent = CustomEvent; 29848 })(); 29849 (function () { 29850 if (!Element.prototype.matches) { 29851 Element.prototype.matches = 29852 Element.prototype.msMatchesSelector || 29853 Element.prototype.webkitMatchesSelector; 29854 } 29855 })(); 29856 } 29857 var lgQuery = /** @class */ (function () { 29858 function lgQuery(selector) { 29859 this.cssVenderPrefixes = [ 29860 'TransitionDuration', 29861 'TransitionTimingFunction', 29862 'Transform', 29863 'Transition', 29864 ]; 29865 this.selector = this._getSelector(selector); 29866 this.firstElement = this._getFirstEl(); 29867 return this; 29868 } 29869 lgQuery.generateUUID = function () { 29870 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 29871 var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8; 29872 return v.toString(16); 29873 }); 29874 }; 29875 lgQuery.prototype._getSelector = function (selector, context) { 29876 if (context === void 0) { context = document; } 29877 if (typeof selector !== 'string') { 29878 return selector; 29879 } 29880 context = context || document; 29881 var fl = selector.substring(0, 1); 29882 if (fl === '#') { 29883 return context.querySelector(selector); 29884 } 29885 else { 29886 return context.querySelectorAll(selector); 29887 } 29888 }; 29889 lgQuery.prototype._each = function (func) { 29890 if (!this.selector) { 29891 return this; 29892 } 29893 if (this.selector.length !== undefined) { 29894 [].forEach.call(this.selector, func); 29895 } 29896 else { 29897 func(this.selector, 0); 29898 } 29899 return this; 29900 }; 29901 lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) { 29902 // prettier-ignore 29903 var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) { 29904 return group1.toUpperCase(); 29905 }); 29906 if (this.cssVenderPrefixes.indexOf(property) !== -1) { 29907 el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value; 29908 el.style['webkit' + property] = value; 29909 el.style['moz' + property] = value; 29910 el.style['ms' + property] = value; 29911 el.style['o' + property] = value; 29912 } 29913 else { 29914 el.style[property] = value; 29915 } 29916 }; 29917 lgQuery.prototype._getFirstEl = function () { 29918 if (this.selector && this.selector.length !== undefined) { 29919 return this.selector[0]; 29920 } 29921 else { 29922 return this.selector; 29923 } 29924 }; 29925 lgQuery.prototype.isEventMatched = function (event, eventName) { 29926 var eventNamespace = eventName.split('.'); 29927 return event 29928 .split('.') 29929 .filter(function (e) { return e; }) 29930 .every(function (e) { 29931 return eventNamespace.indexOf(e) !== -1; 29932 }); 29933 }; 29934 lgQuery.prototype.attr = function (attr, value) { 29935 if (value === undefined) { 29936 if (!this.firstElement) { 29937 return ''; 29938 } 29939 return this.firstElement.getAttribute(attr); 29940 } 29941 this._each(function (el) { 29942 el.setAttribute(attr, value); 29943 }); 29944 return this; 29945 }; 29946 lgQuery.prototype.find = function (selector) { 29947 return $LG(this._getSelector(selector, this.selector)); 29948 }; 29949 lgQuery.prototype.first = function () { 29950 if (this.selector && this.selector.length !== undefined) { 29951 return $LG(this.selector[0]); 29952 } 29953 else { 29954 return $LG(this.selector); 29955 } 29956 }; 29957 lgQuery.prototype.eq = function (index) { 29958 return $LG(this.selector[index]); 29959 }; 29960 lgQuery.prototype.parent = function () { 29961 return $LG(this.selector.parentElement); 29962 }; 29963 lgQuery.prototype.get = function () { 29964 return this._getFirstEl(); 29965 }; 29966 lgQuery.prototype.removeAttr = function (attributes) { 29967 var attrs = attributes.split(' '); 29968 this._each(function (el) { 29969 attrs.forEach(function (attr) { return el.removeAttribute(attr); }); 29970 }); 29971 return this; 29972 }; 29973 lgQuery.prototype.wrap = function (className) { 29974 if (!this.firstElement) { 29975 return this; 29976 } 29977 var wrapper = document.createElement('div'); 29978 wrapper.className = className; 29979 this.firstElement.parentNode.insertBefore(wrapper, this.firstElement); 29980 this.firstElement.parentNode.removeChild(this.firstElement); 29981 wrapper.appendChild(this.firstElement); 29982 return this; 29983 }; 29984 lgQuery.prototype.addClass = function (classNames) { 29985 if (classNames === void 0) { classNames = ''; } 29986 this._each(function (el) { 29987 // IE doesn't support multiple arguments 29988 classNames.split(' ').forEach(function (className) { 29989 if (className) { 29990 el.classList.add(className); 29991 } 29992 }); 29993 }); 29994 return this; 29995 }; 29996 lgQuery.prototype.removeClass = function (classNames) { 29997 this._each(function (el) { 29998 // IE doesn't support multiple arguments 29999 classNames.split(' ').forEach(function (className) { 30000 if (className) { 30001 el.classList.remove(className); 30002 } 30003 }); 30004 }); 30005 return this; 30006 }; 30007 lgQuery.prototype.hasClass = function (className) { 30008 if (!this.firstElement) { 30009 return false; 30010 } 30011 return this.firstElement.classList.contains(className); 30012 }; 30013 lgQuery.prototype.hasAttribute = function (attribute) { 30014 if (!this.firstElement) { 30015 return false; 30016 } 30017 return this.firstElement.hasAttribute(attribute); 30018 }; 30019 lgQuery.prototype.toggleClass = function (className) { 30020 if (!this.firstElement) { 30021 return this; 30022 } 30023 if (this.hasClass(className)) { 30024 this.removeClass(className); 30025 } 30026 else { 30027 this.addClass(className); 30028 } 30029 return this; 30030 }; 30031 lgQuery.prototype.css = function (property, value) { 30032 var _this = this; 30033 this._each(function (el) { 30034 _this._setCssVendorPrefix(el, property, value); 30035 }); 30036 return this; 30037 }; 30038 // Need to pass separate namespaces for separate elements 30039 lgQuery.prototype.on = function (events, listener) { 30040 var _this = this; 30041 if (!this.selector) { 30042 return this; 30043 } 30044 events.split(' ').forEach(function (event) { 30045 if (!Array.isArray(lgQuery.eventListeners[event])) { 30046 lgQuery.eventListeners[event] = []; 30047 } 30048 lgQuery.eventListeners[event].push(listener); 30049 _this.selector.addEventListener(event.split('.')[0], listener); 30050 }); 30051 return this; 30052 }; 30053 // @todo - test this 30054 lgQuery.prototype.once = function (event, listener) { 30055 var _this = this; 30056 this.on(event, function () { 30057 _this.off(event); 30058 listener(event); 30059 }); 30060 return this; 30061 }; 30062 lgQuery.prototype.off = function (event) { 30063 var _this = this; 30064 if (!this.selector) { 30065 return this; 30066 } 30067 Object.keys(lgQuery.eventListeners).forEach(function (eventName) { 30068 if (_this.isEventMatched(event, eventName)) { 30069 lgQuery.eventListeners[eventName].forEach(function (listener) { 30070 _this.selector.removeEventListener(eventName.split('.')[0], listener); 30071 }); 30072 lgQuery.eventListeners[eventName] = []; 30073 } 30074 }); 30075 return this; 30076 }; 30077 lgQuery.prototype.trigger = function (event, detail) { 30078 if (!this.firstElement) { 30079 return this; 30080 } 30081 var customEvent = new CustomEvent(event.split('.')[0], { 30082 detail: detail || null, 30083 }); 30084 this.firstElement.dispatchEvent(customEvent); 30085 return this; 30086 }; 30087 // Does not support IE 30088 lgQuery.prototype.load = function (url) { 30089 var _this = this; 30090 fetch(url) 30091 .then(function (res) { return res.text(); }) 30092 .then(function (html) { 30093 _this.selector.innerHTML = html; 30094 }); 30095 return this; 30096 }; 30097 lgQuery.prototype.html = function (html) { 30098 if (html === undefined) { 30099 if (!this.firstElement) { 30100 return ''; 30101 } 30102 return this.firstElement.innerHTML; 30103 } 30104 this._each(function (el) { 30105 el.innerHTML = html; 30106 }); 30107 return this; 30108 }; 30109 lgQuery.prototype.append = function (html) { 30110 this._each(function (el) { 30111 if (typeof html === 'string') { 30112 el.insertAdjacentHTML('beforeend', html); 30113 } 30114 else { 30115 el.appendChild(html); 30116 } 30117 }); 30118 return this; 30119 }; 30120 lgQuery.prototype.prepend = function (html) { 30121 this._each(function (el) { 30122 el.insertAdjacentHTML('afterbegin', html); 30123 }); 30124 return this; 30125 }; 30126 lgQuery.prototype.remove = function () { 30127 this._each(function (el) { 30128 el.parentNode.removeChild(el); 30129 }); 30130 return this; 30131 }; 30132 lgQuery.prototype.empty = function () { 30133 this._each(function (el) { 30134 el.innerHTML = ''; 30135 }); 30136 return this; 30137 }; 30138 lgQuery.prototype.scrollTop = function (scrollTop) { 30139 if (scrollTop !== undefined) { 30140 document.body.scrollTop = scrollTop; 30141 document.documentElement.scrollTop = scrollTop; 30142 return this; 30143 } 30144 else { 30145 return (window.pageYOffset || 30146 document.documentElement.scrollTop || 30147 document.body.scrollTop || 30148 0); 30149 } 30150 }; 30151 lgQuery.prototype.scrollLeft = function (scrollLeft) { 30152 if (scrollLeft !== undefined) { 30153 document.body.scrollLeft = scrollLeft; 30154 document.documentElement.scrollLeft = scrollLeft; 30155 return this; 30156 } 30157 else { 30158 return (window.pageXOffset || 30159 document.documentElement.scrollLeft || 30160 document.body.scrollLeft || 30161 0); 30162 } 30163 }; 30164 lgQuery.prototype.offset = function () { 30165 if (!this.firstElement) { 30166 return { 30167 left: 0, 30168 top: 0, 30169 }; 30170 } 30171 var rect = this.firstElement.getBoundingClientRect(); 30172 var bodyMarginLeft = $LG('body').style().marginLeft; 30173 // Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value 30174 return { 30175 left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(), 30176 top: rect.top + this.scrollTop(), 30177 }; 30178 }; 30179 lgQuery.prototype.style = function () { 30180 if (!this.firstElement) { 30181 return {}; 30182 } 30183 return (this.firstElement.currentStyle || 30184 window.getComputedStyle(this.firstElement)); 30185 }; 30186 // Width without padding and border even if box-sizing is used. 30187 lgQuery.prototype.width = function () { 30188 var style = this.style(); 30189 return (this.firstElement.clientWidth - 30190 parseFloat(style.paddingLeft) - 30191 parseFloat(style.paddingRight)); 30192 }; 30193 // Height without padding and border even if box-sizing is used. 30194 lgQuery.prototype.height = function () { 30195 var style = this.style(); 30196 return (this.firstElement.clientHeight - 30197 parseFloat(style.paddingTop) - 30198 parseFloat(style.paddingBottom)); 30199 }; 30200 lgQuery.eventListeners = {}; 30201 return lgQuery; 30202 }()); 30203 function $LG(selector) { 30204 initLgPolyfills(); 30205 return new lgQuery(selector); 30206 } 30207 30208 var defaultDynamicOptions = [ 30209 'src', 30210 'sources', 30211 'subHtml', 30212 'subHtmlUrl', 30213 'html', 30214 'video', 30215 'poster', 30216 'slideName', 30217 'responsive', 30218 'srcset', 30219 'sizes', 30220 'iframe', 30221 'downloadUrl', 30222 'download', 30223 'width', 30224 'facebookShareUrl', 30225 'tweetText', 30226 'iframeTitle', 30227 'twitterShareUrl', 30228 'pinterestShareUrl', 30229 'pinterestText', 30230 'fbHtml', 30231 'disqusIdentifier', 30232 'disqusUrl', 30233 ]; 30234 // Convert html data-attribute to camalcase 30235 function convertToData(attr) { 30236 // FInd a way for lgsize 30237 if (attr === 'href') { 30238 return 'src'; 30239 } 30240 attr = attr.replace('data-', ''); 30241 attr = attr.charAt(0).toLowerCase() + attr.slice(1); 30242 attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); 30243 return attr; 30244 } 30245 var utils = { 30246 /** 30247 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option 30248 */ 30249 //Uncode edit ##START## 30250 getSize: function (el, container, spacing, defaultLgSize, galleryItem) { 30251 // getSize: function (el, container, spacing, defaultLgSize) { 30252 //Uncode edit ##END## 30253 if (spacing === void 0) { spacing = 0; } 30254 var LGel = $LG(el); 30255 var lgSize = LGel.attr('data-lg-size') || defaultLgSize; 30256 //Uncode edit ##START## 30257 if ( typeof galleryItem.size && galleryItem.size != null ) { 30258 lgSize = galleryItem.size; 30259 } 30260 //Uncode edit ##END## 30261 if (!lgSize) { 30262 return; 30263 } 30264 var isResponsiveSizes = lgSize.split(','); 30265 // if at-least two viewport sizes are available 30266 if (isResponsiveSizes[1]) { 30267 var wWidth = window.innerWidth; 30268 for (var i = 0; i < isResponsiveSizes.length; i++) { 30269 var size_1 = isResponsiveSizes[i]; 30270 var responsiveWidth = parseInt(size_1.split('-')[2], 10); 30271 if (responsiveWidth > wWidth) { 30272 lgSize = size_1; 30273 break; 30274 } 30275 // take last item as last option 30276 if (i === isResponsiveSizes.length - 1) { 30277 lgSize = size_1; 30278 } 30279 } 30280 } 30281 var size = lgSize.split('-'); 30282 var width = parseInt(size[0], 10); 30283 var height = parseInt(size[1], 10); 30284 var cWidth = container.width(); 30285 var cHeight = container.height() - spacing; 30286 var maxWidth = Math.min(cWidth, width); 30287 var maxHeight = Math.min(cHeight, height); 30288 var ratio = Math.min(maxWidth / width, maxHeight / height); 30289 return { width: width * ratio, height: height * ratio }; 30290 }, 30291 /** 30292 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option 30293 * @param {jQuery Element} 30294 * @returns {String} Transform CSS string 30295 */ 30296 getTransform: function (el, container, top, bottom, imageSize) { 30297 if (!imageSize) { 30298 return; 30299 } 30300 var LGel = $LG(el).find('img').first(); 30301 if (!LGel.get()) { 30302 return; 30303 } 30304 var containerRect = container.get().getBoundingClientRect(); 30305 var wWidth = containerRect.width; 30306 // using innerWidth to include mobile safari bottom bar 30307 var wHeight = container.height() - (top + bottom); 30308 var elWidth = LGel.width(); 30309 var elHeight = LGel.height(); 30310 var elStyle = LGel.style(); 30311 var x = (wWidth - elWidth) / 2 - 30312 LGel.offset().left + 30313 (parseFloat(elStyle.paddingLeft) || 0) + 30314 (parseFloat(elStyle.borderLeft) || 0) + 30315 $LG(window).scrollLeft() + 30316 containerRect.left; 30317 var y = (wHeight - elHeight) / 2 - 30318 LGel.offset().top + 30319 (parseFloat(elStyle.paddingTop) || 0) + 30320 (parseFloat(elStyle.borderTop) || 0) + 30321 $LG(window).scrollTop() + 30322 top; 30323 var scX = elWidth / imageSize.width; 30324 var scY = elHeight / imageSize.height; 30325 var transform = 'translate3d(' + 30326 (x *= -1) + 30327 'px, ' + 30328 (y *= -1) + 30329 'px, 0) scale3d(' + 30330 scX + 30331 ', ' + 30332 scY + 30333 ', 1)'; 30334 return transform; 30335 }, 30336 getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) { 30337 var title = iframeTitle ? 'title="' + iframeTitle + '"' : ''; 30338 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>"; 30339 }, 30340 getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) { 30341 var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : ''; 30342 var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : ''; 30343 var imgMarkup = "<img " + altAttr + " " + srcsetAttr + " " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />"; 30344 var sourceTag = ''; 30345 if (sources) { 30346 var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources; 30347 sourceTag = sourceObj.map(function (source) { 30348 var attrs = ''; 30349 Object.keys(source).forEach(function (key) { 30350 // Do not remove the first space as it is required to separate the attributes 30351 attrs += " " + key + "=\"" + source[key] + "\""; 30352 }); 30353 return "<source " + attrs + "></source>"; 30354 }); 30355 } 30356 return "" + sourceTag + imgMarkup; 30357 }, 30358 // Get src from responsive src 30359 getResponsiveSrc: function (srcItms) { 30360 var rsWidth = []; 30361 var rsSrc = []; 30362 var src = ''; 30363 for (var i = 0; i < srcItms.length; i++) { 30364 var _src = srcItms[i].split(' '); 30365 // Manage empty space 30366 if (_src[0] === '') { 30367 _src.splice(0, 1); 30368 } 30369 rsSrc.push(_src[0]); 30370 rsWidth.push(_src[1]); 30371 } 30372 var wWidth = window.innerWidth; 30373 for (var j = 0; j < rsWidth.length; j++) { 30374 if (parseInt(rsWidth[j], 10) > wWidth) { 30375 src = rsSrc[j]; 30376 break; 30377 } 30378 } 30379 return src; 30380 }, 30381 isImageLoaded: function (img) { 30382 if (!img) 30383 return false; 30384 // During the onload event, IE correctly identifies any images that 30385 // werenât downloaded as not complete. Others should too. Gecko-based 30386 // browsers act like NS4 in that they report this incorrectly. 30387 if (!img.complete) { 30388 return false; 30389 } 30390 // However, they do have two very useful properties: naturalWidth and 30391 // naturalHeight. These give the true size of the image. If it failed 30392 // to load, either of these should be zero. 30393 if (img.naturalWidth === 0) { 30394 return false; 30395 } 30396 // No other way of checking: assume itâs ok. 30397 return true; 30398 }, 30399 getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) { 30400 var videoClass = ''; 30401 if (_isVideo && _isVideo.youtube) { 30402 videoClass = 'lg-has-youtube'; 30403 } 30404 else if (_isVideo && _isVideo.vimeo) { 30405 videoClass = 'lg-has-vimeo'; 30406 } 30407 else { 30408 videoClass = 'lg-has-html5'; 30409 } 30410 return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n <div class=\"lg-video-play-button\">
30410\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>"; 30411 }, 30412 getFocusableElements: function (container) { 30413 var elements = container.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])'); 30414 var visibleElements = [].filter.call(elements, function (element) { 30415 var style = window.getComputedStyle(element); 30416 return style.display !== 'none' && style.visibility !== 'hidden'; 30417 }); 30418 return visibleElements; 30419 }, 30420 /** 30421 * @desc Create dynamic elements array from gallery items when dynamic option is false 30422 * It helps to avoid frequent DOM interaction 30423 * and avoid multiple checks for dynamic elments 30424 * 30425 * @returns {Array} dynamicEl 30426 */ 30427 getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) { 30428 var dynamicElements = []; 30429 var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps); 30430 [].forEach.call(items, function (item) { 30431 var dynamicEl = {}; 30432 for (var i = 0; i < item.attributes.length; i++) { 30433 var attr = item.attributes[i]; 30434 if (attr.specified) { 30435 var dynamicAttr = convertToData(attr.name); 30436 var label = ''; 30437 if (availableDynamicOptions.indexOf(dynamicAttr) > -1) { 30438 label = dynamicAttr; 30439 } 30440 if (label) { 30441 dynamicEl[label] = attr.value; 30442 } 30443 } 30444 } 30445 var currentItem = $LG(item); 30446 var alt = currentItem.find('img').first().attr('alt') || currentItem.attr('data-alt'); 30447 var title = currentItem.attr('title'); 30448 //Uncode edit ##START## 30449 // var thumb = exThumbImage 30450 var thumb = exThumbImage && currentItem.attr(exThumbImage) 30451 //Uncode edit ##END## 30452 ? currentItem.attr(exThumbImage) 30453 : currentItem.find('img').first().attr('src'); 30454 dynamicEl.thumb = thumb; 30455 //Uncode edit ##START## 30456 if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) { 30457 // dynamicEl.subHtml = title || alt || ''; 30458 dynamicEl.subHtml = title || ''; 30459 } 30460 // dynamicEl.alt = alt || title || ''; 30461 dynamicEl.alt = alt || title; 30462 var inlineType = currentItem.attr('data-type'); 30463 dynamicEl.type = inlineType; 30464 //Uncode edit ##END## 30465 dynamicElements.push(dynamicEl); 30466 }); 30467 return dynamicElements; 30468 }, 30469 isMobile: function () { 30470 return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); 30471 }, 30472 /** 30473 * @desc Check the given src is video 30474 * @param {String} src 30475 * @return {Object} video type 30476 * Ex:{ youtube : ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] } 30477 * 30478 * @todo - this information can be moved to dynamicEl to avoid frequent calls 30479 */ 30480 isVideo: function (src, isHTML5VIdeo, index) { 30481 if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) { 30482 if (isHTML5VIdeo) { 30483 return { 30484 html5: true, 30485 }; 30486 } 30487 else { 30488 console.warn('lightGallery :- data-src is not provided on slide item ' + 30489 (index + 1) + 30490 '. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/'); 30491 return; 30492 } 30493 } 30494 var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i); 30495 var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i); 30496 var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/); 30497 if (youtube) { 30498 return { 30499 youtube: youtube, 30500 }; 30501 } 30502 else if (vimeo) { 30503 return { 30504 vimeo: vimeo, 30505 }; 30506 } 30507 else if (wistia) { 30508 return { 30509 wistia: wistia, 30510 }; 30511 } 30512 }, 30513 }; 30514 30515 // @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio 30516 // @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html 30517 // Unique id for each gallery 30518 var lgId = 0; 30519 var LightGallery = /** @class */ (function () { 30520 function LightGallery(element, options) { 30521 this.lgOpened = false;
vendor: 26,259 bytes, lines 30522-31201
30522 this.index = 0; 30523 // lightGallery modules 30524 this.plugins = []; 30525 // false when lightGallery load first slide content; 30526 this.lGalleryOn = false; 30527 // True when a slide animation is in progress 30528 this.lgBusy = false; 30529 this.currentItemsInDom = []; 30530 // Scroll top value before lightGallery is opened 30531 this.prevScrollTop = 0; 30532 this.bodyPaddingRight = 0; 30533 this.isDummyImageRemoved = false; 30534 this.dragOrSwipeEnabled = false; 30535 this.mediaContainerPosition = { 30536 top: 0, 30537 bottom: 0, 30538 }; 30539 if (!element) { 30540 return this; 30541 } 30542 lgId++; 30543 this.lgId = lgId; 30544 this.el = element; 30545 this.LGel = $LG(element); 30546 this.generateSettings(options); 30547 this.buildModules(); 30548 // When using dynamic mode, ensure dynamicEl is an array 30549 if (this.settings.dynamic && 30550 this.settings.dynamicEl !== undefined && 30551 !Array.isArray(this.settings.dynamicEl)) { 30552 throw 'When using dynamic mode, you must also define dynamicEl as an Array.'; 30553 } 30554 this.galleryItems = this.getItems(); 30555 this.normalizeSettings(); 30556 // Gallery items 30557 this.init(); 30558 //Uncode edit ##START## 30559 // this.validateLicense(); 30560 //Uncode edit ##END## 30561 return this; 30562 } 30563 LightGallery.prototype.generateSettings = function (options) { 30564 // lightGallery settings 30565 this.settings = __assign(__assign({}, lightGalleryCoreSettings), options); 30566 if (this.settings.isMobile && 30567 typeof this.settings.isMobile === 'function' 30568 ? this.settings.isMobile() 30569 : utils.isMobile()) { 30570 var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings); 30571 this.settings = __assign(__assign({}, this.settings), mobileSettings); 30572 } 30573 }; 30574 LightGallery.prototype.normalizeSettings = function () { 30575 if (this.settings.slideEndAnimation) { 30576 this.settings.hideControlOnEnd = false; 30577 } 30578 if (!this.settings.closable) { 30579 this.settings.swipeToClose = false; 30580 } 30581 // And reset it on close to get the correct value next time 30582 this.zoomFromOrigin = this.settings.zoomFromOrigin; 30583 // At the moment, Zoom from image doesn't support dynamic options 30584 // @todo add zoomFromOrigin support for dynamic images 30585 if (this.settings.dynamic) { 30586 this.zoomFromOrigin = false; 30587 } 30588 if (!this.settings.container) { 30589 this.settings.container = document.body; 30590 } 30591 // settings.preload should not be grater than $item.length 30592 this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length); 30593 }; 30594 LightGallery.prototype.init = function () { 30595 var _this = this; 30596 this.addSlideVideoInfo(this.galleryItems); 30597 this.buildStructure(); 30598 this.LGel.trigger(lGEvents.init, { 30599 instance: this, 30600 }); 30601 if (this.settings.keyPress) { 30602 this.keyPress(); 30603 } 30604 setTimeout(function () { 30605 _this.enableDrag(); 30606 _this.enableSwipe(); 30607 _this.triggerPosterClick(); 30608 }, 50); 30609 this.arrow(); 30610 if (this.settings.mousewheel) { 30611 this.mousewheel(); 30612 } 30613 if (!this.settings.dynamic) { 30614 this.openGalleryOnItemClick(); 30615 } 30616 }; 30617 LightGallery.prototype.openGalleryOnItemClick = function () { 30618 var _this = this; 30619 var _loop_1 = function (index) { 30620 var element = this_1.items[index]; 30621 var $element = $LG(element); 30622 // Using different namespace for click because click event should not unbind if selector is same object('this') 30623 // @todo manage all event listners - should have namespace that represent element 30624 var uuid = lgQuery.generateUUID(); 30625 $element 30626 .attr('data-lg-id', uuid) 30627 .on("click.lgcustom-item-" + uuid, function (e) { 30628 e.preventDefault(); 30629 var currentItemIndex = _this.settings.index || index; 30630 _this.openGallery(currentItemIndex, element); 30631 }); 30632 }; 30633 var this_1 = this; 30634 // Using for loop instead of using bubbling as the items can be any html element. 30635 for (var index = 0; index < this.items.length; index++) { 30636 _loop_1(index); 30637 } 30638 }; 30639 /** 30640 * Module constructor 30641 * Modules are build incrementally. 30642 * Gallery should be opened only once all the modules are initialized. 30643 * use moduleBuildTimeout to make sure this 30644 */ 30645 LightGallery.prototype.buildModules = function () { 30646 var _this = this; 30647 this.settings.plugins.forEach(function (plugin) { 30648 _this.plugins.push(new plugin(_this, $LG)); 30649 }); 30650 }; 30651 LightGallery.prototype.validateLicense = function () { 30652 if (!this.settings.licenseKey) { 30653 console.warn('Please provide a valid license key'); 30654 } 30655 else if (this.settings.licenseKey === '0000-0000-000-0000') { 30656 console.warn("lightGallery: " + this.settings.licenseKey + " license key is not valid for production use"); 30657 } 30658 }; 30659 LightGallery.prototype.getSlideItem = function (index) { 30660 return $LG(this.getSlideItemId(index)); 30661 }; 30662 LightGallery.prototype.getSlideItemId = function (index) { 30663 return "#lg-item-" + this.lgId + "-" + index; 30664 }; 30665 LightGallery.prototype.getIdName = function (id) { 30666 return id + "-" + this.lgId; 30667 }; 30668 LightGallery.prototype.getElementById = function (id) { 30669 return $LG("#" + this.getIdName(id)); 30670 }; 30671 LightGallery.prototype.manageSingleSlideClassName = function () { 30672 if (this.galleryItems.length < 2) { 30673 this.outer.addClass('lg-single-item'); 30674 } 30675 else { 30676 this.outer.removeClass('lg-single-item'); 30677 } 30678 }; 30679 LightGallery.prototype.buildStructure = function () { 30680 var _this = this; 30681 var container = this.$container && this.$container.get(); 30682 if (container) { 30683 return; 30684 } 30685 var controls = ''; 30686 var subHtmlCont = ''; 30687 // Create controls 30688 if (this.settings.controls) { 30689 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>"; 30690 } 30691 if (this.settings.appendSubHtmlTo !== '.lg-item') { 30692 subHtmlCont = 30693 '<div class="lg-sub-html" role="status" aria-live="polite"></div>'; 30694 } 30695 var addClasses = ''; 30696 if (this.settings.allowMediaOverlap) { 30697 // Do not remove space before last single quote 30698 addClasses += 'lg-media-overlap '; 30699 } 30700 var ariaLabelledby = this.settings.ariaLabelledby 30701 ? 'aria-labelledby="' + this.settings.ariaLabelledby + '"' 30702 : ''; 30703 var ariaDescribedby = this.settings.ariaDescribedby 30704 ? 'aria-describedby="' + this.settings.ariaDescribedby + '"' 30705 : ''; 30706 var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : ''); 30707 var closeIcon = this.settings.closable && this.settings.showCloseIcon 30708 ? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>" 30709 : ''; 30710 var maximizeIcon = this.settings.showMaximizeIcon 30711 ? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>" 30712 : ''; 30713 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' 30714 ? subHtmlCont 30715 : '') + "\n <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n " + (this.settings.appendSubHtmlTo === '.lg-sub-html' 30716 ? subHtmlCont 30717 : '') + "\n </div>\n </div>\n </div>\n "; 30718 $LG(this.settings.container).append(template); 30719 if (document.body !== this.settings.container) { 30720 $LG(this.settings.container).css('position', 'relative'); 30721 } 30722 this.outer = this.getElementById('lg-outer'); 30723 this.$lgComponents = this.getElementById('lg-components'); 30724 this.$backdrop = this.getElementById('lg-backdrop'); 30725 this.$container = this.getElementById('lg-container'); 30726 this.$inner = this.getElementById('lg-inner'); 30727 this.$content = this.getElementById('lg-content'); 30728 this.$toolbar = this.getElementById('lg-toolbar'); 30729 this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms'); 30730 var outerClassNames = this.settings.mode + " "; 30731 this.manageSingleSlideClassName(); 30732 if (this.settings.enableDrag) { 30733 outerClassNames += 'lg-grab '; 30734 } 30735 this.outer.addClass(outerClassNames); 30736 this.$inner.css('transition-timing-function', this.settings.easing); 30737 this.$inner.css('transition-duration', this.settings.speed + 'ms'); 30738 if (this.settings.download) { 30739 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>"); 30740 } 30741 this.counter(); 30742 $LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () { 30743 _this.refreshOnResize(); 30744 }); 30745 this.hideBars(); 30746 this.manageCloseGallery(); 30747 this.toggleMaximize(); 30748 this.initModules(); 30749 }; 30750 LightGallery.prototype.refreshOnResize = function () { 30751 if (this.lgOpened) { 30752 var currentGalleryItem = this.galleryItems[this.index]; 30753 var __slideVideoInfo = currentGalleryItem.__slideVideoInfo; 30754 this.mediaContainerPosition = this.getMediaContainerPosition(); 30755 var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom; 30756 //Uncode edit ##START## 30757 this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 30758 // this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize); 30759 //Uncode edit ##END## 30760 if (__slideVideoInfo) { 30761 this.resizeVideoSlide(this.index, this.currentImageSize); 30762 } 30763 if (this.zoomFromOrigin && !this.isDummyImageRemoved) { 30764 var imgStyle = this.getDummyImgStyles(this.currentImageSize); 30765 this.outer 30766 .find('.lg-current .lg-dummy-img') 30767 .first() 30768 .attr('style', imgStyle); 30769 } 30770 this.LGel.trigger(lGEvents.containerResize); 30771 } 30772 }; 30773 LightGallery.prototype.resizeVideoSlide = function (index, imageSize) { 30774 var lgVideoStyle = this.getVideoContStyle(imageSize); 30775 var currentSlide = this.getSlideItem(index); 30776 currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle); 30777 }; 30778 /** 30779 * Update slides dynamically. 30780 * Add, edit or delete slides dynamically when lightGallery is opened. 30781 * Modify the current gallery items and pass it via updateSlides method 30782 * @note 30783 * - Do not mutate existing lightGallery items directly. 30784 * - Always pass new list of gallery items 30785 * - You need to take care of thumbnails outside the gallery if any 30786 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method. 30787 * @param items Gallery items 30788 * @param index After the update operation, which slide gallery should navigate to 30789 * @category lGPublicMethods 30790 * @example 30791 * const plugin = lightGallery(); 30792 * 30793 * // Adding slides dynamically 30794 * let galleryItems = [ 30795 * // Access existing lightGallery items 30796 * // galleryItems are automatically generated internally from the gallery HTML markup 30797 * // or directly from galleryItems when dynamic gallery is used 30798 * ...plugin.galleryItems, 30799 * ...[ 30800 * { 30801 * src: 'img/img-1.png', 30802 * thumb: 'img/thumb1.png', 30803 * }, 30804 * ], 30805 * ]; 30806 * plugin.updateSlides( 30807 * galleryItems, 30808 * plugin.index, 30809 * ); 30810 * 30811 * 30812 * // Remove slides dynamically 30813 * galleryItems = JSON.parse( 30814 * JSON.stringify(updateSlideInstance.galleryItems), 30815 * ); 30816 * galleryItems.shift(); 30817 * updateSlideInstance.updateSlides(galleryItems, 1); 30818 * @see <a href="/demos/update-slides/">Demo</a> 30819 */ 30820 LightGallery.prototype.updateSlides = function (items, index) { 30821 if (this.index > items.length - 1) { 30822 this.index = items.length - 1; 30823 } 30824 if (items.length === 1) { 30825 this.index = 0; 30826 } 30827 if (!items.length) { 30828 this.closeGallery(); 30829 return; 30830 } 30831 var currentSrc = this.galleryItems[index].src; 30832 this.galleryItems = items; 30833 this.updateControls(); 30834 this.$inner.empty(); 30835 this.currentItemsInDom = []; 30836 var _index = 0; 30837 // Find the current index based on source value of the slide 30838 this.galleryItems.some(function (galleryItem, itemIndex) { 30839 if (galleryItem.src === currentSrc) { 30840 _index = itemIndex; 30841 return true; 30842 } 30843 return false; 30844 }); 30845 this.currentItemsInDom = this.organizeSlideItems(_index, -1); 30846 this.loadContent(_index, true); 30847 this.getSlideItem(_index).addClass('lg-current'); 30848 this.index = _index; 30849 this.updateCurrentCounter(_index); 30850 this.LGel.trigger(lGEvents.updateSlides); 30851 }; 30852 // Get gallery items based on multiple conditions 30853 LightGallery.prototype.getItems = function () { 30854 // Gallery items 30855 this.items = []; 30856 if (!this.settings.dynamic) { 30857 if (this.settings.selector === 'this') { 30858 this.items.push(this.el); 30859 } 30860 else if (this.settings.selector) { 30861 if (typeof this.settings.selector === 'string') { 30862 if (this.settings.selectWithin) { 30863 var selectWithin = $LG(this.settings.selectWithin); 30864 this.items = selectWithin 30865 .find(this.settings.selector) 30866 .get(); 30867 } 30868 else { 30869 this.items = this.el.querySelectorAll(this.settings.selector); 30870 } 30871 } 30872 else { 30873 this.items = this.settings.selector; 30874 } 30875 } 30876 else { 30877 this.items = this.el.children; 30878 } 30879 return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage); 30880 } 30881 else { 30882 return this.settings.dynamicEl || []; 30883 } 30884 }; 30885 LightGallery.prototype.shouldHideScrollbar = function () { 30886 return (this.settings.hideScrollbar && 30887 document.body === this.settings.container); 30888 }; 30889 LightGallery.prototype.hideScrollbar = function () { 30890 if (!this.shouldHideScrollbar()) { 30891 return; 30892 } 30893 this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight); 30894 var bodyRect = document.documentElement.getBoundingClientRect(); 30895 var scrollbarWidth = window.innerWidth - bodyRect.width; 30896 $LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px'); 30897 $LG(document.body).addClass('lg-overlay-open'); 30898 }; 30899 LightGallery.prototype.resetScrollBar = function () { 30900 if (!this.shouldHideScrollbar()) { 30901 return; 30902 } 30903 $LG(document.body).css('padding-right', this.bodyPaddingRight + 'px'); 30904 $LG(document.body).removeClass('lg-overlay-open'); 30905 }; 30906 /** 30907 * Open lightGallery. 30908 * Open gallery with specific slide by passing index of the slide as parameter. 30909 * @category lGPublicMethods 30910 * @param {Number} index - index of the slide 30911 * @param {HTMLElement} element - Which image lightGallery should zoom from 30912 * 30913 * @example 30914 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo'); 30915 * const dynamicGallery = lightGallery($dynamicGallery, { 30916 * dynamic: true, 30917 * dynamicEl: [ 30918 * { 30919 * src: 'img/1.jpg', 30920 * thumb: 'img/thumb-1.jpg', 30921 * subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>', 30922 * }, 30923 * ... 30924 * ], 30925 * }); 30926 * $dynamicGallery.addEventListener('click', function () { 30927 * // Starts with third item.(Optional). 30928 * // This is useful if you want use dynamic mode with 30929 * // custom thumbnails (thumbnails outside gallery), 30930 * dynamicGallery.openGallery(2); 30931 * }); 30932 * 30933 */ 30934 LightGallery.prototype.openGallery = function (index, element) { 30935 var _this = this; 30936 if (index === void 0) { index = this.settings.index; } 30937 // prevent accidental double execution 30938 if (this.lgOpened) 30939 return; 30940 this.lgOpened = true; 30941 this.outer.removeClass('lg-hide-items'); 30942 this.hideScrollbar(); 30943 // Add display block, but still has opacity 0 30944 this.$container.addClass('lg-show'); 30945 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index); 30946 this.currentItemsInDom = itemsToBeInsertedToDom; 30947 var items = ''; 30948 itemsToBeInsertedToDom.forEach(function (item) { 30949 items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>"); 30950 }); 30951 this.$inner.append(items); 30952 this.addHtml(index); 30953 var transform = ''; 30954 this.mediaContainerPosition = this.getMediaContainerPosition(); 30955 var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 30956 if (!this.settings.allowMediaOverlap) { 30957 this.setMediaContainerPosition(top, bottom); 30958 } 30959 var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo; 30960 if (this.zoomFromOrigin && element) { 30961 //Uncode edit ##START## 30962 this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 30963 // this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize); 30964 //Uncode edit ##END## 30965 transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize); 30966 } 30967 if (!this.zoomFromOrigin || !transform) { 30968 this.outer.addClass(this.settings.startClass); 30969 this.getSlideItem(index).removeClass('lg-complete'); 30970 } 30971 var timeout = this.settings.zoomFromOrigin 30972 ? 100 30973 : this.settings.backdropDuration; 30974 setTimeout(function () { 30975 _this.outer.addClass('lg-components-open'); 30976 }, timeout); 30977 this.index = index; 30978 //Uncode edit ##START## 30979 // this.LGel.trigger(lGEvents.beforeOpen); 30980 this.LGel.trigger(lGEvents.beforeOpen, { 30981 galleryItems: this.galleryItems, 30982 items: this.items, 30983 outer: this.outer, 30984 }); 30985 //Uncode edit ##END## 30986 // add class lg-current to remove initial transition 30987 this.getSlideItem(index).addClass('lg-current'); 30988 this.lGalleryOn = false; 30989 // Store the current scroll top value to scroll back after closing the gallery.. 30990 this.prevScrollTop = $LG(window).scrollTop(); 30991 setTimeout(function () { 30992 // Need to check both zoomFromOrigin and transform values as we need to set set the 30993 // default opening animation if user missed to add the lg-size attribute 30994 if (_this.zoomFromOrigin && transform) { 30995 var currentSlide_1 = _this.getSlideItem(index); 30996 currentSlide_1.css('transform', transform); 30997 setTimeout(function () { 30998 currentSlide_1 30999 .addClass('lg-start-progress lg-start-end-progress') 31000 .css('transition-duration', _this.settings.startAnimationDuration + 'ms'); 31001 _this.outer.addClass('lg-zoom-from-image'); 31002 }); 31003 setTimeout(function () { 31004 currentSlide_1.css('transform', 'translate3d(0, 0, 0)'); 31005 }, 100); 31006 } 31007 setTimeout(function () { 31008 _this.$backdrop.addClass('in'); 31009 _this.$container.addClass('lg-show-in'); 31010 }, 10); 31011 setTimeout(function () { 31012 if (_this.settings.trapFocus && 31013 document.body === _this.settings.container) { 31014 _this.trapFocus(); 31015 } 31016 }, _this.settings.backdropDuration + 50); 31017 // lg-visible class resets gallery opacity to 1 31018 if (!_this.zoomFromOrigin || !transform) { 31019 setTimeout(function () { 31020 _this.outer.addClass('lg-visible'); 31021 }, _this.settings.backdropDuration); 31022 } 31023 // initiate slide function 31024 _this.slide(index, false, false, false); 31025 _this.LGel.trigger(lGEvents.afterOpen); 31026 }); 31027 if (document.body === this.settings.container) { 31028 $LG('html').addClass('lg-on'); 31029 } 31030 }; 31031 /** 31032 * Note - Changing the position of the media on every slide transition creates a flickering effect. 31033 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption. 31034 * if you have dynamic captions for each media, 31035 * you can provide an appropriate height for the captions via allowMediaOverlap option 31036 */ 31037 LightGallery.prototype.getMediaContainerPosition = function () { 31038 if (this.settings.allowMediaOverlap) { 31039 return { 31040 top: 0, 31041 bottom: 0, 31042 }; 31043 } 31044 var top = this.$toolbar.get().clientHeight || 0; 31045 var subHtml = this.outer.find('.lg-components .lg-sub-html').get(); 31046 var captionHeight = this.settings.defaultCaptionHeight || 31047 (subHtml && subHtml.clientHeight) || 31048 0; 31049 var thumbContainer = this.outer.find('.lg-thumb-outer').get(); 31050 var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0; 31051 var bottom = thumbHeight + captionHeight; 31052 //Uncode edit ##START## 31053 bottom = bottom < 55 ? 55 : bottom; 31054 //Uncode edit ##END## 31055 return { 31056 top: top, 31057 bottom: bottom, 31058 }; 31059 }; 31060 LightGallery.prototype.setMediaContainerPosition = function (top, bottom) { 31061 if (top === void 0) { top = 0; } 31062 if (bottom === void 0) { bottom = 0; } 31063 this.$content.css('top', top + 'px').css('bottom', bottom + 'px'); 31064 }; 31065 LightGallery.prototype.hideBars = function () { 31066 var _this = this; 31067 // Hide controllers if mouse doesn't move for some period 31068 setTimeout(function () { 31069 _this.outer.removeClass('lg-hide-items'); 31070 if (_this.settings.hideBarsDelay > 0) { 31071 _this.outer.on('mousemove.lg click.lg touchstart.lg', function () { 31072 _this.outer.removeClass('lg-hide-items'); 31073 clearTimeout(_this.hideBarTimeout); 31074 // Timeout will be cleared on each slide movement also 31075 _this.hideBarTimeout = setTimeout(function () { 31076 _this.outer.addClass('lg-hide-items'); 31077 }, _this.settings.hideBarsDelay); 31078 }); 31079 _this.outer.trigger('mousemove.lg'); 31080 } 31081 }, this.settings.showBarsAfter); 31082 }; 31083 LightGallery.prototype.initPictureFill = function ($img) { 31084 if (this.settings.supportLegacyBrowser) { 31085 try { 31086 picturefill({ 31087 elements: [$img.get()], 31088 }); 31089 } 31090 catch (e) { 31091 console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.'); 31092 } 31093 } 31094 }; 31095 /** 31096 * @desc Create image counter 31097 * Ex: 1/10 31098 */ 31099 LightGallery.prototype.counter = function () { 31100 if (this.settings.counter) { 31101 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>"; 31102 this.outer.find(this.settings.appendCounterTo).append(counterHtml); 31103 } 31104 }; 31105 /** 31106 * @desc add sub-html into the slide 31107 * @param {Number} index - index of the slide 31108 */ 31109 LightGallery.prototype.addHtml = function (index) { 31110 var subHtml; 31111 var subHtmlUrl; 31112 if (this.galleryItems[index].subHtmlUrl) { 31113 subHtmlUrl = this.galleryItems[index].subHtmlUrl; 31114 } 31115 else { 31116 subHtml = this.galleryItems[index].subHtml; 31117 } 31118 if (!subHtmlUrl) { 31119 if (subHtml) { 31120 // get first letter of sub-html 31121 // if first letter starts with . or # get the html form the jQuery object 31122 var fL = subHtml.substring(0, 1); 31123 if (fL === '.' || fL === '#') { 31124 if (this.settings.subHtmlSelectorRelative && 31125 !this.settings.dynamic) { 31126 subHtml = $LG(this.items) 31127 .eq(index) 31128 .find(subHtml) 31129 .first() 31130 .html(); 31131 } 31132 else { 31133 subHtml = $LG(subHtml).first().html(); 31134 } 31135 } 31136 } 31137 else { 31138 subHtml = ''; 31139 } 31140 } 31141 if (this.settings.appendSubHtmlTo !== '.lg-item') { 31142 if (subHtmlUrl) { 31143 this.outer.find('.lg-sub-html').load(subHtmlUrl); 31144 } 31145 else { 31146 this.outer.find('.lg-sub-html').html(subHtml); 31147 } 31148 } 31149 else { 31150 var currentSlide = $LG(this.getSlideItemId(index)); 31151 if (subHtmlUrl) { 31152 currentSlide.load(subHtmlUrl); 31153 } 31154 else { 31155 currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>"); 31156 } 31157 } 31158 // Add lg-empty-html class if title doesn't exist 31159 if (typeof subHtml !== 'undefined' && subHtml !== null) { 31160 if (subHtml === '') { 31161 this.outer 31162 .find(this.settings.appendSubHtmlTo) 31163 .addClass('lg-empty-html'); 31164 } 31165 else { 31166 this.outer 31167 .find(this.settings.appendSubHtmlTo) 31168 .removeClass('lg-empty-html'); 31169 } 31170 } 31171 this.LGel.trigger(lGEvents.afterAppendSubHtml, { 31172 index: index, 31173 }); 31174 }; 31175 /** 31176 * @desc Preload slides 31177 * @param {Number} index - index of the slide 31178 * @todo preload not working for the first slide, Also, should work for the first and last slide as well 31179 */ 31180 LightGallery.prototype.preload = function (index) { 31181 for (var i = 1; i <= this.settings.preload; i++) { 31182 if (i >= this.galleryItems.length - index) { 31183 break; 31184 } 31185 this.loadContent(index + i, false); 31186 } 31187 for (var j = 1; j <= this.settings.preload; j++) { 31188 if (index - j < 0) { 31189 break; 31190 } 31191 this.loadContent(index - j, false); 31192 } 31193 }; 31194 LightGallery.prototype.getDummyImgStyles = function (imageSize) { 31195 if (!imageSize) 31196 return ''; 31197 return "width:" + imageSize.width + "px;\n margin-left: -" + imageSize.width / 2 + "px;\n margin-top: -" + imageSize.height / 2 + "px;\n height:" + imageSize.height + "px"; 31198 }; 31199 LightGallery.prototype.getVideoContStyle = function (imageSize) { 31200 if (!imageSize) 31201 return '';
31202 return "width:" + imageSize.width + "px;\n height:" + imageSize.height + "px"; 31203 }; 31204 LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) { 31205 var $currentItem; 31206 if (!this.settings.dynamic) { 31207 $currentItem = $LG(this.items).eq(index); 31208 } 31209 if ($currentItem) { 31210 var _dummyImgSrc = void 0; 31211 if (!this.settings.exThumbImage) { 31212 _dummyImgSrc = $currentItem.find('img').first().attr('src'); 31213 } 31214 else { 31215 _dummyImgSrc = $currentItem.attr(this.settings.exThumbImage); 31216 } 31217 if (!_dummyImgSrc) 31218 return ''; 31219 var imgStyle = this.getDummyImgStyles(this.currentImageSize); 31220 var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />"; 31221 $currentSlide.addClass('lg-first-slide'); 31222 this.outer.addClass('lg-first-slide-loading'); 31223 return dummyImgContent; 31224 } 31225 return ''; 31226 }; 31227 LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) { 31228 var currentGalleryItem = this.galleryItems[index]; 31229 var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources; 31230 // Use the thumbnail as dummy image which will be resized to actual image size and 31231 // displayed on top of actual image 31232 var imgContent = ''; 31233 var altAttr = alt ? 'alt="' + alt + '"' : ''; 31234 if (this.isFirstSlideWithZoomAnimation()) { 31235 imgContent = this.getDummyImageContent($currentSlide, index, altAttr); 31236 } 31237 else { 31238 imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources); 31239 } 31240 var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>"; 31241 $currentSlide.prepend(imgMarkup); 31242 }; 31243 LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) { 31244 var mediaObject = $slide.find('.lg-object').first(); 31245 if (utils.isImageLoaded(mediaObject.get()) || 31246 isHTML5VideoWithoutPoster) { 31247 onLoad(); 31248 } 31249 else { 31250 mediaObject.on('load.lg error.lg', function () { 31251 onLoad && onLoad(); 31252 }); 31253 mediaObject.on('error.lg', function () { 31254 onError && onError(); 31255 }); 31256 } 31257 }; 31258 /** 31259 * 31260 * @param $el Current slide item 31261 * @param index 31262 * @param delay Delay is 0 except first time 31263 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin 31264 * @param isFirstSlide 31265 */ 31266 LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) { 31267 var _this = this; 31268 //Uncode edit ##START## 31269 var $item = _this.galleryItems[index], 31270 type = $item.type; 31271 31272 if ( typeof $item.src !== 'undefined' ) { 31273 var inline_id = $item.src.replace('#', ''), 31274 $inline = document.getElementById(inline_id), 31275 inline_html; 31276 31277 if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) { 31278 inline_html = $inline.innerHTML; 31279 } else { 31280 inline_html = ''; 31281 } 31282 } 31283 //Uncode edit ##END## 31284 this.onSlideObjectLoad(currentSlide, true, function () { 31285 _this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide); 31286 }, function () { 31287 currentSlide.addClass('lg-complete lg-complete_'); 31288 //Uncode edit ##START## 31289 // currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>'); 31290 if ( inline_html !== '' ) { 31291 currentSlide.html(inline_html); 31292 } else { 31293 currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>'); 31294 } 31295 //Uncode edit ##END## 31296 }); 31297 }; 31298 LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) { 31299 var _this = this; 31300 var currentGalleryItem = this.galleryItems[index]; 31301 // Adding delay for video slides without poster for better performance and user experience 31302 // Videos should start playing once once the gallery is completely loaded 31303 var _speed = isFirstSlide &&
vendor: 3,676 bytes, lines 31304-31392
31304 this.getSlideType(currentGalleryItem) === 'video' && 31305 !currentGalleryItem.poster 31306 ? speed 31307 : 0; 31308 setTimeout(function () { 31309 $currentSlide.addClass('lg-complete lg-complete_'); 31310 _this.LGel.trigger(lGEvents.slideItemLoad, { 31311 index: index, 31312 delay: delay || 0, 31313 isFirstSlide: isFirstSlide, 31314 }); 31315 }, _speed); 31316 }; 31317 LightGallery.prototype.isFirstSlideWithZoomAnimation = function () { 31318 return !!(!this.lGalleryOn && 31319 this.zoomFromOrigin && 31320 this.currentImageSize); 31321 }; 31322 // Add video slideInfo 31323 LightGallery.prototype.addSlideVideoInfo = function (items) { 31324 var _this = this; 31325 items.forEach(function (element, index) { 31326 element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index); 31327 if (element.__slideVideoInfo && 31328 _this.settings.loadYouTubePoster && 31329 !element.poster && 31330 element.__slideVideoInfo.youtube) { 31331 element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg"; 31332 } 31333 }); 31334 }; 31335 /** 31336 * Load slide content into slide. 31337 * This is used to load content into slides that is not visible too 31338 * @param {Number} index - index of the slide. 31339 * @param {Boolean} rec - if true call loadcontent() function again. 31340 */ 31341 LightGallery.prototype.loadContent = function (index, rec) { 31342 var _this = this; 31343 var currentGalleryItem = this.galleryItems[index]; 31344 var $currentSlide = $LG(this.getSlideItemId(index)); 31345 var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources; 31346 var src = currentGalleryItem.src; 31347 var video = currentGalleryItem.video; 31348 var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video; 31349 if (currentGalleryItem.responsive) { 31350 var srcDyItms = currentGalleryItem.responsive.split(','); 31351 src = utils.getResponsiveSrc(srcDyItms) || src; 31352 } 31353 var videoInfo = currentGalleryItem.__slideVideoInfo; 31354 var lgVideoStyle = ''; 31355 var iframe = !!currentGalleryItem.iframe; 31356 var isFirstSlide = !this.lGalleryOn; 31357 // delay for adding complete class. it is 0 except first time. 31358 var delay = 0; 31359 if (isFirstSlide) { 31360 if (this.zoomFromOrigin && this.currentImageSize) { 31361 delay = this.settings.startAnimationDuration + 10; 31362 } 31363 else { 31364 delay = this.settings.backdropDuration + 10; 31365 } 31366 } 31367 if (!$currentSlide.hasClass('lg-loaded')) { 31368 if (videoInfo) { 31369 var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom; 31370 //Uncode edit ##START## 31371 var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 31372 // var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize); 31373 //Uncode edit ##END## 31374 lgVideoStyle = this.getVideoContStyle(videoSize); 31375 } 31376 if (iframe) { 31377 var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle); 31378 $currentSlide.prepend(markup); 31379 } 31380 else if (poster) { 31381 var dummyImg = ''; 31382 var hasStartAnimation = isFirstSlide && 31383 this.zoomFromOrigin && 31384 this.currentImageSize; 31385 if (hasStartAnimation) { 31386 dummyImg = this.getDummyImageContent($currentSlide, index, ''); 31387 } 31388 var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo); 31389 $currentSlide.prepend(markup); 31390 } 31391 //Uncode edit ##START## 31392 // else if (videoInfo) {
31393 else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') { 31394 if (! _html5Video) { 31395 var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>"; 31396 } 31397 //Uncode edit ##END## 31398 $currentSlide.prepend(markup); 31399 } 31400 else { 31401 //Uncode edit ##START## 31402 var $item = _this.galleryItems[index], 31403 type = $item.type; 31404 31405 if ( typeof $item.src !== 'undefined' ) { 31406 var inline_id = $item.src.replace('#', ''), 31407 $inline = document.getElementById(inline_id), 31408 inline_html; 31409 31410 if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) { 31411 inline_html = $inline.innerHTML; 31412 } else { 31413 inline_html = ''; 31414 } 31415 } 31416 if ( inline_html !== '' ) { 31417 $currentSlide.html(inline_html); 31418 } else { 31419 this.setImgMarkup(src, $currentSlide, index); 31420 if (srcset || sources) { 31421 var $img = $currentSlide.find('.lg-object'); 31422 this.initPictureFill($img); 31423 } 31424 } 31425 /*this.setImgMarkup(src, $currentSlide, index); 31426 if (srcset || sources) { 31427 var $img = $currentSlide.find('.lg-object'); 31428 this.initPictureFill($img); 31429 }*/ 31430 //Uncode edit ##END## 31431 } 31432 if (poster || videoInfo) { 31433 this.LGel.trigger(lGEvents.hasVideo, { 31434 index: index, 31435 src: src, 31436 html5Video: _html5Video, 31437 hasPoster: !!poster, 31438 }); 31439 } 31440 this.LGel.trigger(lGEvents.afterAppendSlide, { index: index }); 31441 if (this.lGalleryOn && 31442 this.settings.appendSubHtmlTo === '.lg-item') { 31443 this.addHtml(index); 31444 } 31445 } 31446 // For first time add some delay for displaying the start animation. 31447 var _speed = 0; 31448 // Do not change the delay value because it is required for zoom plugin. 31449 // If gallery opened from direct url (hash) speed value should be 0 31450 if (delay && !$LG(document.body).hasClass('lg-from-hash')) { 31451 _speed = delay; 31452 } 31453 // Only for first slide and zoomFromOrigin is enabled 31454 if (this.isFirstSlideWithZoomAnimation()) { 31455 setTimeout(function () { 31456 $currentSlide 31457 .removeClass('lg-start-end-progress lg-start-progress') 31458 .removeAttr('style'); 31459 }, this.settings.startAnimationDuration + 100); 31460 if (!$currentSlide.hasClass('lg-loaded')) { 31461 setTimeout(function () { 31462 if (_this.getSlideType(currentGalleryItem) === 'image') { 31463 var alt = currentGalleryItem.alt; 31464 var altAttr = alt ? 'alt="' + alt + '"' : ''; 31465 $currentSlide 31466 .find('.lg-img-wrap') 31467 .append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources)); 31468 if (srcset || sources) { 31469 var $img = $currentSlide.find('.lg-object'); 31470 _this.initPictureFill($img); 31471 } 31472 } 31473 if (_this.getSlideType(currentGalleryItem) === 'image' || 31474 (_this.getSlideType(currentGalleryItem) === 'video' && 31475 poster)) { 31476 _this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false); 31477 // load remaining slides once the slide is completely loaded 31478 _this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () { 31479 _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed); 31480 }, function () { 31481 _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed); 31482 }); 31483 } 31484 }, this.settings.startAnimationDuration + 100); 31485 } 31486 } 31487 // SLide content has been added to dom 31488 $currentSlide.addClass('lg-loaded'); 31489 if (!this.isFirstSlideWithZoomAnimation() || 31490 (this.getSlideType(currentGalleryItem) === 'video' && !poster)) { 31491 //Uncode edit ##START## 31492 // this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster)); 31493 this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.get
vendor: 31,133 bytes, lines 31493-32417
31493SlideType(currentGalleryItem) === 'audio')); 31494 //Uncode edit ##END## 31495 } 31496 // When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling 31497 if ((!this.zoomFromOrigin || !this.currentImageSize) && 31498 $currentSlide.hasClass('lg-complete_') && 31499 !this.lGalleryOn) { 31500 setTimeout(function () { 31501 $currentSlide.addClass('lg-complete'); 31502 }, this.settings.backdropDuration); 31503 } 31504 // Content loaded 31505 // Need to set lGalleryOn before calling preload function 31506 this.lGalleryOn = true; 31507 if (rec === true) { 31508 if (!$currentSlide.hasClass('lg-complete_')) { 31509 $currentSlide 31510 .find('.lg-object') 31511 .first() 31512 .on('load.lg error.lg', function () { 31513 _this.preload(index); 31514 }); 31515 } 31516 else { 31517 this.preload(index); 31518 } 31519 } 31520 }; 31521 /** 31522 * @desc Remove dummy image content and load next slides 31523 * Called only for the first time if zoomFromOrigin animation is enabled 31524 * @param index 31525 * @param $currentSlide 31526 * @param speed 31527 */ 31528 LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) { 31529 var _this = this; 31530 setTimeout(function () { 31531 $currentSlide.find('.lg-dummy-img').remove(); 31532 $currentSlide.removeClass('lg-first-slide'); 31533 _this.outer.removeClass('lg-first-slide-loading'); 31534 _this.isDummyImageRemoved = true; 31535 _this.preload(index); 31536 }, speed + 300); 31537 }; 31538 LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) { 31539 var _this = this; 31540 if (numberOfItems === void 0) { numberOfItems = 0; } 31541 var itemsToBeInsertedToDom = []; 31542 // Minimum 2 items should be there 31543 var possibleNumberOfItems = Math.max(numberOfItems, 3); 31544 possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length); 31545 var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex; 31546 if (this.galleryItems.length <= 3) { 31547 this.galleryItems.forEach(function (_element, index) { 31548 itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index); 31549 }); 31550 return itemsToBeInsertedToDom; 31551 } 31552 if (index < (this.galleryItems.length - 1) / 2) { 31553 for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) { 31554 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx); 31555 } 31556 var numberOfExistingItems = itemsToBeInsertedToDom.length; 31557 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) { 31558 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1)); 31559 } 31560 } 31561 else { 31562 for (var idx = index; idx <= this.galleryItems.length - 1 && 31563 idx < index + possibleNumberOfItems / 2; idx++) { 31564 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx); 31565 } 31566 var numberOfExistingItems = itemsToBeInsertedToDom.length; 31567 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) { 31568 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1)); 31569 } 31570 } 31571 if (this.settings.loop) { 31572 if (index === this.galleryItems.length - 1) { 31573 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0); 31574 } 31575 else if (index === 0) { 31576 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1)); 31577 } 31578 } 31579 if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) { 31580 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex); 31581 } 31582 return itemsToBeInsertedToDom; 31583 }; 31584 LightGallery.prototype.organizeSlideItems = function (index, prevIndex) { 31585 var _this = this; 31586 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom); 31587 itemsToBeInsertedToDom.forEach(function (item) { 31588 if (_this.currentItemsInDom.indexOf(item) === -1) { 31589 _this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>"); 31590 } 31591 }); 31592 this.currentItemsInDom.forEach(function (item) { 31593 if (itemsToBeInsertedToDom.indexOf(item) === -1) { 31594 $LG("#" + item).remove(); 31595 } 31596 }); 31597 return itemsToBeInsertedToDom; 31598 }; 31599 /** 31600 * Get previous index of the slide 31601 */ 31602 LightGallery.prototype.getPreviousSlideIndex = function () { 31603 var prevIndex = 0; 31604 try { 31605 var currentItemId = this.outer 31606 .find('.lg-current') 31607 .first() 31608 .attr('id'); 31609 prevIndex = parseInt(currentItemId.split('-')[3]) || 0; 31610 } 31611 catch (error) { 31612 prevIndex = 0; 31613 } 31614 return prevIndex; 31615 }; 31616 LightGallery.prototype.setDownloadValue = function (index) { 31617 if (this.settings.download) { 31618 var currentGalleryItem = this.galleryItems[index]; 31619 var hideDownloadBtn = currentGalleryItem.downloadUrl === false || 31620 currentGalleryItem.downloadUrl === 'false'; 31621 if (hideDownloadBtn) { 31622 this.outer.addClass('lg-hide-download'); 31623 } 31624 else { 31625 var $download = this.getElementById('lg-download'); 31626 this.outer.removeClass('lg-hide-download'); 31627 $download.attr('href', currentGalleryItem.downloadUrl || 31628 currentGalleryItem.src); 31629 if (currentGalleryItem.download) { 31630 //Uncode edit ##START## 31631 if ( typeof currentGalleryItem.video !== 'undefined' && currentGalleryItem.video ) { 31632 var currentVideo = JSON.parse( currentGalleryItem.video ), 31633 download_name = currentVideo.source[0].src; 31634 $download.attr('href', download_name).removeAttr('download'); 31635 } else { 31636 var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src, 31637 download_name = download_url.substring(download_url.lastIndexOf('/')+1); 31638 $download.attr('download', download_name); 31639 } 31640 // $download.attr('download', currentGalleryItem.download); 31641 //Uncode edit ##END## 31642 } 31643 } 31644 } 31645 }; 31646 LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) { 31647 var _this = this; 31648 if (this.lGalleryOn) { 31649 previousSlideItem.addClass('lg-slide-progress'); 31650 } 31651 setTimeout(function () { 31652 // remove all transitions 31653 _this.outer.addClass('lg-no-trans'); 31654 _this.outer 31655 .find('.lg-item') 31656 .removeClass('lg-prev-slide lg-next-slide'); 31657 if (direction === 'prev') { 31658 //prevslide 31659 currentSlideItem.addClass('lg-prev-slide'); 31660 previousSlideItem.addClass('lg-next-slide'); 31661 } 31662 else { 31663 // next slide 31664 currentSlideItem.addClass('lg-next-slide'); 31665 previousSlideItem.addClass('lg-prev-slide'); 31666 } 31667 // give 50 ms for browser to add/remove class 31668 setTimeout(function () { 31669 _this.outer.find('.lg-item').removeClass('lg-current'); 31670 currentSlideItem.addClass('lg-current'); 31671 // reset all transitions 31672 _this.outer.removeClass('lg-no-trans'); 31673 }, 50); 31674 }, this.lGalleryOn ? this.settings.slideDelay : 0); 31675 }; 31676 /** 31677 * Goto a specific slide. 31678 * @param {Number} index - index of the slide 31679 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag 31680 * @param {Boolean} fromThumb - true if slide function called via thumbnail click 31681 * @param {String} direction - Direction of the slide(next/prev) 31682 * @category lGPublicMethods 31683 * @example 31684 * const plugin = lightGallery(); 31685 * // to go to 3rd slide 31686 * plugin.slide(2); 31687 * 31688 */ 31689 LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) { 31690 var _this = this; 31691 var prevIndex = this.getPreviousSlideIndex(); 31692 this.currentItemsInDom = this.organizeSlideItems(index, prevIndex); 31693 // Prevent multiple call, Required for hsh plugin 31694 if (this.lGalleryOn && prevIndex === index) { 31695 return; 31696 } 31697 var numberOfGalleryItems = this.galleryItems.length; 31698 if (!this.lgBusy) { 31699 if (this.settings.counter) { 31700 this.updateCurrentCounter(index); 31701 } 31702 var currentSlideItem = this.getSlideItem(index); 31703 var previousSlideItem_1 = this.getSlideItem(prevIndex); 31704 var currentGalleryItem = this.galleryItems[index]; 31705 var videoInfo = currentGalleryItem.__slideVideoInfo; 31706 this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem)); 31707 this.setDownloadValue(index); 31708 if (videoInfo) { 31709 var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom; 31710 //Uncode edit ##START## 31711 var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 31712 // var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize); 31713 //Uncode edit ##END## 31714 this.resizeVideoSlide(index, videoSize); 31715 } 31716 this.LGel.trigger(lGEvents.beforeSlide, { 31717 prevIndex: prevIndex, 31718 index: index, 31719 fromTouch: !!fromTouch, 31720 fromThumb: !!fromThumb, 31721 //Uncode edit ##START## 31722 currentSlide: currentSlideItem, 31723 previousSlide: previousSlideItem_1, 31724 info: currentGalleryItem, 31725 item: this.items[index] 31726 //Uncode edit ##END## 31727 }); 31728 this.lgBusy = true; 31729 clearTimeout(this.hideBarTimeout); 31730 this.arrowDisable(index); 31731 if (!direction) { 31732 if (index < prevIndex) { 31733 direction = 'prev'; 31734 } 31735 else if (index > prevIndex) { 31736 direction = 'next'; 31737 } 31738 } 31739 if (!fromTouch) { 31740 this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1); 31741 } 31742 else { 31743 this.outer 31744 .find('.lg-item') 31745 .removeClass('lg-prev-slide lg-current lg-next-slide'); 31746 var touchPrev = void 0; 31747 var touchNext = void 0; 31748 if (numberOfGalleryItems > 2) { 31749 touchPrev = index - 1; 31750 touchNext = index + 1; 31751 if (index === 0 && prevIndex === numberOfGalleryItems - 1) { 31752 // next slide 31753 touchNext = 0; 31754 touchPrev = numberOfGalleryItems - 1; 31755 } 31756 else if (index === numberOfGalleryItems - 1 && 31757 prevIndex === 0) { 31758 // prev slide 31759 touchNext = 0; 31760 touchPrev = numberOfGalleryItems - 1; 31761 } 31762 } 31763 else { 31764 touchPrev = 0; 31765 touchNext = 1; 31766 } 31767 if (direction === 'prev') { 31768 this.getSlideItem(touchNext).addClass('lg-next-slide'); 31769 } 31770 else { 31771 this.getSlideItem(touchPrev).addClass('lg-prev-slide'); 31772 } 31773 currentSlideItem.addClass('lg-current'); 31774 } 31775 // Do not put load content in set timeout as it needs to load immediately when the gallery is opened 31776 if (!this.lGalleryOn) { 31777 this.loadContent(index, true); 31778 } 31779 else { 31780 setTimeout(function () { 31781 _this.loadContent(index, true); 31782 // Add title if this.settings.appendSubHtmlTo === lg-sub-html 31783 if (_this.settings.appendSubHtmlTo !== '.lg-item') { 31784 _this.addHtml(index); 31785 } 31786 }, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay)); 31787 } 31788 setTimeout(function () { 31789 _this.lgBusy = false; 31790 previousSlideItem_1.removeClass('lg-slide-progress'); 31791 _this.LGel.trigger(lGEvents.afterSlide, { 31792 prevIndex: prevIndex, 31793 index: index, 31794 fromTouch: fromTouch, 31795 fromThumb: fromThumb, 31796 }); 31797 }, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay)); 31798 } 31799 this.index = index; 31800 }; 31801 LightGallery.prototype.updateCurrentCounter = function (index) { 31802 this.getElementById('lg-counter-current').html(index + 1 + ''); 31803 }; 31804 LightGallery.prototype.updateCounterTotal = function () { 31805 this.getElementById('lg-counter-all').html(this.galleryItems.length + ''); 31806 }; 31807 LightGallery.prototype.getSlideType = function (item) { 31808 if (item.__slideVideoInfo) { 31809 return 'video'; 31810 } 31811 else if (item.iframe) { 31812 return 'iframe'; 31813 } 31814 //Uncode edit ##START## 31815 else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) { 31816 return 'audio'; 31817 } 31818 //Uncode edit ##END## 31819 else { 31820 return 'image'; 31821 } 31822 }; 31823 LightGallery.prototype.touchMove = function (startCoords, endCoords, e) { 31824 var distanceX = endCoords.pageX - startCoords.pageX; 31825 var distanceY = endCoords.pageY - startCoords.pageY; 31826 var allowSwipe = false; 31827 if (this.swipeDirection) { 31828 allowSwipe = true; 31829 } 31830 else { 31831 if (Math.abs(distanceX) > 15) { 31832 this.swipeDirection = 'horizontal'; 31833 allowSwipe = true; 31834 } 31835 else if (Math.abs(distanceY) > 15) { 31836 this.swipeDirection = 'vertical'; 31837 allowSwipe = true; 31838 } 31839 } 31840 if (!allowSwipe) { 31841 return; 31842 } 31843 var $currentSlide = this.getSlideItem(this.index); 31844 if (this.swipeDirection === 'horizontal') { 31845 e === null || e === void 0 ? void 0 : e.preventDefault(); 31846 // reset opacity and transition duration 31847 this.outer.addClass('lg-dragging'); 31848 // move current slide 31849 this.setTranslate($currentSlide, distanceX, 0); 31850 // move next and prev slide with current slide 31851 var width = $currentSlide.get().offsetWidth; 31852 var slideWidthAmount = (width * 15) / 100; 31853 var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100); 31854 this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0); 31855 this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0); 31856 } 31857 else if (this.swipeDirection === 'vertical') { 31858 if (this.settings.swipeToClose) { 31859 e === null || e === void 0 ? void 0 : e.preventDefault(); 31860 this.$container.addClass('lg-dragging-vertical'); 31861 var opacity = 1 - Math.abs(distanceY) / window.innerHeight; 31862 this.$backdrop.css('opacity', opacity); 31863 var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2); 31864 this.setTranslate($currentSlide, 0, distanceY, scale, scale); 31865 if (Math.abs(distanceY) > 100) { 31866 this.outer 31867 .addClass('lg-hide-items') 31868 .removeClass('lg-components-open'); 31869 } 31870 } 31871 } 31872 }; 31873 LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) { 31874 var _this = this; 31875 var distance; 31876 // keep slide animation for any mode while dragg/swipe 31877 if (this.settings.mode !== 'lg-slide') { 31878 this.outer.addClass('lg-slide'); 31879 } 31880 // set transition duration 31881 setTimeout(function () { 31882 _this.$container.removeClass('lg-dragging-vertical'); 31883 _this.outer 31884 .removeClass('lg-dragging lg-hide-items') 31885 .addClass('lg-components-open'); 31886 var triggerClick = true; 31887 if (_this.swipeDirection === 'horizontal') { 31888 distance = endCoords.pageX - startCoords.pageX; 31889 var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX); 31890 if (distance < 0 && 31891 distanceAbs > _this.settings.swipeThreshold) { 31892 _this.goToNextSlide(true); 31893 triggerClick = false; 31894 } 31895 else if (distance > 0 && 31896 distanceAbs > _this.settings.swipeThreshold) { 31897 _this.goToPrevSlide(true); 31898 triggerClick = false; 31899 } 31900 } 31901 else if (_this.swipeDirection === 'vertical') { 31902 distance = Math.abs(endCoords.pageY - startCoords.pageY); 31903 if (_this.settings.closable && 31904 _this.settings.swipeToClose && 31905 distance > 100) { 31906 _this.closeGallery(); 31907 return; 31908 } 31909 else { 31910 _this.$backdrop.css('opacity', 1); 31911 } 31912 } 31913 _this.outer.find('.lg-item').removeAttr('style'); 31914 if (triggerClick && 31915 Math.abs(endCoords.pageX - startCoords.pageX) < 5) { 31916 // Trigger click if distance is less than 5 pix 31917 var target = $LG(event.target); 31918 if (_this.isPosterElement(target)) { 31919 _this.LGel.trigger(lGEvents.posterClick); 31920 } 31921 } 31922 _this.swipeDirection = undefined; 31923 }); 31924 // remove slide class once drag/swipe is completed if mode is not slide 31925 setTimeout(function () { 31926 if (!_this.outer.hasClass('lg-dragging') && 31927 _this.settings.mode !== 'lg-slide') { 31928 _this.outer.removeClass('lg-slide'); 31929 } 31930 }, this.settings.speed + 100); 31931 }; 31932 LightGallery.prototype.enableSwipe = function () { 31933 var _this = this; 31934 var startCoords = {}; 31935 var endCoords = {}; 31936 var isMoved = false; 31937 var isSwiping = false; 31938 if (this.settings.enableSwipe) { 31939 this.$inner.on('touchstart.lg', function (e) { 31940 _this.dragOrSwipeEnabled = true; 31941 var $item = _this.getSlideItem(_this.index); 31942 if (($LG(e.target).hasClass('lg-item') || 31943 $item.get().contains(e.target)) && 31944 !_this.outer.hasClass('lg-zoomed') && 31945 !_this.lgBusy && 31946 e.targetTouches.length === 1) { 31947 isSwiping = true; 31948 _this.touchAction = 'swipe'; 31949 _this.manageSwipeClass(); 31950 startCoords = { 31951 pageX: e.targetTouches[0].pageX, 31952 pageY: e.targetTouches[0].pageY, 31953 }; 31954 } 31955 }); 31956 this.$inner.on('touchmove.lg', function (e) { 31957 if (isSwiping && 31958 _this.touchAction === 'swipe' && 31959 e.targetTouches.length === 1) { 31960 endCoords = { 31961 pageX: e.targetTouches[0].pageX, 31962 pageY: e.targetTouches[0].pageY, 31963 }; 31964 _this.touchMove(startCoords, endCoords, e); 31965 isMoved = true; 31966 } 31967 }); 31968 this.$inner.on('touchend.lg', function (event) { 31969 if (_this.touchAction === 'swipe') { 31970 if (isMoved) { 31971 isMoved = false; 31972 _this.touchEnd(endCoords, startCoords, event); 31973 } 31974 else if (isSwiping) { 31975 var target = $LG(event.target); 31976 if (_this.isPosterElement(target)) { 31977 _this.LGel.trigger(lGEvents.posterClick); 31978 } 31979 } 31980 _this.touchAction = undefined; 31981 isSwiping = false; 31982 } 31983 }); 31984 } 31985 }; 31986 LightGallery.prototype.enableDrag = function () { 31987 var _this = this; 31988 var startCoords = {}; 31989 var endCoords = {}; 31990 var isDraging = false; 31991 var isMoved = false; 31992 if (this.settings.enableDrag) { 31993 this.outer.on('mousedown.lg', function (e) { 31994 _this.dragOrSwipeEnabled = true; 31995 var $item = _this.getSlideItem(_this.index); 31996 if ($LG(e.target).hasClass('lg-item') || 31997 $item.get().contains(e.target)) { 31998 if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) { 31999 e.preventDefault(); 32000 if (!_this.lgBusy) { 32001 _this.manageSwipeClass(); 32002 startCoords = { 32003 pageX: e.pageX, 32004 pageY: e.pageY, 32005 }; 32006 isDraging = true; 32007 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 32008 _this.outer.get().scrollLeft += 1; 32009 _this.outer.get().scrollLeft -= 1; 32010 // * 32011 _this.outer 32012 .removeClass('lg-grab') 32013 .addClass('lg-grabbing'); 32014 _this.LGel.trigger(lGEvents.dragStart); 32015 } 32016 } 32017 } 32018 }); 32019 $LG(window).on("mousemove.lg.global" + this.lgId, function (e) { 32020 if (isDraging && _this.lgOpened) { 32021 isMoved = true; 32022 endCoords = { 32023 pageX: e.pageX, 32024 pageY: e.pageY, 32025 }; 32026 _this.touchMove(startCoords, endCoords); 32027 _this.LGel.trigger(lGEvents.dragMove); 32028 } 32029 }); 32030 $LG(window).on("mouseup.lg.global" + this.lgId, function (event) { 32031 if (!_this.lgOpened) { 32032 return; 32033 } 32034 var target = $LG(event.target); 32035 if (isMoved) { 32036 isMoved = false; 32037 _this.touchEnd(endCoords, startCoords, event); 32038 _this.LGel.trigger(lGEvents.dragEnd); 32039 } 32040 else if (_this.isPosterElement(target)) { 32041 _this.LGel.trigger(lGEvents.posterClick); 32042 } 32043 // Prevent execution on click 32044 if (isDraging) { 32045 isDraging = false; 32046 _this.outer.removeClass('lg-grabbing').addClass('lg-grab'); 32047 } 32048 }); 32049 } 32050 }; 32051 LightGallery.prototype.triggerPosterClick = function () { 32052 var _this = this; 32053 this.$inner.on('click.lg', function (event) { 32054 if (!_this.dragOrSwipeEnabled && 32055 _this.isPosterElement($LG(event.target))) { 32056 _this.LGel.trigger(lGEvents.posterClick); 32057 } 32058 }); 32059 }; 32060 LightGallery.prototype.manageSwipeClass = function () { 32061 var _touchNext = this.index + 1; 32062 var _touchPrev = this.index - 1; 32063 if (this.settings.loop && this.galleryItems.length > 2) { 32064 if (this.index === 0) { 32065 _touchPrev = this.galleryItems.length - 1; 32066 } 32067 else if (this.index === this.galleryItems.length - 1) { 32068 _touchNext = 0; 32069 } 32070 } 32071 this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide'); 32072 if (_touchPrev > -1) { 32073 this.getSlideItem(_touchPrev).addClass('lg-prev-slide'); 32074 } 32075 this.getSlideItem(_touchNext).addClass('lg-next-slide'); 32076 }; 32077 /** 32078 * Go to next slide 32079 * @param {Boolean} fromTouch - true if slide function called via touch event 32080 * @category lGPublicMethods 32081 * @example 32082 * const plugin = lightGallery(); 32083 * plugin.goToNextSlide(); 32084 * @see <a href="/demos/methods/">Demo</a> 32085 */ 32086 LightGallery.prototype.goToNextSlide = function (fromTouch) { 32087 var _this = this; 32088 var _loop = this.settings.loop; 32089 if (fromTouch && this.galleryItems.length < 3) { 32090 _loop = false; 32091 } 32092 if (!this.lgBusy) { 32093 if (this.index + 1 < this.galleryItems.length) { 32094 this.index++; 32095 this.LGel.trigger(lGEvents.beforeNextSlide, { 32096 index: this.index, 32097 }); 32098 this.slide(this.index, !!fromTouch, false, 'next'); 32099 } 32100 else { 32101 if (_loop) { 32102 this.index = 0; 32103 this.LGel.trigger(lGEvents.beforeNextSlide, { 32104 index: this.index, 32105 }); 32106 this.slide(this.index, !!fromTouch, false, 'next'); 32107 } 32108 else if (this.settings.slideEndAnimation && !fromTouch) { 32109 this.outer.addClass('lg-right-end'); 32110 setTimeout(function () { 32111 _this.outer.removeClass('lg-right-end'); 32112 }, 400); 32113 } 32114 } 32115 } 32116 }; 32117 /** 32118 * Go to previous slides 32119 * @param {Boolean} fromTouch - true if slide function called via touch event 32120 * @category lGPublicMethods 32121 * @example 32122 * const plugin = lightGallery({}); 32123 * plugin.goToPrevSlide(); 32124 * @see <a href="/demos/methods/">Demo</a> 32125 * 32126 */ 32127 LightGallery.prototype.goToPrevSlide = function (fromTouch) { 32128 var _this = this; 32129 var _loop = this.settings.loop; 32130 if (fromTouch && this.galleryItems.length < 3) { 32131 _loop = false; 32132 } 32133 if (!this.lgBusy) { 32134 if (this.index > 0) { 32135 this.index--; 32136 this.LGel.trigger(lGEvents.beforePrevSlide, { 32137 index: this.index, 32138 fromTouch: fromTouch, 32139 }); 32140 this.slide(this.index, !!fromTouch, false, 'prev'); 32141 } 32142 else { 32143 if (_loop) { 32144 this.index = this.galleryItems.length - 1; 32145 this.LGel.trigger(lGEvents.beforePrevSlide, { 32146 index: this.index, 32147 fromTouch: fromTouch, 32148 }); 32149 this.slide(this.index, !!fromTouch, false, 'prev'); 32150 } 32151 else if (this.settings.slideEndAnimation && !fromTouch) { 32152 this.outer.addClass('lg-left-end'); 32153 setTimeout(function () { 32154 _this.outer.removeClass('lg-left-end'); 32155 }, 400); 32156 } 32157 } 32158 } 32159 }; 32160 LightGallery.prototype.keyPress = function () { 32161 var _this = this; 32162 $LG(window).on("keydown.lg.global" + this.lgId, function (e) { 32163 if (_this.lgOpened && 32164 _this.settings.escKey === true && 32165 e.keyCode === 27) { 32166 e.preventDefault(); 32167 if (_this.settings.allowMediaOverlap && 32168 _this.outer.hasClass('lg-can-toggle') && 32169 _this.outer.hasClass('lg-components-open')) { 32170 _this.outer.removeClass('lg-components-open'); 32171 } 32172 else { 32173 _this.closeGallery(); 32174 } 32175 } 32176 if (_this.lgOpened && _this.galleryItems.length > 1) { 32177 if (e.keyCode === 37) { 32178 e.preventDefault(); 32179 _this.goToPrevSlide(); 32180 } 32181 if (e.keyCode === 39) { 32182 e.preventDefault(); 32183 _this.goToNextSlide(); 32184 } 32185 } 32186 }); 32187 }; 32188 LightGallery.prototype.arrow = function () { 32189 var _this = this; 32190 this.getElementById('lg-prev').on('click.lg', function () { 32191 _this.goToPrevSlide(); 32192 }); 32193 this.getElementById('lg-next').on('click.lg', function () { 32194 _this.goToNextSlide(); 32195 }); 32196 }; 32197 LightGallery.prototype.arrowDisable = function (index) { 32198 // Disable arrows if settings.hideControlOnEnd is true 32199 if (!this.settings.loop && this.settings.hideControlOnEnd) { 32200 var $prev = this.getElementById('lg-prev'); 32201 var $next = this.getElementById('lg-next'); 32202 if (index + 1 === this.galleryItems.length) { 32203 $next.attr('disabled', 'disabled').addClass('disabled'); 32204 } 32205 else { 32206 $next.removeAttr('disabled').removeClass('disabled'); 32207 } 32208 if (index === 0) { 32209 $prev.attr('disabled', 'disabled').addClass('disabled'); 32210 } 32211 else { 32212 $prev.removeAttr('disabled').removeClass('disabled'); 32213 } 32214 } 32215 }; 32216 LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) { 32217 if (scaleX === void 0) { scaleX = 1; } 32218 if (scaleY === void 0) { scaleY = 1; } 32219 $el.css('transform', 'translate3d(' + 32220 xValue + 32221 'px, ' + 32222 yValue + 32223 'px, 0px) scale3d(' + 32224 scaleX + 32225 ', ' + 32226 scaleY + 32227 ', 1)'); 32228 }; 32229 LightGallery.prototype.mousewheel = function () { 32230 var _this = this; 32231 var lastCall = 0; 32232 this.outer.on('wheel.lg', function (e) { 32233 if (!e.deltaY || _this.galleryItems.length < 2) { 32234 return; 32235 } 32236 e.preventDefault(); 32237 var now = new Date().getTime(); 32238 if (now - lastCall < 1000) { 32239 return; 32240 } 32241 lastCall = now; 32242 if (e.deltaY > 0) { 32243 _this.goToNextSlide(); 32244 } 32245 else if (e.deltaY < 0) { 32246 _this.goToPrevSlide(); 32247 } 32248 }); 32249 }; 32250 LightGallery.prototype.isSlideElement = function (target) { 32251 return (target.hasClass('lg-outer') || 32252 target.hasClass('lg-item') || 32253 target.hasClass('lg-img-wrap')); 32254 }; 32255 LightGallery.prototype.isPosterElement = function (target) { 32256 var playButton = this.getSlideItem(this.index) 32257 .find('.lg-video-play-button') 32258 .get(); 32259 return (target.hasClass('lg-video-poster') || 32260 target.hasClass('lg-video-play-button') || 32261 (playButton && playButton.contains(target.get()))); 32262 }; 32263 /** 32264 * Maximize minimize inline gallery. 32265 * @category lGPublicMethods 32266 */ 32267 LightGallery.prototype.toggleMaximize = function () { 32268 var _this = this; 32269 this.getElementById('lg-maximize').on('click.lg', function () { 32270 _this.$container.toggleClass('lg-inline'); 32271 _this.refreshOnResize(); 32272 }); 32273 }; 32274 LightGallery.prototype.invalidateItems = function () { 32275 for (var index = 0; index < this.items.length; index++) { 32276 var element = this.items[index]; 32277 var $element = $LG(element); 32278 $element.off("click.lgcustom-item-" + $element.attr('data-lg-id')); 32279 } 32280 }; 32281 LightGallery.prototype.trapFocus = function () { 32282 var _this = this; 32283 this.$container.get().focus({ 32284 preventScroll: true, 32285 }); 32286 $LG(window).on("keydown.lg.global" + this.lgId, function (e) { 32287 if (!_this.lgOpened) { 32288 return; 32289 } 32290 var isTabPressed = e.key === 'Tab' || e.keyCode === 9; 32291 if (!isTabPressed) { 32292 return; 32293 } 32294 var focusableEls = utils.getFocusableElements(_this.$container.get()); 32295 var firstFocusableEl = focusableEls[0]; 32296 var lastFocusableEl = focusableEls[focusableEls.length - 1]; 32297 if (e.shiftKey) { 32298 if (document.activeElement === firstFocusableEl) { 32299 lastFocusableEl.focus(); 32300 e.preventDefault(); 32301 } 32302 } 32303 else { 32304 if (document.activeElement === lastFocusableEl) { 32305 firstFocusableEl.focus(); 32306 e.preventDefault(); 32307 } 32308 } 32309 }); 32310 }; 32311 LightGallery.prototype.manageCloseGallery = function () { 32312 var _this = this; 32313 if (!this.settings.closable) 32314 return; 32315 var mousedown = false; 32316 this.getElementById('lg-close').on('click.lg', function () { 32317 _this.closeGallery(); 32318 }); 32319 if (this.settings.closeOnTap) { 32320 // If you drag the slide and release outside gallery gets close on chrome 32321 // for preventing this check mousedown and mouseup happened on .lg-item or lg-outer 32322 this.outer.on('mousedown.lg', function (e) { 32323 var target = $LG(e.target); 32324 if (_this.isSlideElement(target)) { 32325 mousedown = true; 32326 } 32327 else { 32328 mousedown = false; 32329 } 32330 }); 32331 this.outer.on('mousemove.lg', function () { 32332 mousedown = false; 32333 }); 32334 this.outer.on('mouseup.lg', function (e) { 32335 var target = $LG(e.target); 32336 if (_this.isSlideElement(target) && mousedown) { 32337 if (!_this.outer.hasClass('lg-dragging')) { 32338 _this.closeGallery(); 32339 } 32340 } 32341 }); 32342 } 32343 }; 32344 /** 32345 * Close lightGallery if it is opened. 32346 * 32347 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery 32348 * @return returns the estimated time to close gallery completely including the close animation duration 32349 * @category lGPublicMethods 32350 * @example 32351 * const plugin = lightGallery(); 32352 * plugin.closeGallery(); 32353 * 32354 */ 32355 LightGallery.prototype.closeGallery = function (force) { 32356 var _this = this; 32357 if (!this.lgOpened || (!this.settings.closable && !force)) { 32358 return 0; 32359 } 32360 this.LGel.trigger(lGEvents.beforeClose); 32361 if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) { 32362 $LG(window).scrollTop(this.prevScrollTop); 32363 } 32364 var currentItem = this.items[this.index]; 32365 var transform; 32366 if (this.zoomFromOrigin && currentItem) { 32367 var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom; 32368 var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster; 32369 //Uncode edit ##START## 32370 var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]); 32371 // var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize); 32372 //Uncode edit ##END## 32373 transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize); 32374 } 32375 if (this.zoomFromOrigin && transform) { 32376 this.outer.addClass('lg-closing lg-zoom-from-image'); 32377 this.getSlideItem(this.index) 32378 .addClass('lg-start-end-progress') 32379 .css('transition-duration', this.settings.startAnimationDuration + 'ms') 32380 .css('transform', transform); 32381 } 32382 else { 32383 this.outer.addClass('lg-hide-items'); 32384 // lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true 32385 // If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts 32386 this.outer.removeClass('lg-zoom-from-image'); 32387 } 32388 // Unbind all events added by lightGallery 32389 // @todo 32390 //this.$el.off('.lg.tm'); 32391 this.destroyModules(); 32392 this.lGalleryOn = false; 32393 this.isDummyImageRemoved = false; 32394 this.zoomFromOrigin = this.settings.zoomFromOrigin; 32395 clearTimeout(this.hideBarTimeout); 32396 this.hideBarTimeout = false; 32397 $LG('html').removeClass('lg-on'); 32398 this.outer.removeClass('lg-visible lg-components-open'); 32399 // Resetting opacity to 0 isd required as vertical swipe to close function adds inline opacity. 32400 this.$backdrop.removeClass('in').css('opacity', 0); 32401 var removeTimeout = this.zoomFromOrigin && transform 32402 ? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration) 32403 : this.settings.backdropDuration; 32404 this.$container.removeClass('lg-show-in'); 32405 // Once the closign animation is completed and gallery is invisible 32406 setTimeout(function () { 32407 if (_this.zoomFromOrigin && transform) { 32408 _this.outer.removeClass('lg-zoom-from-image'); 32409 } 32410 _this.$container.removeClass('lg-show'); 32411 // Reset scrollbar 32412 _this.resetScrollBar(); 32413 // Need to remove inline opacity as it is used in the stylesheet as well 32414 _this.$backdrop 32415 .removeAttr('style') 32416 .css('transition-duration', _this.settings.backdropDuration + 'ms'); 32417 _this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 32418-32621
32418 _this.getSlideItem(_this.index).removeClass('lg-start-end-progress'); 32419 _this.$inner.empty(); 32420 if (_this.lgOpened) { 32421 _this.LGel.trigger(lGEvents.afterClose, { 32422 instance: _this, 32423 }); 32424 } 32425 if (_this.$container.get()) { 32426 _this.$container.get().blur(); 32427 } 32428 _this.lgOpened = false; 32429 }, removeTimeout + 100); 32430 return removeTimeout + 100; 32431 }; 32432 LightGallery.prototype.initModules = function () { 32433 this.plugins.forEach(function (module) { 32434 try { 32435 module.init(); 32436 } 32437 catch (err) { 32438 console.warn("lightGallery:- make sure lightGallery module is properly initiated"); 32439 } 32440 }); 32441 }; 32442 LightGallery.prototype.destroyModules = function (destroy) { 32443 this.plugins.forEach(function (module) { 32444 try { 32445 if (destroy) { 32446 module.destroy(); 32447 } 32448 else { 32449 module.closeGallery && module.closeGallery(); 32450 } 32451 } 32452 catch (err) { 32453 console.warn("lightGallery:- make sure lightGallery module is properly destroyed"); 32454 } 32455 }); 32456 }; 32457 /** 32458 * Refresh lightGallery with new set of children. 32459 * 32460 * @description This is useful to update the gallery when the child elements are changed without calling destroy method. 32461 * 32462 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery 32463 * @see <a href="/demos/dynamic-mode/">Demo</a> 32464 * @category lGPublicMethods 32465 * @example 32466 * const plugin = lightGallery(); 32467 * // Delete or add children, then call 32468 * plugin.refresh(); 32469 * 32470 */ 32471 LightGallery.prototype.refresh = function (galleryItems) { 32472 if (!this.settings.dynamic) { 32473 this.invalidateItems(); 32474 } 32475 if (galleryItems) { 32476 this.galleryItems = galleryItems; 32477 } 32478 else { 32479 this.galleryItems = this.getItems(); 32480 } 32481 this.updateControls(); 32482 this.openGalleryOnItemClick(); 32483 this.LGel.trigger(lGEvents.updateSlides); 32484 }; 32485 LightGallery.prototype.updateControls = function () { 32486 this.addSlideVideoInfo(this.galleryItems); 32487 this.updateCounterTotal(); 32488 this.manageSingleSlideClassName(); 32489 }; 32490 /** 32491 * Destroy lightGallery. 32492 * Destroy lightGallery and its plugin instances completely 32493 * 32494 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance. 32495 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed. 32496 * You can use refresh method most of the times. 32497 * @category lGPublicMethods 32498 * @example 32499 * const plugin = lightGallery(); 32500 * plugin.destroy(); 32501 * 32502 */ 32503 LightGallery.prototype.destroy = function () { 32504 var _this = this; 32505 var closeTimeout = this.closeGallery(true); 32506 setTimeout(function () { 32507 _this.destroyModules(true); 32508 if (!_this.settings.dynamic) { 32509 _this.invalidateItems(); 32510 } 32511 $LG(window).off(".lg.global" + _this.lgId); 32512 _this.LGel.off('.lg'); 32513 _this.$container.remove(); 32514 }, closeTimeout); 32515 return closeTimeout; 32516 }; 32517 return LightGallery; 32518 }()); 32519 32520 function lightGallery(el, options) { 32521 return new LightGallery(el, options); 32522 } 32523 32524 return lightGallery; 32525 32526}))); 32527 32528/*! 32529 * lightgallery | 2.5.0 | June 13th 2022 32530 * http://www.lightgalleryjs.com/ 32531 * Copyright (c) 2020 Sachin Neravath; 32532 * @license GPLv3 32533 */ 32534 32535(function (global, factory) { 32536 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 32537 typeof define === 'function' && define.amd ? define(factory) : 32538 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory()); 32539}(this, (function () { 'use strict'; 32540 32541 /*! ***************************************************************************** 32542 Copyright (c) Microsoft Corporation. 32543 32544 Permission to use, copy, modify, and/or distribute this software for any 32545 purpose with or without fee is hereby granted. 32546 32547 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 32548 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 32549 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 32550 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 32551 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 32552 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 32553 PERFORMANCE OF THIS SOFTWARE. 32554 ***************************************************************************** */ 32555 32556 var __assign = function() { 32557 __assign = Object.assign || function __assign(t) { 32558 for (var s, i = 1, n = arguments.length; i < n; i++) { 32559 s = arguments[i]; 32560 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 32561 } 32562 return t; 32563 }; 32564 return __assign.apply(this, arguments); 32565 }; 32566 32567 var zoomSettings = { 32568 scale: 1, 32569 zoom: true, 32570 actualSize: true, 32571 showZoomInOutIcons: false, 32572 actualSizeIcons: { 32573 zoomIn: 'lg-zoom-in', 32574 zoomOut: 'lg-zoom-out', 32575 }, 32576 enableZoomAfter: 300, 32577 zoomPluginStrings: { 32578 zoomIn: 'Zoom in', 32579 zoomOut: 'Zoom out', 32580 viewActualSize: 'View actual size', 32581 }, 32582 }; 32583 32584 /** 32585 * List of lightGallery events 32586 * All events should be documented here 32587 * Below interfaces are used to build the website documentations 32588 * */ 32589 var lGEvents = { 32590 afterAppendSlide: 'lgAfterAppendSlide', 32591 init: 'lgInit', 32592 hasVideo: 'lgHasVideo', 32593 containerResize: 'lgContainerResize', 32594 updateSlides: 'lgUpdateSlides', 32595 afterAppendSubHtml: 'lgAfterAppendSubHtml', 32596 beforeOpen: 'lgBeforeOpen', 32597 afterOpen: 'lgAfterOpen', 32598 slideItemLoad: 'lgSlideItemLoad', 32599 beforeSlide: 'lgBeforeSlide', 32600 afterSlide: 'lgAfterSlide', 32601 posterClick: 'lgPosterClick', 32602 dragStart: 'lgDragStart', 32603 dragMove: 'lgDragMove', 32604 dragEnd: 'lgDragEnd', 32605 beforeNextSlide: 'lgBeforeNextSlide', 32606 beforePrevSlide: 'lgBeforePrevSlide', 32607 beforeClose: 'lgBeforeClose', 32608 afterClose: 'lgAfterClose', 32609 rotateLeft: 'lgRotateLeft', 32610 rotateRight: 'lgRotateRight', 32611 flipHorizontal: 'lgFlipHorizontal', 32612 flipVertical: 'lgFlipVertical', 32613 autoplay: 'lgAutoplay', 32614 autoplayStart: 'lgAutoplayStart', 32615 autoplayStop: 'lgAutoplayStop', 32616 }; 32617 32618 var Zoom = /** @class */ (function () { 32619 function Zoom(instance, $LG) { 32620 // get lightGallery core plugin instance 32621 this.core = instance;
32622 this.$LG = $LG; 32623 this.settings = __assign(__assign({}, zoomSettings), this.core.settings); 32624 return this; 32625 } 32626 // Append Zoom controls. Actual size, Zoom-in, Zoom-out 32627 Zoom.prototype.buildTemplates = function () { 32628 var zoomIcons = this.settings.showZoomInOutIcons 32629 ? "<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>" 32630 : ''; 32631 if (this.settings.actualSize) { 32632 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>"; 32633 } 32634 this.core.outer.addClass('lg-use-transition-for-zoom'); 32635 this.core.$toolbar.first().append(zoomIcons); 32636 }; 32637 /** 32638 * @desc Enable zoom option only once the image is completely loaded 32639 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted 32640 * 32641 * Zoom styles are defined under lg-zoomable CSS class. 32642 */ 32643 Zoom.prototype.enableZoom = function (event) { 32644 var _this = this; 32645 // delay will be 0 except first time 32646 var _speed = this.settings.enableZoomAfter + event.detail.delay; 32647 // set _speed value 0 if gallery opened from direct url and if it is first slide 32648 if (this.$LG('body').first().hasClass('lg-from-hash') && 32649 event.detail.delay) { 32650 // will execute only once 32651 _speed = 0; 32652 } 32653 else { 32654 // Remove lg-from-hash to enable starting animation. 32655 this.$LG('body').first().removeClass('lg-from-hash'); 32656 } 32657 this.zoomableTimeout = setTimeout(function () { 32658 if (!_this.isImageSlide()) { 32659 return; 32660 } 32661 _this.core.getSlideItem(event.detail.index).addClass('lg-zoomable'); 32662 if (event.detail.index === _this.core.index) { 32663 _this.setZoomEssentials(); 32664 } 32665 }, _speed + 30); 32666 }; 32667 Zoom.prototype.enableZoomOnSlideItemLoad = function () { 32668 // Add zoomable class 32669 this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this)); 32670 }; 32671 Zoom.prototype.getModifier = function (rotateValue, axis, el) { 32672 var originalRotate = rotateValue; 32673 rotateValue = Math.abs(rotateValue); 32674 var transformValues = this.getCurrentTransform(el); 32675 if (!transformValues) { 32676 return 1; 32677 } 32678 var modifier = 1; 32679 if (axis === 'X') { 32680 var flipHorizontalValue = Math.sign(parseFloat(transformValues[0])); 32681 if (rotateValue === 0 || rotateValue === 180) { 32682 modifier = 1; 32683 } 32684 else if (rotateValue === 90) { 32685 if ((originalRotate === -90 && flipHorizontalValue === 1) || 32686 (originalRotate === 90 && flipHorizontalValue === -1)) { 32687 modifier = -1; 32688 } 32689 else { 32690 modifier = 1; 32691 } 32692 } 32693 modifier = modifier * flipHorizontalValue; 32694 } 32695 else { 32696 var flipVerticalValue = Math.sign(parseFloat(transformValues[3])); 32697 if (rotateValue === 0 || rotateValue === 180) { 32698 modifier = 1; 32699 } 32700 else if (rotateValue === 90) { 32701 var sinX = parseFloat(transformValues[1]); 32702 var sinMinusX = parseFloat(transformValues[2]); 32703 modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue); 32704 } 32705 modifier = modifier * flipVerticalValue; 32706 } 32707 return modifier; 32708 }; 32709 Zoom.prototype.getImageSize = function ($image, rotateValue, axis) { 32710 var imageSizes = { 32711 y: 'offsetHeight', 32712 x: 'offsetWidth', 32713 }; 32714 if (Math.abs(rotateValue) === 90) { 32715 // Swap axis 32716 if (axis === 'x') { 32717 axis = 'y'; 32718 } 32719 else { 32720 axis = 'x'; 32721 } 32722 } 32723 return $image[imageSizes[axis]]; 32724 }; 32725 Zoom.prototype.getDragCords = function (e, rotateValue) { 32726 if (rotateValue === 90) { 32727 return { 32728 x: e.pageY, 32729 y: e.pageX, 32730 }; 32731 } 32732 else { 32733 return { 32734 x: e.pageX, 32735 y: e.pageY, 32736 }; 32737 } 32738 }; 32739 Zoom.prototype.getSwipeCords = function (e, rotateValue) { 32740 var x = e.targetTouches[0].pageX; 32741 var y = e.targetTouches[0].pageY; 32742 if (rotateValue === 90) { 32743 return { 32744 x: y, 32745 y: x, 32746 }; 32747 } 32748 else { 32749 return { 32750 x: x, 32751 y: y, 32752 }; 32753 } 32754 }; 32755 Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) { 32756 scale = scale || this.scale || 1; 32757 var allowY = this.imageYSize * scale > this.containerRect.height; 32758 var allowX = this.imageXSize * scale > this.containerRect.width; 32759 if (rotateValue === 90) { 32760 return { 32761 allowX: allowY, 32762 allowY: allowX, 32763 }; 32764 } 32765 else { 32766 return { 32767 allowX: allowX, 32768 allowY: allowY, 32769 }; 32770 } 32771 }; 32772 /** 32773 * 32774 * @param {Element} el 32775 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); 32776 * Get the current transform value 32777 */ 32778 Zoom.prototype.getCurrentTransform = function (el) { 32779 if (!el) { 32780 return; 32781 } 32782 var st = window.getComputedStyle(el, null); 32783 var tm = st.getPropertyValue('-webkit-transform') || 32784 st.getPropertyValue('-moz-transform') || 32785 st.getPropertyValue('-ms-transform') || 32786 st.getPropertyValue('-o-transform') || 32787 st.getPropertyValue('transform') || 32788 'none'; 32789 if (tm !== 'none') { 32790 return tm.split('(')[1].split(')')[0].split(','); 32791 } 32792 return; 32793 }; 32794 Zoom.prototype.getCurrentRotation = function (el) { 32795 if (!el) { 32796 return 0; 32797 } 32798 var values = this.getCurrentTransform(el); 32799 if (values) { 32800 return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) * 32801 (180 / Math.PI)); 32802 // If you want rotate in 360 32803 //return (angle < 0 ? angle + 360 : angle); 32804 } 32805 return 0; 32806 }; 32807 Zoom.prototype.setZoomEssentials = function () { 32808 var $image = this.core 32809 .getSlideItem(this.core.index) 32810 .find('.lg-image') 32811 .first(); 32812 var rotateEl = this.core 32813 .getSlideItem(this.core.index) 32814 .find('.lg-img-rotate') 32815 .first() 32816 .get(); 32817 this.rotateValue = this.getCurrentRotation(rotateEl); 32818 this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y'); 32819 this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x'); 32820 this.containerRect = this.core.outer.get().getBoundingClientRect(); 32821 this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl); 32822 this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl); 32823 }; 32824 /** 32825 * @desc Image zoom 32826 * Translate the wrap and scale the image to get better user experience 32827 * 32828 * @param {String} scale - Zoom decrement/increment value 32829 */ 32830 Zoom.prototype.zoomImage = function (scale) { 32831 // Find offset manually to avoid issue after zoom 32832 var offsetX = (this.containerRect.width - this.imageXSize) / 2 + 32833 this.containerRect.left; 32834 var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 32835 var topBottomSpacing = Math.abs(top - bottom) / 2; 32836 var offsetY = (this.containerRect.height - 32837 this.imageYSize - 32838 topBottomSpacing * this.modifierX) / 32839 2 + 32840 this.scrollTop + 32841 this.containerRect.top; 32842 var originalX; 32843 var originalY; 32844 if (scale === 1) { 32845 this.positionChanged = false;
32846 } 32847 var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale); 32848 var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX; 32849 if (this.positionChanged) { 32850 originalX = this.left / (this.scale - 1); 32851 originalY = this.top / (this.scale - 1); 32852 this.pageX = Math.abs(originalX) + offsetX; 32853 this.pageY = Math.abs(originalY) + offsetY; 32854 this.positionChanged = false; 32855 } 32856 var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale); 32857 var _x = offsetX - this.pageX; 32858 var _y = offsetY - this.pageY; 32859 var x = (scale - 1) * _x; 32860 var y = (scale - 1) * _y; 32861 if (allowX) { 32862 if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) { 32863 x = possibleSwipeCords.minX; 32864 } 32865 else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) { 32866 x = possibleSwipeCords.maxX; 32867 } 32868 } 32869 else { 32870 if (scale > 1) { 32871 if (x < possibleSwipeCords.minX) { 32872 x = possibleSwipeCords.minX; 32873 } 32874 else if (x > possibleSwipeCords.maxX) { 32875 x = possibleSwipeCords.maxX; 32876 } 32877 } 32878 }
32879 if (allowY) { 32880 if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) { 32881 y = possibleSwipeCords.minY; 32882 } 32883 else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) { 32884 y = possibleSwipeCords.maxY; 32885 } 32886 } 32887 else { 32888 // If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out 32889 if (scale > 1) { 32890 //If image goes beyond viewport top, use the minim possible translate value 32891 if (y < possibleSwipeCords.minY) { 32892 y = possibleSwipeCords.minY; 32893 } 32894 else if (y > possibleSwipeCords.maxY) { 32895 y = possibleSwipeCords.maxY; 32896 } 32897 } 32898 } 32899 this.setZoomStyles({ 32900 x: x, 32901 y: y, 32902 scale: scale, 32903 }); 32904 }; 32905 /** 32906 * @desc apply scale3d to image and translate to image wrap 32907 * @param {style} X,Y and scale 32908 */ 32909 Zoom.prototype.setZoomStyles = function (style) { 32910 var $image = this.core 32911 .getSlideItem(this.core.index) 32912 .find('.lg-image') 32913 .first(); 32914 var $dummyImage = this.core.outer 32915 .find('.lg-current .lg-dummy-img') 32916 .first(); 32917 var $imageWrap = $image.parent(); 32918 this.scale = style.scale; 32919 $image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)'); 32920 $dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)'); 32921 var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)'; 32922 $imageWrap.css('transform', transform); 32923 this.left = style.x; 32924 this.top = style.y; 32925 }; 32926 /** 32927 * @param index - Index of the current slide 32928 * @param event - event will be available only if the function is called on clicking/taping the imags 32929 */ 32930 Zoom.prototype.setActualSize = function (index, event) { 32931 var _this = this; 32932 // Allow zoom only on image 32933 if (!this.isImageSlide() || 32934 this.core.outer.hasClass('lg-first-slide-loading')) { 32935 return; 32936 } 32937 var scale = this.getCurrentImageActualSizeScale(); 32938 if (this.core.outer.hasClass('lg-zoomed')) { 32939 this.scale = 1; 32940 } 32941 else { 32942 this.scale = this.getScale(scale); 32943 } 32944 this.setPageCords(event); 32945 this.beginZoom(this.scale); 32946 this.zoomImage(this.scale); 32947 setTimeout(function () { 32948 _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab'); 32949 }, 10); 32950 }; 32951 Zoom.prototype.getNaturalWidth = function (index) { 32952 var $image = this.core.getSlideItem(index).find('.lg-image').first(); 32953 var naturalWidth = this.core.galleryItems[index].width; 32954 return naturalWidth 32955 ? parseFloat(naturalWidth) 32956 : $image.get().naturalWidth; 32957 }; 32958 Zoom.prototype.getActualSizeScale = function (naturalWidth, width) { 32959 var _scale; 32960 var scale;
32961 if (naturalWidth > width) { 32962 _scale = naturalWidth / width; 32963 scale = _scale || 2; 32964 } 32965 else { 32966 scale = 1; 32967 } 32968 return scale; 32969 }; 32970 Zoom.prototype.getCurrentImageActualSizeScale = function () { 32971 var $image = this.core 32972 .getSlideItem(this.core.index) 32973 .find('.lg-image') 32974 .first(); 32975 var width = $image.get().offsetWidth; 32976 var naturalWidth = this.getNaturalWidth(this.core.index) || width; 32977 return this.getActualSizeScale(naturalWidth, width); 32978 }; 32979 Zoom.prototype.getPageCords = function (event) { 32980 var cords = {}; 32981 if (event) { 32982 cords.x = event.pageX || event.targetTouches[0].pageX; 32983 cords.y = event.pageY || event.targetTouches[0].pageY; 32984 } 32985 else { 32986 var containerRect = this.core.outer.get().getBoundingClientRect(); 32987 cords.x = containerRect.width / 2 + containerRect.left; 32988 cords.y = 32989 containerRect.height / 2 + this.scrollTop + containerRect.top; 32990 } 32991 return cords; 32992 }; 32993 Zoom.prototype.setPageCords = function (event) { 32994 var pageCords = this.getPageCords(event); 32995 this.pageX = pageCords.x; 32996 this.pageY = pageCords.y; 32997 }; 32998 // If true, zoomed - in else zoomed out 32999 Zoom.prototype.beginZoom = function (scale) { 33000 this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging'); 33001 if (scale > 1) { 33002 this.core.outer.addClass('lg-zoomed'); 33003 var $actualSize = this.core.getElementById('lg-actual-size'); 33004 $actualSize 33005 .removeClass(this.settings.actualSizeIcons.zoomIn) 33006 .addClass(this.settings.actualSizeIcons.zoomOut); 33007 } 33008 else { 33009 this.resetZoom(); 33010 } 33011 return scale > 1; 33012 }; 33013 Zoom.prototype.getScale = function (scale) { 33014 var actualSizeScale = this.getCurrentImageActualSizeScale(); 33015 if (scale < 1) { 33016 scale = 1; 33017 } 33018 else if (scale > actualSizeScale) { 33019 scale = actualSizeScale; 33020 } 33021 return scale; 33022 }; 33023 Zoom.prototype.init = function () { 33024 var _this = this; 33025 if (!this.settings.zoom) { 33026 return; 33027 } 33028 this.buildTemplates(); 33029 this.enableZoomOnSlideItemLoad(); 33030 var tapped = null; 33031 this.core.outer.on('dblclick.lg', function (event) { 33032 if (!_this.$LG(event.target).hasClass('lg-image')) { 33033 return; 33034 } 33035 _this.setActualSize(_this.core.index, event); 33036 }); 33037 this.core.outer.on('touchstart.lg', function (event) { 33038 var $target = _this.$LG(event.target); 33039 if (event.targetTouches.length === 1 && 33040 $target.hasClass('lg-image')) { 33041 if (!tapped) { 33042 tapped = setTimeout(function () { 33043 tapped = null; 33044 }, 300); 33045 } 33046 else { 33047 clearTimeout(tapped); 33048 tapped = null; 33049 event.preventDefault(); 33050 _this.setActualSize(_this.core.index, event); 33051 } 33052 } 33053 }); 33054 // Update zoom on resize and orientationchange 33055 this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () { 33056 if (!_this.core.lgOpened || !_this.isImageSlide()) 33057 return; 33058 _this.setPageCords(); 33059 _this.setZoomEssentials(); 33060 _this.zoomImage(_this.scale); 33061 }); 33062 // Update zoom on resize and orientationchange 33063 this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () { 33064 if (!_this.core.lgOpened) 33065 return; 33066 _this.scrollTop = _this.$LG(window).scrollTop(); 33067 }); 33068 this.core.getElementById('lg-zoom-out').on('click.lg', function () { 33069 if (_this.core.outer.find('.lg-current .lg-image').get()) { 33070 _this.scale -= _this.settings.scale; 33071 _this.scale = _this.getScale(_this.scale); 33072 _this.beginZoom(_this.scale); 33073 _this.zoomImage(_this.scale); 33074 } 33075 }); 33076 this.core.getElementById('lg-zoom-in').on('click.lg', function () { 33077 _this.zoomIn(); 33078 }); 33079 this.core.getElementById('lg-actual-size').on('click.lg', function () { 33080 _this.setActualSize(_this.core.index); 33081 }); 33082 this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () { 33083 _this.core.outer.find('.lg-item').removeClass('lg-zoomable'); 33084 }); 33085 this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () { 33086 _this.scrollTop = _this.$LG(window).scrollTop(); 33087 // Set the initial value center 33088 _this.pageX = _this.core.outer.width() / 2;
33089 _this.pageY = _this.core.outer.height() / 2 + _this.scrollTop; 33090 _this.scale = 1; 33091 }); 33092 // Reset zoom on slide change 33093 this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) { 33094 var prevIndex = event.detail.prevIndex; 33095 _this.scale = 1; 33096 _this.positionChanged = false; 33097 _this.resetZoom(prevIndex); 33098 if (_this.isImageSlide()) { 33099 _this.setZoomEssentials(); 33100 } 33101 }); 33102 // Drag option after zoom 33103 this.zoomDrag(); 33104 this.pinchZoom(); 33105 this.zoomSwipe(); 33106 // Store the zoomable timeout value just to clear it while closing 33107 this.zoomableTimeout = false; 33108 this.positionChanged = false; 33109 }; 33110 Zoom.prototype.zoomIn = function (scale) { 33111 // Allow zoom only on image 33112 if (!this.isImageSlide()) { 33113 return; 33114 } 33115 if (scale) { 33116 this.scale = scale; 33117 } 33118 else { 33119 this.scale += this.settings.scale; 33120 } 33121 this.scale = this.getScale(this.scale); 33122 this.beginZoom(this.scale); 33123 this.zoomImage(this.scale); 33124 }; 33125 // Reset zoom effect 33126 Zoom.prototype.resetZoom = function (index) { 33127 this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition'); 33128 var $actualSize = this.core.getElementById('lg-actual-size'); 33129 var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index); 33130 $actualSize 33131 .removeClass(this.settings.actualSizeIcons.zoomOut) 33132 .addClass(this.settings.actualSizeIcons.zoomIn); 33133 $item.find('.lg-img-wrap').first().removeAttr('style'); 33134 $item.find('.lg-image').first().removeAttr('style'); 33135 this.scale = 1; 33136 this.left = 0; 33137 this.top = 0; 33138 // Reset pagx pagy values to center 33139 this.setPageCords(); 33140 }; 33141 Zoom.prototype.getTouchDistance = function (e) { 33142 return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) * 33143 (e.targetTouches[0].pageX - e.targetTouches[1].pageX) + 33144 (e.targetTouches[0].pageY - e.targetTouches[1].pageY) * 33145 (e.targetTouches[0].pageY - e.targetTouches[1].pageY)); 33146 }; 33147 Zoom.prototype.pinchZoom = function () { 33148 var _this = this; 33149 var startDist = 0; 33150 var pinchStarted = false; 33151 var initScale = 1; 33152 var $item = this.core.getSlideItem(this.core.index); 33153 this.core.$inner.on('touchstart.lg', function (e) { 33154 $item = _this.core.getSlideItem(_this.core.index); 33155 if (!_this.isImageSlide()) { 33156 return; 33157 } 33158 if (e.targetTouches.length === 2 && 33159 !_this.core.outer.hasClass('lg-first-slide-loading') && 33160 (_this.$LG(e.target).hasClass('lg-item') || 33161 $item.get().contains(e.target))) { 33162 initScale = _this.scale || 1; 33163 _this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging'); 33164 _this.core.touchAction = 'pinch'; 33165 startDist = _this.getTouchDistance(e); 33166 } 33167 }); 33168 this.core.$inner.on('touchmove.lg', function (e) { 33169 if (e.targetTouches.length === 2 && 33170 _this.core.touchAction === 'pinch' && 33171 (_this.$LG(e.target).hasClass('lg-item') || 33172 $item.get().contains(e.target))) { 33173 e.preventDefault(); 33174 var endDist = _this.getTouchDistance(e); 33175 var distance = startDist - endDist; 33176 if (!pinchStarted && Math.abs(distance) > 5) { 33177 pinchStarted = true; 33178 } 33179 if (pinchStarted) { 33180 _this.scale = Math.max(1, initScale + -distance * 0.008); 33181 _this.zoomImage(_this.scale); 33182 } 33183 } 33184 }); 33185 this.core.$inner.on('touchend.lg', function (e) { 33186 if (_this.core.touchAction === 'pinch' && 33187 (_this.$LG(e.target).hasClass('lg-item') || 33188 $item.get().contains(e.target))) { 33189 pinchStarted = false; 33190 startDist = 0; 33191 if (_this.scale <= 1) { 33192 _this.resetZoom(); 33193 } 33194 else { 33195 _this.scale = _this.getScale(_this.scale); 33196 _this.zoomImage(_this.scale); 33197 _this.core.outer.addClass('lg-zoomed'); 33198 } 33199 _this.core.touchAction = undefined; 33200 } 33201 }); 33202 }; 33203 Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) { 33204 var distanceXnew = endCoords.x - startCoords.x; 33205 var distanceYnew = endCoords.y - startCoords.y; 33206 var speedX = Math.abs(distanceXnew) / touchDuration + 1; 33207 var speedY = Math.abs(distanceYnew) / touchDuration + 1; 33208 if (speedX > 2) { 33209 speedX += 1; 33210 } 33211 if (speedY > 2) { 33212 speedY += 1; 33213 } 33214 distanceXnew = distanceXnew * speedX; 33215 distanceYnew = distanceYnew * speedY; 33216 var _LGel = this.core 33217 .getSlideItem(this.core.index) 33218 .find('.lg-img-wrap') 33219 .first(); 33220 var distance = {}; 33221 distance.x = this.left + distanceXnew * this.modifierX; 33222 distance.y = this.top + distanceYnew * this.modifierY; 33223 var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue); 33224 if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) { 33225 if (allowY) { 33226 if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) { 33227 distance.y = possibleSwipeCords.minY; 33228 } 33229 else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) { 33230 distance.y = possibleSwipeCords.maxY; 33231 } 33232 } 33233 if (allowX) { 33234 if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) { 33235 distance.x = possibleSwipeCords.minX; 33236 } 33237 else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) { 33238 distance.x = possibleSwipeCords.maxX; 33239 } 33240 } 33241 if (allowY) { 33242 this.top = distance.y; 33243 } 33244 else { 33245 distance.y = this.top; 33246 } 33247 if (allowX) { 33248 this.left = distance.x; 33249 } 33250 else { 33251 distance.x = this.left; 33252 } 33253 this.setZoomSwipeStyles(_LGel, distance); 33254 this.positionChanged = true; 33255 } 33256 }; 33257 Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) { 33258 var distance = {}; 33259 if (allowY) { 33260 distance.y = 33261 this.top + (endCoords.y - startCoords.y) * this.modifierY; 33262 if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) { 33263 var diffMinY = possibleSwipeCords.minY - distance.y; 33264 distance.y = possibleSwipeCords.minY - diffMinY / 6; 33265 } 33266 else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) { 33267 var diffMaxY = distance.y - possibleSwipeCords.maxY; 33268 distance.y = possibleSwipeCords.maxY + diffMaxY / 6; 33269 } 33270 } 33271 else { 33272 distance.y = this.top; 33273 }
33274 if (allowX) { 33275 distance.x = 33276 this.left + (endCoords.x - startCoords.x) * this.modifierX; 33277 if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) { 33278 var diffMinX = possibleSwipeCords.minX - distance.x; 33279 distance.x = possibleSwipeCords.minX - diffMinX / 6; 33280 } 33281 else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) { 33282 var difMaxX = distance.x - possibleSwipeCords.maxX; 33283 distance.x = possibleSwipeCords.maxX + difMaxX / 6; 33284 } 33285 } 33286 else { 33287 distance.x = this.left; 33288 } 33289 return distance; 33290 }; 33291 Zoom.prototype.isBeyondPossibleLeft = function (x, minX) { 33292 return x >= minX; 33293 }; 33294 Zoom.prototype.isBeyondPossibleRight = function (x, maxX) { 33295 return x <= maxX; 33296 }; 33297 Zoom.prototype.isBeyondPossibleTop = function (y, minY) { 33298 return y >= minY; 33299 }; 33300 Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) { 33301 return y <= maxY; 33302 }; 33303 Zoom.prototype.isImageSlide = function () { 33304 var currentItem = this.core.galleryItems[this.core.index]; 33305 return this.core.getSlideType(currentItem) === 'image'; 33306 }; 33307 Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) { 33308 var dataScale = scale || this.scale || 1; 33309 var elDataScale = Math.abs(dataScale); 33310 var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 33311 var topBottomSpacing = Math.abs(top - bottom) / 2; 33312 var minY = (this.imageYSize - this.containerRect.height) / 2 + 33313 topBottomSpacing * this.modifierX; 33314 var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY; 33315 var minX = (this.imageXSize - this.containerRect.width) / 2; 33316 var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX; 33317 var possibleSwipeCords = { 33318 minY: minY, 33319 maxY: maxY, 33320 minX: minX, 33321 maxX: maxX, 33322 }; 33323 if (Math.abs(rotateValue) === 90) { 33324 possibleSwipeCords = { 33325 minY: minX, 33326 maxY: maxX, 33327 minX: minY, 33328 maxX: maxY, 33329 }; 33330 } 33331 return possibleSwipeCords; 33332 }; 33333 Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) { 33334 LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)'); 33335 }; 33336 Zoom.prototype.zoomSwipe = function () { 33337 var _this = this; 33338 var startCoords = {}; 33339 var endCoords = {}; 33340 var isMoved = false; 33341 // Allow x direction drag 33342 var allowX = false; 33343 // Allow Y direction drag 33344 var allowY = false; 33345 var startTime = new Date(); 33346 var endTime = new Date(); 33347 var possibleSwipeCords; 33348 var _LGel; 33349 var $item = this.core.getSlideItem(this.core.index); 33350 this.core.$inner.on('touchstart.lg', function (e) { 33351 // Allow zoom only on image 33352 if (!_this.isImageSlide()) { 33353 return; 33354 } 33355 $item = _this.core.getSlideItem(_this.core.index); 33356 if ((_this.$LG(e.target).hasClass('lg-item') || 33357 $item.get().contains(e.target)) && 33358 e.targetTouches.length === 1 && 33359 _this.core.outer.hasClass('lg-zoomed')) { 33360 e.preventDefault(); 33361 startTime = new Date(); 33362 _this.core.touchAction = 'zoomSwipe'; 33363 _LGel = _this.core 33364 .getSlideItem(_this.core.index) 33365 .find('.lg-img-wrap') 33366 .first(); 33367 var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue)); 33368 allowY = dragAllowedAxises.allowY; 33369 allowX = dragAllowedAxises.allowX; 33370 if (allowX || allowY) { 33371 startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue)); 33372 } 33373 possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue); 33374 // reset opacity and transition duration 33375 _this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition'); 33376 } 33377 }); 33378 this.core.$inner.on('touchmove.lg', function (e) { 33379 if (e.targetTouches.length === 1 && 33380 _this.core.touchAction === 'zoomSwipe' && 33381 (_this.$LG(e.target).hasClass('lg-item') || 33382 $item.get().contains(e.target))) { 33383 e.preventDefault(); 33384 _this.core.touchAction = 'zoomSwipe'; 33385 endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue)); 33386 var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords); 33387 if (Math.abs(endCoords.x - startCoords.x) > 15 || 33388 Math.abs(endCoords.y - startCoords.y) > 15) { 33389 isMoved = true; 33390 _this.setZoomSwipeStyles(_LGel, distance); 33391 } 33392 } 33393 }); 33394 this.core.$inner.on('touchend.lg', function (e) { 33395 if (_this.core.touchAction === 'zoomSwipe' && 33396 (_this.$LG(e.target).hasClass('lg-item') || 33397 $item.get().contains(e.target))) { 33398 _this.core.touchAction = undefined; 33399 _this.core.outer.removeClass('lg-zoom-dragging'); 33400 if (!isMoved) { 33401 return; 33402 } 33403 isMoved = false;
33404 endTime = new Date(); 33405 var touchDuration = endTime.valueOf() - startTime.valueOf(); 33406 _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue); 33407 } 33408 }); 33409 }; 33410 Zoom.prototype.zoomDrag = function () { 33411 var _this = this; 33412 var startCoords = {}; 33413 var endCoords = {}; 33414 var isDragging = false; 33415 var isMoved = false; 33416 // Allow x direction drag 33417 var allowX = false; 33418 // Allow Y direction drag 33419 var allowY = false; 33420 var startTime; 33421 var endTime; 33422 var possibleSwipeCords; 33423 var _LGel; 33424 this.core.outer.on('mousedown.lg.zoom', function (e) { 33425 // Allow zoom only on image 33426 if (!_this.isImageSlide()) { 33427 return; 33428 } 33429 var $item = _this.core.getSlideItem(_this.core.index); 33430 if (_this.$LG(e.target).hasClass('lg-item') || 33431 $item.get().contains(e.target)) { 33432 startTime = new Date(); 33433 _LGel = _this.core 33434 .getSlideItem(_this.core.index) 33435 .find('.lg-img-wrap') 33436 .first(); 33437 var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue)); 33438 allowY = dragAllowedAxises.allowY; 33439 allowX = dragAllowedAxises.allowX; 33440 if (_this.core.outer.hasClass('lg-zoomed')) { 33441 if (_this.$LG(e.target).hasClass('lg-object') && 33442 (allowX || allowY)) { 33443 e.preventDefault(); 33444 startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 33445 possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue); 33446 isDragging = true; 33447 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 33448 _this.core.outer.get().scrollLeft += 1; 33449 _this.core.outer.get().scrollLeft -= 1; 33450 _this.core.outer 33451 .removeClass('lg-grab') 33452 .addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging'); 33453 // reset opacity and transition duration 33454 } 33455 } 33456 } 33457 }); 33458 this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) { 33459 if (isDragging) { 33460 isMoved = true; 33461 endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 33462 var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords); 33463 _this.setZoomSwipeStyles(_LGel, distance); 33464 } 33465 }); 33466 this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) { 33467 if (isDragging) { 33468 endTime = new Date(); 33469 isDragging = false; 33470 _this.core.outer.removeClass('lg-zoom-dragging'); 33471 // Fix for chrome mouse move on click 33472 if (isMoved && 33473 (startCoords.x !== endCoords.x || 33474 startCoords.y !== endCoords.y)) { 33475 endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 33476 var touchDuration = endTime.valueOf() - startTime.valueOf(); 33477 _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue); 33478 } 33479 isMoved = false; 33480 } 33481 _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab'); 33482 }); 33483 }; 33484 Zoom.prototype.closeGallery = function () { 33485 this.resetZoom(); 33486 }; 33487 Zoom.prototype.destroy = function () { 33488 // Unbind all events added by lightGallery zoom plugin 33489 this.$LG(window).off(".lg.zoom.global" + this.core.lgId); 33490 this.core.LGel.off('.lg.zoom'); 33491 this.core.LGel.off('.zoom'); 33492 clearTimeout(this.zoomableTimeout); 33493 this.zoomableTimeout = false; 33494 }; 33495 return Zoom; 33496 }()); 33497 33498 return Zoom; 33499 33500}))); 33501/*! 33502 * lightgallery | 2.5.0 | June 13th 2022 33503 * http://www.lightgalleryjs.com/ 33504 * Copyright (c) 2020 Sachin Neravath; 33505 * @license GPLv3 33506 */ 33507 33508(function (global, factory) { 33509 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 33510 typeof define === 'function' && define.amd ? define(factory) : 33511 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory()); 33512}(this, (function () { 'use strict'; 33513 33514 /*! ***************************************************************************** 33515 Copyright (c) Microsoft Corporation. 33516 33517 Permission to use, copy, modify, and/or distribute this software for any 33518 purpose with or without fee is hereby granted. 33519 33520 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 33521 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 33522 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 33523 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 33524 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 33525 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 33526 PERFORMANCE OF THIS SOFTWARE. 33527 ***************************************************************************** */ 33528 33529 var __assign = function() { 33530 __assign = Object.assign || function __assign(t) { 33531 for (var s, i = 1, n = arguments.length; i < n; i++) { 33532 s = arguments[i]; 33533 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 33534 } 33535 return t; 33536 }; 33537 return __assign.apply(this, arguments); 33538 }; 33539 33540 var fullscreenSettings = { 33541 fullScreen: true, 33542 fullscreenPluginStrings: { 33543 toggleFullscreen: 'Toggle Fullscreen', 33544 }, 33545 }; 33546 33547 var FullScreen = /** @class */ (function () { 33548 function FullScreen(instance, $LG) { 33549 // get lightGallery core plugin instance 33550 this.core = instance;
33551 this.$LG = $LG; 33552 // extend module default settings with lightGallery core settings 33553 this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings); 33554 return this; 33555 } 33556 FullScreen.prototype.init = function () { 33557 var fullScreen = ''; 33558 if (this.settings.fullScreen) { 33559 // check for fullscreen browser support 33560 if (!document.fullscreenEnabled && 33561 !document.webkitFullscreenEnabled && 33562 !document.mozFullScreenEnabled && 33563 !document.msFullscreenEnabled) { 33564 return; 33565 } 33566 else { 33567 fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>"; 33568 this.core.$toolbar.append(fullScreen); 33569 this.fullScreen(); 33570 } 33571 } 33572 }; 33573 FullScreen.prototype.isFullScreen = function () { 33574 return (document.fullscreenElement || 33575 document.mozFullScreenElement || 33576 document.webkitFullscreenElement || 33577 document.msFullscreenElement); 33578 }; 33579 FullScreen.prototype.requestFullscreen = function () { 33580 var el = document.documentElement; 33581 if (el.requestFullscreen) { 33582 el.requestFullscreen(); 33583 } 33584 else if (el.msRequestFullscreen) { 33585 el.msRequestFullscreen(); 33586 } 33587 else if (el.mozRequestFullScreen) { 33588 el.mozRequestFullScreen(); 33589 } 33590 else if (el.webkitRequestFullscreen) { 33591 el.webkitRequestFullscreen(); 33592 } 33593 }; 33594 FullScreen.prototype.exitFullscreen = function () { 33595 if (document.exitFullscreen) { 33596 document.exitFullscreen(); 33597 } 33598 else if (document.msExitFullscreen) { 33599 document.msExitFullscreen(); 33600 } 33601 else if (document.mozCancelFullScreen) { 33602 document.mozCancelFullScreen(); 33603 } 33604 else if (document.webkitExitFullscreen) { 33605 document.webkitExitFullscreen(); 33606 } 33607 }; 33608 // https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode 33609 FullScreen.prototype.fullScreen = function () { 33610 var _this = this; 33611 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 () { 33612 if (!_this.core.lgOpened) 33613 return; 33614 _this.core.outer.toggleClass('lg-fullscreen-on'); 33615 }); 33616 this.core.outer 33617 .find('.lg-fullscreen') 33618 .first() 33619 .on('click.lg', function () { 33620 if (_this.isFullScreen()) { 33621 _this.exitFullscreen(); 33622 } 33623 else { 33624 _this.requestFullscreen(); 33625 } 33626 }); 33627 }; 33628 FullScreen.prototype.closeGallery = function () { 33629 // exit from fullscreen if activated 33630 if (this.isFullScreen()) { 33631 this.exitFullscreen(); 33632 } 33633 }; 33634 FullScreen.prototype.destroy = function () { 33635 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); 33636 }; 33637 return FullScreen; 33638 }()); 33639 33640 return FullScreen; 33641 33642}))); 33643 33644/*! 33645 * lightgallery | 2.5.0 | June 13th 2022 33646 * http://www.lightgalleryjs.com/ 33647 * Copyright (c) 2020 Sachin Neravath; 33648 * @license GPLv3 33649 */ 33650 33651(function (global, factory) { 33652 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 33653 typeof define === 'function' && define.amd ? define(factory) : 33654 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory()); 33655}(this, (function () { 'use strict'; 33656 33657 /*! ***************************************************************************** 33658 Copyright (c) Microsoft Corporation. 33659 33660 Permission to use, copy, modify, and/or distribute this software for any 33661 purpose with or without fee is hereby granted. 33662 33663 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 33664 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 33665 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 33666 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 33667 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 33668 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 33669 PERFORMANCE OF THIS SOFTWARE. 33670 ***************************************************************************** */ 33671 33672 var __assign = function() { 33673 __assign = Object.assign || function __assign(t) { 33674 for (var s, i = 1, n = arguments.length; i < n; i++) { 33675 s = arguments[i]; 33676 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 33677 } 33678 return t; 33679 }; 33680 return __assign.apply(this, arguments); 33681 }; 33682 33683 /** 33684 * List of lightGallery events 33685 * All events should be documented here 33686 * Below interfaces are used to build the website documentations 33687 * */ 33688 var lGEvents = { 33689 afterAppendSlide: 'lgAfterAppendSlide', 33690 init: 'lgInit', 33691 hasVideo: 'lgHasVideo', 33692 containerResize: 'lgContainerResize', 33693 updateSlides: 'lgUpdateSlides', 33694 afterAppendSubHtml: 'lgAfterAppendSubHtml', 33695 beforeOpen: 'lgBeforeOpen', 33696 afterOpen: 'lgAfterOpen', 33697 slideItemLoad: 'lgSlideItemLoad', 33698 beforeSlide: 'lgBeforeSlide', 33699 afterSlide: 'lgAfterSlide', 33700 posterClick: 'lgPosterClick', 33701 dragStart: 'lgDragStart', 33702 dragMove: 'lgDragMove', 33703 dragEnd: 'lgDragEnd', 33704 beforeNextSlide: 'lgBeforeNextSlide', 33705 beforePrevSlide: 'lgBeforePrevSlide', 33706 beforeClose: 'lgBeforeClose', 33707 afterClose: 'lgAfterClose', 33708 rotateLeft: 'lgRotateLeft', 33709 rotateRight: 'lgRotateRight', 33710 flipHorizontal: 'lgFlipHorizontal', 33711 flipVertical: 'lgFlipVertical', 33712 autoplay: 'lgAutoplay', 33713 autoplayStart: 'lgAutoplayStart', 33714 autoplayStop: 'lgAutoplayStop', 33715 }; 33716 33717 var hashSettings = { 33718 hash: true, 33719 galleryId: '1', 33720 customSlideName: false, 33721 }; 33722 33723 var Hash = /** @class */ (function () { 33724 function Hash(instance, $LG) { 33725 // get lightGallery core plugin instance 33726 this.core = instance;
33727 this.$LG = $LG; 33728 // extend module default settings with lightGallery core settings 33729 this.settings = __assign(__assign({}, hashSettings), this.core.settings); 33730 return this; 33731 } 33732 Hash.prototype.init = function () { 33733 var _this = this; 33734 if (!this.settings.hash) { 33735 return; 33736 } 33737 this.oldHash = window.location.hash; 33738 setTimeout(function () { 33739 _this.buildFromHash(); 33740 }, 100); 33741 // Change hash value on after each slide transition 33742 this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this)); 33743 this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this)); 33744 // Listen hash change and change the slide according to slide value 33745 this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this)); 33746 }; 33747 Hash.prototype.onAfterSlide = function (event) { 33748 var slideName = this.core.galleryItems[event.detail.index].slideName; 33749 slideName = this.settings.customSlideName 33750 ? slideName || event.detail.index 33751 : event.detail.index; 33752 if (history.replaceState) { 33753 history.replaceState(null, '', window.location.pathname + 33754 window.location.search + 33755 '#lg=' + 33756 this.settings.galleryId + 33757 '&slide=' + 33758 slideName); 33759 } 33760 else { 33761 window.location.hash = 33762 'lg=' + this.settings.galleryId + '&slide=' + slideName; 33763 } 33764 }; 33765 /** 33766 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin 33767 * @param {String} hash 33768 * @returns {Number} Index of the slide. 33769 */ 33770 Hash.prototype.getIndexFromUrl = function (hash) { 33771 if (hash === void 0) { hash = window.location.hash; } 33772 var slideName = hash.split('&slide=')[1]; 33773 var _idx = 0; 33774 if (this.settings.customSlideName) { 33775 for (var index = 0; index < this.core.galleryItems.length; index++) { 33776 var dynamicEl = this.core.galleryItems[index]; 33777 if (dynamicEl.slideName === slideName) { 33778 _idx = index; 33779 break; 33780 } 33781 } 33782 } 33783 else { 33784 _idx = parseInt(slideName, 10); 33785 } 33786 return isNaN(_idx) ? 0 : _idx; 33787 }; 33788 // Build Gallery if gallery id exist in the URL 33789 Hash.prototype.buildFromHash = function () { 33790 // if dynamic option is enabled execute immediately 33791 var _hash = window.location.hash; 33792 //Uncode edit ##START## 33793 // if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) { 33794 if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) { 33795 //Uncode edit ##END## 33796 // This class is used to remove the initial animation if galleryId present in the URL 33797 this.$LG(document.body).addClass('lg-from-hash'); 33798 var index = this.getIndexFromUrl(_hash); 33799 this.core.openGallery(index); 33800 return true; 33801 } 33802 }; 33803 Hash.prototype.onCloseAfter = function () { 33804 // Reset to old hash value 33805 if (this.oldHash && 33806 this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) { 33807 if (history.replaceState) { 33808 history.replaceState(null, '', this.oldHash); 33809 } 33810 else { 33811 window.location.hash = this.oldHash; 33812 } 33813 } 33814 else { 33815 if (history.replaceState) { 33816 history.replaceState(null, document.title, window.location.pathname + window.location.search); 33817 } 33818 else { 33819 window.location.hash = ''; 33820 } 33821 } 33822 }; 33823 Hash.prototype.onHashchange = function () { 33824 if (!this.core.lgOpened) 33825 return; 33826 var _hash = window.location.hash; 33827 var index = this.getIndexFromUrl(_hash); 33828 // it galleryId doesn't exist in the url close the gallery 33829 if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) { 33830 this.core.slide(index, false, false); 33831 } 33832 else if (this.core.lGalleryOn) { 33833 this.core.closeGallery(); 33834 } 33835 }; 33836 Hash.prototype.closeGallery = function () { 33837 if (this.settings.hash) { 33838 this.$LG(document.body).removeClass('lg-from-hash'); 33839 } 33840 }; 33841 Hash.prototype.destroy = function () { 33842 this.core.LGel.off('.lg.hash'); 33843 this.core.LGel.off('.hash'); 33844 this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId); 33845 }; 33846 return Hash; 33847 }()); 33848 33849 return Hash; 33850 33851}))); 33852/*! 33853 * lightgallery | 2.5.0 | June 13th 2022 33854 * http://www.lightgalleryjs.com/ 33855 * Copyright (c) 2020 Sachin Neravath; 33856 * @license GPLv3 33857 */ 33858 33859(function (global, factory) { 33860 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 33861 typeof define === 'function' && define.amd ? define(factory) : 33862 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory()); 33863}(this, (function () { 'use strict'; 33864 33865 /*! ***************************************************************************** 33866 Copyright (c) Microsoft Corporation. 33867 33868 Permission to use, copy, modify, and/or distribute this software for any 33869 purpose with or without fee is hereby granted. 33870 33871 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 33872 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 33873 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 33874 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 33875 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 33876 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 33877 PERFORMANCE OF THIS SOFTWARE. 33878 ***************************************************************************** */ 33879 33880 var __assign = function() { 33881 __assign = Object.assign || function __assign(t) { 33882 for (var s, i = 1, n = arguments.length; i < n; i++) { 33883 s = arguments[i]; 33884 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 33885 } 33886 return t; 33887 }; 33888 return __assign.apply(this, arguments); 33889 }; 33890 33891 function __spreadArrays() { 33892 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 33893 for (var r = Array(s), k = 0, i = 0; i < il; i++) 33894 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 33895 r[k] = a[j]; 33896 return r; 33897 } 33898 33899 var shareSettings = { 33900 share: true, 33901 facebook: true, 33902 facebookDropdownText: 'Facebook', 33903 twitter: true, 33904 twitterDropdownText: 'Twitter', 33905 pinterest: true, 33906 pinterestDropdownText: 'Pinterest', 33907 additionalShareOptions: [], 33908 sharePluginStrings: { share: 'Share' }, 33909 }; 33910 33911 function getFacebookShareLink(galleryItem) { 33912 var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u='; 33913 return (facebookBaseUrl + 33914 encodeURIComponent(galleryItem.facebookShareUrl || window.location.href)); 33915 } 33916 33917 function getTwitterShareLink(galleryItem) { 33918 var twitterBaseUrl = '//twitter.com/intent/tweet?text='; 33919 var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href); 33920 var text = galleryItem.tweetText;
33921 return twitterBaseUrl + text + '&url=' + url; 33922 } 33923 33924 function getPinterestShareLink(galleryItem) { 33925 var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url='; 33926 var description = galleryItem.pinterestText; 33927 var media = encodeURIComponent(galleryItem.src); 33928 var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href); 33929 return (pinterestBaseUrl + 33930 url + 33931 '&media=' + 33932 media + 33933 '&description=' + 33934 description); 33935 } 33936 33937 /** 33938 * List of lightGallery events 33939 * All events should be documented here 33940 * Below interfaces are used to build the website documentations 33941 * */ 33942 var lGEvents = { 33943 afterAppendSlide: 'lgAfterAppendSlide', 33944 init: 'lgInit', 33945 hasVideo: 'lgHasVideo', 33946 containerResize: 'lgContainerResize', 33947 updateSlides: 'lgUpdateSlides', 33948 afterAppendSubHtml: 'lgAfterAppendSubHtml', 33949 beforeOpen: 'lgBeforeOpen', 33950 afterOpen: 'lgAfterOpen', 33951 slideItemLoad: 'lgSlideItemLoad', 33952 beforeSlide: 'lgBeforeSlide', 33953 afterSlide: 'lgAfterSlide', 33954 posterClick: 'lgPosterClick', 33955 dragStart: 'lgDragStart', 33956 dragMove: 'lgDragMove', 33957 dragEnd: 'lgDragEnd', 33958 beforeNextSlide: 'lgBeforeNextSlide', 33959 beforePrevSlide: 'lgBeforePrevSlide', 33960 beforeClose: 'lgBeforeClose', 33961 afterClose: 'lgAfterClose', 33962 rotateLeft: 'lgRotateLeft', 33963 rotateRight: 'lgRotateRight', 33964 flipHorizontal: 'lgFlipHorizontal', 33965 flipVertical: 'lgFlipVertical', 33966 autoplay: 'lgAutoplay', 33967 autoplayStart: 'lgAutoplayStart', 33968 autoplayStop: 'lgAutoplayStop', 33969 }; 33970 33971 var Share = /** @class */ (function () { 33972 function Share(instance) { 33973 this.shareOptions = []; 33974 // get lightGallery core plugin instance 33975 this.core = instance; 33976 // extend module default settings with lightGallery core settings 33977 this.settings = __assign(__assign({}, shareSettings), this.core.settings); 33978 return this; 33979 } 33980 Share.prototype.init = function () { 33981 if (!this.settings.share) { 33982 return; 33983 } 33984 this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions); 33985 this.setLgShareMarkup(); 33986 this.core.outer 33987 .find('.lg-share .lg-dropdown') 33988 .append(this.getShareListHtml()); 33989 this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this)); 33990 }; 33991 Share.prototype.getShareListHtml = function () { 33992 var shareHtml = ''; 33993 this.shareOptions.forEach(function (shareOption) { 33994 shareHtml += shareOption.dropdownHTML; 33995 }); 33996 return shareHtml; 33997 }; 33998 Share.prototype.setLgShareMarkup = function () { 33999 var _this = this; 34000 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>"); 34001 this.core.outer.append('<div class="lg-dropdown-overlay"></div>'); 34002 var $shareButton = this.core.outer.find('.lg-share'); 34003 $shareButton.first().on('click.lg', function () { 34004 _this.core.outer.toggleClass('lg-dropdown-active'); 34005 if (_this.core.outer.hasClass('lg-dropdown-active')) { 34006 _this.core.outer.attr('aria-expanded', true); 34007 } 34008 else { 34009 _this.core.outer.attr('aria-expanded', false); 34010 } 34011 }); 34012 this.core.outer 34013 .find('.lg-dropdown-overlay') 34014 .first() 34015 .on('click.lg', function () { 34016 _this.core.outer.removeClass('lg-dropdown-active'); 34017 _this.core.outer.attr('aria-expanded', false); 34018 }); 34019 }; 34020 Share.prototype.onAfterSlide = function (event) { 34021 var _this = this; 34022 var index = event.detail.index; 34023 var currentItem = this.core.galleryItems[index]; 34024 setTimeout(function () { 34025 _this.shareOptions.forEach(function (shareOption) { 34026 var selector = shareOption.selector; 34027 _this.core.outer 34028 .find(selector) 34029 .attr('href', shareOption.generateLink(currentItem)); 34030 }); 34031 }, 100); 34032 }; 34033 Share.prototype.getShareListItemHTML = function (type, text) { 34034 return "<li><a class=\"lg-share-" + type + "\" rel=\"noopener\" target=\"_blank\"><span class=\"lg-icon\"></span><span class=\"lg-dropdown-text\">" + text + "</span></a></li>"; 34035 }; 34036 Share.prototype.getDefaultShareOptions = function () { 34037 return __spreadArrays((this.settings.facebook 34038 ? [ 34039 { 34040 type: 'facebook', 34041 generateLink: getFacebookShareLink,
34042 dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText), 34043 selector: '.lg-share-facebook', 34044 }, 34045 ] 34046 : []), (this.settings.twitter 34047 ? [ 34048 { 34049 type: 'twitter', 34050 generateLink: getTwitterShareLink, 34051 dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText), 34052 selector: '.lg-share-twitter', 34053 }, 34054 ] 34055 : []), (this.settings.pinterest 34056 ? [ 34057 { 34058 type: 'pinterest', 34059 generateLink: getPinterestShareLink, 34060 dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText), 34061 selector: '.lg-share-pinterest', 34062 }, 34063 ] 34064 : [])); 34065 }; 34066 Share.prototype.destroy = function () { 34067 this.core.outer.find('.lg-dropdown-overlay').remove(); 34068 this.core.outer.find('.lg-share').remove(); 34069 this.core.LGel.off('.lg.share'); 34070 this.core.LGel.off('.share'); 34071 }; 34072 return Share; 34073 }()); 34074 34075 return Share; 34076 34077}))); 34078/*! 34079 * lightgallery | 2.5.0 | June 13th 2022 34080 * http://www.lightgalleryjs.com/ 34081 * Copyright (c) 2020 Sachin Neravath; 34082 * @license GPLv3 34083 */ 34084 34085(function (global, factory) { 34086 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 34087 typeof define === 'function' && define.amd ? define(factory) : 34088 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory()); 34089}(this, (function () { 'use strict'; 34090 34091 /*! ***************************************************************************** 34092 Copyright (c) Microsoft Corporation. 34093 34094 Permission to use, copy, modify, and/or distribute this software for any 34095 purpose with or without fee is hereby granted. 34096 34097 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 34098 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 34099 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 34100 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 34101 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 34102 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 34103 PERFORMANCE OF THIS SOFTWARE. 34104 ***************************************************************************** */ 34105 34106 var __assign = function() { 34107 __assign = Object.assign || function __assign(t) { 34108 for (var s, i = 1, n = arguments.length; i < n; i++) { 34109 s = arguments[i]; 34110 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 34111 } 34112 return t; 34113 }; 34114 return __assign.apply(this, arguments); 34115 }; 34116 34117 var thumbnailsSettings = { 34118 thumbnail: true, 34119 animateThumb: true, 34120 currentPagerPosition: 'middle', 34121 alignThumbnails: 'middle', 34122 thumbWidth: 100, 34123 thumbHeight: '80px', 34124 thumbMargin: 5, 34125 appendThumbnailsTo: '.lg-components', 34126 toggleThumb: false, 34127 enableThumbDrag: true, 34128 enableThumbSwipe: true, 34129 thumbnailSwipeThreshold: 10, 34130 loadYouTubeThumbnail: true, 34131 youTubeThumbSize: 1, 34132 thumbnailPluginStrings: { 34133 toggleThumbnails: 'Toggle thumbnails', 34134 }, 34135 }; 34136 34137 /** 34138 * List of lightGallery events 34139 * All events should be documented here 34140 * Below interfaces are used to build the website documentations 34141 * */ 34142 var lGEvents = { 34143 afterAppendSlide: 'lgAfterAppendSlide', 34144 init: 'lgInit', 34145 hasVideo: 'lgHasVideo', 34146 containerResize: 'lgContainerResize', 34147 updateSlides: 'lgUpdateSlides', 34148 afterAppendSubHtml: 'lgAfterAppendSubHtml', 34149 beforeOpen: 'lgBeforeOpen', 34150 afterOpen: 'lgAfterOpen', 34151 slideItemLoad: 'lgSlideItemLoad', 34152 beforeSlide: 'lgBeforeSlide', 34153 afterSlide: 'lgAfterSlide', 34154 posterClick: 'lgPosterClick', 34155 dragStart: 'lgDragStart', 34156 dragMove: 'lgDragMove', 34157 dragEnd: 'lgDragEnd', 34158 beforeNextSlide: 'lgBeforeNextSlide', 34159 beforePrevSlide: 'lgBeforePrevSlide', 34160 beforeClose: 'lgBeforeClose', 34161 afterClose: 'lgAfterClose', 34162 rotateLeft: 'lgRotateLeft', 34163 rotateRight: 'lgRotateRight', 34164 flipHorizontal: 'lgFlipHorizontal', 34165 flipVertical: 'lgFlipVertical', 34166 autoplay: 'lgAutoplay', 34167 autoplayStart: 'lgAutoplayStart', 34168 autoplayStop: 'lgAutoplayStop', 34169 }; 34170 34171 var Thumbnail = /** @class */ (function () { 34172 function Thumbnail(instance, $LG) { 34173 this.thumbOuterWidth = 0; 34174 this.thumbTotalWidth = 0; 34175 this.translateX = 0; 34176 this.thumbClickable = false;
34177 // get lightGallery core plugin instance 34178 this.core = instance; 34179 this.$LG = $LG; 34180 return this; 34181 } 34182 Thumbnail.prototype.init = function () { 34183 // extend module default settings with lightGallery core settings 34184 this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings); 34185 this.thumbOuterWidth = 0; 34186 this.thumbTotalWidth = 34187 this.core.galleryItems.length * 34188 (this.settings.thumbWidth + this.settings.thumbMargin); 34189 // Thumbnail animation value 34190 this.translateX = 0; 34191 this.setAnimateThumbStyles(); 34192 if (!this.core.settings.allowMediaOverlap) { 34193 this.settings.toggleThumb = false; 34194 } 34195 if (this.settings.thumbnail) { 34196 this.build(); 34197 if (this.settings.animateThumb) { 34198 if (this.settings.enableThumbDrag) { 34199 this.enableThumbDrag(); 34200 } 34201 if (this.settings.enableThumbSwipe) { 34202 this.enableThumbSwipe(); 34203 } 34204 this.thumbClickable = false; 34205 } 34206 else { 34207 this.thumbClickable = true; 34208 } 34209 this.toggleThumbBar(); 34210 this.thumbKeyPress(); 34211 } 34212 }; 34213 Thumbnail.prototype.build = function () { 34214 var _this = this; 34215 this.setThumbMarkup(); 34216 this.manageActiveClassOnSlideChange(); 34217 this.$lgThumb.first().on('click.lg touchend.lg', function (e) { 34218 var $target = _this.$LG(e.target); 34219 if (!$target.hasAttribute('data-lg-item-id')) { 34220 return; 34221 } 34222 setTimeout(function () { 34223 // In IE9 and bellow touch does not support 34224 // Go to slide if browser does not support css transitions 34225 if (_this.thumbClickable && !_this.core.lgBusy) { 34226 var index = parseInt($target.attr('data-lg-item-id')); 34227 _this.core.slide(index, false, true, false); 34228 } 34229 }, 50); 34230 }); 34231 //Uncode edit ##START## 34232 // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) { 34233 this.core.LGel.on(lGEvents.beforeSlide, function (event) { 34234 //Uncode edit ##END## 34235 var index = event.detail.index; 34236 _this.animateThumb(index); 34237 }); 34238 //Uncode edit ##START## 34239 // this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () { 34240 this.core.LGel.on(lGEvents.beforeOpen, function () { 34241 //Uncode edit ##END## 34242 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 34243 }); 34244 //Uncode edit ##START## 34245 // this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () { 34246 this.core.LGel.on(lGEvents.updateSlides, function () { 34247 //Uncode edit ##END## 34248 _this.rebuildThumbnails(); 34249 }); 34250 //Uncode edit ##START## 34251 // this.core.LGel.on(lGEvents.containerResize + ".thumb", function () { 34252 this.core.LGel.on(lGEvents.containerResize, function () { 34253 //Uncode edit ##END## 34254 if (!_this.core.lgOpened) 34255 return; 34256 setTimeout(function () { 34257 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 34258 _this.animateThumb(_this.core.index); 34259 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 34260 }, 50); 34261 }); 34262 }; 34263 Thumbnail.prototype.setThumbMarkup = function () { 34264 var thumbOuterClassNames = 'lg-thumb-outer '; 34265 if (this.settings.alignThumbnails) { 34266 thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails; 34267 } 34268 var html = "<div class=\"" + thumbOuterClassNames + "\">\n <div class=\"lg-thumb lg-group\">\n </div>\n </div>"; 34269 this.core.outer.addClass('lg-has-thumb'); 34270 if (this.settings.appendThumbnailsTo === '.lg-components') { 34271 this.core.$lgComponents.append(html); 34272 } 34273 else { 34274 this.core.outer.append(html); 34275 } 34276 this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first(); 34277 this.$lgThumb = this.core.outer.find('.lg-thumb').first(); 34278 if (this.settings.animateThumb) { 34279 this.core.outer 34280 .find('.lg-thumb') 34281 .css('transition-duration', this.core.settings.speed + 'ms') 34282 .css('width', this.thumbTotalWidth + 'px') 34283 .css('position', 'relative'); 34284 } 34285 this.setThumbItemHtml(this.core.galleryItems); 34286 }; 34287 Thumbnail.prototype.enableThumbDrag = function () { 34288 var _this = this; 34289 var thumbDragUtils = { 34290 cords: { 34291 startX: 0, 34292 endX: 0, 34293 }, 34294 isMoved: false, 34295 newTranslateX: 0, 34296 startTime: new Date(), 34297 endTime: new Date(), 34298 touchMoveTime: 0, 34299 }; 34300 var isDragging = false;
34301 this.$thumbOuter.addClass('lg-grab'); 34302 this.core.outer 34303 .find('.lg-thumb') 34304 .first() 34305 .on('mousedown.lg.thumb', function (e) { 34306 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 34307 // execute only on .lg-object 34308 e.preventDefault(); 34309 thumbDragUtils.cords.startX = e.pageX; 34310 thumbDragUtils.startTime = new Date(); 34311 _this.thumbClickable = false; 34312 isDragging = true; 34313 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 34314 _this.core.outer.get().scrollLeft += 1; 34315 _this.core.outer.get().scrollLeft -= 1; 34316 // * 34317 _this.$thumbOuter 34318 .removeClass('lg-grab') 34319 .addClass('lg-grabbing'); 34320 } 34321 }); 34322 this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) { 34323 if (!_this.core.lgOpened) 34324 return; 34325 if (isDragging) { 34326 thumbDragUtils.cords.endX = e.pageX; 34327 thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils); 34328 } 34329 }); 34330 this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () { 34331 if (!_this.core.lgOpened) 34332 return; 34333 if (thumbDragUtils.isMoved) { 34334 thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils); 34335 } 34336 else { 34337 _this.thumbClickable = true; 34338 } 34339 if (isDragging) { 34340 isDragging = false; 34341 _this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab'); 34342 } 34343 }); 34344 }; 34345 Thumbnail.prototype.enableThumbSwipe = function () { 34346 var _this = this; 34347 var thumbDragUtils = { 34348 cords: { 34349 startX: 0, 34350 endX: 0, 34351 }, 34352 isMoved: false, 34353 newTranslateX: 0, 34354 startTime: new Date(), 34355 endTime: new Date(), 34356 touchMoveTime: 0, 34357 }; 34358 this.$lgThumb.on('touchstart.lg', function (e) { 34359 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 34360 e.preventDefault(); 34361 thumbDragUtils.cords.startX = e.targetTouches[0].pageX; 34362 _this.thumbClickable = false; 34363 thumbDragUtils.startTime = new Date(); 34364 } 34365 }); 34366 this.$lgThumb.on('touchmove.lg', function (e) { 34367 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 34368 e.preventDefault(); 34369 thumbDragUtils.cords.endX = e.targetTouches[0].pageX; 34370 thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils); 34371 } 34372 }); 34373 this.$lgThumb.on('touchend.lg', function () { 34374 if (thumbDragUtils.isMoved) { 34375 thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils); 34376 } 34377 else { 34378 _this.thumbClickable = true; 34379 } 34380 }); 34381 }; 34382 // Rebuild thumbnails 34383 Thumbnail.prototype.rebuildThumbnails = function () { 34384 var _this = this; 34385 // Remove transitions 34386 this.$thumbOuter.addClass('lg-rebuilding-thumbnails'); 34387 setTimeout(function () { 34388 _this.thumbTotalWidth = 34389 _this.core.galleryItems.length * 34390 (_this.settings.thumbWidth + _this.settings.thumbMargin); 34391 _this.$lgThumb.css('width', _this.thumbTotalWidth + 'px'); 34392 _this.$lgThumb.empty(); 34393 _this.setThumbItemHtml(_this.core.galleryItems); 34394 _this.animateThumb(_this.core.index); 34395 }, 50); 34396 setTimeout(function () { 34397 _this.$thumbOuter.removeClass('lg-rebuilding-thumbnails'); 34398 }, 200); 34399 }; 34400 // @ts-check 34401 Thumbnail.prototype.setTranslate = function (value) { 34402 this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)'); 34403 }; 34404 Thumbnail.prototype.getPossibleTransformX = function (left) { 34405 if (left > this.thumbTotalWidth - this.thumbOuterWidth) { 34406 left = this.thumbTotalWidth - this.thumbOuterWidth; 34407 } 34408 if (left < 0) { 34409 left = 0; 34410 } 34411 return left; 34412 }; 34413 Thumbnail.prototype.animateThumb = function (index) { 34414 this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms'); 34415 if (this.settings.animateThumb) { 34416 var position = 0; 34417 switch (this.settings.currentPagerPosition) { 34418 case 'left': 34419 position = 0; 34420 break; 34421 case 'middle': 34422 position = 34423 this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2; 34424 break; 34425 case 'right': 34426 position = this.thumbOuterWidth - this.settings.thumbWidth; 34427 } 34428 this.translateX = 34429 (this.settings.thumbWidth + this.settings.thumbMargin) * index - 34430 1 - 34431 position; 34432 if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) { 34433 this.translateX = this.thumbTotalWidth - this.thumbOuterWidth; 34434 } 34435 if (this.translateX < 0) { 34436 this.translateX = 0; 34437 } 34438 this.setTranslate(this.translateX); 34439 } 34440 };
34441 Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) { 34442 thumbDragUtils.newTranslateX = this.translateX; 34443 thumbDragUtils.isMoved = true; 34444 thumbDragUtils.touchMoveTime = new Date().valueOf(); 34445 thumbDragUtils.newTranslateX -= 34446 thumbDragUtils.cords.endX - thumbDragUtils.cords.startX; 34447 thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX); 34448 // move current slide 34449 this.setTranslate(thumbDragUtils.newTranslateX); 34450 this.$thumbOuter.addClass('lg-dragging'); 34451 return thumbDragUtils; 34452 }; 34453 Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) { 34454 thumbDragUtils.isMoved = false; 34455 thumbDragUtils.endTime = new Date(); 34456 this.$thumbOuter.removeClass('lg-dragging'); 34457 var touchDuration = thumbDragUtils.endTime.valueOf() - 34458 thumbDragUtils.startTime.valueOf(); 34459 var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX; 34460 var speedX = Math.abs(distanceXnew) / touchDuration; 34461 // Some magical numbers 34462 // Can be improved 34463 if (speedX > 0.15 && 34464 thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) { 34465 speedX += 1; 34466 if (speedX > 2) { 34467 speedX += 1; 34468 } 34469 speedX = 34470 speedX + 34471 speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth); 34472 this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings'); 34473 distanceXnew = distanceXnew * speedX; 34474 this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew); 34475 this.setTranslate(this.translateX); 34476 } 34477 else { 34478 this.translateX = thumbDragUtils.newTranslateX; 34479 } 34480 if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) < 34481 this.settings.thumbnailSwipeThreshold) { 34482 this.thumbClickable = true; 34483 } 34484 return thumbDragUtils; 34485 }; 34486 Thumbnail.prototype.getThumbHtml = function (thumb, index, alt) { 34487 var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 34488 var thumbImg, 34489 altTh = this.core.galleryItems[index].subHtml, 34490 altApp = ''; 34491 if (slideVideoInfo.youtube) { 34492 if (this.settings.loadYouTubeThumbnail) { 34493 thumbImg = 34494 '//img.youtube.com/vi/' + 34495 slideVideoInfo.youtube[1] + 34496 '/' + 34497 this.settings.youTubeThumbSize + 34498 '.jpg'; 34499 } 34500 else { 34501 thumbImg = thumb; 34502 } 34503 } 34504 else { 34505 thumbImg = thumb; 34506 } 34507 34508 if ( altTh ) { 34509 altTh = altTh.replace(/<\/?[^>]+(>|$)/g, ""); 34510 altApp = 'alt=\"' + altTh + ' \" '; 34511 } else if ( typeof alt !== 'undefined' ) { 34512 altApp = 'alt=\"' + alt + ' \" '; 34513 } 34514 34515 if ( thumbImg ) { 34516 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 + "\" " + altApp + "src=\"" + thumbImg + "\" />\n </div>"; 34517 } else { 34518 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 </div>"; 34519 } 34520 }; 34521 Thumbnail.prototype.getThumbItemHtml = function (items) { 34522 var thumbList = ''; 34523 for (var i = 0; i < items.length; i++) { 34524 thumbList += this.getThumbHtml(items[i].thumb, i, items[i].alt); 34525 } 34526 return thumbList; 34527 }; 34528 Thumbnail.prototype.setThumbItemHtml = function (items) { 34529 var thumbList = this.getThumbItemHtml(items); 34530 this.$lgThumb.html(thumbList); 34531 }; 34532 Thumbnail.prototype.setAnimateThumbStyles = function () { 34533 if (this.settings.animateThumb) { 34534 this.core.outer.addClass('lg-animate-thumb'); 34535 } 34536 }; 34537 // Manage thumbnail active calss
34538 Thumbnail.prototype.manageActiveClassOnSlideChange = function () { 34539 var _this = this; 34540 // manage active class for thumbnail 34541 //Uncode edit ##START## 34542 // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) { 34543 this.core.LGel.on(lGEvents.beforeSlide, function (event) { 34544 //Uncode edit ##END## 34545 var $thumb = _this.core.outer.find('.lg-thumb-item'); 34546 var index = event.detail.index; 34547 $thumb.removeClass('active'); 34548 $thumb.eq(index).addClass('active'); 34549 }); 34550 }; 34551 // Toggle thumbnail bar 34552 Thumbnail.prototype.toggleThumbBar = function () { 34553 var _this = this; 34554 if (this.settings.toggleThumb) { 34555 this.core.outer.addClass('lg-can-toggle'); 34556 this.core.$toolbar.append('<button type="button" aria-label="' + 34557 this.settings.thumbnailPluginStrings['toggleThumbnails'] + 34558 '" class="lg-toggle-thumb lg-icon"></button>'); 34559 this.core.outer 34560 .find('.lg-toggle-thumb') 34561 .first() 34562 .on('click.lg', function () { 34563 _this.core.outer.toggleClass('lg-components-open'); 34564 }); 34565 } 34566 }; 34567 Thumbnail.prototype.thumbKeyPress = function () { 34568 var _this = this; 34569 this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) { 34570 if (!_this.core.lgOpened || !_this.settings.toggleThumb) 34571 return; 34572 if (e.keyCode === 38) { 34573 e.preventDefault(); 34574 _this.core.outer.addClass('lg-components-open'); 34575 } 34576 else if (e.keyCode === 40) { 34577 e.preventDefault(); 34578 _this.core.outer.removeClass('lg-components-open'); 34579 } 34580 }); 34581 }; 34582 Thumbnail.prototype.destroy = function () { 34583 if (this.settings.thumbnail) { 34584 this.$LG(window).off(".lg.thumb.global" + this.core.lgId); 34585 this.core.LGel.off('.lg.thumb'); 34586 this.core.LGel.off('.thumb'); 34587 this.$thumbOuter.remove(); 34588 this.core.outer.removeClass('lg-has-thumb'); 34589 } 34590 }; 34591 return Thumbnail; 34592 }()); 34593 34594 return Thumbnail; 34595 34596}))); 34597/*! 34598 * lightgallery | 2.5.0 | June 13th 2022 34599 * http://www.lightgalleryjs.com/ 34600 * Copyright (c) 2020 Sachin Neravath; 34601 * @license GPLv3 34602 */ 34603 34604(function (global, factory) { 34605 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 34606 typeof define === 'function' && define.amd ? define(factory) : 34607 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory()); 34608}(this, (function () { 'use strict'; 34609 34610 /*! ***************************************************************************** 34611 Copyright (c) Microsoft Corporation. 34612 34613 Permission to use, copy, modify, and/or distribute this software for any 34614 purpose with or without fee is hereby granted. 34615 34616 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 34617 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 34618 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 34619 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 34620 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 34621 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 34622 PERFORMANCE OF THIS SOFTWARE. 34623 ***************************************************************************** */ 34624 34625 var __assign = function() { 34626 __assign = Object.assign || function __assign(t) { 34627 for (var s, i = 1, n = arguments.length; i < n; i++) { 34628 s = arguments[i]; 34629 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 34630 } 34631 return t; 34632 }; 34633 return __assign.apply(this, arguments); 34634 }; 34635 34636 var videoSettings = { 34637 autoplayFirstVideo: true, 34638 youTubePlayerParams: false, 34639 vimeoPlayerParams: false, 34640 wistiaPlayerParams: false, 34641 gotoNextSlideOnVideoEnd: true, 34642 autoplayVideoOnSlide: false, 34643 videojs: false, 34644 videojsTheme: '', 34645 videojsOptions: {}, 34646 }; 34647 34648 /** 34649 * List of lightGallery events 34650 * All events should be documented here 34651 * Below interfaces are used to build the website documentations 34652 * */ 34653 var lGEvents = { 34654 afterAppendSlide: 'lgAfterAppendSlide', 34655 init: 'lgInit', 34656 hasVideo: 'lgHasVideo', 34657 containerResize: 'lgContainerResize', 34658 updateSlides: 'lgUpdateSlides', 34659 afterAppendSubHtml: 'lgAfterAppendSubHtml', 34660 beforeOpen: 'lgBeforeOpen', 34661 afterOpen: 'lgAfterOpen', 34662 slideItemLoad: 'lgSlideItemLoad', 34663 beforeSlide: 'lgBeforeSlide', 34664 afterSlide: 'lgAfterSlide', 34665 posterClick: 'lgPosterClick', 34666 dragStart: 'lgDragStart', 34667 dragMove: 'lgDragMove', 34668 dragEnd: 'lgDragEnd', 34669 beforeNextSlide: 'lgBeforeNextSlide', 34670 beforePrevSlide: 'lgBeforePrevSlide', 34671 beforeClose: 'lgBeforeClose', 34672 afterClose: 'lgAfterClose', 34673 rotateLeft: 'lgRotateLeft', 34674 rotateRight: 'lgRotateRight', 34675 flipHorizontal: 'lgFlipHorizontal', 34676 flipVertical: 'lgFlipVertical', 34677 autoplay: 'lgAutoplay', 34678 autoplayStart: 'lgAutoplayStart', 34679 autoplayStop: 'lgAutoplayStop', 34680 }; 34681 34682 var param = function (obj) { 34683 return Object.keys(obj) 34684 .map(function (k) { 34685 return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]); 34686 }) 34687 .join('&'); 34688 }; 34689 var getVimeoURLParams = function (defaultParams, videoInfo) { 34690 if (!videoInfo || !videoInfo.vimeo) 34691 return '';
34692 var urlParams = videoInfo.vimeo[2] || ''; 34693 var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0 34694 ? '&' + param(defaultParams) 34695 : ''; 34696 // Support private video 34697 var urlWithHash = videoInfo.vimeo[0].split('/').pop() || ''; 34698 var urlWithHashWithParams = urlWithHash.split('?')[0] || ''; 34699 var hash = urlWithHashWithParams.split('#')[0]; 34700 var isPrivate = videoInfo.vimeo[1] !== hash; 34701 if (isPrivate) { 34702 urlParams = urlParams.replace("/" + hash, ''); 34703 } 34704 urlParams = 34705 urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || ''; 34706 // For vimeo last params gets priority if duplicates found 34707 // Uncode edit ##START## 34708 var vimeoPlayerParams = '?autoplay=0'; 34709 if ( videoInfo.autoplay !== '' ) { 34710 vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' ); 34711 vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' ); 34712 } else { 34713 if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) { 34714 vimeoPlayerParams = SiteParameters.vimeoPlayerParams; 34715 } 34716 } 34717 if ( videoInfo.muted !== '' ) { 34718 vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes'); 34719 } else { 34720 if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) { 34721 vimeoPlayerParams += '&muted=1'; 34722 } 34723 } 34724 // var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams; 34725 vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams; 34726 // Uncode edit ##END## 34727 return vimeoPlayerParams; 34728 }; 34729 34730 /** 34731 * Video module for lightGallery 34732 * Supports HTML5, YouTube, Vimeo, wistia videos 34733 * 34734 * 34735 * @ref Wistia 34736 * https://wistia.com/support/integrations/wordpress(How to get url) 34737 * https://wistia.com/support/developers/embed-options#using-embed-options 34738 * https://wistia.com/support/developers/player-api 34739 * https://wistia.com/support/developers/construct-an-embed-code 34740 * http://jsfiddle.net/xvnm7xLm/ 34741 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video 34742 * https://wistia.com/support/embed-and-share/sharing-videos 34743 * https://private-sharing.wistia.com/medias/mwhrulrucj 34744 * 34745 * @ref Youtube 34746 * https://developers.google.com/youtube/player_parameters#enablejsapi 34747 * https://developers.google.com/youtube/iframe_api_reference 34748 * https://developer.chrome.com/blog/autoplay/#iframe-delegation 34749 * 34750 * @ref Vimeo 34751 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url 34752 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode 34753 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters 34754 */ 34755 var Video = /** @class */ (function () { 34756 function Video(instance) { 34757 // get lightGallery core plugin instance 34758 this.core = instance; 34759 this.settings = __assign(__assign({}, videoSettings), this.core.settings); 34760 return this; 34761 } 34762 Video.prototype.init = function () { 34763 var _this = this; 34764 /** 34765 * Event triggered when video url found without poster 34766 * Append video HTML 34767 * Play if autoplayFirstVideo is true 34768 */ 34769 this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this)); 34770 this.core.LGel.on(lGEvents.posterClick + ".video", function () { 34771 var $el = _this.core.getSlideItem(_this.core.index); 34772 _this.loadVideoOnPosterClick($el); 34773 }); 34774 this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this)); 34775 // @desc fired immediately before each slide transition. 34776 this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this)); 34777 // @desc fired immediately after each slide transition. 34778 this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this)); 34779 }; 34780 /** 34781 * @desc Event triggered when a slide is completely loaded 34782 * 34783 * @param {Event} event - lightGalley custom event 34784 */ 34785 Video.prototype.onSlideItemLoad = function (event) { 34786 var _this = this; 34787 var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index; 34788 // Should check the active slide as well as user may have moved to different slide before the first slide is loaded 34789 if (this.settings.autoplayFirstVideo && 34790 isFirstSlide && 34791 index === this.core.index) { 34792 // Delay is just for the transition effect on video load 34793 setTimeout(function () { 34794 _this.loadAndPlayVideo(index); 34795 }, 200); 34796 } 34797 // Should not call on first slide. should check only if the slide is active 34798 if (!isFirstSlide && 34799 this.settings.autoplayVideoOnSlide && 34800 index === this.core.index) { 34801 setTimeout(function () { 34802 _this.loadAndPlayVideo(index); 34803 }, 500); 34804 } 34805 }; 34806 /** 34807 * @desc Event triggered when video url or poster found 34808 * Append video HTML is poster is not given 34809 * Play if autoplayFirstVideo is true 34810 * 34811 * @param {Event} event - Javascript Event object. 34812 */ 34813 Video.prototype.onHasVideo = function (event) { 34814 var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster; 34815 if (!hasPoster) { 34816 // All functions are called separately if poster exist in loadVideoOnPosterClick function 34817 this.appendVideos(this.core.getSlideItem(index), { 34818 src: src, 34819 addClass: 'lg-object', 34820 index: index, 34821 html5Video: html5Video, 34822 // Uncode edit ##START## 34823 autoplay: event.target.getAttribute('data-lb-autoplay'), 34824 muted: event.target.getAttribute('data-lb-muted'), 34825 // Uncode edit ##END## 34826 }); 34827 // Automatically navigate to next slide once video reaches the end. 34828 this.gotoNextSlideOnVideoEnd(src, index); 34829 } 34830 }; 34831 /** 34832 * @desc fired immediately before each slide transition. 34833 * Pause the previous video 34834 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos. 34835 * 34836 * @param {Event} event - Javascript Event object. 34837 * @param {number} prevIndex - Previous index of the slide. 34838 * @param {number} index - Current index of the slide 34839 */ 34840 Video.prototype.onBeforeSlide = function (event) { 34841 if (this.core.lGalleryOn) { 34842 var prevIndex = event.detail.prevIndex; 34843 this.pauseVideo(prevIndex); 34844 } 34845 // Uncode edit ##START## 34846 var _a = event.detail, index = _a.index; 34847 var $slide = this.core.getSlideItem(index); 34848
34849 var iframe = $slide.selector.querySelector('iframe'); 34850 if ( iframe != null ) { 34851 34852 var data_play = iframe.getAttribute('data-autoplay'); 34853 if ( typeof data_play !== 'undefined' && data_play === '1' ) { 34854 this.loadAndPlayVideo(index); 34855 34856 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}, 34857 $videoElement = this.core.getSlideItem(index).find('.lg-video-object').first(); 34858 if (videoInfo.vimeo) { 34859 var vimeoPlayer = new Vimeo.Player($videoElement.get()); 34860 vimeoPlayer.on('play', function () { 34861 vimeoPlayer.setCurrentTime(0); 34862 }); 34863 } else if ( videoInfo.youtube ) { 34864 try { 34865 $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*'); 34866 } 34867 catch (e) { 34868 console.warn(e); 34869 } 34870 } 34871 } 34872 } 34873 // Uncode edit ##END## 34874 }; 34875 /** 34876 * @desc fired immediately after each slide transition. 34877 * Play video if autoplayVideoOnSlide option is enabled. 34878 * 34879 * @param {Event} event - Javascript Event object. 34880 * @param {number} prevIndex - Previous index of the slide. 34881 * @param {number} index - Current index of the slide 34882 * @todo should check on onSlideLoad as well if video is not loaded on after slide 34883 */ 34884 Video.prototype.onAfterSlide = function (event) { 34885 var _this = this; 34886 var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex; 34887 // Do not call on first slide 34888 var $slide = this.core.getSlideItem(index); 34889 if (this.settings.autoplayVideoOnSlide && index !== prevIndex) { 34890 if ($slide.hasClass('lg-complete')) { 34891 setTimeout(function () { 34892 _this.loadAndPlayVideo(index); 34893 }, 100); 34894 } 34895 } 34896 }; 34897 Video.prototype.loadAndPlayVideo = function (index) { 34898 var $slide = this.core.getSlideItem(index); 34899 var currentGalleryItem = this.core.galleryItems[index]; 34900 if (currentGalleryItem.poster) { 34901 this.loadVideoOnPosterClick($slide, true); 34902 } 34903 else { 34904 //Uncode edit ##START## 34905 // this.playVideo(index); 34906 var iframe = $slide.selector.querySelector('iframe'); 34907 if ( iframe != null ) { 34908 var data_play = iframe.getAttribute('data-autoplay'); 34909 if ( typeof data_play !== 'undefined' ) { 34910 if ( data_play === '1' && this.core.index == index ) { 34911 this.playVideo(index); 34912 } else { 34913 this.pauseVideo(index); 34914 } 34915 } 34916 } 34917 //Uncode edit ##END## 34918 } 34919 }; 34920 /** 34921 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide. 34922 * @param {number} index - Index of the slide 34923 */ 34924 Video.prototype.playVideo = function (index) { 34925 this.controlVideo(index, 'play'); 34926 }; 34927 /** 34928 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide. 34929 * @param {number} index - Index of the slide 34930 */ 34931 Video.prototype.pauseVideo = function (index) { 34932 this.controlVideo(index, 'pause'); 34933 }; 34934 // Uncode edit ##START## 34935 //Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) { 34936 Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) { 34937 // Uncode edit ##END## 34938 var video = ''; 34939 var videoInfo = this.core.galleryItems[index] 34940 .__slideVideoInfo || {}; 34941 var currentGalleryItem = this.core.galleryItems[index]; 34942 var videoTitle = currentGalleryItem.title || currentGalleryItem.alt; 34943 videoTitle = videoTitle ? 'title="' + videoTitle + '"' : ''; 34944 var commonIframeProps = "allowtransparency=\"true\"\n frameborder=\"0\"\n scrolling=\"no\"\n allowfullscreen\n mozallowfullscreen\n webkitallowfullscreen\n oallowfullscreen\n msallowfullscreen"; 34945 if (videoInfo.youtube) { 34946 var videoId = 'lg-youtube' + index; 34947 var slideUrlParams = videoInfo.youtube[2] 34948 ? videoInfo.youtube[2] + '&' 34949 : ''; 34950 // For youtube first parms gets priority if duplicates found 34951 // Uncode edit ##START## 34952 // var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1"; 34953 var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1"; 34954 if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) { 34955 youTubePlayerParams += '&autoplay=0'; 34956 } 34957 if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) { 34958 youTubePlayerParams += '&mute=1'; 34959 } 34960 var data_video = ''; 34961 if ( autoplay !== '' ) { 34962 //youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' ); 34963 youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' ); 34964 youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' ); 34965 data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"'; 34966 } 34967 // if ( muted !== '' ) { 34968 // youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' ); 34969 // } 34970 youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' ); 34971 34972 youTubePlayerParams = youTubePlayerParams.replace('??', '?'); 34973 // Uncode edit ##END## 34974 var playerParams = youTubePlayerParams + 34975 (this.settings.youTubePlayerParams 34976 ? '&' + param(this.settings.youTubePlayerParams) 34977 : ''); 34978 // Uncode edit ##START## 34979 // 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>"; 34980 var nocookie = typeof SiteParameters.uncode_nocookie !== 'undefined' ? SiteParameters.uncode_nocookie : ''; 34981 video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube" + nocookie + ".com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>"; 34982 var tag = document.createElement('script'); 34983 tag.src = "//www.youtube.com/player_api"; 34984 var firstScriptTag = document.getElementsByTagName('script')[0]; 34985 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 34986 34987 // Replace the 'ytplayer' element with an <iframe> and 34988 // YouTube player after the API code downloads. 34989 var ytIframeplayer, 34990 setMute = muted === 'yes' ? 0 : 100; 34991 window.onYouTubePlayerAPIReady = function() { 34992 ytIframeplayer = new YT.Player(videoId, { 34993 videoId: videoInfo.youtube[1], 34994 events: { 34995 'onReady': function (event) { 34996 event.target.setVolume(setMute); 34997 } 34998 } 34999 }); 35000 } 35001 // Uncode edit ##END## 35002 } 35003 else if (videoInfo.vimeo) { 35004 var videoId = 'lg-vimeo' + index; 35005 // Uncode edit ##START## 35006 videoInfo.autoplay = autoplay; 35007 videoInfo.muted = muted; 35008 // Uncode edit ##END## 35009 var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo); 35010 // Uncode edit ##START## 35011 // 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>"; 35012 var data_video = ''; 35013 if ( autoplay !== '' ) { 35014 data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"'; 35015 } 35016 video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-vimeo " + addClass + "\" " + videoTitle + " src=\"//player.vimeo.com/video/" + (videoInfo.vimeo[1] + playerParams) + "\" " + commonIframeProps + "></iframe>"; 35017 // Uncode edit ##END## 35018 } 35019 else if (videoInfo.wistia) { 35020 var wistiaId = 'lg-wistia' + index; 35021 var playerParams = param(this.settings.wistiaPlayerParams); 35022 playerParams = playerParams ? '?' + playerParams : ''; 35023 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>"; 35024 } 35025 else if (videoInfo.html5) { 35026 var html5VideoMarkup = ''; 35027 for (var i = 0; i < html5Video.source.length; i++) { 35028 html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">"; 35029 } 35030 if (html5Video.tracks) { 35031 var _loop_1 = function (i) { 35032 var trackAttributes = ''; 35033 var track = html5Video.tracks[i]; 35034 Object.keys(track || {}
35034).forEach(function (key) { 35035 trackAttributes += key + "=\"" + track[key] + "\" "; 35036 }); 35037 html5VideoMarkup += "<track " + trackAttributes + ">"; 35038 }; 35039 for (var i = 0; i < html5Video.tracks.length; i++) { 35040 _loop_1(i); 35041 } 35042 } 35043 var html5VideoAttrs_1 = ''; 35044 var videoAttributes_1 = html5Video.attributes || {}; 35045 Object.keys(videoAttributes_1 || {}).forEach(function (key) { 35046 html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" "; 35047 }); 35048 video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme 35049 ? this.settings.videojsTheme + ' ' 35050 : '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n " + html5VideoMarkup + "\n Your browser does not support HTML5 video.\n </video>"; 35051 } 35052 return video; 35053 }; 35054 /** 35055 * @desc - Append videos to the slide 35056 * 35057 * @param {HTMLElement} el - slide element 35058 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo 35059 */ 35060 Video.prototype.appendVideos = function (el, videoParams) { 35061 var _a; 35062 // Uncode edit ##START## 35063 // var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video); 35064 var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted); 35065 // Uncode edit ##END## 35066 el.find('.lg-video-cont').append(videoHtml); 35067 var $videoElement = el.find('.lg-video-object').first(); 35068 if (videoParams.html5Video) { 35069 $videoElement.on('mousedown.lg.video', function (e) { 35070 e.stopPropagation(); 35071 }); 35072 } 35073 if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) { 35074 try { 35075 return videojs($videoElement.get(), this.settings.videojsOptions); 35076 } 35077 catch (e) { 35078 console.warn('lightGallery:- Make sure you have included videojs'); 35079 } 35080 } 35081 }; 35082 Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) { 35083 var _this = this; 35084 var $videoElement = this.core 35085 .getSlideItem(index) 35086 .find('.lg-video-object') 35087 .first(); 35088 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 35089 if (this.settings.gotoNextSlideOnVideoEnd) { 35090 if (videoInfo.html5) { 35091 $videoElement.on('ended', function () { 35092 _this.core.goToNextSlide(); 35093 }); 35094 } 35095 else if (videoInfo.vimeo) { 35096 try { 35097 // https://github.com/vimeo/player.js/#ended 35098 new Vimeo.Player($videoElement.get()).on('ended', function () { 35099 _this.core.goToNextSlide(); 35100 }); 35101 } 35102 catch (e) { 35103 console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js'); 35104 } 35105 } 35106 else if (videoInfo.wistia) { 35107 try { 35108 window._wq = window._wq || []; 35109 // @todo Event is gettign triggered multiple times 35110 window._wq.push({ 35111 id: $videoElement.attr('id'), 35112 onReady: function (video) { 35113 video.bind('end', function () { 35114 _this.core.goToNextSlide(); 35115 }); 35116 }, 35117 }); 35118 } 35119 catch (e) { 35120 console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js'); 35121 } 35122 } 35123 } 35124 }; 35125 Video.prototype.controlVideo = function (index, action) { 35126 var $videoElement = this.core 35127 .getSlideItem(index) 35128 .find('.lg-video-object') 35129 .first(); 35130 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 35131 if (!$videoElement.get()) 35132 return; 35133 if (videoInfo.youtube) { 35134 try { 35135 $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*'); 35136 } 35137 catch (e) { 35138 console.warn("lightGallery:- " + e); 35139 } 35140 } 35141 else if (videoInfo.vimeo) { 35142 try { 35143 new Vimeo.Player($videoElement.get())[action](); 35144 } 35145 catch (e) { 35146 console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js'); 35147 } 35148 } 35149 else if (videoInfo.html5) { 35150 if (this.settings.videojs) { 35151 try { 35152 videojs($videoElement.get())[action](); 35153 } 35154 catch (e) { 35155 console.warn('lightGallery:- Make sure you have included videojs'); 35156 } 35157 } 35158 else { 35159 $videoElement.get()[action](); 35160 } 35161 } 35162 else if (videoInfo.wistia) { 35163 try { 35164 window._wq = window._wq || []; 35165 // @todo Find a way to destroy wistia player instance 35166 window._wq.push({ 35167 id: $videoElement.attr('id'), 35168 onReady: function (video) { 35169 video[action](); 35170 }, 35171 }); 35172 } 35173 catch (e) { 35174 console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js'); 35175 } 35176 } 35177 }; 35178 Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) { 35179 var _this = this; 35180 // check slide has poster 35181 if (!$el.hasClass('lg-video-loaded')) { 35182 // check already video element present
35183 if (!$el.hasClass('lg-has-video')) { 35184 $el.addClass('lg-has-video'); 35185 var _html = void 0; 35186 var _src = this.core.galleryItems[this.core.index].src; 35187 var video = this.core.galleryItems[this.core.index].video; 35188 if (video) { 35189 _html = 35190 typeof video === 'string' ? JSON.parse(video) : video; 35191 } 35192 var videoJsPlayer_1 = this.appendVideos($el, { 35193 src: _src, 35194 addClass: '', 35195 index: this.core.index, 35196 html5Video: _html, 35197 }); 35198 this.gotoNextSlideOnVideoEnd(_src, this.core.index); 35199 var $tempImg = $el.find('.lg-object').first().get(); 35200 // @todo make sure it is working 35201 $el.find('.lg-video-cont').first().append($tempImg); 35202 $el.addClass('lg-video-loading'); 35203 videoJsPlayer_1 && 35204 videoJsPlayer_1.ready(function () { 35205 videoJsPlayer_1.on('loadedmetadata', function () { 35206 _this.onVideoLoadAfterPosterClick($el, _this.core.index); 35207 }); 35208 }); 35209 $el.find('.lg-video-object') 35210 .first() 35211 .on('load.lg error.lg loadedmetadata.lg', function () { 35212 setTimeout(function () { 35213 _this.onVideoLoadAfterPosterClick($el, _this.core.index); 35214 }, 50); 35215 }); 35216 } 35217 else { 35218 this.playVideo(this.core.index); 35219 } 35220 } 35221 else if (forcePlay) { 35222 this.playVideo(this.core.index); 35223 } 35224 }; 35225 Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) { 35226 $el.addClass('lg-video-loaded'); 35227 this.playVideo(index); 35228 }; 35229 Video.prototype.destroy = function () { 35230 this.core.LGel.off('.lg.video'); 35231 this.core.LGel.off('.video'); 35232 }; 35233 return Video; 35234 }()); 35235 35236 return Video; 35237 35238}))); 35239 35240 35241/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */ 35242!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).Vimeo=e.Vimeo||{},e.Vimeo.Player=t())}(this,function(){"use strict";function r(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var e="undefined"!=typeof global&&"[object global]"==={}.toString.call(global);function i(e,t){return 0===e.indexOf(t.toLowerCase())?e:"".concat(t.toLowerCase()).concat(e.substr(0,1).toUpperCase()).concat(e.substr(1))}function c(e){return/^(https?:)?\/\/((player|www)\.)?vimeo\.com(?=$|\/)/.test(e)}function s(e){var t,n=0<arguments.length&&void 0!==e?e:{},r=n.id,o=n.url,i=r||o;if(!i)throw new Error("An id or url must be passed, either in an options object or as a data-vimeo-id or data-vimeo-url attribute.");if(t=i,!isNaN(parseFloat(t))&&isFinite(t)&&Math.floor(t)==t)return"https://vimeo.com/".concat(i);if(c(i))return i.replace("http:","https:");if(r)throw new TypeError("â".concat(r,"â is not a valid video id."));throw new TypeError("â".concat(i,"â is not a vimeo.com url."))}var t=void 0!==Array.prototype.indexOf,n="undefined"!=typeof window&&void 0!==window.postMessage;if(!(e||t&&n))throw new Error("Sorry, the Vimeo Player API is not available in this browser.");var o,a,u,l,f="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function d(){if(void 0===this)throw new TypeError("Constructor WeakMap requires 'new'");if(l(this,"_id","_WeakMap_"+v()+"."+v()),0<arguments.length)throw new TypeError("WeakMap iterable is not supported")}function h(e,t){if(!m(e)||!a.call(e,"_id"))throw new TypeError(t+" method called on incompatible receiver "+typeof e)}function v(){return Math.random().toString().substring(2)}function m(e){return Object(e)===e}(o="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:f).WeakMap||(a=Object.prototype.hasOwnProperty,u=Object.defineProperty&&function(){try{return 1===Object.defineProperty({},"x",{value:1}).x}catch(e){}}(),l=function(e,t,n){u?Object.defineProperty(e,t,{configurable:!0,writable:!0,value:n}):e[t]=n},o.WeakMap=(l(d.prototype,"delete",function(e){if(h(this,"delete"),!m(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)&&(delete e[this._id],!0)}),l(d.prototype,"get",function(e){if(h(this,"get"),m(e)){var t=e[this._id];return t&&t[0]===e?t[1]:void 0}}),l(d.prototype,"has",function(e){if(h(this,"has"),!m(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)}),l(d.prototype,"set",function(e,t){if(h(this,"set"),!m(e))throw new TypeError("Invalid value used as weak map key");var n=e[this._id];return n&&n[0]===e?n[1]=t:l(e,this._id,[e,t]),this}),l(d,"_polyfill",!0),d));var p,y=(function(e){var t,n,r;r=function(){var t,n,r,o,i,a,e=Object.prototype.toString,u="undefined"!=typeof setImmediate?function(e){return setImmediate(e)}:setTimeout;try{Object.defineProperty({},"x",{}),t=function(e,t,n,r){return Object.defineProperty(e,t,{value:n,writable:!0,configurable:!1!==r})}}catch(e){t=function(e,t,n){return e[t]=n,e}}function l(e,t){this.fn=e,this.self=t,this.next=void 0}function c(e,t){r.add(e,t),n=n||u(r.drain)}function s(e){var t,n=typeof e;return null==e||"object"!=n&&"function"!=n||(t=e.then),"function"==typeof t&&t}function f(){for(var e=0;e<this.chain.length;e++)!function(e,t,n){var r,o;try{!1===t?n.reject(e.msg):(r=!0===t?e.msg:t.call(void 0,e.msg))===n.promise?n.reject(TypeError("Promise-chain cycle")):(o=s(r))?o.call(r,n.resolve,n.reject):n.resolve(r)}catch(e){n.reject(e)}}(this,1===this.state?this.chain[e].success:this.chain[e].failure,this.chain[e]);this.chain.length=0}function d(e){var n,r=this;if(!r.triggered){r.triggered=!0,r.def&&(r=r.def);try{(n=s(e))?c(function(){var t=new m(r);try{n.call(e,function(){d.apply(t,arguments)},function(){h.apply(t,arguments)})}catch(e){h.call(t,e)}}):(r.msg=e,r.state=1,0<r.chain.length&&c(f,r))}catch(e){h.call(new m(r),e)}}}function h(e){var t=this;t.triggered||(t.triggered=!0,t.def&&(t=t.def),t.msg=e,t.state=2,0<t.chain.length&&c(f,t))}function v(e,n,r,o){for(var t=0;t<n.length;t++)!function(t){e.resolve(n[t]).then(function(e){r(t,e)},o)}(t)}function m(e){this.def=e,this.triggered=!1}function p(e){this.promise=e,this.state=0,this.triggered=!1,this.chain=[],this.msg=void 0}function y(e){if("function"!=typeof e)throw TypeError("Not a function");if(0!==this.__NPO__)throw TypeError("Not a promise");this.__NPO__=1;var r=new p(this);this.then=function(e,t){var n={success:"function"!=typeof e||e,failure:"function"==typeof t&&t};return n.promise=new this.constructor(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");n.resolve=e,n.reject=t}),r.chain.push(n),0!==r.state&&c(f,r),n.promise},this.catch=function(e){return this.then(void 0,e)};try{e.call(void 0,function(e){d.call(r,e)},function(e){h.call(r,e)})}catch(e){h.call(r,e)}}var g=t({},"constructor",y,!(r={add:function(e,t){a=new l(e,t),i?i.next=a:o=a,i=a,a=void 0},drain:function(){var e=o;for(o=i=n=void 0;e;)e.fn.call(e.self),e=e.next}}));return t(y.prototype=g,"__NPO__",0,!1),t(y,"resolve",function(n){return n&&"object"==typeof n&&1===n.__NPO__?n:new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");e(n)})}),t(y,"reject",function(n){return new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");t(n)})}),t(y,"all",function(t){var a=this;return"[object Array]"!=e.call(t)?a.reject(TypeError("Not an array")):0===t.length?a.resolve([]):new a(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");var r=t.length,o=Array(r),i=0;v(a,t,function(e,t){o[e]=t,++i===r&&n(o)},e)})}),t(y,"race",function(t){var r=this;return"[object Array]"!=e.call(t)?r.reject(TypeError("Not an array")):new r(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");v(r,t,function(e,t){n(t)},e)})}),y},(n=f)[t="Promise"]=n[t]||r(),e.exports&&(e.exports=n[t])}(p={exports:{}}
35242),p.exports),g=new WeakMap;function w(e,t,n){var r=g.get(e.element)||{};t in r||(r[t]=[]),r[t].push(n),g.set(e.element,r)}function b(e,t){return(g.get(e.element)||{})[t]||[]}function k(e,t,n){var r=g.get(e.element)||{};if(!r[t])return!0;if(!n)return r[t]=[],g.set(e.element,r),!0;var o=r[t].indexOf(n);return-1!==o&&r[t].splice(o,1),g.set(e.element,r),r[t]&&0===r[t].length}function E(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){return console.warn(e),{}}return e}function T(e,t,n){var r,o;e.element.contentWindow&&e.element.contentWindow.postMessage&&(r={method:t},void 0!==n&&(r.value=n),8<=(o=parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/,"$1")))&&o<10&&(r=JSON.stringify(r)),e.element.contentWindow.postMessage(r,e.origin))}function P(n,r){var t,e,o=[];(r=E(r)).event?("error"===r.event&&b(n,r.data.method).forEach(function(e){var t=new Error(r.data.message);t.name=r.data.name,e.reject(t),k(n,r.data.method,e)}),o=b(n,"event:".concat(r.event)),t=r.data):!r.method||(e=function(e,t){var n=b(e,t);if(n.length<1)return!1;var r=n.shift();return k(e,t,r),r}(n,r.method))&&(o.push(e),t=r.value),o.forEach(function(e){try{if("function"==typeof e)return void e.call(n,t);e.resolve(t)}catch(e){}})}var M=["autopause","autoplay","background","byline","color","controls","dnt","height","id","interactive_params","keyboard","loop","maxheight","maxwidth","muted","playsinline","portrait","responsive","speed","texttrack","title","transparent","url","width"];function _(r,e){var t=1<arguments.length&&void 0!==e?e:{};return M.reduce(function(e,t){var n=r.getAttribute("data-vimeo-".concat(t));return!n&&""!==n||(e[t]=""===n?1:n),e},t)}function N(e,t){var n=e.html;if(!t)throw new TypeError("An element must be provided");if(null!==t.getAttribute("data-vimeo-initialized"))return t.querySelector("iframe");var r=document.createElement("div");return r.innerHTML=n,t.appendChild(r.firstChild),t.setAttribute("data-vimeo-initialized","true"),t.querySelector("iframe")}function F(i,e,t){var a=1<arguments.length&&void 0!==e?e:{},u=2<arguments.length?t:void 0;return new Promise(function(t,n){if(!c(i))throw new TypeError("â".concat(i,"â is not a vimeo.com url."));var e="https://vimeo.com/api/oembed.json?url=".concat(encodeURIComponent(i));for(var r in a)a.hasOwnProperty(r)&&(e+="&".concat(r,"=").concat(encodeURIComponent(a[r])));var o=new("XDomainRequest"in window?XDomainRequest:XMLHttpRequest);o.open("GET",e,!0),o.onload=function(){if(404!==o.status)if(403!==o.status)try{var e=JSON.parse(o.responseText);if(403===e.domain_status_code)return N(e,u),void n(new Error("â".concat(i,"â is not embeddable.")));t(e)}catch(e){n(e)}else n(new Error("â".concat(i,"â is not embeddable.")));else n(new Error("â".concat(i,"â was not found.")))},o.onerror=function(){var e=o.status?" (".concat(o.status,")"):"";n(new Error("There was an error fetching the embed code from Vimeo".concat(e,".")))},o.send()})}var x,C,j,A=new WeakMap,S=new WeakMap,q={},Player=function(){function Player(u){var e,t,l=this,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};if(!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,Player),window.jQuery&&u instanceof jQuery&&(1<u.length&&window.console&&console.warn&&console.warn("A jQuery object with multiple elements was passed, using the first element."),u=u[0]),"undefined"!=typeof document&&"string"==typeof u&&(u=document.getElementById(u)),e=u,!Boolean(e&&1===e.nodeType&&"nodeName"in e&&e.ownerDocument&&e.ownerDocument.defaultView))throw new TypeError("You must pass either a valid element or a valid id.");if("IFRAME"===u.nodeName||(t=u.querySelector("iframe"))&&(u=t),"IFRAME"===u.nodeName&&!c(u.getAttribute("src")||""))throw new Error("The player element passed isnât a Vimeo embed.");if(A.has(u))return A.get(u);this._window=u.ownerDocument.defaultView,this.element=u,this.origin="*";var r,o=new y(function(i,a){var e;l._onMessage=function(e){if(c(e.origin)&&l.element.contentWindow===e.source){"*"===l.origin&&(l.origin=e.origin);var t=E(e.data);if(t&&"error"===t.event&&t.data&&"ready"===t.data.method){var n=new Error(t.data.message);return n.name=t.data.name,void a(n)}
vendor: 9,482 bytes, line 35242
35242var r=t&&"ready"===t.event,o=t&&"ping"===t.method;if(r||o)return l.element.setAttribute("data-ready","true"),void i();P(l,t)}},l._window.addEventListener("message",l._onMessage),"IFRAME"!==l.element.nodeName&&F(s(e=_(u,n)),e,u).then(function(e){var t,n,r,o=N(e,u);return l.element=o,l._originalElement=u,t=u,n=o,r=g.get(t),g.set(n,r),g.delete(t),A.set(l.element,l),e}).catch(a)});return S.set(this,o),A.set(this.element,this),"IFRAME"===this.element.nodeName&&T(this,"ping"),q.isEnabled&&(r=function(){return q.exit()},this.fullscreenchangeHandler=function(){(q.isFullscreen?w:k)(l,"event:exitFullscreen",r),l.ready().then(function(){T(l,"fullscreenchange",q.isFullscreen)})},q.on("fullscreenchange",this.fullscreenchangeHandler)),this}var e,t,n;return e=Player,(t=[{key:"callMethod",value:function(n,e){var r=this,o=1<arguments.length&&void 0!==e?e:{};return new y(function(e,t){return r.ready().then(function(){w(r,n,{resolve:e,reject:t}),T(r,n,o)}).catch(t)})}},{key:"get",value:function(n){var r=this;return new y(function(e,t){return n=i(n,"get"),r.ready().then(function(){w(r,n,{resolve:e,reject:t}),T(r,n)}).catch(t)})}},{key:"set",value:function(n,r){var o=this;return new y(function(e,t){if(n=i(n,"set"),null==r)throw new TypeError("There must be a value to set.");return o.ready().then(function(){w(o,n,{resolve:e,reject:t}),T(o,n,r)}).catch(t)})}},{key:"on",value:function(e,t){if(!e)throw new TypeError("You must pass an event name.");if(!t)throw new TypeError("You must pass a callback function.");if("function"!=typeof t)throw new TypeError("The callback must be a function.");0===b(this,"event:".concat(e)).length&&this.callMethod("addEventListener",e).catch(function(){}),w(this,"event:".concat(e),t)}},{key:"off",value:function(e,t){if(!e)throw new TypeError("You must pass an event name.");if(t&&"function"!=typeof t)throw new TypeError("The callback must be a function.");k(this,"event:".concat(e),t)&&this.callMethod("removeEventListener",e).catch(function(e){})}},{key:"loadVideo",value:function(e){return this.callMethod("loadVideo",e)}},{key:"ready",value:function(){var e=S.get(this)||new y(function(e,t){t(new Error("Unknown player. Probably unloaded."))});return y.resolve(e)}},{key:"addCuePoint",value:function(e,t){var n=1<arguments.length&&void 0!==t?t:{};return this.callMethod("addCuePoint",{time:e,data:n})}},{key:"removeCuePoint",value:function(e){return this.callMethod("removeCuePoint",e)}},{key:"enableTextTrack",value:function(e,t){if(!e)throw new TypeError("You must pass a language.");return this.callMethod("enableTextTrack",{language:e,kind:t})}},{key:"disableTextTrack",value:function(){return this.callMethod("disableTextTrack")}},{key:"pause",value:function(){return this.callMethod("pause")}},{key:"play",value:function(){return this.callMethod("play")}},{key:"requestFullscreen",value:function(){return q.isEnabled?q.request(this.element):this.callMethod("requestFullscreen")}},{key:"exitFullscreen",value:function(){return q.isEnabled?q.exit():this.callMethod("exitFullscreen")}},{key:"getFullscreen",value:function(){return q.isEnabled?y.resolve(q.isFullscreen):this.get("fullscreen")}},{key:"requestPictureInPicture",value:function(){return this.callMethod("requestPictureInPicture")}},{key:"exitPictureInPicture",value:function(){return this.callMethod("exitPictureInPicture")}},{key:"getPictureInPicture",value:function(){return this.get("pictureInPicture")}},{key:"unload",value:function(){return this.callMethod("unload")}},{key:"destroy",value:function(){var n=this;return new y(function(e){var t;S.delete(n),A.delete(n.element),n._originalElement&&(A.delete(n._originalElement),n._originalElement.removeAttribute("data-vimeo-initialized")),n.element&&"IFRAME"===n.element.nodeName&&n.element.parentNode&&(n.element.parentNode.parentNode&&n._originalElement&&n._originalElement!==n.element.parentNode?n.element.parentNode.parentNode.removeChild(n.element.parentNode):n.element.parentNode.removeChild(n.element)),n.element&&"DIV"===n.element.nodeName&&n.element.parentNode&&(n.element.removeAttribute("data-vimeo-initialized"),(t=n.element.querySelector("iframe"))&&t.parentNode&&(t.parentNode.parentNode&&n._originalElement&&n._originalElement!==t.parentNode?t.parentNode.parentNode.removeChild(t.parentNode):t.parentNode.removeChild(t))),n._window.removeEventListener("message",n._onMessage),q.isEnabled&&q.off("fullscreenchange",n.fullscreenchangeHandler),e()})}},{key:"getAutopause",value:function(){return this.get("autopause")}},{key:"setAutopause",value:function(e){return this.set("autopause",e)}},{key:"getBuffered",value:function(){return this.get("buffered")}},{key:"getCameraProps",value:function(){return this.get("cameraProps")}},{key:"setCameraProps",value:function(e){return this.set("cameraProps",e)}},{key:"getChapters",value:function(){return this.get("chapters")}},{key:"getCurrentChapter",value:function(){return this.get("currentChapter")}},{key:"getColor",value:function(){return this.get("color")}},{key:"setColor",value:function(e){return this.set("color",e)}},{key:"getCuePoints",value:function(){return this.get("cuePoints")}},{key:"getCurrentTime",value:function(){return this.get("currentTime")}},{key:"setCurrentTime",value:function(e){return this.set("currentTime",e)}},{key:"getDuration",value:function(){return this.get("duration")}},{key:"getEnded",value:function(){return this.get("ended")}},{key:"getLoop",value:function(){return this.get("loop")}},{key:"setLoop",value:function(e){return this.set("loop",e)}},{key:"setMuted",value:function(e){return this.set("muted",e)}},{key:"getMuted",value:function(){return this.get("muted")}},{key:"getPaused",value:function(){return this.get("paused")}},{key:"getPlaybackRate",value:function(){return this.get("playbackRate")}},{key:"setPlaybackRate",value:function(e){return this.set("playbackRate",e)}},{key:"getPlayed",value:function(){return this.get("played")}},{key:"getQualities",value:function(){return this.get("qualities")}},{key:"getQuality",value:function(){return this.get("quality")}},{key:"setQuality",value:function(e){return this.set("quality",e)}},{key:"getSeekable",value:function(){return this.get("seekable")}},{key:"getSeeking",value:function(){return this.get("seeking")}},{key:"getTextTracks",value:function(){return this.get("textTracks")}},{key:"getVideoEmbedCode",value:function(){return this.get("videoEmbedCode")}},{key:"getVideoId",value:function(){return this.get("videoId")}},{key:"getVideoTitle",value:function(){return this.get("videoTitle")}},{key:"getVideoWidth",value:function(){return this.get("videoWidth")}},{key:"getVideoHeight",value:function(){return this.get("videoHeight")}},{key:"getVideoUrl",value:function(){return this.get("videoUrl")}},{key:"getVolume",value:function(){return this.get("volume")}},{key:"setVolume",value:function(e){return this.set("volume",e)}}])&&r(e.prototype,t),n&&r(e,n),Player}();return e||(x=function(){for(var e,t=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],n=0,r=t.length,o={};n<r;n++)if((e=t[n])&&e[1]in document){for(n=0;n<e.length;n++)o[t[0][n]]=e[n];return o}return!1}(),C={fullscreenchange:x.fullscreenchange,fullscreenerror:x.fullscreenerror},j={request:function(o){return new Promise(function(e,t){function n(){j.off("fullscreenchange",n),e()}j.on("fullscreenchange",n);var r=(o=o||document.documentElement)[x.requestFullscreen]();r instanceof Promise&&r.then(n).catch(t)})},exit:function(){return new Promise(function(t,e){var n,r;j.isFullscreen?(n=function e(){j.off("fullscreenchange",e),t()},j.on("fullscreenchange",n),(r=document[x.exitFullscreen]())instanceof Promise&&r.then(n).catch(e)):t()})},on:function(e,t){var n=C[e];n&&document.addEventListener(n,t)},off:function(e,t){var n=C[e];n&&document.removeEventListener(n,t)}},Object.defineProperties(j,{isFullscreen:{get:function(){return Boolean(document[x.fullscreenElement])}},element:{enumerable:!0,get:function(){return document[x.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(document[x.fullscreenEnabled])}}}),q=j,function(e){function n(e){"console"in window&&console.error&&console.error("There was an error creating an embed: ".concat(e))}var t=0<arguments.length&&void 0!==e?e:document;[].slice.call(t.querySelectorAll("[data-vimeo-id], [data-vimeo-url]")).forEach(function(t){try{if(null!==t.getAttribute("data-vimeo-defer"))return;var e=_(t);F(s(e),e,t).then(function(e){return N(e,t)}).catch(n)}catch(e){n(e)}})}(),function(e){var r=0<arguments.length&&void 0!==e?e:document;window.VimeoPlayerResizeEmbeds_||(window.VimeoPlayerResizeEmbeds_=!0,window.addEventListener("message",function(e){if(c(e.origin)&&e.data&&"spacechange"===e.data.event)for(var t=r.querySelectorAll("iframe"),n=0;n<t.length;n++)if(t[n].contentWindow===e.source){t[n].parentElement.style.paddingBottom="".concat(e.data.data[0].bottom,"px");break}}
vendor: 11,908 bytes, lines 35242-35722
35242))}(),function(e){var u=0<arguments.length&&void 0!==e?e:document;window.VimeoSeoMetadataAppended||(window.VimeoSeoMetadataAppended=!0,window.addEventListener("message",function(e){if(c(e.origin)){var t=E(e.data);if(t&&"ready"===t.event)for(var n,r=u.querySelectorAll("iframe"),o=0;o<r.length;o++){var i=r[o],a=i.contentWindow===e.source;n=i.src,/^https:\/\/player\.vimeo\.com\/video\/\d+/.test(n)&&a&&new Player(i).callMethod("appendVideoMetadata",window.location.href)}}}))}()),Player}); 35243 35244/** 35245 * Owl carousel 35246 * @version 2.0.0-beta.3 35247 * @author Bartosz Wojciechowski 35248 * @license The MIT License (MIT) 35249 * @todo Lazy Load Icon 35250 * @todo prevent animationend bubling 35251 * @todo itemsScaleUp 35252 * @todo Test Zepto 35253 * @todo stagePadding calculate wrong active classes 35254 */ 35255;(function($, window, document, undefined) { 35256 35257 /** 35258 * Creates a carousel. 35259 * @class The Owl Carousel. 35260 * @public 35261 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 35262 * @param {Object} [options] - The options 35263 */ 35264 function Owl(element, options) { 35265 35266 /** 35267 * Current settings for the carousel. 35268 * @public 35269 */ 35270 this.settings = null; 35271 35272 /** 35273 * Current options set by the caller including defaults. 35274 * @public 35275 */ 35276 this.options = $.extend({}, Owl.Defaults, options); 35277 35278 /** 35279 * Plugin element. 35280 * @public 35281 */ 35282 this.$element = $(element); 35283 35284 /** 35285 * Proxied event handlers. 35286 * @protected 35287 */ 35288 this._handlers = {}; 35289 35290 /** 35291 * References to the running plugins of this carousel. 35292 * @protected 35293 */ 35294 this._plugins = {}; 35295 35296 /** 35297 * Currently suppressed events to prevent them from beeing retriggered. 35298 * @protected 35299 */ 35300 this._supress = {}; 35301 35302 /** 35303 * Absolute current position. 35304 * @protected 35305 */ 35306 this._current = null; 35307 35308 /** 35309 * Animation speed in milliseconds. 35310 * @protected 35311 */ 35312 this._speed = null; 35313 35314 /** 35315 * Coordinates of all items in pixel. 35316 * @todo The name of this member is missleading. 35317 * @protected 35318 */ 35319 this._coordinates = []; 35320 35321 /** 35322 * Current breakpoint. 35323 * @todo Real media queries would be nice. 35324 * @protected 35325 */ 35326 this._breakpoint = null; 35327 35328 /** 35329 * Current width of the plugin element. 35330 */ 35331 this._width = null; 35332 35333 /** 35334 * All real items. 35335 * @protected 35336 */ 35337 this._items = []; 35338 35339 /** 35340 * All cloned items. 35341 * @protected 35342 */ 35343 this._clones = []; 35344 35345 /** 35346 * Merge values of all items. 35347 * @todo Maybe this could be part of a plugin. 35348 * @protected 35349 */ 35350 this._mergers = []; 35351 35352 /** 35353 * Widths of all items. 35354 */ 35355 this._widths = []; 35356 35357 /** 35358 * Invalidated parts within the update process. 35359 * @protected 35360 */ 35361 this._invalidated = {}; 35362 35363 /** 35364 * Ordered list of workers for the update process. 35365 * @protected 35366 */ 35367 this._pipe = []; 35368 35369 /** 35370 * Current state information for the drag operation. 35371 * @todo #261 35372 * @protected 35373 */ 35374 this._drag = { 35375 time: null, 35376 target: null, 35377 pointer: null, 35378 stage: { 35379 start: null, 35380 current: null 35381 }, 35382 direction: null 35383 }; 35384 35385 /** 35386 * Current state information and their tags. 35387 * @type {Object} 35388 * @protected 35389 */ 35390 this._states = { 35391 current: {}, 35392 tags: { 35393 'initializing': [ 'busy' ], 35394 'animating': [ 'busy' ], 35395 'dragging': [ 'interacting' ] 35396 } 35397 }; 35398 35399 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 35400 this._handlers[handler] = $.proxy(this[handler], this); 35401 }, this)); 35402 35403 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 35404 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 35405 = new plugin(this); 35406 }, this)); 35407 35408 $.each(Owl.Workers, $.proxy(function(priority, worker) { 35409 this._pipe.push({ 35410 'filter': worker.filter, 35411 'run': $.proxy(worker.run, this) 35412 }); 35413 }, this)); 35414 35415 this.setup(); 35416 this.initialize(); 35417 } 35418 35419 /** 35420 * Default options for the carousel. 35421 * @public 35422 */ 35423 Owl.Defaults = { 35424 items: 3, 35425 loop: false, 35426 center: false, 35427 rewind: false, 35428 35429 mouseDrag: true, 35430 touchDrag: true, 35431 pullDrag: true, 35432 freeDrag: false, 35433 35434 margin: 0, 35435 stagePadding: 0, 35436 35437 merge: false, 35438 mergeFit: true, 35439 autoWidth: false, 35440 35441 startPosition: 0, 35442 rtl: false, 35443 35444 smartSpeed: 250, 35445 fluidSpeed: false, 35446 dragEndSpeed: false, 35447 35448 responsive: {}, 35449 responsiveRefreshRate: 200, 35450 responsiveBaseElement: window, 35451 35452 fallbackEasing: 'swing', 35453 35454 info: false, 35455 35456 nestedItemSelector: false, 35457 itemSelector: false, 35458 itemElement: 'div', 35459 stageElement: 'div', 35460 35461 refreshClass: 'owl-refresh', 35462 loadedClass: 'owl-loaded', 35463 loadingClass: 'owl-loading', 35464 rtlClass: 'owl-rtl', 35465 responsiveClass: 'owl-responsive', 35466 dragClass: 'owl-drag', 35467 itemClass: 'owl-item', 35468 stageClass: 'owl-stage', 35469 stageOuterClass: 'owl-stage-outer', 35470 grabClass: 'owl-grab' 35471 }; 35472 35473 /** 35474 * Enumeration for width. 35475 * @public 35476 * @readonly 35477 * @enum {String} 35478 */ 35479 Owl.Width = { 35480 Default: 'default', 35481 Inner: 'inner', 35482 Outer: 'outer' 35483 }; 35484 35485 /** 35486 * Enumeration for types. 35487 * @public 35488 * @readonly 35489 * @enum {String} 35490 */ 35491 Owl.Type = { 35492 Event: 'event', 35493 State: 'state' 35494 }; 35495 35496 /** 35497 * Contains all registered plugins. 35498 * @public 35499 */ 35500 Owl.Plugins = {}; 35501 35502 /** 35503 * List of workers involved in the update process. 35504 */ 35505 Owl.Workers = [ { 35506 filter: [ 'width', 'settings' ], 35507 run: function() { 35508 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 35509 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 35510 } 35511 }, { 35512 filter: [ 'width', 'items', 'settings' ], 35513 run: function(cache) { 35514 cache.current = this._items && this._items[this.relative(this._current)]; 35515 } 35516 }, { 35517 filter: [ 'items', 'settings' ], 35518 run: function() { 35519 this.$stage.children('.cloned').remove(); 35520 } 35521 }, { 35522 filter: [ 'width', 'items', 'settings' ], 35523 run: function(cache) { 35524 var margin = this.settings.margin || '', 35525 grid = !this.settings.autoWidth, 35526 rtl = this.settings.rtl, 35527 css = { 35528 'width': 'auto', 35529 'margin-left': rtl ? margin : '', 35530 'margin-right': rtl ? '' : margin 35531 }; 35532 35533 !grid && this.$stage.children().css(css); 35534 35535 cache.css = css; 35536 } 35537 }, { 35538 filter: [ 'width', 'items', 'settings' ], 35539 run: function(cache) { 35540 //UNCODE edit to fix Chrome stage padding issue 35541 var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin), 35542 merge = null, 35543 iterator = this._items.length, 35544 grid = !this.settings.autoWidth, 35545 widths = []; 35546 35547 cache.items = { 35548 merge: false, 35549 width: width 35550 }; 35551 35552 while (iterator--) { 35553 merge = this._mergers[iterator]; 35554 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 35555 35556 cache.items.merge = merge > 1 || cache.items.merge; 35557 35558 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 35559 } 35560 35561 this._widths = widths; 35562 } 35563 }, { 35564 filter: [ 'items', 'settings' ], 35565 run: function() { 35566 var clones = [], 35567 items = this._items, 35568 settings = this.settings, 35569 view = Math.max(settings.items * 2, 4), 35570 size = Math.ceil(items.length / 2) * 2, 35571 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 35572 append = '', 35573 prepend = ''; 35574 35575 repeat /= 2; 35576 35577 while (repeat--) { 35578 clones.push(this.normalize(clones.length / 2, true)); 35579 append = append + items[clones[clones.length - 1]][0].outerHTML; 35580 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 35581 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 35582 } 35583 35584 this._clones = clones; 35585 35586 // var appendVideo = $(append).find('.uncode-video-container'); 35587 // if (appendVideo.length) { 35588 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 35589 // } 35590 // var prependVideo = $(prepend).find('.uncode-video-container'); 35591 // if (prependVideo.length) { 35592 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 35593 // } 35594 $(append).addClass('cloned').appendTo(this.$stage); 35595 $(prepend).addClass('cloned').prependTo(this.$stage); 35596 } 35597 }, { 35598 filter: [ 'width', 'items', 'settings' ], 35599 run: function() { 35600 var rtl = this.settings.rtl ? 1 : -1, 35601 size = this._clones.length + this._items.length, 35602 iterator = -1, 35603 previous = 0, 35604 current = 0, 35605 coordinates = []; 35606 35607 while (++iterator < size) { 35608 previous = coordinates[iterator - 1] || 0; 35609 current = this._widths[this.relative(iterator)] + this.settings.margin; 35610 coordinates.push(previous + current * rtl); 35611 } 35612 35613 this._coordinates = coordinates; 35614 } 35615 }, { 35616 filter: [ 'width', 'items', 'settings' ], 35617 run: function() { 35618 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 35619 padding = stagePadding, 35620 coordinates = this._coordinates, 35621 css = { 35622 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 35623 'padding-left': padding || '', 35624 'padding-right': padding || '' 35625 }; 35626 35627 this.$stage.css(css); 35628 } 35629 }, { 35630 filter: [ 'width', 'items', 'settings' ], 35631 run: function(cache) { 35632 var iterator = this._coordinates.length, 35633 grid = !this.settings.autoWidth, 35634 items = this.$stage.children(); 35635 35636 if (grid && cache.items.merge) { 35637 while (iterator--) { 35638 cache.css.width = this._widths[this.relative(iterator)]; 35639 items.eq(iterator).css(cache.css); 35640 } 35641 } else if (grid) { 35642 cache.css.width = cache.items.width; 35643 items.css(cache.css); 35644 } 35645 } 35646 }, { 35647 filter: [ 'items' ], 35648 run: function() { 35649 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 35650 } 35651 }, { 35652 filter: [ 'width', 'items', 'settings' ], 35653 run: function(cache) { 35654 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 35655 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 35656 this.reset(cache.current); 35657 } 35658 }, { 35659 filter: [ 'position' ], 35660 run: function() { 35661 this.animate(this.coordinates(this._current)); 35662 } 35663 }, { 35664 filter: [ 'width', 'position', 'items', 'settings' ], 35665 run: function() { 35666 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 35667 rtl = this.settings.rtl ? 1 : -1, 35668 padding = this.settings.stagePadding * 2, 35669 begin = this.coordinates(this.current()) + padding, 35670 end = begin + this.width() * rtl, 35671 inner, outer, matches = [], i, n; 35672 35673 for (i = 0, n = this._coordinates.length; i < n; i++) { 35674 inner = this._coordinates[i - 1] || 0; 35675 outer = Math.abs(this._coordinates[i]) + padding * rtl; 35676 35677 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 35678 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 35679 matches.push(i); 35680 } 35681 } 35682 35683 this.$stage.children('.active').removeClass('active'); 35684 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 35685 35686 if (this.settings.center) { 35687 this.$stage.children('.center').removeClass('center'); 35688 this.$stage.children().eq(this.current()).addClass('center'); 35689 } 35690 } 35691 } ]; 35692 35693 /** 35694 * Initializes the carousel. 35695 * @protected 35696 */ 35697 Owl.prototype.initialize = function() { 35698 this.enter('initializing'); 35699 this.trigger('initialize'); 35700 35701 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 35702 35703 if (this.settings.autoWidth && !this.is('pre-loading')) { 35704 var imgs, nestedSelector, width; 35705 imgs = this.$element.find('img'); 35706 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 35707 width = this.$element.children(nestedSelector).width(); 35708 35709 if (imgs.length && width <= 0) { 35710 this.preloadAutoWidthImages(imgs); 35711 } 35712 } 35713 35714 this.$element.addClass(this.options.loadingClass); 35715 35716 // create stage 35717 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 35718 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 35719 35720 //UNCODE edit to exclude hidden items 35721 if ( this.settings.itemSelector ) { 35722 // append stage
35723 this.$element.prepend(this.$stage.parent()); 35724 // append content 35725 this.replace(this.$element.find(' > ' + this.settings.itemSelector).not(this.$stage.parent())); 35726 } else { 35727 // append stage 35728 this.$element.append(this.$stage.parent()); 35729 // append content 35730 this.replace(this.$element.children().not(this.$stage.parent())); 35731 } 35732 35733 // check visibility 35734 if (this.$element.is(':visible')) { 35735 // update view 35736 this.refresh(); 35737 } else { 35738 // invalidate width 35739 this.invalidate('width'); 35740 } 35741 35742 this.$element 35743 .removeClass(this.options.loadingClass) 35744 .addClass(this.options.loadedClass); 35745 35746 // register event handlers 35747 this.registerEventHandlers(); 35748 35749 this.leave('initializing'); 35750 this.trigger('initialized'); 35751 }; 35752 35753 /** 35754 * Setups the current settings. 35755 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 35756 * @todo Support for media queries by using `matchMedia` would be nice. 35757 * @public 35758 */ 35759 Owl.prototype.setup = function() { 35760 var viewport = this.viewport(), 35761 overwrites = this.options.responsive, 35762 match = -1, 35763 settings = null; 35764 35765 if (!overwrites) { 35766 settings = $.extend({}, this.options); 35767 } else { 35768 $.each(overwrites, function(breakpoint) { 35769 if (breakpoint <= viewport && breakpoint > match) { 35770 match = Number(breakpoint); 35771 } 35772 }); 35773 35774 settings = $.extend({}, this.options, overwrites[match]); 35775 delete settings.responsive; 35776 35777 // responsive class 35778 if (settings.responsiveClass) { 35779 this.$element.attr('class', 35780 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 35781 ); 35782 } 35783 } 35784 35785 if (this.settings === null || this._breakpoint !== match) { 35786 this.trigger('change', { property: { name: 'settings', value: settings } }); 35787 this._breakpoint = match; 35788 this.settings = settings; 35789 this.invalidate('settings'); 35790 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 35791 } 35792 }; 35793 35794 /** 35795 * Updates option logic if necessery. 35796 * @protected 35797 */ 35798 Owl.prototype.optionsLogic = function() { 35799 if (this.settings.autoWidth) { 35800 this.settings.stagePadding = false; 35801 this.settings.merge = false; 35802 } 35803 }; 35804 35805 /** 35806 * Prepares an item before add. 35807 * @todo Rename event parameter `content` to `item`. 35808 * @protected 35809 * @returns {jQuery|HTMLElement} - The item container. 35810 */ 35811 Owl.prototype.prepare = function(item, index) { 35812 var event = this.trigger('prepare', { content: item }); 35813 if (!event.data) { 35814 event.data = $('<' + this.settings.itemElement + '/>') 35815 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 35816 } 35817 35818 this.trigger('prepared', { content: event.data }); 35819 35820 return event.data; 35821 }; 35822 35823 /** 35824 * Updates the view. 35825 * @public 35826 */ 35827 Owl.prototype.update = function() { 35828 var i = 0, 35829 n = this._pipe.length, 35830 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 35831 cache = {}; 35832 35833 while (i < n) { 35834 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 35835 this._pipe[i].run(cache); 35836 } 35837 i++; 35838 } 35839 35840 this._invalidated = {}; 35841 35842 !this.is('valid') && this.enter('valid'); 35843 }; 35844 35845 /** 35846 * Gets the width of the view. 35847 * @public 35848 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 35849 * @returns {Number} - The width of the view in pixel. 35850 */ 35851 Owl.prototype.width = function(dimension) { 35852 dimension = dimension || Owl.Width.Default; 35853 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 35854 switch (dimension) { 35855 case Owl.Width.Inner: 35856 case Owl.Width.Outer: 35857 return this._width; 35858 default: 35859 return this._width - stagePadding * 2 + this.settings.margin; 35860 } 35861 }; 35862 35863 /** 35864 * Refreshes the carousel primarily for adaptive purposes. 35865 * @public 35866 */ 35867 Owl.prototype.refresh = function() { 35868 this.enter('refreshing'); 35869 this.trigger('refresh'); 35870 35871 this.setup(); 35872 35873 this.optionsLogic(); 35874 35875 this.$element.addClass(this.options.refreshClass); 35876 35877 this.update(); 35878 35879 this.$element.removeClass(this.options.refreshClass); 35880 35881 this.leave('refreshing'); 35882 this.trigger('refreshed'); 35883 }; 35884 35885 /** 35886 * Checks window `resize` event. 35887 * @protected 35888 */ 35889 Owl.prototype.onThrottledResize = function() { 35890 window.clearTimeout(this.resizeTimer); 35891 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 35892 }; 35893 35894 /** 35895 * Checks window `resize` event. 35896 * @protected 35897 */ 35898 Owl.prototype.onResize = function() { 35899 if (!this._items.length) { 35900 return false;
vendor: 46,301 bytes, lines 35901-37605
35901 } 35902 35903 if (this._width === this.$element.width()) { 35904 return false; 35905 } 35906 35907 if (!this.$element.is(':visible')) { 35908 return false; 35909 } 35910 35911 this.enter('resizing'); 35912 35913 if (this.trigger('resize').isDefaultPrevented()) { 35914 this.leave('resizing'); 35915 return false; 35916 } 35917 35918 this.invalidate('width'); 35919 35920 this.refresh(); 35921 35922 this.leave('resizing'); 35923 this.trigger('resized'); 35924 }; 35925 35926 /** 35927 * Registers event handlers. 35928 * @todo Check `msPointerEnabled` 35929 * @todo #261 35930 * @protected 35931 */ 35932 Owl.prototype.registerEventHandlers = function() { 35933 if ($.support.transition) { 35934 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 35935 } 35936 35937 if (this.settings.responsive !== false) { 35938 this.on(window, 'resize', this._handlers.onThrottledResize); 35939 } 35940 35941 if (this.settings.mouseDrag) { 35942 this.$element.addClass(this.options.dragClass); 35943 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 35944 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 35945 } 35946 35947 if (this.settings.touchDrag){ 35948 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 35949 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 35950 } 35951 }; 35952 35953 /** 35954 * Handles `touchstart` and `mousedown` events. 35955 * @todo Horizontal swipe threshold as option 35956 * @todo #261 35957 * @protected 35958 * @param {Event} event - The event arguments. 35959 */ 35960 Owl.prototype.onDragStart = function(event) { 35961 var stage = null; 35962 35963 if (event.which === 3) { 35964 return; 35965 } 35966 35967 if ($.support.transform) { 35968 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 35969 stage = { 35970 x: stage[stage.length === 16 ? 12 : 4], 35971 y: stage[stage.length === 16 ? 13 : 5] 35972 }; 35973 } else { 35974 stage = this.$stage.position(); 35975 stage = { 35976 x: this.settings.rtl ? 35977 stage.left + this.$stage.width() - this.width() + this.settings.margin : 35978 stage.left, 35979 y: stage.top 35980 }; 35981 } 35982 35983 if (this.is('animating')) { 35984 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 35985 this.invalidate('position'); 35986 } 35987 35988 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 35989 35990 this.speed(0); 35991 35992 this._drag.time = new Date().getTime(); 35993 this._drag.target = $(event.target); 35994 this._drag.stage.start = stage; 35995 this._drag.stage.current = stage; 35996 this._drag.pointer = this.pointer(event); 35997 35998 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 35999 36000 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 36001 var delta = this.difference(this._drag.pointer, this.pointer(event)); 36002 36003 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 36004 36005 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 36006 return; 36007 } 36008 36009 event.preventDefault(); 36010 36011 this.enter('dragging'); 36012 this.trigger('drag'); 36013 }, this)); 36014 }; 36015 36016 /** 36017 * Handles the `touchmove` and `mousemove` events. 36018 * @todo #261 36019 * @protected 36020 * @param {Event} event - The event arguments. 36021 */ 36022 Owl.prototype.onDragMove = function(event) { 36023 var minimum = null, 36024 maximum = null, 36025 pull = null, 36026 delta = this.difference(this._drag.pointer, this.pointer(event)), 36027 stage = this.difference(this._drag.stage.start, delta); 36028 36029 if (!this.is('dragging')) { 36030 return; 36031 } 36032 36033 event.preventDefault(); 36034 36035 if (this.settings.loop) { 36036 minimum = this.coordinates(this.minimum()); 36037 maximum = this.coordinates(this.maximum() + 1) - minimum; 36038 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 36039 } else { 36040 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 36041 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 36042 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 36043 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 36044 } 36045 36046 this._drag.stage.current = stage; 36047 36048 this.animate(stage.x); 36049 }; 36050 36051 /** 36052 * Handles the `touchend` and `mouseup` events. 36053 * @todo #261 36054 * @todo Threshold for click event 36055 * @protected 36056 * @param {Event} event - The event arguments. 36057 */ 36058 Owl.prototype.onDragEnd = function(event) { 36059 var delta = this.difference(this._drag.pointer, this.pointer(event)), 36060 stage = this._drag.stage.current, 36061 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 36062 36063 $(document).off('.owl.core'); 36064 36065 this.$element.removeClass(this.options.grabClass); 36066 36067 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 36068 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 36069 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 36070 this.invalidate('position'); 36071 this.update(); 36072 36073 this._drag.direction = direction; 36074 36075 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 36076 this._drag.target.one('click.owl.core', function() { return false; }); 36077 } 36078 } 36079 36080 if (!this.is('dragging')) { 36081 return; 36082 } 36083 36084 this.leave('dragging'); 36085 this.trigger('dragged'); 36086 }; 36087 36088 /** 36089 * Gets absolute position of the closest item for a coordinate. 36090 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 36091 * @protected 36092 * @param {Number} coordinate - The coordinate in pixel. 36093 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 36094 * @return {Number} - The absolute position of the closest item. 36095 */ 36096 Owl.prototype.closest = function(coordinate, direction) { 36097 var position = -1, 36098 pull = 30, 36099 width = this.width(), 36100 coordinates = this.coordinates(); 36101 36102 if (!this.settings.freeDrag) { 36103 // check closest item 36104 $.each(coordinates, $.proxy(function(index, value) { 36105 if (coordinate > value - pull && coordinate < value + pull) { 36106 position = index; 36107 } else if (this.op(coordinate, '<', value) 36108 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 36109 position = direction === 'left' ? index + 1 : index; 36110 } 36111 return position === -1; 36112 }, this)); 36113 } 36114 36115 if (!this.settings.loop) { 36116 // non loop boundries 36117 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 36118 position = coordinate = this.minimum(); 36119 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 36120 position = coordinate = this.maximum(); 36121 } 36122 } 36123 36124 return position; 36125 }; 36126 36127 /** 36128 * Animates the stage. 36129 * @todo #270 36130 * @public 36131 * @param {Number} coordinate - The coordinate in pixels. 36132 */ 36133 Owl.prototype.animate = function(coordinate) { 36134 var animate = this.speed() > 0; 36135 36136 this.is('animating') && this.onTransitionEnd(); 36137 36138 if (animate) { 36139 this.enter('animating'); 36140 this.trigger('translate'); 36141 } 36142 36143 if ($.support.transform3d && $.support.transition) { 36144 this.$stage.css({ 36145 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 36146 transition: (this.speed() / 1000) + 's' 36147 }); 36148 } else if (animate) { 36149 this.$stage.animate({ 36150 left: coordinate + 'px' 36151 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 36152 } else { 36153 this.$stage.css({ 36154 left: coordinate + 'px' 36155 }); 36156 } 36157 }; 36158 36159 /** 36160 * Checks whether the carousel is in a specific state or not. 36161 * @param {String} state - The state to check. 36162 * @returns {Boolean} - The flag which indicates if the carousel is busy. 36163 */ 36164 Owl.prototype.is = function(state) { 36165 return this._states.current[state] && this._states.current[state] > 0; 36166 }; 36167 36168 /** 36169 * Sets the absolute position of the current item. 36170 * @public 36171 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 36172 * @returns {Number} - The absolute position of the current item. 36173 */ 36174 Owl.prototype.current = function(position) { 36175 if (position === undefined) { 36176 return this._current; 36177 } 36178 36179 if (this._items.length === 0) { 36180 return undefined; 36181 } 36182 36183 position = this.normalize(position); 36184 36185 if (this._current !== position) { 36186 var event = this.trigger('change', { property: { name: 'position', value: position } }); 36187 36188 if (event.data !== undefined) { 36189 position = this.normalize(event.data); 36190 } 36191 36192 this._current = position; 36193 36194 this.invalidate('position'); 36195 36196 this.trigger('changed', { property: { name: 'position', value: this._current } }); 36197 } 36198 36199 return this._current; 36200 }; 36201 36202 /** 36203 * Invalidates the given part of the update routine. 36204 * @param {String} [part] - The part to invalidate. 36205 * @returns {Array.<String>} - The invalidated parts. 36206 */ 36207 Owl.prototype.invalidate = function(part) { 36208 if ($.type(part) === 'string') { 36209 this._invalidated[part] = true; 36210 this.is('valid') && this.leave('valid'); 36211 } 36212 return $.map(this._invalidated, function(v, i) { return i }); 36213 }; 36214 36215 /** 36216 * Resets the absolute position of the current item. 36217 * @public 36218 * @param {Number} position - The absolute position of the new item. 36219 */ 36220 Owl.prototype.reset = function(position) { 36221 position = this.normalize(position); 36222 36223 if (position === undefined) { 36224 return; 36225 } 36226 36227 this._speed = 0; 36228 this._current = position; 36229 36230 this.suppress([ 'translate', 'translated' ]); 36231 36232 this.animate(this.coordinates(position)); 36233 36234 this.release([ 'translate', 'translated' ]); 36235 }; 36236 36237 /** 36238 * Normalizes an absolute or a relative position of an item. 36239 * @public 36240 * @param {Number} position - The absolute or relative position to normalize. 36241 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 36242 * @returns {Number} - The normalized position. 36243 */ 36244 Owl.prototype.normalize = function(position, relative) { 36245 var n = this._items.length, 36246 m = relative ? 0 : this._clones.length; 36247 36248 if (!$.isNumeric(position) || n < 1) { 36249 position = undefined; 36250 } else if (position < 0 || position >= n + m) { 36251 position = ((position - m / 2) % n + n) % n + m / 2; 36252 } 36253 36254 return position; 36255 }; 36256 36257 /** 36258 * Converts an absolute position of an item into a relative one. 36259 * @public 36260 * @param {Number} position - The absolute position to convert. 36261 * @returns {Number} - The converted position. 36262 */ 36263 Owl.prototype.relative = function(position) { 36264 position -= this._clones.length / 2; 36265 return this.normalize(position, true); 36266 }; 36267 36268 /** 36269 * Gets the maximum position for the current item. 36270 * @public 36271 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 36272 * @returns {Number} 36273 */ 36274 Owl.prototype.maximum = function(relative) { 36275 var settings = this.settings, 36276 maximum = this._coordinates.length, 36277 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 36278 i = -1, j; 36279 36280 if (settings.loop) { 36281 maximum = this._clones.length / 2 + this._items.length - 1; 36282 } else if (settings.autoWidth || settings.merge) { 36283 // binary search 36284 while (maximum - i > 1) { 36285 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 36286 ? i = j : maximum = j; 36287 } 36288 } else if (settings.center) { 36289 maximum = this._items.length - 1; 36290 } else { 36291 maximum = this._items.length - settings.items; 36292 } 36293 36294 if (relative) { 36295 maximum -= this._clones.length / 2; 36296 } 36297 36298 return Math.max(maximum, 0); 36299 }; 36300 36301 /** 36302 * Gets the minimum position for the current item. 36303 * @public 36304 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 36305 * @returns {Number} 36306 */ 36307 Owl.prototype.minimum = function(relative) { 36308 return relative ? 0 : this._clones.length / 2; 36309 }; 36310 36311 /** 36312 * Gets an item at the specified relative position. 36313 * @public 36314 * @param {Number} [position] - The relative position of the item. 36315 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 36316 */ 36317 Owl.prototype.items = function(position) { 36318 if (position === undefined) { 36319 return this._items.slice(); 36320 } 36321 36322 position = this.normalize(position, true); 36323 return this._items[position]; 36324 }; 36325 36326 /** 36327 * Gets an item at the specified relative position. 36328 * @public 36329 * @param {Number} [position] - The relative position of the item. 36330 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 36331 */ 36332 Owl.prototype.mergers = function(position) { 36333 if (position === undefined) { 36334 return this._mergers.slice(); 36335 } 36336 36337 position = this.normalize(position, true); 36338 return this._mergers[position]; 36339 }; 36340 36341 /** 36342 * Gets the absolute positions of clones for an item. 36343 * @public 36344 * @param {Number} [position] - The relative position of the item. 36345 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 36346 */ 36347 Owl.prototype.clones = function(position) { 36348 var odd = this._clones.length / 2, 36349 even = odd + this._items.length, 36350 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 36351 36352 if (position === undefined) { 36353 return $.map(this._clones, function(v, i) { return map(i) }); 36354 } 36355 36356 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 36357 }; 36358 36359 /** 36360 * Sets the current animation speed. 36361 * @public 36362 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 36363 * @returns {Number} - The current animation speed in milliseconds. 36364 */ 36365 Owl.prototype.speed = function(speed) { 36366 if (speed !== undefined) { 36367 this._speed = speed; 36368 } 36369 36370 return this._speed; 36371 }; 36372 36373 /** 36374 * Gets the coordinate of an item. 36375 * @todo The name of this method is missleanding. 36376 * @public 36377 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 36378 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 36379 */ 36380 Owl.prototype.coordinates = function(position) { 36381 var coordinate = null; 36382 36383 if (position === undefined) { 36384 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 36385 return this.coordinates(index); 36386 }, this)); 36387 } 36388 36389 if (this.settings.center) { 36390 coordinate = this._coordinates[position]; 36391 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 36392 } else { 36393 coordinate = this._coordinates[position - 1] || 0; 36394 } 36395 36396 return coordinate; 36397 }; 36398 36399 /** 36400 * Calculates the speed for a translation. 36401 * @protected 36402 * @param {Number} from - The absolute position of the start item. 36403 * @param {Number} to - The absolute position of the target item. 36404 * @param {Number} [factor=undefined] - The time factor in milliseconds. 36405 * @returns {Number} - The time in milliseconds for the translation. 36406 */ 36407 Owl.prototype.duration = function(from, to, factor) { 36408 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 36409 }; 36410 36411 /** 36412 * Slides to the specified item. 36413 * @public 36414 * @param {Number} position - The position of the item. 36415 * @param {Number} [speed] - The time in milliseconds for the transition. 36416 */ 36417 Owl.prototype.to = function(position, speed) { 36418 var current = this.current(), 36419 revert = null, 36420 distance = position - this.relative(current), 36421 direction = (distance > 0) - (distance < 0), 36422 items = this._items.length, 36423 minimum = this.minimum(), 36424 maximum = this.maximum(); 36425 36426 if (this.settings.loop) { 36427 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 36428 distance += direction * -1 * items; 36429 } 36430 36431 position = current + distance; 36432 revert = ((position - minimum) % items + items) % items + minimum; 36433 36434 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 36435 current = revert - distance; 36436 position = revert; 36437 this.reset(current); 36438 } 36439 } else if (this.settings.rewind) { 36440 maximum += 1; 36441 position = (position % maximum + maximum) % maximum; 36442 } else { 36443 position = Math.max(minimum, Math.min(maximum, position)); 36444 } 36445 36446 this.speed(this.duration(current, position, speed)); 36447 this.current(position); 36448 36449 if (this.$element.is(':visible')) { 36450 this.update(); 36451 } 36452 }; 36453 36454 /** 36455 * Slides to the next item. 36456 * @public 36457 * @param {Number} [speed] - The time in milliseconds for the transition. 36458 */ 36459 Owl.prototype.next = function(speed) { 36460 speed = speed || false; 36461 this.to(this.relative(this.current()) + 1, speed); 36462 }; 36463 36464 /** 36465 * Slides to the previous item. 36466 * @public 36467 * @param {Number} [speed] - The time in milliseconds for the transition. 36468 */ 36469 Owl.prototype.prev = function(speed) { 36470 speed = speed || false; 36471 this.to(this.relative(this.current()) - 1, speed); 36472 }; 36473 36474 /** 36475 * Handles the end of an animation. 36476 * @protected 36477 * @param {Event} event - The event arguments. 36478 */ 36479 Owl.prototype.onTransitionEnd = function(event) { 36480 36481 // if css2 animation then event object is undefined 36482 if (event !== undefined) { 36483 event.stopPropagation(); 36484 36485 // Catch only owl-stage transitionEnd event 36486 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 36487 return false; 36488 } 36489 } 36490 36491 this.leave('animating'); 36492 this.trigger('translated'); 36493 }; 36494 36495 /** 36496 * Gets viewport width. 36497 * @protected 36498 * @return {Number} - The width in pixel. 36499 */ 36500 Owl.prototype.viewport = function() { 36501 var width; 36502 if (this.options.responsiveBaseElement !== window) { 36503 width = $(this.options.responsiveBaseElement).width(); 36504 } else if (window.innerWidth) { 36505 width = window.innerWidth; 36506 } else if (document.documentElement && document.documentElement.clientWidth) { 36507 width = document.documentElement.clientWidth; 36508 } else { 36509 throw 'Can not detect viewport width.'; 36510 } 36511 36512 return width; 36513 }; 36514 36515 /** 36516 * Replaces the current content. 36517 * @public 36518 * @param {HTMLElement|jQuery|String} content - The new content. 36519 */ 36520 Owl.prototype.replace = function(content) { 36521 this.$stage.empty(); 36522 this._items = []; 36523 36524 if (content) { 36525 content = (content instanceof jQuery) ? content : $(content); 36526 } 36527 36528 if (this.settings.nestedItemSelector) { 36529 content = content.find('.' + this.settings.nestedItemSelector); 36530 } 36531 36532 content.filter(function() { 36533 return this.nodeType === 1; 36534 }).each($.proxy(function(index, item) { 36535 item = this.prepare(item, index); 36536 this.$stage.append(item); 36537 this._items.push(item); 36538 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 36539 }, this)); 36540 36541 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 36542 36543 this.invalidate('items'); 36544 }; 36545 36546 /** 36547 * Adds an item. 36548 * @todo Use `item` instead of `content` for the event arguments. 36549 * @public 36550 * @param {HTMLElement|jQuery|String} content - The item content to add. 36551 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 36552 */ 36553 Owl.prototype.add = function(content, position) { 36554 var current = this.relative(this._current); 36555 36556 position = position === undefined ? this._items.length : this.normalize(position, true); 36557 content = content instanceof jQuery ? content : $(content); 36558 36559 this.trigger('add', { content: content, position: position }); 36560 36561 content = this.prepare(content, this._items[current].index()); 36562 36563 if (this._items.length === 0 || position === this._items.length) { 36564 this._items.length === 0 && this.$stage.append(content); 36565 this._items.length !== 0 && this._items[position - 1].after(content); 36566 this._items.push(content); 36567 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 36568 } else { 36569 this._items[position].before(content); 36570 this._items.splice(position, 0, content); 36571 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 36572 } 36573 36574 this._items[current] && this.reset(this._items[current].index()); 36575 36576 this.invalidate('items'); 36577 36578 this.trigger('added', { content: content, position: position }); 36579 }; 36580 36581 /** 36582 * Removes an item by its position. 36583 * @todo Use `item` instead of `content` for the event arguments. 36584 * @public 36585 * @param {Number} position - The relative position of the item to remove. 36586 */ 36587 Owl.prototype.remove = function(position) { 36588 position = this.normalize(position, true); 36589 36590 if (position === undefined) { 36591 return; 36592 } 36593 36594 this.trigger('remove', { content: this._items[position], position: position }); 36595 36596 this._items[position].remove(); 36597 this._items.splice(position, 1); 36598 this._mergers.splice(position, 1); 36599 36600 this.invalidate('items'); 36601 36602 this.trigger('removed', { content: null, position: position }); 36603 }; 36604 36605 /** 36606 * Preloads images with auto width. 36607 * @todo Replace by a more generic approach 36608 * @protected 36609 */ 36610 Owl.prototype.preloadAutoWidthImages = function(images) { 36611 images.each($.proxy(function(i, element) { 36612 this.enter('pre-loading'); 36613 element = $(element); 36614 $(new Image()).one('load', $.proxy(function(e) { 36615 element.attr('src', e.target.src); 36616 element.css('opacity', 1); 36617 this.leave('pre-loading'); 36618 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 36619 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 36620 }, this)); 36621 }; 36622 36623 /** 36624 * Destroys the carousel. 36625 * @public 36626 */ 36627 Owl.prototype.destroy = function() { 36628 36629 this.$element.off('.owl.core'); 36630 this.$stage.off('.owl.core'); 36631 $(document).off('.owl.core'); 36632 36633 if (this.settings.responsive !== false) { 36634 window.clearTimeout(this.resizeTimer); 36635 this.off(window, 'resize', this._handlers.onThrottledResize); 36636 } 36637 36638 for (var i in this._plugins) { 36639 this._plugins[i].destroy(); 36640 } 36641 36642 this.$stage.children('.cloned').remove(); 36643 36644 this.$stage.unwrap(); 36645 this.$stage.children().contents().unwrap(); 36646 this.$stage.children().unwrap(); 36647 36648 this.$element 36649 .removeClass(this.options.refreshClass) 36650 .removeClass(this.options.loadingClass) 36651 .removeClass(this.options.loadedClass) 36652 .removeClass(this.options.rtlClass) 36653 .removeClass(this.options.dragClass) 36654 .removeClass(this.options.grabClass) 36655 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 36656 .removeData('owl.carousel'); 36657 }; 36658 36659 /** 36660 * Operators to calculate right-to-left and left-to-right. 36661 * @protected 36662 * @param {Number} [a] - The left side operand. 36663 * @param {String} [o] - The operator. 36664 * @param {Number} [b] - The right side operand. 36665 */ 36666 Owl.prototype.op = function(a, o, b) { 36667 var rtl = this.settings.rtl; 36668 switch (o) { 36669 case '<': 36670 return rtl ? a > b : a < b; 36671 case '>': 36672 return rtl ? a < b : a > b; 36673 case '>=': 36674 return rtl ? a <= b : a >= b; 36675 case '<=': 36676 return rtl ? a >= b : a <= b; 36677 default: 36678 break; 36679 } 36680 }; 36681 36682 /** 36683 * Attaches to an internal event. 36684 * @protected 36685 * @param {HTMLElement} element - The event source. 36686 * @param {String} event - The event name. 36687 * @param {Function} listener - The event handler to attach. 36688 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 36689 */ 36690 Owl.prototype.on = function(element, event, listener, capture) { 36691 if (element.addEventListener) { 36692 element.addEventListener(event, listener, capture); 36693 } else if (element.attachEvent) { 36694 element.attachEvent('on' + event, listener); 36695 } 36696 }; 36697 36698 /** 36699 * Detaches from an internal event. 36700 * @protected 36701 * @param {HTMLElement} element - The event source. 36702 * @param {String} event - The event name. 36703 * @param {Function} listener - The attached event handler to detach. 36704 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 36705 */ 36706 Owl.prototype.off = function(element, event, listener, capture) { 36707 if (element.removeEventListener) { 36708 element.removeEventListener(event, listener, capture); 36709 } else if (element.detachEvent) { 36710 element.detachEvent('on' + event, listener); 36711 } 36712 }; 36713 36714 /** 36715 * Triggers a public event. 36716 * @todo Remove `status`, `relatedTarget` should be used instead. 36717 * @protected 36718 * @param {String} name - The event name. 36719 * @param {*} [data=null] - The event data. 36720 * @param {String} [namespace=carousel] - The event namespace. 36721 * @param {String} [state] - The state which is associated with the event. 36722 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 36723 * @returns {Event} - The event arguments. 36724 */ 36725 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 36726 var status = { 36727 item: { count: this._items.length, index: this.current() } 36728 }, handler = $.camelCase( 36729 $.grep([ 'on', name, namespace ], function(v) { return v }) 36730 .join('-').toLowerCase() 36731 ), event = $.Event( 36732 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 36733 $.extend({ relatedTarget: this }, status, data) 36734 ); 36735 36736 if (!this._supress[name]) { 36737 $.each(this._plugins, function(name, plugin) { 36738 if (plugin.onTrigger) { 36739 plugin.onTrigger(event); 36740 } 36741 }); 36742 36743 this.register({ type: Owl.Type.Event, name: name }); 36744 this.$element.trigger(event); 36745 36746 if (this.settings && typeof this.settings[handler] === 'function') { 36747 this.settings[handler].call(this, event); 36748 } 36749 } 36750 36751 return event; 36752 }; 36753 36754 /** 36755 * Enters a state. 36756 * @param name - The state name. 36757 */ 36758 Owl.prototype.enter = function(name) { 36759 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 36760 if (this._states.current[name] === undefined) { 36761 this._states.current[name] = 0; 36762 } 36763 36764 this._states.current[name]++; 36765 }, this)); 36766 }; 36767 36768 /** 36769 * Leaves a state. 36770 * @param name - The state name. 36771 */ 36772 Owl.prototype.leave = function(name) { 36773 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 36774 this._states.current[name]--; 36775 }, this)); 36776 }; 36777 36778 /** 36779 * Registers an event or state. 36780 * @public 36781 * @param {Object} object - The event or state to register. 36782 */ 36783 Owl.prototype.register = function(object) { 36784 if (object.type === Owl.Type.Event) { 36785 if (!$.event.special[object.name]) { 36786 $.event.special[object.name] = {}; 36787 } 36788 36789 if (!$.event.special[object.name].owl) { 36790 var _default = $.event.special[object.name]._default; 36791 $.event.special[object.name]._default = function(e) { 36792 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 36793 return _default.apply(this, arguments); 36794 } 36795 return e.namespace && e.namespace.indexOf('owl') > -1; 36796 }; 36797 $.event.special[object.name].owl = true; 36798 } 36799 } else if (object.type === Owl.Type.State) { 36800 if (!this._states.tags[object.name]) { 36801 this._states.tags[object.name] = object.tags; 36802 } else { 36803 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 36804 } 36805 36806 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 36807 return $.inArray(tag, this._states.tags[object.name]) === i; 36808 }, this)); 36809 } 36810 }; 36811 36812 /** 36813 * Suppresses events. 36814 * @protected 36815 * @param {Array.<String>} events - The events to suppress. 36816 */ 36817 Owl.prototype.suppress = function(events) { 36818 $.each(events, $.proxy(function(index, event) { 36819 this._supress[event] = true; 36820 }, this)); 36821 }; 36822 36823 /** 36824 * Releases suppressed events. 36825 * @protected 36826 * @param {Array.<String>} events - The events to release. 36827 */ 36828 Owl.prototype.release = function(events) { 36829 $.each(events, $.proxy(function(index, event) { 36830 delete this._supress[event]; 36831 }, this)); 36832 }; 36833 36834 /** 36835 * Gets unified pointer coordinates from event. 36836 * @todo #261 36837 * @protected 36838 * @param {Event} - The `mousedown` or `touchstart` event. 36839 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 36840 */ 36841 Owl.prototype.pointer = function(event) { 36842 var result = { x: null, y: null }; 36843 36844 event = event.originalEvent || event || window.event; 36845 36846 event = event.touches && event.touches.length ? 36847 event.touches[0] : event.changedTouches && event.changedTouches.length ? 36848 event.changedTouches[0] : event; 36849 36850 if (event.pageX) { 36851 result.x = event.pageX; 36852 result.y = event.pageY; 36853 } else { 36854 result.x = event.clientX; 36855 result.y = event.clientY; 36856 } 36857 36858 return result; 36859 }; 36860 36861 /** 36862 * Gets the difference of two vectors. 36863 * @todo #261 36864 * @protected 36865 * @param {Object} - The first vector. 36866 * @param {Object} - The second vector. 36867 * @returns {Object} - The difference. 36868 */ 36869 Owl.prototype.difference = function(first, second) { 36870 return { 36871 x: first.x - second.x, 36872 y: first.y - second.y 36873 }; 36874 }; 36875 36876 /** 36877 * The jQuery Plugin for the Owl Carousel 36878 * @todo Navigation plugin `next` and `prev` 36879 * @public 36880 */ 36881 $.fn.owlCarousel = function(option) { 36882 var args = Array.prototype.slice.call(arguments, 1); 36883 36884 return this.each(function() { 36885 var $this = $(this), 36886 data = $this.data('owl.carousel'); 36887 36888 if (!data) { 36889 data = new Owl(this, typeof option == 'object' && option); 36890 $this.data('owl.carousel', data); 36891 36892 $.each([ 36893 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 36894 ], function(i, event) { 36895 data.register({ type: Owl.Type.Event, name: event }); 36896 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 36897 if (e.namespace && e.relatedTarget !== this) { 36898 this.suppress([ event ]); 36899 data[event].apply(this, [].slice.call(arguments, 1)); 36900 this.release([ event ]); 36901 } 36902 }, data)); 36903 }); 36904 } 36905 36906 if (typeof option == 'string' && option.charAt(0) !== '_') { 36907 data[option].apply(data, args); 36908 } 36909 }); 36910 }; 36911 36912 /** 36913 * The constructor for the jQuery Plugin 36914 * @public 36915 */ 36916 $.fn.owlCarousel.Constructor = Owl; 36917 36918})(window.Zepto || window.jQuery, window, document); 36919 36920/** 36921 * AutoRefresh Plugin 36922 * @version 2.0.0-beta.3 36923 * @author Artus Kolanowski 36924 * @license The MIT License (MIT) 36925 */ 36926;(function($, window, document, undefined) { 36927 36928 /** 36929 * Creates the auto refresh plugin. 36930 * @class The Auto Refresh Plugin 36931 * @param {Owl} carousel - The Owl Carousel 36932 */ 36933 var AutoRefresh = function(carousel) { 36934 /** 36935 * Reference to the core. 36936 * @protected 36937 * @type {Owl} 36938 */ 36939 this._core = carousel; 36940 36941 /** 36942 * Refresh interval. 36943 * @protected 36944 * @type {number} 36945 */ 36946 this._interval = null; 36947 36948 /** 36949 * Whether the element is currently visible or not. 36950 * @protected 36951 * @type {Boolean} 36952 */ 36953 this._visible = null; 36954 36955 /** 36956 * All event handlers. 36957 * @protected 36958 * @type {Object} 36959 */ 36960 this._handlers = { 36961 'initialized.owl.carousel': $.proxy(function(e) { 36962 if (e.namespace && this._core.settings.autoRefresh) { 36963 this.watch(); 36964 } 36965 }, this) 36966 }; 36967 36968 // set default options 36969 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 36970 36971 // register event handlers 36972 this._core.$element.on(this._handlers); 36973 }; 36974 36975 /** 36976 * Default options. 36977 * @public 36978 */ 36979 AutoRefresh.Defaults = { 36980 autoRefresh: true, 36981 autoRefreshInterval: 500 36982 }; 36983 36984 /** 36985 * Watches the element. 36986 */ 36987 AutoRefresh.prototype.watch = function() { 36988 if (this._interval) { 36989 return; 36990 } 36991 36992 this._visible = this._core.$element.is(':visible'); 36993 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 36994 }; 36995 36996 /** 36997 * Refreshes the element. 36998 */ 36999 AutoRefresh.prototype.refresh = function() { 37000 if (this._core.$element.is(':visible') === this._visible || this._core.$element.closest('.drop-menu').length) { 37001 return; 37002 } 37003 37004 this._visible = !this._visible; 37005 37006 this._core.$element.toggleClass('owl-hidden', !this._visible); 37007 37008 this._visible && (this._core.invalidate('width') && this._core.refresh()); 37009 }; 37010 37011 /** 37012 * Destroys the plugin. 37013 */ 37014 AutoRefresh.prototype.destroy = function() { 37015 var handler, property; 37016 37017 window.clearInterval(this._interval); 37018 37019 for (handler in this._handlers) { 37020 this._core.$element.off(handler, this._handlers[handler]); 37021 } 37022 for (property in Object.getOwnPropertyNames(this)) { 37023 typeof this[property] != 'function' && (this[property] = null); 37024 } 37025 }; 37026 37027 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 37028 37029})(window.Zepto || window.jQuery, window, document); 37030 37031/** 37032 * Lazy Plugin 37033 * @version 2.0.0-beta.3 37034 * @author Bartosz Wojciechowski 37035 * @license The MIT License (MIT) 37036 */ 37037;(function($, window, document, undefined) { 37038 37039 /** 37040 * Creates the lazy plugin. 37041 * @class The Lazy Plugin 37042 * @param {Owl} carousel - The Owl Carousel 37043 */ 37044 var Lazy = function(carousel) { 37045 37046 /** 37047 * Reference to the core. 37048 * @protected 37049 * @type {Owl} 37050 */ 37051 this._core = carousel; 37052 37053 /** 37054 * Already loaded items. 37055 * @protected 37056 * @type {Array.<jQuery>} 37057 */ 37058 this._loaded = []; 37059 37060 /** 37061 * Event handlers. 37062 * @protected 37063 * @type {Object} 37064 */ 37065 this._handlers = { 37066 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 37067 if (!e.namespace) { 37068 return; 37069 } 37070 37071 if (!this._core.settings || !this._core.settings.lazyLoad) { 37072 return; 37073 } 37074 37075 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 37076 var settings = this._core.settings, 37077 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 37078 i = ((settings.center && n * -1) || 0), 37079 position = ((e.property && e.property.value) || this._core.current()) + i, 37080 clones = this._core.clones().length, 37081 load = $.proxy(function(i, v) { this.load(v) }, this); 37082 37083 while (i++ < n) { 37084 this.load(clones / 2 + this._core.relative(position)); 37085 clones && $.each(this._core.clones(this._core.relative(position)), load); 37086 position++; 37087 } 37088 } 37089 }, this) 37090 }; 37091 37092 // set the default options 37093 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 37094 37095 // register event handler 37096 this._core.$element.on(this._handlers); 37097 } 37098 37099 /** 37100 * Default options. 37101 * @public 37102 */ 37103 Lazy.Defaults = { 37104 lazyLoad: false 37105 } 37106 37107 /** 37108 * Loads all resources of an item at the specified position. 37109 * @param {Number} position - The absolute position of the item. 37110 * @protected 37111 */ 37112 Lazy.prototype.load = function(position) { 37113 var $item = this._core.$stage.children().eq(position), 37114 $elements = $item && $item.find('.owl-lazy'); 37115 37116 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 37117 return; 37118 } 37119 37120 $elements.each($.proxy(function(index, element) { 37121 var $element = $(element), image, 37122 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 37123 37124 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 37125 37126 if ($element.is('img')) { 37127 $element.one('load.owl.lazy', $.proxy(function() { 37128 $element.css('opacity', 1); 37129 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 37130 }, this)).attr('src', url); 37131 } else { 37132 image = new Image(); 37133 image.onload = $.proxy(function() { 37134 $element.css({ 37135 'background-image': 'url(' + url + ')', 37136 'opacity': '1' 37137 }); 37138 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 37139 }, this); 37140 image.src = url; 37141 } 37142 }, this)); 37143 37144 this._loaded.push($item.get(0)); 37145 } 37146 37147 /** 37148 * Destroys the plugin. 37149 * @public 37150 */ 37151 Lazy.prototype.destroy = function() { 37152 var handler, property; 37153 37154 for (handler in this.handlers) { 37155 this._core.$element.off(handler, this.handlers[handler]); 37156 } 37157 for (property in Object.getOwnPropertyNames(this)) { 37158 typeof this[property] != 'function' && (this[property] = null); 37159 } 37160 }; 37161 37162 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 37163 37164})(window.Zepto || window.jQuery, window, document); 37165 37166/** 37167 * AutoHeight Plugin 37168 * @version 2.0.0-beta.3 37169 * @author Bartosz Wojciechowski 37170 * @license The MIT License (MIT) 37171 */ 37172;(function($, window, document, undefined) { 37173 37174 /** 37175 * Creates the auto height plugin. 37176 * @class The Auto Height Plugin 37177 * @param {Owl} carousel - The Owl Carousel 37178 */ 37179 var AutoHeight = function(carousel) { 37180 /** 37181 * Reference to the core. 37182 * @protected 37183 * @type {Owl} 37184 */ 37185 this._core = carousel; 37186 37187 /** 37188 * All event handlers. 37189 * @protected 37190 * @type {Object} 37191 */ 37192 this._handlers = { 37193 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 37194 if (e.namespace && this._core.settings.autoHeight) { 37195 this.update(); 37196 } 37197 }, this), 37198 'changed.owl.carousel': $.proxy(function(e) { 37199 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 37200 this.update(); 37201 } 37202 }, this), 37203 'loaded.owl.lazy': $.proxy(function(e) { 37204 if (e.namespace && this._core.settings.autoHeight 37205 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 37206 this.update(); 37207 } 37208 }, this) 37209 }; 37210 37211 // set default options 37212 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 37213 37214 // register event handlers 37215 this._core.$element.on(this._handlers); 37216 }; 37217 37218 /** 37219 * Default options. 37220 * @public 37221 */ 37222 AutoHeight.Defaults = { 37223 autoHeight: false, 37224 autoHeightClass: 'owl-height' 37225 }; 37226 37227 /** 37228 * Updates the view. 37229 */ 37230 AutoHeight.prototype.update = function() { 37231 var start = this._core._current, 37232 end = start + this._core.settings.items, 37233 visible = this._core.$stage.children().toArray().slice(start, end); 37234 heights = [], 37235 maxheight = 0; 37236 37237 $.each(visible, function(index, item) { 37238 heights.push($(item).height()); 37239 }); 37240 37241 maxheight = Math.max.apply(null, heights); 37242 37243 this._core.$stage.parent() 37244 .height(maxheight) 37245 .addClass(this._core.settings.autoHeightClass); 37246 }; 37247 37248 AutoHeight.prototype.destroy = function() { 37249 var handler, property; 37250 37251 for (handler in this._handlers) { 37252 this._core.$element.off(handler, this._handlers[handler]); 37253 } 37254 for (property in Object.getOwnPropertyNames(this)) { 37255 typeof this[property] != 'function' && (this[property] = null); 37256 } 37257 }; 37258 37259 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 37260 37261})(window.Zepto || window.jQuery, window, document); 37262 37263/** 37264 * Video Plugin 37265 * @version 2.0.0-beta.3 37266 * @author Bartosz Wojciechowski 37267 * @license The MIT License (MIT) 37268 */ 37269;(function($, window, document, undefined) { 37270 37271 /** 37272 * Creates the video plugin. 37273 * @class The Video Plugin 37274 * @param {Owl} carousel - The Owl Carousel 37275 */ 37276 var Video = function(carousel) { 37277 /** 37278 * Reference to the core. 37279 * @protected 37280 * @type {Owl} 37281 */ 37282 this._core = carousel; 37283 37284 /** 37285 * Cache all video URLs. 37286 * @protected 37287 * @type {Object} 37288 */ 37289 this._videos = {}; 37290 37291 /** 37292 * Current playing item. 37293 * @protected 37294 * @type {jQuery} 37295 */ 37296 this._playing = null; 37297 37298 /** 37299 * All event handlers. 37300 * @todo The cloned content removale is too late 37301 * @protected 37302 * @type {Object} 37303 */ 37304 this._handlers = { 37305 'initialized.owl.carousel': $.proxy(function(e) { 37306 if (e.namespace) { 37307 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 37308 } 37309 }, this), 37310 'resize.owl.carousel': $.proxy(function(e) { 37311 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 37312 e.preventDefault(); 37313 } 37314 }, this), 37315 'refreshed.owl.carousel': $.proxy(function(e) { 37316 if (e.namespace && this._core.is('resizing')) { 37317 this._core.$stage.find('.cloned .owl-video-frame').remove(); 37318 } 37319 }, this), 37320 'changed.owl.carousel': $.proxy(function(e) { 37321 if (e.namespace && e.property.name === 'position' && this._playing) { 37322 this.stop(); 37323 } 37324 }, this), 37325 'prepared.owl.carousel': $.proxy(function(e) { 37326 if (!e.namespace) { 37327 return; 37328 } 37329 37330 var $element = $(e.content).find('.owl-video'); 37331 37332 if ($element.length) { 37333 $element.css('display', 'none'); 37334 this.fetch($element, $(e.content)); 37335 } 37336 }, this) 37337 }; 37338 37339 // set default options 37340 this._core.options = $.extend({}, Video.Defaults, this._core.options); 37341 37342 // register event handlers 37343 this._core.$element.on(this._handlers); 37344 37345 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 37346 this.play(e); 37347 }, this)); 37348 }; 37349 37350 /** 37351 * Default options. 37352 * @public 37353 */ 37354 Video.Defaults = { 37355 video: false, 37356 videoHeight: false, 37357 videoWidth: false 37358 }; 37359 37360 /** 37361 * Gets the video ID and the type (YouTube/Vimeo only). 37362 * @protected 37363 * @param {jQuery} target - The target containing the video data. 37364 * @param {jQuery} item - The item containing the video. 37365 */ 37366 Video.prototype.fetch = function(target, item) { 37367 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 37368 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 37369 width = target.attr('data-width') || this._core.settings.videoWidth, 37370 height = target.attr('data-height') || this._core.settings.videoHeight, 37371 url = target.attr('href'); 37372 37373 if (url) { 37374 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+)?/); 37375 37376 if (id[3].indexOf('youtu') > -1) { 37377 type = 'youtube'; 37378 } else if (id[3].indexOf('vimeo') > -1) { 37379 type = 'vimeo'; 37380 } else { 37381 throw new Error('Video URL not supported.'); 37382 } 37383 id = id[6]; 37384 } else { 37385 throw new Error('Missing video URL.'); 37386 } 37387 37388 this._videos[url] = { 37389 type: type, 37390 id: id, 37391 width: width, 37392 height: height 37393 }; 37394 37395 item.attr('data-video', url); 37396 37397 this.thumbnail(target, this._videos[url]); 37398 }; 37399 37400 /** 37401 * Creates video thumbnail. 37402 * @protected 37403 * @param {jQuery} target - The target containing the video data. 37404 * @param {Object} info - The video info object. 37405 * @see `fetch` 37406 */ 37407 Video.prototype.thumbnail = function(target, video) { 37408 var tnLink, 37409 icon, 37410 path, 37411 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 37412 customTn = target.find('img'), 37413 srcType = 'src', 37414 lazyClass = '', 37415 settings = this._core.settings, 37416 create = function(path) { 37417 icon = '<div class="owl-video-play-icon"></div>'; 37418 37419 if (settings.lazyLoad) { 37420 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 37421 } else { 37422 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 37423 } 37424 target.after(tnLink); 37425 target.after(icon); 37426 }; 37427 37428 // wrap video content into owl-video-wrapper div 37429 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 37430 37431 if (this._core.settings.lazyLoad) { 37432 srcType = 'data-src'; 37433 lazyClass = 'owl-lazy'; 37434 } 37435 37436 // custom thumbnail 37437 if (customTn.length) { 37438 create(customTn.attr(srcType)); 37439 customTn.remove(); 37440 return false; 37441 } 37442 37443 if (video.type === 'youtube') { 37444 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 37445 create(path); 37446 } else if (video.type === 'vimeo') { 37447 $.ajax({ 37448 type: 'GET', 37449 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 37450 jsonp: 'callback', 37451 dataType: 'jsonp', 37452 success: function(data) { 37453 path = data[0].thumbnail_large; 37454 create(path); 37455 } 37456 }); 37457 } 37458 }; 37459 37460 /** 37461 * Stops the current video. 37462 * @public 37463 */ 37464 Video.prototype.stop = function() { 37465 this._core.trigger('stop', null, 'video'); 37466 this._playing.find('.owl-video-frame').remove(); 37467 this._playing.removeClass('owl-video-playing'); 37468 this._playing = null; 37469 this._core.leave('playing'); 37470 this._core.trigger('stopped', null, 'video'); 37471 }; 37472 37473 /** 37474 * Starts the current video. 37475 * @public 37476 * @param {Event} event - The event arguments. 37477 */ 37478 Video.prototype.play = function(event) { 37479 var target = $(event.target), 37480 item = target.closest('.' + this._core.settings.itemClass), 37481 video = this._videos[item.attr('data-video')], 37482 width = video.width || '100%', 37483 height = video.height || this._core.$stage.height(), 37484 html; 37485 37486 if (this._playing) { 37487 return; 37488 } 37489 37490 this._core.enter('playing'); 37491 this._core.trigger('play', null, 'video'); 37492 37493 item = this._core.items(this._core.relative(item.index())); 37494 37495 this._core.reset(item.index()); 37496 37497 if (video.type === 'youtube') { 37498 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 37499 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 37500 } else if (video.type === 'vimeo') { 37501 html = '<iframe src="//player.vimeo.com/video/' + video.id + 37502 '?autoplay=1" width="' + width + '" height="' + height + 37503 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 37504 } 37505 37506 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 37507 37508 this._playing = item.addClass('owl-video-playing'); 37509 }; 37510 37511 /** 37512 * Checks whether an video is currently in full screen mode or not. 37513 * @todo Bad style because looks like a readonly method but changes members. 37514 * @protected 37515 * @returns {Boolean} 37516 */ 37517 Video.prototype.isInFullScreen = function() { 37518 var element = document.fullscreenElement || document.mozFullScreenElement || 37519 document.webkitFullscreenElement; 37520 37521 return element && $(element).parent().hasClass('owl-video-frame'); 37522 }; 37523 37524 /** 37525 * Destroys the plugin. 37526 */ 37527 Video.prototype.destroy = function() { 37528 var handler, property; 37529 37530 this._core.$element.off('click.owl.video'); 37531 37532 for (handler in this._handlers) { 37533 this._core.$element.off(handler, this._handlers[handler]); 37534 } 37535 for (property in Object.getOwnPropertyNames(this)) { 37536 typeof this[property] != 'function' && (this[property] = null); 37537 } 37538 }; 37539 37540 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 37541 37542})(window.Zepto || window.jQuery, window, document); 37543 37544/** 37545 * Animate Plugin 37546 * @version 2.0.0-beta.3 37547 * @author Bartosz Wojciechowski 37548 * @license The MIT License (MIT) 37549 */ 37550;(function($, window, document, undefined) { 37551 37552 /** 37553 * Creates the animate plugin. 37554 * @class The Navigation Plugin 37555 * @param {Owl} scope - The Owl Carousel 37556 */ 37557 var Animate = function(scope) { 37558 this.core = scope; 37559 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 37560 this.swapping = true; 37561 this.previous = undefined; 37562 this.next = undefined; 37563 37564 this.handlers = { 37565 'change.owl.carousel': $.proxy(function(e) { 37566 if (e.namespace && e.property.name == 'position') { 37567 this.previous = this.core.current(); 37568 this.next = e.property.value; 37569 } 37570 }, this), 37571 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 37572 if (e.namespace) { 37573 this.swapping = e.type == 'translated'; 37574 } 37575 }, this), 37576 'translate.owl.carousel': $.proxy(function(e) { 37577 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 37578 this.swap(); 37579 } 37580 }, this) 37581 }; 37582 37583 this.core.$element.on(this.handlers); 37584 }; 37585 37586 /** 37587 * Default options. 37588 * @public 37589 */ 37590 Animate.Defaults = { 37591 animateOut: false, 37592 animateIn: false 37593 }; 37594 37595 /** 37596 * Toggles the animation classes whenever an translations starts. 37597 * @protected 37598 * @returns {Boolean|undefined} 37599 */ 37600 Animate.prototype.swap = function() { 37601 37602 if (this.core.settings.items !== 1) { 37603 return; 37604 } 37605
37606 if (!$.support.animation || !$.support.transition) { 37607 return; 37608 } 37609 37610 this.core.speed(0); 37611 37612 var left, 37613 clear = $.proxy(this.clear, this), 37614 previous = this.core.$stage.children().eq(this.previous), 37615 next = this.core.$stage.children().eq(this.next), 37616 incoming = this.core.settings.animateIn, 37617 outgoing = this.core.settings.animateOut; 37618 37619 if (this.core.current() === this.previous) { 37620 return; 37621 } 37622 37623 if (outgoing) { 37624 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 37625 previous.css( { 'left': left + 'px' } ) 37626 .addClass('animated owl-animated-out') 37627 .addClass(outgoing) 37628 .on($.support.animation.end, clear); 37629 } 37630 37631 if (incoming) { 37632 next.addClass('animated owl-animated-in') 37633 .addClass(incoming) 37634 .on($.support.animation.end, clear); 37635 } 37636 }; 37637 37638 Animate.prototype.clear = function(e) { 37639 if ($(e.target).hasClass('animated')) { 37640 $(e.target).css( { 'left': '' } ) 37641 .removeClass('animated owl-animated-out owl-animated-in') 37642 .removeClass(this.core.settings.animateIn) 37643 .removeClass(this.core.settings.animateOut); 37644 this.core.onTransitionEnd(); 37645 } 37646 }; 37647 37648 /** 37649 * Destroys the plugin. 37650 * @public 37651 */ 37652 Animate.prototype.destroy = function() { 37653 var handler, property; 37654 37655 for (handler in this.handlers) { 37656 this.core.$element.off(handler, this.handlers[handler]); 37657 } 37658 for (property in Object.getOwnPropertyNames(this)) { 37659 typeof this[property] != 'function' && (this[property] = null); 37660 } 37661 }; 37662 37663 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 37664 37665})(window.Zepto || window.jQuery, window, document); 37666 37667/** 37668 * Autoplay Plugin 37669 * @version 2.0.0-beta.3 37670 * @author Bartosz Wojciechowski 37671 * @author Artus Kolanowski 37672 * @license The MIT License (MIT) 37673 */ 37674;(function($, window, document, undefined) { 37675 37676 /** 37677 * Creates the autoplay plugin. 37678 * @class The Autoplay Plugin 37679 * @param {Owl} scope - The Owl Carousel 37680 */ 37681 var Autoplay = function(carousel) { 37682 /** 37683 * Reference to the core. 37684 * @protected 37685 * @type {Owl} 37686 */ 37687 this._core = carousel; 37688 37689 /** 37690 * The autoplay interval. 37691 * @type {Number} 37692 */ 37693 this._interval = null; 37694 37695 /** 37696 * Indicates whenever the autoplay is paused. 37697 * @type {Boolean} 37698 */ 37699 this._paused = false; 37700 37701 /** 37702 * All event handlers. 37703 * @protected 37704 * @type {Object} 37705 */ 37706 this._handlers = { 37707 'changed.owl.carousel': $.proxy(function(e) { 37708 if (e.namespace && e.property.name === 'settings') { 37709 if (this._core.settings.autoplay) { 37710 this.play(); 37711 } else { 37712 this.stop(); 37713 } 37714 } 37715 }, this), 37716 'initialized.owl.carousel': $.proxy(function(e) { 37717 if (e.namespace && this._core.settings.autoplay) { 37718 this.play(); 37719 } 37720 }, this), 37721 'play.owl.autoplay': $.proxy(function(e, t, s) { 37722 if (e.namespace) { 37723 this.play(t, s); 37724 } 37725 }, this), 37726 'stop.owl.autoplay': $.proxy(function(e) { 37727 if (e.namespace) { 37728 this.stop(); 37729 } 37730 }, this), 37731 'mouseover.owl.autoplay': $.proxy(function() { 37732 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 37733 this.pause(); 37734 } 37735 }, this), 37736 'mouseleave.owl.autoplay': $.proxy(function() { 37737 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 37738 this.play(); 37739 } 37740 }, this) 37741 }; 37742 37743 // register event handlers 37744 this._core.$element.on(this._handlers); 37745 37746 // set default options 37747 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 37748 }; 37749 37750 /** 37751 * Default options. 37752 * @public 37753 */ 37754 Autoplay.Defaults = { 37755 autoplay: false, 37756 autoplayTimeout: 5000, 37757 autoplayHoverPause: false, 37758 autoplaySpeed: false 37759 }; 37760 37761 /** 37762 * Starts the autoplay. 37763 * @public 37764 * @param {Number} [timeout] - The interval before the next animation starts. 37765 * @param {Number} [speed] - The animation speed for the animations. 37766 */ 37767 Autoplay.prototype.play = function(timeout, speed) { 37768 this._paused = false; 37769 37770 if (this._core.is('rotating')) { 37771 return; 37772 } 37773 37774 this._core.enter('rotating'); 37775 37776 this._interval = window.setInterval($.proxy(function() { 37777 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 37778 return; 37779 } 37780 this._core.next(speed || this._core.settings.autoplaySpeed); 37781 }, this), timeout || this._core.settings.autoplayTimeout); 37782 }; 37783 37784 /** 37785 * Stops the autoplay. 37786 * @public 37787 */ 37788 Autoplay.prototype.stop = function() { 37789 if (!this._core.is('rotating')) { 37790 return; 37791 } 37792 37793 window.clearInterval(this._interval); 37794 this._core.leave('rotating'); 37795 }; 37796 37797 /** 37798 * Stops the autoplay. 37799 * @public 37800 */ 37801 Autoplay.prototype.pause = function() { 37802 if (!this._core.is('rotating')) { 37803 return; 37804 } 37805 37806 this._paused = true; 37807 }; 37808 37809 /** 37810 * Destroys the plugin. 37811 */ 37812 Autoplay.prototype.destroy = function() { 37813 var handler, property; 37814 37815 this.stop(); 37816 37817 for (handler in this._handlers) { 37818 this._core.$element.off(handler, this._handlers[handler]); 37819 } 37820 for (property in Object.getOwnPropertyNames(this)) { 37821 typeof this[property] != 'function' && (this[property] = null); 37822 } 37823 }; 37824 37825 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 37826 37827})(window.Zepto || window.jQuery, window, document); 37828 37829/** 37830 * Navigation Plugin 37831 * @version 2.0.0-beta.3 37832 * @author Artus Kolanowski 37833 * @license The MIT License (MIT) 37834 */ 37835;(function($, window, document, undefined) { 37836 'use strict'; 37837 37838 /** 37839 * Creates the navigation plugin. 37840 * @class The Navigation Plugin 37841 * @param {Owl} carousel - The Owl Carousel. 37842 */ 37843 var Navigation = function(carousel) { 37844 /** 37845 * Reference to the core. 37846 * @protected 37847 * @type {Owl} 37848 */ 37849 this._core = carousel; 37850 37851 /** 37852 * Indicates whether the plugin is initialized or not. 37853 * @protected 37854 * @type {Boolean} 37855 */ 37856 this._initialized = false;
vendor: 14,134 bytes, lines 37857-38385
37857 37858 /** 37859 * The current paging indexes. 37860 * @protected 37861 * @type {Array} 37862 */ 37863 this._pages = []; 37864 37865 /** 37866 * All DOM elements of the user interface. 37867 * @protected 37868 * @type {Object} 37869 */ 37870 this._controls = {}; 37871 37872 /** 37873 * Markup for an indicator. 37874 * @protected 37875 * @type {Array.<String>} 37876 */ 37877 this._templates = []; 37878 37879 /** 37880 * The carousel element. 37881 * @type {jQuery} 37882 */ 37883 this.$element = this._core.$element; 37884 37885 /** 37886 * Overridden methods of the carousel. 37887 * @protected 37888 * @type {Object} 37889 */ 37890 this._overrides = { 37891 next: this._core.next, 37892 prev: this._core.prev, 37893 to: this._core.to 37894 }; 37895 37896 /** 37897 * All event handlers. 37898 * @protected 37899 * @type {Object} 37900 */ 37901 this._handlers = { 37902 'prepared.owl.carousel': $.proxy(function(e) { 37903 if (e.namespace && this._core.settings.dotsData) { 37904 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 37905 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 37906 } 37907 }, this), 37908 'added.owl.carousel': $.proxy(function(e) { 37909 if (e.namespace && this._core.settings.dotsData) { 37910 this._templates.splice(e.position, 0, this._templates.pop()); 37911 } 37912 }, this), 37913 'remove.owl.carousel': $.proxy(function(e) { 37914 if (e.namespace && this._core.settings.dotsData) { 37915 this._templates.splice(e.position, 1); 37916 } 37917 }, this), 37918 'changed.owl.carousel': $.proxy(function(e) { 37919 if (e.namespace && e.property.name == 'position') { 37920 this.draw(); 37921 } 37922 }, this), 37923 'initialized.owl.carousel': $.proxy(function(e) { 37924 if (e.namespace && !this._initialized) { 37925 this._core.trigger('initialize', null, 'navigation'); 37926 this.initialize(); 37927 this.update(); 37928 this.draw(); 37929 this._initialized = true; 37930 this._core.trigger('initialized', null, 'navigation'); 37931 } 37932 }, this), 37933 'refreshed.owl.carousel': $.proxy(function(e) { 37934 if (e.namespace && this._initialized) { 37935 this._core.trigger('refresh', null, 'navigation'); 37936 this.update(); 37937 this.draw(); 37938 this._core.trigger('refreshed', null, 'navigation'); 37939 } 37940 }, this) 37941 }; 37942 37943 // set default options 37944 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 37945 37946 // register event handlers 37947 this.$element.on(this._handlers); 37948 }; 37949 37950 /** 37951 * Default options. 37952 * @public 37953 * @todo Rename `slideBy` to `navBy` 37954 */ 37955 Navigation.Defaults = { 37956 nav: false, 37957 navText: [ 'prev', 'next' ], 37958 navSpeed: false, 37959 navElement: 'button type="button"', 37960 navContainer: false, 37961 navContainerClass: 'owl-nav', 37962 navClass: [ 'owl-prev', 'owl-next' ], 37963 slideBy: 1, 37964 dotClass: 'owl-dot', 37965 dotsClass: 'owl-dots', 37966 dots: true, 37967 dotsEach: false, 37968 dotsData: false, 37969 dotsSpeed: false, 37970 dotsContainer: false 37971 }; 37972 37973 /** 37974 * Initializes the layout of the plugin and extends the carousel. 37975 * @protected 37976 */ 37977 Navigation.prototype.initialize = function() { 37978 var override, 37979 settings = this._core.settings; 37980 37981 // create DOM structure for relative navigation 37982 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 37983 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 37984 37985 this._controls.$previous = $('<' + settings.navElement[0] + '>') 37986 .addClass(settings.navClass[0]) 37987 .html(settings.navText[0]) 37988 .prependTo(this._controls.$relative) 37989 .on('click', $.proxy(function(e) { 37990 this.prev(settings.navSpeed); 37991 }, this)); 37992 this._controls.$next = $('<' + settings.navElement[1] + '>') 37993 .addClass(settings.navClass[1]) 37994 .html(settings.navText[1]) 37995 .appendTo(this._controls.$relative) 37996 .on('click', $.proxy(function(e) { 37997 this.next(settings.navSpeed); 37998 }, this)); 37999 38000 // create DOM structure for absolute navigation 38001 if (!settings.dotsData) { 38002 this._templates = [ $('<button>') 38003 .addClass(settings.dotClass) 38004 .append($('<span>')) 38005 .prop('outerHTML') ]; 38006 } 38007 38008 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 38009 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 38010 38011 this._controls.$absolute.on('click', 'div, button', $.proxy(function(e) { 38012 var index = $(e.target).parent().is(this._controls.$absolute) 38013 ? $(e.target).index() : $(e.target).parent().index(); 38014 38015 e.preventDefault(); 38016 38017 this.to(index, settings.dotsSpeed); 38018 }, this)); 38019 38020 // override public methods of the carousel 38021 for (override in this._overrides) { 38022 this._core[override] = $.proxy(this[override], this); 38023 } 38024 }; 38025 38026 /** 38027 * Destroys the plugin. 38028 * @protected 38029 */ 38030 Navigation.prototype.destroy = function() { 38031 var handler, control, property, override; 38032 38033 for (handler in this._handlers) { 38034 this.$element.off(handler, this._handlers[handler]); 38035 } 38036 for (control in this._controls) { 38037 this._controls[control].remove(); 38038 } 38039 for (override in this.overides) { 38040 this._core[override] = this._overrides[override]; 38041 } 38042 for (property in Object.getOwnPropertyNames(this)) { 38043 typeof this[property] != 'function' && (this[property] = null); 38044 } 38045 }; 38046 38047 /** 38048 * Updates the internal state. 38049 * @protected 38050 */ 38051 Navigation.prototype.update = function() { 38052 var i, j, k, 38053 lower = this._core.clones().length / 2, 38054 upper = lower + this._core.items().length, 38055 maximum = this._core.maximum(true), 38056 settings = this._core.settings, 38057 size = settings.center || settings.autoWidth || settings.dotsData 38058 ? 1 : settings.dotsEach || settings.items; 38059 38060 if (settings.slideBy !== 'page') { 38061 settings.slideBy = Math.min(settings.slideBy, settings.items); 38062 } 38063 38064 if (settings.dots || settings.slideBy == 'page') { 38065 this._pages = []; 38066 38067 for (i = lower, j = 0, k = 0; i < upper; i++) { 38068 if (j >= size || j === 0) { 38069 this._pages.push({ 38070 start: Math.min(maximum, i - lower), 38071 end: i - lower + size - 1 38072 }); 38073 if (Math.min(maximum, i - lower) === maximum) { 38074 break; 38075 } 38076 j = 0, ++k; 38077 } 38078 j += this._core.mergers(this._core.relative(i)); 38079 } 38080 } 38081 }; 38082 38083 /** 38084 * Draws the user interface. 38085 * @todo The option `dotsData` wont work. 38086 * @protected 38087 */ 38088 Navigation.prototype.draw = function() { 38089 var difference, 38090 settings = this._core.settings, 38091 disabled = this._core.items().length <= settings.items, 38092 index = this._core.relative(this._core.current()), 38093 loop = settings.loop || settings.rewind; 38094 38095 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 38096 38097 if (settings.nav) { 38098 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 38099 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 38100 } 38101 38102 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 38103 38104 if (settings.dots) { 38105 difference = this._pages.length - this._controls.$absolute.children().length; 38106 38107 if (settings.dotsData && difference !== 0) { 38108 this._controls.$absolute.html(this._templates.join('')); 38109 } else if (difference > 0) { 38110 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 38111 } else if (difference < 0) { 38112 this._controls.$absolute.children().slice(difference).remove(); 38113 } 38114 38115 this._controls.$absolute.find('.active').removeClass('active'); 38116 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 38117 } 38118 }; 38119 38120 /** 38121 * Extends event data. 38122 * @protected 38123 * @param {Event} event - The event object which gets thrown. 38124 */ 38125 Navigation.prototype.onTrigger = function(event) { 38126 var settings = this._core.settings; 38127 38128 event.page = { 38129 index: $.inArray(this.current(), this._pages), 38130 count: this._pages.length, 38131 size: settings && (settings.center || settings.autoWidth || settings.dotsData 38132 ? 1 : settings.dotsEach || settings.items) 38133 }; 38134 }; 38135 38136 /** 38137 * Gets the current page position of the carousel. 38138 * @protected 38139 * @returns {Number} 38140 */ 38141 Navigation.prototype.current = function() { 38142 var current = this._core.relative(this._core.current()); 38143 return $.grep(this._pages, $.proxy(function(page, index) { 38144 return page.start <= current && page.end >= current; 38145 }, this)).pop(); 38146 }; 38147 38148 /** 38149 * Gets the current succesor/predecessor position. 38150 * @protected 38151 * @returns {Number} 38152 */ 38153 Navigation.prototype.getPosition = function(successor) { 38154 var position, length, 38155 settings = this._core.settings; 38156 38157 if (settings.slideBy == 'page') { 38158 position = $.inArray(this.current(), this._pages); 38159 length = this._pages.length; 38160 successor ? ++position : --position; 38161 position = this._pages[((position % length) + length) % length].start; 38162 } else { 38163 position = this._core.relative(this._core.current()); 38164 length = this._core.items().length; 38165 successor ? position += settings.slideBy : position -= settings.slideBy; 38166 } 38167 38168 return position; 38169 }; 38170 38171 /** 38172 * Slides to the next item or page. 38173 * @public 38174 * @param {Number} [speed=false] - The time in milliseconds for the transition. 38175 */ 38176 Navigation.prototype.next = function(speed) { 38177 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 38178 }; 38179 38180 /** 38181 * Slides to the previous item or page. 38182 * @public 38183 * @param {Number} [speed=false] - The time in milliseconds for the transition. 38184 */ 38185 Navigation.prototype.prev = function(speed) { 38186 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 38187 }; 38188 38189 /** 38190 * Slides to the specified item or page. 38191 * @public 38192 * @param {Number} position - The position of the item or page. 38193 * @param {Number} [speed] - The time in milliseconds for the transition. 38194 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 38195 */ 38196 Navigation.prototype.to = function(position, speed, standard) { 38197 var length; 38198 38199 if (!standard) { 38200 length = this._pages.length; 38201 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 38202 } else { 38203 $.proxy(this._overrides.to, this._core)(position, speed); 38204 } 38205 }; 38206 38207 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 38208 38209})(window.Zepto || window.jQuery, window, document); 38210 38211/** 38212 * Hash Plugin 38213 * @version 2.0.0-beta.3 38214 * @author Artus Kolanowski 38215 * @license The MIT License (MIT) 38216 */ 38217;(function($, window, document, undefined) { 38218 'use strict'; 38219 38220 /** 38221 * Creates the hash plugin. 38222 * @class The Hash Plugin 38223 * @param {Owl} carousel - The Owl Carousel 38224 */ 38225 var Hash = function(carousel) { 38226 /** 38227 * Reference to the core. 38228 * @protected 38229 * @type {Owl} 38230 */ 38231 this._core = carousel; 38232 38233 /** 38234 * Hash index for the items. 38235 * @protected 38236 * @type {Object} 38237 */ 38238 this._hashes = {}; 38239 38240 /** 38241 * The carousel element. 38242 * @type {jQuery} 38243 */ 38244 this.$element = this._core.$element; 38245 38246 /** 38247 * All event handlers. 38248 * @protected 38249 * @type {Object} 38250 */ 38251 this._handlers = { 38252 'initialized.owl.carousel': $.proxy(function(e) { 38253 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 38254 $(window).trigger('hashchange.owl.navigation'); 38255 } 38256 }, this), 38257 'prepared.owl.carousel': $.proxy(function(e) { 38258 if (e.namespace) { 38259 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 38260 38261 if (!hash) { 38262 return; 38263 } 38264 38265 this._hashes[hash] = e.content; 38266 } 38267 }, this), 38268 'changed.owl.carousel': $.proxy(function(e) { 38269 if (e.namespace && e.property.name === 'position') { 38270 var current = this._core.items(this._core.relative(this._core.current())), 38271 hash = $.map(this._hashes, function(item, hash) { 38272 return item === current ? hash : null; 38273 }).join(); 38274 38275 if (!hash || window.location.hash.slice(1) === hash) { 38276 return; 38277 } 38278 38279 window.location.hash = hash; 38280 } 38281 }, this) 38282 }; 38283 38284 // set default options 38285 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 38286 38287 // register the event handlers 38288 this.$element.on(this._handlers); 38289 38290 // register event listener for hash navigation 38291 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 38292 var hash = window.location.hash.substring(1), 38293 items = this._core.$stage.children(), 38294 position = this._hashes[hash] && items.index(this._hashes[hash]); 38295 38296 if (position === undefined || position === this._core.current()) { 38297 return; 38298 } 38299 38300 this._core.to(this._core.relative(position), false, true); 38301 }, this));*/ 38302 }; 38303 38304 /** 38305 * Default options. 38306 * @public 38307 */ 38308 Hash.Defaults = { 38309 URLhashListener: false 38310 }; 38311 38312 /** 38313 * Destroys the plugin. 38314 * @public 38315 */ 38316 Hash.prototype.destroy = function() { 38317 var handler, property; 38318 38319 $(window).off('hashchange.owl.navigation'); 38320 38321 for (handler in this._handlers) { 38322 this._core.$element.off(handler, this._handlers[handler]); 38323 } 38324 for (property in Object.getOwnPropertyNames(this)) { 38325 typeof this[property] != 'function' && (this[property] = null); 38326 } 38327 }; 38328 38329 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 38330 38331})(window.Zepto || window.jQuery, window, document); 38332 38333/** 38334 * Support Plugin 38335 * 38336 * @version 2.0.0-beta.3 38337 * @author Vivid Planet Software GmbH 38338 * @author Artus Kolanowski 38339 * @license The MIT License (MIT) 38340 */ 38341;(function($, window, document, undefined) { 38342 38343 var style = $('<support>').get(0).style, 38344 prefixes = 'Webkit Moz O ms'.split(' '), 38345 events = { 38346 transition: { 38347 end: { 38348 WebkitTransition: 'webkitTransitionEnd', 38349 MozTransition: 'transitionend', 38350 OTransition: 'oTransitionEnd', 38351 transition: 'transitionend' 38352 } 38353 }, 38354 animation: { 38355 end: { 38356 WebkitAnimation: 'webkitAnimationEnd', 38357 MozAnimation: 'animationend', 38358 OAnimation: 'oAnimationEnd', 38359 animation: 'animationend' 38360 } 38361 } 38362 }, 38363 tests = { 38364 csstransforms: function() { 38365 return !!test('transform'); 38366 }, 38367 csstransforms3d: function() { 38368 return !!test('perspective'); 38369 }, 38370 csstransitions: function() { 38371 return !!test('transition'); 38372 }, 38373 cssanimations: function() { 38374 return !!test('animation'); 38375 } 38376 }; 38377 38378 function test(property, prefixed) { 38379 var result = false, 38380 upper = property.charAt(0).toUpperCase() + property.slice(1); 38381 38382 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 38383 if (style[property] !== undefined) { 38384 result = prefixed ? property : true; 38385 return false;
38386 } 38387 }); 38388 38389 return result; 38390 } 38391 38392 function prefixed(property) { 38393 return test(property, true); 38394 } 38395 38396 if (tests.csstransitions()) { 38397 /* jshint -W053 */ 38398 $.support.transition = new String(prefixed('transition')) 38399 $.support.transition.end = events.transition.end[ $.support.transition ]; 38400 } 38401 38402 if (tests.cssanimations()) { 38403 /* jshint -W053 */ 38404 $.support.animation = new String(prefixed('animation')) 38405 $.support.animation.end = events.animation.end[ $.support.animation ]; 38406 } 38407 38408 if (tests.csstransforms()) { 38409 /* jshint -W053 */ 38410 $.support.transform = new String(prefixed('transform')); 38411 $.support.transform3d = tests.csstransforms3d(); 38412 } 38413 38414})(window.Zepto || window.jQuery, window, document); 38415 38416(function(window, document, undefined) { 38417 38418 /** 38419 * Find the absolute position of an element 38420 */ 38421 var absPos = function(element) { 38422 var offsetLeft, offsetTop; 38423 offsetLeft = offsetTop = 0; 38424 if (element.offsetParent) { 38425 do { 38426 offsetLeft += element.offsetLeft; 38427 offsetTop += element.offsetTop; 38428 } while (element = element.offsetParent); 38429 } 38430 return [offsetLeft, offsetTop]; 38431 }; 38432 38433 /** 38434 * @constructor Progress Circle class 38435 * @param params.canvas Canvas on which the circles will be drawn. 38436 * @param params.minRadius Inner radius of the innermost circle, in px. 38437 * @param params.arcWidth Width of each circle(to be more accurate, ring). 38438 * @param params.gapWidth Space between each circle. 38439 * @param params.centerX X coordinate of the center of circles. 38440 * @param params.centerY Y coordinate of the center of circles. 38441 * @param params.infoLineBaseAngle Base angle of the info line. 38442 * @param params.infoLineAngleInterval Angles between the info lines. 38443 */ 38444 var ProgressCircle = function(params) { 38445 this.canvas = params.canvas; 38446 this.minRadius = params.minRadius || 15; 38447 this.arcWidth = params.arcWidth || 5; 38448 this.gapWidth = params.gapWidth || 3; 38449 this.centerX = params.centerX || this.canvas.width / 2; 38450 this.centerY = params.centerY || this.canvas.height / 2;
38451 this.infoLineLength = params.infoLineLength || 60; 38452 this.horizLineLength = params.horizLineLength || 10; 38453 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 38454 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 38455 38456 this.context = this.canvas.getContext('2d'); 38457 38458 this.width = this.canvas.width; 38459 this.height = this.canvas.height; 38460 38461 this.circles = []; 38462 this.runningCount = 0; 38463 }; 38464 38465 ProgressCircle.prototype = { 38466 constructor: ProgressCircle, 38467 38468 /** 38469 * @method Adds an progress monitor entry. 38470 * @param params.fillColor Color to fill in the circle. 38471 * @param params.outlineColor Color to outline the circle. 38472 * @param params.progressListener Callback function to fetch the progress. 38473 * @param params.infoListener Callback function to fetch the info. 38474 * @returns this 38475 */ 38476 addEntry: function(params) { 38477 this.circles.push(new Circle({ 38478 canvas: this.canvas, 38479 context: this.context, 38480 centerX: this.centerX, 38481 centerY: this.centerY, 38482 innerRadius: this.minRadius + this.circles.length * 38483 (this.gapWidth + this.arcWidth), 38484 arcWidth: this.arcWidth,
38485 infoLineLength: this.infoLineLength, 38486 horizLineLength: this.horizLineLength, 38487 38488 id: this.circles.length, 38489 fillColor: params.fillColor, 38490 outlineColor: params.outlineColor, 38491 progressListener: params.progressListener, 38492 infoListener: params.infoListener, 38493 infoLineAngle: this.infoLineBaseAngle + 38494 this.circles.length * this.infoLineAngleInterval, 38495 })); 38496 38497 return this; 38498 }, 38499 38500 /** 38501 * @method Starts the monitor and updates with the given interval. 38502 * @param interval Interval between updates, in millisecond. 38503 * @returns this 38504 */ 38505 start: function(interval) { 38506 var self = this; 38507 this.timer = setInterval(function() { 38508 self._update(); 38509 }, interval || 33); 38510 38511 return this; 38512 }, 38513 38514 /** 38515 * @method Stop the animation. 38516 */ 38517 stop: function() { 38518 clearTimeout(this.timer); 38519 }, 38520 38521 /** 38522 * @private 38523 * @method Call update on each circle and redraw them. 38524 * @returns this 38525 */ 38526 _update: function() { 38527 this._clear(); 38528 this.circles.forEach(function(circle, idx, array) { 38529 circle.update(); 38530 }); 38531 38532 return this; 38533 }, 38534 38535 /** 38536 * @private 38537 * @method Clear the canvas. 38538 * @returns this 38539 */ 38540 _clear: function() { 38541 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 38542 38543 return this; 38544 }, 38545 38546 }; 38547 38548 /** 38549 * @private 38550 * @class Individual progress circle. 38551 * @param params.canvas Canvas on which the circle will be drawn. 38552 * @param params.context Context of the canvas. 38553 * @param params.innerRadius Inner radius of the circle, in px. 38554 * @param params.arcWidth Width of each arc(circle). 38555 * @param params.gapWidth Distance between each arc. 38556 * @param params.centerX X coordinate of the center of circles. 38557 * @param params.centerY Y coordinate of the center of circles. 38558 * @param params.fillColor Color to fill in the circle. 38559 * @param params.outlineColor Color to outline the circle. 38560 * @param params.progressListener Callback function to fetch the progress. 38561 * @param params.infoListener Callback function to fetch the info. 38562 * @param params.infoLineAngle Angle of info line. 38563 */ 38564 var Circle = function(params) { 38565 this.id = params.id; 38566 this.canvas = params.canvas; 38567 this.context = params.context; 38568 this.centerX = params.centerX; 38569 this.centerY = params.centerY; 38570 this.arcWidth = params.arcWidth; 38571 this.innerRadius = params.innerRadius || 0; 38572 this.fillColor = params.fillColor || '#fff'; 38573 this.outlineColor = params.outlineColor || this.fillColor; 38574 this.progressListener = params.progressListener;
38575 this.infoLineLength = params.infoLineLength || 250; 38576 this.horizLineLength = params.horizLineLength || 50; 38577 this.infoListener = params.infoListener; 38578 this.infoLineAngle = params.infoLineAngle; 38579 38580 this.outerRadius = this.innerRadius + this.arcWidth; 38581 38582 // If the info listener is not registered, then don't calculate 38583 // the related coordinates 38584 if (!this.infoListener) return; 38585 38586 // calculate the info-line turning points 38587 var angle = this.infoLineAngle, 38588 arcDistance = (this.innerRadius + this.outerRadius) / 2, 38589 38590 sinA = Math.sin(angle), 38591 cosA = Math.cos(angle); 38592 38593 this.infoLineStartX = this.centerX + sinA * arcDistance; 38594 this.infoLineStartY = this.centerY - cosA * arcDistance; 38595 38596 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 38597 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 38598 38599 this.infoLineEndX = this.infoLineMidX + 38600 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 38601 this.infoLineEndY = this.infoLineMidY; 38602 38603 var infoText = document.createElement('div'), 38604 style = infoText.style; 38605 38606 style.color = this.fillColor; 38607 style.position = 'absolute'; 38608 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 38609 // style.top will be calculated in the `drawInfo` method. Since 38610 // user may want to change the size of the font, so the top offset 38611 // must be updated in each loop. 38612 infoText.className = 'ProgressCircleInfo'; // For css styling 38613 infoText.id = 'progress_circle_info_' + this.id; 38614 document.body.appendChild(infoText); 38615 this.infoText = infoText; 38616 }; 38617 38618 Circle.prototype = { 38619 constructor: Circle, 38620 38621 update: function() { 38622 this.progress = this.progressListener(); 38623 this._draw(); 38624 38625 if (this.infoListener) { 38626 this.info = this.infoListener(); 38627 this._drawInfo(); 38628 } 38629 }, 38630 38631 /** 38632 * @private 38633 * @method Draw the circle on the canvas. 38634 * @returns this 38635 */ 38636 _draw: function() { 38637 var ctx = this.context, 38638 38639 ANGLE_OFFSET = -Math.PI / 2, 38640 38641 startAngle = 0 + ANGLE_OFFSET, 38642 endAngle= startAngle + this.progress * Math.PI * 2, 38643 38644 x = this.centerX, 38645 y = this.centerY, 38646 38647 innerRadius = this.innerRadius - this.arcWidth - 1, 38648 outerRadius = this.outerRadius - this.arcWidth - 1; 38649 38650 if ( innerRadius < 0 ) 38651 return; 38652 38653 ctx.fillStyle = this.fillColor; 38654 ctx.strokeStyle = this.outlineColor; 38655 38656 ctx.beginPath(); 38657 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 38658 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 38659 ctx.closePath(); 38660 ctx.stroke(); 38661 ctx.fill(); 38662 38663 return this; 38664 }, 38665 38666 /** 38667 * @private 38668 * @method Draw the info lines and info text. 38669 * @returns this 38670 */ 38671 _drawInfo: function() { 38672 38673 var pointList, lineHeight; 38674 38675 pointList = [ 38676 [this.infoLineStartX, this.infoLineStartY], 38677 [this.infoLineMidX, this.infoLineMidY], 38678 [this.infoLineEndX, this.infoLineEndY], 38679 ]; 38680 this._drawSegments(pointList, false); 38681 38682 this.infoText.innerHTML = this.info; 38683 38684 lineHeight = this.infoText.offsetHeight; 38685 this.infoText.style.top = this.infoLineEndY + 38686 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 38687 38688 return this; 38689 }, 38690 38691 /** 38692 * @private 38693 * @method Helper function to draw the segments 38694 * @param pointList An array of points in the form of [x, y]. 38695 * @param close Whether to connect the first and last point. 38696 */ 38697 _drawSegments: function(pointList, close) { 38698 var ctx = this.context; 38699 38700 ctx.beginPath(); 38701 ctx.moveTo(pointList[0][0], pointList[0][1]); 38702 for (var i = 1; i < pointList.length; ++i) { 38703 ctx.lineTo(pointList[i][0], pointList[i][1]); 38704 } 38705 38706 if (close) { 38707 ctx.closePath(); 38708 } 38709 ctx.stroke(); 38710 }, 38711 }; 38712 38713 window.ProgressCircle = ProgressCircle; 38714 38715})(window, document); 38716 38717 38718 38719 38720/* ========================================================= 38721 * jquery.vc_chart.js v1.0 38722 * ========================================================= 38723 * Copyright 2013 Wpbakery 38724 * 38725 * Jquery chart plugin for the Visual Composer. 38726 * ========================================================= */ 38727(function($){ 38728 /** 38729 * Pie chart animated. 38730 * @param element - DOM element 38731 * @param options - settings object. 38732 * @constructor 38733 */ 38734 var VcChart = function(element, options) { 38735 this.el = element; 38736 this.$el = $(this.el); 38737 var $this = this; 38738 $this.options = $.extend({ 38739 color: 'wpb_button', 38740 units: '', 38741 width: '', 38742 label_selector: '.vc_pie_chart_value', 38743 back_selector: '.vc_pie_chart_back', 38744 responsive: true 38745 }, options); 38746 $this.init(); 38747 }; 38748 VcChart.prototype = { 38749 constructor: VcChart, 38750 _progress_v: 0, 38751 animated: false, 38752 colors: { 38753 'wpb_button': 'rgba(247, 247, 247, 1)', 38754 'btn-primary': 'rgba(0, 136, 204, 1)', 38755 'btn-info': 'rgba(88, 185, 218, 1)', 38756 'btn-success': 'rgba(106, 177, 101, 1)', 38757 'btn-warning': 'rgba(255, 153, 0, 1)', 38758 'btn-danger': 'rgba(255, 103, 91, 1)', 38759 'btn-inverse': 'rgba(85, 85, 85, 1)' 38760 }, 38761 init: function() { 38762 this.setupColor(); 38763 this.value = this.$el.data('pie-value')/100; 38764 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 38765 this.$wrapper = $('.vc_pie_wrapper', this.$el); 38766 this.$label = $(this.options.label_selector, this.$el); 38767 this.$back = $(this.options.back_selector, this.$el); 38768 this.$canvas = this.$el.find('canvas'); 38769 this.arcWidth = this.$el.data('pie-width') * 2; 38770 this.draw(); 38771 this.setWayPoint(); 38772 if(this.options.responsive === true) this.setResponsive(); 38773 if (UNCODE.isMobile) this._progress_v = this.value; 38774 }, 38775 setupColor: function() { 38776 // if(typeof this.colors[this.options.color] !== 'undefined') { 38777 // this.color = this.colors[this.options.color]; 38778 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 38779 // this.color = this.options.color; 38780 // } else { 38781 // this.color = 'rgba(247, 247, 247, 0.2)'; 38782 // } 38783 if(typeof this.options.color !== 'undefined') { 38784 this.color = this.options.color; 38785 } else this.color = 'rgba(247, 247, 247, 0.2)'; 38786 38787 }, 38788 setResponsive: function() { 38789 var that = this; 38790 if (!UNCODE.isMobile) { 38791 $(window).resize(function(){ 38792 if(that.animated === true) that.circle.stop(); 38793 that.draw(true); 38794 }); 38795 } 38796 }, 38797 draw: function(redraw) { 38798 var w = this.$el.addClass('vc_ready').width() * 2, 38799 border_w = this.arcWidth, 38800 radius; 38801 if(!w) w = this.$el.parents(':visible').first().width()-2; 38802 //w = Math.round(w/100*80); 38803 //if (w < 250) w = 250; 38804 radius = w/2; 38805 this.$wrapper.css({"width" : (w / 2) + "px"}); 38806 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 38807 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 38808 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 38809 this.$el.addClass('vc_ready'); 38810 this.circle = new ProgressCircle({ 38811 canvas: this.$canvas.get(0), 38812 minRadius: radius, 38813 arcWidth: border_w 38814 }); 38815 if(redraw === true && this.animated === true) { 38816 this._progress_v = this.value; 38817 this.circle.addEntry({ 38818 fillColor: this.color, 38819 progressListener: $.proxy(this.setProgress, this) 38820 }).start(); 38821 } 38822 }, 38823 setProgress: function() { 38824 if (this._progress_v >= this.value) { 38825 this.circle.stop(); 38826 this.animated = true; 38827 this.$label.html(this.label_value + this.options.units); 38828 return this._progress_v; 38829 } 38830 this._progress_v += 0.01; 38831 if (!isNaN(this.label_value)) { 38832 var label_value = this._progress_v/this.value*this.label_value; 38833 var val = Math.round(label_value) + this.options.units; 38834 this.$label.html(val); 38835 } else this.$label.html(this.label_value + this.options.units); 38836 return this._progress_v; 38837 }, 38838 animate: function() { 38839 if(this.animated !== true) { 38840 this.circle.addEntry({ 38841 fillColor: this.color, 38842 progressListener: $.proxy(this.setProgress, this) 38843 }).start(10); 38844 } 38845 }, 38846 setWayPoint: function() { 38847 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 38848 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 38849 } else { 38850 this.animate(); 38851 } 38852 } 38853 }; 38854 /** 38855 * jQuery plugin 38856 * @param option - object with settings 38857 * @return {*} 38858 */ 38859 $.fn.vcChat = function(option, value) { 38860 return this.each(function () { 38861 var $this = $(this), 38862 data = $this.data('vc_chart'), 38863 options = typeof option === 'object' ? option : { 38864 color: $this.data('pie-color'), 38865 units: $this.data('pie-units') 38866 }; 38867 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 38868 if (typeof option == 'string') data[option](value); 38869 }); 38870 }; 38871 /** 38872 * Allows users to rewrite function inside theme. 38873 */ 38874 if ( typeof window['vc_pieChart'] !== 'function' ) { 38875 window.vc_pieChart = function() { 38876 $('.vc_pie_chart:visible:not(.vc_ready)').vcChat(); 38877 } 38878 } 38879 $(document).ready(function(){ 38880 !window.vc_iframe && vc_pieChart(); 38881 38882 /** 38883 * Tab and collapse integration. 38884 */ 38885 $('.nav-tabs a').on('shown.bs.tab', function(e){ 38886 var $cont = $(e.target).closest('.tab-container'), 38887 $active = $('.tab-pane.active', $cont); 38888 $('.vc_pie_chart:not(.vc_ready)', $active).vcChat(); 38889 }); 38890 38891 $('.panel-collapse').on('shown.bs.collapse', function (e) { 38892 $('.vc_pie_chart:not(.vc_ready)', e.target).vcChat(); 38893 }) 38894 }); 38895 38896})(window.jQuery); 38897 38898/* Progress bar 38899 ---------------------------------------------------------- */ 38900function uncode_progress_bar() { 38901 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 38902 if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) { 38903 return; 38904 } 38905 if (!UNCODE.isMobile) { 38906 new Waypoint({ 38907 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 38908 element: val, 38909 handler: function() { 38910 var element = jQuery(this.element); 38911 element.find('.vc_single_bar').each(function(index) { 38912 var $this = jQuery(this), 38913 bar = $this.find('.vc_bar'), 38914 val = bar.data('percentage-value'); 38915 setTimeout(function() { 38916 bar.css({ 38917 "width": val + '%' 38918 }); 38919 }, index * 200); 38920 }); 38921 }, 38922 offset: '80%' 38923 }); 38924 } else { 38925 var element = jQuery(val); 38926 element.find('.vc_single_bar').each(function(index) { 38927 var $this = jQuery(this), 38928 bar = $this.find('.vc_bar'), 38929 val = bar.data('percentage-value'); 38930 setTimeout(function() { 38931 bar.css({ 38932 "width": val + '%' 38933 }); 38934 }, index * 200); 38935 }); 38936 } 38937 }); 38938}; 38939uncode_progress_bar(); 38940 38941/*! 38942 * jquery.counterup.js 1.0 38943 * 38944 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 38945 * Released under the GPL v2 License 38946 * 38947 * Date: Nov 26, 2013 38948 */ 38949(function($) { 38950 "use strict"; 38951 $.fn.counterUp = function(options) { 38952 // Defaults 38953 var settings = $.extend({ 38954 'time': 400, 38955 'delay': 10 38956 }, options); 38957 return this.each(function() { 38958 // Store the object 38959 var $this = $(this); 38960 var $settings = settings; 38961 var counterUpper = function() { 38962 var nums = []; 38963 var divisions = $settings.time / $settings.delay; 38964 var numReal = $this.attr('data-val'), 38965 num = numReal; 38966 var isComma = /[0-9]+,[0-9]+/.test(num); 38967 num = num.replace(/,/g, ''); 38968 var isInt = /^[0-9]+$/.test(num); 38969 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 38970 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 38971 // Generate list of incremental numbers to display 38972 for (var i = divisions; i >= 1; i--) { 38973 // Preserve as int if input was int 38974 var newNum = parseInt(num / divisions * i); 38975 // Preserve float if input was float 38976 if (isFloat) { 38977 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 38978 } 38979 // Preserve commas if input had commas 38980 if (isComma) { 38981 while (/(\d+)(\d{3})/.test(newNum.toString())) { 38982 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 38983 } 38984 } 38985 nums.unshift(newNum); 38986 } 38987 nums.push(numReal); 38988 $this.data('counterup-nums', nums); 38989 $this.text('0'); 38990 // Updates the number until we're done 38991 var f = function() { 38992 if ($this.data('counterup-nums') != null) { 38993 $this.text($this.data('counterup-nums').shift()); 38994 if ($this.data('counterup-nums').length) { 38995 setTimeout($this.data('counterup-func'), $settings.delay); 38996 } else { 38997 delete $this.data('counterup-nums'); 38998 $this.data('counterup-nums', null); 38999 $this.data('counterup-func', null); 39000 } 39001 } 39002 }; 39003 $this.data('counterup-func', f); 39004 // Start the count up 39005 setTimeout($this.data('counterup-func'), $settings.delay); 39006 }; 39007 // Perform counts when the element gets into view 39008 new Waypoint({ 39009 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 39010 element: this, 39011 handler: function() { 39012 counterUpper(); 39013 if (!UNCODE.isUnmodalOpen) { 39014 this.destroy(); 39015 } 39016 }, 39017 offset: '100%' 39018 }); 39019 }); 39020 }; 39021})(jQuery); 39022 39023/*! 39024 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/) 39025 * Copyright (c) 2016 Edson Hilios 39026 * 39027 * Permission is hereby granted, free of charge, to any person obtaining a copy of 39028 * this software and associated documentation files (the "Software"), to deal in 39029 * the Software without restriction, including without limitation the rights to 39030 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 39031 * the Software, and to permit persons to whom the Software is furnished to do so, 39032 * subject to the following conditions: 39033 * 39034 * The above copyright notice and this permission notice shall be included in all 39035 * copies or substantial portions of the Software. 39036 * 39037 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39038 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 39039 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 39040 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 39041 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 39042 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 39043 */ 39044(function(factory) { 39045 "use strict"; 39046 if (typeof define === "function" && define.amd) { 39047 define([ "jquery" ], factory); 39048 } else { 39049 factory(jQuery); 39050 } 39051})(function($) { 39052 "use strict"; 39053 var instances = [], matchers = [], defaultOptions = { 39054 precision: 100, 39055 elapse: false, 39056 defer: false 39057 }; 39058 matchers.push(/^[0-9]*$/.source); 39059 matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 39060 matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 39061 matchers = new RegExp(matchers.join("|")); 39062 function parseDateString(dateString) { 39063 if (dateString instanceof Date) { 39064 return dateString; 39065 } 39066 if (String(dateString).match(matchers)) { 39067 if (String(dateString).match(/^[0-9]*$/)) { 39068 dateString = Number(dateString); 39069 } 39070 if (String(dateString).match(/\-/)) { 39071 dateString = String(dateString).replace(/\-/g, "/"); 39072 } 39073 return new Date(dateString); 39074 } else { 39075 throw new Error("Couldn't cast `" + dateString + "` to a date object."); 39076 } 39077 } 39078 var DIRECTIVE_KEY_MAP = { 39079 Y: "years", 39080 m: "months", 39081 n: "daysToMonth", 39082 d: "daysToWeek", 39083 w: "weeks", 39084 W: "weeksToMonth", 39085 H: "hours", 39086 M: "minutes", 39087 S: "seconds", 39088 D: "totalDays", 39089 I: "totalHours", 39090 N: "totalMinutes", 39091 T: "totalSeconds" 39092 }; 39093 function escapedRegExp(str) { 39094 var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); 39095 return new RegExp(sanitize); 39096 } 39097 function strftime(offsetObject) { 39098 return function(format) { 39099 var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi); 39100 if (directives) { 39101 for (var i = 0, len = directives.length; i < len; ++i) { 39102 var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null; 39103 directive = directive[2]; 39104 if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) { 39105 value = DIRECTIVE_KEY_MAP[directive]; 39106 value = Number(offsetObject[value]); 39107 } 39108 if (value !== null) { 39109 if (modifier === "!") { 39110 value = pluralize(plural, value); 39111 } 39112 if (modifier === "") { 39113 if (value < 10) { 39114 value = "0" + value.toString(); 39115 } 39116 } 39117 format = format.replace(regexp, value.toString()); 39118 } 39119 } 39120 } 39121 format = format.replace(/%%/, "%"); 39122 return format; 39123 }; 39124 } 39125 function pluralize(format, count) { 39126 var plural = "s", singular = ""; 39127 if (format) { 39128 format = format.rep
vendor: 8,618 bytes, lines 39128-39272
39128lace(/(:|;|\s)/gi, "").split(/\,/); 39129 if (format.length === 1) { 39130 plural = format[0]; 39131 } else { 39132 singular = format[0]; 39133 plural = format[1]; 39134 } 39135 } 39136 if (Math.abs(count) > 1) { 39137 return plural; 39138 } else { 39139 return singular; 39140 } 39141 } 39142 var Countdown = function(el, finalDate, options) { 39143 this.el = el; 39144 this.$el = $(el); 39145 this.interval = null; 39146 this.offset = {}; 39147 this.options = $.extend({}, defaultOptions); 39148 this.instanceNumber = instances.length; 39149 instances.push(this); 39150 this.$el.data("countdown-instance", this.instanceNumber); 39151 if (options) { 39152 if (typeof options === "function") { 39153 this.$el.on("update.countdown", options); 39154 this.$el.on("stoped.countdown", options); 39155 this.$el.on("finish.countdown", options); 39156 } else { 39157 this.options = $.extend({}, defaultOptions, options); 39158 } 39159 } 39160 this.setFinalDate(finalDate); 39161 if (this.options.defer === false) { 39162 this.start(); 39163 } 39164 }; 39165 $.extend(Countdown.prototype, { 39166 start: function() { 39167 if (this.interval !== null) { 39168 clearInterval(this.interval); 39169 } 39170 var self = this; 39171 this.update(); 39172 this.interval = setInterval(function() { 39173 self.update.call(self); 39174 }, this.options.precision); 39175 }, 39176 stop: function() { 39177 clearInterval(this.interval); 39178 this.interval = null; 39179 this.dispatchEvent("stoped"); 39180 }, 39181 toggle: function() { 39182 if (this.interval) { 39183 this.stop(); 39184 } else { 39185 this.start(); 39186 } 39187 }, 39188 pause: function() { 39189 this.stop(); 39190 }, 39191 resume: function() { 39192 this.start(); 39193 }, 39194 remove: function() { 39195 this.stop.call(this); 39196 instances[this.instanceNumber] = null; 39197 delete this.$el.data().countdownInstance; 39198 }, 39199 setFinalDate: function(value) { 39200 this.finalDate = parseDateString(value); 39201 }, 39202 update: function() { 39203 if (this.$el.closest("html").length === 0) { 39204 this.remove(); 39205 return; 39206 } 39207 var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft; 39208 newTotalSecsLeft = this.finalDate.getTime() - now.getTime(); 39209 newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3); 39210 newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft); 39211 if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) { 39212 return; 39213 } else { 39214 this.totalSecsLeft = newTotalSecsLeft; 39215 } 39216 this.elapsed = now >= this.finalDate; 39217 this.offset = { 39218 seconds: this.totalSecsLeft % 60, 39219 minutes: Math.floor(this.totalSecsLeft / 60) % 60, 39220 hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24, 39221 days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 39222 daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 39223 daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368), 39224 weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7), 39225 weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4, 39226 months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368), 39227 years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()), 39228 totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24), 39229 totalHours: Math.floor(this.totalSecsLeft / 60 / 60), 39230 totalMinutes: Math.floor(this.totalSecsLeft / 60), 39231 totalSeconds: this.totalSecsLeft 39232 }; 39233 if (!this.options.elapse && this.totalSecsLeft === 0) { 39234 this.stop(); 39235 this.dispatchEvent("finish"); 39236 } else { 39237 this.dispatchEvent("update"); 39238 } 39239 }, 39240 dispatchEvent: function(eventName) { 39241 var event = $.Event(eventName + ".countdown"); 39242 event.finalDate = this.finalDate; 39243 event.elapsed = this.elapsed; 39244 event.offset = $.extend({}, this.offset); 39245 event.strftime = strftime(this.offset); 39246 this.$el.trigger(event); 39247 } 39248 }); 39249 $.fn.countdown = function() { 39250 var argumentsArray = Array.prototype.slice.call(arguments, 0); 39251 return this.each(function() { 39252 var instanceNumber = $(this).data("countdown-instance"); 39253 if (instanceNumber !== undefined) { 39254 var instance = instances[instanceNumber], method = argumentsArray[0]; 39255 if (Countdown.prototype.hasOwnProperty(method)) { 39256 instance[method].apply(instance, argumentsArray.slice(1)); 39257 } else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) { 39258 instance.setFinalDate.call(instance, method); 39259 instance.start(); 39260 } else { 39261 $.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method)); 39262 } 39263 } else { 39264 new Countdown(this, argumentsArray[0], argumentsArray[1]); 39265 } 39266 }); 39267 }; 39268}); 39269 39270!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; 39271function getStyles(config){ 39272 // 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;
39272left: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+"}" 39273}; 39274 var ShareUtils; 39275 39276if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 39277 Object.defineProperty(HTMLElement.prototype, "classList", { 39278 get: function() { 39279 var ret, self, update; 39280 update = function(fn) { 39281 return function(value) { 39282 var classes, index; 39283 classes = self.className.split(/\s+/); 39284 index = classes.indexOf(value); 39285 fn(classes, index, value); 39286 self.className = classes.join(" "); 39287 }; 39288 }; 39289 self = this; 39290 ret = { 39291 add: update(function(classes, index, value) { 39292 ~index || classes.push(value); 39293 }), 39294 remove: update(function(classes, index) { 39295 ~index && classes.splice(index, 1); 39296 }), 39297 toggle: update(function(classes, index, value) { 39298 if (~index) { 39299 classes.splice(index, 1); 39300 } else { 39301 classes.push(value); 39302 } 39303 }), 39304 contains: function(value) { 39305 return !!~self.className.split(/\s+/).indexOf(value); 39306 }, 39307 item: function(i) { 39308 return self.className.split(/\s+/)[i] || null; 39309 } 39310 }; 39311 Object.defineProperty(ret, "length", { 39312 get: function() { 39313 return self.className.split(/\s+/).length; 39314 } 39315 }); 39316 return ret; 39317 } 39318 }); 39319} 39320 39321String.prototype.to_rfc3986 = function() { 39322 var tmp; 39323 tmp = encodeURIComponent(this); 39324 return tmp.replace(/[!'()*]/g, function(c) { 39325 return "%" + c.charCodeAt(0).toString(16); 39326 }); 39327}; 39328 39329ShareUtils = (function() { 39330 function ShareUtils() {} 39331 39332 ShareUtils.prototype.extend = function(to, from, overwrite) { 39333 var hasProp, prop; 39334 for (prop in from) { 39335 hasProp = to[prop] !== undefined; 39336 if (hasProp && typeof from[prop] === "object") { 39337 this.extend(to[prop], from[prop], overwrite); 39338 } else { 39339 if (overwrite || !hasProp) { 39340 to[prop] = from[prop]; 39341 } 39342 } 39343 } 39344 }; 39345 39346 ShareUtils.prototype.hide = function(el) { 39347 return el.style.display = "none"; 39348 }; 39349 39350 ShareUtils.prototype.show = function(el) { 39351 return el.style.display = "block"; 39352 }; 39353 39354 ShareUtils.prototype.has_class = function(el, class_name) { 39355 return el.classList.contains(class_name); 39356 }; 39357 39358 ShareUtils.prototype.add_class = function(el, class_name) { 39359 return el.classList.add(class_name); 39360 }; 39361 39362 ShareUtils.prototype.remove_class = function(el, class_name) { 39363 return el.classList.remove(class_name); 39364 }; 39365 39366 ShareUtils.prototype.is_encoded = function(str) { 39367 str = str.to_rfc3986(); 39368 return decodeURIComponent(str) !== str; 39369 }; 39370 39371 ShareUtils.prototype.encode = function(str) { 39372 if (typeof str === "undefined" || this.is_encoded(str)) { 39373 return str; 39374 } else { 39375 return str.to_rfc3986(); 39376 } 39377 }; 39378 39379 ShareUtils.prototype.popup = function(url, params) { 39380 var k, popup, qs, v; 39381 if (params == null) { 39382 params = {}; 39383 } 39384 popup = { 39385 width: 500, 39386 height: 350 39387 }; 39388 popup.top = (screen.height / 2) - (popup.height / 2); 39389 popup.left = (screen.width / 2) - (popup.width / 2); 39390 qs = ((function() { 39391 var _results; 39392 _results = []; 39393 for (k in params) { 39394 v = params[k]; 39395 _results.push("" + k + "=" + (this.encode(v))); 39396 } 39397 return _results; 39398 }).call(this)).join('&'); 39399 if (qs) { 39400 qs = "?" + qs; 39401 } 39402 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="
39402+ popup.width + ",height=" + popup.height); 39403 }; 39404 39405 return ShareUtils; 39406 39407})(); 39408var Share, 39409 __hasProp = {}.hasOwnProperty, 39410 __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; }; 39411 39412Share = (function(_super) { 39413 __extends(Share, _super); 39414 39415 function Share(element, options) { 39416 this.element = element; 39417 this.el = { 39418 head: document.getElementsByTagName('head')[0], 39419 body: document.getElementsByTagName('body')[0] 39420 }; 39421 this.config = { 39422 enabled_networks: 0, 39423 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 39424 url: window.location.href.replace("&", "%26"), 39425 caption: null, 39426 title: this.default_title(), 39427 image: this.default_image(), 39428 description: this.default_description(), 39429 ui: { 39430 flyout: 'top center', 39431 button_text: 'Share', 39432 button_font: true, 39433 icon_font: true 39434 }, 39435 networks: { 39436 twitter: { 39437 enabled: true, 39438 url: null, 39439 title: null, 39440 description: null 39441 }, 39442 facebook: { 39443 enabled: true, 39444 load_sdk: true, 39445 url: null, 39446 app_id: null, 39447 title: null, 39448 caption: null, 39449 description: null, 39450 image: null 39451 }, 39452 threads: { 39453 enabled: true, 39454 url: null, 39455 title: null, 39456 description: null 39457 }, 39458 bluesky: { 39459 enabled: true, 39460 url: null, 39461 title: null, 39462 description: null 39463 }, 39464 pinterest: { 39465 enabled: true, 39466 url: null, 39467 image: null, 39468 description: null 39469 }, 39470 reddit: { 39471 enabled: true, 39472 url: null, 39473 title: null 39474 }, 39475 linkedin: { 39476 enabled: true, 39477 url: null, 39478 title: null, 39479 description: null 39480 }, 39481 xing: { 39482 enabled: true, 39483 url: null, 39484 title: null, 39485 image: null, 39486 description: null 39487 }, 39488 whatsapp: { 39489 enabled: true, 39490 title: null, 39491 url: null 39492 }, 39493 email: { 39494 enabled: true, 39495 title: null, 39496 description: null, 39497 url: null 39498 } 39499 } 39500 }; 39501 this.setup(element, options); 39502 return this; 39503 } 39504 39505 Share.prototype.setup = function(element, opts) { 39506 var index, instance, instances, _i, _len; 39507 instances = document.querySelectorAll(element); 39508 this.extend(this.config, opts, true); 39509 this.set_global_configuration(); 39510 this.normalize_network_configuration(); 39511 if (this.config.ui.icon_font) { 39512 this.inject_icons(); 39513 } 39514 if (this.config.ui.button_font) { 39515 this.inject_fonts(); 39516 } 39517 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 39518 this.inject_facebook_sdk(); 39519 } 39520 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 39521 instance = instances[index]; 39522 this.setup_instance(element, index); 39523 } 39524 }; 39525 39526 Share.prototype.setup_instance = function(element, index) { 39527 var button, instance, label, network, networks, _i, _len, _results, 39528 _this = this; 39529 instance = document.querySelectorAll(element)[index]; 39530 this.hide(instance); 39531 this.add_class(instance, "sharer-" + index); 39532 instance = document.querySelectorAll(element)[index]; 39533 this.inject_css(instance); 39534 this.inject_html(instance); 39535 this.show(instance); 39536 label = instance.getElementsByTagName("label")[0]; 39537 button = instance.getElementsByClassName("social")[0]; 39538 networks = instance.getElementsByTagName('li'); 39539 this.add_class(button, "networks-" + this.config.enabled_networks); 39540 label.addEventListener("click", function() { 39541 return _this.event_toggle(button); 39542 }); 39543 _this = this; 39544 _results = []; 39545 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 39546 network = networks[index]; 39547 _results.push(network.addEventListener("click", function() { 39548 _this.event_network(instance, this); 39549 return _this.event_close(button); 39550 })); 39551 } 39552 return _results; 39553 }; 39554 39555 Share.prototype.event_toggle = function(button) { 39556 if (this.has_class(button, "active")) { 39557 return this.event_close(button); 39558 } else { 39559 return this.event_open(button); 39560 } 39561 }; 39562 39563 Share.prototype.event_open = function(button) { 39564 if (this.has_class(button, "load")) { 39565 this.remove_class(button, "load"); 39566 } 39567 return this.add_class(button, "active"); 39568 }; 39569 39570 Share.prototype.event_close = function(button) { 39571 return this.remove_class(button, "active"); 39572 }; 39573 39574 Share.prototype.event_network = function(instance, network) { 39575 var name; 39576 name = network.getAttribute("data-network"); 39577 this.hook("before", name, instance);
39578 this["network_" + name](); 39579 return this.hook("after", name, instance); 39580 }; 39581 39582 Share.prototype.open = function() { 39583 return this["public"]("open"); 39584 }; 39585 39586 Share.prototype.close = function() { 39587 return this["public"]("close"); 39588 }; 39589 39590 Share.prototype.toggle = function() { 39591 return this["public"]("toggle"); 39592 }; 39593 39594 Share.prototype["public"] = function(action) { 39595 var button, index, instance, _i, _len, _ref, _results; 39596 _ref = document.querySelectorAll(this.element); 39597 _results = []; 39598 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 39599 instance = _ref[index]; 39600 button = instance.getElementsByClassName("social")[0]; 39601 _results.push(this["event_" + action](button)); 39602 } 39603 return _results; 39604 }; 39605 39606 Share.prototype.network_facebook = function() { 39607 if (this.config.networks.facebook.load_sdk) { 39608 if (!window.FB) { 39609 return console.error("The Facebook JS SDK hasn't loaded yet."); 39610 } 39611 return FB.ui({ 39612 method: 'feed', 39613 name: this.config.networks.facebook.title, 39614 link: this.config.networks.facebook.url, 39615 picture: this.config.networks.facebook.image, 39616 caption: this.config.networks.facebook.caption, 39617 description: this.config.networks.facebook.description 39618 }); 39619 } else { 39620 return this.popup('https://www.facebook.com/sharer/sharer.php', { 39621 u: this.config.networks.facebook.url 39622 }); 39623 } 39624 }; 39625 39626 Share.prototype.network_threads = function() { 39627 return this.popup('https://threads.net/intent/post', { 39628 text: this.config.networks.threads.title, 39629 url: this.config.networks.threads.url 39630 }); 39631 }; 39632 39633 Share.prototype.network_bluesky = function() { 39634 return this.popup('https://bsky.app/intent/compose', { 39635 text: this.config.networks.bluesky.title + ' ' + this.config.networks.bluesky.url 39636 }); 39637 }; 39638 39639 Share.prototype.network_twitter = function() { 39640 return this.popup('https://twitter.com/intent/tweet', { 39641 text: this.config.networks.twitter.title, 39642 url: this.config.networks.twitter.url 39643 }); 39644 }; 39645 39646 Share.prototype.network_pinterest = function() { 39647 return this.popup('https://www.pinterest.com/pin/create/button', { 39648 url: this.config.networks.pinterest.url, 39649 media: this.config.networks.pinterest.image, 39650 description: this.config.networks.pinterest.description 39651 }); 39652 }; 39653 39654 Share.prototype.network_linkedin = function() { 39655 return this.popup('https://www.linkedin.com/shareArticle', { 39656 url: this.config.networks.linkedin.url, 39657 title: this.config.networks.linkedin.title, 39658 summary: this.config.networks.linkedin.description 39659 }); 39660 } 39661 39662 Share.prototype.network_xing = function() { 39663 return this.popup('https://www.xing.com/spi/shares/new', { 39664 url: this.config.networks.xing.url, 39665 image: this.config.networks.xing.image, 39666 title: this.config.networks.xing.title, 39667 summary: this.config.networks.xing.description 39668 }); 39669 } 39670 39671 Share.prototype.network_whatsapp = function() { 39672 return this.popup('https://api.whatsapp.com/send', { 39673 text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url, 39674 }); 39675 } 39676 39677 Share.prototype.network_email = function() { 39678 return this.popup('mailto:', { 39679 subject: this.config.networks.email.title, 39680 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 39681 }); 39682 }; 39683 39684 Share.prototype.inject_icons = function() { 39685 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 39686 }; 39687 39688 Share.prototype.inject_fonts = function() { 39689 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 39690 }; 39691 39692 Share.prototype.inject_stylesheet = function(url) { 39693 var link; 39694 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 39695 link = document.createElement("link"); 39696 link.setAttribute("rel", "stylesheet"); 39697 link.setAttribute("href", url); 39698 return this.el.head.appendChild(link); 39699 } 39700 }; 39701 39702 Share.prototype.inject_css = function(instance) { 39703 var css, meta, selector, style; 39704 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 39705 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 39706 this.config.selector = selector; 39707 css = getStyles(this.config); 39708 style = document.createElement("style"); 39709 style.type = "text/css"; 39710 if (style.styleSheet) { 39711 style.styleSheet.cssText = css; 39712 } else { 39713 style.appendChild(document.createTextNode(css)); 39714 } 39715 this.el.head.appendChild(style); 39716 delete this.config.selector; 39717 meta = document.createElement("meta"); 39718 meta.setAttribute("name", "sharer" + selector); 39719 return this.el.head.appendChild(meta); 39720 } 39721 }; 39722 39723 Share.prototype.inject_html = function(instance) { 39724 // 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>"; 39725 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-threads' data-network='threads' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-whatsapp' data-network='whatsapp' tabindex='0'></li><li class='social-bluesky' data-network='bluesky' 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>"; 39726 }; 39727 39728 Share.prototype.inject_facebook_sdk = function() { 39729 var fb_root, script; 39730 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 39731 script = document.createElement("script"); 39732 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')"; 39733 fb_root = document.createElement("div"); 39734 fb_root.id = "fb-root"; 39735 this.el.body.appendChild(fb_root); 39736 return this.el.body.appendChild(script); 39737 } 39738 }; 39739 39740 Share.prototype.hook = function(type, network, instance) { 39741 var fn, opts; 39742 fn = this.config.networks[network][type]; 39743 if (typeof fn === "function") { 39744 opts = fn.call(this.config.networks[network], instance); 39745 if (opts !== void 0) { 39746 opts = this.normalize_filter_config_updates(opts); 39747 this.extend(this.config.networks[network], opts, true); 39748 this.normalize_network_configuration(); 39749 } 39750 } 39751 }; 39752 39753 Share.prototype.default_title = function() { 39754 var content; 39755 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 39756 return encodeURIComponent(content.getAttribute('content')); 39757 } else if (content = document.querySelector('title')) { 39758 return encodeURIComponent(content.innerText); 39759 } 39760 }; 39761 39762 Share.prototype.default_image = function() { 39763 var content; 39764 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 39765 return content.getAttribute('content'); 39766 } 39767 }; 39768 39769 Share.prototype.default_description = function() { 39770 var content; 39771 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 39772 return encodeURIComponent(content.getAttribute('content')); 39773 } else { 39774 return ''; 39775 } 39776 }; 39777 39778 Share.prototype.set_global_configuration = function() { 39779 var display, network, option, options, _ref, _results; 39780 _ref = this.config.networks; 39781 _results = []; 39782 for (network in _ref) { 39783 options = _ref[network]; 39784 for (option in options) { 39785 if (this.config.networks[network][option] == null) { 39786 this.config.networks[network][option] = this.config[option]; 39787 } 39788 } 39789 if (this.config.networks[network].enabled) { 39790 display = 'block'; 39791 this.config.enabled_networks += 1; 39792 } else { 39793 display = 'none'; 39794 } 39795 _results.push(this.config.networks[network].display = display); 39796 } 39797 return _results; 39798 }; 39799 39800 Share.prototype.normalize_network_configuration = function() { 39801 if (!this.config.networks.facebook.app_id) { 39802 this.config.networks.facebook.load_sdk = false;
39803 } 39804 if (!this.is_encoded(this.config.networks.twitter.description)) { 39805 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 39806 } 39807 if (typeof this.config.networks.facebook.app_id === 'number') { 39808 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 39809 } 39810 }; 39811 39812 Share.prototype.normalize_filter_config_updates = function(opts) { 39813 if (this.config.networks.facebook.app_id !== opts.app_id) { 39814 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."); 39815 delete opts.app_id; 39816 } 39817 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 39818 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."); 39819 delete opts.app_id; 39820 } 39821 return opts; 39822 }; 39823 39824 return Share; 39825 39826})(ShareUtils); 39827 return Share; 39828}); 39829 39830// Generated by CoffeeScript 1.9.2 39831 39832// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 39833 39834(function() { 39835 var $, win; 39836 39837 $ = this.jQuery || window.jQuery; 39838 39839 win = $(window); 39840 39841 $.fn.stick_in_parent = function(opts) { 39842 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 39843 if (opts == null) { 39844 opts = {}; 39845 } 39846 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; 39847 if (offset_top == null) { 39848 offset_top = 0; 39849 } 39850 if (parent_selector == null) { 39851 parent_selector = void 0; 39852 } 39853 if (inner_scrolling == null) { 39854 inner_scrolling = true; 39855 } 39856 if (sticky_class == null) { 39857 sticky_class = "is_stuck"; 39858 } 39859 doc = $(document); 39860 if (enable_bottoming == null) { 39861 enable_bottoming = true; 39862 } 39863 outer_width = function(el) { 39864 var _el, computed, w; 39865 if (window.getComputedStyle) { 39866 _el = el[0]; 39867 computed = window.getComputedStyle(el[0]); 39868 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 39869 if (computed.getPropertyValue("box-sizing") !== "border-box") { 39870 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 39871 } 39872 return w; 39873 } else { 39874 return el.outerWidth(true); 39875 } 39876 }; 39877 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 39878 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 39879 if (elm.data("sticky_kit")) { 39880 return; 39881 } 39882 elm.data("sticky_kit", true); 39883 last_scroll_height = doc.height(); 39884 parent = elm.parent(); 39885 if (parent_selector != null) { 39886 parent = parent.closest(parent_selector); 39887 } 39888 if (!parent.length) { 39889 throw "failed to find stick parent"; 39890 } 39891 fixed = false; 39892 bottomed = false; 39893 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 39894 if (spacer) { 39895 spacer.css('position', elm.css('position')); 39896 } 39897 recalc = function() { 39898 var border_top, padding_top, restore; 39899 if (detached) { 39900 return; 39901 } 39902 last_scroll_height = doc.height(); 39903 border_top = parseInt(parent.css("border-top-width"), 10); 39904 padding_top = parseInt(parent.css("padding-top"), 10); 39905 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 39906 parent_top = parent.offset().top + border_top + padding_top; 39907 parent_height = parent.height(); 39908 if (fixed) { 39909 fixed = false;
vendor: 6,068 bytes, lines 39910-40104
39910 bottomed = false; 39911 if (manual_spacer == null) { 39912 elm.insertAfter(spacer); 39913 spacer.detach(); 39914 } 39915 elm.css({ 39916 position: "", 39917 top: "", 39918 width: "", 39919 bottom: "" 39920 }).removeClass(sticky_class); 39921 restore = true; 39922 } 39923 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 39924 height = elm.outerHeight(true); 39925 el_float = elm.css("float"); 39926 if (spacer) { 39927 spacer.css({ 39928 width: outer_width(elm), 39929 height: height, 39930 display: elm.css("display"), 39931 "vertical-align": elm.css("vertical-align"), 39932 "float": el_float 39933 }); 39934 } 39935 if (restore) { 39936 return tick(); 39937 } 39938 }; 39939 recalc(); 39940 if (height === parent_height) { 39941 return; 39942 } 39943 last_pos = void 0; 39944 offset = offset_top; 39945 recalc_counter = recalc_every; 39946 tick = function() { 39947 var css, delta, recalced, scroll, will_bottom, win_height; 39948 if (detached) { 39949 return; 39950 } 39951 recalced = false; 39952 if (recalc_counter != null) { 39953 recalc_counter -= 1; 39954 if (recalc_counter <= 0) { 39955 recalc_counter = recalc_every; 39956 recalc(); 39957 recalced = true; 39958 } 39959 } 39960 if (!recalced && doc.height() !== last_scroll_height) { 39961 recalc(); 39962 recalced = true; 39963 } 39964 scroll = win.scrollTop(); 39965 if (last_pos != null) { 39966 delta = scroll - last_pos; 39967 } 39968 last_pos = scroll; 39969 if (fixed) { 39970 if (enable_bottoming) { 39971 will_bottom = scroll + height + offset > parent_height + parent_top; 39972 if (bottomed && !will_bottom) { 39973 bottomed = false; 39974 elm.css({ 39975 position: "fixed", 39976 bottom: "", 39977 top: offset 39978 }).trigger("sticky_kit:unbottom"); 39979 } 39980 } 39981 if (scroll < top) { 39982 fixed = false; 39983 offset = offset_top; 39984 if (manual_spacer == null) { 39985 if (el_float === "left" || el_float === "right") { 39986 elm.insertAfter(spacer); 39987 } 39988 spacer.detach(); 39989 } 39990 css = { 39991 position: "", 39992 width: "", 39993 top: "" 39994 }; 39995 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 39996 } 39997 if (inner_scrolling) { 39998 win_height = win.height(); 39999 if (height + offset_top > win_height) { 40000 if (!bottomed) { 40001 offset -= delta; 40002 offset = Math.max(win_height - height, offset); 40003 offset = Math.min(offset_top, offset); 40004 if (fixed) { 40005 elm.css({ 40006 top: offset + "px" 40007 }); 40008 } 40009 } 40010 } 40011 } 40012 } else { 40013 if (scroll > top) { 40014 fixed = true; 40015 css = { 40016 position: "fixed", 40017 top: offset 40018 }; 40019 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 40020 elm.css(css).addClass(sticky_class); 40021 if (manual_spacer == null) { 40022 elm.after(spacer); 40023 if (el_float === "left" || el_float === "right") { 40024 spacer.append(elm); 40025 } 40026 } 40027 elm.trigger("sticky_kit:stick"); 40028 } 40029 } 40030 if (fixed && enable_bottoming) { 40031 if (will_bottom == null) { 40032 will_bottom = scroll + height + offset > parent_height + parent_top; 40033 } 40034 if (!bottomed && will_bottom) { 40035 bottomed = true; 40036 if (parent.css("position") === "static") { 40037 parent.css({ 40038 position: "relative" 40039 }); 40040 } 40041 return elm.css({ 40042 position: "absolute", 40043 bottom: padding_bottom, 40044 top: "auto" 40045 }).trigger("sticky_kit:bottom"); 40046 } 40047 } 40048 }; 40049 recalc_and_tick = function() { 40050 recalc(); 40051 return tick(); 40052 }; 40053 detach = function() { 40054 detached = true; 40055 win.off("touchmove", tick); 40056 win.off("scroll", tick); 40057 win.off("resize", recalc_and_tick); 40058 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 40059 elm.off("sticky_kit:detach", detach); 40060 elm.removeData("sticky_kit"); 40061 elm.css({ 40062 position: "", 40063 bottom: "", 40064 top: "", 40065 width: "" 40066 }); 40067 parent.position("position", ""); 40068 if (fixed) { 40069 if (manual_spacer == null) { 40070 if (el_float === "left" || el_float === "right") { 40071 elm.insertAfter(spacer); 40072 } 40073 spacer.remove(); 40074 } 40075 return elm.removeClass(sticky_class); 40076 } 40077 }; 40078 win.on("touchmove", tick); 40079 win.on("scroll", tick); 40080 win.on("resize", recalc_and_tick); 40081 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 40082 elm.on("sticky_kit:detach", detach); 40083 return setTimeout(tick, 0); 40084 }; 40085 for (i = 0, len = this.length; i < len; i++) { 40086 elm = this[i]; 40087 fn($(elm)); 40088 } 40089 return this; 40090 }; 40091 40092}).call(this); 40093/* ========================================================================== 40094 * bootstrap-tab-history.js 40095 * Author: Michael Narayan <[email protected]> 40096 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 40097 * ========================================================================== 40098 * Licensed under the Apache License, Version 2.0 (the "License"); you may 40099 * not use this file except in compliance with the License. You may obtain a 40100 * copy of the License at 40101 * 40102 * http://www.apache.org/licenses/LICENSE-2.0 40103 * 40104 * Unless required by applicable law or agreed to in writing, softw
40104are 40105 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 40106 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 40107 * License for the specific language governing permissions and limitations 40108 * under the License. 40109 * ========================================================================== */ 40110 40111/* ========================================================================== */ 40112/* JSHint directives */ 40113/* */ 40114/* global BootstrapTabHistory: true */ 40115/* */ 40116/* global document */ 40117/* global jQuery */ 40118/* global history */ 40119/* global window */ 40120/* ========================================================================== */ 40121 40122/** 40123 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 40124 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 40125 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 40126 * 40127 * See the README for additional information. 40128 * 40129 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 40130 */ 40131 40132BootstrapTabHistory = { 40133 options: { 40134 /** 40135 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 40136 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 40137 * 40138 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 40139 * 40140 * @public 40141 * @type {?number} 40142 */ 40143 defaultAnchorYOffset: 0, 40144 /** 40145 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 40146 * 40147 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 40148 * 40149 * @public 40150 * @type {string} 40151 */ 40152 defaultChanger: 'replace', 40153 /** 40154 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 40155 * `null` is passed as the third parameter to these calls. 40156 * 40157 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 40158 * 40159 * @public 40160 * @type {boolean} 40161 */ 40162 defaultUpdateURL: false, 40163 /** 40164 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 40165 * load. 40166 * 40167 * @public 40168 * @type {boolean} 40169 */ 40170 showTabsBasedOnAnchor: true 40171 } 40172}; 40173 40174(function () { 40175 'use strict'; 40176 40177 jQuery(function () { 40178 if(history && history.pushState && history.replaceState) { 40179 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 40180 40181 if(bootstrapTabHistory) { 40182 showTabsBasedOnState(bootstrapTabHistory); 40183 } else { 40184 showTabsBasedOnAnchor(); 40185 } 40186 40187 backfillHistoryState(); 40188 40189 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 40190 jQuery(window).on('popstate', onPopState); 40191 } else { 40192 showTabsBasedOnAnchor(); 40193 } 40194 }); 40195 40196 /** 40197 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 40198 * 40199 * @type {boolean} 40200 */ 40201 var showingTabsBasedOnState = false; 40202 40203 /** 40204 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 40205 * `history.back` handling when `data-tab-history-update-url` is true. 40206 */ 40207 function backfillHistoryState() { 40208 var newState = null; 40209 40210 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 40211 var $activeTabElement = jQuery(this); 40212 var selector = getTabSelector($activeTabElement); 40213 40214 if(selector) { 40215 var tabGroup = getTabGroup($activeTabElement); 40216 40217 if(tabGroup) { 40218 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 40219 } 40220 } 40221 }); 40222 40223 if(newState) { 40224 history.replaceState(newState, '', null); 40225 } 40226 } 40227 40228 /** 40229 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 40230 * said bootstrapTabHistory attribute. 40231 * 40232 * @param {?object} existingState 40233 * @param {!string} tabGroup 40234 * @param {!string} selector 40235 * @returns {!object} 40236 */ 40237 function createNewHistoryState(existingState, tabGroup, selector) { 40238 // Clone history.state and ensure it has a bootstrapTabHistory entry. 40239 var newState = jQuery.extend(true, {}, existingState, { 40240 bootstrapTabHistory: {} 40241 }); 40242 40243 newState.bootstrapTabHistory[tabGroup] = selector; 40244 40245 return newState; 40246 } 40247 40248 /** 40249 * @param {jQuery} $tab
40250 * @returns {?string} 40251 */ 40252 function getTabGroup($tab) { 40253 return parseTruthyAttributeValue($tab.data('tab-history')); 40254 } 40255 40256 /** 40257 * @param {jQuery} $tab 40258 * @returns {?string} 40259 */ 40260 function getTabSelector($tab) { 40261 return $tab.data('target') || $tab.attr('href'); 40262 } 40263 40264 /** 40265 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 40266 * 40267 * @param {jQuery.Event} shownEvt 40268 */ 40269 function onShownTab(shownEvt) { 40270 if(!showingTabsBasedOnState) { 40271 var $activatedTab = jQuery(shownEvt.target); 40272 if ( $activatedTab.hasClass('panel-collapse') ) 40273 $activatedTab = $activatedTab.closest('.panel').find('a'); 40274 var selector = getTabSelector($activatedTab); 40275 40276 if(selector) { 40277 var tabGroup = getTabGroup($activatedTab); 40278 40279 if(tabGroup) { 40280 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 40281 var newState = createNewHistoryState(history.state, tabGroup, selector); 40282 var updateURL = (function ($activatedTab) { 40283 if(selector[0] === '#') { 40284 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 40285 40286 if(elementUpdateURLOption === undefined) { 40287 return BootstrapTabHistory.options.defaultUpdateURL; 40288 } else { 40289 return elementUpdateURLOption; 40290 } 40291 } else { 40292 return false; 40293 } 40294 })($activatedTab); 40295 40296 switch(historyChanger) { 40297 case 'push': 40298 history.pushState(newState, '', updateURL ? selector : null); 40299 break; 40300 case 'replace': 40301 history.replaceState(newState, '', updateURL ? selector : null); 40302 break; 40303 default: 40304 throw new Error('Unknown tab-history-changer: ' + historyChanger); 40305 } 40306 } 40307 } 40308 } 40309 } 40310 40311 /** 40312 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 40313 */ 40314 function onPopState() { 40315 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 40316 40317 if(bootstrapTabHistory) { 40318 showTabsBasedOnState(bootstrapTabHistory); 40319 } 40320 } 40321 40322 /** 40323 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 40324 * 40325 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 40326 * 40327 * @param {*} value 40328 * @returns {*} 40329 */ 40330 function parseTruthyAttributeValue(value) { 40331 if(value) { 40332 return value; 40333 } else if(value === '') { 40334 return true; 40335 } else { 40336 return value; 40337 } 40338 } 40339 40340 /** 40341 * Show tabs based upon the anchor component of `window.location`. 40342 */ 40343 function showTabsBasedOnAnchor() { 40344 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 40345 var anchor = window.location && window.location.hash; 40346 40347 if(anchor) { 40348 var $tabElement = showTabForSelector(anchor); 40349 40350 if($tabElement && window.addEventListener && window.removeEventListener) { 40351 var anchorYOffset = (function ($tabElement) { 40352 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 40353 40354 if(elementSetting === undefined) { 40355 return BootstrapTabHistory.options.defaultAnchorYOffset; 40356 } else { 40357 return elementSetting; 40358 } 40359 })($tabElement); 40360 40361 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 40362 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 40363 // `history.state` object should have been used (unless the browser did not support the modern History API). 40364 if(anchorYOffset || anchorYOffset === 0) { 40365 var scrollListener = function resetAnchorScroll () { 40366 window.removeEventListener('scroll', scrollListener); 40367 window.scrollTo(0, anchorYOffset); 40368 }; 40369 40370 window.addEventListener('scroll', scrollListener); 40371 } 40372 } 40373 } 40374 } 40375 } 40376 40377 /** 40378 * Show a tab which corresponds to the provided selector. 40379 * 40380 * @param {string} selector - A CSS selector. 40381 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 40382 */ 40383 function showTabForSelector(selector) { 40384 var $tabElement = (function (selector) { 40385 var $ret = null; 40386 40387 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 40388 var $potentialTab = jQuery(this); 40389 40390 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 40391 $ret = $potentialTab; 40392 return false;
vendor: 43,483 bytes, lines 40393-41609
40393 } else { 40394 return null; 40395 } 40396 }); 40397 40398 return $ret; 40399 })(selector); 40400 40401 if($tabElement) { 40402 if ( !$tabElement.parent().hasClass('active') ) { 40403 $tabElement.trigger('click'); 40404 } 40405 //$tabElement.tab('show'); 40406 } 40407 40408 return $tabElement; 40409 } 40410 40411 /** 40412 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 40413 * 40414 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 40415 */ 40416 function showTabsBasedOnState(bootstrapTabHistory) { 40417 showingTabsBasedOnState = true; 40418 40419 try { 40420 for(var k in bootstrapTabHistory) { 40421 if(bootstrapTabHistory.hasOwnProperty(k)) { 40422 showTabForSelector(bootstrapTabHistory[k]); 40423 } 40424 } 40425 } finally { 40426 showingTabsBasedOnState = false; 40427 } 40428 } 40429})(); 40430 40431/*! 40432 * justifiedGallery - v3.8.1 40433 * http://miromannino.github.io/Justified-Gallery/ 40434 * Copyright (c) 2020 Miro Mannino 40435 * Licensed under the MIT license. 40436 */ 40437(function (factory) { 40438 if (typeof define === 'function' && define.amd) { 40439 // AMD. Register as an anonymous module. 40440 define(['jquery'], factory); 40441 } else if (typeof module === 'object' && module.exports) { 40442 // Node/CommonJS 40443 module.exports = function (root, jQuery) { 40444 if (jQuery === undefined) { 40445 // require('jQuery') returns a factory that requires window to 40446 // build a jQuery instance, we normalize how we use modules 40447 // that require this pattern but the window provided is a noop 40448 // if it's defined (how jquery works) 40449 if (typeof window !== 'undefined') { 40450 jQuery = require('jquery'); 40451 } 40452 else { 40453 jQuery = require('jquery')(root); 40454 } 40455 } 40456 factory(jQuery); 40457 return jQuery; 40458 }; 40459 } else { 40460 // Browser globals 40461 factory(jQuery); 40462 } 40463}(function ($) { 40464 40465 /** 40466 * Justified Gallery controller constructor 40467 * 40468 * @param $gallery the gallery to build 40469 * @param settings the settings (the defaults are in JustifiedGallery.defaults) 40470 * @constructor 40471 */ 40472 var JustifiedGallery = function ($gallery, settings) { 40473 40474 this.settings = settings; 40475 this.checkSettings(); 40476 40477 this.imgAnalyzerTimeout = null; 40478 this.entries = null; 40479 this.buildingRow = { 40480 entriesBuff: [], 40481 width: 0, 40482 height: 0, 40483 aspectRatio: 0 40484 }; 40485 this.lastFetchedEntry = null; 40486 this.lastAnalyzedIndex = -1; 40487 this.yield = { 40488 every: 2, // do a flush every n flushes (must be greater than 1) 40489 flushed: 0 // flushed rows without a yield 40490 }; 40491 this.border = settings.border >= 0 ? settings.border : settings.margins; 40492 this.maxRowHeight = this.retrieveMaxRowHeight(); 40493 this.suffixRanges = this.retrieveSuffixRanges(); 40494 this.offY = this.border; 40495 this.rows = 0; 40496 this.spinner = { 40497 phase: 0, 40498 timeSlot: 150, 40499 $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'), 40500 intervalId: null 40501 }; 40502 this.scrollBarOn = false; 40503 this.checkWidthIntervalId = null; 40504 this.galleryWidth = $gallery.width(); 40505 this.$gallery = $gallery; 40506 40507 }; 40508 40509 /** @returns {String} the best suffix given the width and the height */ 40510 JustifiedGallery.prototype.getSuffix = function (width, height) { 40511 var longestSide, i; 40512 longestSide = (width > height) ? width : height; 40513 for (i = 0; i < this.suffixRanges.length; i++) { 40514 if (longestSide <= this.suffixRanges[i]) { 40515 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 40516 } 40517 } 40518 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 40519 }; 40520 40521 /** 40522 * Remove the suffix from the string 40523 * 40524 * @returns {string} a new string without the suffix 40525 */ 40526 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 40527 return str.substring(0, str.length - suffix.length); 40528 }; 40529 40530 /** 40531 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 40532 */ 40533 JustifiedGallery.prototype.endsWith = function (str, suffix) { 40534 return str.indexOf(suffix, str.length - suffix.length) !== -1; 40535 }; 40536 40537 /** 40538 * Get the used suffix of a particular url 40539 * 40540 * @param str 40541 * @returns {String} return the used suffix 40542 */ 40543 JustifiedGallery.prototype.getUsedSuffix = function (str) { 40544 for (var si in this.settings.sizeRangeSuffixes) { 40545 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 40546 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 40547 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 40548 } 40549 } 40550 return ''; 40551 }; 40552 40553 /** 40554 * Given an image src, with the width and the height, returns the new image src with the 40555 * best suffix to show the best quality thumbnail. 40556 * 40557 * @returns {String} the suffix to use 40558 */ 40559 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 40560 var newImageSrc; 40561 40562 if (this.settings.thumbnailPath) { 40563 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 40564 } else { 40565 var matchRes = imageSrc.match(this.settings.extension); 40566 var ext = (matchRes !== null) ? matchRes[0] : ''; 40567 newImageSrc = imageSrc.replace(this.settings.extension, ''); 40568 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc)); 40569 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 40570 } 40571 40572 return newImageSrc; 40573 }; 40574 40575 /** 40576 * Shows the images that is in the given entry 40577 * 40578 * @param $entry the entry 40579 * @param callback the callback that is called when the show animation is finished 40580 */ 40581 JustifiedGallery.prototype.showImg = function ($entry, callback) { 40582 if (this.settings.cssAnimation) { 40583 $entry.addClass('jg-entry-visible'); 40584 if (callback) callback(); 40585 } else { 40586 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 40587 $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 40588 } 40589 }; 40590 40591 /** 40592 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 40593 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 40594 * 40595 * @param $image the image to analyze 40596 * @returns {String} the extracted src 40597 */ 40598 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 40599 var imageSrc = $image.data('safe-src'); 40600 var imageSrcLoc = 'data-safe-src'; 40601 // Begin Uncode edit 40602 if (typeof imageSrc === 'undefined') { 40603 var imageCurrentSrc = $image[0].currentSrc; 40604 if (imageCurrentSrc) { 40605 imageSrc = imageCurrentSrc; 40606 } else { 40607 imageSrc = $image.attr('src'); 40608 } 40609 imageSrcLoc = 'src'; 40610 } 40611 // End Uncode edit 40612 $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method 40613 $image.data('jg.src', imageSrc); // this will change overtime 40614 $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method 40615 return imageSrc; 40616 }; 40617 40618 /** @returns {jQuery} the image in the given entry */ 40619 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 40620 var $img = $entry.find(this.settings.imgSelector); 40621 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 40622 return $img.length === 0 ? null : $img; 40623 }; 40624 40625 /** @returns {jQuery} the caption in the given entry */ 40626 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 40627 var $caption = $entry.find('> .jg-caption'); 40628 return $caption.length === 0 ? null : $caption; 40629 }; 40630 40631 /** 40632 * Display the entry 40633 * 40634 * @param {jQuery} $entry the entry to display 40635 * @param {int} x the x position where the entry must be positioned 40636 * @param y the y position where the entry must be positioned 40637 * @param imgWidth the image width 40638 * @param imgHeight the image height 40639 * @param rowHeight the row height of the row that owns the entry 40640 */ 40641 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 40642 $entry.width(imgWidth); 40643 $entry.height(Math.floor(rowHeight));//hacked by Uncode 40644 $entry.css('top', Math.floor(y));//hacked by Uncode 40645 $entry.css('left', x); 40646 40647 var $image = this.imgFromEntry($entry); 40648 if ($image !== null) { 40649 $image.css('width', imgWidth); 40650 $image.css('height', imgHeight); 40651 $image.css('margin-left', - imgWidth / 2); 40652 $image.css('margin-top', - imgHeight / 2); 40653 40654 // Image reloading for an high quality of thumbnails 40655 var imageSrc = $image.data('jg.src'); 40656 if (imageSrc) { 40657 imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 40658 40659 $image.one('error', function () { 40660 this.resetImgSrc($image); //revert to the original thumbnail 40661 }); 40662 40663 var loadNewImage = function () { 40664 // if (imageSrc !== newImageSrc) { 40665 $image.attr('src', imageSrc); 40666 // } 40667 }; 40668 40669 if ($entry.data('jg.loaded') === 'skipped' && imageSrc) { 40670 this.onImageEvent(imageSrc, (function() { 40671 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 40672 $entry.data('jg.loaded', true); 40673 }).bind(this)); 40674 } else { 40675 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 40676 } 40677 40678 } 40679 40680 } else { 40681 this.showImg($entry); 40682 } 40683 40684 this.displayEntryCaption($entry); 40685 }; 40686 40687 /** 40688 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 40689 * or the 'title' attributes. 40690 * 40691 * @param {jQuery} $entry the entry to process 40692 */ 40693 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 40694 var $image = this.imgFromEntry($entry); 40695 if ($image !== null && this.settings.captions) { 40696 var $imgCaption = this.captionFromEntry($entry); 40697 40698 // Create it if it doesn't exists 40699 if ($imgCaption === null) { 40700 var caption = $image.attr('alt'); 40701 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 40702 if (this.isValidCaption(caption)) { // Create only we found something 40703 $imgCaption = $('<div class="jg-caption">' + caption + '</div>'); 40704 $entry.append($imgCaption); 40705 $entry.data('jg.createdCaption', true); 40706 } 40707 } 40708 40709 // Create events (we check again the $imgCaption because it can be still inexistent) 40710 if ($imgCaption !== null) { 40711 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 40712 this.addCaptionEventsHandlers($entry); 40713 } 40714 } else { 40715 this.removeCaptionEventsHandlers($entry); 40716 } 40717 }; 40718 40719 /** 40720 * Validates the caption 40721 * 40722 * @param caption The caption that should be validated 40723 * @return {boolean} Validation result 40724 */ 40725 JustifiedGallery.prototype.isValidCaption = function (caption) { 40726 return (typeof caption !== 'undefined' && caption.length > 0); 40727 }; 40728 40729 /** 40730 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 40731 * It shows the caption using jQuery (or using CSS if it is configured so) 40732 * 40733 * @param {Event} eventObject the event object 40734 */ 40735 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 40736 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 40737 if (this.settings.cssAnimation) { 40738 $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden'); 40739 } else { 40740 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 40741 this.settings.captionSettings.visibleOpacity); 40742 } 40743 }; 40744 40745 /** 40746 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 40747 * It hides the caption using jQuery (or using CSS if it is configured so) 40748 * 40749 * @param {Event} eventObject the event object 40750 */ 40751 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 40752 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 40753 if (this.settings.cssAnimation) { 40754 $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden'); 40755 } else { 40756 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 40757 this.settings.captionSettings.nonVisibleOpacity); 40758 } 40759 }; 40760 40761 /** 40762 * Add the handlers of the entry for the caption 40763 * 40764 * @param $entry the entry to modify 40765 */ 40766 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 40767 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 40768 if (typeof captionMouseEvents === 'undefined') { 40769 captionMouseEvents = { 40770 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 40771 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 40772 }; 40773 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 40774 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 40775 $entry.data('jg.captionMouseEvents', captionMouseEvents); 40776 } 40777 }; 40778 40779 /** 40780 * Remove the handlers of the entry for the caption 40781 * 40782 * @param $entry the entry to modify 40783 */ 40784 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 40785 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 40786 if (typeof captionMouseEvents !== 'undefined') { 40787 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 40788 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 40789 $entry.removeData('jg.captionMouseEvents'); 40790 } 40791 }; 40792 40793 /** 40794 * Clear the building row data to be used for a new row 40795 */ 40796 JustifiedGallery.prototype.clearBuildingRow = function () { 40797 this.buildingRow.entriesBuff = []; 40798 this.buildingRow.aspectRatio = 0; 40799 this.buildingRow.width = 0; 40800 }; 40801 40802 /** 40803 * Justify the building row, preparing it to 40804 * 40805 * @param isLastRow 40806 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 40807 * @returns a boolean to know if the row has been justified or not 40808 */ 40809 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) { 40810 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 40811 var minHeight = 0; 40812 var availableWidth = this.galleryWidth - 2 * this.border - ( 40813 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 40814 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 40815 var defaultRowHeight = this.settings.rowHeight; 40816 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 40817 40818 //Skip the last row if we can't justify it and the lastRow == 'hide' 40819 if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) { 40820 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 40821 $entry = this.buildingRow.entriesBuff[i]; 40822 if (this.settings.cssAnimation) 40823 $entry.removeClass('jg-entry-visible'); 40824 else { 40825 $entry.stop().fadeTo(0, 0.1); 40826 $entry.find('> img, > a > img').fadeTo(0, 0); 40827 } 40828 } 40829 return -1; 40830 } 40831 40832 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 40833 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 40834 justify = false; 40835 40836 if (this.rows > 0) { 40837 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 40838 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 40839 } 40840 } 40841 40842 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 40843 $entry = this.buildingRow.entriesBuff[i]; 40844 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 40845 40846 if (justify) { 40847 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 40848 newImgH = rowHeight; 40849 } else { 40850 newImgW = defaultRowHeight * imgAspectRatio; 40851 newImgH = defaultRowHeight; 40852 } 40853 40854 availableWidth -= Math.round(newImgW); 40855 $entry.data('jg.jwidth', Math.round(newImgW)); 40856 $entry.data('jg.jheight', Math.ceil(newImgH)); 40857 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 40858 } 40859 40860 this.buildingRow.height = minHeight; 40861 return justify; 40862 }; 40863 40864 /** 40865 * Flush a row: justify it, modify the gallery height accordingly to the row height 40866 * 40867 * @param isLastRow 40868 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 40869 */ 40870 JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) { 40871 var settings = this.settings; 40872 var $entry, buildingRowRes, offX = this.border, i; 40873 40874 buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow); 40875 if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) { 40876 this.clearBuildingRow(); 40877 return; 40878 } 40879 40880 if (this.maxRowHeight) { 40881 if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight; 40882 } 40883 40884 //Align last (unjustified) row 40885 if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) { 40886 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 40887 40888 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 40889 $entry = this.buildingRow.entriesBuff[i]; 40890 availableWidth -= $entry.data('jg.jwidth'); 40891 } 40892 40893 if (settings.lastRow === 'center') 40894 offX += Math.round(availableWidth / 2); 40895 else if (settings.lastRow === 'right') 40896 offX += availableWidth; 40897 } 40898 40899 var lastEntryIdx = this.buildingRow.entriesBuff.length - 1; 40900 for (i = 0; i <= lastEntryIdx; i++) { 40901 $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i]; 40902 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 40903 offX += $entry.data('jg.jwidth') + settings.margins; 40904 } 40905 40906 //Gallery Height 40907 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 40908 this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight()); 40909 40910 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 40911 //Ready for a new row 40912 this.offY += this.buildingRow.height + settings.margins; 40913 this.rows += 1; 40914 this.clearBuildingRow(); 40915 this.settings.triggerEvent.call(this, 'jg.rowflush'); 40916 } 40917 }; 40918 40919 40920 // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221 40921 var galleryPrevStaticHeight = 0; 40922 40923 JustifiedGallery.prototype.rememberGalleryHeight = function () { 40924 galleryPrevStaticHeight = this.$gallery.height(); 40925 this.$gallery.height(galleryPrevStaticHeight); 40926 }; 40927 40928 // grow only 40929 JustifiedGallery.prototype.setGalleryTempHeight = function (height) { 40930 galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight); 40931 this.$gallery.height(galleryPrevStaticHeight); 40932 }; 40933 40934 JustifiedGallery.prototype.setGalleryFinalHeight = function (height) { 40935 galleryPrevStaticHeight = height; 40936 this.$gallery.height(height); 40937 }; 40938 40939 /** 40940 * Checks the width of the gallery container, to know if a new justification is needed 40941 */ 40942 JustifiedGallery.prototype.checkWidth = function () { 40943 this.checkWidthIntervalId = setInterval($.proxy(function () { 40944 40945 // if the gallery is not currently visible, abort. 40946 if (!this.$gallery.is(":visible")) return; 40947 40948 var galleryWidth = parseFloat(this.$gallery.width()); 40949 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 40950 this.galleryWidth = galleryWidth; 40951 this.rewind(); 40952 40953 this.rememberGalleryHeight(); 40954 40955 // Restart to analyze 40956 this.startImgAnalyzer(true); 40957 } 40958 }, this), this.settings.refreshTime); 40959 }; 40960 40961 /** 40962 * @returns {boolean} a boolean saying if the spinner is active or not 40963 */ 40964 JustifiedGallery.prototype.isSpinnerActive = function () { 40965 return this.spinner.intervalId !== null; 40966 }; 40967 40968 /** 40969 * @returns {int} the spinner height 40970 */ 40971 JustifiedGallery.prototype.getSpinnerHeight = function () { 40972 return this.spinner.$el.innerHeight(); 40973 }; 40974 40975 /** 40976 * Stops the spinner animation and modify the gallery height to exclude the spinner 40977 */ 40978 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 40979 clearInterval(this.spinner.intervalId); 40980 this.spinner.intervalId = null; 40981 this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight()); 40982 this.spinner.$el.detach(); 40983 }; 40984 40985 /** 40986 * Starts the spinner animation 40987 */ 40988 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 40989 var spinnerContext = this.spinner; 40990 var $spinnerPoints = spinnerContext.$el.find('span'); 40991 clearInterval(spinnerContext.intervalId); 40992 this.$gallery.append(spinnerContext.$el); 40993 this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 40994 spinnerContext.intervalId = setInterval(function () { 40995 if (spinnerContext.phase < $spinnerPoints.length) { 40996 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 40997 } else { 40998 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 40999 } 41000 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 41001 }, spinnerContext.timeSlot); 41002 }; 41003 41004 /** 41005 * Rewind the image analysis to start from the first entry. 41006 */ 41007 JustifiedGallery.prototype.rewind = function () { 41008 this.lastFetchedEntry = null; 41009 this.lastAnalyzedIndex = -1; 41010 this.offY = this.border; 41011 this.rows = 0; 41012 this.clearBuildingRow(); 41013 }; 41014 41015 /** 41016 * @returns {String} `settings.selector` rejecting spinner element 41017 */ 41018 JustifiedGallery.prototype.getSelectorWithoutSpinner = function () { 41019 return this.settings.selector + ', div:not(.jg-spinner)'; 41020 }; 41021 41022 /** 41023 * @returns {Array} all entries matched by `settings.selector` 41024 */ 41025 JustifiedGallery.prototype.getAllEntries = function () { 41026 var selector = this.getSelectorWithoutSpinner(); 41027 return this.$gallery.children(selector).toArray(); 41028 }; 41029 41030 /** 41031 * Update the entries searching it from the justified gallery HTML element 41032 * 41033 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 41034 * @returns {boolean} true if some entries has been founded 41035 */ 41036 JustifiedGallery.prototype.updateEntries = function (norewind) { 41037 var newEntries; 41038 41039 if (norewind && this.lastFetchedEntry != null) { 41040 var selector = this.getSelectorWithoutSpinner(); 41041 newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray(); 41042 } else { 41043 this.entries = []; 41044 newEntries = this.getAllEntries(); 41045 } 41046 41047 if (newEntries.length > 0) { 41048 41049 // Sort or randomize 41050 if ($.isFunction(this.settings.sort)) { 41051 newEntries = this.sortArray(newEntries); 41052 } else if (this.settings.randomize) { 41053 newEntries = this.shuffleArray(newEntries); 41054 } 41055 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 41056 41057 // Filter 41058 if (this.settings.filter) { 41059 newEntries = this.filterArray(newEntries); 41060 } else { 41061 this.resetFilters(newEntries); 41062 } 41063 41064 } 41065 41066 this.entries = this.entries.concat(newEntries); 41067 return true; 41068 }; 41069 41070 /** 41071 * Apply the entries order to the DOM, iterating the entries and appending the images 41072 * 41073 * @param entries the entries that has been modified and that must be re-ordered in the DOM 41074 */ 41075 JustifiedGallery.prototype.insertToGallery = function (entries) { 41076 var that = this; 41077 $.each(entries, function () { 41078 $(this).appendTo(that.$gallery); 41079 }); 41080 }; 41081 41082 /** 41083 * Shuffle the array using the Fisher-Yates shuffle algorithm 41084 * 41085 * @param a the array to shuffle 41086 * @return the shuffled array 41087 */ 41088 JustifiedGallery.prototype.shuffleArray = function (a) { 41089 var i, j, temp; 41090 for (i = a.length - 1; i > 0; i--) { 41091 j = Math.floor(Math.random() * (i + 1)); 41092 temp = a[i]; 41093 a[i] = a[j]; 41094 a[j] = temp; 41095 } 41096 this.insertToGallery(a); 41097 return a; 41098 }; 41099 41100 /** 41101 * Sort the array using settings.comparator as comparator 41102 * 41103 * @param a the array to sort (it is sorted) 41104 * @return the sorted array 41105 */ 41106 JustifiedGallery.prototype.sortArray = function (a) { 41107 a.sort(this.settings.sort); 41108 this.insertToGallery(a); 41109 return a; 41110 }; 41111 41112 /** 41113 * Reset the filters removing the 'jg-filtered' class from all the entries 41114 * 41115 * @param a the array to reset 41116 */ 41117 JustifiedGallery.prototype.resetFilters = function (a) { 41118 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 41119 }; 41120 41121 /** 41122 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 41123 * 41124 * @param a the array to filter 41125 * @return the filtered array 41126 */ 41127 JustifiedGallery.prototype.filterArray = function (a) { 41128 var settings = this.settings; 41129 if ($.type(settings.filter) === 'string') { 41130 // Filter only keeping the entries passed in the string 41131 return a.filter(function (el) { 41132 var $el = $(el); 41133 if ($el.is(settings.filter)) { 41134 $el.removeClass('jg-filtered'); 41135 return true; 41136 } else { 41137 $el.addClass('jg-filtered').removeClass('jg-visible'); 41138 return false; 41139 } 41140 }); 41141 } else if ($.isFunction(settings.filter)) { 41142 // Filter using the passed function 41143 var filteredArr = a.filter(settings.filter); 41144 for (var i = 0; i < a.length; i++) { 41145 if (filteredArr.indexOf(a[i]) === -1) { 41146 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 41147 } else { 41148 $(a[i]).removeClass('jg-filtered'); 41149 } 41150 } 41151 return filteredArr; 41152 } 41153 }; 41154 41155 /** 41156 * Revert the image src to the default value. 41157 */ 41158 JustifiedGallery.prototype.resetImgSrc = function ($img) { 41159 if ($img.data('jg.originalSrcLoc') === 'src') { 41160 $img.attr('src', $img.data('jg.originalSrc')); 41161 } else { 41162 $img.attr('src', ''); 41163 } 41164 }; 41165 41166 /** 41167 * Destroy the Justified Gallery instance. 41168 * 41169 * It clears all the css properties added in the style attributes. We doesn't backup the original 41170 * values for those css attributes, because it costs (performance) and because in general one 41171 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 41172 * classes). Creating a backup is also difficult because JG could be called multiple times and 41173 * with different style attributes. 41174 */ 41175 JustifiedGallery.prototype.destroy = function () { 41176 clearInterval(this.checkWidthIntervalId); 41177 this.stopImgAnalyzerStarter(); 41178 41179 // Get fresh entries list since filtered entries are absent in `this.entries` 41180 $.each(this.getAllEntries(), $.proxy(function (_, entry) { 41181 var $entry = $(entry); 41182 41183 // Reset entry style 41184 $entry.css('width', ''); 41185 $entry.css('height', ''); 41186 $entry.css('top', ''); 41187 $entry.css('left', ''); 41188 $entry.data('jg.loaded', undefined); 41189 $entry.removeClass('jg-entry jg-filtered jg-entry-visible'); 41190 41191 // Reset image style 41192 var $img = this.imgFromEntry($entry); 41193 if ($img) { 41194 $img.css('width', ''); 41195 $img.css('height', ''); 41196 $img.css('margin-left', ''); 41197 $img.css('margin-top', ''); 41198 this.resetImgSrc($img); 41199 $img.data('jg.originalSrc', undefined); 41200 $img.data('jg.originalSrcLoc', undefined); 41201 $img.data('jg.src', undefined); 41202 } 41203 41204 // Remove caption 41205 this.removeCaptionEventsHandlers($entry); 41206 var $caption = this.captionFromEntry($entry); 41207 if ($entry.data('jg.createdCaption')) { 41208 // remove also the caption element (if created by jg) 41209 $entry.data('jg.createdCaption', undefined); 41210 if ($caption !== null) $caption.remove(); 41211 } else { 41212 if ($caption !== null) $caption.fadeTo(0, 1); 41213 } 41214 41215 }, this)); 41216 41217 this.$gallery.css('height', ''); 41218 this.$gallery.removeClass('justified-gallery'); 41219 this.$gallery.data('jg.controller', undefined); 41220 this.settings.triggerEvent.call(this, 'jg.destroy'); 41221 }; 41222 41223 /** 41224 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 41225 * 41226 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 41227 */ 41228 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 41229 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 41230 var $entry = $(this.entries[i]); 41231 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 41232 var availableWidth = this.galleryWidth - 2 * this.border - ( 41233 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 41234 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 41235 41236 this.buildingRow.entriesBuff.push($entry); 41237 this.buildingRow.aspectRatio += imgAspectRatio; 41238 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 41239 this.lastAnalyzedIndex = i; 41240 41241 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 41242 this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 41243 41244 if (++this.yield.flushed >= this.yield.every) { 41245 this.startImgAnalyzer(isForResize); 41246 return; 41247 } 41248 } 41249 } else if ($entry.data('jg.loaded') !== 'error') { 41250 return; 41251 } 41252 } 41253 41254 // Last row flush (the row is not full) 41255 if (this.buildingRow.entriesBuff.length > 0) { 41256 this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 41257 } 41258 41259 if (this.isSpinnerActive()) { 41260 this.stopLoadingSpinnerAnimation(); 41261 } 41262 41263 /* Stop, if there is, the timeout to start the analyzeImages. 41264 This is because an image can be set loaded, and the timeout can be set, 41265 but this image can be analyzed yet. 41266 */ 41267 this.stopImgAnalyzerStarter(); 41268 41269 this.setGalleryFinalHeight(this.galleryHeightToSet); 41270 41271 //On complete callback 41272 this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete'); 41273 }; 41274 41275 /** 41276 * Stops any ImgAnalyzer starter (that has an assigned timeout) 41277 */ 41278 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 41279 this.yield.flushed = 0; 41280 if (this.imgAnalyzerTimeout !== null) { 41281 clearTimeout(this.imgAnalyzerTimeout); 41282 this.imgAnalyzerTimeout = null; 41283 } 41284 }; 41285 41286 /** 41287 * Starts the image analyzer. It is not immediately called to let the browser to update the view 41288 * 41289 * @param isForResize specifies if the image analyzer must be called for resizing or not 41290 */ 41291 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 41292 var that = this; 41293 this.stopImgAnalyzerStarter(); 41294 this.imgAnalyzerTimeout = setTimeout(function () { 41295 that.analyzeImages(isForResize); 41296 }, 0.001); // we can't start it immediately due to a IE different behaviour 41297 }; 41298 41299 /** 41300 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 41301 * because some browsers, with a 404 set complete = true. 41302 * 41303 * @param imageSrc the image src to load 41304 * @param onLoad callback that is called when the image has been loaded 41305 * @param onError callback that is called in case of an error 41306 */ 41307 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 41308 if (!onLoad && !onError) return; 41309 41310 var memImage = new Image(); 41311 var $memImage = $(memImage); 41312 if (onLoad) { 41313 $memImage.one('load', function () { 41314 $memImage.off('load error'); 41315 onLoad(memImage); 41316 }); 41317 } 41318 if (onError) { 41319 $memImage.one('error', function () { 41320 $memImage.off('load error'); 41321 onError(memImage); 41322 }); 41323 } 41324 memImage.src = imageSrc; 41325 }; 41326 41327 /** 41328 * Init of Justified Gallery controlled 41329 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 41330 */ 41331 JustifiedGallery.prototype.init = function () { 41332 var imagesToLoad = false, skippedImages = false, that = this; 41333 $.each(this.entries, function (index, entry) { 41334 var $entry = $(entry); 41335 var $image = that.imgFromEntry($entry); 41336 41337 $entry.addClass('jg-entry'); 41338 41339 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 41340 41341 // Link Rel global overwrite 41342 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 41343 41344 // Link Target global overwrite 41345 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 41346 41347 if ($image !== null) { 41348 41349 // Image src 41350 var imageSrc = that.extractImgSrcFromImage($image); 41351 41352 /* If we have the height and the width, we don't wait that the image is loaded, 41353 but we start directly with the justification */ 41354 if (that.settings.waitThumbnailsLoad === false || !imageSrc) { 41355 var width = parseFloat($image.attr('width')); 41356 var height = parseFloat($image.attr('height')); 41357 if ($image.prop('tagName') === 'svg') { 41358 width = parseFloat($image[0].getBBox().width); 41359 height = parseFloat($image[0].getBBox().height); 41360 } 41361 if (!isNaN(width) && !isNaN(height)) { 41362 $entry.data('jg.width', width); 41363 $entry.data('jg.height', height); 41364 $entry.data('jg.loaded', 'skipped'); 41365 skippedImages = true; 41366 that.startImgAnalyzer(false); 41367 return true; // continue 41368 } 41369 } 41370 41371 $entry.data('jg.loaded', false); 41372 imagesToLoad = true; 41373 41374 // Spinner start 41375 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 41376 41377 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 41378 $entry.data('jg.width', loadImg.width); 41379 $entry.data('jg.height', loadImg.height); 41380 $entry.data('jg.loaded', true); 41381 that.startImgAnalyzer(false); 41382 }, function () { // image load error 41383 $entry.data('jg.loaded', 'error'); 41384 that.startImgAnalyzer(false); 41385 }); 41386 41387 } else { 41388 $entry.data('jg.loaded', true); 41389 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 41390 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 41391 } 41392 41393 } 41394 41395 }); 41396 41397 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 41398 this.checkWidth(); 41399 }; 41400 41401 /** 41402 * Checks that it is a valid number. If a string is passed it is converted to a number 41403 * 41404 * @param settingContainer the object that contains the setting (to allow the conversion) 41405 * @param settingName the setting name 41406 */ 41407 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 41408 if ($.type(settingContainer[settingName]) === 'string') { 41409 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 41410 } 41411 41412 if ($.type(settingContainer[settingName]) === 'number') { 41413 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 41414 } else { 41415 throw settingName + ' must be a number'; 41416 } 41417 }; 41418 41419 /** 41420 * Checks the sizeRangeSuffixes and, if necessary, converts 41421 * its keys from string (e.g. old settings with 'lt100') to int. 41422 */ 41423 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 41424 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 41425 throw 'sizeRangeSuffixes must be defined and must be an object'; 41426 } 41427 41428 var suffixRanges = []; 41429 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 41430 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 41431 } 41432 41433 var newSizeRngSuffixes = { 0: '' }; 41434 for (var i = 0; i < suffixRanges.length; i++) { 41435 if ($.type(suffixRanges[i]) === 'string') { 41436 try { 41437 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 41438 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 41439 } catch (e) { 41440 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 41441 } 41442 } else { 41443 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 41444 } 41445 } 41446 41447 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 41448 }; 41449 41450 /** 41451 * check and convert the maxRowHeight setting 41452 * requires rowHeight to be already set 41453 * TODO: should be always called when only rowHeight is changed 41454 * @return number or null 41455 */ 41456 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 41457 var newMaxRowHeight = null; 41458 var rowHeight = this.settings.rowHeight; 41459 41460 if ($.type(this.settings.maxRowHeight) === 'string') { 41461 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 41462 newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 41463 } else { 41464 newMaxRowHeight = parseFloat(this.settings.maxRowHeight); 41465 } 41466 } else if ($.type(this.settings.maxRowHeight) === 'number') { 41467 newMaxRowHeight = this.settings.maxRowHeight; 41468 } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) { 41469 return null; 41470 } else { 41471 throw 'maxRowHeight must be a number or a percentage'; 41472 } 41473 41474 // check if the converted value is not a number 41475 if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight'; 41476 41477 // check values, maxRowHeight must be >= rowHeight 41478 if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight; 41479 41480 return newMaxRowHeight; 41481 }; 41482 41483 /** 41484 * Checks the settings 41485 */ 41486 JustifiedGallery.prototype.checkSettings = function () { 41487 this.checkSizeRangesSuffixes(); 41488 41489 this.checkOrConvertNumber(this.settings, 'rowHeight'); 41490 this.checkOrConvertNumber(this.settings, 'margins'); 41491 this.checkOrConvertNumber(this.settings, 'border'); 41492 this.checkOrConvertNumber(this.settings, 'maxRowsCount'); 41493 41494 var lastRowModes = [ 41495 'justify', 41496 'nojustify', 41497 'left', 41498 'center', 41499 'right', 41500 'hide' 41501 ]; 41502 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 41503 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 41504 } 41505 41506 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 41507 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 41508 throw 'justifyThreshold must be in the interval [0,1]'; 41509 } 41510 if ($.type(this.settings.cssAnimation) !== 'boolean') { 41511 throw 'cssAnimation must be a boolean'; 41512 } 41513 41514 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 41515 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 41516 41517 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 41518 if (this.settings.captionSettings.visibleOpacity < 0 || 41519 this.settings.captionSettings.visibleOpacity > 1) { 41520 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 41521 } 41522 41523 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 41524 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 41525 this.settings.captionSettings.nonVisibleOpacity > 1) { 41526 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 41527 } 41528 41529 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 41530 this.checkOrConvertNumber(this.settings, 'refreshTime'); 41531 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 41532 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 41533 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 41534 41535 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 41536 throw 'sort must be false or a comparison function'; 41537 } 41538 41539 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 41540 $.type(this.settings.filter) !== 'string') { 41541 throw 'filter must be false, a string or a filter function'; 41542 } 41543 }; 41544 41545 /** 41546 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 41547 * @returns {Array} sorted suffix ranges 41548 */ 41549 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 41550 var suffixRanges = []; 41551 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 41552 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 41553 } 41554 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 41555 return suffixRanges; 41556 }; 41557 41558 /** 41559 * Update the existing settings only changing some of them 41560 * 41561 * @param newSettings the new settings (or a subgroup of them) 41562 */ 41563 JustifiedGallery.prototype.updateSettings = function (newSettings) { 41564 // In this case Justified Gallery has been called again changing only some options 41565 this.settings = $.extend({}, this.settings, newSettings); 41566 this.checkSettings(); 41567 41568 // As reported in the settings: negative value = same as margins, 0 = disabled 41569 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 41570 41571 this.maxRowHeight = this.retrieveMaxRowHeight(); 41572 this.suffixRanges = this.retrieveSuffixRanges(); 41573 }; 41574 41575 JustifiedGallery.prototype.defaults = { 41576 sizeRangeSuffixes: {}, /* e.g. Flickr configuration 41577 { 41578 100: '_t', // used when longest is less than 100px 41579 240: '_m', // used when longest is between 101px and 240px 41580 320: '_n', // ... 41581 500: '', 41582 640: '_z', 41583 1024: '_b' // used as else case because it is the last 41584 } 41585 */ 41586 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 41587 path relative to a specific thumbnail size. The function should accept respectively three arguments: 41588 current path, width and height */ 41589 rowHeight: 120, // required? required to be > 0? 41590 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 41591 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 41592 // can't exceed 3 * rowHeight) 41593 maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled) 41594 margins: 1, 41595 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 41596 41597 lastRow: 'nojustify', // ⦠which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 41598 41599 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 41600 * (i.e. lastRow setting is not considered) */ 41601 waitThumbnailsLoad: true, 41602 captions: true, 41603 cssAnimation: true, 41604 imagesAnimationDuration: 500, // ignored with css animations 41605 captionSettings: { // ignored with css animations 41606 animationDuration: 500, 41607 visibleOpacity: 0.7, 41608 nonVisibleOpacity: 0.0 41609 },
41610 rel: null, // rewrite the rel of each analyzed links 41611 target: null, // rewrite the target of all links 41612 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 41613 refreshTime: 200, // time interval (in ms) to check if the page changes its width 41614 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 41615 randomize: false, 41616 rtl: false, // right-to-left mode 41617 sort: false, /* 41618 - false: to do not sort 41619 - function: to sort them using the function as comparator (see Array.prototype.sort()) 41620 */ 41621 filter: false, /* 41622 - false, null or undefined: for a disabled filter 41623 - a string: an entry is kept if entry.is(filter string) returns true 41624 see jQuery's .is() function for further information 41625 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 41626 It follows the specifications of the Array.prototype.filter() function of JavaScript. 41627 */ 41628 selector: 'a', // The selector that is used to know what are the entries of the gallery 41629 imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry 41630 triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger 41631 this.$gallery.trigger(event); // Consider that 'this' is this set to the JustifiedGallery object, so it can 41632 } // access to fields such as $gallery, useful to trigger events with jQuery. 41633 }; 41634 41635 41636 /** 41637 * Justified Gallery plugin for jQuery 41638 * 41639 * Events 41640 * - jg.complete : called when all the gallery has been created 41641 * - jg.resize : called when the gallery has been resized 41642 * - jg.rowflush : when a new row appears 41643 * 41644 * @param arg the action (or the settings) passed when the plugin is called 41645 * @returns {*} the object itself 41646 */ 41647 $.fn.justifiedGallery = function (arg) { 41648 return this.each(function (index, gallery) { 41649 41650 var $gallery = $(gallery); 41651 $gallery.addClass('justified-gallery'); 41652 41653 var controller = $gallery.data('jg.controller'); 41654 if (typeof controller === 'undefined') { 41655 // Create controller and assign it to the object data 41656 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 41657 if (arg === 'destroy') return; // Just a call to an unexisting object 41658 throw 'The argument must be an object'; 41659 } 41660 controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg)); 41661 $gallery.data('jg.controller', controller); 41662 } else if (arg === 'norewind') { 41663 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 41664 // ... left to be more readable 41665 } else if (arg === 'destroy') { 41666 controller.destroy(); 41667 return; 41668 } else { 41669 // In this case Justified Gallery has been called again changing only some options 41670 controller.updateSettings(arg); 41671 controller.rewind(); 41672 } 41673 41674 // Update the entries list 41675 if (!controller.updateEntries(arg === 'norewind')) return; 41676 41677 // Init justified gallery 41678 controller.init(); 41679 41680 }); 41681 }; 41682 41683})); 41684 41685/*! 41686* Customized version of iScroll.js 0.0.1 41687* It fixes bugs affecting its integration with fullpage.js 41688*/ 41689/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 41690(function (window, document, Math) { 41691var rAF = window.requestAnimationFrame || 41692 window.webkitRequestAnimationFrame || 41693 window.mozRequestAnimationFrame || 41694 window.oRequestAnimationFrame || 41695 window.msRequestAnimationFrame || 41696 function (callback) { window.setTimeout(callback, 1000 / 60); }; 41697 41698var utils = (function () { 41699 var me = {}; 41700 41701 var _elementStyle = document.createElement('div').style; 41702 var _vendor = (function () { 41703 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 41704 transform, 41705 i = 0, 41706 l = vendors.length; 41707 41708 for ( ; i < l; i++ ) { 41709 transform = vendors[i] + 'ransform'; 41710 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 41711 } 41712 41713 return false;
41714 })(); 41715 41716 function _prefixStyle (style) { 41717 if ( _vendor === false ) return false; 41718 if ( _vendor === '' ) return style; 41719 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 41720 } 41721 41722 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 41723 41724 me.extend = function (target, obj) { 41725 for ( var i in obj ) { 41726 target[i] = obj[i]; 41727 } 41728 }; 41729 41730 me.addEvent = function (el, type, fn, capture) { 41731 el.addEventListener(type, fn, !!capture); 41732 }; 41733 41734 me.removeEvent = function (el, type, fn, capture) { 41735 el.removeEventListener(type, fn, !!capture); 41736 }; 41737 41738 me.prefixPointerEvent = function (pointerEvent) { 41739 return window.MSPointerEvent ? 41740 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 41741 pointerEvent; 41742 }; 41743 41744 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 41745 var distance = current - start, 41746 speed = Math.abs(distance) / time, 41747 destination, 41748 duration; 41749 41750 deceleration = deceleration === undefined ? 0.0006 : deceleration; 41751 41752 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 41753 duration = speed / deceleration; 41754 41755 if ( destination < lowerMargin ) { 41756 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 41757 distance = Math.abs(destination - current); 41758 duration = distance / speed; 41759 } else if ( destination > 0 ) { 41760 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 41761 distance = Math.abs(current) + destination; 41762 duration = distance / speed; 41763 } 41764 41765 return { 41766 destination: Math.round(destination), 41767 duration: duration 41768 }; 41769 }; 41770 41771 var _transform = _prefixStyle('transform'); 41772 41773 me.extend(me, { 41774 hasTransform: _transform !== false, 41775 hasPerspective: _prefixStyle('perspective') in _elementStyle, 41776 hasTouch: 'ontouchstart' in window, 41777 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 41778 hasTransition: _prefixStyle('transition') in _elementStyle 41779 }); 41780 41781 /* 41782 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 41783 - galaxy S2 is ok 41784 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 41785 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 41786 - galaxy S3 is badAndroid (stock brower, webview) 41787 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 41788 - galaxy S4 is badAndroid (stock brower, webview) 41789 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 41790 - galaxy S5 is OK 41791 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 41792 - galaxy S6 is OK 41793 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 41794 */ 41795 me.isBadAndroid = (function() { 41796 var appVersion = window.navigator.appVersion; 41797 // Android browser is not a chrome browser. 41798 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 41799 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 41800 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 41801 return parseFloat(safariVersion[1]) < 535.19; 41802 } else { 41803 return true; 41804 } 41805 } else { 41806 return false; 41807 } 41808 })(); 41809 41810 me.extend(me.style = {}, { 41811 transform: _transform, 41812 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 41813 transitionDuration: _prefixStyle('transitionDuration'), 41814 transitionDelay: _prefixStyle('transitionDelay'), 41815 transformOrigin: _prefixStyle('transformOrigin') 41816 }); 41817 41818 me.hasClass = function (e, c) { 41819 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 41820 return re.test(e.className); 41821 }; 41822 41823 me.addClass = function (e, c) { 41824 if ( me.hasClass(e, c) ) { 41825 return; 41826 } 41827 41828 var newclass = e.className.split(' '); 41829 newclass.push(c); 41830 e.className = newclass.join(' '); 41831 }; 41832 41833 me.removeClass = function (e, c) { 41834 if ( !me.hasClass(e, c) ) { 41835 return; 41836 } 41837 41838 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 41839 e.className = e.className.replace(re, ' '); 41840 }; 41841 41842 me.offset = function (el) { 41843 var left = -el.offsetLeft, 41844 top = -el.offsetTop; 41845 41846 // jshint -W084 41847 while (el = el.offsetParent) { 41848 left -= el.offsetLeft; 41849 top -= el.offsetTop; 41850 } 41851 // jshint +W084 41852 41853 return { 41854 left: left, 41855 top: top 41856 }; 41857 }; 41858 41859 me.preventDefaultException = function (el, exceptions) { 41860 for ( var i in exceptions ) { 41861 if ( exceptions[i].test(el[i]) ) { 41862 return true; 41863 } 41864 } 41865 41866 return false;
41867 }; 41868 41869 me.extend(me.eventType = {}, { 41870 touchstart: 1, 41871 touchmove: 1, 41872 touchend: 1, 41873 41874 mousedown: 2, 41875 mousemove: 2, 41876 mouseup: 2, 41877 41878 pointerdown: 3, 41879 pointermove: 3, 41880 pointerup: 3, 41881 41882 MSPointerDown: 3, 41883 MSPointerMove: 3, 41884 MSPointerUp: 3 41885 }); 41886 41887 me.extend(me.ease = {}, { 41888 quadratic: { 41889 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 41890 fn: function (k) { 41891 return k * ( 2 - k ); 41892 } 41893 }, 41894 circular: { 41895 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) 41896 fn: function (k) { 41897 return Math.sqrt( 1 - ( --k * k ) ); 41898 } 41899 }, 41900 back: { 41901 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 41902 fn: function (k) { 41903 var b = 4; 41904 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 41905 } 41906 }, 41907 bounce: { 41908 style: '', 41909 fn: function (k) { 41910 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 41911 return 7.5625 * k * k; 41912 } else if ( k < ( 2 / 2.75 ) ) { 41913 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 41914 } else if ( k < ( 2.5 / 2.75 ) ) { 41915 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 41916 } else { 41917 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 41918 } 41919 } 41920 }, 41921 elastic: { 41922 style: '', 41923 fn: function (k) { 41924 var f = 0.22, 41925 e = 0.4; 41926 41927 if ( k === 0 ) { return 0; } 41928 if ( k == 1 ) { return 1; } 41929 41930 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 41931 } 41932 } 41933 }); 41934 41935 me.tap = function (e, eventName) { 41936 var ev = document.createEvent('Event'); 41937 ev.initEvent(eventName, true, true); 41938 ev.pageX = e.pageX; 41939 ev.pageY = e.pageY; 41940 e.target.dispatchEvent(ev); 41941 }; 41942 41943 me.click = function (e) { 41944 var target = e.target, 41945 ev; 41946 41947 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 41948 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 41949 // initMouseEvent is deprecated. 41950 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 41951 ev.initEvent('click', true, true); 41952 ev.view = e.view || window; 41953 ev.detail = 1; 41954 ev.screenX = target.screenX || 0; 41955 ev.screenY = target.screenY || 0; 41956 ev.clientX = target.clientX || 0; 41957 ev.clientY = target.clientY || 0; 41958 ev.ctrlKey = !!e.ctrlKey; 41959 ev.altKey = !!e.altKey; 41960 ev.shiftKey = !!e.shiftKey; 41961 ev.metaKey = !!e.metaKey; 41962 ev.button = 0; 41963 ev.relatedTarget = null; 41964 ev._constructed = true; 41965 target.dispatchEvent(ev); 41966 } 41967 }; 41968 41969 return me; 41970})(); 41971function IScroll (el, options) { 41972 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 41973 this.scroller = this.wrapper.children[0]; 41974 this.scrollerStyle = this.scroller.style; // cache style for better performance 41975 41976 this.options = { 41977 41978 resizeScrollbars: true, 41979 41980 mouseWheelSpeed: 20, 41981 41982 snapThreshold: 0.334, 41983 41984// INSERT POINT: OPTIONS 41985 disablePointer : !utils.hasPointer, 41986 disableTouch : utils.hasPointer || !utils.hasTouch, 41987 disableMouse : utils.hasPointer || utils.hasTouch, 41988 startX: 0, 41989 startY: 0, 41990 scrollY: true, 41991 directionLockThreshold: 5, 41992 momentum: true, 41993 41994 bounce: true, 41995 bounceTime: 600, 41996 bounceEasing: '', 41997 41998 preventDefault: true, 41999 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ }, 42000 42001 HWCompositing: true, 42002 useTransition: true, 42003 useTransform: true, 42004 bindToWrapper: typeof window.onmousedown === "undefined" 42005 }; 42006 42007 for ( var i in options ) { 42008 this.options[i] = options[i]; 42009 } 42010 42011 // Normalize options 42012 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 42013 42014 this.options.useTransition = utils.hasTransition && this.options.useTransition; 42015 this.options.useTransform = utils.hasTransform && this.options.useTransform; 42016 42017 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 42018 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 42019 42020 // If you want eventPassthrough I have to lock one of the axes 42021 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 42022 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 42023 42024 // With eventPassthrough we also need lockDirection mechanism 42025 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 42026 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 42027 42028 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 42029 42030 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 42031 42032 if ( this.options.tap === true ) {
42033 this.options.tap = 'tap'; 42034 } 42035 42036 // https://github.com/cubiq/iscroll/issues/1029 42037 if (!this.options.useTransition && !this.options.useTransform) { 42038 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 42039 this.scrollerStyle.position = "relative"; 42040 } 42041 } 42042 42043 if ( this.options.shrinkScrollbars == 'scale' ) { 42044 this.options.useTransition = false; 42045 } 42046 42047 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 42048 42049// INSERT POINT: NORMALIZATION 42050 42051 // Some defaults 42052 this.x = 0; 42053 this.y = 0; 42054 this.directionX = 0; 42055 this.directionY = 0; 42056 this._events = {}; 42057 42058// INSERT POINT: DEFAULTS 42059 42060 this._init(); 42061 this.refresh(); 42062 42063 this.scrollTo(this.options.startX, this.options.startY); 42064 this.enable(); 42065} 42066 42067IScroll.prototype = { 42068 version: '5.2.0', 42069 42070 _init: function () { 42071 this._initEvents(); 42072 42073 if ( this.options.scrollbars || this.options.indicators ) { 42074 this._initIndicators(); 42075 } 42076 42077 if ( this.options.mouseWheel ) { 42078 this._initWheel(); 42079 } 42080 42081 if ( this.options.snap ) { 42082 this._initSnap(); 42083 } 42084 42085 if ( this.options.keyBindings ) { 42086 this._initKeys(); 42087 } 42088 42089// INSERT POINT: _init 42090 42091 }, 42092 42093 destroy: function () { 42094 this._initEvents(true); 42095 clearTimeout(this.resizeTimeout); 42096 this.resizeTimeout = null; 42097 this._execEvent('destroy'); 42098 }, 42099 42100 _transitionEnd: function (e) { 42101 if ( e.target != this.scroller || !this.isInTransition ) { 42102 return; 42103 } 42104 42105 this._transitionTime(); 42106 if ( !this.resetPosition(this.options.bounceTime) ) { 42107 this.isInTransition = false; 42108 this._execEvent('scrollEnd'); 42109 } 42110 }, 42111 42112 _start: function (e) { 42113 // React to left mouse button only 42114 if ( utils.eventType[e.type] != 1 ) { 42115 // for button property 42116 // http://unixpapa.com/js/mouse.html 42117 var button; 42118 if (!e.which) { 42119 /* IE case */ 42120 button = (e.button < 2) ? 0 : 42121 ((e.button == 4) ? 1 : 2); 42122 } else { 42123 /* All others */ 42124 button = e.button; 42125 } 42126 if ( button !== 0 ) { 42127 return; 42128 } 42129 } 42130 42131 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 42132 return; 42133 } 42134 42135 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 42136 e.preventDefault(); 42137 } 42138 42139 var point = e.touches ? e.touches[0] : e, 42140 pos; 42141 42142 this.initiated = utils.eventType[e.type]; 42143 this.moved = false; 42144 this.distX = 0; 42145 this.distY = 0; 42146 this.directionX = 0; 42147 this.directionY = 0; 42148 this.directionLocked = 0; 42149 42150 this.startTime = utils.getTime(); 42151 42152 if ( this.options.useTransition && this.isInTransition ) { 42153 this._transitionTime(); 42154 this.isInTransition = false; 42155 pos = this.getComputedPosition(); 42156 this._translate(Math.round(pos.x), Math.round(pos.y)); 42157 this._execEvent('scrollEnd'); 42158 } else if ( !this.options.useTransition && this.isAnimating ) { 42159 this.isAnimating = false; 42160 this._execEvent('scrollEnd'); 42161 } 42162 42163 this.startX = this.x; 42164 this.startY = this.y; 42165 this.absStartX = this.x; 42166 this.absStartY = this.y; 42167 this.pointX = point.pageX; 42168 this.pointY = point.pageY; 42169 42170 this._execEvent('beforeScrollStart'); 42171 }, 42172 42173 _move: function (e) { 42174 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 42175 return; 42176 } 42177 42178 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 42179 e.preventDefault(); 42180 } 42181 42182 var point = e.touches ? e.touches[0] : e, 42183 deltaX = point.pageX - this.pointX, 42184 deltaY = point.pageY - this.pointY, 42185 timestamp = utils.getTime(), 42186 newX, newY, 42187 absDistX, absDistY; 42188 42189 this.pointX = point.pageX; 42190 this.pointY = point.pageY; 42191 42192 this.distX += deltaX; 42193 this.distY += deltaY; 42194 absDistX = Math.abs(this.distX); 42195 absDistY = Math.abs(this.distY); 42196 42197 // We need to move at least 10 pixels for the scrolling to initiate 42198 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 42199 return; 42200 } 42201 42202 // If you are scrolling in one direction lock the other 42203 if ( !this.directionLocked && !this.options.freeScroll ) { 42204 if ( absDistX > absDistY + this.options.directionLockThreshold ) {
42205 this.directionLocked = 'h'; // lock horizontally 42206 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 42207 this.directionLocked = 'v'; // lock vertically 42208 } else { 42209 this.directionLocked = 'n'; // no lock 42210 } 42211 } 42212 42213 if ( this.directionLocked == 'h' ) { 42214 if ( this.options.eventPassthrough == 'vertical' ) { 42215 e.preventDefault(); 42216 } else if ( this.options.eventPassthrough == 'horizontal' ) { 42217 this.initiated = false; 42218 return; 42219 } 42220 42221 deltaY = 0; 42222 } else if ( this.directionLocked == 'v' ) { 42223 if ( this.options.eventPassthrough == 'horizontal' ) { 42224 e.preventDefault(); 42225 } else if ( this.options.eventPassthrough == 'vertical' ) { 42226 this.initiated = false; 42227 return; 42228 } 42229 42230 deltaX = 0; 42231 } 42232 42233 deltaX = this.hasHorizontalScroll ? deltaX : 0; 42234 deltaY = this.hasVerticalScroll ? deltaY : 0; 42235 42236 newX = this.x + deltaX; 42237 newY = this.y + deltaY; 42238 42239 // Slow down if outside of the boundaries 42240 if ( newX > 0 || newX < this.maxScrollX ) { 42241 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 42242 } 42243 if ( newY > 0 || newY < this.maxScrollY ) { 42244 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 42245 } 42246 42247 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 42248 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 42249 42250 if ( !this.moved ) { 42251 this._execEvent('scrollStart'); 42252 } 42253 42254 this.moved = true; 42255 42256 this._translate(newX, newY); 42257 42258/* REPLACE START: _move */ 42259 42260 if ( timestamp - this.startTime > 300 ) { 42261 this.startTime = timestamp; 42262 this.startX = this.x; 42263 this.startY = this.y; 42264 } 42265 42266/* REPLACE END: _move */ 42267 42268 }, 42269 42270 _end: function (e) { 42271 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 42272 return; 42273 } 42274 42275 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 42276 e.preventDefault(); 42277 } 42278 42279 var point = e.changedTouches ? e.changedTouches[0] : e, 42280 momentumX, 42281 momentumY, 42282 duration = utils.getTime() - this.startTime, 42283 newX = Math.round(this.x), 42284 newY = Math.round(this.y), 42285 distanceX = Math.abs(newX - this.startX), 42286 distanceY = Math.abs(newY - this.startY), 42287 time = 0, 42288 easing = ''; 42289 42290 this.isInTransition = 0; 42291 this.initiated = 0; 42292 this.endTime = utils.getTime(); 42293 42294 // reset if we are outside of the boundaries 42295 if ( this.resetPosition(this.options.bounceTime) ) { 42296 return; 42297 } 42298 42299 this.scrollTo(newX, newY); // ensures that the last position is rounded 42300 42301 // we scrolled less than 10 pixels 42302 if ( !this.moved ) { 42303 if ( this.options.tap ) { 42304 utils.tap(e, this.options.tap); 42305 } 42306 42307 if ( this.options.click ) { 42308 utils.click(e); 42309 } 42310 42311 this._execEvent('scrollCancel'); 42312 return; 42313 } 42314 42315 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 42316 this._execEvent('flick'); 42317 return; 42318 } 42319 42320 // start momentum animation if needed 42321 if ( this.options.momentum && duration < 300 ) { 42322 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 }; 42323 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 }; 42324 newX = momentumX.destination; 42325 newY = momentumY.destination; 42326 time = Math.max(momentumX.duration, momentumY.duration); 42327 this.isInTransition = 1; 42328 } 42329 42330 42331 if ( this.options.snap ) { 42332 var snap = this._nearestSnap(newX, newY); 42333 this.currentPage = snap; 42334 time = this.options.snapSpeed || Math.max( 42335 Math.max( 42336 Math.min(Math.abs(newX - snap.x), 1000), 42337 Math.min(Math.abs(newY - snap.y), 1000) 42338 ), 300); 42339 newX = snap.x; 42340 newY = snap.y; 42341 42342 this.directionX = 0; 42343 this.directionY = 0; 42344 easing = this.options.bounceEasing; 42345 } 42346 42347// INSERT POINT: _end 42348 42349 if ( newX != this.x || newY != this.y ) { 42350 // change easing function when scroller goes out of the boundaries 42351 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 42352 easing = utils.ease.quadratic; 42353 } 42354 42355 this.scrollTo(newX, newY, time, easing); 42356 return; 42357 } 42358 42359 this._execEvent('scrollEnd'); 42360 }, 42361 42362 _resize: function () { 42363 var that = this; 42364 42365 clearTimeout(this.resizeTimeout); 42366 42367 this.resizeTimeout = setTimeout(function () { 42368 that.refresh(); 42369 }, this.options.resizePolling); 42370 }, 42371 42372 resetPosition: function (time) { 42373 var x = this.x, 42374 y = this.y; 42375 42376 time = time || 0; 42377 42378 if ( !this.hasHorizontalScroll || this.x > 0 ) { 42379 x = 0; 42380 } else if ( this.x < this.maxScrollX ) { 42381 x = this.maxScrollX; 42382 } 42383 42384 if ( !this.hasVerticalScroll || this.y > 0 ) { 42385 y = 0; 42386 } else if ( this.y < this.maxScrollY ) { 42387 y = this.maxScrollY; 42388 } 42389 42390 if ( x == this.x && y == this.y ) { 42391 return false;
42392 } 42393 42394 this.scrollTo(x, y, time, this.options.bounceEasing); 42395 42396 return true; 42397 }, 42398 42399 disable: function () { 42400 this.enabled = false; 42401 }, 42402 42403 enable: function () { 42404 this.enabled = true; 42405 }, 42406 42407 refresh: function () { 42408 var rf = this.wrapper.offsetHeight; // Force reflow 42409 42410 this.wrapperWidth = this.wrapper.clientWidth; 42411 this.wrapperHeight = this.wrapper.clientHeight; 42412 42413/* REPLACE START: refresh */ 42414 42415 this.scrollerWidth = this.scroller.offsetWidth; 42416 this.scrollerHeight = this.scroller.offsetHeight; 42417 42418 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 42419 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 42420 42421/* REPLACE END: refresh */ 42422 42423 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 42424 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 42425 42426 if ( !this.hasHorizontalScroll ) { 42427 this.maxScrollX = 0; 42428 this.scrollerWidth = this.wrapperWidth; 42429 } 42430 42431 if ( !this.hasVerticalScroll ) { 42432 this.maxScrollY = 0; 42433 this.scrollerHeight = this.wrapperHeight; 42434 } 42435 42436 this.endTime = 0; 42437 this.directionX = 0; 42438 this.directionY = 0; 42439 42440 this.wrapperOffset = utils.offset(this.wrapper); 42441 42442 this._execEvent('refresh'); 42443 42444 this.resetPosition(); 42445 42446// INSERT POINT: _refresh 42447 42448 }, 42449 42450 42451 on: function (type, fn) { 42452 if ( !this._events[type] ) { 42453 this._events[type] = []; 42454 } 42455 42456 this._events[type].push(fn); 42457 }, 42458 42459 off: function (type, fn) { 42460 if ( !this._events[type] ) { 42461 return; 42462 } 42463 42464 var index = this._events[type].indexOf(fn); 42465 42466 if ( index > -1 ) { 42467 this._events[type].splice(index, 1); 42468 } 42469 }, 42470 42471 _execEvent: function (type) { 42472 if ( !this._events[type] ) { 42473 return; 42474 } 42475 42476 var i = 0, 42477 l = this._events[type].length; 42478 42479 if ( !l ) { 42480 return; 42481 } 42482 42483 for ( ; i < l; i++ ) { 42484 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 42485 } 42486 }, 42487 42488 scrollBy: function (x, y, time, easing) { 42489 x = this.x + x; 42490 y = this.y + y; 42491 time = time || 0; 42492 42493 this.scrollTo(x, y, time, easing); 42494 }, 42495 42496 scrollTo: function (x, y, time, easing) { 42497 easing = easing || utils.ease.circular; 42498 42499 this.isInTransition = this.options.useTransition && time > 0; 42500 var transitionType = this.options.useTransition && easing.style; 42501 if ( !time || transitionType ) { 42502 if(transitionType) { 42503 this._transitionTimingFunction(easing.style); 42504 this._transitionTime(time); 42505 } 42506 this._translate(x, y); 42507 } else { 42508 this._animate(x, y, time, easing.fn); 42509 } 42510 }, 42511 42512 scrollToElement: function (el, time, offsetX, offsetY, easing) { 42513 el = el.nodeType ? el : this.scroller.querySelector(el); 42514 42515 if ( !el ) { 42516 return; 42517 } 42518 42519 var pos = utils.offset(el); 42520 42521 pos.left -= this.wrapperOffset.left; 42522 pos.top -= this.wrapperOffset.top; 42523 42524 // if offsetX/Y are true we center the element to the screen 42525 if ( offsetX === true ) { 42526 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 42527 } 42528 if ( offsetY === true ) { 42529 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 42530 } 42531 42532 pos.left -= offsetX || 0; 42533 pos.top -= offsetY || 0; 42534 42535 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 42536 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 42537 42538 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 42539 42540 this.scrollTo(pos.left, pos.top, time, easing); 42541 }, 42542 42543 _transitionTime: function (time) { 42544 if (!this.options.useTransition) { 42545 return; 42546 } 42547 time = time || 0; 42548 var durationProp = utils.style.transitionDuration; 42549 if(!durationProp) { 42550 return; 42551 } 42552 42553 this.scrollerStyle[durationProp] = time + 'ms'; 42554 42555 if ( !time && utils.isBadAndroid ) { 42556 this.scrollerStyle[durationProp] = '0.0001ms'; 42557 // remove 0.0001ms 42558 var self = this; 42559 rAF(function() { 42560 if(self.scrollerStyle[durationProp] === '0.0001ms') { 42561 self.scrollerStyle[durationProp] = '0s'; 42562 } 42563 }); 42564 } 42565 42566 42567 if ( this.indicators ) { 42568 for ( var i = this.indicators.length; i--; ) { 42569 this.indicators[i].transitionTime(time); 42570 } 42571 } 42572 42573 42574// INSERT POINT: _transitionTime 42575 42576 }, 42577 42578 _transitionTimingFunction: function (easing) { 42579 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 42580 42581 42582 if ( this.indicators ) { 42583 for ( var i = this.indicators.length; i--; ) { 42584 this.indicators[i].transitionTimingFunction(easing); 42585 } 42586 } 42587 42588 42589// INSERT POINT: _transitionTimingFunction 42590 42591 }, 42592 42593 _translate: function (x, y) { 42594 //Uncode addition 42595 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 42596 return false;
42597 42598 if ( this.options.useTransform ) { 42599 42600/* REPLACE START: _translate */ 42601 42602 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 42603 42604/* REPLACE END: _translate */ 42605 42606 } else { 42607 x = Math.round(x); 42608 y = Math.round(y); 42609 this.scrollerStyle.left = x + 'px'; 42610 this.scrollerStyle.top = y + 'px'; 42611 } 42612 42613 this.x = x; 42614 this.y = y; 42615 42616 42617 if ( this.indicators ) { 42618 for ( var i = this.indicators.length; i--; ) { 42619 this.indicators[i].updatePosition(); 42620 } 42621 } 42622 42623 //Uncode addition 42624 var uncodevent = new CustomEvent('fp-slide-scroll'); 42625 window.dispatchEvent(uncodevent); 42626 42627// INSERT POINT: _translate 42628 42629 }, 42630 42631 _initEvents: function (remove) { 42632 var eventType = remove ? utils.removeEvent : utils.addEvent, 42633 target = this.options.bindToWrapper ? this.wrapper : window; 42634 42635 eventType(window, 'orientationchange', this); 42636 eventType(window, 'resize', this); 42637 42638 if ( this.options.click ) { 42639 eventType(this.wrapper, 'click', this, true); 42640 } 42641 42642 if ( !this.options.disableMouse ) { 42643 eventType(this.wrapper, 'mousedown', this); 42644 eventType(target, 'mousemove', this); 42645 eventType(target, 'mousecancel', this); 42646 eventType(target, 'mouseup', this); 42647 } 42648 42649 if ( utils.hasPointer && !this.options.disablePointer ) { 42650 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 42651 eventType(target, utils.prefixPointerEvent('pointermove'), this); 42652 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 42653 eventType(target, utils.prefixPointerEvent('pointerup'), this); 42654 } 42655 42656 if ( utils.hasTouch && !this.options.disableTouch ) { 42657 eventType(this.wrapper, 'touchstart', this); 42658 eventType(target, 'touchmove', this); 42659 eventType(target, 'touchcancel', this); 42660 eventType(target, 'touchend', this); 42661 } 42662 42663 eventType(this.scroller, 'transitionend', this); 42664 eventType(this.scroller, 'webkitTransitionEnd', this); 42665 eventType(this.scroller, 'oTransitionEnd', this); 42666 eventType(this.scroller, 'MSTransitionEnd', this); 42667 }, 42668 42669 getComputedPosition: function () { 42670 var matrix = window.getComputedStyle(this.scroller, null), 42671 x, y; 42672 42673 if ( this.options.useTransform ) { 42674 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 42675 x = +(matrix[12] || matrix[4]); 42676 y = +(matrix[13] || matrix[5]); 42677 } else { 42678 x = +matrix.left.replace(/[^-\d.]/g, ''); 42679 y = +matrix.top.replace(/[^-\d.]/g, ''); 42680 } 42681 42682 return { x: x, y: y }; 42683 }, 42684 _initIndicators: function () { 42685 var interactive = this.options.interactiveScrollbars, 42686 customStyle = typeof this.options.scrollbars != 'string', 42687 indicators = [], 42688 indicator; 42689 42690 var that = this; 42691 42692 this.indicators = []; 42693 42694 if ( this.options.scrollbars ) { 42695 // Vertical scrollbar 42696 if ( this.options.scrollY ) { 42697 indicator = { 42698 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 42699 interactive: interactive, 42700 defaultScrollbars: true, 42701 customStyle: customStyle, 42702 resize: this.options.resizeScrollbars, 42703 shrink: this.options.shrinkScrollbars, 42704 fade: this.options.fadeScrollbars, 42705 listenX: false 42706 }; 42707 42708 this.wrapper.appendChild(indicator.el); 42709 indicators.push(indicator); 42710 } 42711 42712 // Horizontal scrollbar 42713 if ( this.options.scrollX ) { 42714 indicator = { 42715 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 42716 interactive: interactive, 42717 defaultScrollbars: true, 42718 customStyle: customStyle, 42719 resize: this.options.resizeScrollbars, 42720 shrink: this.options.shrinkScrollbars, 42721 fade: this.options.fadeScrollbars, 42722 listenY: false 42723 }; 42724 42725 this.wrapper.appendChild(indicator.el); 42726 indicators.push(indicator); 42727 } 42728 } 42729 42730 if ( this.options.indicators ) { 42731 // TODO: check concat compatibility 42732 indicators = indicators.concat(this.options.indicators); 42733 } 42734 42735 for ( var i = indicators.length; i--; ) { 42736 this.indicators.push( new Indicator(this, indicators[i]) ); 42737 } 42738 42739 // TODO: check if we can use array.map (wide compatibility and performance issues) 42740 function _indicatorsMap (fn) { 42741 if (that.indicators) { 42742 for ( var i = that.indicators.length; i--; ) { 42743 fn.call(that.indicators[i]); 42744 } 42745 } 42746 } 42747 42748 if ( this.options.fadeScrollbars ) { 42749 this.on('scrollEnd', function () { 42750 _indicatorsMap(function () { 42751 this.fade(); 42752 }); 42753 }); 42754 42755 this.on('scrollCancel', function () { 42756 _indicatorsMap(function () { 42757 this.fade(); 42758 }); 42759 }); 42760 42761 this.on('scrollStart', function () { 42762 _indicatorsMap(function () { 42763 this.fade(1); 42764 }); 42765 }); 42766 42767 this.on('beforeScrollStart', function () { 42768 _indicatorsMap(function () { 42769 this.fade(1, true); 42770 }); 42771 }); 42772 } 42773 42774 42775 this.on('refresh', function () { 42776 _indicatorsMap(function () { 42777 this.refresh(); 42778 }); 42779 }); 42780 42781 this.on('destroy', function () { 42782 _indicatorsMap(function () { 42783 this.destroy(); 42784 }); 42785 42786 delete this.indicators; 42787 }); 42788 }, 42789 42790 _initWheel: function () { 42791 utils.addEvent(this.wrapper, 'wheel', this); 42792 utils.addEvent(this.wrapper, 'mousewheel', this); 42793 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 42794 42795 this.on('destroy', function () { 42796 clearTimeout(this.wheelTimeout); 42797 this.wheelTimeout = null; 42798 utils.removeEvent(this.wrapper, 'wheel', this); 42799 utils.removeEvent(this.wrapper, 'mousewheel', this); 42800 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 42801 }); 42802 }, 42803 42804 _wheel: function (e) { 42805 if ( !this.enabled ) { 42806 return; 42807 } 42808 42809 var wheelDeltaX, wheelDeltaY, 42810 newX, newY, 42811 that = this; 42812 42813 if ( this.wheelTimeout === undefined ) { 42814 that._execEvent('scrollStart'); 42815 } 42816 42817 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 42818 clearTimeout(this.wheelTimeout); 42819 this.wheelTimeout = setTimeout(function () { 42820 if(!that.options.snap) { 42821 that._execEvent('scrollEnd'); 42822 } 42823 that.wheelTimeout = undefined; 42824 }, 400); 42825 42826 if ( 'deltaX' in e ) { 42827 if (e.deltaMode === 1) { 42828 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 42829 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 42830 } else { 42831 wheelDeltaX = -e.deltaX; 42832 wheelDeltaY = -e.deltaY; 42833 } 42834 } else if ( 'wheelDeltaX' in e ) { 42835 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 42836 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 42837 } else if ( 'wheelDelta' in e ) { 42838 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 42839 } else if ( 'detail' in e ) { 42840 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 42841 } else { 42842 return; 42843 } 42844 42845 wheelDeltaX *= this.options.invertWheelDirection; 42846 wheelDeltaY *= this.options.invertWheelDirection; 42847 42848 if ( !this.hasVerticalScroll ) { 42849 wheelDeltaX = wheelDeltaY; 42850 wheelDeltaY = 0; 42851 } 42852 42853 if ( this.options.snap ) { 42854 newX = this.currentPage.pageX; 42855 newY = this.currentPage.pageY; 42856 42857 if ( wheelDeltaX > 0 ) { 42858 newX--; 42859 } else if ( wheelDeltaX < 0 ) { 42860 newX++; 42861 } 42862 42863 if ( wheelDeltaY > 0 ) { 42864 newY--; 42865 } else if ( wheelDeltaY < 0 ) { 42866 newY++; 42867 } 42868 42869 this.goToPage(newX, newY); 42870 42871 return; 42872 } 42873 42874 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 42875 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 42876 42877 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 42878 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 42879 42880 if ( newX > 0 ) { 42881 newX = 0; 42882 } else if ( newX < this.maxScrollX ) { 42883 newX = this.maxScrollX; 42884 } 42885 42886 if ( newY > 0 ) { 42887 newY = 0; 42888 } else if ( newY < this.maxScrollY ) { 42889 newY = this.maxScrollY; 42890 } 42891 42892 this.scrollTo(newX, newY, 0); 42893 42894// INSERT POINT: _wheel 42895 }, 42896 42897 _initSnap: function () { 42898 this.currentPage = {}; 42899 42900 if ( typeof this.options.snap == 'string' ) { 42901 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 42902 } 42903 42904 this.on('refresh', function () { 42905 var i = 0, l, 42906 m = 0, n, 42907 cx, cy, 42908 x = 0, y,
42909 stepX = this.options.snapStepX || this.wrapperWidth, 42910 stepY = this.options.snapStepY || this.wrapperHeight, 42911 el; 42912 42913 this.pages = []; 42914 42915 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 42916 return; 42917 } 42918 42919 if ( this.options.snap === true ) { 42920 cx = Math.round( stepX / 2 ); 42921 cy = Math.round( stepY / 2 ); 42922 42923 while ( x > -this.scrollerWidth ) { 42924 this.pages[i] = []; 42925 l = 0; 42926 y = 0; 42927 42928 while ( y > -this.scrollerHeight ) { 42929 this.pages[i][l] = { 42930 x: Math.max(x, this.maxScrollX), 42931 y: Math.max(y, this.maxScrollY), 42932 width: stepX, 42933 height: stepY, 42934 cx: x - cx, 42935 cy: y - cy 42936 }; 42937 42938 y -= stepY; 42939 l++; 42940 } 42941 42942 x -= stepX; 42943 i++; 42944 } 42945 } else { 42946 el = this.options.snap; 42947 l = el.length; 42948 n = -1; 42949 42950 for ( ; i < l; i++ ) { 42951 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 42952 m = 0; 42953 n++; 42954 } 42955 42956 if ( !this.pages[m] ) { 42957 this.pages[m] = []; 42958 } 42959 42960 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 42961 y = Math.max(-el[i].offsetTop, this.maxScrollY); 42962 cx = x - Math.round(el[i].offsetWidth / 2); 42963 cy = y - Math.round(el[i].offsetHeight / 2); 42964 42965 this.pages[m][n] = { 42966 x: x, 42967 y: y, 42968 width: el[i].offsetWidth, 42969 height: el[i].offsetHeight, 42970 cx: cx, 42971 cy: cy 42972 }; 42973 42974 if ( x > this.maxScrollX ) { 42975 m++; 42976 } 42977 } 42978 } 42979 42980 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 42981 42982 // Update snap threshold if needed 42983 if ( this.options.snapThreshold % 1 === 0 ) { 42984 this.snapThresholdX = this.options.snapThreshold; 42985 this.snapThresholdY = this.options.snapThreshold; 42986 } else { 42987 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 42988 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 42989 } 42990 }); 42991 42992 this.on('flick', function () { 42993 var time = this.options.snapSpeed || Math.max( 42994 Math.max( 42995 Math.min(Math.abs(this.x - this.startX), 1000), 42996 Math.min(Math.abs(this.y - this.startY), 1000) 42997 ), 300); 42998 42999 this.goToPage( 43000 this.currentPage.pageX + this.directionX, 43001 this.currentPage.pageY + this.directionY, 43002 time 43003 ); 43004 }); 43005 }, 43006 43007 _nearestSnap: function (x, y) { 43008 if ( !this.pages.length ) { 43009 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 43010 } 43011 43012 var i = 0, 43013 l = this.pages.length, 43014 m = 0; 43015 43016 // Check if we exceeded the snap threshold 43017 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 43018 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 43019 return this.currentPage; 43020 } 43021 43022 if ( x > 0 ) { 43023 x = 0; 43024 } else if ( x < this.maxScrollX ) { 43025 x = this.maxScrollX; 43026 } 43027 43028 if ( y > 0 ) { 43029 y = 0; 43030 } else if ( y < this.maxScrollY ) { 43031 y = this.maxScrollY; 43032 } 43033 43034 for ( ; i < l; i++ ) { 43035 if ( x >= this.pages[i][0].cx ) { 43036 x = this.pages[i][0].x; 43037 break; 43038 } 43039 } 43040 43041 l = this.pages[i].length; 43042 43043 for ( ; m < l; m++ ) { 43044 if ( y >= this.pages[0][m].cy ) { 43045 y = this.pages[0][m].y; 43046 break; 43047 } 43048 } 43049 43050 if ( i == this.currentPage.pageX ) { 43051 i += this.directionX; 43052 43053 if ( i < 0 ) { 43054 i = 0; 43055 } else if ( i >= this.pages.length ) { 43056 i = this.pages.length - 1; 43057 } 43058 43059 x = this.pages[i][0].x; 43060 } 43061 43062 if ( m == this.currentPage.pageY ) { 43063 m += this.directionY; 43064 43065 if ( m < 0 ) { 43066 m = 0; 43067 } else if ( m >= this.pages[0].length ) { 43068 m = this.pages[0].length - 1; 43069 } 43070 43071 y = this.pages[0][m].y; 43072 } 43073 43074 return { 43075 x: x, 43076 y: y, 43077 pageX: i, 43078 pageY: m 43079 }; 43080 }, 43081 43082 goToPage: function (x, y, time, easing) { 43083 easing = easing || this.options.bounceEasing; 43084 43085 if ( x >= this.pages.length ) { 43086 x = this.pages.length - 1; 43087 } else if ( x < 0 ) { 43088 x = 0; 43089 } 43090 43091 if ( y >= this.pages[x].length ) { 43092 y = this.pages[x].length - 1; 43093 } else if ( y < 0 ) { 43094 y = 0; 43095 } 43096 43097 var posX = this.pages[x][y].x, 43098 posY = this.pages[x][y].y; 43099 43100 time = time === undefined ? this.options.snapSpeed || Math.max( 43101 Math.max( 43102 Math.min(Math.abs(posX - this.x), 1000), 43103 Math.min(Math.abs(posY - this.y), 1000) 43104 ), 300) : time; 43105 43106 this.currentPage = { 43107 x: posX, 43108 y: posY, 43109 pageX: x, 43110 pageY: y 43111 }; 43112 43113 this.scrollTo(posX, posY, time, easing); 43114 }, 43115 43116 next: function (time, easing) { 43117 var x = this.currentPage.pageX, 43118 y = this.currentPage.pageY; 43119 43120 x++; 43121 43122 if ( x >= this.pages.length && this.hasVerticalScroll ) { 43123 x = 0; 43124 y++; 43125 } 43126 43127 this.goToPage(x, y, time, easing); 43128 }, 43129 43130 prev: function (time, easing) { 43131 var x = this.currentPage.pageX, 43132 y = this.currentPage.pageY; 43133 43134 x--; 43135 43136 if ( x < 0 && this.hasVerticalScroll ) { 43137 x = 0; 43138 y--; 43139 } 43140 43141 this.goToPage(x, y, time, easing); 43142 }, 43143 43144 _initKeys: function (e) { 43145 // default key bindings 43146 var keys = { 43147 pageUp: 33, 43148 pageDown: 34, 43149 end: 35, 43150 home: 36, 43151 left: 37, 43152 up: 38, 43153 right: 39, 43154 down: 40 43155 }; 43156 var i; 43157 43158 // if you give me characters I give you keycode 43159 if ( typeof this.options.keyBindings == 'object' ) { 43160 for ( i in this.options.keyBindings ) { 43161 if ( typeof this.options.keyBindings[i] == 'string' ) { 43162 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
43162deAt(0); 43163 } 43164 } 43165 } else { 43166 this.options.keyBindings = {}; 43167 } 43168 43169 for ( i in keys ) { 43170 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 43171 } 43172 43173 utils.addEvent(window, 'keydown', this); 43174 43175 this.on('destroy', function () { 43176 utils.removeEvent(window, 'keydown', this); 43177 }); 43178 }, 43179 43180 _key: function (e) { 43181 if ( !this.enabled ) { 43182 return; 43183 } 43184 43185 var snap = this.options.snap, // we are using this alot, better to cache it 43186 newX = snap ? this.currentPage.pageX : this.x, 43187 newY = snap ? this.currentPage.pageY : this.y, 43188 now = utils.getTime(), 43189 prevTime = this.keyTime || 0, 43190 acceleration = 0.250, 43191 pos; 43192 43193 if ( this.options.useTransition && this.isInTransition ) { 43194 pos = this.getComputedPosition(); 43195 43196 this._translate(Math.round(pos.x), Math.round(pos.y)); 43197 this.isInTransition = false; 43198 } 43199 43200 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 43201 43202 switch ( e.keyCode ) { 43203 case this.options.keyBindings.pageUp: 43204 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 43205 newX += snap ? 1 : this.wrapperWidth; 43206 } else { 43207 newY += snap ? 1 : this.wrapperHeight; 43208 } 43209 break; 43210 case this.options.keyBindings.pageDown: 43211 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 43212 newX -= snap ? 1 : this.wrapperWidth; 43213 } else { 43214 newY -= snap ? 1 : this.wrapperHeight; 43215 } 43216 break; 43217 case this.options.keyBindings.end: 43218 newX = snap ? this.pages.length-1 : this.maxScrollX; 43219 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 43220 break; 43221 case this.options.keyBindings.home: 43222 newX = 0; 43223 newY = 0; 43224 break; 43225 case this.options.keyBindings.left: 43226 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 43227 break; 43228 case this.options.keyBindings.up: 43229 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 43230 break; 43231 case this.options.keyBindings.right: 43232 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 43233 break; 43234 case this.options.keyBindings.down: 43235 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 43236 break; 43237 default: 43238 return; 43239 } 43240 43241 if ( snap ) { 43242 this.goToPage(newX, newY); 43243 return; 43244 } 43245 43246 if ( newX > 0 ) { 43247 newX = 0; 43248 this.keyAcceleration = 0; 43249 } else if ( newX < this.maxScrollX ) { 43250 newX = this.maxScrollX; 43251 this.keyAcceleration = 0; 43252 } 43253 43254 if ( newY > 0 ) { 43255 newY = 0; 43256 this.keyAcceleration = 0; 43257 } else if ( newY < this.maxScrollY ) { 43258 newY = this.maxScrollY; 43259 this.keyAcceleration = 0; 43260 } 43261 43262 this.scrollTo(newX, newY, 0); 43263 43264 this.keyTime = now; 43265 }, 43266 43267 _animate: function (destX, destY, duration, easingFn) { 43268 var that = this, 43269 startX = this.x, 43270 startY = this.y, 43271 startTime = utils.getTime(), 43272 destTime = startTime + duration; 43273 43274 function step () { 43275 var now = utils.getTime(), 43276 newX, newY, 43277 easing; 43278 43279 if ( now >= destTime ) { 43280 that.isAnimating = false; 43281 that._translate(destX, destY); 43282 43283 if ( !that.resetPosition(that.options.bounceTime) ) { 43284 that._execEvent('scrollEnd'); 43285 } 43286 43287 return; 43288 } 43289 43290 now = ( now - startTime ) / duration; 43291 easing = easingFn(now); 43292 newX = ( destX - startX ) * easing + startX; 43293 newY = ( destY - startY ) * easing + startY; 43294 that._translate(newX, newY); 43295 43296 if ( that.isAnimating ) { 43297 rAF(step); 43298 } 43299 } 43300 43301 this.isAnimating = true; 43302 step(); 43303 }, 43304 handleEvent: function (e) { 43305 switch ( e.type ) { 43306 case 'touchstart': 43307 case 'pointerdown': 43308 case 'MSPointerDown': 43309 case 'mousedown': 43310 this._start(e); 43311 break; 43312 case 'touchmove': 43313 case 'pointermove': 43314 case 'MSPointerMove': 43315 case 'mousemove': 43316 this._move(e); 43317 break; 43318 case 'touchend': 43319 case 'pointerup': 43320 case 'MSPointerUp': 43321 case 'mouseup': 43322 case 'touchcancel': 43323 case 'pointercancel': 43324 case 'MSPointerCancel': 43325 case 'mousecancel': 43326 this._end(e); 43327 break; 43328 case 'orientationchange': 43329 case 'resize': 43330 this._resize(); 43331 break; 43332 case 'transitionend': 43333 case 'webkitTransitionEnd': 43334 case 'oTransitionEnd': 43335 case 'MSTransitionEnd': 43336 this._transitionEnd(e); 43337 break; 43338 case 'wheel': 43339 case 'DOMMouseScroll': 43340 case 'mousewheel': 43341 this._wheel(e); 43342 break; 43343 case 'keydown': 43344 this._key(e); 43345 break; 43346 case 'click': 43347 if ( this.enabled && !e._constructed ) { 43348 e.preventDefault(); 43349 e.stopPropagation(); 43350 } 43351 break; 43352 } 43353 } 43354}; 43355function createDefaultScrollbar (direction, interactive, type) { 43356 var scrollbar = document.createElement('div'), 43357 indicator = document.createElement('div'); 43358 43359 if ( type === true ) { 43360 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 43361 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'; 43362 } 43363 43364 indicator.className = 'iScrollIndicator'; 43365 43366 if ( direction == 'h' ) { 43367 if ( type === true ) { 43368 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 43369 indicator.style.height = '100%'; 43370 } 43371 scrollbar.className = 'iScrollHorizontalScrollbar'; 43372 } else { 43373 if ( type === true ) { 43374 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 43375 indicator.style.width = '100%'; 43376 } 43377 scrollbar.className = 'iScrollVerticalScrollbar'; 43378 } 43379 43380 scrollbar.style.cssText += ';overflow:hidden'; 43381 43382 if ( !interactive ) { 43383 scrollbar.style.pointerEvents = 'none'; 43384 } 43385 43386 scrollbar.appendChild(indicator); 43387 43388 return scrollbar; 43389} 43390 43391function Indicator (scroller, options) { 43392 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 43393 this.wrapperStyle = this.wrapper.style; 43394 this.indicator = this.wrapper.children[0]; 43395 this.indicatorStyle = this.indicator.style; 43396 this.scroller = scroller; 43397 43398 this.options = { 43399 listenX: true, 43400 listenY: true, 43401 interactive: false, 43402 resize: true, 43403 defaultScrollbars: false, 43404 shrink: false, 43405 fade: false, 43406 speedRatioX: 0, 43407 speedRatioY: 0 43408 }; 43409 43410 for ( var i in options ) { 43411 this.options[i] = options[i]; 43412 } 43413 43414 this.sizeRatioX = 1; 43415 this.sizeRatioY = 1; 43416 this.maxPosX = 0; 43417 this.maxPosY = 0; 43418 43419 if ( this.options.interactive ) { 43420 if ( !this.options.disableTouch ) { 43421 utils.addEvent(this.indicator, 'touchstart', this); 43422 utils.addEvent(window, 'touchend', this); 43423 } 43424 if ( !this.options.disablePointer ) { 43425 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 43426 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 43427 } 43428 if ( !this.options.disableMouse ) { 43429 utils.addEvent(this.indicator, 'mousedown', this); 43430 utils.addEvent(window, 'mouseup', this); 43431 } 43432 } 43433 43434 if ( this.options.fade ) { 43435 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 43436 var durationProp = utils.style.transitionDuration; 43437 if(!durationProp) { 43438 return; 43439 } 43440 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 43441 // remove 0.0001ms 43442 var self = this; 43443 if(utils.isBadAndroid) { 43444 rAF(function() { 43445 if(self.wrapperStyle[durationProp] === '0.0001ms') { 43446 self.wrapperStyle[durationProp] = '0s'; 43447 } 43448 }); 43449 } 43450 this.wrapperStyle.opacity = '0'; 43451 } 43452} 43453 43454Indicator.prototype = { 43455 handleEvent: function (e) { 43456 switch ( e.type ) { 43457 case 'touchstart': 43458 case 'pointerdown': 43459 case 'MSPointerDown': 43460 case 'mousedown': 43461 this._start(e); 43462 break; 43463 case 'touchmove': 43464 case 'pointermove': 43465 case 'MSPointerMove': 43466 case 'mousemove': 43467 this._move(e); 43468 break; 43469 case 'touchend': 43470 case 'pointerup': 43471 case 'MSPointerUp': 43472 case 'mouseup': 43473 case 'touchcancel': 43474 case 'pointercancel': 43475 case 'MSPointerCancel': 43476 case 'mousecancel': 43477 this._end(e); 43478 break; 43479 } 43480 }, 43481 43482 destroy: function () { 43483 if ( this.options.fadeScrollbars ) { 43484 clearTimeout(this.fadeTimeout); 43485 this.fadeTimeout = null; 43486 } 43487 if ( this.options.interactive ) { 43488 utils.removeEvent(this.indicator, 'touchstart', this); 43489 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 43490 utils.removeEvent(this.indicator, 'mousedown', this); 43491 43492 utils.removeEvent(window, 'touchmove', this); 43493 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 43494 utils.removeEvent(window, 'mousemove', this); 43495 43496 utils.removeEvent(window, 'touchend', this); 43497 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 43498 utils.removeEvent(window, 'mouseup', this); 43499 } 43500 43501 if ( this.options.defaultScrollbars ) { 43502 this.wrapper.parentNode.removeChild(this.wrapper); 43503 } 43504 }, 43505 43506 _start: function (e) { 43507 var point = e.touches ? e.touches[0] : e; 43508 43509 e.preventDefault(); 43510 e.stopPropagation(); 43511 43512 this.transitionTime(); 43513 43514 this.initiated = true; 43515 this.moved = false;
43516 this.lastPointX = point.pageX; 43517 this.lastPointY = point.pageY; 43518 43519 this.startTime = utils.getTime(); 43520 43521 if ( !this.options.disableTouch ) { 43522 utils.addEvent(window, 'touchmove', this); 43523 } 43524 if ( !this.options.disablePointer ) { 43525 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 43526 } 43527 if ( !this.options.disableMouse ) { 43528 utils.addEvent(window, 'mousemove', this); 43529 } 43530 43531 this.scroller._execEvent('beforeScrollStart'); 43532 }, 43533 43534 _move: function (e) { 43535 var point = e.touches ? e.touches[0] : e, 43536 deltaX, deltaY, 43537 newX, newY, 43538 timestamp = utils.getTime(); 43539 43540 if ( !this.moved ) { 43541 this.scroller._execEvent('scrollStart'); 43542 } 43543 43544 this.moved = true; 43545 43546 deltaX = point.pageX - this.lastPointX; 43547 this.lastPointX = point.pageX; 43548 43549 deltaY = point.pageY - this.lastPointY; 43550 this.lastPointY = point.pageY; 43551 43552 newX = this.x + deltaX; 43553 newY = this.y + deltaY; 43554 43555 this._pos(newX, newY); 43556 43557// INSERT POINT: indicator._move 43558 43559 e.preventDefault(); 43560 e.stopPropagation(); 43561 }, 43562 43563 _end: function (e) { 43564 if ( !this.initiated ) { 43565 return; 43566 } 43567 43568 this.initiated = false; 43569 43570 e.preventDefault(); 43571 e.stopPropagation(); 43572 43573 utils.removeEvent(window, 'touchmove', this); 43574 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 43575 utils.removeEvent(window, 'mousemove', this); 43576 43577 if ( this.scroller.options.snap ) { 43578 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 43579 43580 var time = this.options.snapSpeed || Math.max( 43581 Math.max( 43582 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 43583 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 43584 ), 300); 43585 43586 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 43587 this.scroller.directionX = 0; 43588 this.scroller.directionY = 0; 43589 this.scroller.currentPage = snap; 43590 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 43591 } 43592 } 43593 43594 if ( this.moved ) { 43595 this.scroller._execEvent('scrollEnd'); 43596 } 43597 }, 43598 43599 transitionTime: function (time) { 43600 time = time || 0; 43601 var durationProp = utils.style.transitionDuration; 43602 if(!durationProp) { 43603 return; 43604 } 43605 43606 this.indicatorStyle[durationProp] = time + 'ms'; 43607 43608 if ( !time && utils.isBadAndroid ) { 43609 this.indicatorStyle[durationProp] = '0.0001ms'; 43610 // remove 0.0001ms 43611 var self = this; 43612 rAF(function() { 43613 if(self.indicatorStyle[durationProp] === '0.0001ms') { 43614 self.indicatorStyle[durationProp] = '0s'; 43615 } 43616 }); 43617 } 43618 }, 43619 43620 transitionTimingFunction: function (easing) { 43621 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 43622 }, 43623 43624 refresh: function () { 43625 this.transitionTime(); 43626 43627 if ( this.options.listenX && !this.options.listenY ) { 43628 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 43629 } else if ( this.options.listenY && !this.options.listenX ) { 43630 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 43631 } else { 43632 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 43633 } 43634 43635 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 43636 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 43637 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 43638 43639 if ( this.options.defaultScrollbars && this.options.customStyle ) { 43640 if ( this.options.listenX ) { 43641 this.wrapper.style.right = '8px'; 43642 } else { 43643 this.wrapper.style.bottom = '8px'; 43644 } 43645 } 43646 } else { 43647 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 43648 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 43649 43650 if ( this.options.defaultScrollbars && this.options.customStyle ) { 43651 if ( this.options.listenX ) { 43652 this.wrapper.style.right = '2px'; 43653 } else { 43654 this.wrapper.style.bottom = '2px'; 43655 } 43656 } 43657 } 43658 43659 var r = this.wrapper.offsetHeight; // force refresh 43660 43661 if ( this.options.listenX ) {
43662 this.wrapperWidth = this.wrapper.clientWidth; 43663 if ( this.options.resize ) { 43664 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 43665 this.indicatorStyle.width = this.indicatorWidth + 'px'; 43666 } else { 43667 this.indicatorWidth = this.indicator.clientWidth; 43668 } 43669 43670 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 43671 43672 if ( this.options.shrink == 'clip' ) { 43673 this.minBoundaryX = -this.indicatorWidth + 8; 43674 this.maxBoundaryX = this.wrapperWidth - 8; 43675 } else { 43676 this.minBoundaryX = 0; 43677 this.maxBoundaryX = this.maxPosX; 43678 } 43679 43680 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 43681 } 43682 43683 if ( this.options.listenY ) { 43684 this.wrapperHeight = this.wrapper.clientHeight; 43685 if ( this.options.resize ) { 43686 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 43687 this.indicatorStyle.height = this.indicatorHeight + 'px'; 43688 } else { 43689 this.indicatorHeight = this.indicator.clientHeight; 43690 } 43691 43692 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 43693 43694 if ( this.options.shrink == 'clip' ) { 43695 this.minBoundaryY = -this.indicatorHeight + 8; 43696 this.maxBoundaryY = this.wrapperHeight - 8; 43697 } else { 43698 this.minBoundaryY = 0; 43699 this.maxBoundaryY = this.maxPosY; 43700 } 43701 43702 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 43703 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 43704 } 43705 43706 this.updatePosition(); 43707 }, 43708 43709 updatePosition: function () { 43710 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 43711 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 43712 43713 if ( !this.options.ignoreBoundaries ) { 43714 if ( x < this.minBoundaryX ) { 43715 if ( this.options.shrink == 'scale' ) { 43716 this.width = Math.max(this.indicatorWidth + x, 8); 43717 this.indicatorStyle.width = this.width + 'px'; 43718 } 43719 x = this.minBoundaryX; 43720 } else if ( x > this.maxBoundaryX ) { 43721 if ( this.options.shrink == 'scale' ) { 43722 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 43723 this.indicatorStyle.width = this.width + 'px'; 43724 x = this.maxPosX + this.indicatorWidth - this.width; 43725 } else { 43726 x = this.maxBoundaryX; 43727 } 43728 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 43729 this.width = this.indicatorWidth; 43730 this.indicatorStyle.width = this.width + 'px'; 43731 } 43732 43733 if ( y < this.minBoundaryY ) { 43734 if ( this.options.shrink == 'scale' ) { 43735 this.height = Math.max(this.indicatorHeight + y * 3, 8); 43736 this.indicatorStyle.height = this.height + 'px'; 43737 } 43738 y = this.minBoundaryY; 43739 } else if ( y > this.maxBoundaryY ) { 43740 if ( this.options.shrink == 'scale' ) { 43741 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 43742 this.indicatorStyle.height = this.height + 'px'; 43743 y = this.maxPosY + this.indicatorHeight - this.height; 43744 } else { 43745 y = this.maxBoundaryY; 43746 } 43747 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 43748 this.height = this.indicatorHeight; 43749 this.indicatorStyle.height = this.height + 'px'; 43750 } 43751 } 43752 43753 this.x = x; 43754 this.y = y; 43755 43756 if ( this.scroller.options.useTransform ) { 43757 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 43758 } else { 43759 this.indicatorStyle.left = x + 'px'; 43760 this.indicatorStyle.top = y + 'px'; 43761 } 43762 }, 43763 43764 _pos: function (x, y) { 43765 if ( x < 0 ) { 43766 x = 0; 43767 } else if ( x > this.maxPosX ) { 43768 x = this.maxPosX; 43769 } 43770 43771 if ( y < 0 ) { 43772 y = 0; 43773 } else if ( y > this.maxPosY ) { 43774 y = this.maxPosY;
43775 } 43776 43777 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 43778 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 43779 43780 this.scroller.scrollTo(x, y); 43781 }, 43782 43783 fade: function (val, hold) { 43784 if ( hold && !this.visible ) { 43785 return; 43786 } 43787 43788 clearTimeout(this.fadeTimeout); 43789 this.fadeTimeout = null; 43790 43791 var time = val ? 250 : 500, 43792 delay = val ? 0 : 300; 43793 43794 val = val ? '1' : '0'; 43795 43796 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 43797 43798 this.fadeTimeout = setTimeout((function (val) { 43799 this.wrapperStyle.opacity = val; 43800 this.visible = +val; 43801 }).bind(this, val), delay); 43802 } 43803}; 43804 43805IScroll.utils = utils; 43806 43807if ( typeof module != 'undefined' && module.exports ) { 43808 module.exports = IScroll; 43809} else if ( typeof define == 'function' && define.amd ) { 43810 define( function () { return IScroll; } ); 43811} else { 43812 window.IScroll = IScroll; 43813} 43814 43815})(window, document, Math); 43816/*! 43817 * fullPage 2.9.4 43818 * https://github.com/alvarotrigo/fullPage.js 43819 * @license MIT licensed 43820 * 43821 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 43822 */ 43823(function(global, factory) { 43824 'use strict'; 43825 if (typeof define === 'function' && define.amd) { 43826 define(['jquery'], function($) { 43827 return factory($, global, global.document, global.Math); 43828 }); 43829 } else if (typeof exports === "object" && exports) { 43830 module.exports = factory(require('jquery'), global, global.document, global.Math); 43831 } else { 43832 factory(jQuery, global, global.document, global.Math); 43833 } 43834})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 43835 'use strict'; 43836 43837 // keeping central set of classnames and selectors 43838 var WRAPPER = 'fullpage-wrapper'; 43839 var WRAPPER_SEL = '.' + WRAPPER; 43840 43841 // slimscroll 43842 var SCROLLABLE = 'fp-scrollable'; 43843 var SCROLLABLE_SEL = '.' + SCROLLABLE; 43844 43845 // util 43846 var RESPONSIVE = 'fp-responsive'; 43847 var NO_TRANSITION = 'fp-notransition'; 43848 var DESTROYED = 'fp-destroyed'; 43849 var ENABLED = 'fp-enabled'; 43850 var VIEWING_PREFIX = 'fp-viewing'; 43851 var ACTIVE = 'active'; 43852 var ACTIVE_SEL = '.' + ACTIVE; 43853 var COMPLETELY = 'fp-completely'; 43854 var COMPLETELY_SEL = '.' + COMPLETELY; 43855 43856 // section 43857 var SECTION_DEFAULT_SEL = '.section'; 43858 var SECTION = 'fp-section'; 43859 var SECTION_SEL = '.' + SECTION; 43860 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 43861 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 43862 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 43863 var TABLE_CELL = 'fp-tableCell'; 43864 var TABLE_CELL_SEL = '.' + TABLE_CELL; 43865 var AUTO_HEIGHT = 'fp-auto-height'; 43866 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 43867 var NORMAL_SCROLL = 'fp-normal-scroll'; 43868 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 43869 43870 // section nav 43871 var SECTION_NAV = 'fp-nav'; 43872 var SECTION_NAV_SEL = '#' + SECTION_NAV; 43873 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 43874 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 43875 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 43876 43877 // slide 43878 var SLIDE_DEFAULT_SEL = '.slide'; 43879 var SLIDE = 'fp-slide'; 43880 var SLIDE_SEL = '.' + SLIDE; 43881 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 43882 var SLIDES_WRAPPER = 'fp-slides'; 43883 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 43884 var SLIDES_CONTAINER = 'fp-slidesContainer'; 43885 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 43886 var TABLE = 'fp-table'; 43887 43888 // slide nav 43889 var SLIDES_NAV = 'fp-slidesNav'; 43890 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 43891 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 43892 var SLIDES_ARROW = 'fp-controlArrow'; 43893 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 43894 var SLIDES_PREV = 'fp-prev'; 43895 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 43896 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 43897 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 43898 var SLIDES_NEXT = 'fp-next';
43899 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 43900 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 43901 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 43902 43903 var $window = $(window); 43904 var $document = $(document); 43905 43906 // Default options for iScroll.js used when using scrollOverflow 43907 var iscrollOptions = { 43908 scrollbars: true, 43909 mouseWheel: true, 43910 hideScrollbars: false, 43911 fadeScrollbars: false, 43912 disableMouse: true, 43913 interactiveScrollbars: true, 43914 bounce: false, 43915 }; 43916 43917 $.fn.fullpage = function(options) { 43918 //only once my friend! 43919 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 43920 43921 // common jQuery objects 43922 var $htmlBody = $('html, body'); 43923 var $body = $('body'); 43924 43925 var FP = $.fn.fullpage; 43926 43927 // Creating some defaults, extending them with any options that were provided 43928 options = $.extend({ 43929 //navigation 43930 menu: false, 43931 anchors:[], 43932 lockAnchors: false, 43933 navigation: false, 43934 navigationPosition: 'right', 43935 navigationTooltips: [], 43936 showActiveTooltip: false, 43937 slidesNavigation: false, 43938 slidesNavPosition: 'bottom', 43939 scrollBar: false, 43940 hybrid: false, 43941 43942 //scrolling 43943 css3: true, 43944 scrollingSpeed: 700, 43945 autoScrolling: true, 43946 fitToSection: true, 43947 fitToSectionDelay: 1000, 43948 easing: 'easeInOutCubic', 43949 easingcss3: 'ease', 43950 loopBottom: false, 43951 loopTop: false, 43952 loopHorizontal: true, 43953 continuousVertical: false, 43954 continuousHorizontal: false, 43955 scrollHorizontally: false, 43956 interlockedSlides: false, 43957 dragAndMove: false, 43958 offsetSections: false, 43959 resetSliders: false, 43960 fadingEffect: false, 43961 normalScrollElements: null, 43962 scrollOverflow: false, 43963 scrollOverflowReset: false, 43964 scrollOverflowHandler: iscrollHandler, 43965 scrollOverflowOptions: null, 43966 touchSensitivity: 5, 43967 normalScrollElementTouchThreshold: 5, 43968 bigSectionsDestination: null, 43969 43970 //Accessibility 43971 keyboardScrolling: true, 43972 animateAnchor: true, 43973 recordHistory: true, 43974 43975 //design 43976 controlArrows: true, 43977 controlArrowColor: '#fff', 43978 verticalCentered: true, 43979 sectionsColor : [], 43980 paddingTop: 0, 43981 paddingBottom: 0, 43982 fixedElements: null, 43983 responsive: 0, //backwards compabitility with responsiveWiddth 43984 responsiveWidth: 0, 43985 responsiveHeight: 0, 43986 responsiveSlides: false, 43987 parallax: false, 43988 parallaxOptions: { 43989 type: 'reveal', 43990 percentage: 62, 43991 property: 'translate' 43992 }, 43993 43994 //Custom selectors 43995 sectionSelector: SECTION_DEFAULT_SEL, 43996 slideSelector: SLIDE_DEFAULT_SEL, 43997 43998 //events 43999 afterLoad: null, 44000 onLeave: null, 44001 afterRender: null, 44002 afterResize: null, 44003 afterReBuild: null, 44004 afterSlideLoad: null, 44005 onSlideLeave: null, 44006 afterResponsive: null, 44007 44008 lazyLoading: true 44009 }, options); 44010 44011 //flag to avoid very fast sliding for landscape sliders 44012 var slideMoving = false; 44013 44014 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 44015 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 44016 var container = $(this); 44017 var windowsHeight = $window.height(); 44018 var isResizing = false; 44019 var isWindowFocused = true; 44020 var lastScrolledDestiny; 44021 var lastScrolledSlide; 44022 var canScroll = true; 44023 var scrollings = []; 44024 var controlPressed; 44025 var startingSection; 44026 var isScrollAllowed = {}; 44027 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 44028 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 44029 var MSPointer = getMSPointer(); 44030 var events = { 44031 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 44032 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 44033 }; 44034 44035 //cheks for passive event support 44036 //added by Uncode from new fullPage updates 44037 var g_supportsPassive = false;
44038 try { 44039 var opts = Object.defineProperty({}, 'passive', { 44040 get: function() { 44041 g_supportsPassive = true; 44042 } 44043 }); 44044 window.addEventListener("testPassive", null, opts); 44045 window.removeEventListener("testPassive", null, opts); 44046 } catch (e) {} 44047 44048 //timeouts 44049 var resizeId; 44050 var afterSectionLoadsId; 44051 var afterSlideLoadsId; 44052 var scrollId; 44053 var scrollId2; 44054 var keydownId; 44055 var originals = $.extend(true, {}, options); //deep copy 44056 44057 //Uncode addition 44058 var $masthead = $('#masthead'); 44059 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 44060 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 44061 var bodyBorder = UNCODE.bodyBorder; 44062 var adminBarHeight = UNCODE.adminBarHeight; 44063 44064 displayWarnings(); 44065 44066 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 44067 iscrollOptions.click = isTouch; // see #2035 44068 44069 //extending iScroll options with the user custom ones 44070 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 44071 44072 //easeInOutCubic animation included in the plugin 44073 $.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;}}); 44074 44075 /** 44076 * Sets the autoScroll option. 44077 * It changes the scroll bar visibility and the history of the site as a result. 44078 */ 44079 function setAutoScrolling(value, type){ 44080 //removing the transformation 44081 if(!value){ 44082 silentScroll(0); 44083 } 44084 44085 setVariableState('autoScrolling', value, type); 44086 44087 var element = $(SECTION_ACTIVE_SEL); 44088 44089 if(options.autoScrolling && !options.scrollBar){ 44090 $htmlBody.css({ 44091 'overflow' : 'hidden !important', 44092 'height' : '100%' 44093 }); 44094 44095 //Uncode addition 44096 //setRecordHistory(originals.recordHistory, 'internal'); 44097 44098 //for IE touch devices 44099 container.css({ 44100 '-ms-touch-action': 'none', 44101 'touch-action': 'none' 44102 }); 44103 44104 if(element.length){ 44105 //moving the container up 44106 silentScroll(element.position().top); 44107 } 44108 44109 }else{ 44110 $htmlBody.css({ 44111 'overflow' : 'visible !important', 44112 'height' : 'initial' 44113 }); 44114 44115 //Uncode addition 44116 //setRecordHistory(false, 'internal'); 44117 44118 //for IE touch devices 44119 container.css({ 44120 '-ms-touch-action': '', 44121 'touch-action': '' 44122 }); 44123 44124 //scrolling the page to the section with no animation 44125 if (element.length) { 44126 $htmlBody.scrollTop(element.position().top); 44127 } 44128 } 44129 } 44130 44131 /** 44132 * Defines wheter to record the history for each hash change in the URL. 44133 */ 44134 function setRecordHistory(value, type){ 44135 setVariableState('recordHistory', value, type); 44136 } 44137 44138 /** 44139 * Defines the scrolling speed 44140 */ 44141 function setScrollingSpeed(value, type){ 44142 setVariableState('scrollingSpeed', value, type); 44143 } 44144 44145 /** 44146 * Sets fitToSection 44147 */ 44148 function setFitToSection(value, type){ 44149 setVariableState('fitToSection', value, type); 44150 } 44151 44152 /** 44153 * Sets lockAnchors 44154 */ 44155 function setLockAnchors(value){ 44156 options.lockAnchors = value; 44157 } 44158 44159 /** 44160 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 44161 */ 44162 function setMouseWheelScrolling(value){ 44163 if(value){ 44164 addMouseWheelHandler(); 44165 addMiddleWheelHandler(); 44166 }else{ 44167 removeMouseWheelHandler(); 44168 removeMiddleWheelHandler(); 44169 } 44170 } 44171 44172 /** 44173 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 44174 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 44175 * 44176 * @param directions string containing the direction or directions separated by comma. 44177 */ 44178 function setAllowScrolling(value, directions){ 44179 if(typeof directions !== 'undefined'){ 44180 directions = directions.replace(/ /g,'').split(','); 44181 44182 $.each(directions, function (index, direction){ 44183 setIsScrollAllowed(value, direction, 'm'); 44184 }); 44185 } 44186 else if(value){ 44187 setMouseWheelScrolling(true); 44188 addTouchHandler(); 44189 }else{ 44190 setMouseWheelScrolling(false); 44191 removeTouchHandler(); 44192 } 44193 } 44194 44195 /** 44196 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 44197 */ 44198 function setKeyboardScrolling(value, directions){ 44199 if(typeof directions !== 'undefined'){ 44200 directions = directions.replace(/ /g,'').split(','); 44201 44202 $.each(directions, function (index, direction){ 44203 setIsScrollAllowed(value, direction, 'k'); 44204 }); 44205 }else{ 44206 options.keyboardScrolling = value; 44207 } 44208 } 44209 44210 /** 44211 * Moves the page up one section. 44212 */ 44213 function moveSectionUp(){ 44214 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 44215 44216 //looping to the bottom if there's no more sections above 44217 if (!prev.length && (options.loopTop || options.continuousVertical)) {
44218 prev = $(SECTION_SEL).last(); 44219 } 44220 44221 if (prev.length) { 44222 scrollPage(prev, null, true); 44223 } 44224 } 44225 44226 /** 44227 * Moves the page down one section. 44228 */ 44229 function moveSectionDown(){ 44230 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 44231 44232 //looping to the top if there's no more sections below 44233 if(!next.length && 44234 (options.loopBottom || options.continuousVertical)){ 44235 next = $(SECTION_SEL).first(); 44236 } 44237 44238 if(next.length){ 44239 scrollPage(next, null, false); 44240 } 44241 } 44242 44243 /** 44244 * Moves the page to the given section and slide with no animation. 44245 * Anchors or index positions can be used as params. 44246 */ 44247 function silentMoveTo(sectionAnchor, slideAnchor){ 44248 setScrollingSpeed (0, 'internal'); 44249 moveTo(sectionAnchor, slideAnchor); 44250 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 44251 } 44252 44253 /** 44254 * Moves the page to the given section and slide. 44255 * Anchors or index positions can be used as params. 44256 */ 44257 function moveTo(sectionAnchor, slideAnchor){ 44258 var destiny = getSectionByAnchor(sectionAnchor); 44259 44260 if (typeof slideAnchor !== 'undefined'){ 44261 scrollPageAndSlide(sectionAnchor, slideAnchor); 44262 }else if(destiny.length > 0){ 44263 scrollPage(destiny); 44264 } 44265 } 44266 44267 /** 44268 * Slides right the slider of the active section. 44269 * Optional `section` param. 44270 */ 44271 function moveSlideRight(section){ 44272 moveSlide('right', section); 44273 } 44274 44275 /** 44276 * Slides left the slider of the active section. 44277 * Optional `section` param. 44278 */ 44279 function moveSlideLeft(section){ 44280 moveSlide('left', section); 44281 } 44282 44283 /** 44284 * When resizing is finished, we adjust the slides sizes and positions 44285 */ 44286 function reBuild(resizing){ 44287 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 44288 44289 isResizing = true; 44290 44291 windowsHeight = $window.height(); //updating global var 44292 44293 $(SECTION_SEL).each(function(){ 44294 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 44295 var slides = $(this).find(SLIDE_SEL); 44296 44297 //adjusting the height of the table-cell for IE and Firefox 44298 if(options.verticalCentered){ 44299 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 44300 } 44301 44302 $(this).css('height', windowsHeight + 'px'); 44303 44304 //resizing the scrolling divs 44305 if(options.scrollOverflow){ 44306 if(slides.length){ 44307 slides.each(function(){ 44308 createScrollBar($(this)); 44309 }); 44310 }else{ 44311 createScrollBar($(this)); 44312 } 44313 } 44314 44315 //adjusting the position fo the FULL WIDTH slides... 44316 if (slides.length > 1) { 44317 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 44318 } 44319 }); 44320 44321 var activeSection = $(SECTION_ACTIVE_SEL); 44322 var sectionIndex = activeSection.index(SECTION_SEL); 44323 44324 //isn't it the first section? 44325 if(sectionIndex){ 44326 //adjusting the position for the current section 44327 silentMoveTo(sectionIndex + 1); 44328 } 44329 44330 isResizing = false; 44331 // Uncode change 44332 // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 44333 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight()); 44334 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 44335 } 44336 44337 /** 44338 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 44339 * are smaller than the set limit values. 44340 */ 44341 function setResponsive(active){ 44342 var isResponsive = $body.hasClass(RESPONSIVE); 44343 44344 if(active){ 44345 if(!isResponsive){ 44346 setAutoScrolling(false, 'internal'); 44347 setFitToSection(false, 'internal'); 44348 $(SECTION_NAV_SEL).hide(); 44349 $body.addClass(RESPONSIVE); 44350 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 44351 } 44352 } 44353 else if(isResponsive){ 44354 setAutoScrolling(originals.autoScrolling, 'internal'); 44355 setFitToSection(originals.autoScrolling, 'internal'); 44356 $(SECTION_NAV_SEL).show(); 44357 $body.removeClass(RESPONSIVE); 44358 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 44359 } 44360 } 44361 44362 if($(this).length){ 44363 //public functions 44364 FP.setAutoScrolling = setAutoScrolling; 44365 FP.setRecordHistory = setRecordHistory; 44366 FP.setScrollingSpeed = setScrollingSpeed; 44367 FP.setFitToSection = setFitToSection; 44368 FP.setLockAnchors = setLockAnchors; 44369 FP.setMouseWheelScrolling = setMouseWheelScrolling; 44370 FP.setAllowScrolling = setAllowScrolling; 44371 FP.setKeyboardScrolling = setKeyboardScrolling; 44372 FP.moveSectionUp = moveSectionUp; 44373 FP.moveSectionDown = moveSectionDown; 44374 FP.silentMoveTo = silentMoveTo; 44375 FP.moveTo = moveTo; 44376 FP.moveSlideRight = moveSlideRight; 44377 FP.moveSlideLeft = moveSlideLeft; 44378 FP.fitToSection = fitToSection; 44379 FP.reBuild = reBuild; 44380 FP.setResponsive = setResponsive; 44381 FP.destroy = destroy; 44382 44383 init(); 44384 44385 bindEvents(); 44386 } 44387
44388 function init(){ 44389 //if css3 is not supported, it will use jQuery animations 44390 if(options.css3){ 44391 options.css3 = support3d(); 44392 } 44393 44394 options.scrollBar = options.scrollBar || options.hybrid; 44395 44396 setOptionsFromDOM(); 44397 prepareDom(); 44398 setAllowScrolling(true); 44399 setAutoScrolling(options.autoScrolling, 'internal'); 44400 responsive(); 44401 44402 //setting the class for the body element 44403 setBodyClass(); 44404 44405 //Uncode addition 44406 // if(document.readyState === 'complete'){ 44407 // scrollToAnchor(); 44408 // } 44409 // $window.on('load', scrollToAnchor); 44410 } 44411 44412 function bindEvents(){ 44413 $window 44414 //when scrolling... 44415 //.on('scroll', scrollHandler) 44416 44417 //detecting any change on the URL to scroll to the given anchor link 44418 //(a way to detect back history button as we play with the hashes on the URL) 44419 .on('hashchange', hashChangeHandler) 44420 44421 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 44422 .blur(blurHandler) 44423 44424 //when resizing the site, we adjust the heights of the sections, slimScroll... 44425 .resize(resizeHandler); 44426 44427 $document 44428 //Sliding with arrow keys, both, vertical and horizontal 44429 .keydown(keydownHandler) 44430 44431 //to prevent scrolling while zooming 44432 .keyup(keyUpHandler) 44433 44434 //Scrolls to the section when clicking the navigation bullet 44435 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 44436 44437 //Scrolls the slider to the given slide destination for the given section 44438 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 44439 44440 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 44441 44442 //Scrolling horizontally when clicking on the slider controls. 44443 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 44444 44445 /** 44446 * Applying normalScroll elements. 44447 * Ignoring the scrolls over the specified selectors. 44448 */ 44449 if(options.normalScrollElements){ 44450 $document.on('mouseenter', options.normalScrollElements, function () { 44451 setMouseWheelScrolling(false); 44452 }); 44453 44454 $document.on('mouseleave', options.normalScrollElements, function(){ 44455 setMouseWheelScrolling(true); 44456 }); 44457 } 44458 } 44459 44460 /** 44461 * Setting options from DOM elements if they are not provided. 44462 */ 44463 function setOptionsFromDOM(){ 44464 var sections = container.find(options.sectionSelector); 44465 44466 //no anchors option? Checking for them in the DOM attributes 44467 if(!options.anchors.length){ 44468 options.anchors = sections.filter('[data-anchor]').map(function(){ 44469 return $(this).data('anchor').toString(); 44470 }).get(); 44471 } 44472 44473 //no tooltips option? Checking for them in the DOM attributes 44474 if(!options.navigationTooltips.length){ 44475 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 44476 return $(this).data('tooltip').toString(); 44477 }).get(); 44478 } 44479 } 44480 44481 /** 44482 * Works over the DOM structure to set it up for the current fullpage options. 44483 */ 44484 function prepareDom(){ 44485 container.css({ 44486 'height': '100%', 44487 'position': 'relative' 44488 }); 44489 44490 //adding a class to recognize the container internally in the code 44491 container.addClass(WRAPPER); 44492 $('html').addClass(ENABLED); 44493 44494 windowsHeight = $window.height(); 44495 44496 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 44497 44498 addInternalSelectors(); 44499 44500 //styling the sections / slides / menu 44501 $(SECTION_SEL).each(function(index){ 44502 var section = $(this); 44503 var slides = section.find(SLIDE_SEL); 44504 var numSlides = slides.length; 44505 44506 styleSection(section, index); 44507 styleMenu(section, index); 44508 44509 // if there's any slide 44510 if (numSlides > 0) { 44511 styleSlides(section, slides, numSlides); 44512 }else{ 44513 if(options.verticalCentered){ 44514 addTableClass(section); 44515 } 44516 } 44517 }); 44518 44519 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 44520 if(options.fixedElements && options.css3){ 44521 $(options.fixedElements).appendTo($body); 44522 } 44523 44524 //vertical centered of the navigation + active bullet 44525 if(options.navigation){ 44526 addVerticalNavigation(); 44527 } 44528 44529 enableYoutubeAPI(); 44530 44531 if(options.scrollOverflow){ 44532 if(document.readyState === 'complete'){ 44533 createScrollBarHandler(); 44534 } 44535 //after DOM and images are loaded 44536 $window.on('load', createScrollBarHandler); 44537 }else{ 44538 afterRenderActions(); 44539 } 44540 } 44541 44542 /** 44543 * Styles the horizontal slides for a section. 44544 */ 44545 function styleSlides(section, slides, numSlides){ 44546 var sliderWidth = numSlides * 100; 44547 var slideWidth = 100 / numSlides; 44548 44549 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 44550 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 44551 44552 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 44553 44554 if(numSlides > 1){ 44555 if(options.controlArrows){ 44556 createSlideArrows(section); 44557 } 44558 44559 if(options.slidesNavigation){ 44560 addSlidesNavigation(section, numSlides); 44561 } 44562 } 44563 44564 slides.each(function(index) { 44565 $(this).css('width', slideWidth + '%'); 44566 44567 if(options.verticalCentered){ 44568 addTableClass($(this)); 44569 } 44570 }); 44571 44572 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 44573 44574 //if the slide won't be an starting point, the default will be the first one 44575 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
44575ide by default. 44576 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 44577 silentLandscapeScroll(startingSlide, 'internal'); 44578 }else{ 44579 slides.eq(0).addClass(ACTIVE); 44580 } 44581 } 44582 44583 /** 44584 * Styling vertical sections 44585 */ 44586 function styleSection(section, index){ 44587 //if no active section is defined, the 1st one will be the default one 44588 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 44589 section.addClass(ACTIVE); 44590 } 44591 startingSection = $(SECTION_ACTIVE_SEL); 44592 44593 section.css('height', windowsHeight + 'px'); 44594 44595 if(options.paddingTop){ 44596 section.css('padding-top', options.paddingTop); 44597 } 44598 44599 if(options.paddingBottom){ 44600 section.css('padding-bottom', options.paddingBottom); 44601 } 44602 44603 if (typeof options.sectionsColor[index] !== 'undefined') { 44604 section.css('background-color', options.sectionsColor[index]); 44605 } 44606 44607 if (typeof options.anchors[index] !== 'undefined') { 44608 section.attr('data-anchor', options.anchors[index]); 44609 } 44610 } 44611 44612 /** 44613 * Sets the data-anchor attributes to the menu elements and activates the current one. 44614 */ 44615 function styleMenu(section, index){ 44616 if (typeof options.anchors[index] !== 'undefined') { 44617 //activating the menu / nav element on load 44618 if(section.hasClass(ACTIVE)){ 44619 activateMenuAndNav(options.anchors[index], index); 44620 } 44621 } 44622 44623 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 44624 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 44625 $(options.menu).appendTo($body); 44626 } 44627 } 44628 44629 /** 44630 * Adds internal classes to be able to provide customizable selectors 44631 * keeping the link with the style sheet. 44632 */ 44633 function addInternalSelectors(){ 44634 container.find(options.sectionSelector).addClass(SECTION); 44635 container.find(options.slideSelector).addClass(SLIDE); 44636 } 44637 44638 /** 44639 * Creates the control arrows for the given section 44640 */ 44641 function createSlideArrows(section){ 44642 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 44643 44644 if(options.controlArrowColor!='#fff'){ 44645 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 44646 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 44647 } 44648 44649 if(!options.loopHorizontal){ 44650 section.find(SLIDES_ARROW_PREV_SEL).hide(); 44651 } 44652 } 44653 44654 /** 44655 * Creates a vertical navigation bar. 44656 */ 44657 function addVerticalNavigation(){ 44658 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 44659 var nav = $(SECTION_NAV_SEL); 44660 44661 nav.addClass(function() { 44662 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 44663 }); 44664 44665 for (var i = 0; i < $(SECTION_SEL).length; i++) { 44666 var link = ''; 44667 if (options.anchors.length) { 44668 link = options.anchors[i]; 44669 } 44670 44671 var li = '<li><a href="#' + link + '"><span></span></a>'; 44672 44673 // Only add tooltip if needed (defined by user) 44674 var tooltip = options.navigationTooltips[i]; 44675 44676 if (typeof tooltip !== 'undefined' && tooltip !== '') { 44677 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 44678 } 44679 44680 li += '</li>'; 44681 44682 nav.find('ul').append(li); 44683 } 44684 44685 //centering it vertically 44686 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 44687 44688 //activating the current active section 44689 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 44690 } 44691 44692 /** 44693 * Creates the slim scroll scrollbar for the sections and slides inside them. 44694 */ 44695 function createScrollBarHandler(){ 44696 $(SECTION_SEL).each(function(){ 44697 var slides = $(this).find(SLIDE_SEL); 44698 44699 if(slides.length){ 44700 slides.each(function(){ 44701 createScrollBar($(this)); 44702 }); 44703 }else{ 44704 createScrollBar($(this)); 44705 } 44706 44707 }); 44708 afterRenderActions(); 44709 } 44710 44711 /*
44712 * Enables the Youtube videos API so we can control their flow if necessary. 44713 */ 44714 function enableYoutubeAPI(){ 44715 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 44716 addURLParam($(this), 'enablejsapi=1'); 44717 }); 44718 } 44719 44720 /** 44721 * Adds a new parameter and its value to the `src` of a given element 44722 */ 44723 function addURLParam(element, newParam){ 44724 var originalSrc = element.attr('src'); 44725 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 44726 } 44727 44728 /* 44729 * Returns the prefix sign to use for a new parameter in an existen URL. 44730 * 44731 * @return {String} ? | & 44732 */ 44733 function getUrlParamSign(url){ 44734 return ( !/\?/.test( url ) ) ? '?' : '&'; 44735 } 44736 44737 /** 44738 * Actions and callbacks to fire afterRender 44739 */ 44740 function afterRenderActions(){ 44741 var section = $(SECTION_ACTIVE_SEL); 44742 44743 section.addClass(COMPLETELY); 44744 44745 if(options.scrollOverflowHandler.afterRender){ 44746 options.scrollOverflowHandler.afterRender(section); 44747 } 44748 lazyLoad(section); 44749 playMedia(section); 44750 options.scrollOverflowHandler.afterLoad(); 44751 44752 if(isDestinyTheStartingSection()){ 44753 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 44754 } 44755 44756 // Uncode change 44757 // $.isFunction( options.afterRender ) && options.afterRender.call(container); 44758 $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight()); 44759 } 44760 44761 /** 44762 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 44763 */ 44764 function isDestinyTheStartingSection(){ 44765 var anchors = window.location.hash.replace('#', '').split('/'); 44766 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 44767 44768 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 44769 } 44770 44771 44772 var isScrolling = false; 44773 var lastScroll = 0; 44774 44775 //when scrolling... 44776 function scrollHandler(){ 44777 var currentSection; 44778 44779 if(!options.autoScrolling || options.scrollBar){ 44780 var currentScroll = $window.scrollTop(); 44781 var scrollDirection = getScrollDirection(currentScroll); 44782 var visibleSectionIndex = 0; 44783 var screen_mid = currentScroll + ($window.height() / 2.0); 44784 var isAtBottom = $body.height() - $window.height() === currentScroll; 44785 var sections = document.querySelectorAll(SECTION_SEL); 44786 44787 //when using `auto-height` for a small last section it won't be centered in the viewport 44788 if(isAtBottom){ 44789 visibleSectionIndex = sections.length - 1; 44790 } 44791 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 44792 else if(!currentScroll){ 44793 visibleSectionIndex = 0; 44794 } 44795 44796 //taking the section which is showing more content in the viewport 44797 else{ 44798 for (var i = 0; i < sections.length; ++i) { 44799 var section = sections[i]; 44800 44801 // Pick the the last section which passes the middle line of the screen. 44802 if (section.offsetTop <= screen_mid) 44803 { 44804 visibleSectionIndex = i; 44805 } 44806 } 44807 } 44808 44809 if(isCompletelyInViewPort(scrollDirection)){ 44810 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 44811 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 44812 } 44813 } 44814 44815 //geting the last one, the current one on the screen 44816 currentSection = $(sections).eq(visibleSectionIndex); 44817 44818 //setting the visible section as active when manually scrolling 44819 //executing only once the first time we reach the section 44820 if(!currentSection.hasClass(ACTIVE)){ 44821 isScrolling = true; 44822 var leavingSection = $(SECTION_ACTIVE_SEL); 44823 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 44824 var yMovement = getYmovement(currentSection); 44825 var anchorLink = currentSection.data('anchor'); 44826 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 44827 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 44828 var slideIndex; 44829 var slideAnchorLink; 44830 44831 if(activeSlide.length){ 44832 slideAnchorLink = activeSlide.data('anchor'); 44833 slideIndex = activeSlide.index(); 44834 } 44835 44836 if(canScroll){ 44837 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 44838 44839 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 44840 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 44841 44842 stopMedia(leavingSection); 44843 lazyLoad(currentSection); 44844 playMedia(currentSection); 44845 44846 activateMenuAndNav(anchorLink, sectionIndex - 1); 44847 44848 if(options.anchors.length){ 44849 //needed to enter in hashChange event when using the menu with anchor links 44850 lastScrolledDestiny = anchorLink; 44851 } 44852 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 44853 } 44854 44855 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 44856 clearTimeout(scrollId); 44857 scrollId = setTimeout(function(){ 44858 isScrolling = false;
44859 }, 100); 44860 } 44861 44862 if(options.fitToSection){ 44863 //for the auto adjust of the viewport to fit a whole section 44864 clearTimeout(scrollId2); 44865 44866 scrollId2 = setTimeout(function(){ 44867 //checking it again in case it changed during the delay 44868 if(options.fitToSection){ 44869 fitToSection(); 44870 } 44871 }, options.fitToSectionDelay); 44872 } 44873 } 44874 } 44875 44876 /** 44877 * Fits the site to the nearest active section 44878 */ 44879 function fitToSection(){ 44880 //checking fitToSection again in case it was set to false before the timeout delay 44881 if(canScroll){ 44882 //allows to scroll to an active section and 44883 //if the section is already active, we prevent firing callbacks 44884 isResizing = true; 44885 44886 scrollPage($(SECTION_ACTIVE_SEL)); 44887 isResizing = false; 44888 } 44889 } 44890 44891 /** 44892 * Determines whether the active section has seen in its whole or not. 44893 */ 44894 function isCompletelyInViewPort(movement){ 44895 var top = $(SECTION_ACTIVE_SEL).position().top; 44896 var bottom = top + $window.height(); 44897 44898 if(movement == 'up'){ 44899 return bottom >= ($window.scrollTop() + $window.height()); 44900 } 44901 return top <= $window.scrollTop(); 44902 } 44903 44904 /** 44905 * Gets the directon of the the scrolling fired by the scroll event. 44906 */ 44907 function getScrollDirection(currentScroll){ 44908 var direction = currentScroll > lastScroll ? 'down' : 'up'; 44909 44910 lastScroll = currentScroll; 44911 44912 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 44913 previousDestTop = currentScroll; 44914 44915 return direction; 44916 } 44917 44918 /** 44919 * Determines the way of scrolling up or down: 44920 * by 'automatically' scrolling a section or by using the default and normal scrolling. 44921 */ 44922 function scrolling(type, scrollable){ 44923 if (!isScrollAllowed.m[type]){ 44924 return; 44925 } 44926 var check = (type === 'down') ? 'bottom' : 'top'; 44927 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 44928 44929 if(scrollable.length > 0 ){ 44930 //is the scrollbar at the start/end of the scroll? 44931 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 44932 scrollSection(); 44933 }else{ 44934 return true; 44935 } 44936 }else{ 44937 // moved up/down 44938 scrollSection(); 44939 } 44940 } 44941 44942 /* 44943 * Preventing bouncing in iOS #2285 44944 */ 44945 function preventBouncing(event){ 44946 var e = event.originalEvent; 44947 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){ 44948 //preventing the easing on iOS devices 44949 event.preventDefault(); 44950 } 44951 } 44952 44953 var touchStartY = 0; 44954 var touchStartX = 0; 44955 var touchEndY = 0; 44956 var touchEndX = 0; 44957 44958 /* Detecting touch events 44959 44960 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 44961 * This way, the touchstart and the touch moves shows an small difference between them which is the 44962 * used one to determine the direction. 44963 */ 44964 function touchMoveHandler(event){ 44965 var e = event.originalEvent; 44966 var activeSection = $(e.target).closest(SECTION_SEL); 44967 44968 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 44969 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 44970 44971 if(options.autoScrolling){ 44972 //preventing the easing on iOS devices 44973 event.preventDefault(); 44974 } 44975 44976 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 44977 var touchEvents = getEventsPage(e); 44978 44979 touchEndY = touchEvents.y; 44980 touchEndX = touchEvents.x; 44981 44982 //if movement in the X axys is greater than in the Y and the currect section has slides... 44983 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 44984 44985 //is the movement greater than the minimum resistance to scroll? 44986 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 44987 if (touchStartX > touchEndX) { 44988 if(isScrollAllowed.m.right){ 44989 moveSlideRight(activeSection); //next 44990 } 44991 } else { 44992 if(isScrollAllowed.m.left){ 44993 moveSlideLeft(activeSection); //prev 44994 } 44995 } 44996 } 44997 } 44998 44999 //vertical scrolling (only when autoScrolling is enabled) 45000 else if(options.autoScrolling && canScroll){ 45001 45002 //is the movement greater than the minimum resistance to scroll? 45003 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 45004 if (touchStartY > touchEndY) { 45005 scrolling('down', scrollable); 45006 } else if (touchEndY > touchStartY) { 45007 scrolling('up', scrollable); 45008 } 45009 } 45010 } 45011 } 45012 } 45013 45014 /** 45015 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 45016 * Currently works well for iOS - Android might need some testing 45017 * @param {Element} el target element / jquery selector (in subsequent nodes) 45018 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 45019 * @return {boolean} true if there is a match to options.normalScrollElements 45020 */ 45021 function checkParentForNormalScrollElement (el, hop) { 45022 hop = hop || 0; 45023 var parent = $(el).parent(); 45024 45025 if (hop < options.normalScrollElementTouchThreshold && 45026 parent.is(options.normalScrollElements) ) { 45027 return true; 45028 } else if (hop == options.normalScrollElementTouchThreshold) { 45029 return false;
45030 } else { 45031 return checkParentForNormalScrollElement(parent, ++hop); 45032 } 45033 } 45034 45035 /** 45036 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 45037 * this way we make sure that is really a touch event what IE is detecting. 45038 */ 45039 function isReallyTouch(e){ 45040 //if is not IE || IE is detecting `touch` or `pen` 45041 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 45042 } 45043 45044 /** 45045 * Handler for the touch start event. 45046 */ 45047 function touchStartHandler(event){ 45048 var e = event.originalEvent; 45049 45050 //stopping the auto scroll to adjust to a section 45051 if(options.fitToSection){ 45052 $htmlBody.stop(); 45053 } 45054 45055 if(isReallyTouch(e)){ 45056 var touchEvents = getEventsPage(e); 45057 touchStartY = touchEvents.y; 45058 touchStartX = touchEvents.x; 45059 } 45060 } 45061 45062 /** 45063 * Gets the average of the last `number` elements of the given array. 45064 */ 45065 function getAverage(elements, number){ 45066 var sum = 0; 45067 45068 //taking `number` elements from the end to make the average, if there are not enought, 1 45069 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 45070 45071 for(var i = 0; i < lastElements.length; i++){ 45072 sum = sum + lastElements[i]; 45073 } 45074 45075 return Math.ceil(sum/number); 45076 } 45077 45078 /** 45079 * Detecting mousewheel scrolling 45080 * 45081 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 45082 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 45083 */ 45084 var prevTime = new Date().getTime(); 45085 45086 function MouseWheelHandler(e) { 45087 var curTime = new Date().getTime(); 45088 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 45089 45090 //autoscrolling and not zooming? 45091 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 45092 // cross-browser wheel delta 45093 e = e || window.event; 45094 var value = e.wheelDelta || -e.deltaY || -e.detail; 45095 var delta = Math.max(-1, Math.min(1, value)); 45096 45097 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 45098 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 45099 45100 //Limiting the array to 150 (lets not waste memory!) 45101 if(scrollings.length > 149){ 45102 scrollings.shift(); 45103 } 45104 45105 //keeping record of the previous scrollings 45106 scrollings.push(Math.abs(value)); 45107 45108 //preventing to scroll the site on mouse wheel when scrollbar is present 45109 if(options.scrollBar){ 45110 e.preventDefault ? e.preventDefault() : e.returnValue = false; 45111 } 45112 45113 var activeSection = $(SECTION_ACTIVE_SEL); 45114 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 45115 45116 //time difference between the last scroll and the current one 45117 var timeDiff = curTime-prevTime; 45118 prevTime = curTime; 45119 45120 //haven't they scrolled in a while? 45121 //(enough to be consider a different scrolling action to scroll another section) 45122 if(timeDiff > 200){ 45123 //emptying the array, we dont care about old scrollings for our averages 45124 scrollings = []; 45125 } 45126 45127 if(canScroll){ 45128 var averageEnd = getAverage(scrollings, 10); 45129 var averageMiddle = getAverage(scrollings, 70); 45130 var isAccelerating = averageEnd >= averageMiddle; 45131 45132 //to avoid double swipes... 45133 if(isAccelerating && isScrollingVertically){ 45134 //scrolling down? 45135 if (delta < 0) { 45136 scrolling('down', scrollable); 45137 45138 //scrolling up? 45139 }else { 45140 scrolling('up', scrollable); 45141 } 45142 } 45143 } 45144 45145 return false;
45146 } 45147 45148 if(options.fitToSection){ 45149 //stopping the auto scroll to adjust to a section 45150 $htmlBody.stop(); 45151 } 45152 } 45153 45154 /** 45155 * Slides a slider to the given direction. 45156 * Optional `section` param. 45157 */ 45158 function moveSlide(direction, section){ 45159 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 45160 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 45161 var numSlides = slides.find(SLIDE_SEL).length; 45162 45163 // more than one slide needed and nothing should be sliding 45164 if (!slides.length || slideMoving || numSlides < 2) { 45165 return; 45166 } 45167 45168 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 45169 var destiny = null; 45170 45171 if(direction === 'left'){ 45172 destiny = currentSlide.prev(SLIDE_SEL); 45173 }else{ 45174 destiny = currentSlide.next(SLIDE_SEL); 45175 } 45176 45177 //isn't there a next slide in the secuence? 45178 if(!destiny.length){ 45179 //respect loopHorizontal settin 45180 if (!options.loopHorizontal) return; 45181 45182 if(direction === 'left'){ 45183 destiny = currentSlide.siblings(':last'); 45184 }else{ 45185 destiny = currentSlide.siblings(':first'); 45186 } 45187 } 45188 45189 slideMoving = true; 45190 45191 landscapeScroll(slides, destiny, direction); 45192 } 45193 45194 /** 45195 * Maintains the active slides in the viewport 45196 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 45197 */ 45198 function keepSlidesPosition(){ 45199 $(SLIDE_ACTIVE_SEL).each(function(){ 45200 silentLandscapeScroll($(this), 'internal'); 45201 }); 45202 } 45203 45204 var previousDestTop = 0; 45205 /** 45206 * Returns the destination Y position based on the scrolling direction and 45207 * the height of the section. 45208 */ 45209 function getDestinationPosition(element){ 45210 var elemPosition = element.position(); 45211 45212 //top of the desination will be at the top of the viewport 45213 var position = elemPosition.top; 45214 var isScrollingDown = elemPosition.top > previousDestTop; 45215 var sectionBottom = position - windowsHeight + element.outerHeight(); 45216 var bigSectionsDestination = options.bigSectionsDestination; 45217 45218 //Uncode addition 45219 var containerH = container.outerHeight(); 45220 var containerPosition = container.offset(); 45221 45222 //########### Commented by Uncode - START ########### 45223 //is the destination element bigger than the viewport? 45224 // if(element.outerHeight() > windowsHeight){ 45225 // //scrolling up? 45226 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 45227 // position = sectionBottom; 45228 // } 45229 // } 45230 45231 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 45232 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 45233 // //The bottom of the destination will be at the bottom of the viewport 45234 // position = sectionBottom; 45235 // } 45236 //########### Commented by Uncode - END ########### 45237 45238 //Uncode addition 45239 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 45240 position += 18; 45241 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 45242 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 45243 } 45244 45245 /* 45246 Keeping record of the last scrolled position to determine the scrolling direction. 45247 No conventional methods can be used as the scroll bar might not be present 45248 AND the section might not be active if it is auto-height and didnt reach the middle 45249 of the viewport. 45250 */ 45251 previousDestTop = position; 45252 return position; 45253 } 45254 45255 /** 45256 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 45257 */ 45258 function scrollPage(element, callback, isMovementUp){ 45259 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 45260 45261 var dtop = getDestinationPosition(element); 45262 var slideAnchorLink; 45263 var slideIndex; 45264 45265 //local variables 45266 var v = { 45267 element: element, 45268 callback: callback, 45269 isMovementUp: isMovementUp, 45270 dtop: dtop, 45271 yMovement: getYmovement(element), 45272 anchorLink: element.data('anchor'), 45273 sectionIndex: element.index(SECTION_SEL), 45274 activeSlide: element.find(SLIDE_ACTIVE_SEL), 45275 activeSection: $(SECTION_ACTIVE_SEL), 45276 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 45277 45278 //caching the value of isResizing at the momment the function is called 45279 //because it will be checked later inside a setTimeout and the value might change 45280 localIsResizing: isResizing 45281 }; 45282 45283 //quiting when destination scroll is the same as the current one 45284 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 45285 45286 if(v.activeSlide.length){ 45287 slideAnchorLink = v.activeSlide.data('anchor'); 45288 slideIndex = v.activeSlide.index(); 45289 } 45290 45291 // If continuousVertical && we need to wrap around 45292 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 45293 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 45294 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 45295 45296 v = createInfiniteSections(v); 45297 } 45298 45299 //callback (onLeave) if the site is not just resizing and readjusting the slides 45300 if($.isFunction(options.onLeave) && !v.localIsResizing){ 45301 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 45302 return; 45303 } 45304 } 45305 45306 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 45307 if(!v.localIsResizing){ 45308 stopMedia(v.activeSection); 45309 } 45310 45311 options.scrollOverflowHandler.beforeLeave(); 45312 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 45313 lazyLoad(element); 45314 options.scrollOverflowHandler.onLeave(); 45315 45316 45317 //preventing from activating the MouseWheelHandler event 45318 //more than once if the page is scrolling 45319 canScroll = false;
45320 45321 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 45322 45323 performMovement(v); 45324 45325 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 45326 lastScrolledDestiny = v.anchorLink; 45327 45328 //avoid firing it twice (as it does also on scroll) 45329 activateMenuAndNav(v.anchorLink, v.sectionIndex); 45330 } 45331 45332 /** 45333 * Performs the vertical movement (by CSS3 or by jQuery) 45334 */ 45335 function performMovement(v){ 45336 // using CSS3 translate functionality 45337 if (options.css3 && options.autoScrolling && !options.scrollBar) { 45338 45339 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 45340 // that's why we round it to 0. 45341 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 45342 transformContainer(translate3d, true); 45343 45344 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 45345 //scrollingSpeed to change in case of using silentMoveTo(); 45346 if(options.scrollingSpeed){ 45347 clearTimeout(afterSectionLoadsId); 45348 afterSectionLoadsId = setTimeout(function () { 45349 afterSectionLoads(v); 45350 }, options.scrollingSpeed); 45351 }else{ 45352 afterSectionLoads(v); 45353 } 45354 } 45355 45356 // using jQuery animate 45357 else{ 45358 var scrollSettings = getScrollSettings(v); 45359 45360 $(scrollSettings.element).animate( 45361 scrollSettings.options, 45362 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 45363 if(options.scrollBar){ 45364 45365 /* Hack! 45366 The timeout prevents setting the most dominant section in the viewport as "active" when the user 45367 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 45368 45369 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 45370 */ 45371 setTimeout(function(){ 45372 afterSectionLoads(v); 45373 },30); 45374 }else{ 45375 afterSectionLoads(v); 45376 } 45377 }); 45378 } 45379 } 45380 45381 /** 45382 * Gets the scrolling settings depending on the plugin autoScrolling option 45383 */ 45384 function getScrollSettings(v){ 45385 var scroll = {}; 45386 45387 if(options.autoScrolling && !options.scrollBar){ 45388 scroll.options = { 'top': -v.dtop}; 45389 scroll.element = WRAPPER_SEL; 45390 }else{ 45391 scroll.options = { 'scrollTop': v.dtop}; 45392 scroll.element = 'html, body'; 45393 } 45394 45395 return scroll; 45396 } 45397 45398 /** 45399 * Adds sections before or after the current one to create the infinite effect. 45400 */ 45401 function createInfiniteSections(v){ 45402 // Scrolling down 45403 if (!v.isMovementUp) { 45404 // Move all previous sections to after the active section 45405 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 45406 } 45407 else { // Scrolling up 45408 // Move all next sections to before the active section 45409 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 45410 } 45411 45412 // Maintain the displayed position (now that we changed the element order) 45413 silentScroll($(SECTION_ACTIVE_SEL).position().top); 45414 45415 // Maintain the active slides visible in the viewport 45416 keepSlidesPosition(); 45417 45418 // save for later the elements that still need to be reordered 45419 v.wrapAroundElements = v.activeSection; 45420 45421 // Recalculate animation variables 45422 v.dtop = v.element.position().top; 45423 v.yMovement = getYmovement(v.element); 45424 45425 return v; 45426 } 45427 45428 /** 45429 * Fix section order after continuousVertical changes have been animated 45430 */ 45431 function continuousVerticalFixSectionOrder (v) {
45432 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 45433 // finish moving the elements around so the direct navigation will function more simply 45434 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 45435 return; 45436 } 45437 45438 if (v.isMovementUp) { 45439 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 45440 } 45441 else { 45442 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 45443 } 45444 45445 silentScroll($(SECTION_ACTIVE_SEL).position().top); 45446 45447 // Maintain the active slides visible in the viewport 45448 keepSlidesPosition(); 45449 } 45450 45451 45452 /** 45453 * Actions to do once the section is loaded. 45454 */ 45455 function afterSectionLoads (v){ 45456 continuousVerticalFixSectionOrder(v); 45457 45458 //callback (afterLoad) if the site is not just resizing and readjusting the slides 45459 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 45460 options.scrollOverflowHandler.afterLoad(); 45461 45462 if(!v.localIsResizing){ 45463 playMedia(v.element); 45464 } 45465 45466 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 45467 45468 canScroll = true; 45469 45470 $.isFunction(v.callback) && v.callback.call(this); 45471 } 45472 45473 /** 45474 * Sets the value for the given attribute from the `data-` attribute with the same suffix 45475 * ie: data-srcset ==> srcset | data-src ==> src 45476 */ 45477 function setSrc(element, attribute){ 45478 element 45479 .attr(attribute, element.data(attribute)) 45480 .removeAttr('data-' + attribute); 45481 } 45482 45483 /** 45484 * Lazy loads image, video and audio elements. 45485 */ 45486 function lazyLoad(destiny){ 45487 if (!options.lazyLoading){ 45488 return; 45489 } 45490 45491 var panel = getSlideOrSection(destiny); 45492 var element; 45493 45494 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 45495 element = $(this); 45496 45497 $.each(['src', 'srcset'], function(index, type){ 45498 var attribute = element.attr('data-' + type); 45499 if(typeof attribute !== 'undefined' && attribute){ 45500 setSrc(element, type); 45501 } 45502 }); 45503 45504 if(element.is('source')){ 45505 element.closest('video').get(0).load(); 45506 } 45507 }); 45508 } 45509 45510 /** 45511 * Plays video and audio elements. 45512 */ 45513 function playMedia(destiny){ 45514 var panel = getSlideOrSection(destiny); 45515 45516 //playing HTML5 media elements 45517 panel.find('video, audio').each(function(){ 45518 var element = $(this).get(0); 45519 45520 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 45521 element.play(); 45522 } 45523 }); 45524 45525 //youtube videos 45526 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 45527 var element = $(this).get(0); 45528 45529 if ( element.hasAttribute('data-autoplay') ){ 45530 playYoutube(element); 45531 } 45532 45533 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 45534 element.onload = function() { 45535 if ( element.hasAttribute('data-autoplay') ){ 45536 playYoutube(element); 45537 } 45538 }; 45539 }); 45540 } 45541 45542 /** 45543 * Plays a youtube video 45544 */ 45545 function playYoutube(element){ 45546 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 45547 } 45548 45549 /** 45550 * Stops video and audio elements. 45551 */ 45552 function stopMedia(destiny){ 45553 var panel = getSlideOrSection(destiny); 45554 45555 //stopping HTML5 media elements 45556 panel.find('video, audio').each(function(){ 45557 var element = $(this).get(0); 45558 45559 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 45560 element.pause(); 45561 } 45562 }); 45563 45564 //youtube videos 45565 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 45566 var element = $(this).get(0); 45567 45568 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 45569 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 45570 } 45571 }); 45572 } 45573 45574 /** 45575 * Gets the active slide (or section) for the given section 45576 */ 45577 function getSlideOrSection(destiny){ 45578 var slide = destiny.find(SLIDE_ACTIVE_SEL); 45579 if( slide.length ) { 45580 destiny = $(slide); 45581 } 45582 45583 return destiny; 45584 } 45585 45586 /**
45587 * Scrolls to the anchor in the URL when loading the site 45588 */ 45589 function scrollToAnchor(){ 45590 //getting the anchor link in the URL and deleting the `#` 45591 var value = window.location.hash.replace('#', '').split('/'); 45592 var sectionAnchor = decodeURIComponent(value[0]); 45593 var slideAnchor = decodeURIComponent(value[1]); 45594 45595 if(sectionAnchor){ //if theres any # 45596 if(options.animateAnchor){ 45597 scrollPageAndSlide(sectionAnchor, slideAnchor); 45598 }else{ 45599 silentMoveTo(sectionAnchor, slideAnchor); 45600 } 45601 } 45602 } 45603 45604 /** 45605 * Detecting any change on the URL to scroll to the given anchor link 45606 * (a way to detect back history button as we play with the hashes on the URL) 45607 */ 45608 function hashChangeHandler(){ 45609 if(!isScrolling && !options.lockAnchors){ 45610 var value = window.location.hash.replace('#', '').split('/'); 45611 var sectionAnchor = decodeURIComponent(value[0]); 45612 var slideAnchor = decodeURIComponent(value[1]); 45613 45614 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 45615 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 45616 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 45617 45618 45619 if(sectionAnchor.length){ 45620 /*in order to call scrollpage() only once for each destination at a time 45621 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 45622 event is fired on every scroll too.*/ 45623 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 45624 scrollPageAndSlide(sectionAnchor, slideAnchor); 45625 } 45626 } 45627 } 45628 } 45629 45630 //Sliding with arrow keys, both, vertical and horizontal 45631 function keydownHandler(e) { 45632 45633 clearTimeout(keydownId); 45634 45635 var activeElement = $(':focus'); 45636 45637 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 45638 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 45639 options.keyboardScrolling && options.autoScrolling){ 45640 var keyCode = e.which; 45641 45642 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 45643 var keyControls = [40, 38, 32, 33, 34]; 45644 if($.inArray(keyCode, keyControls) > -1){ 45645 e.preventDefault(); 45646 } 45647 45648 controlPressed = e.ctrlKey; 45649 45650 keydownId = setTimeout(function(){ 45651 onkeydown(e); 45652 },150); 45653 } 45654 } 45655 45656 function tooltipTextHandler(){ 45657 $(this).prev().trigger('click'); 45658 } 45659 45660 //to prevent scrolling while zooming 45661 function keyUpHandler(e){ 45662 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 45663 controlPressed = e.ctrlKey; 45664 } 45665 } 45666 45667 //binding the mousemove when the mouse's middle button is released 45668 function mouseDownHandler(e){ 45669 //middle button 45670 if (e.which == 2){ 45671 oldPageY = e.pageY; 45672 container.on('mousemove', mouseMoveHandler); 45673 } 45674 } 45675 45676 //unbinding the mousemove when the mouse's middle button is released 45677 function mouseUpHandler(e){ 45678 //middle button 45679 if (e.which == 2){ 45680 container.off('mousemove'); 45681 } 45682 } 45683 45684 //Scrolling horizontally when clicking on the slider controls. 45685 function slideArrowHandler(){ 45686 var section = $(this).closest(SECTION_SEL); 45687 45688 if ($(this).hasClass(SLIDES_PREV)) { 45689 if(isScrollAllowed.m.left){ 45690 moveSlideLeft(section); 45691 } 45692 } else { 45693 if(isScrollAllowed.m.right){ 45694 moveSlideRight(section); 45695 } 45696 } 45697 } 45698 45699 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 45700 function blurHandler(){ 45701 isWindowFocused = false;
45702 controlPressed = false; 45703 } 45704 45705 //Scrolls to the section when clicking the navigation bullet 45706 function sectionBulletHandler(e){ 45707 e.preventDefault(); 45708 var index = $(this).parent().index(); 45709 scrollPage($(SECTION_SEL).eq(index)); 45710 } 45711 45712 //Scrolls the slider to the given slide destination for the given section 45713 function slideBulletHandler(e){ 45714 e.preventDefault(); 45715 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 45716 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 45717 45718 landscapeScroll(slides, destiny); 45719 } 45720 45721 /** 45722 * Keydown event 45723 */ 45724 function onkeydown(e){ 45725 var shiftPressed = e.shiftKey; 45726 45727 //do nothing if we can not scroll or we are not using horizotnal key arrows. 45728 if(!canScroll && [37,39].indexOf(e.which) < 0){ 45729 return; 45730 } 45731 45732 switch (e.which) { 45733 //up 45734 case 38: 45735 case 33: 45736 if(isScrollAllowed.k.up){ 45737 moveSectionUp(); 45738 } 45739 break; 45740 45741 //down 45742 case 32: //spacebar 45743 if(shiftPressed && isScrollAllowed.k.up){ 45744 moveSectionUp(); 45745 break; 45746 } 45747 /* falls through */ 45748 case 40: 45749 case 34: 45750 if(isScrollAllowed.k.down){ 45751 moveSectionDown(); 45752 } 45753 break; 45754 45755 //Home 45756 case 36: 45757 if(isScrollAllowed.k.up){ 45758 moveTo(1); 45759 } 45760 break; 45761 45762 //End 45763 case 35: 45764 if(isScrollAllowed.k.down){ 45765 moveTo( $(SECTION_SEL).length ); 45766 } 45767 break; 45768 45769 //left 45770 case 37: 45771 if(isScrollAllowed.k.left){ 45772 moveSlideLeft(); 45773 } 45774 break; 45775 45776 //right 45777 case 39: 45778 if(isScrollAllowed.k.right){ 45779 moveSlideRight(); 45780 } 45781 break; 45782 45783 default: 45784 return; // exit this handler for other keys 45785 } 45786 } 45787 45788 /** 45789 * Detecting the direction of the mouse movement. 45790 * Used only for the middle button of the mouse. 45791 */ 45792 var oldPageY = 0; 45793 function mouseMoveHandler(e){ 45794 if(canScroll){ 45795 // moving up 45796 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 45797 moveSectionUp(); 45798 } 45799 45800 // moving down 45801 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 45802 moveSectionDown(); 45803 } 45804 } 45805 oldPageY = e.pageY; 45806 } 45807 45808 /** 45809 * Scrolls horizontal sliders. 45810 */ 45811 function landscapeScroll(slides, destiny, direction){ 45812 var section = slides.closest(SECTION_SEL); 45813 var v = { 45814 slides: slides, 45815 destiny: destiny, 45816 direction: direction, 45817 destinyPos: destiny.position(), 45818 slideIndex: destiny.index(), 45819 section: section, 45820 sectionIndex: section.index(SECTION_SEL), 45821 anchorLink: section.data('anchor'), 45822 slidesNav: section.find(SLIDES_NAV_SEL), 45823 slideAnchor: getAnchor(destiny), 45824 prevSlide: section.find(SLIDE_ACTIVE_SEL), 45825 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 45826 45827 //caching the value of isResizing at the momment the function is called 45828 //because it will be checked later inside a setTimeout and the value might change 45829 localIsResizing: isResizing 45830 }; 45831 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 45832 v.direction = v.direction ? v.direction : v.xMovement; 45833 45834 //important!! Only do it when not resizing 45835 if(!v.localIsResizing){ 45836 //preventing from scrolling to the next/prev section when using scrollHorizontally 45837 canScroll = false;
45838 } 45839 45840 if(options.onSlideLeave){ 45841 45842 //if the site is not just resizing and readjusting the slides 45843 if(!v.localIsResizing && v.xMovement!=='none'){ 45844 if($.isFunction( options.onSlideLeave )){ 45845 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 45846 slideMoving = false; 45847 return; 45848 } 45849 } 45850 } 45851 } 45852 45853 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 45854 45855 if(!v.localIsResizing){ 45856 stopMedia(v.prevSlide); 45857 lazyLoad(destiny); 45858 } 45859 45860 if(!options.loopHorizontal && options.controlArrows){ 45861 //hidding it for the fist slide, showing for the rest 45862 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 45863 45864 //hidding it for the last slide, showing for the rest 45865 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 45866 } 45867 45868 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 45869 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 45870 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 45871 } 45872 45873 performHorizontalMove(slides, v, true); 45874 } 45875 45876 45877 function afterSlideLoads(v){ 45878 activeSlidesNavigation(v.slidesNav, v.slideIndex); 45879 45880 //if the site is not just resizing and readjusting the slides 45881 if(!v.localIsResizing){ 45882 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 45883 45884 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 45885 //and to prevent double scroll right after a windows resize 45886 canScroll = true; 45887 45888 playMedia(v.destiny); 45889 } 45890 45891 //letting them slide again 45892 slideMoving = false; 45893 } 45894 45895 /** 45896 * Performs the horizontal movement. (CSS3 or jQuery) 45897 * 45898 * @param fireCallback {Bool} - determines whether or not to fire the callback 45899 */ 45900 function performHorizontalMove(slides, v, fireCallback){ 45901 var destinyPos = v.destinyPos; 45902 45903 if(options.css3){ 45904 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 45905 45906 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 45907 45908 afterSlideLoadsId = setTimeout(function(){ 45909 fireCallback && afterSlideLoads(v); 45910 }, options.scrollingSpeed, options.easing); 45911 }else{ 45912 slides.animate({ 45913 scrollLeft : Math.round(destinyPos.left) 45914 }, options.scrollingSpeed, options.easing, function() { 45915 45916 fireCallback && afterSlideLoads(v); 45917 }); 45918 } 45919 } 45920 45921 /** 45922 * Sets the state for the horizontal bullet navigations. 45923 */ 45924 function activeSlidesNavigation(slidesNav, slideIndex){ 45925 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 45926 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 45927 } 45928 45929 var previousHeight = windowsHeight; 45930 45931 //when resizing the site, we adjust the heights of the sections, slimScroll... 45932 function resizeHandler(){ 45933 //checking if it needs to get responsive 45934 responsive(); 45935 45936 // rebuild immediately on touch devices 45937 if (isTouchDevice) { 45938 var activeElement = $(document.activeElement); 45939 45940 //if the keyboard is NOT visible 45941 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 45942 var currentHeight = $window.height(); 45943 45944 //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) 45945 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 45946 reBuild(true); 45947 previousHeight = currentHeight; 45948 } 45949 } 45950 }else{ 45951 //in order to call the functions only when the resize is finished 45952 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 45953 clearTimeout(resizeId); 45954 45955 resizeId = setTimeout(function(){ 45956 reBuild(true); 45957 }, 350); 45958 } 45959 } 45960 45961 /** 45962 * Checks if the site needs to get responsive and disables autoScrolling if so. 45963 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 45964 */ 45965 function responsive(){ 45966 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 45967 var heightLimit = options.responsiveHeight; 45968 45969 //only calculating what we need. Remember its called on the resize event. 45970 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 45971 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 45972 45973 if(widthLimit && heightLimit){ 45974 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 45975 } 45976 else if(widthLimit){ 45977 setResponsive(isBreakingPointWidth); 45978 } 45979 else if(heightLimit){ 45980 setResponsive(isBreakingPointHeight); 45981 } 45982 } 45983 45984 /** 45985 * Adds transition animations for the given element 45986 */ 45987 function addAnimation(container, element){ 45988 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 45989 45990 container.removeClass(NO_TRANSITION); 45991 return container.css({
45992 '-webkit-transition': transition, 45993 'transition': transition 45994 }); 45995 } 45996 45997 /** 45998 * Remove transition animations for the given element 45999 */ 46000 function removeAnimation(element){ 46001 return element.addClass(NO_TRANSITION); 46002 } 46003 46004 /** 46005 * Activating the vertical navigation bullets according to the given slide name. 46006 */ 46007 function activateNavDots(name, sectionIndex){ 46008 if(options.navigation){ 46009 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 46010 if(name){ 46011 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 46012 }else{ 46013 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 46014 } 46015 } 46016 } 46017 46018 /** 46019 * Activating the website main menu elements according to the given slide name. 46020 */ 46021 function activateMenuElement(name){ 46022 if(options.menu){ 46023 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 46024 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 46025 } 46026 } 46027 46028 /** 46029 * Sets to active the current menu and vertical nav items. 46030 */ 46031 function activateMenuAndNav(anchor, index){ 46032 activateMenuElement(anchor); 46033 activateNavDots(anchor, index); 46034 } 46035 46036 /** 46037 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 46038 * from the current section. 46039 */ 46040 function getYmovement(destiny){ 46041 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 46042 var toIndex = destiny.index(SECTION_SEL); 46043 if( fromIndex == toIndex){ 46044 return 'none'; 46045 } 46046 if(fromIndex > toIndex){ 46047 return 'up'; 46048 } 46049 return 'down'; 46050 } 46051 46052 /** 46053 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 46054 * from the current slide. 46055 */ 46056 function getXmovement(fromIndex, toIndex){ 46057 if( fromIndex == toIndex){ 46058 return 'none'; 46059 } 46060 if(fromIndex > toIndex){ 46061 return 'left'; 46062 } 46063 return 'right'; 46064 } 46065 46066 /** 46067 * Checks if the element needs scrollbar and if the user wants to apply it. 46068 * If so it creates it. 46069 * 46070 * @param {Object} element jQuery object of the section or slide 46071 */ 46072 function createScrollBar(element){ 46073 //User doesn't want scrollbar here? Sayonara baby! 46074 if(element.hasClass('fp-noscroll')) return; 46075 46076 //needed to make `scrollHeight` work under Opera 12 46077 element.css('overflow', 'hidden'); 46078 46079 var scrollOverflowHandler = options.scrollOverflowHandler; 46080 var wrap = scrollOverflowHandler.wrapContent(); 46081 //in case element is a slide 46082 var section = element.closest(SECTION_SEL); 46083 var scrollable = scrollOverflowHandler.scrollable(element); 46084 var contentHeight; 46085 46086 //if there was scroll, the contentHeight will be the one in the scrollable section 46087 if(scrollable.length){ 46088 contentHeight = scrollOverflowHandler.scrollHeight(element); 46089 }else{ 46090 contentHeight = element.get(0).scrollHeight; 46091 if(options.verticalCentered){ 46092 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 46093 } 46094 } 46095 46096 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 46097 46098 //needs scroll? 46099 if ( contentHeight > scrollHeight) { 46100 //did we already have an scrollbar ? Updating it 46101 if(scrollable.length){ 46102 scrollOverflowHandler.update(element, scrollHeight); 46103 } 46104 //creating the scrolling 46105 else{ 46106 if(options.verticalCentered){ 46107 element.find(TABLE_CELL_SEL).wrapInner(wrap); 46108 }else{ 46109 element.wrapInner(wrap); 46110 } 46111 scrollOverflowHandler.create(element, scrollHeight); 46112 } 46113 } 46114 //removing the scrolling when it is not necessary anymore 46115 else{ 46116 scrollOverflowHandler.remove(element); 46117 } 46118 46119 //undo 46120 element.css('overflow', ''); 46121 } 46122 46123 function addTableClass(element){ 46124 //In case we are styling for the 2nd time as in with reponsiveSlides 46125 if(!element.hasClass(TABLE)){ 46126 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 46127 } 46128 } 46129 46130 function getTableHeight(element){ 46131 var sectionHeight = windowsHeight; 46132 46133 if(options.paddingTop || options.paddingBottom){ 46134 var section = element; 46135 if(!section.hasClass(SECTION)){ 46136 section = element.closest(SECTION_SEL); 46137 } 46138 46139 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 46140 sectionHeight = (windowsHeight - paddings); 46141 } 46142 46143 return sectionHeight; 46144 } 46145 46146 /** 46147 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 46148 */ 46149 function transformContainer(translate3d, animated){ 46150 if(animated){ 46151 addAnimation(container); 46152 }else{ 46153 removeAnimation(container); 46154 } 46155 46156 container.css(getTransforms(translate3d)); 46157 46158 //syncronously removing the class after the animation has been applied. 46159 setTimeout(function(){ 46160 container.removeClass(NO_TRANSITION); 46161 },10); 46162 } 46163 46164 /** 46165 * Gets a section by its anchor / index 46166 */ 46167 function getSectionByAnchor(sectionAnchor){ 46168 if(!sectionAnchor) return []; 46169 46170 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 46171 if(!section.length){ 46172 section = $(SECTION_SEL).eq( sectionAnchor -1); 46173 } 46174 46175 return section; 46176 } 46177 46178 /** 46179 * Gets a slide inside a given section by its anchor / index 46180 */ 46181 function getSlideByAnchor(slideAnchor, section){ 46182 var slides = section.find(SLIDES_WRAPPER_SEL); 46183 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 46184
46185 if(!slide.length){ 46186 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 46187 } 46188 46189 return slide; 46190 } 46191 46192 /** 46193 * Scrolls to the given section and slide anchors 46194 */ 46195 function scrollPageAndSlide(destiny, slide){ 46196 var section = getSectionByAnchor(destiny); 46197 46198 //do nothing if there's no section with the given anchor name 46199 if(!section.length) return; 46200 46201 //default slide 46202 if (typeof slide === 'undefined') { 46203 slide = 0; 46204 } 46205 46206 //we need to scroll to the section and then to the slide 46207 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 46208 scrollPage(section, function(){ 46209 scrollSlider(section, slide); 46210 }); 46211 } 46212 //if we were already in the section 46213 else{ 46214 scrollSlider(section, slide); 46215 } 46216 } 46217 46218 /** 46219 * Scrolls the slider to the given slide destination for the given section 46220 */ 46221 function scrollSlider(section, slideAnchor){ 46222 if(typeof slideAnchor !== 'undefined'){ 46223 var slides = section.find(SLIDES_WRAPPER_SEL); 46224 var destiny = getSlideByAnchor(slideAnchor, section); 46225 46226 if(destiny.length){ 46227 landscapeScroll(slides, destiny); 46228 } 46229 } 46230 } 46231 46232 /** 46233 * Creates a landscape navigation bar with dots for horizontal sliders. 46234 */ 46235 function addSlidesNavigation(section, numSlides){ 46236 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 46237 var nav = section.find(SLIDES_NAV_SEL); 46238 46239 //top or bottom 46240 nav.addClass(options.slidesNavPosition); 46241 46242 for(var i=0; i< numSlides; i++){ 46243 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 46244 } 46245 46246 //centering it 46247 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 46248 46249 nav.find('li').first().find('a').addClass(ACTIVE); 46250 } 46251 46252 46253 /** 46254 * Sets the state of the website depending on the active section/slide. 46255 * It changes the URL hash when needed and updates the body class. 46256 */ 46257 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 46258 var sectionHash = ''; 46259 46260 if(options.anchors.length && !options.lockAnchors){ 46261 46262 //isn't it the first slide? 46263 if(slideIndex){ 46264 if(typeof anchorLink !== 'undefined'){ 46265 sectionHash = anchorLink; 46266 } 46267 46268 //slide without anchor link? We take the index instead. 46269 if(typeof slideAnchor === 'undefined'){ 46270 slideAnchor = slideIndex; 46271 } 46272 46273 lastScrolledSlide = slideAnchor; 46274 setUrlHash(sectionHash + '/' + slideAnchor); 46275 46276 //first slide won't have slide anchor, just the section one 46277 }else if(typeof slideIndex !== 'undefined'){ 46278 lastScrolledSlide = slideAnchor; 46279 setUrlHash(anchorLink); 46280 } 46281 46282 //section without slides 46283 else{ 46284 setUrlHash(anchorLink); 46285 } 46286 } 46287 46288 setBodyClass(); 46289 } 46290 46291 /** 46292 * Sets the URL hash. 46293 */ 46294 function setUrlHash(url){ 46295 //Uncode addition 46296 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 46297 return false; 46298 46299 if(options.recordHistory){ 46300 location.hash = url; 46301 }else{ 46302 //Uncode addition 46303 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 46304 // if(isTouchDevice || isTouch){ 46305 // window.history.replaceState(undefined, undefined, '#' + url); 46306 // }else{ 46307 // var baseUrl = window.location.href.split('#')[0]; 46308 // window.location.replace( baseUrl + '#' + url ); 46309 // } 46310 return false;
46311 } 46312 } 46313 46314 /** 46315 * Gets the anchor for the given slide / section. Its index will be used if there's none. 46316 */ 46317 function getAnchor(element){ 46318 var anchor = element.data('anchor'); 46319 var index = element.index(); 46320 46321 //Slide without anchor link? We take the index instead. 46322 if(typeof anchor === 'undefined'){ 46323 anchor = index; 46324 } 46325 46326 return anchor; 46327 } 46328 46329 /** 46330 * Sets a class for the body of the page depending on the active section / slide 46331 */ 46332 function setBodyClass(){ 46333 var section = $(SECTION_ACTIVE_SEL); 46334 var slide = section.find(SLIDE_ACTIVE_SEL); 46335 46336 var sectionAnchor = getAnchor(section); 46337 var slideAnchor = getAnchor(slide); 46338 46339 var text = String(sectionAnchor); 46340 46341 if(slide.length){ 46342 text = text + '-' + slideAnchor; 46343 } 46344 46345 //changing slash for dash to make it a valid CSS style 46346 text = text.replace('/', '-').replace('#',''); 46347 46348 //removing previous anchor classes 46349 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 46350 $body[0].className = $body[0].className.replace(classRe, ''); 46351 46352 //adding the current anchor 46353 $body.addClass(VIEWING_PREFIX + '-' + text); 46354 } 46355 46356 /** 46357 * Checks for translate3d support 46358 * @return boolean 46359 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 46360 */ 46361 function support3d() { 46362 var el = document.createElement('p'), 46363 has3d, 46364 transforms = { 46365 'webkitTransform':'-webkit-transform', 46366 'OTransform':'-o-transform', 46367 'msTransform':'-ms-transform', 46368 'MozTransform':'-moz-transform', 46369 'transform':'transform' 46370 }; 46371 46372 // Add it to the body to get the computed style. 46373 document.body.insertBefore(el, null); 46374 46375 for (var t in transforms) { 46376 if (el.style[t] !== undefined) { 46377 el.style[t] = 'translate3d(1px,1px,1px)'; 46378 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 46379 } 46380 } 46381 46382 document.body.removeChild(el); 46383 46384 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 46385 } 46386 46387 /** 46388 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 46389 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 46390 */ 46391 function removeMouseWheelHandler(){ 46392 if (document.addEventListener) { 46393 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 46394 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 46395 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 46396 } else { 46397 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 46398 } 46399 } 46400 46401 /** 46402 * Adds the auto scrolling action for the mouse wheel and trackpad. 46403 * After this function is called, the mousewheel and trackpad movements will scroll through sections 46404 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 46405 */ 46406 function addMouseWheelHandler(){ 46407 var prefix = ''; 46408 var _addEventListener; 46409 46410 if (window.addEventListener){ 46411 _addEventListener = "addEventListener"; 46412 }else{ 46413 _addEventListener = "attachEvent"; 46414 prefix = 'on'; 46415 } 46416 46417 // detect available wheel event 46418 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 46419 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 46420 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 46421 var passiveEvent = g_supportsPassive ? {passive: false }
46421: false; 46422 46423 46424 if(support == 'DOMMouseScroll'){ 46425 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent); 46426 } 46427 46428 //handle MozMousePixelScroll in older Firefox 46429 else{ 46430 document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent); 46431 } 46432 } 46433 46434 /** 46435 * Binding the mousemove when the mouse's middle button is pressed 46436 */ 46437 function addMiddleWheelHandler(){ 46438 container 46439 .on('mousedown', mouseDownHandler) 46440 .on('mouseup', mouseUpHandler); 46441 } 46442 46443 /** 46444 * Unbinding the mousemove when the mouse's middle button is released 46445 */ 46446 function removeMiddleWheelHandler(){ 46447 container 46448 .off('mousedown', mouseDownHandler) 46449 .off('mouseup', mouseUpHandler); 46450 } 46451 46452 /** 46453 * Adds the possibility to auto scroll through sections on touch devices. 46454 */ 46455 function addTouchHandler(){ 46456 if(isTouchDevice || isTouch){ 46457 if(options.autoScrolling){ 46458 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 46459 } 46460 46461 $(WRAPPER_SEL) 46462 .off(events.touchstart).on(events.touchstart, touchStartHandler) 46463 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 46464 } 46465 } 46466 46467 /** 46468 * Removes the auto scrolling for touch devices. 46469 */ 46470 function removeTouchHandler(){ 46471 if(isTouchDevice || isTouch){ 46472 $(WRAPPER_SEL) 46473 .off(events.touchstart) 46474 .off(events.touchmove); 46475 } 46476 } 46477 46478 /* 46479 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11) 46480 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 46481 */ 46482 function getMSPointer(){ 46483 var pointer; 46484 46485 //IE >= 11 & rest of browsers 46486 if(window.PointerEvent){ 46487 pointer = { down: 'pointerdown', move: 'pointermove'}; 46488 } 46489 46490 //IE < 11 46491 else{ 46492 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 46493 } 46494 46495 return pointer; 46496 } 46497 46498 /** 46499 * Gets the pageX and pageY properties depending on the browser. 46500 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 46501 */ 46502 function getEventsPage(e){ 46503 var events = []; 46504 46505 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 46506 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 46507 46508 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 46509 if(isTouch && isReallyTouch(e) && options.scrollBar){ 46510 events.y = e.touches[0].pageY; 46511 events.x = e.touches[0].pageX; 46512 } 46513 46514 return events; 46515 } 46516 46517 /** 46518 * Slides silently (with no animation) the active slider to the given slide. 46519 * @param noCallback {bool} true or defined -> no callbacks 46520 */ 46521 function silentLandscapeScroll(activeSlide, noCallbacks){ 46522 setScrollingSpeed (0, 'internal'); 46523 46524 if(typeof noCallbacks !== 'undefined'){ 46525 //preventing firing callbacks afterSlideLoad etc. 46526 isResizing = true; 46527 } 46528 46529 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 46530 46531 if(typeof noCallbacks !== 'undefined'){ 46532 isResizing = false; 46533 } 46534 46535 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 46536 } 46537 46538 /** 46539 * Scrolls silently (with no animation) the page to the given Y position. 46540 */ 46541 function silentScroll(top){ 46542 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 46543 // that's why we round it to 0. 46544 var roundedTop = Math.round(top); 46545 46546 if (options.css3 && options.autoScrolling && !options.scrollBar){ 46547 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 46548 transformContainer(translate3d, false); 46549 } 46550 else if(options.autoScrolling && !options.scrollBar){ 46551 container.css('top', -roundedTop); 46552 } 46553 else{ 46554 $htmlBody.scrollTop(roundedTop); 46555 } 46556 } 46557 46558 /** 46559 * Returns the cross-browser transform string. 46560 */ 46561 function getTransforms(translate3d){ 46562 return {
46563 '-webkit-transform': translate3d, 46564 '-moz-transform': translate3d, 46565 '-ms-transform':translate3d, 46566 'transform': translate3d 46567 }; 46568 } 46569 46570 /** 46571 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 46572 * @type m (mouse) or k (keyboard) 46573 */ 46574 function setIsScrollAllowed(value, direction, type){ 46575 switch (direction){ 46576 case 'up': isScrollAllowed[type].up = value; break; 46577 case 'down': isScrollAllowed[type].down = value; break; 46578 case 'left': isScrollAllowed[type].left = value; break; 46579 case 'right': isScrollAllowed[type].right = value; break; 46580 case 'all': 46581 if(type == 'm'){ 46582 setAllowScrolling(value); 46583 }else{ 46584 setKeyboardScrolling(value); 46585 } 46586 } 46587 } 46588 46589 /* 46590 * Destroys fullpage.js plugin events and optinally its html markup and styles 46591 */ 46592 function destroy(all){ 46593 setAutoScrolling(false, 'internal'); 46594 setAllowScrolling(false); 46595 setKeyboardScrolling(false); 46596 container.addClass(DESTROYED); 46597 46598 clearTimeout(afterSlideLoadsId); 46599 clearTimeout(afterSectionLoadsId); 46600 clearTimeout(resizeId); 46601 clearTimeout(scrollId); 46602 clearTimeout(scrollId2); 46603 46604 $window 46605 .off('scroll', scrollHandler) 46606 .off('hashchange', hashChangeHandler) 46607 .off('resize', resizeHandler); 46608 46609 $document 46610 .off('click touchstart', SECTION_NAV_SEL + ' a') 46611 .off('mouseenter', SECTION_NAV_SEL + ' li') 46612 .off('mouseleave', SECTION_NAV_SEL + ' li') 46613 .off('click touchstart', SLIDES_NAV_LINK_SEL) 46614 .off('mouseover', options.normalScrollElements) 46615 .off('mouseout', options.normalScrollElements); 46616 46617 $(SECTION_SEL) 46618 .off('click touchstart', SLIDES_ARROW_SEL); 46619 46620 clearTimeout(afterSlideLoadsId); 46621 clearTimeout(afterSectionLoadsId); 46622 46623 //lets make a mess! 46624 if(all){ 46625 destroyStructure(); 46626 } 46627 } 46628 46629 /* 46630 * Removes inline styles added by fullpage.js 46631 */ 46632 function destroyStructure(){ 46633 //reseting the `top` or `translate` properties to 0 46634 silentScroll(0); 46635 46636 //loading all the lazy load content 46637 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 46638 setSrc($(this), 'src'); 46639 }); 46640 46641 container.find('img[data-srcset]').each(function(){ 46642 setSrc($(this), 'srcset'); 46643 }); 46644 46645 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 46646 46647 //removing inline styles 46648 $(SECTION_SEL).css( { 46649 'height': '', 46650 'background-color' : '', 46651 'padding': '' 46652 }); 46653 46654 $(SLIDE_SEL).css( { 46655 'width': '' 46656 }); 46657 46658 container.css({ 46659 'height': '', 46660 'position': '', 46661 '-ms-touch-action': '', 46662 'touch-action': '' 46663 }); 46664 46665 $htmlBody.css({ 46666 'overflow': '', 46667 'height': '' 46668 }); 46669 46670 // remove .fp-enabled class 46671 $('html').removeClass(ENABLED); 46672 46673 // remove .fp-responsive class 46674 $body.removeClass(RESPONSIVE); 46675 46676 // remove all of the .fp-viewing- classes 46677 $.each($body.get(0).className.split(/\s+/), function (index, className) { 46678 if (className.indexOf(VIEWING_PREFIX) === 0) { 46679 $body.removeClass(className); 46680 } 46681 }); 46682 46683 //removing added classes 46684 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 46685 options.scrollOverflowHandler.remove($(this)); 46686 $(this).removeClass(TABLE + ' ' + ACTIVE); 46687 }); 46688 46689 removeAnimation(container); 46690 46691 //Unwrapping content 46692 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 46693 //unwrap not being use in case there's no child element inside and its just text 46694 $(this).replaceWith(this.childNodes); 46695 }); 46696 46697 //removing the applied transition from the fullpage wrapper 46698 container.css({
46699 '-webkit-transition': 'none', 46700 'transition': 'none' 46701 }); 46702 46703 //scrolling the page to the top with no animation 46704 $htmlBody.scrollTop(0); 46705 46706 //removing selectors 46707 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 46708 $.each(usedSelectors, function(index, value){ 46709 $('.' + value).removeClass(value); 46710 }); 46711 } 46712 46713 /* 46714 * Sets the state for a variable with multiple states (original, and temporal) 46715 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 46716 * This function is used to keep track of both states, the original and the temporal one. 46717 * If type is not 'internal', then we assume the user is globally changing the variable. 46718 */ 46719 function setVariableState(variable, value, type){ 46720 options[variable] = value; 46721 if(type !== 'internal'){ 46722 originals[variable] = value; 46723 } 46724 } 46725 46726 /** 46727 * Displays warnings 46728 */ 46729 function displayWarnings(){ 46730 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 46731 //UNCODE.addition 46732 // if($('html').hasClass(ENABLED)){ 46733 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 46734 // return; 46735 // } 46736 46737 // Disable mutually exclusive settings 46738 //UNCODE.addition 46739 // if (options.continuousVertical && 46740 // (options.loopTop || options.loopBottom)) { 46741 // options.continuousVertical = false;
46742 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 46743 // } 46744 46745 // if(options.scrollBar && options.scrollOverflow){ 46746 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 46747 // } 46748 46749 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 46750 // options.continuousVertical = false; 46751 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 46752 // } 46753 46754 //using extensions? Wrong file! 46755 $.each(extensions, function(index, extension){ 46756 //is the option set to true? 46757 if(options[extension]){ 46758 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 46759 } 46760 }); 46761 46762 //anchors can not have the same value as any element ID or NAME 46763 $.each(options.anchors, function(index, name){ 46764 46765 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 46766 var nameAttr = $document.find('[name]').filter(function() { 46767 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 46768 }); 46769 46770 var idAttr = $document.find('[id]').filter(function() { 46771 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 46772 }); 46773 46774 if(idAttr.length || nameAttr.length ){ 46775 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 46776 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 46777 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 46778 } 46779 }); 46780 } 46781 46782 /** 46783 * Shows a message in the console of the given type. 46784 */ 46785 function showError(type, text){ 46786 console && console[type] && console[type]('fullPage: ' + text); 46787 } 46788 46789 }; //end of $.fn.fullpage 46790 46791 if(typeof IScroll !== 'undefined'){ 46792 /* 46793 * Turns iScroll `mousewheel` option off dynamically 46794 * https://github.com/cubiq/iscroll/issues/1036 46795 */ 46796 IScroll.prototype.wheelOn = function () { 46797 this.wrapper.addEventListener('wheel', this); 46798 this.wrapper.addEventListener('mousewheel', this); 46799 this.wrapper.addEventListener('DOMMouseScroll', this); 46800 }; 46801 46802 /* 46803 * Turns iScroll `mousewheel` option on dynamically 46804 * https://github.com/cubiq/iscroll/issues/1036 46805 */ 46806 IScroll.prototype.wheelOff = function () { 46807 this.wrapper.removeEventListener('wheel', this); 46808 this.wrapper.removeEventListener('mousewheel', this); 46809 this.wrapper.removeEventListener('DOMMouseScroll', this); 46810 }; 46811 } 46812 46813 /** 46814 * An object to handle overflow scrolling. 46815 * This uses jquery.slimScroll to accomplish overflow scrolling. 46816 * It is possible to pass in an alternate scrollOverflowHandler 46817 * to the fullpage.js option that implements the same functions 46818 * as this handler. 46819 * 46820 * @type {Object} 46821 */ 46822 var iscrollHandler = { 46823 refreshId: null, 46824 iScrollInstances: [], 46825 46826 // Enables or disables the mouse wheel for the active section or all slides in it 46827 toggleWheel: function(value){ 46828 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 46829 scrollable.each(function(){ 46830 var iScrollInstance = $(this).data('iscrollInstance'); 46831 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 46832 if(value){ 46833 iScrollInstance.wheelOn(); 46834 } 46835 else{ 46836 iScrollInstance.wheelOff(); 46837 } 46838 } 46839 }); 46840 }, 46841 46842 /** 46843 * Turns off iScroll for the destination section. 46844 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
46845 * scroll the destination section/slide before the sections animations ends. 46846 */ 46847 onLeave: function(){ 46848 iscrollHandler.toggleWheel(false); 46849 }, 46850 46851 // Turns off iScroll for the leaving section 46852 beforeLeave: function(){ 46853 iscrollHandler.onLeave() 46854 }, 46855 46856 // Turns on iScroll on section load 46857 afterLoad: function(){ 46858 iscrollHandler.toggleWheel(true); 46859 }, 46860 46861 /** 46862 * Called when overflow scrolling is needed for a section. 46863 * 46864 * @param {Object} element jQuery object containing current section 46865 * @param {Number} scrollHeight Current window height in pixels 46866 */ 46867 create: function(element, scrollHeight) { 46868 var scrollable = element.find(SCROLLABLE_SEL); 46869 46870 scrollable.height(scrollHeight); 46871 scrollable.each(function() { 46872 var $this = $(this); 46873 var iScrollInstance = $this.data('iscrollInstance'); 46874 if (iScrollInstance) { 46875 $.each(iscrollHandler.iScrollInstances, function(){ 46876 $(this).destroy(); 46877 }); 46878 } 46879 46880 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 46881 iscrollHandler.iScrollInstances.push(iScrollInstance); 46882 46883 //off by default until the section gets active 46884 iScrollInstance.wheelOff(); 46885 46886 $this.data('iscrollInstance', iScrollInstance); 46887 }); 46888 }, 46889 46890 /** 46891 * Return a boolean depending on whether the scrollable element is a 46892 * the end or at the start of the scrolling depending on the given type. 46893 * 46894 * @param {String} type Either 'top' or 'bottom' 46895 * @param {Object} scrollable jQuery object for the scrollable element 46896 * @return {Boolean} 46897 */ 46898 isScrolled: function(type, scrollable) { 46899 var scroller = scrollable.data('iscrollInstance'); 46900 46901 //no scroller? 46902 if (!scroller) { 46903 return true; 46904 } 46905 46906 //Uncode addition 46907 var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0; 46908 //End Uncode addition 46909 46910 if (type === 'top') { 46911 return scroller.y >= 0 && !scrollable.scrollTop(); 46912 } else if (type === 'bottom') { 46913 //Uncode change 46914 // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight; 46915 return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight; 46916 //End Uncode change 46917 } 46918 }, 46919 46920 /** 46921 * Returns the scrollable element for the given section. 46922 * If there are landscape slides, will only return a scrollable element 46923 * if it is in the active slide. 46924 * 46925 * @param {Object} activeSection jQuery object containing current section 46926 * @return {Boolean} 46927 */ 46928 scrollable: function(activeSection){ 46929 // if there are landscape slides, we check if the scrolling bar is in the current one or not 46930 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 46931 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 46932 } 46933 return activeSection.find(SCROLLABLE_SEL); 46934 }, 46935 46936 /** 46937 * Returns the scroll height of the wrapped content. 46938 * If this is larger than the window height minus section padding, 46939 * overflow scrolling is needed. 46940 * 46941 * @param {Object} element jQuery object containing current section 46942 * @return {Number} 46943 */ 46944 scrollHeight: function(element) { 46945 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 46946 }, 46947 46948 /** 46949 * Called when overflow scrolling is no longer needed for a section. 46950 * 46951 * @param {Object}
vendor: 5,435 bytes, lines 46951-47102
46951 element jQuery object containing current section 46952 */ 46953 remove: function(element) { 46954 var scrollable = element.find(SCROLLABLE_SEL); 46955 if (scrollable.length) { 46956 var iScrollInstance = scrollable.data('iscrollInstance'); 46957 iScrollInstance.destroy(); 46958 46959 scrollable.data('iscrollInstance', null); 46960 } 46961 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 46962 }, 46963 46964 /** 46965 * Called when overflow scrolling has already been setup but the 46966 * window height has potentially changed. 46967 * 46968 * @param {Object} element jQuery object containing current section 46969 * @param {Number} scrollHeight Current window height in pixels 46970 */ 46971 update: function(element, scrollHeight) { 46972 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 46973 //short period of time. 46974 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 46975 clearTimeout(iscrollHandler.refreshId); 46976 iscrollHandler.refreshId = setTimeout(function(){ 46977 $.each(iscrollHandler.iScrollInstances, function(){ 46978 $(this).get(0).refresh(); 46979 }); 46980 }, 150); 46981 46982 //updating the wrappers height 46983 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 46984 }, 46985 46986 /** 46987 * Called to get any additional elements needed to wrap the section 46988 * content in order to facilitate overflow scrolling. 46989 * 46990 * @return {String|Object} Can be a string containing HTML, 46991 * a DOM element, or jQuery object. 46992 */ 46993 wrapContent: function() { 46994 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 46995 } 46996 }; 46997}); 46998 46999(function (global, factory) { 47000 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 47001 typeof define === 'function' && define.amd ? define(['exports'], factory) : 47002 (global = global || self, factory(global.window = global.window || {})); 47003 }(this, (function (exports) { 'use strict'; 47004 47005 function _defineProperties(target, props) { 47006 for (var i = 0; i < props.length; i++) { 47007 var descriptor = props[i]; 47008 descriptor.enumerable = descriptor.enumerable || false; 47009 descriptor.configurable = true; 47010 if ("value" in descriptor) descriptor.writable = true; 47011 Object.defineProperty(target, descriptor.key, descriptor); 47012 } 47013 } 47014 47015 function _createClass(Constructor, protoProps, staticProps) { 47016 if (protoProps) _defineProperties(Constructor.prototype, protoProps); 47017 if (staticProps) _defineProperties(Constructor, staticProps); 47018 return Constructor; 47019 } 47020 47021 /*! 47022 * Observer 3.12.5 47023 * https://gsap.com 47024 * 47025 * @license Copyright 2008-2024, GreenSock. All rights reserved. 47026 * Subject to the terms at https://gsap.com/standard-license or for 47027 * Club GSAP members, the agreement issued with that membership. 47028 * @author: Jack Doyle, [email protected] 47029 */ 47030 var gsap, 47031 _coreInitted, 47032 _clamp, 47033 _win, 47034 _doc, 47035 _docEl, 47036 _body, 47037 _isTouch, 47038 _pointerType, 47039 ScrollTrigger, 47040 _root, 47041 _normalizer, 47042 _eventTypes, 47043 _context, 47044 _getGSAP = function _getGSAP() { 47045 return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap; 47046 }, 47047 _startup = 1, 47048 _observers = [], 47049 _scrollers = [], 47050 _proxies = [], 47051 _getTime = Date.now, 47052 _bridge = function _bridge(name, value) { 47053 return value; 47054 }, 47055 _integrate = function _integrate() { 47056 var core = ScrollTrigger.core, 47057 data = core.bridge || {}, 47058 scrollers = core._scrollers, 47059 proxies = core._proxies; 47060 scrollers.push.apply(scrollers, _scrollers); 47061 proxies.push.apply(proxies, _proxies); 47062 _scrollers = scrollers; 47063 _proxies = proxies; 47064 47065 _bridge = function _bridge(name, value) { 47066 return data[name](value); 47067 }; 47068 }, 47069 _getProxyProp = function _getProxyProp(element, property) { 47070 return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property]; 47071 }, 47072 _isViewport = function _isViewport(el) { 47073 return !!~_root.indexOf(el); 47074 }, 47075 _addListener = function _addListener(element, type, func, passive, capture) { 47076 return element.addEventListener(type, func, { 47077 passive: passive !== false, 47078 capture: !!capture 47079 }); 47080 }, 47081 _removeListener = function _removeListener(element, type, func, capture) { 47082 return element.removeEventListener(type, func, !!capture); 47083 }, 47084 _scrollLeft = "scrollLeft", 47085 _scrollTop = "scrollTop", 47086 _onScroll = function _onScroll() { 47087 return _normalizer && _normalizer.isPressed || _scrollers.cache++; 47088 }, 47089 _scrollCacheFunc = function _scrollCacheFunc(f, doNotCache) { 47090 var cachingFunc = function cachingFunc(value) { 47091 if (value || value === 0) { 47092 _startup && (_win.history.scrollRestoration = "manual"); 47093 var isNormalizing = _normalizer && _normalizer.isPressed; 47094 value = cachingFunc.v = Math.round(value) || (_normalizer && _normalizer.iOS ? 1 : 0); 47095 f(value); 47096 cachingFunc.cacheID = _scrollers.cache; 47097 isNormalizing && _bridge("ss", value); 47098 } else if (doNotCache || _scrollers.cache !== cachingFunc.cacheID || _bridge("ref")) { 47099 cachingFunc.cacheID = _scrollers.cache; 47100 cachingFunc.v = f(); 47101 } 47102
vendor: 13,754 bytes, lines 47103-47556
47103 return cachingFunc.v + cachingFunc.offset; 47104 }; 47105 47106 cachingFunc.offset = 0; 47107 return f && cachingFunc; 47108 }, 47109 _horizontal = { 47110 s: _scrollLeft, 47111 p: "left", 47112 p2: "Left", 47113 os: "right", 47114 os2: "Right", 47115 d: "width", 47116 d2: "Width", 47117 a: "x", 47118 sc: _scrollCacheFunc(function (value) { 47119 return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0; 47120 }) 47121 }, 47122 _vertical = { 47123 s: _scrollTop, 47124 p: "top", 47125 p2: "Top", 47126 os: "bottom", 47127 os2: "Bottom", 47128 d: "height", 47129 d2: "Height", 47130 a: "y", 47131 op: _horizontal, 47132 sc: _scrollCacheFunc(function (value) { 47133 return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0; 47134 }) 47135 }, 47136 _getTarget = function _getTarget(t, self) { 47137 return (self && self._ctx && self._ctx.selector || gsap.utils.toArray)(t)[0] || (typeof t === "string" && gsap.config().nullTargetWarn !== false ? console.warn("Element not found:", t) : null); 47138 }, 47139 _getScrollFunc = function _getScrollFunc(element, _ref) { 47140 var s = _ref.s, 47141 sc = _ref.sc; 47142 _isViewport(element) && (element = _doc.scrollingElement || _docEl); 47143 47144 var i = _scrollers.indexOf(element), 47145 offset = sc === _vertical.sc ? 1 : 2; 47146 47147 !~i && (i = _scrollers.push(element) - 1); 47148 _scrollers[i + offset] || _addListener(element, "scroll", _onScroll); 47149 var prev = _scrollers[i + offset], 47150 func = prev || (_scrollers[i + offset] = _scrollCacheFunc(_getProxyProp(element, s), true) || (_isViewport(element) ? sc : _scrollCacheFunc(function (value) { 47151 return arguments.length ? element[s] = value : element[s]; 47152 }))); 47153 func.target = element; 47154 prev || (func.smooth = gsap.getProperty(element, "scrollBehavior") === "smooth"); 47155 return func; 47156 }, 47157 _getVelocityProp = function _getVelocityProp(value, minTimeRefresh, useDelta) { 47158 var v1 = value, 47159 v2 = value, 47160 t1 = _getTime(), 47161 t2 = t1, 47162 min = minTimeRefresh || 50, 47163 dropToZeroTime = Math.max(500, min * 3), 47164 update = function update(value, force) { 47165 var t = _getTime(); 47166 47167 if (force || t - t1 > min) { 47168 v2 = v1; 47169 v1 = value; 47170 t2 = t1; 47171 t1 = t; 47172 } else if (useDelta) { 47173 v1 += value; 47174 } else { 47175 v1 = v2 + (value - v2) / (t - t2) * (t1 - t2); 47176 } 47177 }, 47178 reset = function reset() { 47179 v2 = v1 = useDelta ? 0 : v1; 47180 t2 = t1 = 0; 47181 }, 47182 getVelocity = function getVelocity(latestValue) { 47183 var tOld = t2, 47184 vOld = v2, 47185 t = _getTime(); 47186 47187 (latestValue || latestValue === 0) && latestValue !== v1 && update(latestValue); 47188 return t1 === t2 || t - t2 > dropToZeroTime ? 0 : (v1 + (useDelta ? vOld : -vOld)) / ((useDelta ? t : t1) - tOld) * 1000; 47189 }; 47190 47191 return { 47192 update: update, 47193 reset: reset, 47194 getVelocity: getVelocity 47195 }; 47196 }, 47197 _getEvent = function _getEvent(e, preventDefault) { 47198 preventDefault && !e._gsapAllow && e.preventDefault(); 47199 return e.changedTouches ? e.changedTouches[0] : e; 47200 }, 47201 _getAbsoluteMax = function _getAbsoluteMax(a) { 47202 var max = Math.max.apply(Math, a), 47203 min = Math.min.apply(Math, a); 47204 return Math.abs(max) >= Math.abs(min) ? max : min; 47205 }, 47206 _setScrollTrigger = function _setScrollTrigger() { 47207 ScrollTrigger = gsap.core.globals().ScrollTrigger; 47208 ScrollTrigger && ScrollTrigger.core && _integrate(); 47209 }, 47210 _initCore = function _initCore(core) { 47211 gsap = core || _getGSAP(); 47212 47213 if (!_coreInitted && gsap && typeof document !== "undefined" && document.body) { 47214 _win = window; 47215 _doc = document; 47216 _docEl = _doc.documentElement; 47217 _body = _doc.body; 47218 _root = [_win, _doc, _docEl, _body]; 47219 _clamp = gsap.utils.clamp; 47220 47221 _context = gsap.core.context || function () {}; 47222 47223 _pointerType = "onpointerenter" in _body ? "pointer" : "mouse"; 47224 _isTouch = Observer.isTouch = _win.matchMedia && _win.matchMedia("(hover: none), (pointer: coarse)").matches ? 1 : "ontouchstart" in _win || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 ? 2 : 0; 47225 _eventTypes = Observer.eventTypes = ("ontouchstart" in _docEl ? "touchstart,touchmove,touchcancel,touchend" : !("onpointerdown" in _docEl) ? "mousedown,mousemove,mouseup,mouseup" : "pointerdown,pointermove,pointercancel,pointerup").split(","); 47226 setTimeout(function () { 47227 return _startup = 0; 47228 }, 500); 47229 47230 _setScrollTrigger(); 47231 47232 _coreInitted = 1; 47233 } 47234 47235 return _coreInitted; 47236 }; 47237 47238 _horizontal.op = _vertical; 47239 _scrollers.cache = 0; 47240 var Observer = function () { 47241 function Observer(vars) { 47242 this.init(vars); 47243 } 47244 47245 var _proto = Observer.prototype; 47246 47247 _proto.init = function init(vars) { 47248 _coreInitted || _initCore(gsap) || console.warn("Please gsap.registerPlugin(Observer)"); 47249 ScrollTrigger || _setScrollTrigger(); 47250 var tolerance = vars.tolerance, 47251 dragMinimum = vars.dragMinimum, 47252 type = vars.type, 47253 target = vars.target, 47254 lineHeight = vars.lineHeight, 47255 debounce = vars.debounce, 47256 preventDefault = vars.preventDefault, 47257 onStop = vars.onStop, 47258 onStopDelay = vars.onStopDelay, 47259 ignore = vars.ignore, 47260 wheelSpeed = vars.wheelSpeed, 47261 event = vars.event, 47262 onDragStart = vars.onDragStart, 47263 onDragEnd = vars.onDragEnd, 47264 onDrag = vars.onDrag, 47265 onPress = vars.onPress, 47266 onRelease = vars.onRelease, 47267 onRight = vars.onRight, 47268 onLeft = vars.onLeft, 47269 onUp = vars.onUp, 47270 onDown = vars.onDown, 47271 onChangeX = vars.onChangeX, 47272 onChangeY = vars.onChangeY, 47273 onChange = vars.onChange, 47274 onToggleX = vars.onToggleX, 47275 onToggleY = vars.onToggleY, 47276 onHover = vars.onHover, 47277 onHoverEnd = vars.onHoverEnd, 47278 onMove = vars.onMove, 47279 ignoreCheck = vars.ignoreCheck, 47280 isNormalizer = vars.isNormalizer, 47281 onGestureStart = vars.onGestureStart, 47282 onGestureEnd = vars.onGestureEnd, 47283 onWheel = vars.onWheel, 47284 onEnable = vars.onEnable, 47285 onDisable = vars.onDisable, 47286 onClick = vars.onClick, 47287 scrollSpeed = vars.scrollSpeed, 47288 capture = vars.capture, 47289 allowClicks = vars.allowClicks, 47290 lockAxis = vars.lockAxis, 47291 onLockAxis = vars.onLockAxis; 47292 this.target = target = _getTarget(target) || _docEl; 47293 this.vars = vars; 47294 ignore && (ignore = gsap.utils.toArray(ignore)); 47295 tolerance = tolerance || 1e-9; 47296 dragMinimum = dragMinimum || 0; 47297 wheelSpeed = wheelSpeed || 1; 47298 scrollSpeed = scrollSpeed || 1; 47299 type = type || "wheel,touch,pointer"; 47300 debounce = debounce !== false; 47301 lineHeight || (lineHeight = parseFloat(_win.getComputedStyle(_body).lineHeight) || 22); 47302 47303 var id, 47304 onStopDelayedCall, 47305 dragged, 47306 moved, 47307 wheeled, 47308 locked, 47309 axis, 47310 self = this, 47311 prevDeltaX = 0, 47312 prevDeltaY = 0, 47313 passive = vars.passive || !preventDefault, 47314 scrollFuncX = _getScrollFunc(target, _horizontal), 47315 scrollFuncY = _getScrollFunc(target, _vertical), 47316 scrollX = scrollFuncX(), 47317 scrollY = scrollFuncY(), 47318 limitToTouch = ~type.indexOf("touch") && !~type.indexOf("pointer") && _eventTypes[0] === "pointerdown", 47319 isViewport = _isViewport(target), 47320 ownerDoc = target.ownerDocument || _doc, 47321 deltaX = [0, 0, 0], 47322 deltaY = [0, 0, 0], 47323 onClickTime = 0, 47324 clickCapture = function clickCapture() { 47325 return onClickTime = _getTime(); 47326 }, 47327 _ignoreCheck = function _ignoreCheck(e, isPointerOrTouch) { 47328 return (self.event = e) && ignore && ~ignore.indexOf(e.target) || isPointerOrTouch && limitToTouch && e.pointerType !== "touch" || ignoreCheck && ignoreCheck(e, isPointerOrTouch); 47329 }, 47330 onStopFunc = function onStopFunc() { 47331 self._vx.reset(); 47332 47333 self._vy.reset(); 47334 47335 onStopDelayedCall.pause(); 47336 onStop && onStop(self); 47337 }, 47338 update = function update() { 47339 var dx = self.deltaX = _getAbsoluteMax(deltaX), 47340 dy = self.deltaY = _getAbsoluteMax(deltaY), 47341 changedX = Math.abs(dx) >= tolerance, 47342 changedY = Math.abs(dy) >= tolerance; 47343 47344 onChange && (changedX || changedY) && onChange(self, dx, dy, deltaX, deltaY); 47345 47346 if (changedX) { 47347 onRight && self.deltaX > 0 && onRight(self); 47348 onLeft && self.deltaX < 0 && onLeft(self); 47349 onChangeX && onChangeX(self); 47350 onToggleX && self.deltaX < 0 !== prevDeltaX < 0 && onToggleX(self); 47351 prevDeltaX = self.deltaX; 47352 deltaX[0] = deltaX[1] = deltaX[2] = 0; 47353 } 47354 47355 if (changedY) { 47356 onDown && self.deltaY > 0 && onDown(self); 47357 onUp && self.deltaY < 0 && onUp(self); 47358 onChangeY && onChangeY(self); 47359 onToggleY && self.deltaY < 0 !== prevDeltaY < 0 && onToggleY(self); 47360 prevDeltaY = self.deltaY; 47361 deltaY[0] = deltaY[1] = deltaY[2] = 0; 47362 } 47363 47364 if (moved || dragged) { 47365 onMove && onMove(self); 47366 47367 if (dragged) { 47368 onDrag(self); 47369 dragged = false; 47370 } 47371 47372 moved = false; 47373 } 47374 47375 locked && !(locked = false) && onLockAxis && onLockAxis(self); 47376 47377 if (wheeled) { 47378 onWheel(self); 47379 wheeled = false; 47380 } 47381 47382 id = 0; 47383 }, 47384 onDelta = function onDelta(x, y, index) { 47385 deltaX[index] += x; 47386 deltaY[index] += y; 47387 47388 self._vx.update(x); 47389 47390 self._vy.update(y); 47391 47392 debounce ? id || (id = requestAnimationFrame(update)) : update(); 47393 }, 47394 onTouchOrPointerDelta = function onTouchOrPointerDelta(x, y) { 47395 if (lockAxis && !axis) { 47396 self.axis = axis = Math.abs(x) > Math.abs(y) ? "x" : "y"; 47397 locked = true; 47398 } 47399 47400 if (axis !== "y") { 47401 deltaX[2] += x; 47402 47403 self._vx.update(x, true); 47404 } 47405 47406 if (axis !== "x") { 47407 deltaY[2] += y; 47408 47409 self._vy.update(y, true); 47410 } 47411 47412 debounce ? id || (id = requestAnimationFrame(update)) : update(); 47413 }, 47414 _onDrag = function _onDrag(e) { 47415 if (_ignoreCheck(e, 1)) { 47416 return; 47417 } 47418 47419 e = _getEvent(e, preventDefault); 47420 var x = e.clientX, 47421 y = e.clientY, 47422 dx = x - self.x, 47423 dy = y - self.y, 47424 isDragging = self.isDragging; 47425 self.x = x; 47426 self.y = y; 47427 47428 if (isDragging || Math.abs(self.startX - x) >= dragMinimum || Math.abs(self.startY - y) >= dragMinimum) { 47429 onDrag && (dragged = true); 47430 isDragging || (self.isDragging = true); 47431 onTouchOrPointerDelta(dx, dy); 47432 isDragging || onDragStart && onDragStart(self); 47433 } 47434 }, 47435 _onPress = self.onPress = function (e) { 47436 if (_ignoreCheck(e, 1) || e && e.button) { 47437 return; 47438 } 47439 47440 self.axis = axis = null; 47441 onStopDelayedCall.pause(); 47442 self.isPressed = true; 47443 e = _getEvent(e); 47444 prevDeltaX = prevDeltaY = 0; 47445 self.startX = self.x = e.clientX; 47446 self.startY = self.y = e.clientY; 47447 47448 self._vx.reset(); 47449 47450 self._vy.reset(); 47451 47452 _addListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, passive, true); 47453 47454 self.deltaX = self.deltaY = 0; 47455 onPress && onPress(self); 47456 }, 47457 _onRelease = self.onRelease = function (e) { 47458 if (_ignoreCheck(e, 1)) { 47459 return; 47460 } 47461 47462 _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true); 47463 47464 var isTrackingDrag = !isNaN(self.y - self.startY), 47465 wasDragging = self.isDragging, 47466 isDragNotClick = wasDragging && (Math.abs(self.x - self.startX) > 3 || Math.abs(self.y - self.startY) > 3), 47467 eventData = _getEvent(e); 47468 47469 if (!isDragNotClick && isTrackingDrag) { 47470 self._vx.reset(); 47471 47472 self._vy.reset(); 47473 47474 if (preventDefault && allowClicks) { 47475 gsap.delayedCall(0.08, function () { 47476 if (_getTime() - onClickTime > 300 && !e.defaultPrevented) { 47477 if (e.target.click) { 47478 e.target.click(); 47479 } else if (ownerDoc.createEvent) { 47480 var syntheticEvent = ownerDoc.createEvent("MouseEvents"); 47481 syntheticEvent.initMouseEvent("click", true, true, _win, 1, eventData.screenX, eventData.screenY, eventData.clientX, eventData.clientY, false, false, false, false, 0, null); 47482 e.target.dispatchEvent(syntheticEvent); 47483 } 47484 } 47485 }); 47486 } 47487 } 47488 47489 self.isDragging = self.isGesturing = self.isPressed = false; 47490 onStop && wasDragging && !isNormalizer && onStopDelayedCall.restart(true); 47491 onDragEnd && wasDragging && onDragEnd(self); 47492 onRelease && onRelease(self, isDragNotClick); 47493 }, 47494 _onGestureStart = function _onGestureStart(e) { 47495 return e.touches && e.touches.length > 1 && (self.isGesturing = true) && onGestureStart(e, self.isDragging); 47496 }, 47497 _onGestureEnd = function _onGestureEnd() { 47498 return (self.isGesturing = false) || onGestureEnd(self); 47499 }, 47500 onScroll = function onScroll(e) { 47501 if (_ignoreCheck(e)) { 47502 return; 47503 } 47504 47505 var x = scrollFuncX(), 47506 y = scrollFuncY(); 47507 onDelta((x - scrollX) * scrollSpeed, (y - scrollY) * scrollSpeed, 1); 47508 scrollX = x; 47509 scrollY = y; 47510 onStop && onStopDelayedCall.restart(true); 47511 }, 47512 _onWheel = function _onWheel(e) { 47513 if (_ignoreCheck(e)) { 47514 return; 47515 } 47516 47517 e = _getEvent(e, preventDefault); 47518 onWheel && (wheeled = true); 47519 var multiplier = (e.deltaMode === 1 ? lineHeight : e.deltaMode === 2 ? _win.innerHeight : 1) * wheelSpeed; 47520 onDelta(e.deltaX * multiplier, e.deltaY * multiplier, 0); 47521 onStop && !isNormalizer && onStopDelayedCall.restart(true); 47522 }, 47523 _onMove = function _onMove(e) { 47524 if (_ignoreCheck(e)) { 47525 return; 47526 } 47527 47528 var x = e.clientX, 47529 y = e.clientY, 47530 dx = x - self.x, 47531 dy = y - self.y; 47532 self.x = x; 47533 self.y = y; 47534 moved = true; 47535 onStop && onStopDelayedCall.restart(true); 47536 (dx || dy) && onTouchOrPointerDelta(dx, dy); 47537 }, 47538 _onHover = function _onHover(e) { 47539 self.event = e; 47540 onHover(self); 47541 }, 47542 _onHoverEnd = function _onHoverEnd(e) { 47543 self.event = e; 47544 onHoverEnd(self); 47545 }, 47546 _onClick = function _onClick(e) { 47547 return _ignoreCheck(e) || _getEvent(e, preventDefault) && onClick(self); 47548 }; 47549 47550 onStopDelayedCall = self._dc = gsap.delayedCall(onStopDelay || 0.25, onStopFunc).pause(); 47551 self.deltaX = self.deltaY = 0; 47552 self._vx = _getVelocityProp(0, 50, true); 47553 self._vy = _getVelocityProp(0, 50, true); 47554 self.scrollX = scrollFuncX; 47555 self.scrollY = scrollFuncY; 47556 self.isDragging = self.isGesturing = self.isPressed = false;
vendor: 7,173 bytes, lines 47557-47799
47557 47558 _context(this); 47559 47560 self.enable = function (e) { 47561 if (!self.isEnabled) { 47562 _addListener(isViewport ? ownerDoc : target, "scroll", _onScroll); 47563 47564 type.indexOf("scroll") >= 0 && _addListener(isViewport ? ownerDoc : target, "scroll", onScroll, passive, capture); 47565 type.indexOf("wheel") >= 0 && _addListener(target, "wheel", _onWheel, passive, capture); 47566 47567 if (type.indexOf("touch") >= 0 && _isTouch || type.indexOf("pointer") >= 0) { 47568 _addListener(target, _eventTypes[0], _onPress, passive, capture); 47569 47570 _addListener(ownerDoc, _eventTypes[2], _onRelease); 47571 47572 _addListener(ownerDoc, _eventTypes[3], _onRelease); 47573 47574 allowClicks && _addListener(target, "click", clickCapture, true, true); 47575 onClick && _addListener(target, "click", _onClick); 47576 onGestureStart && _addListener(ownerDoc, "gesturestart", _onGestureStart); 47577 onGestureEnd && _addListener(ownerDoc, "gestureend", _onGestureEnd); 47578 onHover && _addListener(target, _pointerType + "enter", _onHover); 47579 onHoverEnd && _addListener(target, _pointerType + "leave", _onHoverEnd); 47580 onMove && _addListener(target, _pointerType + "move", _onMove); 47581 } 47582 47583 self.isEnabled = true; 47584 e && e.type && _onPress(e); 47585 onEnable && onEnable(self); 47586 } 47587 47588 return self; 47589 }; 47590 47591 self.disable = function () { 47592 if (self.isEnabled) { 47593 _observers.filter(function (o) { 47594 return o !== self && _isViewport(o.target); 47595 }).length || _removeListener(isViewport ? ownerDoc : target, "scroll", _onScroll); 47596 47597 if (self.isPressed) { 47598 self._vx.reset(); 47599 47600 self._vy.reset(); 47601 47602 _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true); 47603 } 47604 47605 _removeListener(isViewport ? ownerDoc : target, "scroll", onScroll, capture); 47606 47607 _removeListener(target, "wheel", _onWheel, capture); 47608 47609 _removeListener(target, _eventTypes[0], _onPress, capture); 47610 47611 _removeListener(ownerDoc, _eventTypes[2], _onRelease); 47612 47613 _removeListener(ownerDoc, _eventTypes[3], _onRelease); 47614 47615 _removeListener(target, "click", clickCapture, true); 47616 47617 _removeListener(target, "click", _onClick); 47618 47619 _removeListener(ownerDoc, "gesturestart", _onGestureStart); 47620 47621 _removeListener(ownerDoc, "gestureend", _onGestureEnd); 47622 47623 _removeListener(target, _pointerType + "enter", _onHover); 47624 47625 _removeListener(target, _pointerType + "leave", _onHoverEnd); 47626 47627 _removeListener(target, _pointerType + "move", _onMove); 47628 47629 self.isEnabled = self.isPressed = self.isDragging = false; 47630 onDisable && onDisable(self); 47631 } 47632 }; 47633 47634 self.kill = self.revert = function () { 47635 self.disable(); 47636 47637 var i = _observers.indexOf(self); 47638 47639 i >= 0 && _observers.splice(i, 1); 47640 _normalizer === self && (_normalizer = 0); 47641 }; 47642 47643 _observers.push(self); 47644 47645 isNormalizer && _isViewport(target) && (_normalizer = self); 47646 self.enable(event); 47647 }; 47648 47649 _createClass(Observer, [{ 47650 key: "velocityX", 47651 get: function get() { 47652 return this._vx.getVelocity(); 47653 } 47654 }, { 47655 key: "velocityY", 47656 get: function get() { 47657 return this._vy.getVelocity(); 47658 } 47659 }]); 47660 47661 return Observer; 47662 }(); 47663 Observer.version = "3.12.5"; 47664 47665 Observer.create = function (vars) { 47666 return new Observer(vars); 47667 }; 47668 47669 Observer.register = _initCore; 47670 47671 Observer.getAll = function () { 47672 return _observers.slice(); 47673 }; 47674 47675 Observer.getById = function (id) { 47676 return _observers.filter(function (o) { 47677 return o.vars.id === id; 47678 })[0]; 47679 }; 47680 47681 _getGSAP() && gsap.registerPlugin(Observer); 47682 47683 /*! 47684 * ScrollTrigger 3.12.5 47685 * https://gsap.com 47686 * 47687 * @license Copyright 2008-2024, GreenSock. All rights reserved. 47688 * Subject to the terms at https://gsap.com/standard-license or for 47689 * Club GSAP members, the agreement issued with that membership. 47690 * @author: Jack Doyle, [email protected] 47691 */ 47692 47693 var gsap$1, 47694 _coreInitted$1, 47695 _win$1, 47696 _doc$1, 47697 _docEl$1, 47698 _body$1, 47699 _root$1, 47700 _resizeDelay, 47701 _toArray, 47702 _clamp$1, 47703 _time2, 47704 _syncInterval, 47705 _refreshing, 47706 _pointerIsDown, 47707 _transformProp, 47708 _i, 47709 _prevWidth, 47710 _prevHeight, 47711 _autoRefresh, 47712 _sort, 47713 _suppressOverwrites, 47714 _ignoreResize, 47715 _normalizer$1, 47716 _ignoreMobileResize, 47717 _baseScreenHeight, 47718 _baseScreenWidth, 47719 _fixIOSBug, 47720 _context$1, 47721 _scrollRestoration, 47722 _div100vh, 47723 _100vh, 47724 _isReverted, 47725 _clampingMax, 47726 _limitCallbacks, 47727 _startup$1 = 1, 47728 _getTime$1 = Date.now, 47729 _time1 = _getTime$1(), 47730 _lastScrollTime = 0, 47731 _enabled = 0, 47732 _parseClamp = function _parseClamp(value, type, self) { 47733 var clamp = _isString(value) && (value.substr(0, 6) === "clamp(" || value.indexOf("max") > -1); 47734 self["_" + type + "Clamp"] = clamp; 47735 return clamp ? value.substr(6, value.length - 7) : value; 47736 }, 47737 _keepClamp = function _keepClamp(value, clamp) { 47738 return clamp && (!_isString(value) || value.substr(0, 6) !== "clamp(") ? "clamp(" + value + ")" : value; 47739 }, 47740 _rafBugFix = function _rafBugFix() { 47741 return _enabled && requestAnimationFrame(_rafBugFix); 47742 }, 47743 _pointerDownHandler = function _pointerDownHandler() { 47744 return _pointerIsDown = 1; 47745 }, 47746 _pointerUpHandler = function _pointerUpHandler() { 47747 return _pointerIsDown = 0; 47748 }, 47749 _passThrough = function _passThrough(v) { 47750 return v; 47751 }, 47752 _round = function _round(value) { 47753 return Math.round(value * 100000) / 100000 || 0; 47754 }, 47755 _windowExists = function _windowExists() { 47756 return typeof window !== "undefined"; 47757 }, 47758 _getGSAP$1 = function _getGSAP() { 47759 return gsap$1 || _windowExists() && (gsap$1 = window.gsap) && gsap$1.registerPlugin && gsap$1; 47760 }, 47761 _isViewport$1 = function _isViewport(e) { 47762 return !!~_root$1.indexOf(e); 47763 }, 47764 _getViewportDimension = function _getViewportDimension(dimensionProperty) { 47765 return (dimensionProperty === "Height" ? _100vh : _win$1["inner" + dimensionProperty]) || _docEl$1["client" + dimensionProperty] || _body$1["client" + dimensionProperty]; 47766 }, 47767 _getBoundsFunc = function _getBoundsFunc(element) { 47768 return _getProxyProp(element, "getBoundingClientRect") || (_isViewport$1(element) ? function () { 47769 _winOffsets.width = _win$1.innerWidth; 47770 _winOffsets.height = _100vh; 47771 return _winOffsets; 47772 } : function () { 47773 return _getBounds(element); 47774 }); 47775 }, 47776 _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref) { 47777 var d = _ref.d, 47778 d2 = _ref.d2, 47779 a = _ref.a; 47780 return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () { 47781 return a()[d]; 47782 } : function () { 47783 return (isViewport ? _getViewportDimension(d2) : scroller["client" + d2]) || 0; 47784 }; 47785 }, 47786 _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) { 47787 return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () { 47788 return _winOffsets; 47789 }; 47790 }, 47791 _maxScroll = function _maxScroll(element, _ref2) { 47792 var s = _ref2.s, 47793 d2 = _ref2.d2, 47794 d = _ref2.d, 47795 a = _ref2.a; 47796 return Math.max(0, (s = "scroll" + d2) && (a = _getProxyProp(element, s)) ? a() - _getBoundsFunc(element)()[d] : _isViewport$1(element) ? (_docEl$1[s] || _body$1[s]) - _getViewportDimension(d2) : element[s] - element["offset" + d2]); 47797 }, 47798 _iterateAutoRefresh = function _iterateAutoRefresh(func, events) { 47799 for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 4,900 bytes, lines 47800-47981
47800 (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]); 47801 } 47802 }, 47803 _isString = function _isString(value) { 47804 return typeof value === "string"; 47805 }, 47806 _isFunction = function _isFunction(value) { 47807 return typeof value === "function"; 47808 }, 47809 _isNumber = function _isNumber(value) { 47810 return typeof value === "number"; 47811 }, 47812 _isObject = function _isObject(value) { 47813 return typeof value === "object"; 47814 }, 47815 _endAnimation = function _endAnimation(animation, reversed, pause) { 47816 return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause(); 47817 }, 47818 _callback = function _callback(self, func) { 47819 if (self.enabled) { 47820 var result = self._ctx ? self._ctx.add(function () { 47821 return func(self); 47822 }) : func(self); 47823 result && result.totalTime && (self.callbackAnimation = result); 47824 } 47825 }, 47826 _abs = Math.abs, 47827 _left = "left", 47828 _top = "top", 47829 _right = "right", 47830 _bottom = "bottom", 47831 _width = "width", 47832 _height = "height", 47833 _Right = "Right", 47834 _Left = "Left", 47835 _Top = "Top", 47836 _Bottom = "Bottom", 47837 _padding = "padding", 47838 _margin = "margin", 47839 _Width = "Width", 47840 _Height = "Height", 47841 _px = "px", 47842 _getComputedStyle = function _getComputedStyle(element) { 47843 return _win$1.getComputedStyle(element); 47844 }, 47845 _makePositionable = function _makePositionable(element) { 47846 var position = _getComputedStyle(element).position; 47847 47848 element.style.position = position === "absolute" || position === "fixed" ? position : "relative"; 47849 }, 47850 _setDefaults = function _setDefaults(obj, defaults) { 47851 for (var p in defaults) { 47852 p in obj || (obj[p] = defaults[p]); 47853 } 47854 47855 return obj; 47856 }, 47857 _getBounds = function _getBounds(element, withoutTransforms) { 47858 var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap$1.to(element, { 47859 x: 0, 47860 y: 0, 47861 xPercent: 0, 47862 yPercent: 0, 47863 rotation: 0, 47864 rotationX: 0, 47865 rotationY: 0, 47866 scale: 1, 47867 skewX: 0, 47868 skewY: 0 47869 }).progress(1), 47870 bounds = element.getBoundingClientRect(); 47871 tween && tween.progress(0).kill(); 47872 return bounds; 47873 }, 47874 _getSize = function _getSize(element, _ref3) { 47875 var d2 = _ref3.d2; 47876 return element["offset" + d2] || element["client" + d2] || 0; 47877 }, 47878 _getLabelRatioArray = function _getLabelRatioArray(timeline) { 47879 var a = [], 47880 labels = timeline.labels, 47881 duration = timeline.duration(), 47882 p; 47883 47884 for (p in labels) { 47885 a.push(labels[p] / duration); 47886 } 47887 47888 return a; 47889 }, 47890 _getClosestLabel = function _getClosestLabel(animation) { 47891 return function (value) { 47892 return gsap$1.utils.snap(_getLabelRatioArray(animation), value); 47893 }; 47894 }, 47895 _snapDirectional = function _snapDirectional(snapIncrementOrArray) { 47896 var snap = gsap$1.utils.snap(snapIncrementOrArray), 47897 a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) { 47898 return a - b; 47899 }); 47900 return a ? function (value, direction, threshold) { 47901 if (threshold === void 0) { 47902 threshold = 1e-3; 47903 } 47904 47905 var i; 47906 47907 if (!direction) { 47908 return snap(value); 47909 } 47910 47911 if (direction > 0) { 47912 value -= threshold; 47913 47914 for (i = 0; i < a.length; i++) { 47915 if (a[i] >= value) { 47916 return a[i]; 47917 } 47918 } 47919 47920 return a[i - 1]; 47921 } else { 47922 i = a.length; 47923 value += threshold; 47924 47925 while (i--) { 47926 if (a[i] <= value) { 47927 return a[i]; 47928 } 47929 } 47930 } 47931 47932 return a[0]; 47933 } : function (value, direction, threshold) { 47934 if (threshold === void 0) { 47935 threshold = 1e-3; 47936 } 47937 47938 var snapped = snap(value); 47939 return !direction || Math.abs(snapped - value) < threshold || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray); 47940 }; 47941 }, 47942 _getLabelAtDirection = function _getLabelAtDirection(timeline) { 47943 return function (value, st) { 47944 return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction); 47945 }; 47946 }, 47947 _multiListener = function _multiListener(func, element, types, callback) { 47948 return types.split(",").forEach(function (type) { 47949 return func(element, type, callback); 47950 }); 47951 }, 47952 _addListener$1 = function _addListener(element, type, func, nonPassive, capture) { 47953 return element.addEventListener(type, func, { 47954 passive: !nonPassive, 47955 capture: !!capture 47956 }); 47957 }, 47958 _removeListener$1 = function _removeListener(element, type, func, capture) { 47959 return element.removeEventListener(type, func, !!capture); 47960 }, 47961 _wheelListener = function _wheelListener(func, el, scrollFunc) { 47962 scrollFunc = scrollFunc && scrollFunc.wheelHandler; 47963 47964 if (scrollFunc) { 47965 func(el, "wheel", scrollFunc); 47966 func(el, "touchmove", scrollFunc); 47967 } 47968 }, 47969 _markerDefaults = { 47970 startColor: "green", 47971 endColor: "red", 47972 indent: 0, 47973 fontSize: "16px", 47974 fontWeight: "normal" 47975 }, 47976 _defaults = { 47977 toggleActions: "play", 47978 anticipatePin: 0 47979 }, 47980 _keywords = { 47981 top: 0,
vendor: 14,119 bytes, lines 47982-48422
47982 left: 0, 47983 center: 0.5, 47984 bottom: 1, 47985 right: 1 47986 }, 47987 _offsetToPx = function _offsetToPx(value, size) { 47988 if (_isString(value)) { 47989 var eqIndex = value.indexOf("="), 47990 relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0; 47991 47992 if (~eqIndex) { 47993 value.indexOf("%") > eqIndex && (relative *= size / 100); 47994 value = value.substr(0, eqIndex - 1); 47995 } 47996 47997 value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0); 47998 } 47999 48000 return value; 48001 }, 48002 _createMarker = function _createMarker(type, name, container, direction, _ref4, offset, matchWidthEl, containerAnimation) { 48003 var startColor = _ref4.startColor, 48004 endColor = _ref4.endColor, 48005 fontSize = _ref4.fontSize, 48006 indent = _ref4.indent, 48007 fontWeight = _ref4.fontWeight; 48008 48009 var e = _doc$1.createElement("div"), 48010 useFixedPosition = _isViewport$1(container) || _getProxyProp(container, "pinType") === "fixed", 48011 isScroller = type.indexOf("scroller") !== -1, 48012 parent = useFixedPosition ? _body$1 : container, 48013 isStart = type.indexOf("start") !== -1, 48014 color = isStart ? startColor : endColor, 48015 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;"; 48016 48017 css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;"); 48018 (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;"); 48019 matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;"); 48020 e._isStart = isStart; 48021 e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : "")); 48022 e.style.cssText = css; 48023 e.innerText = name || name === 0 ? type + "-" + name : type; 48024 parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e); 48025 e._offset = e["offset" + direction.op.d2]; 48026 48027 _positionMarker(e, 0, direction, isStart); 48028 48029 return e; 48030 }, 48031 _positionMarker = function _positionMarker(marker, start, direction, flipped) { 48032 var vars = { 48033 display: "block" 48034 }, 48035 side = direction[flipped ? "os2" : "p2"], 48036 oppositeSide = direction[flipped ? "p2" : "os2"]; 48037 marker._isFlipped = flipped; 48038 vars[direction.a + "Percent"] = flipped ? -100 : 0; 48039 vars[direction.a] = flipped ? "1px" : 0; 48040 vars["border" + side + _Width] = 1; 48041 vars["border" + oppositeSide + _Width] = 0; 48042 vars[direction.p] = start + "px"; 48043 gsap$1.set(marker, vars); 48044 }, 48045 _triggers = [], 48046 _ids = {}, 48047 _rafID, 48048 _sync = function _sync() { 48049 return _getTime$1() - _lastScrollTime > 34 && (_rafID || (_rafID = requestAnimationFrame(_updateAll))); 48050 }, 48051 _onScroll$1 = function _onScroll() { 48052 if (!_normalizer$1 || !_normalizer$1.isPressed || _normalizer$1.startX > _body$1.clientWidth) { 48053 _scrollers.cache++; 48054 48055 if (_normalizer$1) { 48056 _rafID || (_rafID = requestAnimationFrame(_updateAll)); 48057 } else { 48058 _updateAll(); 48059 } 48060 48061 _lastScrollTime || _dispatch("scrollStart"); 48062 _lastScrollTime = _getTime$1(); 48063 } 48064 }, 48065 _setBaseDimensions = function _setBaseDimensions() { 48066 _baseScreenWidth = _win$1.innerWidth; 48067 _baseScreenHeight = _win$1.innerHeight; 48068 }, 48069 _onResize = function _onResize() { 48070 _scrollers.cache++; 48071 !_refreshing && !_ignoreResize && !_doc$1.fullscreenElement && !_doc$1.webkitFullscreenElement && (!_ignoreMobileResize || _baseScreenWidth !== _win$1.innerWidth || Math.abs(_win$1.innerHeight - _baseScreenHeight) > _win$1.innerHeight * 0.25) && _resizeDelay.restart(true); 48072 }, 48073 _listeners = {}, 48074 _emptyArray = [], 48075 _softRefresh = function _softRefresh() { 48076 return _removeListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh) || _refreshAll(true); 48077 }, 48078 _dispatch = function _dispatch(type) { 48079 return _listeners[type] && _listeners[type].map(function (f) { 48080 return f(); 48081 }) || _emptyArray; 48082 }, 48083 _savedStyles = [], 48084 _revertRecorded = function _revertRecorded(media) { 48085 for (var i = 0; i < _savedStyles.length; i += 5) { 48086 if (!media || _savedStyles[i + 4] && _savedStyles[i + 4].query === media) { 48087 _savedStyles[i].style.cssText = _savedStyles[i + 1]; 48088 _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || ""); 48089 _savedStyles[i + 3].uncache = 1; 48090 } 48091 } 48092 }, 48093 _revertAll = function _revertAll(kill, media) { 48094 var trigger; 48095 48096 for (_i = 0; _i < _triggers.length; _i++) { 48097 trigger = _triggers[_i]; 48098 48099 if (trigger && (!media || trigger._ctx === media)) { 48100 if (kill) { 48101 trigger.kill(1); 48102 } else { 48103 trigger.revert(true, true); 48104 } 48105 } 48106 } 48107 48108 _isReverted = true; 48109 media && _revertRecorded(media); 48110 media || _dispatch("revert"); 48111 }, 48112 _clearScrollMemory = function _clearScrollMemory(scrollRestoration, force) { 48113 _scrollers.cache++; 48114 (force || !_refreshingAll) && _scrollers.forEach(function (obj) { 48115 return _isFunction(obj) && obj.cacheID++ && (obj.rec = 0); 48116 }); 48117 _isString(scrollRestoration) && (_win$1.history.scrollRestoration = _scrollRestoration = scrollRestoration); 48118 }, 48119 _refreshingAll, 48120 _refreshID = 0, 48121 _queueRefreshID, 48122 _queueRefreshAll = function _queueRefreshAll() { 48123 if (_queueRefreshID !== _refreshID) { 48124 var id = _queueRefreshID = _refreshID; 48125 requestAnimationFrame(function () { 48126 return id === _refreshID && _refreshAll(true); 48127 }); 48128 } 48129 }, 48130 _refresh100vh = function _refresh100vh() { 48131 _body$1.appendChild(_div100vh); 48132 48133 _100vh = !_normalizer$1 && _div100vh.offsetHeight || _win$1.innerHeight; 48134 48135 _body$1.removeChild(_div100vh); 48136 }, 48137 _hideAllMarkers = function _hideAllMarkers(hide) { 48138 return _toArray(".gsap-marker-start, .gsap-marker-end, .gsap-marker-scroller-start, .gsap-marker-scroller-end").forEach(function (el) { 48139 return el.style.display = hide ? "none" : "block"; 48140 }); 48141 }, 48142 _refreshAll = function _refreshAll(force, skipRevert) { 48143 if (_lastScrollTime && !force && !_isReverted) { 48144 _addListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh); 48145 48146 return; 48147 } 48148 48149 _refresh100vh(); 48150 48151 _refreshingAll = ScrollTrigger$1.isRefreshing = true; 48152 48153 _scrollers.forEach(function (obj) { 48154 return _isFunction(obj) && ++obj.cacheID && (obj.rec = obj()); 48155 }); 48156 48157 var refreshInits = _dispatch("refreshInit"); 48158 48159 _sort && ScrollTrigger$1.sort(); 48160 skipRevert || _revertAll(); 48161 48162 _scrollers.forEach(function (obj) { 48163 if (_isFunction(obj)) { 48164 obj.smooth && (obj.target.style.scrollBehavior = "auto"); 48165 obj(0); 48166 } 48167 }); 48168 48169 _triggers.slice(0).forEach(function (t) { 48170 return t.refresh(); 48171 }); 48172 48173 _isReverted = false; 48174 48175 _triggers.forEach(function (t) { 48176 if (t._subPinOffset && t.pin) { 48177 var prop = t.vars.horizontal ? "offsetWidth" : "offsetHeight", 48178 original = t.pin[prop]; 48179 t.revert(true, 1); 48180 t.adjustPinSpacing(t.pin[prop] - original); 48181 t.refresh(); 48182 } 48183 }); 48184 48185 _clampingMax = 1; 48186 48187 _hideAllMarkers(true); 48188 48189 _triggers.forEach(function (t) { 48190 var max = _maxScroll(t.scroller, t._dir), 48191 endClamp = t.vars.end === "max" || t._endClamp && t.end > max, 48192 startClamp = t._startClamp && t.start >= max; 48193 48194 (endClamp || startClamp) && t.setPositions(startClamp ? max - 1 : t.start, endClamp ? Math.max(startClamp ? max : t.start + 1, max) : t.end, true); 48195 }); 48196 48197 _hideAllMarkers(false); 48198 48199 _clampingMax = 0; 48200 refreshInits.forEach(function (result) { 48201 return result && result.render && result.render(-1); 48202 }); 48203 48204 _scrollers.forEach(function (obj) { 48205 if (_isFunction(obj)) { 48206 obj.smooth && requestAnimationFrame(function () { 48207 return obj.target.style.scrollBehavior = "smooth"; 48208 }); 48209 obj.rec && obj(obj.rec); 48210 } 48211 }); 48212 48213 _clearScrollMemory(_scrollRestoration, 1); 48214 48215 _resizeDelay.pause(); 48216 48217 _refreshID++; 48218 _refreshingAll = 2; 48219 48220 _updateAll(2); 48221 48222 _triggers.forEach(function (t) { 48223 return _isFunction(t.vars.onRefresh) && t.vars.onRefresh(t); 48224 }); 48225 48226 _refreshingAll = ScrollTrigger$1.isRefreshing = false; 48227 48228 _dispatch("refresh"); 48229 }, 48230 _lastScroll = 0, 48231 _direction = 1, 48232 _primary, 48233 _updateAll = function _updateAll(force) { 48234 if (force === 2 || !_refreshingAll && !_isReverted) { 48235 ScrollTrigger$1.isUpdating = true; 48236 _primary && _primary.update(0); 48237 48238 var l = _triggers.length, 48239 time = _getTime$1(), 48240 recordVelocity = time - _time1 >= 50, 48241 scroll = l && _triggers[0].scroll(); 48242 48243 _direction = _lastScroll > scroll ? -1 : 1; 48244 _refreshingAll || (_lastScroll = scroll); 48245 48246 if (recordVelocity) { 48247 if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) { 48248 _lastScrollTime = 0; 48249 48250 _dispatch("scrollEnd"); 48251 } 48252 48253 _time2 = _time1; 48254 _time1 = time; 48255 } 48256 48257 if (_direction < 0) { 48258 _i = l; 48259 48260 while (_i-- > 0) { 48261 _triggers[_i] && _triggers[_i].update(0, recordVelocity); 48262 } 48263 48264 _direction = 1; 48265 } else { 48266 for (_i = 0; _i < l; _i++) { 48267 _triggers[_i] && _triggers[_i].update(0, recordVelocity); 48268 } 48269 } 48270 48271 ScrollTrigger$1.isUpdating = false; 48272 } 48273 48274 _rafID = 0; 48275 }, 48276 _propNamesToCopy = [_left, _top, _bottom, _right, _margin + _Bottom, _margin + _Right, _margin + _Top, _margin + _Left, "display", "flexShrink", "float", "zIndex", "gridColumnStart", "gridColumnEnd", "gridRowStart", "gridRowEnd", "gridArea", "justifySelf", "alignSelf", "placeSelf", "order"], 48277 _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]), 48278 _swapPinOut = function _swapPinOut(pin, spacer, state) { 48279 _setState(state); 48280 48281 var cache = pin._gsap; 48282 48283 if (cache.spacerIsNative) { 48284 _setState(cache.spacerState); 48285 } else if (pin._gsap.swappedIn) { 48286 var parent = spacer.parentNode; 48287 48288 if (parent) { 48289 parent.insertBefore(pin, spacer); 48290 parent.removeChild(spacer); 48291 } 48292 } 48293 48294 pin._gsap.swappedIn = false; 48295 }, 48296 _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) { 48297 if (!pin._gsap.swappedIn) { 48298 var i = _propNamesToCopy.length, 48299 spacerStyle = spacer.style, 48300 pinStyle = pin.style, 48301 p; 48302 48303 while (i--) { 48304 p = _propNamesToCopy[i]; 48305 spacerStyle[p] = cs[p]; 48306 } 48307 48308 spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative"; 48309 cs.display === "inline" && (spacerStyle.display = "inline-block"); 48310 pinStyle[_bottom] = pinStyle[_right] = "auto"; 48311 spacerStyle.flexBasis = cs.flexBasis || "auto"; 48312 spacerStyle.overflow = "visible"; 48313 spacerStyle.boxSizing = "border-box"; 48314 spacerStyle[_width] = _getSize(pin, _horizontal) + _px; 48315 spacerStyle[_height] = _getSize(pin, _vertical) + _px; 48316 spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0"; 48317 48318 _setState(spacerState); 48319 48320 pinStyle[_width] = pinStyle["max" + _Width] = cs[_width]; 48321 pinStyle[_height] = pinStyle["max" + _Height] = cs[_height]; 48322 pinStyle[_padding] = cs[_padding]; 48323 48324 if (pin.parentNode !== spacer) { 48325 pin.parentNode.insertBefore(spacer, pin); 48326 spacer.appendChild(pin); 48327 } 48328 48329 pin._gsap.swappedIn = true; 48330 } 48331 }, 48332 _capsExp = /([A-Z])/g, 48333 _setState = function _setState(state) { 48334 if (state) { 48335 var style = state.t.style, 48336 l = state.length, 48337 i = 0, 48338 p, 48339 value; 48340 (state.t._gsap || gsap$1.core.getCache(state.t)).uncache = 1; 48341 48342 for (; i < l; i += 2) { 48343 value = state[i + 1]; 48344 p = state[i]; 48345 48346 if (value) { 48347 style[p] = value; 48348 } else if (style[p]) { 48349 style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase()); 48350 } 48351 } 48352 } 48353 }, 48354 _getState = function _getState(element) { 48355 var l = _stateProps.length, 48356 style = element.style, 48357 state = [], 48358 i = 0; 48359 48360 for (; i < l; i++) { 48361 state.push(_stateProps[i], style[_stateProps[i]]); 48362 } 48363 48364 state.t = element; 48365 return state; 48366 }, 48367 _copyState = function _copyState(state, override, omitOffsets) { 48368 var result = [], 48369 l = state.length, 48370 i = omitOffsets ? 8 : 0, 48371 p; 48372 48373 for (; i < l; i += 2) { 48374 p = state[i]; 48375 result.push(p, p in override ? override[p] : state[i + 1]); 48376 } 48377 48378 result.t = state.t; 48379 return result; 48380 }, 48381 _winOffsets = { 48382 left: 0, 48383 top: 0 48384 }, 48385 _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation, clampZeroProp) { 48386 _isFunction(value) && (value = value(self)); 48387 48388 if (_isString(value) && value.substr(0, 3) === "max") { 48389 value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0); 48390 } 48391 48392 var time = containerAnimation ? containerAnimation.time() : 0, 48393 p1, 48394 p2, 48395 element; 48396 containerAnimation && containerAnimation.seek(0); 48397 isNaN(value) || (value = +value); 48398 48399 if (!_isNumber(value)) { 48400 _isFunction(trigger) && (trigger = trigger(self)); 48401 var offsets = (value || "0").split(" "), 48402 bounds, 48403 localOffset, 48404 globalOffset, 48405 display; 48406 element = _getTarget(trigger, self) || _body$1; 48407 bounds = _getBounds(element) || {}; 48408 48409 if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") { 48410 display = element.style.display; 48411 element.style.display = "block"; 48412 bounds = _getBounds(element); 48413 display ? element.style.display = display : element.style.removeProperty("display"); 48414 } 48415 48416 localOffset = _offsetToPx(offsets[0], bounds[direction.d]); 48417 globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize); 48418 value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset; 48419 markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20); 48420 scrollerSize -= scrollerSize - globalOffset; 48421 } else { 48422 containerAnimation && (value = gsap$1.utils.mapRange(containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, 0, scrollerMa
vendor: 4,541 bytes, lines 48422-48578
48422x, value)); 48423 markerScroller && _positionMarker(markerScroller, scrollerSize, direction, true); 48424 } 48425 48426 if (clampZeroProp) { 48427 self[clampZeroProp] = value || -0.001; 48428 value < 0 && (value = 0); 48429 } 48430 48431 if (marker) { 48432 var position = value + scrollerSize, 48433 isStart = marker._isStart; 48434 p1 = "scroll" + direction.d2; 48435 48436 _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body$1[p1], _docEl$1[p1]) : marker.parentNode[p1]) <= position + 1); 48437 48438 if (useFixedPosition) { 48439 scrollerBounds = _getBounds(markerScroller); 48440 useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px); 48441 } 48442 } 48443 48444 if (containerAnimation && element) { 48445 p1 = _getBounds(element); 48446 containerAnimation.seek(scrollerMax); 48447 p2 = _getBounds(element); 48448 containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p]; 48449 value = value / containerAnimation._caScrollDist * scrollerMax; 48450 } 48451 48452 containerAnimation && containerAnimation.seek(time); 48453 return containerAnimation ? value : Math.round(value); 48454 }, 48455 _prefixExp = /(webkit|moz|length|cssText|inset)/i, 48456 _reparent = function _reparent(element, parent, top, left) { 48457 if (element.parentNode !== parent) { 48458 var style = element.style, 48459 p, 48460 cs; 48461 48462 if (parent === _body$1) { 48463 element._stOrig = style.cssText; 48464 cs = _getComputedStyle(element); 48465 48466 for (p in cs) { 48467 if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") { 48468 style[p] = cs[p]; 48469 } 48470 } 48471 48472 style.top = top; 48473 style.left = left; 48474 } else { 48475 style.cssText = element._stOrig; 48476 } 48477 48478 gsap$1.core.getCache(element).uncache = 1; 48479 parent.appendChild(element); 48480 } 48481 }, 48482 _interruptionTracker = function _interruptionTracker(getValueFunc, initialValue, onInterrupt) { 48483 var last1 = initialValue, 48484 last2 = last1; 48485 return function (value) { 48486 var current = Math.round(getValueFunc()); 48487 48488 if (current !== last1 && current !== last2 && Math.abs(current - last1) > 3 && Math.abs(current - last2) > 3) { 48489 value = current; 48490 onInterrupt && onInterrupt(); 48491 } 48492 48493 last2 = last1; 48494 last1 = value; 48495 return value; 48496 }; 48497 }, 48498 _shiftMarker = function _shiftMarker(marker, direction, value) { 48499 var vars = {}; 48500 vars[direction.p] = "+=" + value; 48501 gsap$1.set(marker, vars); 48502 }, 48503 _getTweenCreator = function _getTweenCreator(scroller, direction) { 48504 var getScroll = _getScrollFunc(scroller, direction), 48505 prop = "_scroll" + direction.p2, 48506 getTween = function getTween(scrollTo, vars, initialValue, change1, change2) { 48507 var tween = getTween.tween, 48508 onComplete = vars.onComplete, 48509 modifiers = {}; 48510 initialValue = initialValue || getScroll(); 48511 48512 var checkForInterruption = _interruptionTracker(getScroll, initialValue, function () { 48513 tween.kill(); 48514 getTween.tween = 0; 48515 }); 48516 48517 change2 = change1 && change2 || 0; 48518 change1 = change1 || scrollTo - initialValue; 48519 tween && tween.kill(); 48520 vars[prop] = scrollTo; 48521 vars.inherit = false; 48522 vars.modifiers = modifiers; 48523 48524 modifiers[prop] = function () { 48525 return checkForInterruption(initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio); 48526 }; 48527 48528 vars.onUpdate = function () { 48529 _scrollers.cache++; 48530 getTween.tween && _updateAll(); 48531 }; 48532 48533 vars.onComplete = function () { 48534 getTween.tween = 0; 48535 onComplete && onComplete.call(tween); 48536 }; 48537 48538 tween = getTween.tween = gsap$1.to(scroller, vars); 48539 return tween; 48540 }; 48541 48542 scroller[prop] = getScroll; 48543 48544 getScroll.wheelHandler = function () { 48545 return getTween.tween && getTween.tween.kill() && (getTween.tween = 0); 48546 }; 48547 48548 _addListener$1(scroller, "wheel", getScroll.wheelHandler); 48549 48550 ScrollTrigger$1.isTouch && _addListener$1(scroller, "touchmove", getScroll.wheelHandler); 48551 return getTween; 48552 }; 48553 48554 var ScrollTrigger$1 = function () { 48555 function ScrollTrigger(vars, animation) { 48556 _coreInitted$1 || ScrollTrigger.register(gsap$1) || console.warn("Please gsap.registerPlugin(ScrollTrigger)"); 48557 48558 _context$1(this); 48559 48560 this.init(vars, animation); 48561 } 48562 48563 var _proto = ScrollTrigger.prototype; 48564 48565 _proto.init = function init(vars, animation) { 48566 this.progress = this.start = 0; 48567 this.vars && this.kill(true, true); 48568 48569 if (!_enabled) { 48570 this.update = this.refresh = this.kill = _passThrough; 48571 return; 48572 } 48573 48574 vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? { 48575 trigger: vars 48576 } : vars, _defaults); 48577 48578 var _vars = vars,
vendor: 4,184 bytes, lines 48579-48719
48579 onUpdate = _vars.onUpdate, 48580 toggleClass = _vars.toggleClass, 48581 id = _vars.id, 48582 onToggle = _vars.onToggle, 48583 onRefresh = _vars.onRefresh, 48584 scrub = _vars.scrub, 48585 trigger = _vars.trigger, 48586 pin = _vars.pin, 48587 pinSpacing = _vars.pinSpacing, 48588 invalidateOnRefresh = _vars.invalidateOnRefresh, 48589 anticipatePin = _vars.anticipatePin, 48590 onScrubComplete = _vars.onScrubComplete, 48591 onSnapComplete = _vars.onSnapComplete, 48592 once = _vars.once, 48593 snap = _vars.snap, 48594 pinReparent = _vars.pinReparent, 48595 pinSpacer = _vars.pinSpacer, 48596 containerAnimation = _vars.containerAnimation, 48597 fastScrollEnd = _vars.fastScrollEnd, 48598 preventOverlaps = _vars.preventOverlaps, 48599 direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical, 48600 isToggle = !scrub && scrub !== 0, 48601 scroller = _getTarget(vars.scroller || _win$1), 48602 scrollerCache = gsap$1.core.getCache(scroller), 48603 isViewport = _isViewport$1(scroller), 48604 useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed", 48605 callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack], 48606 toggleActions = isToggle && vars.toggleActions.split(" "), 48607 markers = "markers" in vars ? vars.markers : _defaults.markers, 48608 borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0, 48609 self = this, 48610 onRefreshInit = vars.onRefreshInit && function () { 48611 return vars.onRefreshInit(self); 48612 }, 48613 getScrollerSize = _getSizeFunc(scroller, isViewport, direction), 48614 getScrollerOffsets = _getOffsetsFunc(scroller, isViewport), 48615 lastSnap = 0, 48616 lastRefresh = 0, 48617 prevProgress = 0, 48618 scrollFunc = _getScrollFunc(scroller, direction), 48619 tweenTo, 48620 pinCache, 48621 snapFunc, 48622 scroll1, 48623 scroll2, 48624 start, 48625 end, 48626 markerStart, 48627 markerEnd, 48628 markerStartTrigger, 48629 markerEndTrigger, 48630 markerVars, 48631 executingOnRefresh, 48632 change, 48633 pinOriginalState, 48634 pinActiveState, 48635 pinState, 48636 spacer, 48637 offset, 48638 pinGetter, 48639 pinSetter, 48640 pinStart, 48641 pinChange, 48642 spacingStart, 48643 spacerState, 48644 markerStartSetter, 48645 pinMoves, 48646 markerEndSetter, 48647 cs, 48648 snap1, 48649 snap2, 48650 scrubTween, 48651 scrubSmooth, 48652 snapDurClamp, 48653 snapDelayedCall, 48654 prevScroll, 48655 prevAnimProgress, 48656 caMarkerSetter, 48657 customRevertReturn; 48658 48659 self._startClamp = self._endClamp = false; 48660 self._dir = direction; 48661 anticipatePin *= 45; 48662 self.scroller = scroller; 48663 self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc; 48664 scroll1 = scrollFunc(); 48665 self.vars = vars; 48666 animation = animation || vars.animation; 48667 48668 if ("refreshPriority" in vars) { 48669 _sort = 1; 48670 vars.refreshPriority === -9999 && (_primary = self); 48671 } 48672 48673 scrollerCache.tweenScroll = scrollerCache.tweenScroll || { 48674 top: _getTweenCreator(scroller, _vertical), 48675 left: _getTweenCreator(scroller, _horizontal) 48676 }; 48677 self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p]; 48678 48679 self.scrubDuration = function (value) { 48680 scrubSmooth = _isNumber(value) && value; 48681 48682 if (!scrubSmooth) { 48683 scrubTween && scrubTween.progress(1).kill(); 48684 scrubTween = 0; 48685 } else { 48686 scrubTween ? scrubTween.duration(value) : scrubTween = gsap$1.to(animation, { 48687 ease: "expo", 48688 totalProgress: "+=0", 48689 inherit: false, 48690 duration: scrubSmooth, 48691 paused: true, 48692 onComplete: function onComplete() { 48693 return onScrubComplete && onScrubComplete(self); 48694 } 48695 }); 48696 } 48697 }; 48698 48699 if (animation) { 48700 animation.vars.lazy = false; 48701 animation._initted && !self.isReverted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.duration() && animation.render(0, true, true); 48702 self.animation = animation.pause(); 48703 animation.scrollTrigger = self; 48704 self.scrubDuration(scrub); 48705 snap1 = 0; 48706 id || (id = animation.vars.id); 48707 } 48708 48709 if (snap) { 48710 if (!_isObject(snap) || snap.push) { 48711 snap = { 48712 snapTo: snap 48713 }; 48714 } 48715 48716 "scrollBehavior" in _body$1.style && gsap$1.set(isViewport ? [_body$1, _docEl$1] : scroller, { 48717 scrollBehavior: "auto" 48718 }); 48719
vendor: 4,259 bytes, lines 48720-48815
48720 _scrollers.forEach(function (o) { 48721 return _isFunction(o) && o.target === (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller) && (o.smooth = false); 48722 }); 48723 48724 snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) { 48725 return _snapDirectional(snap.snapTo)(value, _getTime$1() - lastRefresh < 500 ? 0 : st.direction); 48726 } : gsap$1.utils.snap(snap.snapTo); 48727 snapDurClamp = snap.duration || { 48728 min: 0.1, 48729 max: 2 48730 }; 48731 snapDurClamp = _isObject(snapDurClamp) ? _clamp$1(snapDurClamp.min, snapDurClamp.max) : _clamp$1(snapDurClamp, snapDurClamp); 48732 snapDelayedCall = gsap$1.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () { 48733 var scroll = scrollFunc(), 48734 refreshedRecently = _getTime$1() - lastRefresh < 500, 48735 tween = tweenTo.tween; 48736 48737 if ((refreshedRecently || Math.abs(self.getVelocity()) < 10) && !tween && !_pointerIsDown && lastSnap !== scroll) { 48738 var progress = (scroll - start) / change, 48739 totalProgress = animation && !isToggle ? animation.totalProgress() : progress, 48740 velocity = refreshedRecently ? 0 : (totalProgress - snap2) / (_getTime$1() - _time2) * 1000 || 0, 48741 change1 = gsap$1.utils.clamp(-progress, 1 - progress, _abs(velocity / 2) * velocity / 0.185), 48742 naturalEnd = progress + (snap.inertia === false ? 0 : change1), 48743 endValue, 48744 endScroll, 48745 _snap = snap, 48746 onStart = _snap.onStart, 48747 _onInterrupt = _snap.onInterrupt, 48748 _onComplete = _snap.onComplete; 48749 endValue = snapFunc(naturalEnd, self); 48750 _isNumber(endValue) || (endValue = naturalEnd); 48751 endScroll = Math.round(start + endValue * change); 48752 48753 if (scroll <= end && scroll >= start && endScroll !== scroll) { 48754 if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) { 48755 return; 48756 } 48757 48758 if (snap.inertia === false) { 48759 change1 = endValue - progress; 48760 } 48761 48762 tweenTo(endScroll, { 48763 duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)), 48764 ease: snap.ease || "power3", 48765 data: _abs(endScroll - scroll), 48766 onInterrupt: function onInterrupt() { 48767 return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self); 48768 }, 48769 onComplete: function onComplete() { 48770 self.update(); 48771 lastSnap = scrollFunc(); 48772 48773 if (animation) { 48774 scrubTween ? scrubTween.resetTo("totalProgress", endValue, animation._tTime / animation._tDur) : animation.progress(endValue); 48775 } 48776 48777 snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress; 48778 onSnapComplete && onSnapComplete(self); 48779 _onComplete && _onComplete(self); 48780 } 48781 }, scroll, change1 * change, endScroll - scroll - change1 * change); 48782 onStart && onStart(self, tweenTo.tween); 48783 } 48784 } else if (self.isActive && lastSnap !== scroll) { 48785 snapDelayedCall.restart(true); 48786 } 48787 }).pause(); 48788 } 48789 48790 id && (_ids[id] = self); 48791 trigger = self.trigger = _getTarget(trigger || pin !== true && pin); 48792 customRevertReturn = trigger && trigger._gsap && trigger._gsap.stRevert; 48793 customRevertReturn && (customRevertReturn = customRevertReturn(self)); 48794 pin = pin === true ? trigger : _getTarget(pin); 48795 _isString(toggleClass) && (toggleClass = { 48796 targets: trigger, 48797 className: toggleClass 48798 }); 48799 48800 if (pin) { 48801 pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && pin.parentNode && pin.parentNode.style && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding); 48802 self.pin = pin; 48803 pinCache = gsap$1.core.getCache(pin); 48804 48805 if (!pinCache.spacer) { 48806 if (pinSpacer) { 48807 pinSpacer = _getTarget(pinSpacer); 48808 pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement); 48809 pinCache.spacerIsNative = !!pinSpacer; 48810 pinSpacer && (pinCache.spacerState = _getState(pinSpacer)); 48811 } 48812 48813 pinCache.spacer = spacer = pinSpacer || _doc$1.createElement("div"); 48814 spacer.classList.add("pin-spacer"); 48815 id && spacer.classList.add("pin-spacer-" + id);
vendor: 4,987 bytes, lines 48816-48970
48816 pinCache.pinState = pinOriginalState = _getState(pin); 48817 } else { 48818 pinOriginalState = pinCache.pinState; 48819 } 48820 48821 vars.force3D !== false && gsap$1.set(pin, { 48822 force3D: true 48823 }); 48824 self.spacer = spacer = pinCache.spacer; 48825 cs = _getComputedStyle(pin); 48826 spacingStart = cs[pinSpacing + direction.os2]; 48827 pinGetter = gsap$1.getProperty(pin); 48828 pinSetter = gsap$1.quickSetter(pin, direction.a, _px); 48829 48830 _swapPinIn(pin, spacer, cs); 48831 48832 pinState = _getState(pin); 48833 } 48834 48835 if (markers) { 48836 markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults; 48837 markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0); 48838 markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger); 48839 offset = markerStartTrigger["offset" + direction.op.d2]; 48840 48841 var content = _getTarget(_getProxyProp(scroller, "content") || scroller); 48842 48843 markerStart = this.markerStart = _createMarker("start", id, content, direction, markerVars, offset, 0, containerAnimation); 48844 markerEnd = this.markerEnd = _createMarker("end", id, content, direction, markerVars, offset, 0, containerAnimation); 48845 containerAnimation && (caMarkerSetter = gsap$1.quickSetter([markerStart, markerEnd], direction.a, _px)); 48846 48847 if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) { 48848 _makePositionable(isViewport ? _body$1 : scroller); 48849 48850 gsap$1.set([markerStartTrigger, markerEndTrigger], { 48851 force3D: true 48852 }); 48853 markerStartSetter = gsap$1.quickSetter(markerStartTrigger, direction.a, _px); 48854 markerEndSetter = gsap$1.quickSetter(markerEndTrigger, direction.a, _px); 48855 } 48856 } 48857 48858 if (containerAnimation) { 48859 var oldOnUpdate = containerAnimation.vars.onUpdate, 48860 oldParams = containerAnimation.vars.onUpdateParams; 48861 containerAnimation.eventCallback("onUpdate", function () { 48862 self.update(0, 0, 1); 48863 oldOnUpdate && oldOnUpdate.apply(containerAnimation, oldParams || []); 48864 }); 48865 } 48866 48867 self.previous = function () { 48868 return _triggers[_triggers.indexOf(self) - 1]; 48869 }; 48870 48871 self.next = function () { 48872 return _triggers[_triggers.indexOf(self) + 1]; 48873 }; 48874 48875 self.revert = function (revert, temp) { 48876 if (!temp) { 48877 return self.kill(true); 48878 } 48879 48880 var r = revert !== false || !self.enabled, 48881 prevRefreshing = _refreshing; 48882 48883 if (r !== self.isReverted) { 48884 if (r) { 48885 prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0); 48886 prevProgress = self.progress; 48887 prevAnimProgress = animation && animation.progress(); 48888 } 48889 48890 markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) { 48891 return m.style.display = r ? "none" : "block"; 48892 }); 48893 48894 if (r) { 48895 _refreshing = self; 48896 self.update(r); 48897 } 48898 48899 if (pin && (!pinReparent || !self.isActive)) { 48900 if (r) { 48901 _swapPinOut(pin, spacer, pinOriginalState); 48902 } else { 48903 _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState); 48904 } 48905 } 48906 48907 r || self.update(r); 48908 _refreshing = prevRefreshing; 48909 self.isReverted = r; 48910 } 48911 }; 48912 48913 self.refresh = function (soft, force, position, pinOffset) { 48914 if ((_refreshing || !self.enabled) && !force) { 48915 return; 48916 } 48917 48918 if (pin && soft && _lastScrollTime) { 48919 _addListener$1(ScrollTrigger, "scrollEnd", _softRefresh); 48920 48921 return; 48922 } 48923 48924 !_refreshingAll && onRefreshInit && onRefreshInit(self); 48925 _refreshing = self; 48926 48927 if (tweenTo.tween && !position) { 48928 tweenTo.tween.kill(); 48929 tweenTo.tween = 0; 48930 } 48931 48932 scrubTween && scrubTween.pause(); 48933 invalidateOnRefresh && animation && animation.revert({ 48934 kill: false 48935 }).invalidate(); 48936 self.isReverted || self.revert(true, true); 48937 self._subPinOffset = false; 48938 48939 var size = getScrollerSize(), 48940 scrollerBounds = getScrollerOffsets(), 48941 max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction), 48942 isFirstRefresh = change <= 0.01, 48943 offset = 0, 48944 otherPinOffset = pinOffset || 0, 48945 parsedEnd = _isObject(position) ? position.end : vars.end, 48946 parsedEndTrigger = vars.endTrigger || trigger, 48947 parsedStart = _isObject(position) ? position.start : vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"), 48948 pinnedContainer = self.pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer, self), 48949 triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0, 48950 i = triggerIndex, 48951 cs, 48952 bounds, 48953 scroll, 48954 isVertical, 48955 override, 48956 curTrigger, 48957 curPin, 48958 oppositeScroll, 48959 initted, 48960 revertedPins, 48961 forcedOverflow, 48962 markerStartOffset, 48963 markerEndOffset; 48964 48965 if (markers && _isObject(position)) { 48966 markerStartOffset = gsap$1.getProperty(markerStartTrigger, direction.p); 48967 markerEndOffset = gsap$1.getProperty(markerEndTrigger, direction.p); 48968 } 48969 48970 while (i--) {
vendor: 4,360 bytes, lines 48971-49082
48971 curTrigger = _triggers[i]; 48972 curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = self); 48973 curPin = curTrigger.pin; 48974 48975 if (curPin && (curPin === trigger || curPin === pin || curPin === pinnedContainer) && !curTrigger.isReverted) { 48976 revertedPins || (revertedPins = []); 48977 revertedPins.unshift(curTrigger); 48978 curTrigger.revert(true, true); 48979 } 48980 48981 if (curTrigger !== _triggers[i]) { 48982 triggerIndex--; 48983 i--; 48984 } 48985 } 48986 48987 _isFunction(parsedStart) && (parsedStart = parsedStart(self)); 48988 parsedStart = _parseClamp(parsedStart, "start", self); 48989 start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._startClamp && "_startClamp") || (pin ? -0.001 : 0); 48990 _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self)); 48991 48992 if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) { 48993 if (~parsedEnd.indexOf(" ")) { 48994 parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd; 48995 } else { 48996 offset = _offsetToPx(parsedEnd.substr(2), size); 48997 parsedEnd = _isString(parsedStart) ? parsedStart : (containerAnimation ? gsap$1.utils.mapRange(0, containerAnimation.duration(), containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, start) : start) + offset; 48998 parsedEndTrigger = trigger; 48999 } 49000 } 49001 49002 parsedEnd = _parseClamp(parsedEnd, "end", self); 49003 end = Math.max(start, _parsePosition(parsedEnd || (parsedEndTrigger ? "100% 0" : max), parsedEndTrigger, size, direction, scrollFunc() + offset, markerEnd, markerEndTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._endClamp && "_endClamp")) || -0.001; 49004 offset = 0; 49005 i = triggerIndex; 49006 49007 while (i--) { 49008 curTrigger = _triggers[i]; 49009 curPin = curTrigger.pin; 49010 49011 if (curPin && curTrigger.start - curTrigger._pinPush <= start && !containerAnimation && curTrigger.end > 0) { 49012 cs = curTrigger.end - (self._startClamp ? Math.max(0, curTrigger.start) : curTrigger.start); 49013 49014 if ((curPin === trigger && curTrigger.start - curTrigger._pinPush < start || curPin === pinnedContainer) && isNaN(parsedStart)) { 49015 offset += cs * (1 - curTrigger.progress); 49016 } 49017 49018 curPin === pin && (otherPinOffset += cs); 49019 } 49020 } 49021 49022 start += offset; 49023 end += offset; 49024 self._startClamp && (self._startClamp += offset); 49025 49026 if (self._endClamp && !_refreshingAll) { 49027 self._endClamp = end || -0.001; 49028 end = Math.min(end, _maxScroll(scroller, direction)); 49029 } 49030 49031 change = end - start || (start -= 0.01) && 0.001; 49032 49033 if (isFirstRefresh) { 49034 prevProgress = gsap$1.utils.clamp(0, 1, gsap$1.utils.normalize(start, end, prevScroll)); 49035 } 49036 49037 self._pinPush = otherPinOffset; 49038 49039 if (markerStart && offset) { 49040 cs = {}; 49041 cs[direction.a] = "+=" + offset; 49042 pinnedContainer && (cs[direction.p] = "-=" + scrollFunc()); 49043 gsap$1.set([markerStart, markerEnd], cs); 49044 } 49045 49046 if (pin && !(_clampingMax && self.end >= _maxScroll(scroller, direction))) { 49047 cs = _getComputedStyle(pin); 49048 isVertical = direction === _vertical; 49049 scroll = scrollFunc(); 49050 pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset; 49051 49052 if (!max && end > 1) { 49053 forcedOverflow = (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller).style; 49054 forcedOverflow = { 49055 style: forcedOverflow, 49056 value: forcedOverflow["overflow" + direction.a.toUpperCase()] 49057 }; 49058 49059 if (isViewport && _getComputedStyle(_body$1)["overflow" + direction.a.toUpperCase()] !== "scroll") { 49060 forcedOverflow.style["overflow" + direction.a.toUpperCase()] = "scroll"; 49061 } 49062 } 49063 49064 _swapPinIn(pin, spacer, cs); 49065 49066 pinState = _getState(pin); 49067 bounds = _getBounds(pin, true); 49068 oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)(); 49069 49070 if (pinSpacing) { 49071 spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px]; 49072 spacerState.t = spacer; 49073 i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0; 49074 49075 if (i) { 49076 spacerState.push(direction.d, i + _px); 49077 spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px); 49078 } 49079 49080 _setState(spacerState); 49081 49082 if (pinnedContainer) {
vendor: 9,034 bytes, lines 49083-49325
49083 _triggers.forEach(function (t) { 49084 if (t.pin === pinnedContainer && t.vars.pinSpacing !== false) { 49085 t._subPinOffset = true; 49086 } 49087 }); 49088 } 49089 49090 useFixedPosition && scrollFunc(prevScroll); 49091 } else { 49092 i = _getSize(pin, direction); 49093 i && spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px); 49094 } 49095 49096 if (useFixedPosition) { 49097 override = { 49098 top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px, 49099 left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px, 49100 boxSizing: "border-box", 49101 position: "fixed" 49102 }; 49103 override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px; 49104 override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px; 49105 override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0"; 49106 override[_padding] = cs[_padding]; 49107 override[_padding + _Top] = cs[_padding + _Top]; 49108 override[_padding + _Right] = cs[_padding + _Right]; 49109 override[_padding + _Bottom] = cs[_padding + _Bottom]; 49110 override[_padding + _Left] = cs[_padding + _Left]; 49111 pinActiveState = _copyState(pinOriginalState, override, pinReparent); 49112 _refreshingAll && scrollFunc(0); 49113 } 49114 49115 if (animation) { 49116 initted = animation._initted; 49117 49118 _suppressOverwrites(1); 49119 49120 animation.render(animation.duration(), true, true); 49121 pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset; 49122 pinMoves = Math.abs(change - pinChange) > 1; 49123 useFixedPosition && pinMoves && pinActiveState.splice(pinActiveState.length - 2, 2); 49124 animation.render(0, true, true); 49125 initted || animation.invalidate(true); 49126 animation.parent || animation.totalTime(animation.totalTime()); 49127 49128 _suppressOverwrites(0); 49129 } else { 49130 pinChange = change; 49131 } 49132 49133 forcedOverflow && (forcedOverflow.value ? forcedOverflow.style["overflow" + direction.a.toUpperCase()] = forcedOverflow.value : forcedOverflow.style.removeProperty("overflow-" + direction.a)); 49134 } else if (trigger && scrollFunc() && !containerAnimation) { 49135 bounds = trigger.parentNode; 49136 49137 while (bounds && bounds !== _body$1) { 49138 if (bounds._pinOffset) { 49139 start -= bounds._pinOffset; 49140 end -= bounds._pinOffset; 49141 } 49142 49143 bounds = bounds.parentNode; 49144 } 49145 } 49146 49147 revertedPins && revertedPins.forEach(function (t) { 49148 return t.revert(false, true); 49149 }); 49150 self.start = start; 49151 self.end = end; 49152 scroll1 = scroll2 = _refreshingAll ? prevScroll : scrollFunc(); 49153 49154 if (!containerAnimation && !_refreshingAll) { 49155 scroll1 < prevScroll && scrollFunc(prevScroll); 49156 self.scroll.rec = 0; 49157 } 49158 49159 self.revert(false, true); 49160 lastRefresh = _getTime$1(); 49161 49162 if (snapDelayedCall) { 49163 lastSnap = -1; 49164 snapDelayedCall.restart(true); 49165 } 49166 49167 _refreshing = 0; 49168 animation && isToggle && (animation._initted || prevAnimProgress) && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress || 0, true).render(animation.time(), true, true); 49169 49170 if (isFirstRefresh || prevProgress !== self.progress || containerAnimation || invalidateOnRefresh) { 49171 animation && !isToggle && animation.totalProgress(containerAnimation && start < -0.001 && !prevProgress ? gsap$1.utils.normalize(start, end, 0) : prevProgress, true); 49172 self.progress = isFirstRefresh || (scroll1 - start) / change === prevProgress ? 0 : prevProgress; 49173 } 49174 49175 pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange)); 49176 scrubTween && scrubTween.invalidate(); 49177 49178 if (!isNaN(markerStartOffset)) { 49179 markerStartOffset -= gsap$1.getProperty(markerStartTrigger, direction.p); 49180 markerEndOffset -= gsap$1.getProperty(markerEndTrigger, direction.p); 49181 49182 _shiftMarker(markerStartTrigger, direction, markerStartOffset); 49183 49184 _shiftMarker(markerStart, direction, markerStartOffset - (pinOffset || 0)); 49185 49186 _shiftMarker(markerEndTrigger, direction, markerEndOffset); 49187 49188 _shiftMarker(markerEnd, direction, markerEndOffset - (pinOffset || 0)); 49189 } 49190 49191 isFirstRefresh && !_refreshingAll && self.update(); 49192 49193 if (onRefresh && !_refreshingAll && !executingOnRefresh) { 49194 executingOnRefresh = true; 49195 onRefresh(self); 49196 executingOnRefresh = false; 49197 } 49198 }; 49199 49200 self.getVelocity = function () { 49201 return (scrollFunc() - scroll2) / (_getTime$1() - _time2) * 1000 || 0; 49202 }; 49203 49204 self.endAnimation = function () { 49205 _endAnimation(self.callbackAnimation); 49206 49207 if (animation) { 49208 scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1); 49209 } 49210 }; 49211 49212 self.labelToScroll = function (label) { 49213 return animation && animation.labels && (start || self.refresh() || start) + animation.labels[label] / animation.duration() * change || 0; 49214 }; 49215 49216 self.getTrailing = function (name) { 49217 var i = _triggers.indexOf(self), 49218 a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1); 49219 49220 return (_isString(name) ? a.filter(function (t) { 49221 return t.vars.preventOverlaps === name; 49222 }) : a).filter(function (t) { 49223 return self.direction > 0 ? t.end <= start : t.start >= end; 49224 }); 49225 }; 49226 49227 self.update = function (reset, recordVelocity, forceFake) { 49228 if (containerAnimation && !forceFake && !reset) { 49229 return; 49230 } 49231 49232 var scroll = _refreshingAll === true ? prevScroll : self.scroll(), 49233 p = reset ? 0 : (scroll - start) / change, 49234 clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0, 49235 prevProgress = self.progress, 49236 isActive, 49237 wasActive, 49238 toggleState, 49239 action, 49240 stateChanged, 49241 toggled, 49242 isAtMax, 49243 isTakingAction; 49244 49245 if (recordVelocity) { 49246 scroll2 = scroll1; 49247 scroll1 = containerAnimation ? scrollFunc() : scroll; 49248 49249 if (snap) { 49250 snap2 = snap1; 49251 snap1 = animation && !isToggle ? animation.totalProgress() : clipped; 49252 } 49253 } 49254 49255 if (anticipatePin && pin && !_refreshing && !_startup$1 && _lastScrollTime) { 49256 if (!clipped && start < scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) { 49257 clipped = 0.0001; 49258 } else if (clipped === 1 && end > scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) { 49259 clipped = 0.9999; 49260 } 49261 } 49262 49263 if (clipped !== prevProgress && self.enabled) { 49264 isActive = self.isActive = !!clipped && clipped < 1; 49265 wasActive = !!prevProgress && prevProgress < 1; 49266 toggled = isActive !== wasActive; 49267 stateChanged = toggled || !!clipped !== !!prevProgress; 49268 self.direction = clipped > prevProgress ? 1 : -1; 49269 self.progress = clipped; 49270 49271 if (stateChanged && !_refreshing) { 49272 toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3; 49273 49274 if (isToggle) { 49275 action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState]; 49276 isTakingAction = animation && (action === "complete" || action === "reset" || action in animation); 49277 } 49278 } 49279 49280 preventOverlaps && (toggled || isTakingAction) && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) { 49281 return t.endAnimation(); 49282 })); 49283 49284 if (!isToggle) { 49285 if (scrubTween && !_refreshing && !_startup$1) { 49286 scrubTween._dp._time - scrubTween._start !== scrubTween._time && scrubTween.render(scrubTween._dp._time - scrubTween._start); 49287 49288 if (scrubTween.resetTo) { 49289 scrubTween.resetTo("totalProgress", clipped, animation._tTime / animation._tDur); 49290 } else { 49291 scrubTween.vars.totalProgress = clipped; 49292 scrubTween.invalidate().restart(); 49293 } 49294 } else if (animation) { 49295 animation.totalProgress(clipped, !!(_refreshing && (lastRefresh || reset))); 49296 } 49297 } 49298 49299 if (pin) { 49300 reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart); 49301 49302 if (!useFixedPosition) { 49303 pinSetter(_round(pinStart + pinChange * clipped)); 49304 } else if (stateChanged) { 49305 isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction); 49306 49307 if (pinReparent) { 49308 if (!reset && (isActive || isAtMax)) { 49309 var bounds = _getBounds(pin, true), 49310 _offset = scroll - start; 49311 49312 _reparent(pin, _body$1, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px); 49313 } else { 49314 _reparent(pin, spacer); 49315 } 49316 } 49317 49318 _setState(isActive || isAtMax ? pinActiveState : pinState); 49319 49320 pinMoves && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0)); 49321 } 49322 } 49323 49324 snap && !tweenTo.tween && !_refreshing && !_startup$1 && snapDelayedCall.restart(true); 49325 toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEac
vendor: 4,284 bytes, lines 49325-49466
49325h(function (el) { 49326 return el.classList[isActive || once ? "add" : "remove"](toggleClass.className); 49327 }); 49328 onUpdate && !isToggle && !reset && onUpdate(self); 49329 49330 if (stateChanged && !_refreshing) { 49331 if (isToggle) { 49332 if (isTakingAction) { 49333 if (action === "complete") { 49334 animation.pause().totalProgress(1); 49335 } else if (action === "reset") { 49336 animation.restart(true).pause(); 49337 } else if (action === "restart") { 49338 animation.restart(true); 49339 } else { 49340 animation[action](); 49341 } 49342 } 49343 49344 onUpdate && onUpdate(self); 49345 } 49346 49347 if (toggled || !_limitCallbacks) { 49348 onToggle && toggled && _callback(self, onToggle); 49349 callbacks[toggleState] && _callback(self, callbacks[toggleState]); 49350 once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0); 49351 49352 if (!toggled) { 49353 toggleState = clipped === 1 ? 1 : 3; 49354 callbacks[toggleState] && _callback(self, callbacks[toggleState]); 49355 } 49356 } 49357 49358 if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) { 49359 _endAnimation(self.callbackAnimation); 49360 49361 scrubTween ? scrubTween.progress(1) : _endAnimation(animation, action === "reverse" ? 1 : !clipped, 1); 49362 } 49363 } else if (isToggle && onUpdate && !_refreshing) { 49364 onUpdate(self); 49365 } 49366 } 49367 49368 if (markerEndSetter) { 49369 var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll; 49370 markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0)); 49371 markerEndSetter(n); 49372 } 49373 49374 caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0)); 49375 }; 49376 49377 self.enable = function (reset, refresh) { 49378 if (!self.enabled) { 49379 self.enabled = true; 49380 49381 _addListener$1(scroller, "resize", _onResize); 49382 49383 isViewport || _addListener$1(scroller, "scroll", _onScroll$1); 49384 onRefreshInit && _addListener$1(ScrollTrigger, "refreshInit", onRefreshInit); 49385 49386 if (reset !== false) { 49387 self.progress = prevProgress = 0; 49388 scroll1 = scroll2 = lastSnap = scrollFunc(); 49389 } 49390 49391 refresh !== false && self.refresh(); 49392 } 49393 }; 49394 49395 self.getTween = function (snap) { 49396 return snap && tweenTo ? tweenTo.tween : scrubTween; 49397 }; 49398 49399 self.setPositions = function (newStart, newEnd, keepClamp, pinOffset) { 49400 if (containerAnimation) { 49401 var st = containerAnimation.scrollTrigger, 49402 duration = containerAnimation.duration(), 49403 _change = st.end - st.start; 49404 49405 newStart = st.start + _change * newStart / duration; 49406 newEnd = st.start + _change * newEnd / duration; 49407 } 49408 49409 self.refresh(false, false, { 49410 start: _keepClamp(newStart, keepClamp && !!self._startClamp), 49411 end: _keepClamp(newEnd, keepClamp && !!self._endClamp) 49412 }, pinOffset); 49413 self.update(); 49414 }; 49415 49416 self.adjustPinSpacing = function (amount) { 49417 if (spacerState && amount) { 49418 var i = spacerState.indexOf(direction.d) + 1; 49419 spacerState[i] = parseFloat(spacerState[i]) + amount + _px; 49420 spacerState[1] = parseFloat(spacerState[1]) + amount + _px; 49421 49422 _setState(spacerState); 49423 } 49424 }; 49425 49426 self.disable = function (reset, allowAnimation) { 49427 if (self.enabled) { 49428 reset !== false && self.revert(true, true); 49429 self.enabled = self.isActive = false; 49430 allowAnimation || scrubTween && scrubTween.pause(); 49431 prevScroll = 0; 49432 pinCache && (pinCache.uncache = 1); 49433 onRefreshInit && _removeListener$1(ScrollTrigger, "refreshInit", onRefreshInit); 49434 49435 if (snapDelayedCall) { 49436 snapDelayedCall.pause(); 49437 tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0); 49438 } 49439 49440 if (!isViewport) { 49441 var i = _triggers.length; 49442 49443 while (i--) { 49444 if (_triggers[i].scroller === scroller && _triggers[i] !== self) { 49445 return; 49446 } 49447 } 49448 49449 _removeListener$1(scroller, "resize", _onResize); 49450 49451 isViewport || _removeListener$1(scroller, "scroll", _onScroll$1); 49452 } 49453 } 49454 }; 49455 49456 self.kill = function (revert, allowAnimation) { 49457 self.disable(revert, allowAnimation); 49458 scrubTween && !allowAnimation && scrubTween.kill(); 49459 id && delete _ids[id]; 49460 49461 var i = _triggers.indexOf(self); 49462 49463 i >= 0 && _triggers.splice(i, 1); 49464 i === _i && _direction > 0 && _i--; 49465 i = 0; 49466
vendor: 15,520 bytes, lines 49467-49973
49467 _triggers.forEach(function (t) { 49468 return t.scroller === self.scroller && (i = 1); 49469 }); 49470 49471 i || _refreshingAll || (self.scroll.rec = 0); 49472 49473 if (animation) { 49474 animation.scrollTrigger = null; 49475 revert && animation.revert({ 49476 kill: false 49477 }); 49478 allowAnimation || animation.kill(); 49479 } 49480 49481 markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) { 49482 return m.parentNode && m.parentNode.removeChild(m); 49483 }); 49484 _primary === self && (_primary = 0); 49485 49486 if (pin) { 49487 pinCache && (pinCache.uncache = 1); 49488 i = 0; 49489 49490 _triggers.forEach(function (t) { 49491 return t.pin === pin && i++; 49492 }); 49493 49494 i || (pinCache.spacer = 0); 49495 } 49496 49497 vars.onKill && vars.onKill(self); 49498 }; 49499 49500 _triggers.push(self); 49501 49502 self.enable(false, false); 49503 customRevertReturn && customRevertReturn(self); 49504 49505 if (animation && animation.add && !change) { 49506 var updateFunc = self.update; 49507 49508 self.update = function () { 49509 self.update = updateFunc; 49510 start || end || self.refresh(); 49511 }; 49512 49513 gsap$1.delayedCall(0.01, self.update); 49514 change = 0.01; 49515 start = end = 0; 49516 } else { 49517 self.refresh(); 49518 } 49519 49520 pin && _queueRefreshAll(); 49521 }; 49522 49523 ScrollTrigger.register = function register(core) { 49524 if (!_coreInitted$1) { 49525 gsap$1 = core || _getGSAP$1(); 49526 _windowExists() && window.document && ScrollTrigger.enable(); 49527 _coreInitted$1 = _enabled; 49528 } 49529 49530 return _coreInitted$1; 49531 }; 49532 49533 ScrollTrigger.defaults = function defaults(config) { 49534 if (config) { 49535 for (var p in config) { 49536 _defaults[p] = config[p]; 49537 } 49538 } 49539 49540 return _defaults; 49541 }; 49542 49543 ScrollTrigger.disable = function disable(reset, kill) { 49544 _enabled = 0; 49545 49546 _triggers.forEach(function (trigger) { 49547 return trigger[kill ? "kill" : "disable"](reset); 49548 }); 49549 49550 _removeListener$1(_win$1, "wheel", _onScroll$1); 49551 49552 _removeListener$1(_doc$1, "scroll", _onScroll$1); 49553 49554 clearInterval(_syncInterval); 49555 49556 _removeListener$1(_doc$1, "touchcancel", _passThrough); 49557 49558 _removeListener$1(_body$1, "touchstart", _passThrough); 49559 49560 _multiListener(_removeListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler); 49561 49562 _multiListener(_removeListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler); 49563 49564 _resizeDelay.kill(); 49565 49566 _iterateAutoRefresh(_removeListener$1); 49567 49568 for (var i = 0; i < _scrollers.length; i += 3) { 49569 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]); 49570 49571 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]); 49572 } 49573 }; 49574 49575 ScrollTrigger.enable = function enable() { 49576 _win$1 = window; 49577 _doc$1 = document; 49578 _docEl$1 = _doc$1.documentElement; 49579 _body$1 = _doc$1.body; 49580 49581 if (gsap$1) { 49582 _toArray = gsap$1.utils.toArray; 49583 _clamp$1 = gsap$1.utils.clamp; 49584 _context$1 = gsap$1.core.context || _passThrough; 49585 _suppressOverwrites = gsap$1.core.suppressOverwrites || _passThrough; 49586 _scrollRestoration = _win$1.history.scrollRestoration || "auto"; 49587 _lastScroll = _win$1.pageYOffset; 49588 gsap$1.core.globals("ScrollTrigger", ScrollTrigger); 49589 49590 if (_body$1) { 49591 _enabled = 1; 49592 _div100vh = document.createElement("div"); 49593 _div100vh.style.height = "100vh"; 49594 _div100vh.style.position = "absolute"; 49595 49596 _refresh100vh(); 49597 49598 _rafBugFix(); 49599 49600 Observer.register(gsap$1); 49601 ScrollTrigger.isTouch = Observer.isTouch; 49602 _fixIOSBug = Observer.isTouch && /(iPad|iPhone|iPod|Mac)/g.test(navigator.userAgent); 49603 _ignoreMobileResize = Observer.isTouch === 1; 49604 49605 _addListener$1(_win$1, "wheel", _onScroll$1); 49606 49607 _root$1 = [_win$1, _doc$1, _docEl$1, _body$1]; 49608 49609 if (gsap$1.matchMedia) { 49610 ScrollTrigger.matchMedia = function (vars) { 49611 var mm = gsap$1.matchMedia(), 49612 p; 49613 49614 for (p in vars) { 49615 mm.add(p, vars[p]); 49616 } 49617 49618 return mm; 49619 }; 49620 49621 gsap$1.addEventListener("matchMediaInit", function () { 49622 return _revertAll(); 49623 }); 49624 gsap$1.addEventListener("matchMediaRevert", function () { 49625 return _revertRecorded(); 49626 }); 49627 gsap$1.addEventListener("matchMedia", function () { 49628 _refreshAll(0, 1); 49629 49630 _dispatch("matchMedia"); 49631 }); 49632 gsap$1.matchMedia("(orientation: portrait)", function () { 49633 _setBaseDimensions(); 49634 49635 return _setBaseDimensions; 49636 }); 49637 } else { 49638 console.warn("Requires GSAP 3.11.0 or later"); 49639 } 49640 49641 _setBaseDimensions(); 49642 49643 _addListener$1(_doc$1, "scroll", _onScroll$1); 49644 49645 var bodyStyle = _body$1.style, 49646 border = bodyStyle.borderTopStyle, 49647 AnimationProto = gsap$1.core.Animation.prototype, 49648 bounds, 49649 i; 49650 AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", { 49651 value: function value() { 49652 return this.time(-0.01, true); 49653 } 49654 }); 49655 bodyStyle.borderTopStyle = "solid"; 49656 bounds = _getBounds(_body$1); 49657 _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0; 49658 _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0; 49659 border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style"); 49660 _syncInterval = setInterval(_sync, 250); 49661 gsap$1.delayedCall(0.5, function () { 49662 return _startup$1 = 0; 49663 }); 49664 49665 _addListener$1(_doc$1, "touchcancel", _passThrough); 49666 49667 _addListener$1(_body$1, "touchstart", _passThrough); 49668 49669 _multiListener(_addListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler); 49670 49671 _multiListener(_addListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler); 49672 49673 _transformProp = gsap$1.utils.checkPrefix("transform"); 49674 49675 _stateProps.push(_transformProp); 49676 49677 _coreInitted$1 = _getTime$1(); 49678 _resizeDelay = gsap$1.delayedCall(0.2, _refreshAll).pause(); 49679 _autoRefresh = [_doc$1, "visibilitychange", function () { 49680 var w = _win$1.innerWidth, 49681 h = _win$1.innerHeight; 49682 49683 if (_doc$1.hidden) { 49684 _prevWidth = w; 49685 _prevHeight = h; 49686 } else if (_prevWidth !== w || _prevHeight !== h) { 49687 _onResize(); 49688 } 49689 }, _doc$1, "DOMContentLoaded", _refreshAll, _win$1, "load", _refreshAll, _win$1, "resize", _onResize]; 49690 49691 _iterateAutoRefresh(_addListener$1); 49692 49693 _triggers.forEach(function (trigger) { 49694 return trigger.enable(0, 1); 49695 }); 49696 49697 for (i = 0; i < _scrollers.length; i += 3) { 49698 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]); 49699 49700 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]); 49701 } 49702 } 49703 } 49704 }; 49705 49706 ScrollTrigger.config = function config(vars) { 49707 "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks); 49708 var ms = vars.syncInterval; 49709 ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms); 49710 "ignoreMobileResize" in vars && (_ignoreMobileResize = ScrollTrigger.isTouch === 1 && vars.ignoreMobileResize); 49711 49712 if ("autoRefreshEvents" in vars) { 49713 _iterateAutoRefresh(_removeListener$1) || _iterateAutoRefresh(_addListener$1, vars.autoRefreshEvents || "none"); 49714 _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1; 49715 } 49716 }; 49717 49718 ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) { 49719 var t = _getTarget(target), 49720 i = _scrollers.indexOf(t), 49721 isViewport = _isViewport$1(t); 49722 49723 if (~i) { 49724 _scrollers.splice(i, isViewport ? 6 : 2); 49725 } 49726 49727 if (vars) { 49728 isViewport ? _proxies.unshift(_win$1, vars, _body$1, vars, _docEl$1, vars) : _proxies.unshift(t, vars); 49729 } 49730 }; 49731 49732 ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) { 49733 _triggers.forEach(function (t) { 49734 return t._ctx && t._ctx.query === query && t._ctx.kill(true, true); 49735 }); 49736 }; 49737 49738 ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) { 49739 var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(), 49740 offset = bounds[horizontal ? _width : _height] * ratio || 0; 49741 return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win$1.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win$1.innerHeight; 49742 }; 49743 49744 ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) { 49745 _isString(element) && (element = _getTarget(element)); 49746 var bounds = element.getBoundingClientRect(), 49747 size = bounds[horizontal ? _width : _height], 49748 offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0; 49749 return horizontal ? (bounds.left + offset) / _win$1.innerWidth : (bounds.top + offset) / _win$1.innerHeight; 49750 }; 49751 49752 ScrollTrigger.killAll = function killAll(allowListeners) { 49753 _triggers.slice(0).forEach(function (t) { 49754 return t.vars.id !== "ScrollSmoother" && t.kill(); 49755 }); 49756 49757 if (allowListeners !== true) { 49758 var listeners = _listeners.killAll || []; 49759 _listeners = {}; 49760 listeners.forEach(function (f) { 49761 return f(); 49762 }); 49763 } 49764 }; 49765 49766 return ScrollTrigger; 49767 }(); 49768 ScrollTrigger$1.version = "3.12.5"; 49769 49770 ScrollTrigger$1.saveStyles = function (targets) { 49771 return targets ? _toArray(targets).forEach(function (target) { 49772 if (target && target.style) { 49773 var i = _savedStyles.indexOf(target); 49774 49775 i >= 0 && _savedStyles.splice(i, 5); 49776 49777 _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap$1.core.getCache(target), _context$1()); 49778 } 49779 }) : _savedStyles; 49780 }; 49781 49782 ScrollTrigger$1.revert = function (soft, media) { 49783 return _revertAll(!soft, media); 49784 }; 49785 49786 ScrollTrigger$1.create = function (vars, animation) { 49787 return new ScrollTrigger$1(vars, animation); 49788 }; 49789 49790 ScrollTrigger$1.refresh = function (safe) { 49791 return safe ? _onResize() : (_coreInitted$1 || ScrollTrigger$1.register()) && _refreshAll(true); 49792 }; 49793 49794 ScrollTrigger$1.update = function (force) { 49795 return ++_scrollers.cache && _updateAll(force === true ? 2 : 0); 49796 }; 49797 49798 ScrollTrigger$1.clearScrollMemory = _clearScrollMemory; 49799 49800 ScrollTrigger$1.maxScroll = function (element, horizontal) { 49801 return _maxScroll(element, horizontal ? _horizontal : _vertical); 49802 }; 49803 49804 ScrollTrigger$1.getScrollFunc = function (element, horizontal) { 49805 return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical); 49806 }; 49807 49808 ScrollTrigger$1.getById = function (id) { 49809 return _ids[id]; 49810 }; 49811 49812 ScrollTrigger$1.getAll = function () { 49813 return _triggers.filter(function (t) { 49814 return t.vars.id !== "ScrollSmoother"; 49815 }); 49816 }; 49817 49818 ScrollTrigger$1.isScrolling = function () { 49819 return !!_lastScrollTime; 49820 }; 49821 49822 ScrollTrigger$1.snapDirectional = _snapDirectional; 49823 49824 ScrollTrigger$1.addEventListener = function (type, callback) { 49825 var a = _listeners[type] || (_listeners[type] = []); 49826 ~a.indexOf(callback) || a.push(callback); 49827 }; 49828 49829 ScrollTrigger$1.removeEventListener = function (type, callback) { 49830 var a = _listeners[type], 49831 i = a && a.indexOf(callback); 49832 i >= 0 && a.splice(i, 1); 49833 }; 49834 49835 ScrollTrigger$1.batch = function (targets, vars) { 49836 var result = [], 49837 varsCopy = {}, 49838 interval = vars.interval || 0.016, 49839 batchMax = vars.batchMax || 1e9, 49840 proxyCallback = function proxyCallback(type, callback) { 49841 var elements = [], 49842 triggers = [], 49843 delay = gsap$1.delayedCall(interval, function () { 49844 callback(elements, triggers); 49845 elements = []; 49846 triggers = []; 49847 }).pause(); 49848 return function (self) { 49849 elements.length || delay.restart(true); 49850 elements.push(self.trigger); 49851 triggers.push(self); 49852 batchMax <= elements.length && delay.progress(1); 49853 }; 49854 }, 49855 p; 49856 49857 for (p in vars) { 49858 varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p]; 49859 } 49860 49861 if (_isFunction(batchMax)) { 49862 batchMax = batchMax(); 49863 49864 _addListener$1(ScrollTrigger$1, "refresh", function () { 49865 return batchMax = vars.batchMax(); 49866 }); 49867 } 49868 49869 _toArray(targets).forEach(function (target) { 49870 var config = {}; 49871 49872 for (p in varsCopy) { 49873 config[p] = varsCopy[p]; 49874 } 49875 49876 config.trigger = target; 49877 result.push(ScrollTrigger$1.create(config)); 49878 }); 49879 49880 return result; 49881 }; 49882 49883 var _clampScrollAndGetDurationMultiplier = function _clampScrollAndGetDurationMultiplier(scrollFunc, current, end, max) { 49884 current > max ? scrollFunc(max) : current < 0 && scrollFunc(0); 49885 return end > max ? (max - current) / (end - current) : end < 0 ? current / (current - end) : 1; 49886 }, 49887 _allowNativePanning = function _allowNativePanning(target, direction) { 49888 if (direction === true) { 49889 target.style.removeProperty("touch-action"); 49890 } else { 49891 target.style.touchAction = direction === true ? "auto" : direction ? "pan-" + direction + (Observer.isTouch ? " pinch-zoom" : "") : "none"; 49892 } 49893 49894 target === _docEl$1 && _allowNativePanning(_body$1, direction); 49895 }, 49896 _overflow = { 49897 auto: 1, 49898 scroll: 1 49899 }, 49900 _nestedScroll = function _nestedScroll(_ref5) { 49901 var event = _ref5.event, 49902 target = _ref5.target, 49903 axis = _ref5.axis; 49904 49905 var node = (event.changedTouches ? event.changedTouches[0] : event).target, 49906 cache = node._gsap || gsap$1.core.getCache(node), 49907 time = _getTime$1(), 49908 cs; 49909 49910 if (!cache._isScrollT || time - cache._isScrollT > 2000) { 49911 while (node && node !== _body$1 && (node.scrollHeight <= node.clientHeight && node.scrollWidth <= node.clientWidth || !(_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]))) { 49912 node = node.parentNode; 49913 } 49914 49915 cache._isScroll = node && node !== target && !_isViewport$1(node) && (_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]); 49916 cache._isScrollT = time; 49917 } 49918 49919 if (cache._isScroll || axis === "x") { 49920 event.stopPropagation(); 49921 event._gsapAllow = true; 49922 } 49923 }, 49924 _inputObserver = function _inputObserver(target, type, inputs, nested) { 49925 return Observer.create({ 49926 target: target, 49927 capture: true, 49928 debounce: false, 49929 lockAxis: true, 49930 type: type, 49931 onWheel: nested = nested && _nestedScroll, 49932 onPress: nested, 49933 onDrag: nested, 49934 onScroll: nested, 49935 onEnable: function onEnable() { 49936 return inputs && _addListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, false, true); 49937 }, 49938 onDisable: function onDisable() { 49939 return _removeListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, true); 49940 } 49941 }); 49942 }, 49943 _inputExp = /(input|label|select|textarea)/i, 49944 _inputIsFocused, 49945 _captureInputs = function _captureInputs(e) { 49946 var isInput = _inputExp.test(e.target.tagName); 49947 49948 if (isInput || _inputIsFocused) { 49949 e._gsapAllow = true; 49950 _inputIsFocused = isInput; 49951 } 49952 }, 49953 _getScrollNormalizer = function _getScrollNormalizer(vars) { 49954 _isObject(vars) || (vars = {}); 49955 vars.preventDefault = vars.isNormalizer = vars.allowClicks = true; 49956 vars.type || (vars.type = "wheel,touch"); 49957 vars.debounce = !!vars.debounce; 49958 vars.id = vars.id || "normalizer"; 49959 49960 var _vars2 = vars, 49961 normalizeScrollX = _vars2.normalizeScrollX, 49962 momentum = _vars2.momentum, 49963 allowNestedScroll = _vars2.allowNestedScroll, 49964 onRelease = _vars2.onRelease, 49965 self, 49966 maxY, 49967 target = _getTarget(vars.target) || _docEl$1, 49968 smoother = gsap$1.core.globals().ScrollSmoother, 49969 smootherInstance = smoother && smoother.get(), 49970 content = _fixIOSBug && (vars.content && _getTarget(vars.content) || smootherInstance && vars.content !== false && !smootherInstance.smooth() && smootherInstance.content()), 49971 scrollFuncY = _getScrollFunc(target, _vertical), 49972 scrollFuncX = _getScrollFunc(target, _horizontal), 49973 scale = 1,
vendor: 4,132 bytes, lines 49974-50095
49974 initialScale = (Observer.isTouch && _win$1.visualViewport ? _win$1.visualViewport.scale * _win$1.visualViewport.width : _win$1.outerWidth) / _win$1.innerWidth, 49975 wheelRefresh = 0, 49976 resolveMomentumDuration = _isFunction(momentum) ? function () { 49977 return momentum(self); 49978 } : function () { 49979 return momentum || 2.8; 49980 }, 49981 lastRefreshID, 49982 skipTouchMove, 49983 inputObserver = _inputObserver(target, vars.type, true, allowNestedScroll), 49984 resumeTouchMove = function resumeTouchMove() { 49985 return skipTouchMove = false; 49986 }, 49987 scrollClampX = _passThrough, 49988 scrollClampY = _passThrough, 49989 updateClamps = function updateClamps() { 49990 maxY = _maxScroll(target, _vertical); 49991 scrollClampY = _clamp$1(_fixIOSBug ? 1 : 0, maxY); 49992 normalizeScrollX && (scrollClampX = _clamp$1(0, _maxScroll(target, _horizontal))); 49993 lastRefreshID = _refreshID; 49994 }, 49995 removeContentOffset = function removeContentOffset() { 49996 content._gsap.y = _round(parseFloat(content._gsap.y) + scrollFuncY.offset) + "px"; 49997 content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + parseFloat(content._gsap.y) + ", 0, 1)"; 49998 scrollFuncY.offset = scrollFuncY.cacheID = 0; 49999 }, 50000 ignoreDrag = function ignoreDrag() { 50001 if (skipTouchMove) { 50002 requestAnimationFrame(resumeTouchMove); 50003 50004 var offset = _round(self.deltaY / 2), 50005 scroll = scrollClampY(scrollFuncY.v - offset); 50006 50007 if (content && scroll !== scrollFuncY.v + scrollFuncY.offset) { 50008 scrollFuncY.offset = scroll - scrollFuncY.v; 50009 50010 var y = _round((parseFloat(content && content._gsap.y) || 0) - scrollFuncY.offset); 50011 50012 content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + y + ", 0, 1)"; 50013 content._gsap.y = y + "px"; 50014 scrollFuncY.cacheID = _scrollers.cache; 50015 50016 _updateAll(); 50017 } 50018 50019 return true; 50020 } 50021 50022 scrollFuncY.offset && removeContentOffset(); 50023 skipTouchMove = true; 50024 }, 50025 tween, 50026 startScrollX, 50027 startScrollY, 50028 onStopDelayedCall, 50029 onResize = function onResize() { 50030 updateClamps(); 50031 50032 if (tween.isActive() && tween.vars.scrollY > maxY) { 50033 scrollFuncY() > maxY ? tween.progress(1) && scrollFuncY(maxY) : tween.resetTo("scrollY", maxY); 50034 } 50035 }; 50036 50037 content && gsap$1.set(content, { 50038 y: "+=0" 50039 }); 50040 50041 vars.ignoreCheck = function (e) { 50042 return _fixIOSBug && e.type === "touchmove" && ignoreDrag() || scale > 1.05 && e.type !== "touchstart" || self.isGesturing || e.touches && e.touches.length > 1; 50043 }; 50044 50045 vars.onPress = function () { 50046 skipTouchMove = false; 50047 var prevScale = scale; 50048 scale = _round((_win$1.visualViewport && _win$1.visualViewport.scale || 1) / initialScale); 50049 tween.pause(); 50050 prevScale !== scale && _allowNativePanning(target, scale > 1.01 ? true : normalizeScrollX ? false : "x"); 50051 startScrollX = scrollFuncX(); 50052 startScrollY = scrollFuncY(); 50053 updateClamps(); 50054 lastRefreshID = _refreshID; 50055 }; 50056 50057 vars.onRelease = vars.onGestureStart = function (self, wasDragging) { 50058 scrollFuncY.offset && removeContentOffset(); 50059 50060 if (!wasDragging) { 50061 onStopDelayedCall.restart(true); 50062 } else { 50063 _scrollers.cache++; 50064 var dur = resolveMomentumDuration(), 50065 currentScroll, 50066 endScroll; 50067 50068 if (normalizeScrollX) { 50069 currentScroll = scrollFuncX(); 50070 endScroll = currentScroll + dur * 0.05 * -self.velocityX / 0.227; 50071 dur *= _clampScrollAndGetDurationMultiplier(scrollFuncX, currentScroll, endScroll, _maxScroll(target, _horizontal)); 50072 tween.vars.scrollX = scrollClampX(endScroll); 50073 } 50074 50075 currentScroll = scrollFuncY(); 50076 endScroll = currentScroll + dur * 0.05 * -self.velocityY / 0.227; 50077 dur *= _clampScrollAndGetDurationMultiplier(scrollFuncY, currentScroll, endScroll, _maxScroll(target, _vertical)); 50078 tween.vars.scrollY = scrollClampY(endScroll); 50079 tween.invalidate().duration(dur).play(0.01); 50080 50081 if (_fixIOSBug && tween.vars.scrollY >= maxY || currentScroll >= maxY - 1) { 50082 gsap$1.to({}, { 50083 onUpdate: onResize, 50084 duration: dur 50085 }); 50086 } 50087 } 50088 50089 onRelease && onRelease(self); 50090 }; 50091 50092 vars.onWheel = function () { 50093 tween._ts && tween.pause(); 50094 50095 if (_getTime$1() - wheelRefresh > 1000) {
vendor: 28,617 bytes, lines 50096-51150
50096 lastRefreshID = 0; 50097 wheelRefresh = _getTime$1(); 50098 } 50099 }; 50100 50101 vars.onChange = function (self, dx, dy, xArray, yArray) { 50102 _refreshID !== lastRefreshID && updateClamps(); 50103 dx && normalizeScrollX && scrollFuncX(scrollClampX(xArray[2] === dx ? startScrollX + (self.startX - self.x) : scrollFuncX() + dx - xArray[1])); 50104 50105 if (dy) { 50106 scrollFuncY.offset && removeContentOffset(); 50107 var isTouch = yArray[2] === dy, 50108 y = isTouch ? startScrollY + self.startY - self.y : scrollFuncY() + dy - yArray[1], 50109 yClamped = scrollClampY(y); 50110 isTouch && y !== yClamped && (startScrollY += yClamped - y); 50111 scrollFuncY(yClamped); 50112 } 50113 50114 (dy || dx) && _updateAll(); 50115 }; 50116 50117 vars.onEnable = function () { 50118 _allowNativePanning(target, normalizeScrollX ? false : "x"); 50119 50120 ScrollTrigger$1.addEventListener("refresh", onResize); 50121 50122 _addListener$1(_win$1, "resize", onResize); 50123 50124 if (scrollFuncY.smooth) { 50125 scrollFuncY.target.style.scrollBehavior = "auto"; 50126 scrollFuncY.smooth = scrollFuncX.smooth = false; 50127 } 50128 50129 inputObserver.enable(); 50130 }; 50131 50132 vars.onDisable = function () { 50133 _allowNativePanning(target, true); 50134 50135 _removeListener$1(_win$1, "resize", onResize); 50136 50137 ScrollTrigger$1.removeEventListener("refresh", onResize); 50138 inputObserver.kill(); 50139 }; 50140 50141 vars.lockAxis = vars.lockAxis !== false; 50142 self = new Observer(vars); 50143 self.iOS = _fixIOSBug; 50144 _fixIOSBug && !scrollFuncY() && scrollFuncY(1); 50145 _fixIOSBug && gsap$1.ticker.add(_passThrough); 50146 onStopDelayedCall = self._dc; 50147 tween = gsap$1.to(self, { 50148 ease: "power4", 50149 paused: true, 50150 inherit: false, 50151 scrollX: normalizeScrollX ? "+=0.1" : "+=0", 50152 scrollY: "+=0.1", 50153 modifiers: { 50154 scrollY: _interruptionTracker(scrollFuncY, scrollFuncY(), function () { 50155 return tween.pause(); 50156 }) 50157 }, 50158 onUpdate: _updateAll, 50159 onComplete: onStopDelayedCall.vars.onComplete 50160 }); 50161 return self; 50162 }; 50163 50164 ScrollTrigger$1.sort = function (func) { 50165 return _triggers.sort(func || function (a, b) { 50166 return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6); 50167 }); 50168 }; 50169 50170 ScrollTrigger$1.observe = function (vars) { 50171 return new Observer(vars); 50172 }; 50173 50174 ScrollTrigger$1.normalizeScroll = function (vars) { 50175 if (typeof vars === "undefined") { 50176 return _normalizer$1; 50177 } 50178 50179 if (vars === true && _normalizer$1) { 50180 return _normalizer$1.enable(); 50181 } 50182 50183 if (vars === false) { 50184 _normalizer$1 && _normalizer$1.kill(); 50185 _normalizer$1 = vars; 50186 return; 50187 } 50188 50189 var normalizer = vars instanceof Observer ? vars : _getScrollNormalizer(vars); 50190 _normalizer$1 && _normalizer$1.target === normalizer.target && _normalizer$1.kill(); 50191 _isViewport$1(normalizer.target) && (_normalizer$1 = normalizer); 50192 return normalizer; 50193 }; 50194 50195 ScrollTrigger$1.core = { 50196 _getVelocityProp: _getVelocityProp, 50197 _inputObserver: _inputObserver, 50198 _scrollers: _scrollers, 50199 _proxies: _proxies, 50200 bridge: { 50201 ss: function ss() { 50202 _lastScrollTime || _dispatch("scrollStart"); 50203 _lastScrollTime = _getTime$1(); 50204 }, 50205 ref: function ref() { 50206 return _refreshing; 50207 } 50208 } 50209 }; 50210 _getGSAP$1() && gsap$1.registerPlugin(ScrollTrigger$1); 50211 50212 exports.ScrollTrigger = ScrollTrigger$1; 50213 exports.default = ScrollTrigger$1; 50214 50215 if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;} 50216 50217 }))); 50218 50219/*! 50220 * CustomEase 3.12.7 50221 * https://gsap.com 50222 * 50223 * @license Copyright 2025, GreenSock. All rights reserved. 50224 * Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership. 50225 * @author: Jack Doyle, [email protected] 50226 */ 50227 50228 (function (global, factory) { 50229 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 50230 typeof define === 'function' && define.amd ? define(['exports'], factory) : 50231 (global = global || self, factory(global.window = global.window || {})); 50232}(this, (function (exports) { 'use strict'; 50233 50234 var _svgPathExp = /[achlmqstvz]|(-?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig, 50235 _scientific = /[\+\-]?\d*\.?\d+e[\+\-]?\d+/ig, 50236 _DEG2RAD = Math.PI / 180, 50237 _sin = Math.sin, 50238 _cos = Math.cos, 50239 _abs = Math.abs, 50240 _sqrt = Math.sqrt, 50241 _isNumber = function _isNumber(value) { 50242 return typeof value === "number"; 50243 }, 50244 _roundingNum = 1e5, 50245 _round = function _round(value) { 50246 return Math.round(value * _roundingNum) / _roundingNum || 0; 50247 }; 50248 function transformRawPath(rawPath, a, b, c, d, tx, ty) { 50249 var j = rawPath.length, 50250 segment, 50251 l, 50252 i, 50253 x, 50254 y; 50255 50256 while (--j > -1) { 50257 segment = rawPath[j]; 50258 l = segment.length; 50259 50260 for (i = 0; i < l; i += 2) { 50261 x = segment[i]; 50262 y = segment[i + 1]; 50263 segment[i] = x * a + y * c + tx; 50264 segment[i + 1] = x * b + y * d + ty; 50265 } 50266 } 50267 50268 rawPath._dirty = 1; 50269 return rawPath; 50270 } 50271 50272 function arcToSegment(lastX, lastY, rx, ry, angle, largeArcFlag, sweepFlag, x, y) { 50273 if (lastX === x && lastY === y) { 50274 return; 50275 } 50276 50277 rx = _abs(rx); 50278 ry = _abs(ry); 50279 50280 var angleRad = angle % 360 * _DEG2RAD, 50281 cosAngle = _cos(angleRad), 50282 sinAngle = _sin(angleRad), 50283 PI = Math.PI, 50284 TWOPI = PI * 2, 50285 dx2 = (lastX - x) / 2, 50286 dy2 = (lastY - y) / 2, 50287 x1 = cosAngle * dx2 + sinAngle * dy2, 50288 y1 = -sinAngle * dx2 + cosAngle * dy2, 50289 x1_sq = x1 * x1, 50290 y1_sq = y1 * y1, 50291 radiiCheck = x1_sq / (rx * rx) + y1_sq / (ry * ry); 50292 50293 if (radiiCheck > 1) { 50294 rx = _sqrt(radiiCheck) * rx; 50295 ry = _sqrt(radiiCheck) * ry; 50296 } 50297 50298 var rx_sq = rx * rx, 50299 ry_sq = ry * ry, 50300 sq = (rx_sq * ry_sq - rx_sq * y1_sq - ry_sq * x1_sq) / (rx_sq * y1_sq + ry_sq * x1_sq); 50301 50302 if (sq < 0) { 50303 sq = 0; 50304 } 50305 50306 var coef = (largeArcFlag === sweepFlag ? -1 : 1) * _sqrt(sq), 50307 cx1 = coef * (rx * y1 / ry), 50308 cy1 = coef * -(ry * x1 / rx), 50309 sx2 = (lastX + x) / 2, 50310 sy2 = (lastY + y) / 2, 50311 cx = sx2 + (cosAngle * cx1 - sinAngle * cy1), 50312 cy = sy2 + (sinAngle * cx1 + cosAngle * cy1), 50313 ux = (x1 - cx1) / rx, 50314 uy = (y1 - cy1) / ry, 50315 vx = (-x1 - cx1) / rx, 50316 vy = (-y1 - cy1) / ry, 50317 temp = ux * ux + uy * uy, 50318 angleStart = (uy < 0 ? -1 : 1) * Math.acos(ux / _sqrt(temp)), 50319 angleExtent = (ux * vy - uy * vx < 0 ? -1 : 1) * Math.acos((ux * vx + uy * vy) / _sqrt(temp * (vx * vx + vy * vy))); 50320 50321 isNaN(angleExtent) && (angleExtent = PI); 50322 50323 if (!sweepFlag && angleExtent > 0) { 50324 angleExtent -= TWOPI; 50325 } else if (sweepFlag && angleExtent < 0) { 50326 angleExtent += TWOPI; 50327 } 50328 50329 angleStart %= TWOPI; 50330 angleExtent %= TWOPI; 50331 50332 var segments = Math.ceil(_abs(angleExtent) / (TWOPI / 4)), 50333 rawPath = [], 50334 angleIncrement = angleExtent / segments, 50335 controlLength = 4 / 3 * _sin(angleIncrement / 2) / (1 + _cos(angleIncrement / 2)), 50336 ma = cosAngle * rx, 50337 mb = sinAngle * rx, 50338 mc = sinAngle * -ry, 50339 md = cosAngle * ry, 50340 i; 50341 50342 for (i = 0; i < segments; i++) { 50343 angle = angleStart + i * angleIncrement; 50344 x1 = _cos(angle); 50345 y1 = _sin(angle); 50346 ux = _cos(angle += angleIncrement); 50347 uy = _sin(angle); 50348 rawPath.push(x1 - controlLength * y1, y1 + controlLength * x1, ux + controlLength * uy, uy - controlLength * ux, ux, uy); 50349 } 50350 50351 for (i = 0; i < rawPath.length; i += 2) { 50352 x1 = rawPath[i]; 50353 y1 = rawPath[i + 1]; 50354 rawPath[i] = x1 * ma + y1 * mc + cx; 50355 rawPath[i + 1] = x1 * mb + y1 * md + cy; 50356 } 50357 50358 rawPath[i - 2] = x; 50359 rawPath[i - 1] = y; 50360 return rawPath; 50361 } 50362 50363 function stringToRawPath(d) { 50364 var a = (d + "").replace(_scientific, function (m) { 50365 var n = +m; 50366 return n < 0.0001 && n > -0.0001 ? 0 : n; 50367 }).match(_svgPathExp) || [], 50368 path = [], 50369 relativeX = 0, 50370 relativeY = 0, 50371 twoThirds = 2 / 3, 50372 elements = a.length, 50373 points = 0, 50374 errorMessage = "ERROR: malformed path: " + d, 50375 i, 50376 j, 50377 x, 50378 y, 50379 command, 50380 isRelative, 50381 segment, 50382 startX, 50383 startY, 50384 difX, 50385 difY, 50386 beziers, 50387 prevCommand, 50388 flag1, 50389 flag2, 50390 line = function line(sx, sy, ex, ey) { 50391 difX = (ex - sx) / 3; 50392 difY = (ey - sy) / 3; 50393 segment.push(sx + difX, sy + difY, ex - difX, ey - difY, ex, ey); 50394 }; 50395 50396 if (!d || !isNaN(a[0]) || isNaN(a[1])) { 50397 console.log(errorMessage); 50398 return path; 50399 } 50400 50401 for (i = 0; i < elements; i++) { 50402 prevCommand = command; 50403 50404 if (isNaN(a[i])) { 50405 command = a[i].toUpperCase(); 50406 isRelative = command !== a[i]; 50407 } else { 50408 i--; 50409 } 50410 50411 x = +a[i + 1]; 50412 y = +a[i + 2]; 50413 50414 if (isRelative) { 50415 x += relativeX; 50416 y += relativeY; 50417 } 50418 50419 if (!i) { 50420 startX = x; 50421 startY = y; 50422 } 50423 50424 if (command === "M") { 50425 if (segment) { 50426 if (segment.length < 8) { 50427 path.length -= 1; 50428 } else { 50429 points += segment.length; 50430 } 50431 } 50432 50433 relativeX = startX = x; 50434 relativeY = startY = y; 50435 segment = [x, y]; 50436 path.push(segment); 50437 i += 2; 50438 command = "L"; 50439 } else if (command === "C") { 50440 if (!segment) { 50441 segment = [0, 0]; 50442 } 50443 50444 if (!isRelative) { 50445 relativeX = relativeY = 0; 50446 } 50447 50448 segment.push(x, y, relativeX + a[i + 3] * 1, relativeY + a[i + 4] * 1, relativeX += a[i + 5] * 1, relativeY += a[i + 6] * 1); 50449 i += 6; 50450 } else if (command === "S") { 50451 difX = relativeX; 50452 difY = relativeY; 50453 50454 if (prevCommand === "C" || prevCommand === "S") { 50455 difX += relativeX - segment[segment.length - 4]; 50456 difY += relativeY - segment[segment.length - 3]; 50457 } 50458 50459 if (!isRelative) { 50460 relativeX = relativeY = 0; 50461 } 50462 50463 segment.push(difX, difY, x, y, relativeX += a[i + 3] * 1, relativeY += a[i + 4] * 1); 50464 i += 4; 50465 } else if (command === "Q") { 50466 difX = relativeX + (x - relativeX) * twoThirds; 50467 difY = relativeY + (y - relativeY) * twoThirds; 50468 50469 if (!isRelative) { 50470 relativeX = relativeY = 0; 50471 } 50472 50473 relativeX += a[i + 3] * 1; 50474 relativeY += a[i + 4] * 1; 50475 segment.push(difX, difY, relativeX + (x - relativeX) * twoThirds, relativeY + (y - relativeY) * twoThirds, relativeX, relativeY); 50476 i += 4; 50477 } else if (command === "T") { 50478 difX = relativeX - segment[segment.length - 4]; 50479 difY = relativeY - segment[segment.length - 3]; 50480 segment.push(relativeX + difX, relativeY + difY, x + (relativeX + difX * 1.5 - x) * twoThirds, y + (relativeY + difY * 1.5 - y) * twoThirds, relativeX = x, relativeY = y); 50481 i += 2; 50482 } else if (command === "H") { 50483 line(relativeX, relativeY, relativeX = x, relativeY); 50484 i += 1; 50485 } else if (command === "V") { 50486 line(relativeX, relativeY, relativeX, relativeY = x + (isRelative ? relativeY - relativeX : 0)); 50487 i += 1; 50488 } else if (command === "L" || command === "Z") { 50489 if (command === "Z") { 50490 x = startX; 50491 y = startY; 50492 segment.closed = true; 50493 } 50494 50495 if (command === "L" || _abs(relativeX - x) > 0.5 || _abs(relativeY - y) > 0.5) { 50496 line(relativeX, relativeY, x, y); 50497 50498 if (command === "L") { 50499 i += 2; 50500 } 50501 } 50502 50503 relativeX = x; 50504 relativeY = y; 50505 } else if (command === "A") { 50506 flag1 = a[i + 4]; 50507 flag2 = a[i + 5]; 50508 difX = a[i + 6]; 50509 difY = a[i + 7]; 50510 j = 7; 50511 50512 if (flag1.length > 1) { 50513 if (flag1.length < 3) { 50514 difY = difX; 50515 difX = flag2; 50516 j--; 50517 } else { 50518 difY = flag2; 50519 difX = flag1.substr(2); 50520 j -= 2; 50521 } 50522 50523 flag2 = flag1.charAt(1); 50524 flag1 = flag1.charAt(0); 50525 } 50526 50527 beziers = arcToSegment(relativeX, relativeY, +a[i + 1], +a[i + 2], +a[i + 3], +flag1, +flag2, (isRelative ? relativeX : 0) + difX * 1, (isRelative ? relativeY : 0) + difY * 1); 50528 i += j; 50529 50530 if (beziers) { 50531 for (j = 0; j < beziers.length; j++) { 50532 segment.push(beziers[j]); 50533 } 50534 } 50535 50536 relativeX = segment[segment.length - 2]; 50537 relativeY = segment[segment.length - 1]; 50538 } else { 50539 console.log(errorMessage); 50540 } 50541 } 50542 50543 i = segment.length; 50544 50545 if (i < 6) { 50546 path.pop(); 50547 i = 0; 50548 } else if (segment[0] === segment[i - 2] && segment[1] === segment[i - 1]) { 50549 segment.closed = true; 50550 } 50551 50552 path.totalPoints = points + i; 50553 return path; 50554 } 50555 function rawPathToString(rawPath) { 50556 if (_isNumber(rawPath[0])) { 50557 rawPath = [rawPath]; 50558 } 50559 50560 var result = "", 50561 l = rawPath.length, 50562 sl, 50563 s, 50564 i, 50565 segment; 50566 50567 for (s = 0; s < l; s++) { 50568 segment = rawPath[s]; 50569 result += "M" + _round(segment[0]) + "," + _round(segment[1]) + " C"; 50570 sl = segment.length; 50571 50572 for (i = 2; i < sl; i++) { 50573 result += _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i]) + " "; 50574 } 50575 50576 if (segment.closed) { 50577 result += "z"; 50578 } 50579 } 50580 50581 return result; 50582 } 50583 50584 /*! 50585 * CustomEase 3.12.7 50586 * https://gsap.com 50587 * 50588 * @license Copyright 2008-2025, GreenSock. All rights reserved. 50589 * Subject to the terms at https://gsap.com/standard-license or for 50590 * Club GSAP members, the agreement issued with that membership. 50591 * @author: Jack Doyle, [email protected] 50592 */ 50593 50594 var gsap, 50595 _coreInitted, 50596 _getGSAP = function _getGSAP() { 50597 return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap; 50598 }, 50599 _initCore = function _initCore() { 50600 gsap = _getGSAP(); 50601 50602 if (gsap) { 50603 gsap.registerEase("_CE", CustomEase.create); 50604 _coreInitted = 1; 50605 } else { 50606 console.warn("Please gsap.registerPlugin(CustomEase)"); 50607 } 50608 }, 50609 _bigNum = 1e20, 50610 _round$1 = function _round(value) { 50611 return ~~(value * 1000 + (value < 0 ? -.5 : .5)) / 1000; 50612 }, 50613 _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/gi, 50614 _needsParsingExp = /[cLlsSaAhHvVtTqQ]/g, 50615 _findMinimum = function _findMinimum(values) { 50616 var l = values.length, 50617 min = _bigNum, 50618 i; 50619 50620 for (i = 1; i < l; i += 6) { 50621 +values[i] < min && (min = +values[i]); 50622 } 50623 50624 return min; 50625 }, 50626 _normalize = function _normalize(values, height, originY) { 50627 if (!originY && originY !== 0) { 50628 originY = Math.max(+values[values.length - 1], +values[1]); 50629 } 50630 50631 var tx = +values[0] * -1, 50632 ty = -originY, 50633 l = values.length, 50634 sx = 1 / (+values[l - 2] + tx), 50635 sy = -height || (Math.abs(+values[l - 1] - +values[1]) < 0.01 * (+values[l - 2] - +values[0]) ? _findMinimum(values) + ty : +values[l - 1] + ty), 50636 i; 50637 50638 if (sy) { 50639 sy = 1 / sy; 50640 } else { 50641 sy = -sx; 50642 } 50643 50644 for (i = 0; i < l; i += 2) { 50645 values[i] = (+values[i] + tx) * sx; 50646 values[i + 1] = (+values[i + 1] + ty) * sy; 50647 } 50648 }, 50649 _bezierToPoints = function _bezierToPoints(x1, y1, x2, y2, x3, y3, x4, y4, threshold, points, index) { 50650 var x12 = (x1 + x2) / 2, 50651 y12 = (y1 + y2) / 2, 50652 x23 = (x2 + x3) / 2, 50653 y23 = (y2 + y3) / 2, 50654 x34 = (x3 + x4) / 2, 50655 y34 = (y3 + y4) / 2, 50656 x123 = (x12 + x23) / 2, 50657 y123 = (y12 + y23) / 2, 50658 x234 = (x23 + x34) / 2, 50659 y234 = (y23 + y34) / 2, 50660 x1234 = (x123 + x234) / 2, 50661 y1234 = (y123 + y234) / 2, 50662 dx = x4 - x1, 50663 dy = y4 - y1, 50664 d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx), 50665 d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx), 50666 length; 50667 50668 if (!points) { 50669 points = [{ 50670 x: x1, 50671 y: y1 50672 }, { 50673 x: x4, 50674 y: y4 50675 }]; 50676 index = 1; 50677 } 50678 50679 points.splice(index || points.length - 1, 0, { 50680 x: x1234, 50681 y: y1234 50682 }); 50683 50684 if ((d2 + d3) * (d2 + d3) > threshold * (dx * dx + dy * dy)) { 50685 length = points.length; 50686 50687 _bezierToPoints(x1, y1, x12, y12, x123, y123, x1234, y1234, threshold, points, index); 50688 50689 _bezierToPoints(x1234, y1234, x234, y234, x34, y34, x4, y4, threshold, points, index + 1 + (points.length - length)); 50690 } 50691 50692 return points; 50693 }; 50694 50695 var CustomEase = function () { 50696 function CustomEase(id, data, config) { 50697 _coreInitted || _initCore(); 50698 this.id = id; 50699 this.setData(data, config); 50700 } 50701 50702 var _proto = CustomEase.prototype; 50703 50704 _proto.setData = function setData(data, config) { 50705 config = config || {}; 50706 data = data || "0,0,1,1"; 50707 var values = data.match(_numExp), 50708 closest = 1, 50709 points = [], 50710 lookup = [], 50711 precision = config.precision || 1, 50712 fast = precision <= 1, 50713 l, 50714 a1, 50715 a2, 50716 i, 50717 inc, 50718 j, 50719 point, 50720 prevPoint, 50721 p; 50722 this.data = data; 50723 50724 if (_needsParsingExp.test(data) || ~data.indexOf("M") && data.indexOf("C") < 0) { 50725 values = stringToRawPath(data)[0]; 50726 } 50727 50728 l = values.length; 50729 50730 if (l === 4) { 50731 values.unshift(0, 0); 50732 values.push(1, 1); 50733 l = 8; 50734 } else if ((l - 2) % 6) { 50735 throw "Invalid CustomEase"; 50736 } 50737 50738 if (+values[0] !== 0 || +values[l - 2] !== 1) { 50739 _normalize(values, config.height, config.originY); 50740 } 50741 50742 this.segment = values; 50743 50744 for (i = 2; i < l; i += 6) { 50745 a1 = { 50746 x: +values[i - 2], 50747 y: +values[i - 1] 50748 }; 50749 a2 = { 50750 x: +values[i + 4], 50751 y: +values[i + 5] 50752 }; 50753 points.push(a1, a2); 50754 50755 _bezierToPoints(a1.x, a1.y, +values[i], +values[i + 1], +values[i + 2], +values[i + 3], a2.x, a2.y, 1 / (precision * 200000), points, points.length - 1); 50756 } 50757 50758 l = points.length; 50759 50760 for (i = 0; i < l; i++) { 50761 point = points[i]; 50762 prevPoint = points[i - 1] || point; 50763 50764 if ((point.x > prevPoint.x || prevPoint.y !== point.y && prevPoint.x === point.x || point === prevPoint) && point.x <= 1) { 50765 prevPoint.cx = point.x - prevPoint.x; 50766 prevPoint.cy = point.y - prevPoint.y; 50767 prevPoint.n = point; 50768 prevPoint.nx = point.x; 50769 50770 if (fast && i > 1 && Math.abs(prevPoint.cy / prevPoint.cx - points[i - 2].cy / points[i - 2].cx) > 2) { 50771 fast = 0; 50772 } 50773 50774 if (prevPoint.cx < closest) { 50775 if (!prevPoint.cx) { 50776 prevPoint.cx = 0.001; 50777 50778 if (i === l - 1) { 50779 prevPoint.x -= 0.001; 50780 closest = Math.min(closest, 0.001); 50781 fast = 0; 50782 } 50783 } else { 50784 closest = prevPoint.cx; 50785 } 50786 } 50787 } else { 50788 points.splice(i--, 1); 50789 l--; 50790 } 50791 } 50792 50793 l = 1 / closest + 1 | 0; 50794 inc = 1 / l; 50795 j = 0; 50796 point = points[0]; 50797 50798 if (fast) { 50799 for (i = 0; i < l; i++) { 50800 p = i * inc; 50801 50802 if (point.nx < p) { 50803 point = points[++j]; 50804 } 50805 50806 a1 = point.y + (p - point.x) / point.cx * point.cy; 50807 lookup[i] = { 50808 x: p, 50809 cx: inc, 50810 y: a1, 50811 cy: 0, 50812 nx: 9 50813 }; 50814 50815 if (i) { 50816 lookup[i - 1].cy = a1 - lookup[i - 1].y; 50817 } 50818 } 50819 50820 j = points[points.length - 1]; 50821 lookup[l - 1].cy = j.y - a1; 50822 lookup[l - 1].cx = j.x - lookup[lookup.length - 1].x; 50823 } else { 50824 for (i = 0; i < l; i++) { 50825 if (point.nx < i * inc) { 50826 point = points[++j]; 50827 } 50828 50829 lookup[i] = point; 50830 } 50831 50832 if (j < points.length - 1) { 50833 lookup[i - 1] = points[points.length - 2]; 50834 } 50835 } 50836 50837 this.ease = function (p) { 50838 var point = lookup[p * l | 0] || lookup[l - 1]; 50839 50840 if (point.nx < p) { 50841 point = point.n; 50842 } 50843 50844 return point.y + (p - point.x) / point.cx * point.cy; 50845 }; 50846 50847 this.ease.custom = this; 50848 this.id && gsap && gsap.registerEase(this.id, this.ease); 50849 return this; 50850 }; 50851 50852 _proto.getSVGData = function getSVGData(config) { 50853 return CustomEase.getSVGData(this, config); 50854 }; 50855 50856 CustomEase.create = function create(id, data, config) { 50857 return new CustomEase(id, data, config).ease; 50858 }; 50859 50860 CustomEase.register = function register(core) { 50861 gsap = core; 50862 50863 _initCore(); 50864 }; 50865 50866 CustomEase.get = function get(id) { 50867 return gsap.parseEase(id); 50868 }; 50869 50870 CustomEase.getSVGData = function getSVGData(ease, config) { 50871 config = config || {}; 50872 var width = config.width || 100, 50873 height = config.height || 100, 50874 x = config.x || 0, 50875 y = (config.y || 0) + height, 50876 e = gsap.utils.toArray(config.path)[0], 50877 a, 50878 slope, 50879 i, 50880 inc, 50881 tx, 50882 ty, 50883 precision, 50884 threshold, 50885 prevX, 50886 prevY; 50887 50888 if (config.invert) { 50889 height = -height; 50890 y = 0; 50891 } 50892 50893 if (typeof ease === "string") { 50894 ease = gsap.parseEase(ease); 50895 } 50896 50897 if (ease.custom) { 50898 ease = ease.custom; 50899 } 50900 50901 if (ease instanceof CustomEase) { 50902 a = rawPathToString(transformRawPath([ease.segment], width, 0, 0, -height, x, y)); 50903 } else { 50904 a = [x, y]; 50905 precision = Math.max(5, (config.precision || 1) * 200); 50906 inc = 1 / precision; 50907 precision += 2; 50908 threshold = 5 / precision; 50909 prevX = _round$1(x + inc * width); 50910 prevY = _round$1(y + ease(inc) * -height); 50911 slope = (prevY - y) / (prevX - x); 50912 50913 for (i = 2; i < precision; i++) { 50914 tx = _round$1(x + i * inc * width); 50915 ty = _round$1(y + ease(i * inc) * -height); 50916 50917 if (Math.abs((ty - prevY) / (tx - prevX) - slope) > threshold || i === precision - 1) { 50918 a.push(prevX, prevY); 50919 slope = (ty - prevY) / (tx - prevX); 50920 } 50921 50922 prevX = tx; 50923 prevY = ty; 50924 } 50925 50926 a = "M" + a.join(","); 50927 } 50928 50929 e && e.setAttribute("d", a); 50930 return a; 50931 }; 50932 50933 return CustomEase; 50934 }(); 50935 CustomEase.version = "3.12.7"; 50936 CustomEase.headless = true; 50937 _getGSAP() && gsap.registerPlugin(CustomEase); 50938 50939 exports.CustomEase = CustomEase; 50940 exports.default = CustomEase; 50941 50942 Object.defineProperty(exports, '__esModule', { value: true }); 50943 50944}))); 50945(function (global, factory) { 50946 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 50947 typeof define === 'function' && define.amd ? define(['exports'], factory) : 50948 (global = global || self, factory(global.window = global.window || {})); 50949}(this, (function (exports) { 'use strict'; 50950 50951 function _inheritsLoose(subClass, superClass) { 50952 subClass.prototype = Object.create(superClass.prototype); 50953 subClass.prototype.constructor = subClass; 50954 subClass.__proto__ = superClass; 50955 } 50956 50957 function _assertThisInitialized(self) { 50958 if (self === void 0) { 50959 throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 50960 } 50961 50962 return self; 50963 } 50964 50965 var _doc, 50966 _win, 50967 _docElement, 50968 _body, 50969 _divContainer, 50970 _svgContainer, 50971 _identityMatrix, 50972 _gEl, 50973 _transformProp = "transform", 50974 _transformOriginProp = _transformProp + "Origin", 50975 _hasOffsetBug, 50976 _setDoc = function _setDoc(element) { 50977 var doc = element.ownerDocument || element; 50978 50979 if (!(_transformProp in element.style) && "msTransform" in element.style) { 50980 _transformProp = "msTransform"; 50981 _transformOriginProp = _transformProp + "Origin"; 50982 } 50983 50984 while (doc.parentNode && (doc = doc.parentNode)) {} 50985 50986 _win = window; 50987 _identityMatrix = new Matrix2D(); 50988 50989 if (doc) { 50990 _doc = doc; 50991 _docElement = doc.documentElement; 50992 _body = doc.body; 50993 _gEl = _doc.createElementNS("http://www.w3.org/2000/svg", "g"); 50994 _gEl.style.transform = "none"; 50995 var d1 = doc.createElement("div"), 50996 d2 = doc.createElement("div"), 50997 root = doc && (doc.body || doc.firstElementChild); 50998 50999 if (root && root.appendChild) { 51000 root.appendChild(d1); 51001 d1.appendChild(d2); 51002 d1.setAttribute("style", "position:static;transform:translate3d(0,0,1px)"); 51003 _hasOffsetBug = d2.offsetParent !== d1; 51004 root.removeChild(d1); 51005 } 51006 } 51007 51008 return doc; 51009 }, 51010 _forceNonZeroScale = function _forceNonZeroScale(e) { 51011 var a, cache; 51012 51013 while (e && e !== _body) { 51014 cache = e._gsap; 51015 cache && cache.uncache && cache.get(e, "x"); 51016 51017 if (cache && !cache.scaleX && !cache.scaleY && cache.renderTransform) { 51018 cache.scaleX = cache.scaleY = 1e-4; 51019 cache.renderTransform(1, cache); 51020 a ? a.push(cache) : a = [cache]; 51021 } 51022 51023 e = e.parentNode; 51024 } 51025 51026 return a; 51027 }, 51028 _svgTemps = [], 51029 _divTemps = [], 51030 _getDocScrollTop = function _getDocScrollTop() { 51031 return _win.pageYOffset || _doc.scrollTop || _docElement.scrollTop || _body.scrollTop || 0; 51032 }, 51033 _getDocScrollLeft = function _getDocScrollLeft() { 51034 return _win.pageXOffset || _doc.scrollLeft || _docElement.scrollLeft || _body.scrollLeft || 0; 51035 }, 51036 _svgOwner = function _svgOwner(element) { 51037 return element.ownerSVGElement || ((element.tagName + "").toLowerCase() === "svg" ? element : null); 51038 }, 51039 _isFixed = function _isFixed(element) { 51040 if (_win.getComputedStyle(element).position === "fixed") { 51041 return true; 51042 } 51043 51044 element = element.parentNode; 51045 51046 if (element && element.nodeType === 1) { 51047 return _isFixed(element); 51048 } 51049 }, 51050 _createSibling = function _createSibling(element, i) { 51051 if (element.parentNode && (_doc || _setDoc(element))) { 51052 var svg = _svgOwner(element), 51053 ns = svg ? svg.getAttribute("xmlns") || "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml", 51054 type = svg ? i ? "rect" : "g" : "div", 51055 x = i !== 2 ? 0 : 100, 51056 y = i === 3 ? 100 : 0, 51057 css = "position:absolute;display:block;pointer-events:none;margin:0;padding:0;", 51058 e = _doc.createElementNS ? _doc.createElementNS(ns.replace(/^https/, "http"), type) : _doc.createElement(type); 51059 51060 if (i) { 51061 if (!svg) { 51062 if (!_divContainer) { 51063 _divContainer = _createSibling(element); 51064 _divContainer.style.cssText = css; 51065 } 51066 51067 e.style.cssText = css + "width:0.1px;height:0.1px;top:" + y + "px;left:" + x + "px"; 51068 51069 _divContainer.appendChild(e); 51070 } else { 51071 _svgContainer || (_svgContainer = _createSibling(element)); 51072 e.setAttribute("width", 0.01); 51073 e.setAttribute("height", 0.01); 51074 e.setAttribute("transform", "translate(" + x + "," + y + ")"); 51075 51076 _svgContainer.appendChild(e); 51077 } 51078 } 51079 51080 return e; 51081 } 51082 51083 throw "Need document and parent."; 51084 }, 51085 _consolidate = function _consolidate(m) { 51086 var c = new Matrix2D(), 51087 i = 0; 51088 51089 for (; i < m.numberOfItems; i++) { 51090 c.multiply(m.getItem(i).matrix); 51091 } 51092 51093 return c; 51094 }, 51095 _getCTM = function _getCTM(svg) { 51096 var m = svg.getCTM(), 51097 transform; 51098 51099 if (!m) { 51100 transform = svg.style[_transformProp]; 51101 svg.style[_transformProp] = "none"; 51102 svg.appendChild(_gEl); 51103 m = _gEl.getCTM(); 51104 svg.removeChild(_gEl); 51105 transform ? svg.style[_transformProp] = transform : svg.style.removeProperty(_transformProp.replace(/([A-Z])/g, "-$1").toLowerCase()); 51106 } 51107 51108 return m || _identityMatrix.clone(); 51109 }, 51110 _placeSiblings = function _placeSiblings(element, adjustGOffset) { 51111 var svg = _svgOwner(element), 51112 isRootSVG = element === svg, 51113 siblings = svg ? _svgTemps : _divTemps, 51114 parent = element.parentNode, 51115 container, 51116 m, 51117 b, 51118 x, 51119 y, 51120 cs; 51121 51122 if (element === _win) { 51123 return element; 51124 } 51125 51126 siblings.length || siblings.push(_createSibling(element, 1), _createSibling(element, 2), _createSibling(element, 3)); 51127 container = svg ? _svgContainer : _divContainer; 51128 51129 if (svg) { 51130 if (isRootSVG) { 51131 b = _getCTM(element); 51132 x = -b.e / b.a; 51133 y = -b.f / b.d; 51134 m = _identityMatrix; 51135 } else if (element.getBBox) { 51136 b = element.getBBox(); 51137 m = element.transform ? element.transform.baseVal : {}; 51138 m = !m.numberOfItems ? _identityMatrix : m.numberOfItems > 1 ? _consolidate(m) : m.getItem(0).matrix; 51139 x = m.a * b.x + m.c * b.y; 51140 y = m.b * b.x + m.d * b.y; 51141 } else { 51142 m = new Matrix2D(); 51143 x = y = 0; 51144 } 51145 51146 if (adjustGOffset && element.tagName.toLowerCase() === "g") { 51147 x = y = 0; 51148 } 51149 51150 (isRootSVG ? svg : parent).appendChild(container);
vendor: 1,139 bytes, lines 51151-51186
51151 container.setAttribute("transform", "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + (m.e + x) + "," + (m.f + y) + ")"); 51152 } else { 51153 x = y = 0; 51154 51155 if (_hasOffsetBug) { 51156 m = element.offsetParent; 51157 b = element; 51158 51159 while (b && (b = b.parentNode) && b !== m && b.parentNode) { 51160 if ((_win.getComputedStyle(b)[_transformProp] + "").length > 4) { 51161 x = b.offsetLeft; 51162 y = b.offsetTop; 51163 b = 0; 51164 } 51165 } 51166 } 51167 51168 cs = _win.getComputedStyle(element); 51169 51170 if (cs.position !== "absolute" && cs.position !== "fixed") { 51171 m = element.offsetParent; 51172 51173 while (parent && parent !== m) { 51174 x += parent.scrollLeft || 0; 51175 y += parent.scrollTop || 0; 51176 parent = parent.parentNode; 51177 } 51178 } 51179 51180 b = container.style; 51181 b.top = element.offsetTop - y + "px"; 51182 b.left = element.offsetLeft - x + "px"; 51183 b[_transformProp] = cs[_transformProp]; 51184 b[_transformOriginProp] = cs[_transformOriginProp]; 51185 b.position = cs.position === "fixed" ? "fixed" : "absolute"; 51186 element.parentNode
vendor: 37,456 bytes, lines 51186-52441
51186.appendChild(container); 51187 } 51188 51189 return container; 51190 }, 51191 _setMatrix = function _setMatrix(m, a, b, c, d, e, f) { 51192 m.a = a; 51193 m.b = b; 51194 m.c = c; 51195 m.d = d; 51196 m.e = e; 51197 m.f = f; 51198 return m; 51199 }; 51200 51201 var Matrix2D = function () { 51202 function Matrix2D(a, b, c, d, e, f) { 51203 if (a === void 0) { 51204 a = 1; 51205 } 51206 51207 if (b === void 0) { 51208 b = 0; 51209 } 51210 51211 if (c === void 0) { 51212 c = 0; 51213 } 51214 51215 if (d === void 0) { 51216 d = 1; 51217 } 51218 51219 if (e === void 0) { 51220 e = 0; 51221 } 51222 51223 if (f === void 0) { 51224 f = 0; 51225 } 51226 51227 _setMatrix(this, a, b, c, d, e, f); 51228 } 51229 51230 var _proto = Matrix2D.prototype; 51231 51232 _proto.inverse = function inverse() { 51233 var a = this.a, 51234 b = this.b, 51235 c = this.c, 51236 d = this.d, 51237 e = this.e, 51238 f = this.f, 51239 determinant = a * d - b * c || 1e-10; 51240 return _setMatrix(this, d / determinant, -b / determinant, -c / determinant, a / determinant, (c * f - d * e) / determinant, -(a * f - b * e) / determinant); 51241 }; 51242 51243 _proto.multiply = function multiply(matrix) { 51244 var a = this.a, 51245 b = this.b, 51246 c = this.c, 51247 d = this.d, 51248 e = this.e, 51249 f = this.f, 51250 a2 = matrix.a, 51251 b2 = matrix.c, 51252 c2 = matrix.b, 51253 d2 = matrix.d, 51254 e2 = matrix.e, 51255 f2 = matrix.f; 51256 return _setMatrix(this, a2 * a + c2 * c, a2 * b + c2 * d, b2 * a + d2 * c, b2 * b + d2 * d, e + e2 * a + f2 * c, f + e2 * b + f2 * d); 51257 }; 51258 51259 _proto.clone = function clone() { 51260 return new Matrix2D(this.a, this.b, this.c, this.d, this.e, this.f); 51261 }; 51262 51263 _proto.equals = function equals(matrix) { 51264 var a = this.a, 51265 b = this.b, 51266 c = this.c, 51267 d = this.d, 51268 e = this.e, 51269 f = this.f; 51270 return a === matrix.a && b === matrix.b && c === matrix.c && d === matrix.d && e === matrix.e && f === matrix.f; 51271 }; 51272 51273 _proto.apply = function apply(point, decoratee) { 51274 if (decoratee === void 0) { 51275 decoratee = {}; 51276 } 51277 51278 var x = point.x, 51279 y = point.y, 51280 a = this.a, 51281 b = this.b, 51282 c = this.c, 51283 d = this.d, 51284 e = this.e, 51285 f = this.f; 51286 decoratee.x = x * a + y * c + e || 0; 51287 decoratee.y = x * b + y * d + f || 0; 51288 return decoratee; 51289 }; 51290 51291 return Matrix2D; 51292 }(); 51293 function getGlobalMatrix(element, inverse, adjustGOffset, includeScrollInFixed) { 51294 if (!element || !element.parentNode || (_doc || _setDoc(element)).documentElement === element) { 51295 return new Matrix2D(); 51296 } 51297 51298 var zeroScales = _forceNonZeroScale(element), 51299 svg = _svgOwner(element), 51300 temps = svg ? _svgTemps : _divTemps, 51301 container = _placeSiblings(element, adjustGOffset), 51302 b1 = temps[0].getBoundingClientRect(), 51303 b2 = temps[1].getBoundingClientRect(), 51304 b3 = temps[2].getBoundingClientRect(), 51305 parent = container.parentNode, 51306 isFixed = !includeScrollInFixed && _isFixed(element), 51307 m = new Matrix2D((b2.left - b1.left) / 100, (b2.top - b1.top) / 100, (b3.left - b1.left) / 100, (b3.top - b1.top) / 100, b1.left + (isFixed ? 0 : _getDocScrollLeft()), b1.top + (isFixed ? 0 : _getDocScrollTop())); 51308 51309 parent.removeChild(container); 51310 51311 if (zeroScales) { 51312 b1 = zeroScales.length; 51313 51314 while (b1--) { 51315 b2 = zeroScales[b1]; 51316 b2.scaleX = b2.scaleY = 0; 51317 b2.renderTransform(1, b2); 51318 } 51319 } 51320 51321 return inverse ? m.inverse() : m; 51322 } 51323 51324 var gsap, 51325 _win$1, 51326 _doc$1, 51327 _docElement$1, 51328 _body$1, 51329 _tempDiv, 51330 _placeholderDiv, 51331 _coreInitted, 51332 _checkPrefix, 51333 _toArray, 51334 _supportsPassive, 51335 _isTouchDevice, 51336 _touchEventLookup, 51337 _isMultiTouching, 51338 _isAndroid, 51339 InertiaPlugin, 51340 _defaultCursor, 51341 _supportsPointer, 51342 _context, 51343 _getStyleSaver, 51344 _dragCount = 0, 51345 _windowExists = function _windowExists() { 51346 return typeof window !== "undefined"; 51347 }, 51348 _getGSAP = function _getGSAP() { 51349 return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap; 51350 }, 51351 _isFunction = function _isFunction(value) { 51352 return typeof value === "function"; 51353 }, 51354 _isObject = function _isObject(value) { 51355 return typeof value === "object"; 51356 }, 51357 _isUndefined = function _isUndefined(value) { 51358 return typeof value === "undefined"; 51359 }, 51360 _emptyFunc = function _emptyFunc() { 51361 return false; 51362 }, 51363 _transformProp$1 = "transform", 51364 _transformOriginProp$1 = "transformOrigin", 51365 _round = function _round(value) { 51366 return Math.round(value * 10000) / 10000; 51367 }, 51368 _isArray = Array.isArray, 51369 _createElement = function _createElement(type, ns) { 51370 var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type); 51371 return e.style ? e : _doc$1.createElement(type); 51372 }, 51373 _RAD2DEG = 180 / Math.PI, 51374 _bigNum = 1e20, 51375 _identityMatrix$1 = new Matrix2D(), 51376 _getTime = Date.now || function () { 51377 return new Date().getTime(); 51378 }, 51379 _renderQueue = [], 51380 _lookup = {}, 51381 _lookupCount = 0, 51382 _clickableTagExp = /^(?:a|input|textarea|button|select)$/i, 51383 _lastDragTime = 0, 51384 _temp1 = {}, 51385 _windowProxy = {}, 51386 _copy = function _copy(obj, factor) { 51387 var copy = {}, 51388 p; 51389 51390 for (p in obj) { 51391 copy[p] = factor ? obj[p] * factor : obj[p]; 51392 } 51393 51394 return copy; 51395 }, 51396 _extend = function _extend(obj, defaults) { 51397 for (var p in defaults) { 51398 if (!(p in obj)) { 51399 obj[p] = defaults[p]; 51400 } 51401 } 51402 51403 return obj; 51404 }, 51405 _setTouchActionForAllDescendants = function _setTouchActionForAllDescendants(elements, value) { 51406 var i = elements.length, 51407 children; 51408 51409 while (i--) { 51410 value ? elements[i].style.touchAction = value : elements[i].style.removeProperty("touch-action"); 51411 children = elements[i].children; 51412 children && children.length && _setTouchActionForAllDescendants(children, value); 51413 } 51414 }, 51415 _renderQueueTick = function _renderQueueTick() { 51416 return _renderQueue.forEach(function (func) { 51417 return func(); 51418 }); 51419 }, 51420 _addToRenderQueue = function _addToRenderQueue(func) { 51421 _renderQueue.push(func); 51422 51423 if (_renderQueue.length === 1) { 51424 gsap.ticker.add(_renderQueueTick); 51425 } 51426 }, 51427 _renderQueueTimeout = function _renderQueueTimeout() { 51428 return !_renderQueue.length && gsap.ticker.remove(_renderQueueTick); 51429 }, 51430 _removeFromRenderQueue = function _removeFromRenderQueue(func) { 51431 var i = _renderQueue.length; 51432 51433 while (i--) { 51434 if (_renderQueue[i] === func) { 51435 _renderQueue.splice(i, 1); 51436 } 51437 } 51438 51439 gsap.to(_renderQueueTimeout, { 51440 overwrite: true, 51441 delay: 15, 51442 duration: 0, 51443 onComplete: _renderQueueTimeout, 51444 data: "_draggable" 51445 }); 51446 }, 51447 _setDefaults = function _setDefaults(obj, defaults) { 51448 for (var p in defaults) { 51449 if (!(p in obj)) { 51450 obj[p] = defaults[p]; 51451 } 51452 } 51453 51454 return obj; 51455 }, 51456 _addListener = function _addListener(element, type, func, capture) { 51457 if (element.addEventListener) { 51458 var touchType = _touchEventLookup[type]; 51459 capture = capture || (_supportsPassive ? { 51460 passive: false 51461 } : null); 51462 element.addEventListener(touchType || type, func, capture); 51463 touchType && type !== touchType && element.addEventListener(type, func, capture); 51464 } 51465 }, 51466 _removeListener = function _removeListener(element, type, func, capture) { 51467 if (element.removeEventListener) { 51468 var touchType = _touchEventLookup[type]; 51469 element.removeEventListener(touchType || type, func, capture); 51470 touchType && type !== touchType && element.removeEventListener(type, func, capture); 51471 } 51472 }, 51473 _preventDefault = function _preventDefault(event) { 51474 event.preventDefault && event.preventDefault(); 51475 event.preventManipulation && event.preventManipulation(); 51476 }, 51477 _hasTouchID = function _hasTouchID(list, ID) { 51478 var i = list.length; 51479 51480 while (i--) { 51481 if (list[i].identifier === ID) { 51482 return true; 51483 } 51484 } 51485 }, 51486 _onMultiTouchDocumentEnd = function _onMultiTouchDocumentEnd(event) { 51487 _isMultiTouching = event.touches && _dragCount < event.touches.length; 51488 51489 _removeListener(event.target, "touchend", _onMultiTouchDocumentEnd); 51490 }, 51491 _onMultiTouchDocument = function _onMultiTouchDocument(event) { 51492 _isMultiTouching = event.touches && _dragCount < event.touches.length; 51493 51494 _addListener(event.target, "touchend", _onMultiTouchDocumentEnd); 51495 }, 51496 _getDocScrollTop$1 = function _getDocScrollTop(doc) { 51497 return _win$1.pageYOffset || doc.scrollTop || doc.documentElement.scrollTop || doc.body.scrollTop || 0; 51498 }, 51499 _getDocScrollLeft$1 = function _getDocScrollLeft(doc) { 51500 return _win$1.pageXOffset || doc.scrollLeft || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0; 51501 }, 51502 _addScrollListener = function _addScrollListener(e, callback) { 51503 _addListener(e, "scroll", callback); 51504 51505 if (!_isRoot(e.parentNode)) { 51506 _addScrollListener(e.parentNode, callback); 51507 } 51508 }, 51509 _removeScrollListener = function _removeScrollListener(e, callback) { 51510 _removeListener(e, "scroll", callback); 51511 51512 if (!_isRoot(e.parentNode)) { 51513 _removeScrollListener(e.parentNode, callback); 51514 } 51515 }, 51516 _isRoot = function _isRoot(e) { 51517 return !!(!e || e === _docElement$1 || e.nodeType === 9 || e === _doc$1.body || e === _win$1 || !e.nodeType || !e.parentNode); 51518 }, 51519 _getMaxScroll = function _getMaxScroll(element, axis) { 51520 var dim = axis === "x" ? "Width" : "Height", 51521 scroll = "scroll" + dim, 51522 client = "client" + dim; 51523 return Math.max(0, _isRoot(element) ? Math.max(_docElement$1[scroll], _body$1[scroll]) - (_win$1["inner" + dim] || _docElement$1[client] || _body$1[client]) : element[scroll] - element[client]); 51524 }, 51525 _recordMaxScrolls = function _recordMaxScrolls(e, skipCurrent) { 51526 var x = _getMaxScroll(e, "x"), 51527 y = _getMaxScroll(e, "y"); 51528 51529 if (_isRoot(e)) { 51530 e = _windowProxy; 51531 } else { 51532 _recordMaxScrolls(e.parentNode, skipCurrent); 51533 } 51534 51535 e._gsMaxScrollX = x; 51536 e._gsMaxScrollY = y; 51537 51538 if (!skipCurrent) { 51539 e._gsScrollX = e.scrollLeft || 0; 51540 e._gsScrollY = e.scrollTop || 0; 51541 } 51542 }, 51543 _setStyle = function _setStyle(element, property, value) { 51544 var style = element.style; 51545 51546 if (!style) { 51547 return; 51548 } 51549 51550 if (_isUndefined(style[property])) { 51551 property = _checkPrefix(property, element) || property; 51552 } 51553 51554 if (value == null) { 51555 style.removeProperty && style.removeProperty(property.replace(/([A-Z])/g, "-$1").toLowerCase()); 51556 } else { 51557 style[property] = value; 51558 } 51559 }, 51560 _getComputedStyle = function _getComputedStyle(element) { 51561 return _win$1.getComputedStyle(element instanceof Element ? element : element.host || (element.parentNode || {}).host || element); 51562 }, 51563 _tempRect = {}, 51564 _parseRect = function _parseRect(e) { 51565 if (e === _win$1) { 51566 _tempRect.left = _tempRect.top = 0; 51567 _tempRect.width = _tempRect.right = _docElement$1.clientWidth || e.innerWidth || _body$1.clientWidth || 0; 51568 _tempRect.height = _tempRect.bottom = (e.innerHeight || 0) - 20 < _docElement$1.clientHeight ? _docElement$1.clientHeight : e.innerHeight || _body$1.clientHeight || 0; 51569 return _tempRect; 51570 } 51571 51572 var doc = e.ownerDocument || _doc$1, 51573 r = !_isUndefined(e.pageX) ? { 51574 left: e.pageX - _getDocScrollLeft$1(doc), 51575 top: e.pageY - _getDocScrollTop$1(doc), 51576 right: e.pageX - _getDocScrollLeft$1(doc) + 1, 51577 bottom: e.pageY - _getDocScrollTop$1(doc) + 1 51578 } : !e.nodeType && !_isUndefined(e.left) && !_isUndefined(e.top) ? e : _toArray(e)[0].getBoundingClientRect(); 51579 51580 if (_isUndefined(r.right) && !_isUndefined(r.width)) { 51581 r.right = r.left + r.width; 51582 r.bottom = r.top + r.height; 51583 } else if (_isUndefined(r.width)) { 51584 r = { 51585 width: r.right - r.left, 51586 height: r.bottom - r.top, 51587 right: r.right, 51588 left: r.left, 51589 bottom: r.bottom, 51590 top: r.top 51591 }; 51592 } 51593 51594 return r; 51595 }, 51596 _dispatchEvent = function _dispatchEvent(target, type, callbackName) { 51597 var vars = target.vars, 51598 callback = vars[callbackName], 51599 listeners = target._listeners[type], 51600 result; 51601 51602 if (_isFunction(callback)) { 51603 result = callback.apply(vars.callbackScope || target, vars[callbackName + "Params"] || [target.pointerEvent]); 51604 } 51605 51606 if (listeners && target.dispatchEvent(type) === false) { 51607 result = false; 51608 } 51609 51610 return result; 51611 }, 51612 _getBounds = function _getBounds(target, context) { 51613 var e = _toArray(target)[0], 51614 top, 51615 left, 51616 offset; 51617 51618 if (!e.nodeType && e !== _win$1) { 51619 if (!_isUndefined(target.left)) { 51620 offset = { 51621 x: 0, 51622 y: 0 51623 }; 51624 return { 51625 left: target.left - offset.x, 51626 top: target.top - offset.y, 51627 width: target.width, 51628 height: target.height 51629 }; 51630 } 51631 51632 left = target.min || target.minX || target.minRotation || 0; 51633 top = target.min || target.minY || 0; 51634 return { 51635 left: left, 51636 top: top, 51637 width: (target.max || target.maxX || target.maxRotation || 0) - left, 51638 height: (target.max || target.maxY || 0) - top 51639 }; 51640 } 51641 51642 return _getElementBounds(e, context); 51643 }, 51644 _point1 = {}, 51645 _getElementBounds = function _getElementBounds(element, context) { 51646 context = _toArray(context)[0]; 51647 var isSVG = element.getBBox && element.ownerSVGElement, 51648 doc = element.ownerDocument || _doc$1, 51649 left, 51650 right, 51651 top, 51652 bottom, 51653 matrix, 51654 p1, 51655 p2, 51656 p3, 51657 p4, 51658 bbox, 51659 width, 51660 height, 51661 cs; 51662 51663 if (element === _win$1) { 51664 top = _getDocScrollTop$1(doc); 51665 left = _getDocScrollLeft$1(doc); 51666 right = left + (doc.documentElement.clientWidth || element.innerWidth || doc.body.clientWidth || 0); 51667 bottom = top + ((element.innerHeight || 0) - 20 < doc.documentElement.clientHeight ? doc.documentElement.clientHeight : element.innerHeight || doc.body.clientHeight || 0); 51668 } else if (context === _win$1 || _isUndefined(context)) { 51669 return element.getBoundingClientRect(); 51670 } else { 51671 left = top = 0; 51672 51673 if (isSVG) { 51674 bbox = element.getBBox(); 51675 width = bbox.width; 51676 height = bbox.height; 51677 } else { 51678 if (element.viewBox && (bbox = element.viewBox.baseVal)) { 51679 left = bbox.x || 0; 51680 top = bbox.y || 0; 51681 width = bbox.width; 51682 height = bbox.height; 51683 } 51684 51685 if (!width) { 51686 cs = _getComputedStyle(element); 51687 bbox = cs.boxSizing === "border-box"; 51688 width = (parseFloat(cs.width) || element.clientWidth || 0) + (bbox ? 0 : parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth)); 51689 height = (parseFloat(cs.height) || element.clientHeight || 0) + (bbox ? 0 : parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth)); 51690 } 51691 } 51692 51693 right = width; 51694 bottom = height; 51695 } 51696 51697 if (element === context) { 51698 return { 51699 left: left, 51700 top: top, 51701 width: right - left, 51702 height: bottom - top 51703 }; 51704 } 51705 51706 matrix = getGlobalMatrix(context, true).multiply(getGlobalMatrix(element)); 51707 p1 = matrix.apply({ 51708 x: left, 51709 y: top 51710 }); 51711 p2 = matrix.apply({ 51712 x: right, 51713 y: top 51714 }); 51715 p3 = matrix.apply({ 51716 x: right, 51717 y: bottom 51718 }); 51719 p4 = matrix.apply({ 51720 x: left, 51721 y: bottom 51722 }); 51723 left = Math.min(p1.x, p2.x, p3.x, p4.x); 51724 top = Math.min(p1.y, p2.y, p3.y, p4.y); 51725 return { 51726 left: left, 51727 top: top, 51728 width: Math.max(p1.x, p2.x, p3.x, p4.x) - left, 51729 height: Math.max(p1.y, p2.y, p3.y, p4.y) - top 51730 }; 51731 }, 51732 _parseInertia = function _parseInertia(draggable, snap, max, min, factor, forceZeroVelocity) { 51733 var vars = {}, 51734 a, 51735 i, 51736 l; 51737 51738 if (snap) { 51739 if (factor !== 1 && snap instanceof Array) { 51740 vars.end = a = []; 51741 l = snap.length; 51742 51743 if (_isObject(snap[0])) { 51744 for (i = 0; i < l; i++) { 51745 a[i] = _copy(snap[i], factor); 51746 } 51747 } else { 51748 for (i = 0; i < l; i++) { 51749 a[i] = snap[i] * factor; 51750 } 51751 } 51752 51753 max += 1.1; 51754 min -= 1.1; 51755 } else if (_isFunction(snap)) { 51756 vars.end = function (value) { 51757 var result = snap.call(draggable, value), 51758 copy, 51759 p; 51760 51761 if (factor !== 1) { 51762 if (_isObject(result)) { 51763 copy = {}; 51764 51765 for (p in result) { 51766 copy[p] = result[p] * factor; 51767 } 51768 51769 result = copy; 51770 } else { 51771 result *= factor; 51772 } 51773 } 51774 51775 return result; 51776 }; 51777 } else { 51778 vars.end = snap; 51779 } 51780 } 51781 51782 if (max || max === 0) { 51783 vars.max = max; 51784 } 51785 51786 if (min || min === 0) { 51787 vars.min = min; 51788 } 51789 51790 if (forceZeroVelocity) { 51791 vars.velocity = 0; 51792 } 51793 51794 return vars; 51795 }, 51796 _isClickable = function _isClickable(element) { 51797 var data; 51798 return !element || !element.getAttribute || element === _body$1 ? false : (data = element.getAttribute("data-clickable")) === "true" || data !== "false" && (_clickableTagExp.test(element.nodeName + "") || element.getAttribute("contentEditable") === "true") ? true : _isClickable(element.parentNode); 51799 }, 51800 _setSelectable = function _setSelectable(elements, selectable) { 51801 var i = elements.length, 51802 e; 51803 51804 while (i--) { 51805 e = elements[i]; 51806 e.ondragstart = e.onselectstart = selectable ? null : _emptyFunc; 51807 gsap.set(e, { 51808 lazy: true, 51809 userSelect: selectable ? "text" : "none" 51810 }); 51811 } 51812 }, 51813 _isFixed$1 = function _isFixed(element) { 51814 if (_getComputedStyle(element).position === "fixed") { 51815 return true; 51816 } 51817 51818 element = element.parentNode; 51819 51820 if (element && element.nodeType === 1) { 51821 return _isFixed(element); 51822 } 51823 }, 51824 _supports3D, 51825 _addPaddingBR, 51826 ScrollProxy = function ScrollProxy(element, vars) { 51827 element = gsap.utils.toArray(element)[0]; 51828 vars = vars || {}; 51829 var content = document.createElement("div"), 51830 style = content.style, 51831 node = element.firstChild, 51832 offsetTop = 0, 51833 offsetLeft = 0, 51834 prevTop = element.scrollTop, 51835 prevLeft = element.scrollLeft, 51836 scrollWidth = element.scrollWidth, 51837 scrollHeight = element.scrollHeight, 51838 extraPadRight = 0, 51839 maxLeft = 0, 51840 maxTop = 0, 51841 elementWidth, 51842 elementHeight, 51843 contentHeight, 51844 nextNode, 51845 transformStart, 51846 transformEnd; 51847 51848 if (_supports3D && vars.force3D !== false) { 51849 transformStart = "translate3d("; 51850 transformEnd = "px,0px)"; 51851 } else if (_transformProp$1) { 51852 transformStart = "translate("; 51853 transformEnd = "px)"; 51854 } 51855 51856 this.scrollTop = function (value, force) { 51857 if (!arguments.length) { 51858 return -this.top(); 51859 } 51860 51861 this.top(-value, force); 51862 }; 51863 51864 this.scrollLeft = function (value, force) { 51865 if (!arguments.length) { 51866 return -this.left(); 51867 } 51868 51869 this.left(-value, force); 51870 }; 51871 51872 this.left = function (value, force) { 51873 if (!arguments.length) { 51874 return -(element.scrollLeft + offsetLeft); 51875 } 51876 51877 var dif = element.scrollLeft - prevLeft, 51878 oldOffset = offsetLeft; 51879 51880 if ((dif > 2 || dif < -2) && !force) { 51881 prevLeft = element.scrollLeft; 51882 gsap.killTweensOf(this, { 51883 left: 1, 51884 scrollLeft: 1 51885 }); 51886 this.left(-prevLeft); 51887 51888 if (vars.onKill) { 51889 vars.onKill(); 51890 } 51891 51892 return; 51893 } 51894 51895 value = -value; 51896 51897 if (value < 0) { 51898 offsetLeft = value - 0.5 | 0; 51899 value = 0; 51900 } else if (value > maxLeft) { 51901 offsetLeft = value - maxLeft | 0; 51902 value = maxLeft; 51903 } else { 51904 offsetLeft = 0; 51905 } 51906 51907 if (offsetLeft || oldOffset) { 51908 if (!this._skip) { 51909 style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd; 51910 } 51911 51912 if (offsetLeft + extraPadRight >= 0) { 51913 style.paddingRight = offsetLeft + extraPadRight + "px"; 51914 } 51915 } 51916 51917 element.scrollLeft = value | 0; 51918 prevLeft = element.scrollLeft; 51919 }; 51920 51921 this.top = function (value, force) { 51922 if (!arguments.length) { 51923 return -(element.scrollTop + offsetTop); 51924 } 51925 51926 var dif = element.scrollTop - prevTop, 51927 oldOffset = offsetTop; 51928 51929 if ((dif > 2 || dif < -2) && !force) { 51930 prevTop = element.scrollTop; 51931 gsap.killTweensOf(this, { 51932 top: 1, 51933 scrollTop: 1 51934 }); 51935 this.top(-prevTop); 51936 51937 if (vars.onKill) { 51938 vars.onKill(); 51939 } 51940 51941 return; 51942 } 51943 51944 value = -value; 51945 51946 if (value < 0) { 51947 offsetTop = value - 0.5 | 0; 51948 value = 0; 51949 } else if (value > maxTop) { 51950 offsetTop = value - maxTop | 0; 51951 value = maxTop; 51952 } else { 51953 offsetTop = 0; 51954 } 51955 51956 if (offsetTop || oldOffset) { 51957 if (!this._skip) { 51958 style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd; 51959 } 51960 } 51961 51962 element.scrollTop = value | 0; 51963 prevTop = element.scrollTop; 51964 }; 51965 51966 this.maxScrollTop = function () { 51967 return maxTop; 51968 }; 51969 51970 this.maxScrollLeft = function () { 51971 return maxLeft; 51972 }; 51973 51974 this.disable = function () { 51975 node = content.firstChild; 51976 51977 while (node) { 51978 nextNode = node.nextSibling; 51979 element.appendChild(node); 51980 node = nextNode; 51981 } 51982 51983 if (element === content.parentNode) { 51984 element.removeChild(content); 51985 } 51986 }; 51987 51988 this.enable = function () { 51989 node = element.firstChild; 51990 51991 if (node === content) { 51992 return; 51993 } 51994 51995 while (node) { 51996 nextNode = node.nextSibling; 51997 content.appendChild(node); 51998 node = nextNode; 51999 } 52000 52001 element.appendChild(content); 52002 this.calibrate(); 52003 }; 52004 52005 this.calibrate = function (force) { 52006 var widthMatches = element.clientWidth === elementWidth, 52007 cs, 52008 x, 52009 y; 52010 prevTop = element.scrollTop; 52011 prevLeft = element.scrollLeft; 52012 52013 if (widthMatches && element.clientHeight === elementHeight && content.offsetHeight === contentHeight && scrollWidth === element.scrollWidth && scrollHeight === element.scrollHeight && !force) { 52014 return; 52015 } 52016 52017 if (offsetTop || offsetLeft) { 52018 x = this.left(); 52019 y = this.top(); 52020 this.left(-element.scrollLeft); 52021 this.top(-element.scrollTop); 52022 } 52023 52024 cs = _getComputedStyle(element); 52025 52026 if (!widthMatches || force) { 52027 style.display = "block"; 52028 style.width = "auto"; 52029 style.paddingRight = "0px"; 52030 extraPadRight = Math.max(0, element.scrollWidth - element.clientWidth); 52031 52032 if (extraPadRight) { 52033 extraPadRight += parseFloat(cs.paddingLeft) + (_addPaddingBR ? parseFloat(cs.paddingRight) : 0); 52034 } 52035 } 52036 52037 style.display = "inline-block"; 52038 style.position = "relative"; 52039 style.overflow = "visible"; 52040 style.verticalAlign = "top"; 52041 style.boxSizing = "content-box"; 52042 style.width = "100%"; 52043 style.paddingRight = extraPadRight + "px"; 52044 52045 if (_addPaddingBR) { 52046 style.paddingBottom = cs.paddingBottom; 52047 } 52048 52049 elementWidth = element.clientWidth; 52050 elementHeight = element.clientHeight; 52051 scrollWidth = element.scrollWidth; 52052 scrollHeight = element.scrollHeight; 52053 maxLeft = element.scrollWidth - elementWidth; 52054 maxTop = element.scrollHeight - elementHeight; 52055 contentHeight = content.offsetHeight; 52056 style.display = "block"; 52057 52058 if (x || y) { 52059 this.left(x); 52060 this.top(y); 52061 } 52062 }; 52063 52064 this.content = content; 52065 this.element = element; 52066 this._skip = false; 52067 this.enable(); 52068 }, 52069 _initCore = function _initCore(required) { 52070 if (_windowExists() && document.body) { 52071 var nav = window && window.navigator; 52072 _win$1 = window; 52073 _doc$1 = document; 52074 _docElement$1 = _doc$1.documentElement; 52075 _body$1 = _doc$1.body; 52076 _tempDiv = _createElement("div"); 52077 _supportsPointer = !!window.PointerEvent; 52078 _placeholderDiv = _createElement("div"); 52079 _placeholderDiv.style.cssText = "visibility:hidden;height:1px;top:-1px;pointer-events:none;position:relative;clear:both;cursor:grab"; 52080 _defaultCursor = _placeholderDiv.style.cursor === "grab" ? "grab" : "move"; 52081 _isAndroid = nav && nav.userAgent.toLowerCase().indexOf("android") !== -1; 52082 _isTouchDevice = "ontouchstart" in _docElement$1 && "orientation" in _win$1 || nav && (nav.MaxTouchPoints > 0 || nav.msMaxTouchPoints > 0); 52083 52084 _addPaddingBR = function () { 52085 var div = _createElement("div"), 52086 child = _createElement("div"), 52087 childStyle = child.style, 52088 parent = _body$1, 52089 val; 52090 52091 childStyle.display = "inline-block"; 52092 childStyle.position = "relative"; 52093 div.style.cssText = "width:90px;height:40px;padding:10px;overflow:auto;visibility:hidden"; 52094 div.appendChild(child); 52095 parent.appendChild(div); 52096 val = child.offsetHeight + 18 > div.scrollHeight; 52097 parent.removeChild(div); 52098 return val; 52099 }(); 52100 52101 _touchEventLookup = function (types) { 52102 var standard = types.split(","), 52103 converted = ("onpointerdown" in _tempDiv ? "pointerdown,pointermove,pointerup,pointercancel" : "onmspointerdown" in _tempDiv ? "MSPointerDown,MSPointerMove,MSPointerUp,MSPointerCancel" : types).split(","), 52104 obj = {}, 52105 i = 4; 52106 52107 while (--i > -1) { 52108 obj[standard[i]] = converted[i]; 52109 obj[converted[i]] = standard[i]; 52110 } 52111 52112 try { 52113 _docElement$1.addEventListener("test", null, Object.defineProperty({}, "passive", { 52114 get: function get() { 52115 _supportsPassive = 1; 52116 } 52117 })); 52118 } catch (e) {} 52119 52120 return obj; 52121 }("touchstart,touchmove,touchend,touchcancel"); 52122 52123 _addListener(_doc$1, "touchcancel", _emptyFunc); 52124 52125 _addListener(_win$1, "touchmove", _emptyFunc); 52126 52127 _body$1 && _body$1.addEventListener("touchstart", _emptyFunc); 52128 52129 _addListener(_doc$1, "contextmenu", function () { 52130 for (var p in _lookup) { 52131 if (_lookup[p].isPressed) { 52132 _lookup[p].endDrag(); 52133 } 52134 } 52135 }); 52136 52137 gsap = _coreInitted = _getGSAP(); 52138 } 52139 52140 if (gsap) { 52141 InertiaPlugin = gsap.plugins.inertia; 52142 52143 _context = gsap.core.context || function () {}; 52144 52145 _checkPrefix = gsap.utils.checkPrefix; 52146 _transformProp$1 = _checkPrefix(_transformProp$1); 52147 _transformOriginProp$1 = _checkPrefix(_transformOriginProp$1); 52148 _toArray = gsap.utils.toArray; 52149 _getStyleSaver = gsap.core.getStyleSaver; 52150 _supports3D = !!_checkPrefix("perspective"); 52151 } else if (required) { 52152 console.warn("Please gsap.registerPlugin(Draggable)"); 52153 } 52154 }; 52155 52156 var EventDispatcher = function () { 52157 function EventDispatcher(target) { 52158 this._listeners = {}; 52159 this.target = target || this; 52160 } 52161 52162 var _proto = EventDispatcher.prototype; 52163 52164 _proto.addEventListener = function addEventListener(type, callback) { 52165 var list = this._listeners[type] || (this._listeners[type] = []); 52166 52167 if (!~list.indexOf(callback)) { 52168 list.push(callback); 52169 } 52170 }; 52171 52172 _proto.removeEventListener = function removeEventListener(type, callback) { 52173 var list = this._listeners[type], 52174 i = list && list.indexOf(callback); 52175 i >= 0 && list.splice(i, 1); 52176 }; 52177 52178 _proto.dispatchEvent = function dispatchEvent(type) { 52179 var _this = this; 52180 52181 var result; 52182 (this._listeners[type] || []).forEach(function (callback) { 52183 return callback.call(_this, { 52184 type: type, 52185 target: _this.target 52186 }) === false && (result = false); 52187 }); 52188 return result; 52189 }; 52190 52191 return EventDispatcher; 52192 }(); 52193 52194 var Draggable = function (_EventDispatcher) { 52195 _inheritsLoose(Draggable, _EventDispatcher); 52196 52197 function Draggable(target, vars) { 52198 var _this2; 52199 52200 _this2 = _EventDispatcher.call(this) || this; 52201 _coreInitted || _initCore(1); 52202 target = _toArray(target)[0]; 52203 _this2.styles = _getStyleSaver && _getStyleSaver(target, "transform,left,top"); 52204 52205 if (!InertiaPlugin) { 52206 InertiaPlugin = gsap.plugins.inertia; 52207 } 52208 52209 _this2.vars = vars = _copy(vars || {}); 52210 _this2.target = target; 52211 _this2.x = _this2.y = _this2.rotation = 0; 52212 _this2.dragResistance = parseFloat(vars.dragResistance) || 0; 52213 _this2.edgeResistance = isNaN(vars.edgeResistance) ? 1 : parseFloat(vars.edgeResistance) || 0; 52214 _this2.lockAxis = vars.lockAxis; 52215 _this2.autoScroll = vars.autoScroll || 0; 52216 _this2.lockedAxis = null; 52217 _this2.allowEventDefault = !!vars.allowEventDefault; 52218 gsap.getProperty(target, "x"); 52219 52220 var type = (vars.type || "x,y").toLowerCase(), 52221 xyMode = ~type.indexOf("x") || ~type.indexOf("y"), 52222 rotationMode = type.indexOf("rotation") !== -1, 52223 xProp = rotationMode ? "rotation" : xyMode ? "x" : "left", 52224 yProp = xyMode ? "y" : "top", 52225 allowX = !!(~type.indexOf("x") || ~type.indexOf("left") || type === "scroll"), 52226 allowY = !!(~type.indexOf("y") || ~type.indexOf("top") || type === "scroll"), 52227 minimumMovement = vars.minimumMovement || 2, 52228 self = _assertThisInitialized(_this2), 52229 triggers = _toArray(vars.trigger || vars.handle || target), 52230 killProps = {}, 52231 dragEndTime = 0, 52232 checkAutoScrollBounds = false, 52233 autoScrollMarginTop = vars.autoScrollMarginTop || 40, 52234 autoScrollMarginRight = vars.autoScrollMarginRight || 40, 52235 autoScrollMarginBottom = vars.autoScrollMarginBottom || 40, 52236 autoScrollMarginLeft = vars.autoScrollMarginLeft || 40, 52237 isClickable = vars.clickableTest || _isClickable, 52238 clickTime = 0, 52239 gsCache = target._gsap || gsap.core.getCache(target), 52240 isFixed = _isFixed$1(target), 52241 getPropAsNum = function getPropAsNum(property, unit) { 52242 return parseFloat(gsCache.get(target, property, unit)); 52243 }, 52244 ownerDoc = target.ownerDocument || _doc$1, 52245 enabled, 52246 scrollProxy, 52247 startPointerX, 52248 startPointerY, 52249 startElementX, 52250 startElementY, 52251 hasBounds, 52252 hasDragCallback, 52253 hasMoveCallback, 52254 maxX, 52255 minX, 52256 maxY, 52257 minY, 52258 touch, 52259 touchID, 52260 rotationOrigin, 52261 dirty, 52262 old, 52263 snapX, 52264 snapY, 52265 snapXY, 52266 isClicking, 52267 touchEventTarget, 52268 matrix, 52269 interrupted, 52270 allowNativeTouchScrolling, 52271 touchDragAxis, 52272 isDispatching, 52273 clickDispatch, 52274 trustedClickDispatch, 52275 isPreventingDefault, 52276 innerMatrix, 52277 dragged, 52278 onContextMenu = function onContextMenu(e) { 52279 _preventDefault(e); 52280 52281 e.stopImmediatePropagation && e.stopImmediatePropagation(); 52282 return false; 52283 }, 52284 render = function render(suppressEvents) { 52285 if (self.autoScroll && self.isDragging && (checkAutoScrollBounds || dirty)) { 52286 var e = target, 52287 autoScrollFactor = self.autoScroll * 15, 52288 parent, 52289 isRoot, 52290 rect, 52291 pointerX, 52292 pointerY, 52293 changeX, 52294 changeY, 52295 gap; 52296 checkAutoScrollBounds = false; 52297 _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop; 52298 _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft; 52299 pointerX = self.pointerX - _windowProxy.scrollLeft; 52300 pointerY = self.pointerY - _windowProxy.scrollTop; 52301 52302 while (e && !isRoot) { 52303 isRoot = _isRoot(e.parentNode); 52304 parent = isRoot ? _windowProxy : e.parentNode; 52305 rect = isRoot ? { 52306 bottom: Math.max(_docElement$1.clientHeight, _win$1.innerHeight || 0), 52307 right: Math.max(_docElement$1.clientWidth, _win$1.innerWidth || 0), 52308 left: 0, 52309 top: 0 52310 } : parent.getBoundingClientRect(); 52311 changeX = changeY = 0; 52312 52313 if (allowY) { 52314 gap = parent._gsMaxScrollY - parent.scrollTop; 52315 52316 if (gap < 0) { 52317 changeY = gap; 52318 } else if (pointerY > rect.bottom - autoScrollMarginBottom && gap) { 52319 checkAutoScrollBounds = true; 52320 changeY = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.bottom - pointerY) / autoScrollMarginBottom) | 0); 52321 } else if (pointerY < rect.top + autoScrollMarginTop && parent.scrollTop) { 52322 checkAutoScrollBounds = true; 52323 changeY = -Math.min(parent.scrollTop, autoScrollFactor * (1 - Math.max(0, pointerY - rect.top) / autoScrollMarginTop) | 0); 52324 } 52325 52326 if (changeY) { 52327 parent.scrollTop += changeY; 52328 } 52329 } 52330 52331 if (allowX) { 52332 gap = parent._gsMaxScrollX - parent.scrollLeft; 52333 52334 if (gap < 0) { 52335 changeX = gap; 52336 } else if (pointerX > rect.right - autoScrollMarginRight && gap) { 52337 checkAutoScrollBounds = true; 52338 changeX = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.right - pointerX) / autoScrollMarginRight) | 0); 52339 } else if (pointerX < rect.left + autoScrollMarginLeft && parent.scrollLeft) { 52340 checkAutoScrollBounds = true; 52341 changeX = -Math.min(parent.scrollLeft, autoScrollFactor * (1 - Math.max(0, pointerX - rect.left) / autoScrollMarginLeft) | 0); 52342 } 52343 52344 if (changeX) { 52345 parent.scrollLeft += changeX; 52346 } 52347 } 52348 52349 if (isRoot && (changeX || changeY)) { 52350 _win$1.scrollTo(parent.scrollLeft, parent.scrollTop); 52351 52352 setPointerPosition(self.pointerX + changeX, self.pointerY + changeY); 52353 } 52354 52355 e = parent; 52356 } 52357 } 52358 52359 if (dirty) { 52360 var x = self.x, 52361 y = self.y; 52362 52363 if (rotationMode) { 52364 self.deltaX = x - parseFloat(gsCache.rotation); 52365 self.rotation = x; 52366 gsCache.rotation = x + "deg"; 52367 gsCache.renderTransform(1, gsCache); 52368 } else { 52369 if (scrollProxy) { 52370 if (allowY) { 52371 self.deltaY = y - scrollProxy.top(); 52372 scrollProxy.top(y); 52373 } 52374 52375 if (allowX) { 52376 self.deltaX = x - scrollProxy.left(); 52377 scrollProxy.left(x); 52378 } 52379 } else if (xyMode) { 52380 if (allowY) { 52381 self.deltaY = y - parseFloat(gsCache.y); 52382 gsCache.y = y + "px"; 52383 } 52384 52385 if (allowX) { 52386 self.deltaX = x - parseFloat(gsCache.x); 52387 gsCache.x = x + "px"; 52388 } 52389 52390 gsCache.renderTransform(1, gsCache); 52391 } else { 52392 if (allowY) { 52393 self.deltaY = y - parseFloat(target.style.top || 0); 52394 target.style.top = y + "px"; 52395 } 52396 52397 if (allowX) { 52398 self.deltaX = x - parseFloat(target.style.left || 0); 52399 target.style.left = x + "px"; 52400 } 52401 } 52402 } 52403 52404 if (hasDragCallback && !suppressEvents && !isDispatching) { 52405 isDispatching = true; 52406 52407 if (_dispatchEvent(self, "drag", "onDrag") === false) { 52408 if (allowX) { 52409 self.x -= self.deltaX; 52410 } 52411 52412 if (allowY) { 52413 self.y -= self.deltaY; 52414 } 52415 52416 render(true); 52417 } 52418 52419 isDispatching = false; 52420 } 52421 } 52422 52423 dirty = false; 52424 }, 52425 syncXY = function syncXY(skipOnUpdate, skipSnap) { 52426 var x = self.x, 52427 y = self.y, 52428 snappedValue, 52429 cs; 52430 52431 if (!target._gsap) { 52432 gsCache = gsap.core.getCache(target); 52433 } 52434 52435 gsCache.uncache && gsap.getProperty(target, "x"); 52436 52437 if (xyMode) { 52438 self.x = parseFloat(gsCache.x); 52439 self.y = parseFloat(gsCache.y); 52440 } else if (rotationMode) { 52441 self.x = self.rotation =
52441parseFloat(gsCache.rotation
vendor: 18,327 bytes, lines 52441-52991
52441); 52442 } else if (scrollProxy) { 52443 self.y = scrollProxy.top(); 52444 self.x = scrollProxy.left(); 52445 } else { 52446 self.y = parseFloat(target.style.top || (cs = _getComputedStyle(target)) && cs.top) || 0; 52447 self.x = parseFloat(target.style.left || (cs || {}).left) || 0; 52448 } 52449 52450 if ((snapX || snapY || snapXY) && !skipSnap && (self.isDragging || self.isThrowing)) { 52451 if (snapXY) { 52452 _temp1.x = self.x; 52453 _temp1.y = self.y; 52454 snappedValue = snapXY(_temp1); 52455 52456 if (snappedValue.x !== self.x) { 52457 self.x = snappedValue.x; 52458 dirty = true; 52459 } 52460 52461 if (snappedValue.y !== self.y) { 52462 self.y = snappedValue.y; 52463 dirty = true; 52464 } 52465 } 52466 52467 if (snapX) { 52468 snappedValue = snapX(self.x); 52469 52470 if (snappedValue !== self.x) { 52471 self.x = snappedValue; 52472 52473 if (rotationMode) { 52474 self.rotation = snappedValue; 52475 } 52476 52477 dirty = true; 52478 } 52479 } 52480 52481 if (snapY) { 52482 snappedValue = snapY(self.y); 52483 52484 if (snappedValue !== self.y) { 52485 self.y = snappedValue; 52486 } 52487 52488 dirty = true; 52489 } 52490 } 52491 52492 dirty && render(true); 52493 52494 if (!skipOnUpdate) { 52495 self.deltaX = self.x - x; 52496 self.deltaY = self.y - y; 52497 52498 _dispatchEvent(self, "throwupdate", "onThrowUpdate"); 52499 } 52500 }, 52501 buildSnapFunc = function buildSnapFunc(snap, min, max, factor) { 52502 if (min == null) { 52503 min = -_bigNum; 52504 } 52505 52506 if (max == null) { 52507 max = _bigNum; 52508 } 52509 52510 if (_isFunction(snap)) { 52511 return function (n) { 52512 var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance; 52513 return snap.call(self, (n > max ? max + (n - max) * edgeTolerance : n < min ? min + (n - min) * edgeTolerance : n) * factor) * factor; 52514 }; 52515 } 52516 52517 if (_isArray(snap)) { 52518 return function (n) { 52519 var i = snap.length, 52520 closest = 0, 52521 absDif = _bigNum, 52522 val, 52523 dif; 52524 52525 while (--i > -1) { 52526 val = snap[i]; 52527 dif = val - n; 52528 52529 if (dif < 0) { 52530 dif = -dif; 52531 } 52532 52533 if (dif < absDif && val >= min && val <= max) { 52534 closest = i; 52535 absDif = dif; 52536 } 52537 } 52538 52539 return snap[closest]; 52540 }; 52541 } 52542 52543 return isNaN(snap) ? function (n) { 52544 return n; 52545 } : function () { 52546 return snap * factor; 52547 }; 52548 }, 52549 buildPointSnapFunc = function buildPointSnapFunc(snap, minX, maxX, minY, maxY, radius, factor) { 52550 radius = radius && radius < _bigNum ? radius * radius : _bigNum; 52551 52552 if (_isFunction(snap)) { 52553 return function (point) { 52554 var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance, 52555 x = point.x, 52556 y = point.y, 52557 result, 52558 dx, 52559 dy; 52560 point.x = x = x > maxX ? maxX + (x - maxX) * edgeTolerance : x < minX ? minX + (x - minX) * edgeTolerance : x; 52561 point.y = y = y > maxY ? maxY + (y - maxY) * edgeTolerance : y < minY ? minY + (y - minY) * edgeTolerance : y; 52562 result = snap.call(self, point); 52563 52564 if (result !== point) { 52565 point.x = result.x; 52566 point.y = result.y; 52567 } 52568 52569 if (factor !== 1) { 52570 point.x *= factor; 52571 point.y *= factor; 52572 } 52573 52574 if (radius < _bigNum) { 52575 dx = point.x - x; 52576 dy = point.y - y; 52577 52578 if (dx * dx + dy * dy > radius) { 52579 point.x = x; 52580 point.y = y; 52581 } 52582 } 52583 52584 return point; 52585 }; 52586 } 52587 52588 if (_isArray(snap)) { 52589 return function (p) { 52590 var i = snap.length, 52591 closest = 0, 52592 minDist = _bigNum, 52593 x, 52594 y, 52595 point, 52596 dist; 52597 52598 while (--i > -1) { 52599 point = snap[i]; 52600 x = point.x - p.x; 52601 y = point.y - p.y; 52602 dist = x * x + y * y; 52603 52604 if (dist < minDist) { 52605 closest = i; 52606 minDist = dist; 52607 } 52608 } 52609 52610 return minDist <= radius ? snap[closest] : p; 52611 }; 52612 } 52613 52614 return function (n) { 52615 return n; 52616 }; 52617 }, 52618 calculateBounds = function calculateBounds() { 52619 var bounds, targetBounds, snap, snapIsRaw; 52620 hasBounds = false; 52621 52622 if (scrollProxy) { 52623 scrollProxy.calibrate(); 52624 self.minX = minX = -scrollProxy.maxScrollLeft(); 52625 self.minY = minY = -scrollProxy.maxScrollTop(); 52626 self.maxX = maxX = self.maxY = maxY = 0; 52627 hasBounds = true; 52628 } else if (!!vars.bounds) { 52629 bounds = _getBounds(vars.bounds, target.parentNode); 52630 52631 if (rotationMode) { 52632 self.minX = minX = bounds.left; 52633 self.maxX = maxX = bounds.left + bounds.width; 52634 self.minY = minY = self.maxY = maxY = 0; 52635 } else if (!_isUndefined(vars.bounds.maxX) || !_isUndefined(vars.bounds.maxY)) { 52636 bounds = vars.bounds; 52637 self.minX = minX = bounds.minX; 52638 self.minY = minY = bounds.minY; 52639 self.maxX = maxX = bounds.maxX; 52640 self.maxY = maxY = bounds.maxY; 52641 } else { 52642 targetBounds = _getBounds(target, target.parentNode); 52643 self.minX = minX = Math.round(getPropAsNum(xProp, "px") + bounds.left - targetBounds.left); 52644 self.minY = minY = Math.round(getPropAsNum(yProp, "px") + bounds.top - targetBounds.top); 52645 self.maxX = maxX = Math.round(minX + (bounds.width - targetBounds.width)); 52646 self.maxY = maxY = Math.round(minY + (bounds.height - targetBounds.height)); 52647 } 52648 52649 if (minX > maxX) { 52650 self.minX = maxX; 52651 self.maxX = maxX = minX; 52652 minX = self.minX; 52653 } 52654 52655 if (minY > maxY) { 52656 self.minY = maxY; 52657 self.maxY = maxY = minY; 52658 minY = self.minY; 52659 } 52660 52661 if (rotationMode) { 52662 self.minRotation = minX; 52663 self.maxRotation = maxX; 52664 } 52665 52666 hasBounds = true; 52667 } 52668 52669 if (vars.liveSnap) { 52670 snap = vars.liveSnap === true ? vars.snap || {} : vars.liveSnap; 52671 snapIsRaw = _isArray(snap) || _isFunction(snap); 52672 52673 if (rotationMode) { 52674 snapX = buildSnapFunc(snapIsRaw ? snap : snap.rotation, minX, maxX, 1); 52675 snapY = null; 52676 } else { 52677 if (snap.points) { 52678 snapXY = buildPointSnapFunc(snapIsRaw ? snap : snap.points, minX, maxX, minY, maxY, snap.radius, scrollProxy ? -1 : 1); 52679 } else { 52680 if (allowX) { 52681 snapX = buildSnapFunc(snapIsRaw ? snap : snap.x || snap.left || snap.scrollLeft, minX, maxX, scrollProxy ? -1 : 1); 52682 } 52683 52684 if (allowY) { 52685 snapY = buildSnapFunc(snapIsRaw ? snap : snap.y || snap.top || snap.scrollTop, minY, maxY, scrollProxy ? -1 : 1); 52686 } 52687 } 52688 } 52689 } 52690 }, 52691 onThrowComplete = function onThrowComplete() { 52692 self.isThrowing = false; 52693 52694 _dispatchEvent(self, "throwcomplete", "onThrowComplete"); 52695 }, 52696 onThrowInterrupt = function onThrowInterrupt() { 52697 self.isThrowing = false; 52698 }, 52699 animate = function animate(inertia, forceZeroVelocity) { 52700 var snap, snapIsRaw, tween, overshootTolerance; 52701 52702 if (inertia && InertiaPlugin) { 52703 if (inertia === true) { 52704 snap = vars.snap || vars.liveSnap || {}; 52705 snapIsRaw = _isArray(snap) || _isFunction(snap); 52706 inertia = { 52707 resistance: (vars.throwResistance || vars.resistance || 1000) / (rotationMode ? 10 : 1) 52708 }; 52709 52710 if (rotationMode) { 52711 inertia.rotation = _parseInertia(self, snapIsRaw ? snap : snap.rotation, maxX, minX, 1, forceZeroVelocity); 52712 } else { 52713 if (allowX) { 52714 inertia[xProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.x || snap.left, maxX, minX, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "x"); 52715 } 52716 52717 if (allowY) { 52718 inertia[yProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.y || snap.top, maxY, minY, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "y"); 52719 } 52720 52721 if (snap.points || _isArray(snap) && _isObject(snap[0])) { 52722 inertia.linkedProps = xProp + "," + yProp; 52723 inertia.radius = snap.radius; 52724 } 52725 } 52726 } 52727 52728 self.isThrowing = true; 52729 overshootTolerance = !isNaN(vars.overshootTolerance) ? vars.overshootTolerance : vars.edgeResistance === 1 ? 0 : 1 - self.edgeResistance + 0.2; 52730 52731 if (!inertia.duration) { 52732 inertia.duration = { 52733 max: Math.max(vars.minDuration || 0, "maxDuration" in vars ? vars.maxDuration : 2), 52734 min: !isNaN(vars.minDuration) ? vars.minDuration : overshootTolerance === 0 || _isObject(inertia) && inertia.resistance > 1000 ? 0 : 0.5, 52735 overshoot: overshootTolerance 52736 }; 52737 } 52738 52739 self.tween = tween = gsap.to(scrollProxy || target, { 52740 inertia: inertia, 52741 data: "_draggable", 52742 inherit: false, 52743 onComplete: onThrowComplete, 52744 onInterrupt: onThrowInterrupt, 52745 onUpdate: vars.fastMode ? _dispatchEvent : syncXY, 52746 onUpdateParams: vars.fastMode ? [self, "onthrowupdate", "onThrowUpdate"] : snap && snap.radius ? [false, true] : [] 52747 }); 52748 52749 if (!vars.fastMode) { 52750 if (scrollProxy) { 52751 scrollProxy._skip = true; 52752 } 52753 52754 tween.render(1e9, true, true); 52755 syncXY(true, true); 52756 self.endX = self.x; 52757 self.endY = self.y; 52758 52759 if (rotationMode) { 52760 self.endRotation = self.x; 52761 } 52762 52763 tween.play(0); 52764 syncXY(true, true); 52765 52766 if (scrollProxy) { 52767 scrollProxy._skip = false; 52768 } 52769 } 52770 } else if (hasBounds) { 52771 self.applyBounds(); 52772 } 52773 }, 52774 updateMatrix = function updateMatrix(shiftStart) { 52775 var start = matrix, 52776 p; 52777 matrix = getGlobalMatrix(target.parentNode, true); 52778 52779 if (shiftStart && self.isPressed && !matrix.equals(start || new Matrix2D())) { 52780 p = start.inverse().apply({ 52781 x: startPointerX, 52782 y: startPointerY 52783 }); 52784 matrix.apply(p, p); 52785 startPointerX = p.x; 52786 startPointerY = p.y; 52787 } 52788 52789 if (matrix.equals(_identityMatrix$1)) { 52790 matrix = null; 52791 } 52792 }, 52793 recordStartPositions = function recordStartPositions() { 52794 var edgeTolerance = 1 - self.edgeResistance, 52795 offsetX = isFixed ? _getDocScrollLeft$1(ownerDoc) : 0, 52796 offsetY = isFixed ? _getDocScrollTop$1(ownerDoc) : 0, 52797 parsedOrigin, 52798 x, 52799 y; 52800 52801 if (xyMode) { 52802 gsCache.x = getPropAsNum(xProp, "px") + "px"; 52803 gsCache.y = getPropAsNum(yProp, "px") + "px"; 52804 gsCache.renderTransform(); 52805 } 52806 52807 updateMatrix(false); 52808 _point1.x = self.pointerX - offsetX; 52809 _point1.y = self.pointerY - offsetY; 52810 matrix && matrix.apply(_point1, _point1); 52811 startPointerX = _point1.x; 52812 startPointerY = _point1.y; 52813 52814 if (dirty) { 52815 setPointerPosition(self.pointerX, self.pointerY); 52816 render(true); 52817 } 52818 52819 innerMatrix = getGlobalMatrix(target); 52820 52821 if (scrollProxy) { 52822 calculateBounds(); 52823 startElementY = scrollProxy.top(); 52824 startElementX = scrollProxy.left(); 52825 } else { 52826 if (isTweening()) { 52827 syncXY(true, true); 52828 calculateBounds(); 52829 } else { 52830 self.applyBounds(); 52831 } 52832 52833 if (rotationMode) { 52834 parsedOrigin = target.ownerSVGElement ? [gsCache.xOrigin - target.getBBox().x, gsCache.yOrigin - target.getBBox().y] : (_getComputedStyle(target)[_transformOriginProp$1] || "0 0").split(" "); 52835 rotationOrigin = self.rotationOrigin = getGlobalMatrix(target).apply({ 52836 x: parseFloat(parsedOrigin[0]) || 0, 52837 y: parseFloat(parsedOrigin[1]) || 0 52838 }); 52839 syncXY(true, true); 52840 x = self.pointerX - rotationOrigin.x - offsetX; 52841 y = rotationOrigin.y - self.pointerY + offsetY; 52842 startElementX = self.x; 52843 startElementY = self.y = Math.atan2(y, x) * _RAD2DEG; 52844 } else { 52845 startElementY = getPropAsNum(yProp, "px"); 52846 startElementX = getPropAsNum(xProp, "px"); 52847 } 52848 } 52849 52850 if (hasBounds && edgeTolerance) { 52851 if (startElementX > maxX) { 52852 startElementX = maxX + (startElementX - maxX) / edgeTolerance; 52853 } else if (startElementX < minX) { 52854 startElementX = minX - (minX - startElementX) / edgeTolerance; 52855 } 52856 52857 if (!rotationMode) { 52858 if (startElementY > maxY) { 52859 startElementY = maxY + (startElementY - maxY) / edgeTolerance; 52860 } else if (startElementY < minY) { 52861 startElementY = minY - (minY - startElementY) / edgeTolerance; 52862 } 52863 } 52864 } 52865 52866 self.startX = startElementX = _round(startElementX); 52867 self.startY = startElementY = _round(startElementY); 52868 }, 52869 isTweening = function isTweening() { 52870 return self.tween && self.tween.isActive(); 52871 }, 52872 removePlaceholder = function removePlaceholder() { 52873 if (_placeholderDiv.parentNode && !isTweening() && !self.isDragging) { 52874 _placeholderDiv.parentNode.removeChild(_placeholderDiv); 52875 } 52876 }, 52877 onPress = function onPress(e, force) { 52878 var i; 52879 52880 if (!enabled || self.isPressed || !e || (e.type === "mousedown" || e.type === "pointerdown") && !force && _getTime() - clickTime < 30 && _touchEventLookup[self.pointerEvent.type]) { 52881 isPreventingDefault && e && enabled && _preventDefault(e); 52882 return; 52883 } 52884 52885 interrupted = isTweening(); 52886 dragged = false; 52887 self.pointerEvent = e; 52888 52889 if (_touchEventLookup[e.type]) { 52890 touchEventTarget = ~e.type.indexOf("touch") ? e.currentTarget || e.target : ownerDoc; 52891 52892 _addListener(touchEventTarget, "touchend", onRelease); 52893 52894 _addListener(touchEventTarget, "touchmove", onMove); 52895 52896 _addListener(touchEventTarget, "touchcancel", onRelease); 52897 52898 _addListener(ownerDoc, "touchstart", _onMultiTouchDocument); 52899 } else { 52900 touchEventTarget = null; 52901 52902 _addListener(ownerDoc, "mousemove", onMove); 52903 } 52904 52905 touchDragAxis = null; 52906 52907 if (!_supportsPointer || !touchEventTarget) { 52908 _addListener(ownerDoc, "mouseup", onRelease); 52909 52910 e && e.target && _addListener(e.target, "mouseup", onRelease); 52911 } 52912 52913 isClicking = isClickable.call(self, e.target) && vars.dragClickables === false && !force; 52914 52915 if (isClicking) { 52916 _addListener(e.target, "change", onRelease); 52917 52918 _dispatchEvent(self, "pressInit", "onPressInit"); 52919 52920 _dispatchEvent(self, "press", "onPress"); 52921 52922 _setSelectable(triggers, true); 52923 52924 isPreventingDefault = false; 52925 return; 52926 } 52927 52928 allowNativeTouchScrolling = !touchEventTarget || allowX === allowY || self.vars.allowNativeTouchScrolling === false || self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2) ? false : allowX ? "y" : "x"; 52929 isPreventingDefault = !allowNativeTouchScrolling && !self.allowEventDefault; 52930 52931 if (isPreventingDefault) { 52932 _preventDefault(e); 52933 52934 _addListener(_win$1, "touchforcechange", _preventDefault); 52935 } 52936 52937 if (e.changedTouches) { 52938 e = touch = e.changedTouches[0]; 52939 touchID = e.identifier; 52940 } else if (e.pointerId) { 52941 touchID = e.pointerId; 52942 } else { 52943 touch = touchID = null; 52944 } 52945 52946 _dragCount++; 52947 52948 _addToRenderQueue(render); 52949 52950 startPointerY = self.pointerY = e.pageY; 52951 startPointerX = self.pointerX = e.pageX; 52952 52953 _dispatchEvent(self, "pressInit", "onPressInit"); 52954 52955 if (allowNativeTouchScrolling || self.autoScroll) { 52956 _recordMaxScrolls(target.parentNode); 52957 } 52958 52959 if (target.parentNode && self.autoScroll && !scrollProxy && !rotationMode && target.parentNode._gsMaxScrollX && !_placeholderDiv.parentNode && !target.getBBox) { 52960 _placeholderDiv.style.width = target.parentNode.scrollWidth + "px"; 52961 target.parentNode.appendChild(_placeholderDiv); 52962 } 52963 52964 recordStartPositions(); 52965 self.tween && self.tween.kill(); 52966 self.isThrowing = false; 52967 gsap.killTweensOf(scrollProxy || target, killProps, true); 52968 scrollProxy && gsap.killTweensOf(target, { 52969 scrollTo: 1 52970 }, true); 52971 self.tween = self.lockedAxis = null; 52972 52973 if (vars.zIndexBoost || !rotationMode && !scrollProxy && vars.zIndexBoost !== false) { 52974 target.style.zIndex = Draggable.zIndex++; 52975 } 52976 52977 self.isPressed = true; 52978 hasDragCallback = !!(vars.onDrag || self._listeners.drag); 52979 hasMoveCallback = !!(vars.onMove || self._listeners.move); 52980 52981 if (vars.cursor !== false || vars.activeCursor) { 52982 i = triggers.length; 52983 52984 while (--i > -1) { 52985 gsap.set(triggers[i], { 52986 cursor: vars.activeCursor || vars.cursor || (_defaultCursor === "grab" ? "grabbing" : _defaultCursor) 52987 }); 52988 } 52989 } 52990 52991 _dispatchEvent(self, "press", "onPress");
vendor: 2,447 bytes, lines 52992-53059
52992 }, 52993 onMove = function onMove(e) { 52994 var originalEvent = e, 52995 touches, 52996 pointerX, 52997 pointerY, 52998 i, 52999 dx, 53000 dy; 53001 53002 if (!enabled || _isMultiTouching || !self.isPressed || !e) { 53003 isPreventingDefault && e && enabled && _preventDefault(e); 53004 return; 53005 } 53006 53007 self.pointerEvent = e; 53008 touches = e.changedTouches; 53009 53010 if (touches) { 53011 e = touches[0]; 53012 53013 if (e !== touch && e.identifier !== touchID) { 53014 i = touches.length; 53015 53016 while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {} 53017 53018 if (i < 0) { 53019 return; 53020 } 53021 } 53022 } else if (e.pointerId && touchID && e.pointerId !== touchID) { 53023 return; 53024 } 53025 53026 if (touchEventTarget && allowNativeTouchScrolling && !touchDragAxis) { 53027 _point1.x = e.pageX - (isFixed ? _getDocScrollLeft$1(ownerDoc) : 0); 53028 _point1.y = e.pageY - (isFixed ? _getDocScrollTop$1(ownerDoc) : 0); 53029 matrix && matrix.apply(_point1, _point1); 53030 pointerX = _point1.x; 53031 pointerY = _point1.y; 53032 dx = Math.abs(pointerX - startPointerX); 53033 dy = Math.abs(pointerY - startPointerY); 53034 53035 if (dx !== dy && (dx > minimumMovement || dy > minimumMovement) || _isAndroid && allowNativeTouchScrolling === touchDragAxis) { 53036 touchDragAxis = dx > dy && allowX ? "x" : "y"; 53037 53038 if (allowNativeTouchScrolling && touchDragAxis !== allowNativeTouchScrolling) { 53039 _addListener(_win$1, "touchforcechange", _preventDefault); 53040 } 53041 53042 if (self.vars.lockAxisOnTouchScroll !== false && allowX && allowY) { 53043 self.lockedAxis = touchDragAxis === "x" ? "y" : "x"; 53044 _isFunction(self.vars.onLockAxis) && self.vars.onLockAxis.call(self, originalEvent); 53045 } 53046 53047 if (_isAndroid && allowNativeTouchScrolling === touchDragAxis) { 53048 onRelease(originalEvent); 53049 return; 53050 } 53051 } 53052 } 53053 53054 if (!self.allowEventDefault && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling !== touchDragAxis) && originalEvent.cancelable !== false) { 53055 _preventDefault(originalEvent); 53056 53057 isPreventingDefault = true; 53058 } else if (isPreventingDefault) { 53059 isPreventingDefault = false;
vendor: 3,917 bytes, lines 53060-53188
53060 } 53061 53062 if (self.autoScroll) { 53063 checkAutoScrollBounds = true; 53064 } 53065 53066 setPointerPosition(e.pageX, e.pageY, hasMoveCallback); 53067 }, 53068 setPointerPosition = function setPointerPosition(pointerX, pointerY, invokeOnMove) { 53069 var dragTolerance = 1 - self.dragResistance, 53070 edgeTolerance = 1 - self.edgeResistance, 53071 prevPointerX = self.pointerX, 53072 prevPointerY = self.pointerY, 53073 prevStartElementY = startElementY, 53074 prevX = self.x, 53075 prevY = self.y, 53076 prevEndX = self.endX, 53077 prevEndY = self.endY, 53078 prevEndRotation = self.endRotation, 53079 prevDirty = dirty, 53080 xChange, 53081 yChange, 53082 x, 53083 y, 53084 dif, 53085 temp; 53086 self.pointerX = pointerX; 53087 self.pointerY = pointerY; 53088 53089 if (isFixed) { 53090 pointerX -= _getDocScrollLeft$1(ownerDoc); 53091 pointerY -= _getDocScrollTop$1(ownerDoc); 53092 } 53093 53094 if (rotationMode) { 53095 y = Math.atan2(rotationOrigin.y - pointerY, pointerX - rotationOrigin.x) * _RAD2DEG; 53096 dif = self.y - y; 53097 53098 if (dif > 180) { 53099 startElementY -= 360; 53100 self.y = y; 53101 } else if (dif < -180) { 53102 startElementY += 360; 53103 self.y = y; 53104 } 53105 53106 if (self.x !== startElementX || Math.abs(startElementY - y) > minimumMovement) { 53107 self.y = y; 53108 x = startElementX + (startElementY - y) * dragTolerance; 53109 } else { 53110 x = startElementX; 53111 } 53112 } else { 53113 if (matrix) { 53114 temp = pointerX * matrix.a + pointerY * matrix.c + matrix.e; 53115 pointerY = pointerX * matrix.b + pointerY * matrix.d + matrix.f; 53116 pointerX = temp; 53117 } 53118 53119 yChange = pointerY - startPointerY; 53120 xChange = pointerX - startPointerX; 53121 53122 if (yChange < minimumMovement && yChange > -minimumMovement) { 53123 yChange = 0; 53124 } 53125 53126 if (xChange < minimumMovement && xChange > -minimumMovement) { 53127 xChange = 0; 53128 } 53129 53130 if ((self.lockAxis || self.lockedAxis) && (xChange || yChange)) { 53131 temp = self.lockedAxis; 53132 53133 if (!temp) { 53134 self.lockedAxis = temp = allowX && Math.abs(xChange) > Math.abs(yChange) ? "y" : allowY ? "x" : null; 53135 53136 if (temp && _isFunction(self.vars.onLockAxis)) { 53137 self.vars.onLockAxis.call(self, self.pointerEvent); 53138 } 53139 } 53140 53141 if (temp === "y") { 53142 yChange = 0; 53143 } else if (temp === "x") { 53144 xChange = 0; 53145 } 53146 } 53147 53148 x = _round(startElementX + xChange * dragTolerance); 53149 y = _round(startElementY + yChange * dragTolerance); 53150 } 53151 53152 if ((snapX || snapY || snapXY) && (self.x !== x || self.y !== y && !rotationMode)) { 53153 if (snapXY) { 53154 _temp1.x = x; 53155 _temp1.y = y; 53156 temp = snapXY(_temp1); 53157 x = _round(temp.x); 53158 y = _round(temp.y); 53159 } 53160 53161 if (snapX) { 53162 x = _round(snapX(x)); 53163 } 53164 53165 if (snapY) { 53166 y = _round(snapY(y)); 53167 } 53168 } 53169 53170 if (hasBounds) { 53171 if (x > maxX) { 53172 x = maxX + Math.round((x - maxX) * edgeTolerance); 53173 } else if (x < minX) { 53174 x = minX + Math.round((x - minX) * edgeTolerance); 53175 } 53176 53177 if (!rotationMode) { 53178 if (y > maxY) { 53179 y = Math.round(maxY + (y - maxY) * edgeTolerance); 53180 } else if (y < minY) { 53181 y = Math.round(minY + (y - minY) * edgeTolerance); 53182 } 53183 } 53184 } 53185 53186 if (self.x !== x || self.y !== y && !rotationMode) { 53187 if (rotationMode) { 53188 self.endRotation = self.x = self.endX = x
vendor: 13,666 bytes, lines 53188-53595
53188; 53189 dirty = true; 53190 } else { 53191 if (allowY) { 53192 self.y = self.endY = y; 53193 dirty = true; 53194 } 53195 53196 if (allowX) { 53197 self.x = self.endX = x; 53198 dirty = true; 53199 } 53200 } 53201 53202 if (!invokeOnMove || _dispatchEvent(self, "move", "onMove") !== false) { 53203 if (!self.isDragging && self.isPressed) { 53204 self.isDragging = dragged = true; 53205 53206 _dispatchEvent(self, "dragstart", "onDragStart"); 53207 } 53208 } else { 53209 self.pointerX = prevPointerX; 53210 self.pointerY = prevPointerY; 53211 startElementY = prevStartElementY; 53212 self.x = prevX; 53213 self.y = prevY; 53214 self.endX = prevEndX; 53215 self.endY = prevEndY; 53216 self.endRotation = prevEndRotation; 53217 dirty = prevDirty; 53218 } 53219 } 53220 }, 53221 onRelease = function onRelease(e, force) { 53222 if (!enabled || !self.isPressed || e && touchID != null && !force && (e.pointerId && e.pointerId !== touchID && e.target !== target || e.changedTouches && !_hasTouchID(e.changedTouches, touchID))) { 53223 isPreventingDefault && e && enabled && _preventDefault(e); 53224 return; 53225 } 53226 53227 self.isPressed = false; 53228 var originalEvent = e, 53229 wasDragging = self.isDragging, 53230 isContextMenuRelease = self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2), 53231 placeholderDelayedCall = gsap.delayedCall(0.001, removePlaceholder), 53232 touches, 53233 i, 53234 syntheticEvent, 53235 eventTarget, 53236 syntheticClick; 53237 53238 if (touchEventTarget) { 53239 _removeListener(touchEventTarget, "touchend", onRelease); 53240 53241 _removeListener(touchEventTarget, "touchmove", onMove); 53242 53243 _removeListener(touchEventTarget, "touchcancel", onRelease); 53244 53245 _removeListener(ownerDoc, "touchstart", _onMultiTouchDocument); 53246 } else { 53247 _removeListener(ownerDoc, "mousemove", onMove); 53248 } 53249 53250 _removeListener(_win$1, "touchforcechange", _preventDefault); 53251 53252 if (!_supportsPointer || !touchEventTarget) { 53253 _removeListener(ownerDoc, "mouseup", onRelease); 53254 53255 e && e.target && _removeListener(e.target, "mouseup", onRelease); 53256 } 53257 53258 dirty = false; 53259 53260 if (wasDragging) { 53261 dragEndTime = _lastDragTime = _getTime(); 53262 self.isDragging = false; 53263 } 53264 53265 _removeFromRenderQueue(render); 53266 53267 if (isClicking && !isContextMenuRelease) { 53268 if (e) { 53269 _removeListener(e.target, "change", onRelease); 53270 53271 self.pointerEvent = originalEvent; 53272 } 53273 53274 _setSelectable(triggers, false); 53275 53276 _dispatchEvent(self, "release", "onRelease"); 53277 53278 _dispatchEvent(self, "click", "onClick"); 53279 53280 isClicking = false; 53281 return; 53282 } 53283 53284 i = triggers.length; 53285 53286 while (--i > -1) { 53287 _setStyle(triggers[i], "cursor", vars.cursor || (vars.cursor !== false ? _defaultCursor : null)); 53288 } 53289 53290 _dragCount--; 53291 53292 if (e) { 53293 touches = e.changedTouches; 53294 53295 if (touches) { 53296 e = touches[0]; 53297 53298 if (e !== touch && e.identifier !== touchID) { 53299 i = touches.length; 53300 53301 while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {} 53302 53303 if (i < 0 && !force) { 53304 return; 53305 } 53306 } 53307 } 53308 53309 self.pointerEvent = originalEvent; 53310 self.pointerX = e.pageX; 53311 self.pointerY = e.pageY; 53312 } 53313 53314 if (isContextMenuRelease && originalEvent) { 53315 _preventDefault(originalEvent); 53316 53317 isPreventingDefault = true; 53318 53319 _dispatchEvent(self, "release", "onRelease"); 53320 } else if (originalEvent && !wasDragging) { 53321 isPreventingDefault = false; 53322 53323 if (interrupted && (vars.snap || vars.bounds)) { 53324 animate(vars.inertia || vars.throwProps); 53325 } 53326 53327 _dispatchEvent(self, "release", "onRelease"); 53328 53329 if ((!_isAndroid || originalEvent.type !== "touchmove") && originalEvent.type.indexOf("cancel") === -1) { 53330 _dispatchEvent(self, "click", "onClick"); 53331 53332 if (_getTime() - clickTime < 300) { 53333 _dispatchEvent(self, "doubleclick", "onDoubleClick"); 53334 } 53335 53336 eventTarget = originalEvent.target || target; 53337 clickTime = _getTime(); 53338 53339 syntheticClick = function syntheticClick() { 53340 if (clickTime !== clickDispatch && self.enabled() && !self.isPressed && !originalEvent.defaultPrevented) { 53341 if (eventTarget.click) { 53342 eventTarget.click(); 53343 } else if (ownerDoc.createEvent) { 53344 syntheticEvent = ownerDoc.createEvent("MouseEvents"); 53345 syntheticEvent.initMouseEvent("click", true, true, _win$1, 1, self.pointerEvent.screenX, self.pointerEvent.screenY, self.pointerX, self.pointerY, false, false, false, false, 0, null); 53346 eventTarget.dispatchEvent(syntheticEvent); 53347 } 53348 } 53349 }; 53350 53351 if (!_isAndroid && !originalEvent.defaultPrevented) { 53352 gsap.delayedCall(0.05, syntheticClick); 53353 } 53354 } 53355 } else { 53356 animate(vars.inertia || vars.throwProps); 53357 53358 if (!self.allowEventDefault && originalEvent && (vars.dragClickables !== false || !isClickable.call(self, originalEvent.target)) && wasDragging && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling === touchDragAxis) && originalEvent.cancelable !== false) { 53359 isPreventingDefault = true; 53360 53361 _preventDefault(originalEvent); 53362 } else { 53363 isPreventingDefault = false; 53364 } 53365 53366 _dispatchEvent(self, "release", "onRelease"); 53367 } 53368 53369 isTweening() && placeholderDelayedCall.duration(self.tween.duration()); 53370 wasDragging && _dispatchEvent(self, "dragend", "onDragEnd"); 53371 return true; 53372 }, 53373 updateScroll = function updateScroll(e) { 53374 if (e && self.isDragging && !scrollProxy) { 53375 var parent = e.target || target.parentNode, 53376 deltaX = parent.scrollLeft - parent._gsScrollX, 53377 deltaY = parent.scrollTop - parent._gsScrollY; 53378 53379 if (deltaX || deltaY) { 53380 if (matrix) { 53381 startPointerX -= deltaX * matrix.a + deltaY * matrix.c; 53382 startPointerY -= deltaY * matrix.d + deltaX * matrix.b; 53383 } else { 53384 startPointerX -= deltaX; 53385 startPointerY -= deltaY; 53386 } 53387 53388 parent._gsScrollX += deltaX; 53389 parent._gsScrollY += deltaY; 53390 setPointerPosition(self.pointerX, self.pointerY); 53391 } 53392 } 53393 }, 53394 onClick = function onClick(e) { 53395 var time = _getTime(), 53396 recentlyClicked = time - clickTime < 100, 53397 recentlyDragged = time - dragEndTime < 50, 53398 alreadyDispatched = recentlyClicked && clickDispatch === clickTime, 53399 defaultPrevented = self.pointerEvent && self.pointerEvent.defaultPrevented, 53400 alreadyDispatchedTrusted = recentlyClicked && trustedClickDispatch === clickTime, 53401 trusted = e.isTrusted || e.isTrusted == null && recentlyClicked && alreadyDispatched; 53402 53403 if ((alreadyDispatched || recentlyDragged && self.vars.suppressClickOnDrag !== false) && e.stopImmediatePropagation) { 53404 e.stopImmediatePropagation(); 53405 } 53406 53407 if (recentlyClicked && !(self.pointerEvent && self.pointerEvent.defaultPrevented) && (!alreadyDispatched || trusted && !alreadyDispatchedTrusted)) { 53408 if (trusted && alreadyDispatched) { 53409 trustedClickDispatch = clickTime; 53410 } 53411 53412 clickDispatch = clickTime; 53413 return; 53414 } 53415 53416 if (self.isPressed || recentlyDragged || recentlyClicked) { 53417 if (!trusted || !e.detail || !recentlyClicked || defaultPrevented) { 53418 _preventDefault(e); 53419 } 53420 } 53421 53422 if (!recentlyClicked && !recentlyDragged && !dragged) { 53423 e && e.target && (self.pointerEvent = e); 53424 53425 _dispatchEvent(self, "click", "onClick"); 53426 } 53427 }, 53428 localizePoint = function localizePoint(p) { 53429 return matrix ? { 53430 x: p.x * matrix.a + p.y * matrix.c + matrix.e, 53431 y: p.x * matrix.b + p.y * matrix.d + matrix.f 53432 } : { 53433 x: p.x, 53434 y: p.y 53435 }; 53436 }; 53437 53438 old = Draggable.get(target); 53439 old && old.kill(); 53440 53441 _this2.startDrag = function (event, align) { 53442 var r1, r2, p1, p2; 53443 onPress(event || self.pointerEvent, true); 53444 53445 if (align && !self.hitTest(event || self.pointerEvent)) { 53446 r1 = _parseRect(event || self.pointerEvent); 53447 r2 = _parseRect(target); 53448 p1 = localizePoint({ 53449 x: r1.left + r1.width / 2, 53450 y: r1.top + r1.height / 2 53451 }); 53452 p2 = localizePoint({ 53453 x: r2.left + r2.width / 2, 53454 y: r2.top + r2.height / 2 53455 }); 53456 startPointerX -= p1.x - p2.x; 53457 startPointerY -= p1.y - p2.y; 53458 } 53459 53460 if (!self.isDragging) { 53461 self.isDragging = dragged = true; 53462 53463 _dispatchEvent(self, "dragstart", "onDragStart"); 53464 } 53465 }; 53466 53467 _this2.drag = onMove; 53468 53469 _this2.endDrag = function (e) { 53470 return onRelease(e || self.pointerEvent, true); 53471 }; 53472 53473 _this2.timeSinceDrag = function () { 53474 return self.isDragging ? 0 : (_getTime() - dragEndTime) / 1000; 53475 }; 53476 53477 _this2.timeSinceClick = function () { 53478 return (_getTime() - clickTime) / 1000; 53479 }; 53480 53481 _this2.hitTest = function (target, threshold) { 53482 return Draggable.hitTest(self.target, target, threshold); 53483 }; 53484 53485 _this2.getDirection = function (from, diagonalThreshold) { 53486 var mode = from === "velocity" && InertiaPlugin ? from : _isObject(from) && !rotationMode ? "element" : "start", 53487 xChange, 53488 yChange, 53489 ratio, 53490 direction, 53491 r1, 53492 r2; 53493 53494 if (mode === "element") { 53495 r1 = _parseRect(self.target); 53496 r2 = _parseRect(from); 53497 } 53498 53499 xChange = mode === "start" ? self.x - startElementX : mode === "velocity" ? InertiaPlugin.getVelocity(target, xProp) : r1.left + r1.width / 2 - (r2.left + r2.width / 2); 53500 53501 if (rotationMode) { 53502 return xChange < 0 ? "counter-clockwise" : "clockwise"; 53503 } else { 53504 diagonalThreshold = diagonalThreshold || 2; 53505 yChange = mode === "start" ? self.y - startElementY : mode === "velocity" ? InertiaPlugin.getVelocity(target, yProp) : r1.top + r1.height / 2 - (r2.top + r2.height / 2); 53506 ratio = Math.abs(xChange / yChange); 53507 direction = ratio < 1 / diagonalThreshold ? "" : xChange < 0 ? "left" : "right"; 53508 53509 if (ratio < diagonalThreshold) { 53510 if (direction !== "") { 53511 direction += "-"; 53512 } 53513 53514 direction += yChange < 0 ? "up" : "down"; 53515 } 53516 } 53517 53518 return direction; 53519 }; 53520 53521 _this2.applyBounds = function (newBounds, sticky) { 53522 var x, y, forceZeroVelocity, e, parent, isRoot; 53523 53524 if (newBounds && vars.bounds !== newBounds) { 53525 vars.bounds = newBounds; 53526 return self.update(true, sticky); 53527 } 53528 53529 syncXY(true); 53530 calculateBounds(); 53531 53532 if (hasBounds && !isTweening()) { 53533 x = self.x; 53534 y = self.y; 53535 53536 if (x > maxX) { 53537 x = maxX; 53538 } else if (x < minX) { 53539 x = minX; 53540 } 53541 53542 if (y > maxY) { 53543 y = maxY; 53544 } else if (y < minY) { 53545 y = minY; 53546 } 53547 53548 if (self.x !== x || self.y !== y) { 53549 forceZeroVelocity = true; 53550 self.x = self.endX = x; 53551 53552 if (rotationMode) { 53553 self.endRotation = x; 53554 } else { 53555 self.y = self.endY = y; 53556 } 53557 53558 dirty = true; 53559 render(true); 53560 53561 if (self.autoScroll && !self.isDragging) { 53562 _recordMaxScrolls(target.parentNode); 53563 53564 e = target; 53565 _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop; 53566 _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft; 53567 53568 while (e && !isRoot) { 53569 isRoot = _isRoot(e.parentNode); 53570 parent = isRoot ? _windowProxy : e.parentNode; 53571 53572 if (allowY && parent.scrollTop > parent._gsMaxScrollY) { 53573 parent.scrollTop = parent._gsMaxScrollY; 53574 } 53575 53576 if (allowX && parent.scrollLeft > parent._gsMaxScrollX) { 53577 parent.scrollLeft = parent._gsMaxScrollX; 53578 } 53579 53580 e = parent; 53581 } 53582 } 53583 } 53584 53585 if (self.isThrowing && (forceZeroVelocity || self.endX > maxX || self.endX < minX || self.endY > maxY || self.endY < minY)) { 53586 animate(vars.inertia || vars.throwProps, forceZeroVelocity); 53587 } 53588 } 53589 53590 return self; 53591 }; 53592 53593 _this2.update = function (applyBounds, sticky, ignoreExternalChanges) { 53594 if (sticky && self.isPressed) { 53595
vendor: 3,070 bytes, lines 53595-53696
53595var m = getGlobalMatrix(target), 53596 p = innerMatrix.apply({ 53597 x: self.x - startElementX, 53598 y: self.y - startElementY 53599 }), 53600 m2 = getGlobalMatrix(target.parentNode, true); 53601 m2.apply({ 53602 x: m.e - p.x, 53603 y: m.f - p.y 53604 }, p); 53605 self.x -= p.x - m2.e; 53606 self.y -= p.y - m2.f; 53607 render(true); 53608 recordStartPositions(); 53609 } 53610 53611 var x = self.x, 53612 y = self.y; 53613 updateMatrix(!sticky); 53614 53615 if (applyBounds) { 53616 self.applyBounds(); 53617 } else { 53618 dirty && ignoreExternalChanges && render(true); 53619 syncXY(true); 53620 } 53621 53622 if (sticky) { 53623 setPointerPosition(self.pointerX, self.pointerY); 53624 dirty && render(true); 53625 } 53626 53627 if (self.isPressed && !sticky && (allowX && Math.abs(x - self.x) > 0.01 || allowY && Math.abs(y - self.y) > 0.01 && !rotationMode)) { 53628 recordStartPositions(); 53629 } 53630 53631 if (self.autoScroll) { 53632 _recordMaxScrolls(target.parentNode, self.isDragging); 53633 53634 checkAutoScrollBounds = self.isDragging; 53635 render(true); 53636 53637 _removeScrollListener(target, updateScroll); 53638 53639 _addScrollListener(target, updateScroll); 53640 } 53641 53642 return self; 53643 }; 53644 53645 _this2.enable = function (type) { 53646 var setVars = { 53647 lazy: true 53648 }, 53649 id, 53650 i, 53651 trigger; 53652 53653 if (vars.cursor !== false) { 53654 setVars.cursor = vars.cursor || _defaultCursor; 53655 } 53656 53657 if (gsap.utils.checkPrefix("touchCallout")) { 53658 setVars.touchCallout = "none"; 53659 } 53660 53661 if (type !== "soft") { 53662 _setTouchActionForAllDescendants(triggers, allowX === allowY ? "none" : vars.allowNativeTouchScrolling && target.scrollHeight === target.clientHeight === (target.scrollWidth === target.clientHeight) || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x"); 53663 53664 i = triggers.length; 53665 53666 while (--i > -1) { 53667 trigger = triggers[i]; 53668 _supportsPointer || _addListener(trigger, "mousedown", onPress); 53669 53670 _addListener(trigger, "touchstart", onPress); 53671 53672 _addListener(trigger, "click", onClick, true); 53673 53674 gsap.set(trigger, setVars); 53675 53676 if (trigger.getBBox && trigger.ownerSVGElement && allowX !== allowY) { 53677 gsap.set(trigger.ownerSVGElement, { 53678 touchAction: vars.allowNativeTouchScrolling || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x" 53679 }); 53680 } 53681 53682 vars.allowContextMenu || _addListener(trigger, "contextmenu", onContextMenu); 53683 } 53684 53685 _setSelectable(triggers, false); 53686 } 53687 53688 _addScrollListener(target, updateScroll); 53689 53690 enabled = true; 53691 53692 if (InertiaPlugin && type !== "soft") { 53693 InertiaPlugin.track(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left"); 53694 } 53695 53696 target._gsDragID = id =
vendor: 5,466 bytes, lines 53696-53902
53696 "d" + _lookupCount++; 53697 _lookup[id] = self; 53698 53699 if (scrollProxy) { 53700 scrollProxy.enable(); 53701 scrollProxy.element._gsDragID = id; 53702 } 53703 53704 (vars.bounds || rotationMode) && recordStartPositions(); 53705 vars.bounds && self.applyBounds(); 53706 return self; 53707 }; 53708 53709 _this2.disable = function (type) { 53710 var dragging = self.isDragging, 53711 i = triggers.length, 53712 trigger; 53713 53714 while (--i > -1) { 53715 _setStyle(triggers[i], "cursor", null); 53716 } 53717 53718 if (type !== "soft") { 53719 _setTouchActionForAllDescendants(triggers, null); 53720 53721 i = triggers.length; 53722 53723 while (--i > -1) { 53724 trigger = triggers[i]; 53725 53726 _setStyle(trigger, "touchCallout", null); 53727 53728 _removeListener(trigger, "mousedown", onPress); 53729 53730 _removeListener(trigger, "touchstart", onPress); 53731 53732 _removeListener(trigger, "click", onClick, true); 53733 53734 _removeListener(trigger, "contextmenu", onContextMenu); 53735 } 53736 53737 _setSelectable(triggers, true); 53738 53739 if (touchEventTarget) { 53740 _removeListener(touchEventTarget, "touchcancel", onRelease); 53741 53742 _removeListener(touchEventTarget, "touchend", onRelease); 53743 53744 _removeListener(touchEventTarget, "touchmove", onMove); 53745 } 53746 53747 _removeListener(ownerDoc, "mouseup", onRelease); 53748 53749 _removeListener(ownerDoc, "mousemove", onMove); 53750 } 53751 53752 _removeScrollListener(target, updateScroll); 53753 53754 enabled = false; 53755 53756 if (InertiaPlugin && type !== "soft") { 53757 InertiaPlugin.untrack(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left"); 53758 self.tween && self.tween.kill(); 53759 } 53760 53761 scrollProxy && scrollProxy.disable(); 53762 53763 _removeFromRenderQueue(render); 53764 53765 self.isDragging = self.isPressed = isClicking = false; 53766 dragging && _dispatchEvent(self, "dragend", "onDragEnd"); 53767 return self; 53768 }; 53769 53770 _this2.enabled = function (value, type) { 53771 return arguments.length ? value ? self.enable(type) : self.disable(type) : enabled; 53772 }; 53773 53774 _this2.kill = function () { 53775 self.isThrowing = false; 53776 self.tween && self.tween.kill(); 53777 self.disable(); 53778 gsap.set(triggers, { 53779 clearProps: "userSelect" 53780 }); 53781 delete _lookup[target._gsDragID]; 53782 return self; 53783 }; 53784 53785 _this2.revert = function () { 53786 this.kill(); 53787 this.styles && this.styles.revert(); 53788 }; 53789 53790 if (~type.indexOf("scroll")) { 53791 scrollProxy = _this2.scrollProxy = new ScrollProxy(target, _extend({ 53792 onKill: function onKill() { 53793 self.isPressed && onRelease(null); 53794 } 53795 }, vars)); 53796 target.style.overflowY = allowY && !_isTouchDevice ? "auto" : "hidden"; 53797 target.style.overflowX = allowX && !_isTouchDevice ? "auto" : "hidden"; 53798 target = scrollProxy.content; 53799 } 53800 53801 if (rotationMode) { 53802 killProps.rotation = 1; 53803 } else { 53804 if (allowX) { 53805 killProps[xProp] = 1; 53806 } 53807 53808 if (allowY) { 53809 killProps[yProp] = 1; 53810 } 53811 } 53812 53813 gsCache.force3D = "force3D" in vars ? vars.force3D : true; 53814 53815 _context(_assertThisInitialized(_this2)); 53816 53817 _this2.enable(); 53818 53819 return _this2; 53820 } 53821 53822 Draggable.register = function register(core) { 53823 gsap = core; 53824 53825 _initCore(); 53826 }; 53827 53828 Draggable.create = function create(targets, vars) { 53829 _coreInitted || _initCore(true); 53830 return _toArray(targets).map(function (target) { 53831 return new Draggable(target, vars); 53832 }); 53833 }; 53834 53835 Draggable.get = function get(target) { 53836 return _lookup[(_toArray(target)[0] || {})._gsDragID]; 53837 }; 53838 53839 Draggable.timeSinceDrag = function timeSinceDrag() { 53840 return (_getTime() - _lastDragTime) / 1000; 53841 }; 53842 53843 Draggable.hitTest = function hitTest(obj1, obj2, threshold) { 53844 if (obj1 === obj2) { 53845 return false; 53846 } 53847 53848 var r1 = _parseRect(obj1), 53849 r2 = _parseRect(obj2), 53850 top = r1.top, 53851 left = r1.left, 53852 right = r1.right, 53853 bottom = r1.bottom, 53854 width = r1.width, 53855 height = r1.height, 53856 isOutside = r2.left > right || r2.right < left || r2.top > bottom || r2.bottom < top, 53857 overlap, 53858 area, 53859 isRatio; 53860 53861 if (isOutside || !threshold) { 53862 return !isOutside; 53863 } 53864 53865 isRatio = (threshold + "").indexOf("%") !== -1; 53866 threshold = parseFloat(threshold) || 0; 53867 overlap = { 53868 left: Math.max(left, r2.left), 53869 top: Math.max(top, r2.top) 53870 }; 53871 overlap.width = Math.min(right, r2.right) - overlap.left; 53872 overlap.height = Math.min(bottom, r2.bottom) - overlap.top; 53873 53874 if (overlap.width < 0 || overlap.height < 0) { 53875 return false; 53876 } 53877 53878 if (isRatio) { 53879 threshold *= 0.01; 53880 area = overlap.width * overlap.height; 53881 return area >= width * height * threshold || area >= r2.width * r2.height * threshold; 53882 } 53883 53884 return overlap.width > threshold && overlap.height > threshold; 53885 }; 53886 53887 return Draggable; 53888 }(EventDispatcher); 53889 53890 _setDefaults(Draggable.prototype, { 53891 pointerX: 0, 53892 pointerY: 0, 53893 startX: 0, 53894 startY: 0, 53895 deltaX: 0, 53896 deltaY: 0, 53897 isDragging: false, 53898 isPressed: false 53899 }); 53900 53901 Draggable.zIndex = 1000; 53902 Draggable.version = "3.1
539022.5"; 53903 _getGSAP() && gsap.registerPlugin(Draggable); 53904 53905 exports.Draggable = Draggable; 53906 exports.default = Draggable; 53907 53908 if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;} 53909 53910}))); 53911/* ======================================================================== 53912 * Bootstrap: collapse.js v3.1.1 53913 * http://getbootstrap.com/javascript/#collapse 53914 * ======================================================================== 53915 * Copyright 2011-2014 Twitter, Inc. 53916 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 53917 * ======================================================================== */ 53918 53919 53920+function ($) { 53921 'use strict'; 53922 53923 // COLLAPSE PUBLIC CLASS DEFINITION 53924 // ================================ 53925 53926 var Collapse = function (element, options) { 53927 this.$element = $(element) 53928 this.options = $.extend({}, Collapse.DEFAULTS, options) 53929 this.transitioning = null 53930 53931 if (this.options.parent) this.$parent = $(this.options.parent) 53932 if (this.options.toggle) this.toggle() 53933 } 53934 53935 Collapse.DEFAULTS = { 53936 toggle: true 53937 } 53938 53939 Collapse.prototype.dimension = function () { 53940 var hasWidth = this.$element.hasClass('width') 53941 return hasWidth ? 'width' : 'height' 53942 } 53943 53944 Collapse.prototype.show = function () { 53945 if (this.transitioning || this.$element.hasClass('in')) return 53946 53947 var startEvent = $.Event('show.bs.collapse') 53948 this.$element.trigger(startEvent) 53949 if (startEvent.isDefaultPrevented()) return 53950 53951 var actives = this.$parent && this.$parent.find('> .panel > .in') 53952 53953 if (actives && actives.length) { 53954 var hasData = actives.data('bs.collapse') 53955 if (hasData && hasData.transitioning) return 53956 //START UNCODE EDIT 53957 var parentNoToggle = this.$parent.data('no-toggle') 53958 if (!parentNoToggle) { 53959 actives.collapse('hide') 53960 } 53961 //END UNCODE EDIT 53962 hasData || actives.data('bs.collapse', null) 53963 } 53964 53965 var dimension = this.dimension() 53966 53967 this.$element 53968 .removeClass('collapse') 53969 .addClass('collapsing')[dimension](0) 53970 53971 this.transitioning = 1 53972 53973 var complete = function (e) { 53974 if (e && e.target != this.$element[0]) return 53975 this.$element 53976 .removeClass('collapsing') 53977 .addClass('collapse in')[dimension]('auto') 53978 this.transitioning = 0 53979 this.$element.trigger('shown.bs.collapse') 53980 } 53981 53982 if (!$.support.transition) return complete.call(this) 53983 53984 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 53985 53986 this.$element 53987 .one($.support.transition.end, $.proxy(complete, this)) 53988 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 53989 } 53990 53991 Collapse.prototype.hide = function () { 53992 if (this.transitioning || !this.$element.hasClass('in')) return 53993 53994 var startEvent = $.Event('hide.bs.collapse') 53995 this.$element.trigger(startEvent) 53996 if (startEvent.isDefaultPrevented()) return 53997 53998 var dimension = this.dimension() 53999 54000 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 54001 54002 this.$element 54003 .addClass('collapsing') 54004 .removeClass('collapse') 54005 .removeClass('in') 54006 54007 this.transitioning = 1 54008 54009 var complete = function (e) { 54010 if (e && e.target != this.$element[0]) return 54011 this.transitioning = 0 54012 this.$element 54013 .trigger('hidden.bs.collapse') 54014 .removeClass('collapsing') 54015 .addClass('collapse') 54016 } 54017 54018 if (!$.support.transition) return complete.call(this) 54019 54020 this.$element 54021 [dimension](0) 54022 .one($.support.transition.end, $.proxy(complete, this)) 54023 .emulateTransitionEnd(350) 54024 } 54025 54026 Collapse.prototype.toggle = function () { 54027 this[this.$element.hasClass('in') ? 'hide' : 'show']() 54028 } 54029 54030 54031 // COLLAPSE PLUGIN DEFINITION 54032 // ========================== 54033 54034 var old = $.fn.collapse 54035 54036 $.fn.collapse = function (option) { 54037 return this.each(function () { 54038 var $this = $(this) 54039 var data = $this.data('bs.collapse') 54040 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 54041 54042 if (!data && options.toggle && option == 'show') option = !option 54043 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 54044 if (typeof option == 'string') data[option]() 54045 }) 54046 } 54047 54048 $.fn.collapse.Constructor = Collapse 54049 54050 54051 // COLLAPSE NO CONFLICT 54052 // ==================== 54053 54054 $.fn.collapse.noConflict = function () { 54055 $.fn.collapse = old 54056 return this 54057 } 54058 54059 54060 // COLLAPSE DATA-API 54061 // ================= 54062 54063 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 54064 var $this = $(this), href 54065 var target = $this.attr('data-target') 54066 || e.preventDefault() 54067 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 54068 //Edited by Uncode to replace ID in panel [START] 54069 var _target = href.replace(/^#/, ""); 54070 if ( $('[data-id="' + _target + '"]').length ) { 54071 var $target = $('[data-id="' + _target + '"]') 54072 } else { 54073 var $target = $(target) 54074 } 54075 //Edited by Uncode to replace ID in panel [END] 54076 var data = $target.data('bs.collapse') 54077 var option = data ? 'toggle' : $this.data() 54078 var parent = $this.attr('data-parent') 54079 var $parent = parent && $(parent) 54080 54081 if (!data || !data.transitioning) { 54082 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 54083 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 54084 } 54085 54086 $target.collapse(option) 54087 }) 54088 54089}(jQuery); 54090 54091/* ======================================================================== 54092 * Bootstrap: tab.js v3.1.1 54093 * http://getbootstrap.com/javascript/#tabs 54094 * ======================================================================== 54095 * Copyright 2011-2014 Twitter, Inc. 54096 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 54097 * ======================================================================== */ 54098 54099 54100+function ($) { 54101 'use strict'; 54102 54103 // TAB CLASS DEFINITION 54104 // ==================== 54105 54106 var Tab = function (element) { 54107 this.element = $(element) 54108 } 54109 54110 Tab.prototype.show = function () { 54111 var $this = this.element 54112 var $ul = $this.closest('ul:not(.dropdown-menu)') 54113 var selector = $this.data('target') 54114 54115 if (!selector) { 54116 selector = $this.attr('href') 54117 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 54118 } 54119 54120 if ($this.parent('li').hasClass('active')) return 54121 54122 var previous = $ul.find('.active:last a')[0] 54123 var e = $.Event('show.bs.tab', { 54124 relatedTarget: previous 54125 }) 54126 54127 $this.trigger(e) 54128 54129 if (e.isDefaultPrevented()) return 54130 54131 //Edited by Uncode to replace ID in panel [START] 54132 var _target = selector.replace(/^#/, ""); 54133 if ( $('[data-id="' + _target + '"]').length ) 54134 var $target = $('[data-id="' + _target + '"]') 54135 else 54136 var $target = $(selector) 54137 //Edited by Uncode to replace ID in panel [END] 54138 54139 this.activate($this.parent('li'), $ul) 54140 this.activate($target, $target.parent(), function () { 54141 $this.trigger({ 54142 type: 'shown.bs.tab', 54143 relatedTarget: previous 54144 }) 54145 }) 54146 } 54147 54148 Tab.prototype.activate = function (element, container, callback) { 54149 var $active = container.find('> .active').add(container.find('> .active > .active')) 54150 var transition = callback 54151 && $.support.transition 54152 && $active.hasClass('fade') 54153 54154 function next() { 54155 $active 54156 .removeClass('active') 54157 .find('> .dropdown-menu > .active') 54158 .removeClass('active') 54159 54160 $active 54161 .find('.tab-excerpt').slideUp(); 54162 54163 element.addClass('active') 54164 $('.tab-excerpt', element).slideDown(); 54165 54166 //if (transition) { 54167 element[0].offsetWidth // reflow for transition 54168 element.add($active).addClass('in') 54169 /*} else { 54170 element.removeClass('fade') 54171 }*/ 54172 54173 if (element.parents('.dropdown-menu').length) { 54174 element.closest('li.dropdown').addClass('active') 54175 } 54176 54177 if ( ! element.is('li') ) { 54178 element.closest('.tab-content').find('> .active').not(element).removeClass('active'); 54179 } 54180 54181 callback && callback() 54182 } 54183 54184 transition ? 54185 $active 54186 .one($.support.transition.end, next) 54187 .emulateTransitionEnd(150) : 54188 next() 54189 54190 $active.removeClass('in') 54191 } 54192 54193 54194 // TAB PLUGIN DEFINITION 54195 // ===================== 54196 54197 var old = $.fn.tab 54198 54199 $.fn.tab = function ( option ) { 54200 return this.each(function () { 54201 var $this = $(this) 54202 var data = $this.data('bs.tab') 54203 54204 if (!data) $this.data('bs.tab', (data = new Tab(this))) 54205 if (typeof option == 'string') data[option]() 54206 }) 54207 } 54208 54209 $.fn.tab.Constructor = Tab 54210 54211 54212 // TAB NO CONFLICT 54213 // =============== 54214 54215 $.fn.tab.noConflict = function () { 54216 $.fn.tab = old 54217 return this 54218 } 54219 54220 54221 // TAB DATA-API 54222 // ============ 54223 54224 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 54225 e.preventDefault() 54226 $(this).tab('show') 54227 }) 54228 54229}(jQuery); 54230 54231/* ======================================================================== 54232 * Bootstrap: tooltip.js v3.1.1 54233 * http://getbootstrap.com/javascript/#tooltip 54234 * Inspired by the original jQuery.tipsy by Jason Frame 54235 * ======================================================================== 54236 * Copyright 2011-2014 Twitter, Inc. 54237 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 54238 * ======================================================================== */ 54239 54240 54241+function ($) { 54242 'use strict'; 54243 54244 // TOOLTIP PUBLIC CLASS DEFINITION 54245 // =============================== 54246 54247 var Tooltip = function (element, options) { 54248 this.type = 54249 this.options = 54250 this.enabled = 54251 this.timeout = 54252 this.hoverState = 54253 this.$element = null 54254 54255 this.init('tooltip', element, options) 54256 } 54257 54258 Tooltip.DEFAULTS = { 54259 animation: true, 54260 placement: 'top', 54261 selector: false, 54262 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 54263 trigger: 'hover focus', 54264 title: '', 54265 delay: 0, 54266 html: false, 54267 container: false, 54268 viewport: { 54269 selector: 'body', 54270 padding: 0 54271 } 54272 } 54273 54274 Tooltip.prototype.init = function (type, element, options) { 54275 this.enabled = true 54276 this.type = type 54277 this.$element = $(element) 54278 this.options = this.getOptions(options) 54279 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 54280 54281 var triggers = this.options.trigger.split(' ') 54282 54283 for (var i = triggers.length; i--;) { 54284 var trigger = triggers[i] 54285 54286 if (trigger == 'click') { 54287 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 54288 } else if (trigger != 'manual') { 54289 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 54290 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 54291 54292 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 54293 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 54294 } 54295 } 54296 54297 this.options.selector ? 54298 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 54299 this.fixTitle() 54300 } 54301 54302 Tooltip.prototype.getDefaults = function () { 54303 return Tooltip.DEFAULTS 54304 } 54305 54306 Tooltip.prototype.getOptions = function (options) { 54307 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 54308 54309 if (options.delay && typeof options.delay == 'number') { 54310 options.delay = { 54311 show: options.delay, 54312 hide: options.delay 54313 } 54314 } 54315 54316 return options 54317 } 54318 54319 Tooltip.prototype.getDelegateOptions = function () { 54320 var options = {} 54321 var defaults = this.getDefaults() 54322 54323 this._options && $.each(this._options, function (key, value) { 54324 if (defaults[key] != value) options[key] = value 54325 }) 54326 54327 return options 54328 } 54329 54330 Tooltip.prototype.enter = function (obj) { 54331 var self = obj instanceof this.constructor ? 54332 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 54333 54334 clearTimeout(self.timeout) 54335 54336 self.hoverState = 'in' 54337 54338 if (!self.options.delay || !self.options.delay.show) return self.show() 54339 54340 self.timeout = setTimeout(function () { 54341 if (self.hoverState == 'in') self.show() 54342 }, self.options.delay.show) 54343 } 54344 54345 Tooltip.prototype.leave = function (obj) { 54346 var self = obj instanceof this.constructor ? 54347 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 54348 54349 clearTimeout(self.timeout) 54350 54351 self.hoverState = 'out' 54352 54353 if (!self.options.delay || !self.options.delay.hide) return self.hide() 54354 54355 self.timeout = setTimeout(function () { 54356 if (self.hoverState == 'out') self.hide() 54357 }, self.options.delay.hide) 54358 } 54359 54360 Tooltip.prototype.show = function () { 54361 var e = $.Event('show.bs.' + this.type) 54362 54363 if (this.hasContent() && this.enabled) { 54364 this.$element.trigger(e) 54365 54366 if (e.isDefaultPrevented()) return 54367 var that = this; 54368 54369 var $tip = this.tip() 54370 54371 this.setContent() 54372 54373 if (this.options.animation) $tip.addClass('fade') 54374 54375 var placement = typeof this.options.placement == 'function' ? 54376 this.options.placement.call(this, $tip[0], this.$element[0]) : 54377 this.options.placement 54378 54379 var autoToken = /\s?auto?\s?/i 54380 var autoPlace = autoToken.test(placement) 54381 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 54382 54383 $tip 54384 .detach() 54385 .css({ top: 0, left: 0, display: 'block' }) 54386 .addClass(placement) 54387 54388 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 54389 54390 var pos = this.getPosition() 54391 var actualWidth = $tip[0].offsetWidth 54392 var actualHeight = $tip[0].offsetHeight 54393 54394 if (autoPlace) { 54395 var orgPlacement = placement 54396 var $parent = this.$element.parent() 54397 var parentDim = this.getPosition($parent) 54398 54399 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 54400 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 54401 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 54402 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 54403 placement 54404 54405 $tip 54406 .removeClass(orgPlacement) 54407 .addClass(placement) 54408 } 54409 54410 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 54411 54412 this.applyPlacement(calculatedOffset, placement) 54413 this.hoverState = null 54414 54415 var complete = function() { 54416 that.$element.trigger('shown.bs.' + that.type) 54417 } 54418 54419 $.support.transition && this.$tip.hasClass('fade') ? 54420 $tip 54421 .one($.support.transition.end, complete) 54422 .emulateTransitionEnd(150) : 54423 complete() 54424 } 54425 } 54426 54427 Tooltip.prototype.applyPlacement = function (offset, placement) { 54428 var $tip = this.tip() 54429 var width = $tip[0].offsetWidth 54430 var height = $tip[0].offsetHeight 54431 54432 // manually read margins because getBoundingClientRect includes difference 54433 var marginTop = parseInt($tip.css('margin-top'), 10) 54434 var marginLeft = parseInt($tip.css('margin-left'), 10) 54435 54436 // we must check for NaN for ie 8/9 54437 if (isNaN(marginTop)) marginTop = 0 54438 if (isNaN(marginLeft)) marginLeft = 0 54439 54440 offset.top = offset.top + marginTop 54441 offset.left = offset.left + marginLeft 54442 54443 // $.fn.offset doesn't round pixel values 54444 // so we use setOffset directly with our own function B-0 54445 $.offset.setOffset($tip[0], $.extend({ 54446 using: function (props) { 54447 $tip.css({ 54448 top: Math.round(props.top), 54449 left: Math.round(props.left) 54450 }) 54451 } 54452 }, offset), 0) 54453 54454 $tip.addClass('in') 54455 54456 // check to see if placing tip in new offset caused the tip to resize itself 54457 var actualWidth = $tip[0].offsetWidth 54458 var actualHeight = $tip[0].offsetHeight 54459 54460 if (placement == 'top' && actualHeight != height) { 54461 offset.top = offset.top + height - actualHeight 54462 } 54463 54464 var delta = this.getViewportAdjustedDelta(placement, offset, actualWid
54464th, actualHeight) 54465 54466 if (delta.left) offset.left += delta.left 54467 else offset.top += delta.top 54468 54469 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 54470 var arrowPosition = delta.left ? 'left' : 'top' 54471 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 54472 54473 $tip.offset(offset) 54474 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 54475 } 54476 54477 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 54478 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 54479 } 54480 54481 Tooltip.prototype.setContent = function () { 54482 var $tip = this.tip() 54483 var title = this.getTitle() 54484 54485 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 54486 $tip.removeClass('fade in top bottom left right') 54487 } 54488 54489 Tooltip.prototype.hide = function () { 54490 var that = this 54491 var $tip = this.tip() 54492 var e = $.Event('hide.bs.' + this.type) 54493 54494 function complete() { 54495 if (that.hoverState != 'in') $tip.detach() 54496 that.$element.trigger('hidden.bs.' + that.type) 54497 } 54498 54499 this.$element.trigger(e) 54500 54501 if (e.isDefaultPrevented()) return 54502 54503 $tip.removeClass('in') 54504 54505 $.support.transition && this.$tip.hasClass('fade') ? 54506 $tip 54507 .one($.support.transition.end, complete) 54508 .emulateTransitionEnd(150) : 54509 complete() 54510 54511 this.hoverState = null 54512 54513 return this 54514 } 54515 54516 Tooltip.prototype.fixTitle = function () { 54517 var $e = this.$element 54518 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 54519 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 54520 } 54521 } 54522 54523 Tooltip.prototype.hasContent = function () { 54524 return this.getTitle() 54525 } 54526 54527 Tooltip.prototype.getPosition = function ($element) { 54528 $element = $element || this.$element 54529 var el = $element[0] 54530 var isBody = el.tagName == 'BODY' 54531 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 54532 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 54533 width: isBody ? $(window).width() : $element.outerWidth(), 54534 height: isBody ? $(window).height() : $element.outerHeight() 54535 }, isBody ? {top: 0, left: 0} : $element.offset()) 54536 } 54537 54538 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 54539 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 54540 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 54541 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 54542 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 54543 54544 } 54545 54546 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 54547 var delta = { top: 0, left: 0 } 54548 if (!this.$viewport) return delta 54549 54550 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 54551 var viewportDimensions = this.getPosition(this.$viewport) 54552 54553 if (/right|left/.test(placement)) { 54554 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 54555 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 54556 if (topEdgeOffset < viewportDimensions.top) { // top overflow 54557 delta.top = viewportDimensions.top - topEdgeOffset 54558 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 54559 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
54559EdgeOffset 54560 } 54561 } else { 54562 var leftEdgeOffset = pos.left - viewportPadding 54563 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 54564 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 54565 delta.left = viewportDimensions.left - leftEdgeOffset 54566 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 54567 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 54568 } 54569 } 54570 54571 return delta 54572 } 54573 54574 Tooltip.prototype.getTitle = function () { 54575 var title 54576 var $e = this.$element 54577 var o = this.options 54578 54579 title = $e.attr('data-original-title') 54580 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 54581 54582 return title 54583 } 54584 54585 Tooltip.prototype.tip = function () { 54586 return this.$tip = this.$tip || $(this.options.template) 54587 } 54588 54589 Tooltip.prototype.arrow = function () { 54590 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 54591 } 54592 54593 Tooltip.prototype.validate = function () { 54594 if (!this.$element[0].parentNode) { 54595 this.hide() 54596 this.$element = null 54597 this.options = null 54598 } 54599 } 54600 54601 Tooltip.prototype.enable = function () { 54602 this.enabled = true 54603 } 54604 54605 Tooltip.prototype.disable = function () { 54606 this.enabled = false 54607 } 54608 54609 Tooltip.prototype.toggleEnabled = function () { 54610 this.enabled = !this.enabled 54611 } 54612 54613 Tooltip.prototype.toggle = function (e) { 54614 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 54615 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 54616 } 54617 54618 Tooltip.prototype.destroy = function () { 54619 clearTimeout(this.timeout) 54620 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 54621 } 54622 54623 54624 // TOOLTIP PLUGIN DEFINITION 54625 // ========================= 54626 54627 var old = $.fn.tooltip 54628 54629 $.fn.tooltip = function (option) { 54630 return this.each(function () { 54631 var $this = $(this) 54632 var data = $this.data('bs.tooltip') 54633 var options = typeof option == 'object' && option 54634 54635 if (!data && option == 'destroy') return 54636 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 54637 if (typeof option == 'string') data[option]() 54638 }) 54639 } 54640 54641 $.fn.tooltip.Constructor = Tooltip 54642 54643 54644 // TOOLTIP NO CONFLICT 54645 // =================== 54646 54647 $.fn.tooltip.noConflict = function () { 54648 $.fn.tooltip = old 54649 return this 54650 } 54651 54652}(jQuery); 54653 54654/* ======================================================================== 54655 * Bootstrap: transition.js v3.1.1 54656 * http://getbootstrap.com/javascript/#transitions 54657 * ======================================================================== 54658 * Copyright 2011-2014 Twitter, Inc. 54659 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 54660 * ======================================================================== */ 54661 54662 54663+function ($) { 54664 'use strict'; 54665 54666 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 54667 // ============================================================ 54668 54669 function transitionEnd() { 54670 var el = document.createElement('bootstrap') 54671 54672 var transEndEventNames = { 54673 WebkitTransition : 'webkitTransitionEnd', 54674 MozTransition : 'transitionend', 54675 OTransition : 'oTransitionEnd otransitionend', 54676 transition : 'transitionend' 54677 } 54678 54679 for (var name in transEndEventNames) { 54680 if (el.style[name] !== undefined) { 54681 return { end: transEndEventNames[name] } 54682 } 54683 } 54684 54685 return false // explicit for ie8 ( ._.) 54686 } 54687 54688 // http://blog.alexmaccaw.com/css-transitions 54689 $.fn.emulateTransitionEnd = function (duration) { 54690 var called = false, $el = this 54691 $(this).one($.support.transition.end, function () { called = true }) 54692 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 54693 setTimeout(callback, duration) 54694 return this 54695 } 54696 54697 $(function () { 54698 $.support.transition = transitionEnd() 54699 }) 54700 54701}(jQuery); 54702 54703 54704// ------------------------------------------ 54705// Rellax.js 54706// Buttery smooth parallax library 54707// Copyright (c) 2016 Moe Amaya (@moeamaya) 54708// MIT license 54709// 54710// Thanks to Paraxify.js and Jaime Cabllero 54711// for parallax concepts 54712// ------------------------------------------ 54713 54714(function (root, factory) { 54715 if (typeof define === 'function' && define.amd) { 54716 // AMD. Register as an anonymous module. 54717 define([], factory); 54718 } else if (typeof module === 'object' && module.exports) { 54719 // Node. Does not work with strict CommonJS, but 54720 // only CommonJS-like environments that support module.exports, 54721 // like Node. 54722 module.exports = factory(); 54723 } else { 54724 // Browser globals (root is window) 54725 root.Rellax = factory(); 54726 } 54727}(typeof window !== "undefined" ? window : global, function () { 54728 var Rellax = function(el, options){ 54729 "use strict"; 54730 54731 var self = Object.create(Rellax.prototype); 54732 54733 var posY = 0; 54734 var screenY = 0; 54735 var posX = 0; 54736 var screenX = 0; 54737 var blocks = []; 54738 var pause = true; 54739 54740 // check what requestAnimationFrame to use, and if 54741 // it's not supported, use the onscroll event 54742 var loop = window.requestAnimationFrame || 54743 window.webkitRequestAnimationFrame || 54744 window.mozRequestAnimationFrame || 54745 window.msRequestAnimationFrame || 54746 window.oRequestAnimationFrame || 54747 function(callback){ return setTimeout(callback, 1000 / 60); }; 54748 54749 // store the id for later use 54750 var loopId = null; 54751 54752 // Test via a getter in the options object to see if the passive property is accessed 54753 var supportsPassive = false;
vendor: 10,724 bytes, lines 54754-55055
54754 try { 54755 var opts = Object.defineProperty({}, 'passive', { 54756 get: function() { 54757 supportsPassive = true; 54758 } 54759 }); 54760 window.addEventListener("testPassive", null, opts); 54761 window.removeEventListener("testPassive", null, opts); 54762 } catch (e) {} 54763 54764 // check what cancelAnimation method to use 54765 var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout; 54766 54767 // check which transform property to use 54768 var transformProp = window.transformProp || (function(){ 54769 var testEl = document.createElement('div'); 54770 if (testEl.style.transform === null) { 54771 var vendors = ['Webkit', 'Moz', 'ms']; 54772 for (var vendor in vendors) { 54773 if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) { 54774 return vendors[vendor] + 'Transform'; 54775 } 54776 } 54777 } 54778 return 'transform'; 54779 })(); 54780 54781 // Default Settings 54782 self.options = { 54783 speed: -2, 54784 verticalSpeed: null, 54785 horizontalSpeed: null, 54786 breakpoints: [576, 768, 1201], 54787 center: false, 54788 wrapper: null, 54789 relativeToWrapper: false, 54790 round: true, 54791 vertical: true, 54792 horizontal: false, 54793 verticalScrollAxis: "y", 54794 horizontalScrollAxis: "x", 54795 callback: function() {}, 54796 }; 54797 54798 // User defined options (might have more in the future) 54799 if (options){ 54800 Object.keys(options).forEach(function(key){ 54801 self.options[key] = options[key]; 54802 }); 54803 } 54804 54805 function validateCustomBreakpoints () { 54806 if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) { 54807 var isAscending = true; 54808 var isNumerical = true; 54809 var lastVal; 54810 self.options.breakpoints.forEach(function (i) { 54811 if (typeof i !== 'number') isNumerical = false; 54812 if (lastVal !== null) { 54813 if (i < lastVal) isAscending = false; 54814 } 54815 lastVal = i; 54816 }); 54817 if (isAscending && isNumerical) return; 54818 } 54819 // revert defaults if set incorrectly 54820 self.options.breakpoints = [576, 768, 1201]; 54821 console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted"); 54822 } 54823 54824 if (options && options.breakpoints) { 54825 validateCustomBreakpoints(); 54826 } 54827 54828 // By default, rellax class 54829 if (!el) { 54830 el = '.rellax'; 54831 } 54832 54833 // check if el is a className or a node 54834 var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el]; 54835 54836 // Now query selector 54837 if (elements.length > 0) { 54838 self.elems = elements; 54839 } 54840 54841 // The elements don't exist 54842 else { 54843 console.warn("Rellax: The elements you're trying to select don't exist."); 54844 return; 54845 } 54846 54847 // Has a wrapper and it exists 54848 if (self.options.wrapper) { 54849 if (!self.options.wrapper.nodeType) { 54850 var wrapper = document.querySelector(self.options.wrapper); 54851 54852 if (wrapper) { 54853 self.options.wrapper = wrapper; 54854 } else { 54855 console.warn("Rellax: The wrapper you're trying to use doesn't exist."); 54856 return; 54857 } 54858 } 54859 } 54860 54861 // set a placeholder for the current breakpoint 54862 var currentBreakpoint; 54863 54864 // helper to determine current breakpoint 54865 var getCurrentBreakpoint = function (w) { 54866 var bp = self.options.breakpoints; 54867 if (w < bp[0]) return 'xs'; 54868 if (w >= bp[0] && w < bp[1]) return 'sm'; 54869 if (w >= bp[1] && w < bp[2]) return 'md'; 54870 return 'lg'; 54871 }; 54872 54873 // Get and cache initial position of all elements 54874 var cacheBlocks = function() { 54875 for (var i = 0; i < self.elems.length; i++){ 54876 var block = createBlock(self.elems[i]); 54877 blocks.push(block); 54878 } 54879 }; 54880 54881 54882 // Let's kick this script off 54883 // Build array for cached element values 54884 var init = function() { 54885 for (var i = 0; i < blocks.length; i++){ 54886 self.elems[i].style.cssText = blocks[i].style; 54887 } 54888 54889 blocks = []; 54890 54891 screenY = window.innerHeight; 54892 screenX = window.innerWidth; 54893 currentBreakpoint = getCurrentBreakpoint(screenX); 54894 54895 setPosition(); 54896 54897 cacheBlocks(); 54898 54899 animate(); 54900 54901 // If paused, unpause and set listener for window resizing events 54902 if (pause) { 54903 window.addEventListener('resize', init); 54904 pause = false; 54905 // Start the loop 54906 update(); 54907 } 54908 }; 54909 54910 // We want to cache the parallax blocks' 54911 // values: base, top, height, speed 54912 // el: is dom object, return: el cache values 54913 var createBlock = function(el) { 54914 var dataPercentage = el.getAttribute( 'data-rellax-percentage' ); 54915 var dataSpeed = el.getAttribute( 'data-rellax-speed' ); 54916 var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' ); 54917 var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' ); 54918 var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' ); 54919 var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' ); 54920 var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed'); 54921 var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed'); 54922 var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis'); 54923 var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis'); 54924 var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0; 54925 var dataMin = el.getAttribute( 'data-rellax-min' ); 54926 var dataMax = el.getAttribute( 'data-rellax-max' ); 54927 var dataMinX = el.getAttribute('data-rellax-min-x'); 54928 var dataMaxX = el.getAttribute('data-rellax-max-x'); 54929 var dataMinY = el.getAttribute('data-rellax-min-y'); 54930 var dataMaxY = el.getAttribute('data-rellax-max-y'); 54931 var mapBreakpoints; 54932 var breakpoints = true; 54933 54934 if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) { 54935 breakpoints = false; 54936 } else { 54937 mapBreakpoints = { 54938 'xs': dataXsSpeed, 54939 'sm': dataMobileSpeed, 54940 'md': dataTabletSpeed, 54941 'lg': dataDesktopSpeed 54942 }; 54943 } 54944 54945 // initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser) 54946 // ensures elements are positioned based on HTML layout. 54947 // 54948 // If the element has the percentage attribute, the posY and posX needs to be 54949 // the current scroll position's value, so that the elements are still positioned based on HTML layout 54950 var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 54951 // If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll. 54952 if (self.options.relativeToWrapper) { 54953 var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 54954 wrapperPosY = scrollPosY - self.options.wrapper.offsetTop; 54955 } 54956 var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0; 54957 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; 54958 54959 var blockTop = posY + el.getBoundingClientRect().top; 54960 var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight; 54961 54962 var blockLeft = posX + el.getBoundingClientRect().left; 54963 var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth; 54964 54965 // apparently parallax equation everyone uses 54966 var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY); 54967 var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX); 54968 if(self.options.center){ percentageX = 0.5; percentageY = 0.5; } 54969 54970 // Optional individual block speed as data attr, otherwise global speed 54971 var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed); 54972 var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed; 54973 var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed; 54974 54975 // Optional individual block movement axis direction as data attr, otherwise global movement direction 54976 var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis; 54977 var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis; 54978 54979 var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed); 54980 54981 // ~~Store non-translate3d transforms~~ 54982 // Store inline styles and extract transforms 54983 var style = el.style.cssText; 54984 var transform = ''; 54985 54986 // Check if there's an inline styled transform 54987 var searchResult = /transform\s*:/i.exec(style); 54988 if (searchResult) { 54989 // Get the index of the transform 54990 var index = searchResult.index; 54991 54992 // Trim the style to the transform point and get the following semi-colon index 54993 var trimmedStyle = style.slice(index); 54994 var delimiter = trimmedStyle.indexOf(';'); 54995 54996 // Remove "transform" string and save the attribute 54997 if (delimiter) { 54998 transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,''); 54999 } else { 55000 transform = " " + trimmedStyle.slice(11).replace(/\s/g,''); 55001 } 55002 } 55003 55004 return { 55005 baseX: bases.x, 55006 baseY: bases.y, 55007 top: blockTop, 55008 left: blockLeft, 55009 height: blockHeight, 55010 width: blockWidth, 55011 speed: speed, 55012 verticalSpeed: verticalSpeed, 55013 horizontalSpeed: horizontalSpeed, 55014 verticalScrollAxis: verticalScrollAxis, 55015 horizontalScrollAxis: horizontalScrollAxis, 55016 style: style, 55017 transform: transform, 55018 zindex: dataZindex, 55019 min: dataMin, 55020 max: dataMax, 55021 minX: dataMinX, 55022 maxX: dataMaxX, 55023 minY: dataMinY, 55024 maxY: dataMaxY 55025 }; 55026 }; 55027 55028 // set scroll position (posY, posX) 55029 // side effect method is not ideal, but okay for now 55030 // returns true if the scroll changed, false if nothing happened 55031 var setPosition = function() { 55032 var oldY = posY; 55033 var oldX = posX; 55034 55035 posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 55036 posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset; 55037 // If option relativeToWrapper is true, use relative wrapper value instead. 55038 if (self.options.relativeToWrapper) { 55039 var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 55040 posY = scrollPosY - self.options.wrapper.offsetTop; 55041 } 55042 55043 55044 if (oldY != posY && self.options.vertical) { 55045 // scroll changed, return true 55046 return true; 55047 } 55048 55049 if (oldX != posX && self.options.horizontal) { 55050 // scroll changed, return true 55051 return true; 55052 } 55053 55054 // scroll did not change 55055 return false;
55056 }; 55057 55058 // Ahh a pure function, gets new transform value 55059 // based on scrollPosition and speed 55060 // Allow for decimal pixel values 55061 var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) { 55062 var result = {}; 55063 var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX))); 55064 var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY))); 55065 55066 result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100; 55067 result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100; 55068 55069 return result; 55070 }; 55071 55072 // Remove event listeners and loop again 55073 var deferredUpdate = function() { 55074 window.removeEventListener('resize', deferredUpdate); 55075 window.removeEventListener('orientationchange', deferredUpdate); 55076 (self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate); 55077 (self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate); 55078 55079 // loop again 55080 loopId = loop(update); 55081 }; 55082 55083 // Loop 55084 var update = function() { 55085 if (setPosition() && pause === false) { 55086 animate(); 55087 55088 // loop again 55089 loopId = loop(update); 55090 } else { 55091 loopId = null; 55092 55093 // Don't animate until we get a position updating event 55094 window.addEventListener('resize', deferredUpdate); 55095 window.addEventListener('orientationchange', deferredUpdate); 55096 (self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false); 55097 (self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false); 55098 } 55099 }; 55100 55101 // Transform3d on parallax element 55102 var animate = function() { 55103 var positions; 55104 for (var i = 0; i < self.elems.length; i++){ 55105 // Determine relevant movement directions 55106 var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase(); 55107 var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase(); 55108 var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0; 55109 var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0; 55110 var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0; 55111 var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0; 55112 55113 var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY)); 55114 var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX)); 55115 55116 // Subtracting initialize value, so element stays in same spot as HTML 55117 positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed); 55118 var positionY = positions.y - blocks[i].baseY; 55119 var positionX = positions.x - blocks[i].baseX; 55120 55121 // The next two "if" blocks go like this: 55122 // Check if a limit is defined (first "min", then "max"); 55123 // Check if we need to change the Y or the X 55124 // (Currently working only if just one of the axes is enabled) 55125 // Then, check if the new position is inside the allowed limit 55126 // If so, use new position. If not, set position to limit. 55127 55128 // Check if a min limit is defined 55129 if (blocks[i].min !== null) { 55130 if (self.options.vertical && !self.options.horizontal) { 55131 positionY = positionY <= blocks[i].min ? blocks[i].min : positionY; 55132 } 55133 if (self.options.horizontal && !self.options.vertical) { 55134 positionX = positionX <= blocks[i].min ? blocks[i].min : positionX; 55135 } 55136 } 55137 55138 // Check if directional min limits are defined 55139 if (blocks[i].minY != null) { 55140 positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY; 55141 } 55142 if (blocks[i].minX != null) { 55143 positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX; 55144 } 55145 55146 // Check if a max limit is defined 55147 if (blocks[i].max !== null) { 55148 if (self.options.vertical && !self.options.horizontal) { 55149 positionY = positionY >= blocks[i].max ? blocks[i].max : positionY; 55150 } 55151 if (self.options.horizontal && !self.options.vertical) { 55152 positionX = positionX >= blocks[i].max ? blocks[i].max : positionX; 55153 } 55154 } 55155 55156 // Check if directional max limits are defined 55157 if (blocks[i].maxY != null) { 55158 positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY; 55159 } 55160 if (blocks[i].maxX != null) { 55161 positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX; 55162 } 55163 55164 var zindex = blocks[i].zindex; 55165 55166 // Move that element 55167 // (Set the new translation and append initial inline transforms.) 55168 var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform; 55169 self.elems[i].style[transformProp] = translate; 55170 } 55171 self.options.callback(positions); 55172 }; 55173 55174 self.destroy = function() { 55175 for (var i = 0; i < self.elems.length; i++){ 55176 self.elems[i].style.cssText = blocks[i].style; 55177 } 55178 55179 // Remove resize event listener if not pause, and pause 55180 if (!pause) { 55181 window.removeEventListener('resize', init); 55182 pause = true; 55183 } 55184 55185 // Clear the animation loop to prevent possible memory leak 55186 clearLoop(loopId); 55187 loopId = null; 55188 }; 55189 55190 // Init 55191 init(); 55192 55193 // Allow to recalculate the initial values whenever we want 55194 self.refresh = init; 55195 55196 return self; 55197 }; 55198 return Rellax; 55199})); 55200 55201/* 55202 * OKVideo by OKFocus v2.3.2 55203 * http://okfoc.us 55204 * 55205 * Copyright 2014, OKFocus 55206 * Licensed under the MIT license. 55207 * 55208 */ 55209var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array(); 55210// youtube player ready 55211function onYouTubeIframeAPIReady() { 55212 YTplayers = new Array(); 55213 jQuery('.uncode-video-container.video').each(function() { 55214 var playerY; 55215 if (jQuery(this).attr('data-provider') == 'youtube') { 55216 var id = jQuery(this).attr('data-id'), 55217 start = jQuery(this).attr('data-start'), 55218 end = jQuery(this).attr('data-end'); 55219 start = typeof start && start !== null ? start : 0; 55220 end = typeof end && end !== null ? end : 0; 55221 options = jQuery(window).data('okoptions-' + id); 55222 if ( typeof options === 'undefined' ) { 55223 return true; 55224 } 55225 options.time = jQuery(this).attr('data-t'); 55226 playerY = new YT.Player('okplayer-' + id, { 55227 videoId: options.video ? options.video.id : null, 55228 playerVars: { 55229 'autohide': 1, 55230 'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay, 55231 'disablekb': 1, 55232 'cc_load_policy': options.captions, 55233 'controls': 0, 55234 'enablejsapi': 1, 55235 'fs': 0, 55236 'modestbranding': 1, 55237 'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname), 55238 'iv_load_policy': options.annotations, 55239 'loop': options.loop, 55240 'showinfo': 0, 55241 'rel': 0, 55242 'wmode': 'opaque', 55243 'hd': options.hd, 55244 'mute': 1, 55245 'start': start, 55246 'end': end 55247 }, 55248 events: { 55249 'onReady': OKEvents.yt.ready, 55250 'onStateChange': OKEvents.yt.onStateChange, 55251 'onError': OKEvents.yt.error 55252 } 55253 }); 55254 YTplayers[id] = playerY; 55255 playerY.videoId = id; 55256 } 55257 55258 }); 55259} 55260// vimeo player ready 55261function vimeoPlayerReady(id) { 55262 options = jQuery(window).data('okoptions-' + id); 55263 if ( typeof options === 'undefined' ) { 55264 return true; 55265 }
55266 var jIframe = options.jobject, 55267 iframe = jIframe[0]; 55268 55269 jIframe.attr('src', jIframe.data('src')); 55270 var playerV = new Vimeo.Player(iframe); 55271 // hide player until Vimeo hides controls... 55272 playerV.on('loaded', function(e) { 55273 OKEvents.v.onReady(iframe); 55274 var carouselContainer = jQuery(iframe).closest('.owl-carousel'); 55275 if (carouselContainer.length) { 55276 UNCODE.owlPlayVideo(carouselContainer); 55277 } 55278 // "Do not try to add listeners or call functions before receiving this event." 55279 if (OKEvents.utils.isMobile()) { 55280 // mobile devices cannot listen for play event 55281 OKEvents.v.onPlay(playerV); 55282 } else { 55283 playerV.on('play', function(){ 55284 OKEvents.v.onPlay(playerV); 55285 jQuery(window).trigger('okevents.v.play', [playerV]); 55286 }); 55287 playerV.on('pause', function(){ 55288 OKEvents.v.onPause; 55289 jQuery(window).trigger('okevents.v.pause', [playerV]); 55290 }); 55291 playerV.on('ended', function(){ 55292 OKEvents.v.onFinish 55293 jQuery(window).trigger('okevents.v.ended', [playerV]); 55294 }); 55295 } 55296 if (options.time != null) { 55297 var optsTimeStr = (options.time).replace('t=', ''), 55298 timeV = ''; 55299 55300 if ( /[a-zA-Z]/g.test(optsTimeStr) ) { 55301 var timeArr = optsTimeStr.split(/([^\d.-])/); 55302 for ( var i = 0; i < timeArr.length; i++ ) { 55303 if ( timeArr[i] === 'h' ) { 55304 timeV += parseFloat(timeArr[i-1]) * 3600; 55305 } else if ( timeArr[i] === 'm' ) { 55306 timeV += parseFloat(timeArr[i-1]) * 60; 55307 } else if ( timeArr[i] === 's' ) { 55308 timeV += parseFloat(timeArr[i-1]); 55309 } 55310 } 55311 } else { 55312 timeV = optsTimeStr; 55313 } 55314 55315 playerV.setCurrentTime(timeV); 55316 } 55317 55318 playerV.setVolume(0); 55319 playerV.play(); 55320 jQuery(iframe).css({ 55321 visibility: 'visible', 55322 opacity: 1 55323 }); 55324 jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 55325 jQuery(iframe).closest('#page-header').addClass('video-started'); 55326 jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 55327 55328 jQuery(window).trigger('okevents.v.loaded', [playerV]); 55329 }); 55330} 55331OKEvents = { 55332 yt: { 55333 ready: function(event) { 55334 var id = event.target.videoId, 55335 $video = jQuery('#okplayer-' + id), 55336 options = jQuery(window).data('okoptions-' + id); 55337 if ( typeof options === 'undefined' ) { 55338 return true; 55339 } 55340 youtubePlayers[id] = event.target; 55341 event.target.setVolume(options.volume); 55342 if (options.autoplay === 1) { 55343 if (options.playlist.list) { 55344 player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality); 55345 } else { 55346 var inCarousel = $video.closest('.owl-item'); 55347 if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) { 55348 if (options.time != null) { 55349 event.target.seekTo(parseInt(options.time)); 55350 } 55351 event.target.playVideo(); 55352 } else { 55353 event.target.pauseVideo(); 55354 } 55355 } 55356 } 55357 OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target); 55358 55359 $video.closest('[data-provider]').on('uncode-resume', function(){ 55360 if (options.time != null) { 55361 event.target.seekTo(parseInt(options.time)).playVideo(); 55362 } else { 55363 event.target.seekTo(0).playVideo(); 55364 } 55365 }); 55366 55367 $video.closest('[data-provider]').on('uncode-pause', function(){ 55368 if (options.time != null) { 55369 event.target.seekTo(parseInt(options.time)).pauseVideo(); 55370 } else { 55371 event.target.seekTo(0).pauseVideo(); 55372 } 55373 }); 55374 jQuery(window).trigger('okevents.y.loaded', [event]); 55375 }, 55376 onStateChange: function(event) { 55377 var id = event.target.videoId, 55378 $video = jQuery('#okplayer-' + id), 55379 options = jQuery(window).data('okoptions-' + id); 55380 if ( typeof options === 'undefined' || typeof event.target.setVolume === 'undefined' ) { 55381 return true; 55382 } 55383 youtubePlayers[id] = event.target; 55384 event.target.setVolume(options.volume); 55385 var $fluid = $video.closest('.fluid-object'), 55386 $tmb = $video.closest('.tmb'), 55387 setTime; 55388 switch (event.data) { 55389 case -1: 55390 OKEvents.utils.isFunction(options.unstarted) && options.unstarted(); 55391 break; 55392 case 0: 55393 OKEvents.utils.isFunction(options.onFinished) && options.onFinished(); 55394 options.loop && event.target.playVideo(); 55395 break; 55396 case 1: 55397 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 55398 setTimeout(function() { 55399 UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)'); 55400 jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 55401 jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started'); 55402 jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 55403 }, 300); 55404 break; 55405 case 2: 55406 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 55407 break; 55408 case 3: 55409 OKEvents.utils.isFunction(options.buffering) && options.buffering(); 55410 break; 55411 case 5: 55412 OKEvents.utils.isFunction(options.cued) && options.cued(); 55413 break; 55414 default:
55415 throw "OKVideo: received invalid data from YT player."; 55416 } 55417 55418 jQuery(window).trigger('okevents.y.change', [event]); 55419 }, 55420 error: function(event) { 55421 throw event; 55422 } 55423 }, 55424 v: { 55425 onReady: function(target) { 55426 if ( typeof options === 'undefined' ) { 55427 return true; 55428 } 55429 OKEvents.utils.isFunction(options.onReady) && options.onReady(target); 55430 }, 55431 onPlay: function(player) { 55432 if ( typeof options === 'undefined' ) { 55433 return true; 55434 } 55435 if (!OKEvents.utils.isMobile()) player.setVolume(options.volume); 55436 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 55437 jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 55438 jQuery(player.element).closest('#page-header').addClass('video-started'); 55439 jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 55440 }, 55441 onPause: function() { 55442 if ( typeof options === 'undefined' ) { 55443 return true; 55444 } 55445 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 55446 }, 55447 onFinish: function() { 55448 if ( typeof options === 'undefined' ) { 55449 return true; 55450 } 55451 OKEvents.utils.isFunction(options.onFinish) && options.onFinish(); 55452 } 55453 }, 55454 utils: { 55455 isFunction: function(func) { 55456 if (typeof func === 'function') { 55457 return true; 55458 } else { 55459 return false; 55460 } 55461 }, 55462 isMobile: function() { 55463 if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) { 55464 return true; 55465 } else { 55466 return false; 55467 } 55468 } 55469 } 55470}; 55471/** 55472 * vivus - JavaScript library to make drawing animation on SVG 55473 * @version v0.4.4 55474 * @link https://github.com/maxwellito/vivus 55475 * @license MIT 55476 */ 55477 55478'use strict'; 55479 55480(function () { 55481 55482 'use strict'; 55483 55484/** 55485 * Pathformer 55486 * Beta version 55487 * 55488 * Take any SVG version 1.1 and transform 55489 * child elements to 'path' elements 55490 * 55491 * This code is purely forked from 55492 * https://github.com/Waest/SVGPathConverter 55493 */ 55494 55495/** 55496 * Class constructor 55497 * 55498 * @param {DOM|String} element Dom element of the SVG or id of it 55499 */ 55500function Pathformer(element) { 55501 // Test params 55502 if (typeof element === 'undefined') { 55503 throw new Error('Pathformer [constructor]: "element" parameter is required'); 55504 } 55505 55506 // Set the element 55507 if (element.constructor === String) { 55508 element = document.getElementById(element); 55509 if (!element) { 55510 throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID'); 55511 } 55512 } 55513 if (element instanceof window.SVGElement || 55514 element instanceof window.SVGGElement || 55515 /^svg$/i.test(element.nodeName)) { 55516 this.el = element; 55517 } else { 55518 throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement'); 55519 } 55520 55521 // Start 55522 this.scan(element); 55523} 55524 55525/** 55526 * List of tags which can be transformed 55527 * to path elements 55528 * 55529 * @type {Array} 55530 */ 55531Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect']; 55532 55533/** 55534 * List of attribute names which contain 55535 * data. This array list them to check if 55536 * they contain bad values, like percentage. 55537 * 55538 * @type {Array} 55539 */ 55540Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 55540-56338
55540y1', 'y2']; 55541 55542/** 55543 * Finds the elements compatible for transform 55544 * and apply the liked method 55545 * 55546 * @param {object} options Object from the constructor 55547 */ 55548Pathformer.prototype.scan = function (svg) { 55549 var fn, element, pathData, pathDom, 55550 elements = svg.querySelectorAll(this.TYPES.join(',')); 55551 55552 for (var i = 0; i < elements.length; i++) { 55553 element = elements[i]; 55554 fn = this[element.tagName.toLowerCase() + 'ToPath']; 55555 pathData = fn(this.parseAttr(element.attributes)); 55556 pathDom = this.pathMaker(element, pathData); 55557 element.parentNode.replaceChild(pathDom, element); 55558 } 55559}; 55560 55561 55562/** 55563 * Read `line` element to extract and transform 55564 * data, to make it ready for a `path` object. 55565 * 55566 * @param {DOMelement} element Line element to transform 55567 * @return {object} Data for a `path` element 55568 */ 55569Pathformer.prototype.lineToPath = function (element) { 55570 var newElement = {}, 55571 x1 = element.x1 || 0, 55572 y1 = element.y1 || 0, 55573 x2 = element.x2 || 0, 55574 y2 = element.y2 || 0; 55575 55576 newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2; 55577 return newElement; 55578}; 55579 55580/** 55581 * Read `rect` element to extract and transform 55582 * data, to make it ready for a `path` object. 55583 * The radius-border is not taken in charge yet. 55584 * (your help is more than welcomed) 55585 * 55586 * @param {DOMelement} element Rect element to transform 55587 * @return {object} Data for a `path` element 55588 */ 55589Pathformer.prototype.rectToPath = function (element) { 55590 var newElement = {}, 55591 x = parseFloat(element.x) || 0, 55592 y = parseFloat(element.y) || 0, 55593 width = parseFloat(element.width) || 0, 55594 height = parseFloat(element.height) || 0; 55595 55596 if (element.rx || element.ry) { 55597 var rx = parseInt(element.rx, 10) || -1, 55598 ry = parseInt(element.ry, 10) || -1; 55599 rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2); 55600 ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2); 55601 55602 newElement.d = 'M ' + (x + rx) + ',' + y + ' ' + 55603 'L ' + (x + width - rx) + ',' + y + ' ' + 55604 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' + 55605 'L ' + (x + width) + ',' + (y + height - ry) + ' ' + 55606 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' + 55607 'L ' + (x + rx) + ',' + (y + height) + ' ' + 55608 'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' + 55609 'L ' + x + ',' + (y + ry) + ' ' + 55610 'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y; 55611 } 55612 else { 55613 newElement.d = 'M' + x + ' ' + y + ' ' + 55614 'L' + (x + width) + ' ' + y + ' ' + 55615 'L' + (x + width) + ' ' + (y + height) + ' ' + 55616 'L' + x + ' ' + (y + height) + ' Z'; 55617 } 55618 return newElement; 55619}; 55620 55621/** 55622 * Read `polyline` element to extract and transform 55623 * data, to make it ready for a `path` object. 55624 * 55625 * @param {DOMelement} element Polyline element to transform 55626 * @return {object} Data for a `path` element 55627 */ 55628Pathformer.prototype.polylineToPath = function (element) { 55629 var newElement = {}, 55630 points = element.points.trim().split(' '), 55631 i, path; 55632 55633 // Reformatting if points are defined without commas 55634 if (element.points.indexOf(',') === -1) { 55635 var formattedPoints = []; 55636 for (i = 0; i < points.length; i+=2) { 55637 formattedPoints.push(points[i] + ',' + points[i+1]); 55638 } 55639 points = formattedPoints; 55640 } 55641 55642 // Generate the path.d value 55643 path = 'M' + points[0]; 55644 for(i = 1; i < points.length; i++) { 55645 if (points[i].indexOf(',') !== -1) { 55646 path += 'L' + points[i]; 55647 } 55648 } 55649 newElement.d = path; 55650 return newElement; 55651}; 55652 55653/** 55654 * Read `polygon` element to extract and transform 55655 * data, to make it ready for a `path` object. 55656 * This method rely on polylineToPath, because the 55657 * logic is similar. The path created is just closed, 55658 * so it needs an 'Z' at the end. 55659 * 55660 * @param {DOMelement} element Polygon element to transform 55661 * @return {object} Data for a `path` element 55662 */ 55663Pathformer.prototype.polygonToPath = function (element) { 55664 var newElement = Pathformer.prototype.polylineToPath(element); 55665 55666 newElement.d += 'Z'; 55667 return newElement; 55668}; 55669 55670/** 55671 * Read `ellipse` element to extract and transform 55672 * data, to make it ready for a `path` object. 55673 * 55674 * @param {DOMelement} element ellipse element to transform 55675 * @return {object} Data for a `path` element 55676 */ 55677Pathformer.prototype.ellipseToPath = function (element) { 55678 var newElement = {}, 55679 rx = parseFloat(element.rx) || 0, 55680 ry = parseFloat(element.ry) || 0, 55681 cx = parseFloat(element.cx) || 0, 55682 cy = parseFloat(element.cy) || 0, 55683 startX = cx - rx, 55684 startY = cy, 55685 endX = parseFloat(cx) + parseFloat(rx), 55686 endY = cy; 55687 55688 newElement.d = 'M' + startX + ',' + startY + 55689 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY + 55690 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY; 55691 return newElement; 55692}; 55693 55694/** 55695 * Read `circle` element to extract and transform 55696 * data, to make it ready for a `path` object. 55697 * 55698 * @param {DOMelement} element Circle element to transform 55699 * @return {object} Data for a `path` element 55700 */ 55701Pathformer.prototype.circleToPath = function (element) { 55702 var newElement = {}, 55703 r = parseFloat(element.r) || 0, 55704 cx = parseFloat(element.cx) || 0, 55705 cy = parseFloat(element.cy) || 0, 55706 startX = cx - r, 55707 startY = cy, 55708 endX = parseFloat(cx) + parseFloat(r), 55709 endY = cy; 55710 55711 newElement.d = 'M' + startX + ',' + startY + 55712 'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY + 55713 'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY; 55714 return newElement; 55715}; 55716 55717/** 55718 * Create `path` elements form original element 55719 * and prepared objects 55720 * 55721 * @param {DOMelement} element Original element to transform 55722 * @param {object} pathData Path data (from `toPath` methods) 55723 * @return {DOMelement} Path element 55724 */ 55725Pathformer.prototype.pathMaker = function (element, pathData) { 55726 var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path'); 55727 for(i = 0; i < element.attributes.length; i++) { 55728 attr = element.attributes[i]; 55729 if (this.ATTR_WATCH.indexOf(attr.name) === -1) { 55730 pathTag.setAttribute(attr.name, attr.value); 55731 } 55732 } 55733 for(i in pathData) { 55734 pathTag.setAttribute(i, pathData[i]); 55735 } 55736 return pathTag; 55737}; 55738 55739/** 55740 * Parse attributes of a DOM element to 55741 * get an object of attribute => value 55742 * 55743 * @param {NamedNodeMap} attributes Attributes object from DOM element to parse 55744 * @return {object} Object of attributes 55745 */ 55746Pathformer.prototype.parseAttr = function (element) { 55747 var attr, output = {}; 55748 for (var i = 0; i < element.length; i++) { 55749 attr = element[i]; 55750 // Check if no data attribute contains '%', or the transformation is impossible 55751 if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) { 55752 throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.'); 55753 } 55754 output[attr.name] = attr.value; 55755 } 55756 return output; 55757}; 55758 55759 'use strict'; 55760 55761var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt; 55762 55763/** 55764 * Vivus 55765 * Beta version 55766 * 55767 * Take any SVG and make the animation 55768 * to give give the impression of live drawing 55769 * 55770 * This in more than just inspired from codrops 55771 * At that point, it's a pure fork. 55772 */ 55773 55774/** 55775 * Class constructor 55776 * option structure 55777 * type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed) 55778 * duration: <int> (in frames) 55779 * start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport) 55780 * delay: <int> (delay between the drawing of first and last path) 55781 * dashGap <integer> whitespace extra margin between dashes 55782 * pathTimingFunction <function> timing animation function for each path element of the SVG 55783 * animTimingFunction <function> timing animation function for the complete SVG 55784 * forceRender <boolean> force the browser to re-render all updated path items 55785 * selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original 55786 * 55787 * The attribute 'type' is by default on 'delayed'. 55788 * - 'delayed' 55789 * all paths are draw at the same time but with a 55790 * little delay between them before start 55791 * - 'sync' 55792 * all path are start and finish at the same time 55793 * - 'oneByOne' 55794 * only one path is draw at the time 55795 * the end of the first one will trigger the draw 55796 * of the next one 55797 * 55798 * All these values can be overwritten individually 55799 * for each path item in the SVG 55800 * The value of frames will always take the advantage of 55801 * the duration value. 55802 * If you fail somewhere, an error will be thrown. 55803 * Good luck. 55804 * 55805 * @constructor 55806 * @this {Vivus} 55807 * @param {DOM|String} element Dom element of the SVG or id of it 55808 * @param {Object} options Options about the animation 55809 * @param {Function} callback Callback for the end of the animation 55810 */ 55811function Vivus (element, options, callback) { 55812 55813 setupEnv(); 55814 55815 // Setup 55816 this.isReady = false; 55817 this.setElement(element, options); 55818 this.setOptions(options); 55819 this.setCallback(callback); 55820 55821 if (this.isReady) { 55822 this.init(); 55823 } 55824} 55825 55826/** 55827 * Timing functions 55828 ************************************** 55829 * 55830 * Default functions to help developers. 55831 * It always take a number as parameter (between 0 to 1) then 55832 * return a number (between 0 and 1) 55833 */ 55834Vivus.LINEAR = function (x) {return x;}; 55835Vivus.EASE = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;}; 55836Vivus.EASE_OUT = function (x) {return 1 - Math.pow(1-x, 3);}; 55837Vivus.EASE_IN = function (x) {return Math.pow(x, 3);}; 55838Vivus.EASE_OUT_BOUNCE = function (x) { 55839 var base = -Math.cos(x * (0.5 * Math.PI)) + 1, 55840 rate = Math.pow(base,1.5), 55841 rateR = Math.pow(1 - x, 2), 55842 progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1; 55843 return (1- rateR) + (progress * rateR); 55844}; 55845 55846 55847/** 55848 * Setters 55849 ************************************** 55850 */ 55851 55852/** 55853 * Check and set the element in the instance 55854 * The method will not return anything, but will throw an 55855 * error if the parameter is invalid 55856 * 55857 * @param {DOM|String} element SVG Dom element or id of it 55858 */ 55859Vivus.prototype.setElement = function (element, options) { 55860 var onLoad, self; 55861 55862 // Basic check 55863 if (typeof element === 'undefined') { 55864 throw new Error('Vivus [constructor]: "element" parameter is required'); 55865 } 55866 55867 // Set the element 55868 if (element.constructor === String) { 55869 element = document.getElementById(element); 55870 if (!element) { 55871 throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID'); 55872 } 55873 } 55874 this.parentEl = element; 55875 55876 // Load the SVG with XMLHttpRequest and extract the SVG 55877 if (options && options.file) { 55878 var self = this; 55879 onLoad = function (e) { 55880 var domSandbox = document.createElement('div'); 55881 domSandbox.innerHTML = this.responseText; 55882 55883 var svgTag = domSandbox.querySelector('svg'); 55884 if (!svgTag) { 55885 throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file); 55886 } 55887 55888 self.el = svgTag 55889 self.el.setAttribute('width', '100%'); 55890 self.el.setAttribute('height', '100%'); 55891 self.parentEl.appendChild(self.el) 55892 self.isReady = true; 55893 self.init(); 55894 self = null; 55895 } 55896 55897 var oReq = new window.XMLHttpRequest(); 55898 oReq.addEventListener('load', onLoad); 55899 oReq.open('GET', options.file); 55900 oReq.send(); 55901 return; 55902 } 55903 55904 switch (element.constructor) { 55905 case window.SVGSVGElement: 55906 case window.SVGElement: 55907 case window.SVGGElement: 55908 this.el = element; 55909 this.isReady = true; 55910 break; 55911 55912 case window.HTMLObjectElement: 55913 self = this; 55914 onLoad = function (e) { 55915 if (self.isReady) { 55916 return; 55917 } 55918 self.el = element.contentDocument && element.contentDocument.querySelector('svg'); 55919 if (!self.el && e) { 55920 throw new Error('Vivus [constructor]: object loaded does not contain any SVG'); 55921 } 55922 else if (self.el) { 55923 if (element.getAttribute('built-by-vivus')) { 55924 self.parentEl.insertBefore(self.el, element); 55925 self.parentEl.removeChild(element); 55926 self.el.setAttribute('width', '100%'); 55927 self.el.setAttribute('height', '100%'); 55928 } 55929 self.isReady = true; 55930 self.init(); 55931 self = null; 55932 } 55933 }; 55934 55935 if (!onLoad()) { 55936 element.addEventListener('load', onLoad); 55937 } 55938 break; 55939 55940 default: 55941 throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)'); 55942 } 55943}; 55944 55945/** 55946 * Set up user option to the instance 55947 * The method will not return anything, but will throw an 55948 * error if the parameter is invalid 55949 * 55950 * @param {object} options Object from the constructor 55951 */ 55952Vivus.prototype.setOptions = function (options) { 55953 var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync']; 55954 var allowedStarts = ['inViewport', 'manual', 'autostart']; 55955 55956 // Basic check 55957 if (options !== undefined && options.constructor !== Object) { 55958 throw new Error('Vivus [constructor]: "options" parameter must be an object'); 55959 } 55960 else { 55961 options = options || {}; 55962 } 55963 55964 // Set the animation type 55965 if (options.type && allowedTypes.indexOf(options.type) === -1) { 55966 throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`'); 55967 } 55968 else { 55969 this.type = options.type || allowedTypes[0]; 55970 } 55971 55972 // Set the start type 55973 if (options.start && allowedStarts.indexOf(options.start) === -1) { 55974 throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option'); 55975 } 55976 else { 55977 this.start = options.start || allowedStarts[0]; 55978 } 55979 55980 this.isIE = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 ); 55981 this.duration = parsePositiveInt(options.duration, 120); 55982 this.delay = parsePositiveInt(options.delay, null); 55983 //Uncode addition 55984 this.delayStart = parsePositiveInt(options.delayStart, null); 55985 //#END 55986 this.dashGap = parsePositiveInt(options.dashGap, 1); 55987 this.forceRender = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE; 55988 this.reverseStack = !!options.reverseStack; 55989 this.selfDestroy = !!options.selfDestroy; 55990 this.onReady = options.onReady; 55991 this.map = []; 55992 this.frameLength = this.currentFrame = this.delayUnit = this.speed = this.handle = null; 55993 55994 this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false; 55995 55996 this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR; 55997 this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR; 55998 55999 if (this.delay >= this.duration) { 56000 throw new Error('Vivus [constructor]: delay must be shorter than duration'); 56001 } 56002}; 56003 56004/** 56005 * Set up callback to the instance 56006 * The method will not return enything, but will throw an 56007 * error if the parameter is invalid 56008 * 56009 * @param {Function} callback Callback for the animation end 56010 */ 56011Vivus.prototype.setCallback = function (callback) { 56012 // Basic check 56013 if (!!callback && callback.constructor !== Function) { 56014 throw new Error('Vivus [constructor]: "callback" parameter must be a function'); 56015 } 56016 this.callback = callback || function () {}; 56017}; 56018 56019 56020/** 56021 * Core 56022 ************************************** 56023 */ 56024 56025/** 56026 * Map the svg, path by path. 56027 * The method return nothing, it just fill the 56028 * `map` array. Each item in this array represent 56029 * a path element from the SVG, with informations for 56030 * the animation. 56031 * 56032 * ``` 56033 * [ 56034 * { 56035 * el: <DOMobj> the path element 56036 * length: <number> length of the path line 56037 * startAt: <number> time start of the path animation (in frames) 56038 * duration: <number> path animation duration (in frames) 56039 * }, 56040 * ... 56041 * ] 56042 * ``` 56043 * 56044 */ 56045Vivus.prototype.mapping = function () { 56046 var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint; 56047 timePoint = totalLength = lengthMeter = 0; 56048 paths = this.el.querySelectorAll('path'); 56049 56050 for (i = 0; i < paths.length; i++) { 56051 path = paths[i]; 56052 if (this.isInvisible(path)) { 56053 continue; 56054 } 56055 pathObj = { 56056 el: path, 56057 length: Math.ceil(path.getTotalLength()) 56058 }; 56059 // Test if the path length is correct 56060 if (isNaN(pathObj.length)) { 56061 if (window.console && console.warn) { 56062 console.warn('Vivus [mapping]: cannot retrieve a path element length', path); 56063 } 56064 continue; 56065 } 56066 this.map.push(pathObj); 56067 path.style.strokeDasharray = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2); 56068 path.style.strokeDashoffset = pathObj.length + this.dashGap; 56069 pathObj.length += this.dashGap; 56070 totalLength += pathObj.length; 56071 56072 this.renderPath(i); 56073 } 56074 56075 totalLength = totalLength === 0 ? 1 : totalLength; 56076 this.delay = this.delay === null ? this.duration / 3 : this.delay; 56077 this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1); 56078 56079 // Reverse stack if asked 56080 if (this.reverseStack) { 56081 this.map.reverse(); 56082 } 56083 56084 for (i = 0; i < this.map.length; i++) { 56085 pathObj = this.map[i]; 56086 56087 switch (this.type) { 56088 case 'delayed': 56089 pathObj.startAt = this.delayUnit * i; 56090 pathObj.duration = this.duration - this.delay; 56091 break; 56092 56093 case 'oneByOne': 56094 pathObj.startAt = lengthMeter / totalLength * this.duration; 56095 pathObj.duration = pathObj.length / totalLength * this.duration; 56096 break; 56097 56098 case 'sync': 56099 case 'async': 56100 case 'nsync': 56101 pathObj.startAt = 0; 56102 pathObj.duration = this.duration; 56103 break; 56104 56105 case 'scenario-sync': 56106 path = pathObj.el; 56107 pAttrs = this.parseAttr(path); 56108 pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0); 56109 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 56110 timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration; 56111 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 56112 break; 56113 56114 case 'scenario': 56115 path = pathObj.el; 56116 pAttrs = this.parseAttr(path); 56117 pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0; 56118 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 56119 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 56120 break; 56121 } 56122 lengthMeter += pathObj.length; 56123 this.frameLength = this.frameLength || this.duration; 56124 } 56125}; 56126 56127/** 56128 * Interval method to draw the SVG from current 56129 * position of the animation. It update the value of 56130 * `currentFrame` and re-trace the SVG. 56131 * 56132 * It use this.handle to store the requestAnimationFrame 56133 * and clear it one the animation is stopped. So this 56134 * attribute can be used to know if the animation is 56135 * playing. 56136 * 56137 * Once the animation at the end, this method will 56138 * trigger the Vivus callback. 56139 * 56140 */ 56141Vivus.prototype.drawer = function () { 56142 var self = this; 56143 this.currentFrame += this.speed; 56144 56145 if (this.currentFrame <= 0) { 56146 this.stop(); 56147 this.reset(); 56148 } else if (this.currentFrame >= this.frameLength) { 56149 this.stop(); 56150 this.currentFrame = this.frameLength; 56151 this.trace(); 56152 if (this.selfDestroy) { 56153 this.destroy(); 56154 } 56155 } else { 56156 this.trace(); 56157 this.handle = requestAnimFrame(function () { 56158 self.drawer(); 56159 }); 56160 return; 56161 } 56162 56163 this.callback(this); 56164 if (this.instanceCallback) { 56165 this.instanceCallback(this); 56166 this.instanceCallback = null; 56167 } 56168}; 56169 56170/** 56171 * Draw the SVG at the current instant from the 56172 * `currentFrame` value. Here is where most of the magic is. 56173 * The trick is to use the `strokeDashoffset` style property. 56174 * 56175 * For optimisation reasons, a new property called `progress` 56176 * is added in each item of `map`. This one contain the current 56177 * progress of the path element. Only if the new value is different 56178 * the new value will be applied to the DOM element. This 56179 * method save a lot of resources to re-render the SVG. And could 56180 * be improved if the animation couldn't be played forward. 56181 * 56182 */ 56183Vivus.prototype.trace = function () { 56184 var i, progress, path, currentFrame; 56185 currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength; 56186 for (i = 0; i < this.map.length; i++) { 56187 path = this.map[i]; 56188 progress = (currentFrame - path.startAt) / path.duration; 56189 progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress))); 56190 if (path.progress !== progress) { 56191 path.progress = progress; 56192 path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress)); 56193 this.renderPath(i); 56194 } 56195 } 56196}; 56197 56198/** 56199 * Method forcing the browser to re-render a path element 56200 * from it's index in the map. Depending on the `forceRender` 56201 * value. 56202 * The trick is to replace the path element by it's clone. 56203 * This practice is not recommended because it's asking more 56204 * ressources, too much DOM manupulation.. 56205 * but it's the only way to let the magic happen on IE. 56206 * By default, this fallback is only applied on IE. 56207 * 56208 * @param {Number} index Path index 56209 */ 56210Vivus.prototype.renderPath = function (index) { 56211 if (this.forceRender && this.map && this.map[index]) { 56212 var pathObj = this.map[index], 56213 newPath = pathObj.el.cloneNode(true); 56214 pathObj.el.parentNode.replaceChild(newPath, pathObj.el); 56215 pathObj.el = newPath; 56216 } 56217}; 56218 56219/** 56220 * When the SVG object is loaded and ready, 56221 * this method will continue the initialisation. 56222 * 56223 * This this mainly due to the case of passing an 56224 * object tag in the constructor. It will wait 56225 * the end of the loading to initialise. 56226 * 56227 */ 56228Vivus.prototype.init = function () { 56229 // Set object variables 56230 this.frameLength = 0; 56231 this.currentFrame = 0; 56232 this.map = []; 56233 56234 // Start 56235 new Pathformer(this.el); 56236 this.mapping(); 56237 this.starter(); 56238 56239 if (this.onReady) { 56240 this.onReady(this); 56241 } 56242}; 56243 56244/** 56245 * Trigger to start of the animation. 56246 * Depending on the `start` value, a different script 56247 * will be applied. 56248 * 56249 * If the `start` value is not valid, an error will be thrown. 56250 * Even if technically, this is impossible. 56251 * 56252 */ 56253Vivus.prototype.starter = function () { 56254 switch (this.start) { 56255 case 'manual': 56256 return; 56257 56258 case 'autostart': 56259 this.play(); 56260 break; 56261 56262 case 'inViewport': 56263 var self = this, 56264 listener = function () { 56265 if (self.isInViewport(self.parentEl, 1)) { 56266 self.play(); 56267 window.removeEventListener('scroll', listener); 56268 //Uncode addition 56269 window.removeEventListener('fp-slide-changed', listener); 56270 window.removeEventListener('fp-slide-scroll', listener); 56271 //#END 56272 } 56273 }; 56274 window.addEventListener('scroll', listener); 56275 //Uncode addition 56276 window.addEventListener('fp-slide-changed', listener); 56277 window.addEventListener('fp-slide-scroll', listener); 56278 //#END 56279 listener(); 56280 break; 56281 } 56282}; 56283 56284 56285/** 56286 * Controls 56287 ************************************** 56288 */ 56289 56290/** 56291 * Get the current status of the animation between 56292 * three different states: 'start', 'progress', 'end'. 56293 * @return {string} Instance status 56294 */ 56295Vivus.prototype.getStatus = function () { 56296 return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress'; 56297}; 56298 56299/** 56300 * Reset the instance to the initial state : undraw 56301 * Be careful, it just reset the animation, if you're 56302 * playing the animation, this won't stop it. But just 56303 * make it start from start. 56304 * 56305 */ 56306Vivus.prototype.reset = function () { 56307 return this.setFrameProgress(0); 56308}; 56309 56310/** 56311 * Set the instance to the final state : drawn 56312 * Be careful, it just set the animation, if you're 56313 * playing the animation on rewind, this won't stop it. 56314 * But just make it start from the end. 56315 * 56316 */ 56317Vivus.prototype.finish = function () { 56318 return this.setFrameProgress(1); 56319}; 56320 56321/** 56322 * Set the level of progress of the drawing. 56323 * 56324 * @param {number} progress Level of progress to set 56325 */ 56326Vivus.prototype.setFrameProgress = function (progress) { 56327 progress = Math.min(1, Math.max(0, progress)); 56328 this.currentFrame = Math.round(this.frameLength * progress); 56329 this.trace(); 56330 return this; 56331}; 56332 56333/** 56334 * Play the animation at the desired speed. 56335 * Speed must be a valid number (no zero). 56336 * By default, the speed value is 1. 56337 * But a negative value is accepted to go forward. 56338 *
56339 * And works with float too. 56340 * But don't forget we are in JavaScript, se be nice 56341 * with him and give him a 1/2^x value. 56342 * 56343 * @param {number} speed Animation speed [optional] 56344 */ 56345Vivus.prototype.play = function (speed, callback) { 56346 this.instanceCallback = null; 56347 56348 if (speed && typeof speed === 'function') { 56349 this.instanceCallback = speed; // first parameter is actually the callback function 56350 speed = null; 56351 } 56352 else if (speed && typeof speed !== 'number') { 56353 throw new Error('Vivus [play]: invalid speed'); 56354 } 56355 // if the first parameter wasn't the callback, check if the seconds was 56356 if (callback && typeof(callback) === 'function' && !this.instanceCallback) { 56357 this.instanceCallback = callback; 56358 } 56359 56360 56361 this.speed = speed || 1; 56362 //Uncode addition 56363 if (!this.handle) { 56364 var $this = this, 56365 delay = (this.delayStart != null) ? this.delayStart : 0; 56366 setTimeout(function() { 56367 $this.drawer(); 56368 }, delay); 56369 } 56370 //#END 56371 return this; 56372}; 56373 56374/** 56375 * Stop the current animation, if on progress. 56376 * Should not trigger any error. 56377 * 56378 */ 56379Vivus.prototype.stop = function () { 56380 if (this.handle) { 56381 cancelAnimFrame(this.handle); 56382 this.handle = null; 56383 } 56384 return this; 56385}; 56386 56387/** 56388 * Destroy the instance. 56389 * Remove all bad styling attributes on all 56390 * path tags 56391 * 56392 */ 56393Vivus.prototype.destroy = function () { 56394 this.stop(); 56395 var i, path; 56396 for (i = 0; i < this.map.length; i++) { 56397 path = this.map[i]; 56398 path.el.style.strokeDashoffset = null; 56399 path.el.style.strokeDasharray = null; 56400 this.renderPath(i); 56401 } 56402}; 56403 56404 56405/** 56406 * Utils methods 56407 * include methods from Codrops 56408 ************************************** 56409 */ 56410 56411/** 56412 * Method to best guess if a path should added into 56413 * the animation or not. 56414 * 56415 * 1. Use the `data-vivus-ignore` attribute if set 56416 * 2. Check if the instance must ignore invisible paths 56417 * 3. Check if the path is visible 56418 * 56419 * For now the visibility checking is unstable. 56420 * It will be used for a beta phase. 56421 * 56422 * Other improvments are planned. Like detecting 56423 * is the path got a stroke or a valid opacity. 56424 */ 56425Vivus.prototype.isInvisible = function (el) { 56426 var rect, 56427 ignoreAttr = el.getAttribute('data-ignore'); 56428 56429 if (ignoreAttr !== null) { 56430 return ignoreAttr !== 'false'; 56431 } 56432 56433 if (this.ignoreInvisible) { 56434 rect = el.getBoundingClientRect(); 56435 return !rect.width && !rect.height; 56436 } 56437 else { 56438 return false; 56439 } 56440}; 56441 56442/** 56443 * Parse attributes of a DOM element to 56444 * get an object of {attributeName => attributeValue} 56445 * 56446 * @param {object} element DOM element to parse 56447 * @return {object} Object of attributes 56448 */ 56449Vivus.prototype.parseAttr = function (element) { 56450 var attr, output = {}; 56451 if (element && element.attributes) { 56452 for (var i = 0; i < element.attributes.length; i++) { 56453 attr = element.attributes[i]; 56454 output[attr.name] = attr.value; 56455 } 56456 } 56457 return output; 56458}; 56459 56460/** 56461 * Reply if an element is in the page viewport 56462 * 56463 * @param {object} el Element to observe 56464 * @param {number} h Percentage of height 56465 * @return {boolean} 56466 */ 56467Vivus.prototype.isInViewport = function (el, h) { 56468 var scrolled = this.scrollY(), 56469 viewed = scrolled + this.getViewportH(), 56470 elBCR = el.getBoundingClientRect(), 56471 elHeight = elBCR.height, 56472 elTop = scrolled + elBCR.top, 56473 elBottom = elTop + elHeight; 56474 56475 // if 0, the element is considered in the viewport as soon as it enters. 56476 // if 1, the element is considered in the viewport only when it's fully inside 56477 // value in percentage (1 >= h >= 0) 56478 h = h || 0; 56479 56480 return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled; 56481}; 56482 56483 56484/** 56485 * Get the viewport height in pixels 56486 * 56487 * @return {integer} Viewport height 56488 */ 56489Vivus.prototype.getViewportH = function () { 56490 var client = this.docElem.clientHeight, 56491 inner = window.innerHeight; 56492 56493 if (client < inner) { 56494 return inner; 56495 } 56496 else { 56497 return client; 56498 } 56499}; 56500 56501/** 56502 * Get the page Y offset 56503 * 56504 * @return {integer} Page Y offset 56505 */ 56506Vivus.prototype.scrollY = function () { 56507 return window.pageYOffset || this.docElem.scrollTop; 56508}; 56509 56510setupEnv = function () { 56511 56512 if (Vivus.prototype.docElem) { 56513 return; 56514 } 56515 56516 /** 56517 * Alias for document element 56518 * 56519 * @type {DOMelement} 56520 */ 56521 Vivus.prototype.docElem = window.document.documentElement; 56522 56523 /** 56524 * Alias for `requestAnimationFrame` or 56525 * `setTimeout` function for deprecated browsers. 56526 * 56527 */ 56528 requestAnimFrame = (function () { 56529 return ( 56530 window.requestAnimationFrame || 56531 window.webkitRequestAnimationFrame || 56532 window.mozRequestAnimationFrame || 56533 window.oRequestAnimationFrame || 56534 window.msRequestAnimationFrame || 56535 function(/* function */ callback){ 56536 return window.setTimeout(callback, 1000 / 60); 56537 } 56538 ); 56539 })(); 56540 56541 /** 56542 * Alias for `cancelAnimationFrame` or 56543 * `cancelTimeout` function for deprecated browsers. 56544 * 56545 */ 56546 cancelAnimFrame = (function () { 56547 return ( 56548 window.cancelAnimationFrame || 56549 window.webkitCancelAnimationFrame || 56550 window.mozCancelAnimationFrame || 56551 window.oCancelAnimationFrame || 56552 window.msCancelAnimationFrame || 56553 function(id){ 56554 return window.clearTimeout(id); 56555 } 56556 ); 56557 })(); 56558}; 56559 56560/** 56561 * Parse string to integer. 56562 * If the number is not positive or null 56563 * the method will return the default value 56564 * or 0 if undefined 56565 * 56566 * @param {string} value String to parse 56567 * @param {*}
56567 defaultValue Value to return if the result parsed is invalid 56568 * @return {number} 56569 * 56570 */ 56571parsePositiveInt = function (value, defaultValue) { 56572 var output = parseInt(value, 10); 56573 return (output >= 0) ? output : defaultValue; 56574}; 56575 56576 56577 if (typeof define === 'function' && define.amd) { 56578 // AMD. Register as an anonymous module. 56579 define([], function() { 56580 return Vivus; 56581 }); 56582 } else if (typeof exports === 'object') { 56583 // Node. Does not work with strict CommonJS, but 56584 // only CommonJS-like environments that support module.exports, 56585 // like Node. 56586 module.exports = Vivus; 56587 } else { 56588 // Browser globals 56589 window.Vivus = Vivus; 56590 } 56591 56592}()); 56593 56594//Noise.js 56595!function(){"use strict";var r=.5*(Math.sqrt(3)-1),e=(3-Math.sqrt(3))/6,t=1/6,a=(Math.sqrt(5)-1)/4,o=(5-Math.sqrt(5))/20;function i(r){var e;e="function"==typeof r?r:r?function(){var r=0,e=0,t=0,a=1,o=(i=4022871197,function(r){r=r.toString();for(var e=0;e<r.length;e++){var t=.02519603282416938*(i+=r.charCodeAt(e));t-=i=t>>>0,i=(t*=i)>>>0,i+=4294967296*(t-=i)}return 2.3283064365386963e-10*(i>>>0)});var i;r=o(" "),e=o(" "),t=o(" ");for(var n=0;n<arguments.length;n++)(r-=o(arguments[n]))<0&&(r+=1),(e-=o(arguments[n]))<0&&(e+=1),(t-=o(arguments[n]))<0&&(t+=1);return o=null,function(){var o=2091639*r+2.3283064365386963e-10*a;return r=e,e=t,t=o-(a=0|o)}}(r):Math.random,this.p=n(e),this.perm=new Uint8Array(512),this.permMod12=new Uint8Array(512);for(var t=0;t<512;t++)this.perm[t]=this.p[255&t],this.permMod12[t]=this.perm[t]%12}function n(r){var e,t=new Uint8Array(256);for(e=0;e<256;e++)t[e]=e;for(e=0;e<255;e++){var a=e+~~(r()*(256-e)),o=t[e];t[e]=t[a],t[a]=o}return t}i.prototype={grad3:new Float32Array([1,1,0,-1,1,0,1,-1,0,-1,-1,0,1,0,1,-1,0,1,1,0,-1,-1,0,-1,0,1,1,0,-1,1,0,1,-1,0,-1,-1]),grad4:new Float32Array([0,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,1,0,1,1,1,0,1,-1,1,0,-1,1,1,0,-1,-1,-1,0,1,1,-1,0,1,-1,-1,0,-1,1,-1,0,-1,-1,1,1,0,1,1,1,0,-1,1,-1,0,1,1,-1,0,-1,-1,1,0,1,-1,1,0,-1,-1,-1,0,1,-1,-1,0,-1,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,0]),noise2D:function(t,a){var o,i,n=this.permMod12,f=this.perm,s=this.grad3,v=0,h=0,l=0,u=(t+a)*r,d=Math.floor(t+u),p=Math.floor(a+u),M=(d+p)*e,m=t-(d-M),c=a-(p-M);m>c?(o=1,i=0):(o=0,i=1);var y=m-o+e,w=c-i+e,g=m-1+2*e,A=c-1+2*e,x=255&d,q=255&p,D=.5-m*m-c*c;if(D>=0){var S=3*n[x+f[q]];v=(D*=D)*D*(s[S]*m+s[S+1]*c)}var U=.5-y*y-w*w;if(U>=0){var b=3*n[x+o+f[q+i]];h=(U*=U)*U*(s[b]*y+s[b+1]*w)}var F=.5-g*g-A*A;if(F>=0){var N=3*n[x+1+f[q+1]];l=(F*=F)*F*(s[N]*g+s[N+1]*A)}return 70*(v+h+l)},noise3D:function(r,e,a){var o,i,n,f,s,v,h,l,u,d,p=this.permMod12,M=this.perm,m=this.grad3,c=(r+e+a)*(1/3),y=Math.floor(r+c),w=Math.floor(e+c),g=Math.floor(a+c),A=(y+w+g)*t,x=r-(y-A),q=e-(w-A),D=a-(g-A);x>=q?q>=D?(s=1,v=0,h=0,l=1,u=1,d=0):x>=D?(s=1,v=0,h=0,l=1,u=0,d=1):(s=0,v=0,h=1,l=1,u=0,d=1):q<D?(s=0,v=0,h=1,l=0,u=1,d=1):x<D?(s=0,v=1,h=0,l=0,u=1,d=1):(s=0,v=1,h=0,l=1,u=1,d=0);var S=x-s+t,U=q-v+t,b=D-h+t,F=x-l+2*t,N=q-u+2*t,C=D-d+2*t,P=x-1+.5,T=q-1+.5,_=D-1+.5,j=255&y,k=255&w,z=255&g,B=.6-x*x-q*q-D*D;if(B<0)o=0;else{var E=3*p[j+M[k+M[z]]];o=(B*=B)*B*(m[E]*x+m[E+1]*q+m[E+2]*D)}var G=.6-S*S-U*U-b*b;if(G<0)i=0;else{var H=3*p[j+s+M[k+v+M[z+h]]];i=(G*=G)*G*(m[H]*S+m[H+1]*U+m[H+2]*b)}var I=.6-F*F-N*N-C*C;if(I<0)n=0;else{var J=3*p[j+l+M[k+u+M[z+d]]];n=(I*=I)*I*(m[J]*F+m[J+1]*N+m[J+2]*C)}var K=.6-P*P-T*T-_*_;if(K<0)f=0;else{var L=3*p[j+1+M[k+1+M[z+1]]];f=(K*=K)*K*(m[L]*P+m[L+1]*T+m[L+2]*_)}return 32*(o+i+n+f)},noise4D:function(r,e,t,i){var n,f,s,v,h,l,u,d,p,M,m,c,y,w,g,A,x,q=this.perm,D=this.grad4,S=(r+e+t+i)*a,U=Math.floor(r+S),b=Math.floor(e+S),F=Math.floor(t+S),N=Math.floor(i+S),C=(U+b+F+N)*o,P=r-(U-C),T=e-(b-C),_=t-(F-C),j=i-(N-C),k=0,z=0,B=0,E=0;P>T?k++:z++,P>_?k++:B++,P>j?k++:E++,T>_?z++:B++,T>j?z++:E++,_>j?B++:E++;var G=P-(l=k>=3?1:0)+o,H=T-(u=z>=3?1:0)+o,I=_-(d=B>=3?1:0)+o,J=j-(p=E>=3?1:0)+o,K=P-(M=k>=2?1:0)+2*o,L=T-(m=z>=2?1:0)+2*o,O=_-(c=B>=2?1:0)+2*o,Q=j-(y=E>=2?1:0)+2*o,R=P-(w=k>=1?1:0)+3*o,V=T-(g=z>=1?1:0)+3*o,W=_-(A=B>=1?1:0)+3*o,X=j-(x=E>=1?1:0)+3*o,Y=P-1+4*o,Z=T-1+4*o,$=_-1+4*o,rr=j-1+4*o,er=255&U,tr=255&b,ar=255&F,or=255&N,ir=.6-P*P-T*T-_*_-j*j;if(ir<0)n=0;else{var nr=q[er+q[tr+q[ar+q[or]]]]%32*4;n=(ir*=ir)*ir*(D[nr]*P+D[nr+1]*T+D[nr+2]*_+D[nr+3]*j)}var fr=.6-G*G-H*H-I*I-J*J;if(fr<0)f=0;else{var sr=q[er+l+q[tr+u+q[ar+d+q[or+p]]]]%32*4;f=(fr*=fr)*fr*(D[sr]*G+D[sr+1]*H+D[sr+2]*I+D[sr+3]*J)}var vr=.6-K*K-L*L-O*O-Q*Q;if(vr<0)s=0;else{var hr=q[er+M+q[tr+m+q[ar+c+q[or+y]]]]%32*4;s=(vr*=vr)*vr*(D[hr]*K+D[hr+1]*L+D[hr+2]*O+D[hr+3]*Q)}
56595var lr=.6-R*R-V*V-W*W-X*X;if(lr<0)v=0;else{var ur=q[er+w+q[tr+g+q[ar+A+q[or+x]]]]%32*4;v=(lr*=lr)*lr*(D[ur]*R+D[ur+1]*V+D[ur+2]*W+D[ur+3]*X)}var dr=.6-Y*Y-Z*Z-$*$-rr*rr;if(dr<0)h=0;else{var pr=q[er+1+q[tr+1+q[ar+1+q[or+1]]]]%32*4;h=(dr*=dr)*dr*(D[pr]*Y+D[pr+1]*Z+D[pr+2]*$+D[pr+3]*rr)}return 27*(n+f+s+v+h)}},i._buildPermutationTable=n,"undefined"!=typeof define&&define.amd&&define(function(){return i}),"undefined"!=typeof exports?exports.SimplexNoise=i:"undefined"!=typeof window&&(window.SimplexNoise=i),"undefined"!=typeof module&&(module.exports=i)}();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.