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: 15,202 bytes, lines 2077-2609
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) {
vendor: 9,840 bytes, lines 2610-2896
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
vendor: 4,984 bytes, lines 2897-3039
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); 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
vendor: 15,902 bytes, lines 18439-19089
18439 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: 23,480 bytes, lines 19092-20004
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() {
vendor: 13,499 bytes, lines 20005-20573
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
vendor: 38,285 bytes, lines 20574-21997
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
vendor: 29,252 bytes, lines 21998-23154
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 spaces 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 var $nav = $(opts.navSelector), 23457 $content = $(opts.contentSelector), 23458 triggerTop = $nav.is(':visible') ? $nav.offset().top : $content.offset().top + $content.outerHeight(); 23459 23460 opts.pixelsFromNavToBottom = $(document).height() - triggerTop; 23461 this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom); 23462 } 23463 23464 var self = this; 23465 23466 // determine loading.start actions 23467 opts.loading.start = opts.loading.start || function () { 23468 $(opts.navSelector).hide(); 23469 opts.loading.msg 23470 .appendTo(opts.loading.selector) 23471 .show(opts.loading.speed, $.proxy(function () { 23472 this.beginAjax(opts); 23473 }, self)); 23474 }; 23475 23476 // determine loading.finished actions 23477 opts.loading.finished = opts.loading.finished || function () { 23478 if (!opts.state.isBeyondMaxPage) 23479 opts.loading.msg.fadeOut(opts.loading.speed); 23480 }; 23481 23482 // callback loading 23483 opts.callback = function (instance, data, url) { 23484 if (!!opts.behavior && instance['_callback_' + opts.behavior] !== undefined) { 23485 instance['_callback_' + opts.behavior].call($(opts.contentSelector)[0], data, url); 23486 } 23487 23488 if (callback) { 23489 callback.call($(opts.contentSelector)[0], data, opts, url); 23490 } 23491 23492 if (opts.prefill) { 23493 $window.bind('resize.infinite-scroll', instance._prefill); 23494 } 23495 }; 23496 23497 if (options.debug) { 23498 // Tell IE9 to use its built-in console 23499 if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') { 23500 ['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd'] 23501 .forEach(function (method) { 23502 console[method] = this.call(console[method], console); 23503 }, Function.prototype.bind); 23504 } 23505 } 23506 23507 this._setup(); 23508 23509 // Setups the prefill method for use 23510 if (opts.prefill) { 23511 this._prefill(); 23512 } 23513 23514 // Return true to indicate successful creation 23515 return true; 23516 }, 23517 23518 _prefill: function infscr_prefill() { 23519 var instance = this; 23520 var $window = $(window); 23521 23522 function needsPrefill() { 23523 return ($(instance.options.contentSelector).height() <= $window.height()); 23524 } 23525 23526 this._prefill = function () { 23527 if (needsPrefill()) { 23528 instance.scroll(); 23529 } 23530 23531 $window.bind('resize.infinite-scroll', function () { 23532 if (needsPrefill()) { 23533 $window.unbind('resize.infinite-scroll'); 23534 instance.scroll(); 23535 } 23536 }); 23537 }; 23538 23539 // Call self after setting up the new function 23540 this._prefill(); 23541 }, 23542 23543 // Console log wrapper 23544 _debug: function infscr_debug() { 23545 if (true !== this.options.debug) { 23546 return; 23547 } 23548 23549 if (typeof console !== 'undefined' && typeof console.log === 'function') { 23550 // Modern browsers 23551 // Single argument, which is a string 23552 if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') { 23553 console.log((Array.prototype.slice.call(arguments)).toString()); 23554 } else { 23555 console.log(Array.prototype.slice.call(arguments)); 23556 } 23557 } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') { 23558 // IE8 23559 Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments)); 23560 } 23561 }, 23562 23563 // find the number to increment in the path.
23564 _determinepath: function infscr_determinepath(path) { 23565 23566 var opts = this.options; 23567 23568 // if behavior is defined and this function is extended, call that instead of default 23569 if (!!opts.behavior && this['_determinepath_' + opts.behavior] !== undefined) { 23570 return this['_determinepath_' + opts.behavior].call(this, path); 23571 } 23572 23573 var url = new URL(path); 23574 var pathname = url.pathname; 23575 var hasNumber = /\d/.test(pathname); 23576 23577 if (!!opts.pathParse) { 23578 this._debug('pathParse manual'); 23579 return opts.pathParse(path, this.options.state.currPage + 1); 23580 } else if (hasNumber && path.match(/(\?|\&)(upage=)(\d+)/)) { 23581 var parts = path.split(/(\?|\&)(upage=)(\d+)/); 23582 return [parts[0] + parts[1] + parts[2], parts[4]]; 23583 } else if (path.match(/^(.*?)\b2\b(.*?$)/)) { 23584 path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 23585 23586 // if there is any 2 in the url at all. 23587 } else if (path.match(/^(.*?)2(.*?$)/)) { 23588 // page= is used in django: 23589 // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127 23590 if (path.match(/^(.*?page=)2(\/.*|$)/)) { 23591 path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 23592 return path; 23593 } 23594 23595 path = path.match(/^(.*?)2(.*?$)/).slice(1); 23596 23597 } else { 23598 // page= is used in drupal too but second page is page=1 not page=2: 23599 // thx Jerod Fritz, vladikoff 23600 if (path.match(/^(.*?page=)1(\/.*|$)/)) { 23601 path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 23602 return path; 23603 } else { 23604 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."); 23605 // Get rid of isInvalidPage to allow permalink to state 23606 opts.state.isInvalidPage = true; //prevent it from running on this page. 23607 } 23608 } 23609 this._debug('determinePath', path); 23610 return path; 23611 23612 }, 23613 23614 // Custom error 23615 _error: function infscr_error(xhr) { 23616 23617 var opts = this.options; 23618 23619 // if behavior is defined and this function is extended, call that instead of default 23620 if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) { 23621 this['_error_'+opts.behavior].call(this,xhr); 23622 return; 23623 } 23624 23625 if (xhr !== 'destroy' && xhr !== 'end') { 23626 xhr = 'unknown'; 23627 } 23628 23629 this._debug('Error', xhr); 23630 23631 if (xhr === 'end' || opts.state.isBeyondMaxPage) { 23632 this._showdonemsg(); 23633 } 23634 23635 opts.state.isDone = true; 23636 opts.state.currPage = 1; // if you need to go back to this instance 23637 opts.state.isPaused = false; 23638 opts.state.isBeyondMaxPage = false; 23639 this._binding('unbind'); 23640 23641 }, 23642 23643 // Load Callback 23644 _loadcallback: function infscr_loadcallback(box, data, url) { 23645 var opts = this.options, 23646 callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK 23647 result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append', 23648 frag; 23649 23650 // if behavior is defined and this function is extended, call that instead of default 23651 if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) { 23652 this['_loadcallback_'+opts.behavior].call(this,box,data); 23653 return; 23654 } 23655 23656 switch (result) { 23657 case 'done': 23658 this._showdonemsg(); 23659 return false; 23660 23661 case 'no-append': 23662 if (opts.dataType === 'html') { 23663 data = '<div>' + data + '</div>'; 23664 data = $(data).find(opts.itemSelector); 23665 } 23666 23667 // if it didn't return anything 23668 if (data.length === 0) { 23669 return this._error('end'); 23670 } 23671 23672 break; 23673 23674 case 'append': 23675 var children = box.children(); 23676 // if it didn't return anything 23677 if (children.length === 0) { 23678 return this._error('end'); 23679 } 23680 23681 // use a documentFragment because it works when content is going into a table or UL 23682 frag = document.createDocumentFragment(); 23683 while (box[0].firstChild) { 23684 frag.appendChild(box[0].firstChild); 23685 } 23686 23687 this._debug('contentSelector', $(opts.contentSelector)[0]); 23688 $(opts.contentSelector)[0].appendChild(frag); 23689 // previously, we would pass in the new DOM element as context for the callback 23690 // however we're now using a documentfragment, which doesn't have parents or children, 23691 // so the context is the contentContainer guy, and we pass in an array 23692 // of the elements collected as the first argument. 23693 23694 data = children.get(); 23695 break; 23696 } 23697 23698 // loadingEnd function 23699 opts.loading.finished.call($(opts.contentSelector)[0],opts); 23700 23701 // smooth scroll to ease in the new content 23702 if (opts.animate) { 23703 var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px'; 23704 $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; }); 23705 } 23706 23707 if (!opts.animate) { 23708 // once the call is done, we can allow it again. 23709 opts.state.isDuringAjax = false;
23710 } 23711 23712 callback(this, data, url); 23713 23714 if (opts.prefill) { 23715 this._prefill(); 23716 } 23717 }, 23718 23719 _nearbottom: function infscr_nearbottom() { 23720 23721 var opts = this.options, 23722 pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height(); 23723 23724 // if behavior is defined and this function is extended, call that instead of default 23725 if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) { 23726 return this['_nearbottom_'+opts.behavior].call(this); 23727 } 23728 23729 this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom); 23730 23731 // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom.... 23732 return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom); 23733 23734 }, 23735 23736 // Pause / temporarily disable plugin from firing 23737 _pausing: function infscr_pausing(pause) { 23738 23739 var opts = this.options; 23740 23741 // if behavior is defined and this function is extended, call that instead of default 23742 if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) { 23743 this['_pausing_'+opts.behavior].call(this,pause); 23744 return; 23745 } 23746 23747 // If pause is not 'pause' or 'resume', toggle it's value 23748 if (pause !== 'pause' && pause !== 'resume' && pause !== null) { 23749 this._debug('Invalid argument. Toggling pause value instead'); 23750 } 23751 23752 pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle'; 23753 23754 switch (pause) { 23755 case 'pause': 23756 opts.state.isPaused = true; 23757 break; 23758 23759 case 'resume': 23760 opts.state.isPaused = false; 23761 break; 23762 23763 case 'toggle': 23764 opts.state.isPaused = !opts.state.isPaused; 23765 break; 23766 } 23767 23768 this._debug('Paused', opts.state.isPaused); 23769 return false; 23770 23771 }, 23772 23773 // Behavior is determined 23774 // If the behavior option is undefined, it will set to default and bind to scroll 23775 _setup: function infscr_setup() { 23776 23777 var opts = this.options; 23778 23779 // if behavior is defined and this function is extended, call that instead of default 23780 if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) { 23781 this['_setup_'+opts.behavior].call(this); 23782 return; 23783 } 23784 23785 this._binding('bind'); 23786 23787 return false; 23788 23789 }, 23790 23791 // Show done message 23792 _showdonemsg: function infscr_showdonemsg() { 23793 23794 var opts = this.options; 23795 23796 // if behavior is defined and this function is extended, call that instead of default 23797 if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) { 23798 this['_showdonemsg_'+opts.behavior].call(this); 23799 return; 23800 } 23801 23802 opts.loading.msg 23803 .find('img') 23804 .hide() 23805 .parent() 23806 .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () { 23807 $(this).parent().fadeOut(opts.loading.speed); 23808 }); 23809 23810 // user provided callback when done 23811 opts.errorCallback.call($(opts.contentSelector)[0],'done'); 23812 }, 23813 23814 // grab each selector option and see if any fail 23815 _validate: function infscr_validate(opts) { 23816 for (var key in opts) { 23817 if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) { 23818 this._debug('Your ' + key + ' found no elements.'); 23819 return false; 23820 } 23821 } 23822 23823 return true; 23824 }, 23825 23826 /* 23827 ---------------------------- 23828 Public methods 23829 ---------------------------- 23830 */ 23831 23832 // Bind to scroll 23833 bind: function infscr_bind() { 23834 this._binding('bind'); 23835 }, 23836 23837 // Destroy current instance of plugin 23838 destroy: function infscr_destroy() { 23839 this.options.state.isDestroyed = true; 23840 this.options.loading.finished(); 23841 return this._error('destroy'); 23842 }, 23843 23844 // Set pause value to false 23845 pause: function infscr_pause() { 23846 this._pausing('pause'); 23847 }, 23848 23849 // Set pause value to false 23850 resume: function infscr_resume() { 23851 this._pausing('resume'); 23852 }, 23853 23854 beginAjax: function infscr_ajax(opts) { 23855 var instance = this, 23856 path = opts.path, 23857 box, desturl, method, condition; 23858 23859 // increment the URL bit. e.g. /page/3/ 23860 opts.state.currPage++; 23861 23862 // Manually control maximum page 23863 if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){ 23864 opts.state.isBeyondMaxPage = true; 23865 this.destroy(); 23866 return; 23867 } 23868 23869 // if we're dealing with a table we can't use DIVs 23870 box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>'); 23871 23872 desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage); 23873 23874 instance._debug('heading into ajax', desturl); 23875 23876 method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback'; 23877 if (opts.appendCallback && opts.dataType === 'html') { 23878 method += '+callback'; 23879 } 23880 23881 switch (method) { 23882 case 'html+callback': 23883 instance._debug('Using HTML via .load() method'); 23884 box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) { 23885 instance._loadcallback(box, responseText, desturl); 23886 }); 23887 23888 break; 23889 23890 case 'html': 23891 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 23892 $.ajax({ 23893 // params 23894 url: desturl, 23895 dataType: opts.dataType, 23896 complete: function infscr_ajax_callback(jqXHR, textStatus) { 23897 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 23898 if (condition) { 23899 instance._loadcallback(box, jqXHR.responseText, desturl); 23900 } else { 23901 instance._error('end'); 23902 } 23903 } 23904 }); 23905 23906 break; 23907 case 'json': 23908 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 23909 $.ajax({ 23910 dataType: 'json', 23911 type: 'GET', 23912 url: desturl, 23913 success: function (data, textStatus, jqXHR) { 23914 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 23915 if (opts.appendCallback) { 23916 // if appendCallback is true, you must defined template in options. 23917 // note that data passed into _loadcallback is already an html (after processed in opts.template(data)). 23918 if (opts.template !== undefined) { 23919 var theData = opts.template(data); 23920 box.append(theData); 23921 if (condition) { 23922 instance._loadcallback(box, theData); 23923 } else { 23924 instance._error('end'); 23925 } 23926 } else { 23927 instance._debug('template must be defined.'); 23928 instance._error('end'); 23929 } 23930 } else { 23931 // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback. 23932 if (condition) { 23933 instance._loadcallback(box, data, desturl); 23934 } else { 23935 instance._error('end'); 23936 } 23937 } 23938 }, 23939 error: function() { 23940 instance._debug('JSON ajax request failed.'); 23941 instance._error('end'); 23942 } 23943 }); 23944 23945 break; 23946 } 23947 }, 23948 23949 // Retrieve next set of content items 23950 retrieve: function infscr_retrieve(pageNum) { 23951 pageNum = pageNum || null; 23952 23953 var instance = this, 23954 opts = instance.options; 23955 23956 // if behavior is defined and this function is extended, call that instead of default 23957 if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) { 23958 this['retrieve_'+opts.behavior].call(this,pageNum); 23959 return; 23960 } 23961 23962 // for manual triggers, if destroyed, get out of here 23963 if (opts.state.isDestroyed) { 23964 this._debug('Instance is destroyed'); 23965 return false;
23966 } 23967 23968 // we dont want to fire the ajax multiple times 23969 opts.state.isDuringAjax = true; 23970 23971 opts.loading.start.call($(opts.contentSelector)[0],opts); 23972 }, 23973 23974 // Check to see next page is needed 23975 scroll: function infscr_scroll() { 23976 23977 var opts = this.options, 23978 state = opts.state; 23979 23980 // if behavior is defined and this function is extended, call that instead of default 23981 if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) { 23982 this['scroll_'+opts.behavior].call(this); 23983 return; 23984 } 23985 23986 if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) { 23987 return; 23988 } 23989 23990 if (!this._nearbottom()) { 23991 return; 23992 } 23993 23994 this.retrieve(); 23995 23996 }, 23997 23998 // Toggle pause value 23999 toggle: function infscr_toggle() { 24000 this._pausing(); 24001 }, 24002 24003 // Unbind from scroll 24004 unbind: function infscr_unbind() { 24005 this._binding('unbind'); 24006 }, 24007 24008 // update options 24009 update: function infscr_options(key) { 24010 if ($.isPlainObject(key)) { 24011 this.options = $.extend(true,this.options,key); 24012 } 24013 } 24014 }; 24015 24016 24017 /* 24018 ---------------------------- 24019 Infinite Scroll function 24020 ---------------------------- 24021 24022 Borrowed logic from the following... 24023 24024 jQuery UI 24025 - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js 24026 24027 jCarousel 24028 - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js 24029 24030 Masonry 24031 - https://github.com/desandro/masonry/blob/master/jquery.masonry.js 24032 24033*/ 24034 24035 $.fn.infinitescroll = function infscr_init(options, callback) { 24036 24037 24038 var thisCall = typeof options; 24039 24040 switch (thisCall) { 24041 24042 // method 24043 case 'string': 24044 var args = Array.prototype.slice.call(arguments, 1); 24045 24046 this.each(function () { 24047 var instance = $.data(this, 'infinitescroll'); 24048 24049 if (!instance) { 24050 // not setup yet 24051 // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup'); 24052 return false; 24053 } 24054 24055 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') { 24056 // return $.error('No such method ' + options + ' for Infinite Scroll'); 24057 return false; 24058 } 24059 24060 // no errors! 24061 instance[options].apply(instance, args); 24062 }); 24063 24064 break; 24065 24066 // creation 24067 case 'object': 24068 24069 this.each(function () { 24070 24071 var instance = $.data(this, 'infinitescroll'); 24072 24073 if (instance) { 24074 24075 // update options of current instance 24076 instance.update(options); 24077 24078 } else { 24079 24080 // initialize new instance 24081 instance = new $.infinitescroll(options, callback, this); 24082 24083 // don't attach if instantiation failed 24084 if (!instance.failed) { 24085 $.data(this, 'infinitescroll', instance); 24086 } 24087 24088 } 24089 24090 }); 24091 24092 break; 24093 24094 } 24095 24096 return this; 24097 }; 24098 24099 24100 24101 /* 24102 * smartscroll: debounced scroll event for jQuery * 24103 * https://github.com/lukeshumard/smartscroll 24104 * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js * 24105 * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. * 24106 */ 24107 24108 var event = $.event, 24109 scrollTimeout; 24110 24111 event.special.smartscroll = { 24112 setup: function () { 24113 $(this).bind('scroll', event.special.smartscroll.handler); 24114 }, 24115 teardown: function () { 24116 $(this).unbind('scroll', event.special.smartscroll.handler); 24117 }, 24118 handler: function (event, execAsap) { 24119 // Save the context 24120 var context = this, 24121 args = arguments; 24122 24123 // set correct event type 24124 event.type = 'smartscroll'; 24125 24126 if (scrollTimeout) { clearTimeout(scrollTimeout); } 24127 scrollTimeout = setTimeout(function () { 24128 $(context).trigger('smartscroll', args); 24129 }, execAsap === 'execAsap' ? 0 : 100); 24130 } 24131 }; 24132 24133 $.fn.smartscroll = function (fn) {
24134 return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']); 24135 }; 24136 24137})); 24138 24139/*! 24140Waypoints - 4.0.1 24141Copyright © 2011-2016 Caleb Troughton 24142Licensed under the MIT license. 24143https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 24144*/ 24145(function() { 24146 'use strict' 24147 24148 var keyCounter = 0 24149 var allWaypoints = {} 24150 24151 /* http://imakewebthings.com/waypoints/api/waypoint */ 24152 function Waypoint(options) { 24153 if (!options) { 24154 throw new Error('No options passed to Waypoint constructor') 24155 } 24156 if (!options.element) { 24157 throw new Error('No element option passed to Waypoint constructor') 24158 } 24159 if (!options.handler) { 24160 throw new Error('No handler option passed to Waypoint constructor') 24161 } 24162 24163 this.key = 'waypoint-' + keyCounter 24164 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 24165 this.element = this.options.element 24166 this.adapter = new Waypoint.Adapter(this.element) 24167 this.callback = options.handler 24168 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 24169 this.enabled = this.options.enabled 24170 this.triggerPoint = null 24171 this.group = Waypoint.Group.findOrCreate({ 24172 name: this.options.group, 24173 axis: this.axis 24174 }) 24175 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 24176 24177 if (Waypoint.offsetAliases[this.options.offset]) { 24178 this.options.offset = Waypoint.offsetAliases[this.options.offset] 24179 } 24180 this.group.add(this) 24181 this.context.add(this) 24182 allWaypoints[this.key] = this 24183 keyCounter += 1 24184 } 24185 24186 /* Private */ 24187 Waypoint.prototype.queueTrigger = function(direction) { 24188 this.group.queueTrigger(this, direction) 24189 } 24190 24191 /* Private */ 24192 Waypoint.prototype.trigger = function(args) { 24193 if (!this.enabled) { 24194 return 24195 } 24196 if (this.callback) { 24197 this.callback.apply(this, args) 24198 } 24199 } 24200 24201 /* Public */ 24202 /* http://imakewebthings.com/waypoints/api/destroy */ 24203 Waypoint.prototype.destroy = function() { 24204 this.context.remove(this) 24205 this.group.remove(this) 24206 delete allWaypoints[this.key] 24207 } 24208 24209 /* Public */ 24210 /* http://imakewebthings.com/waypoints/api/disable */ 24211 Waypoint.prototype.disable = function() { 24212 this.enabled = false 24213 return this 24214 } 24215 24216 /* Public */ 24217 /* http://imakewebthings.com/waypoints/api/enable */ 24218 Waypoint.prototype.enable = function() { 24219 this.context.refresh() 24220 this.enabled = true 24221 return this 24222 } 24223 24224 /* Public */ 24225 /* http://imakewebthings.com/waypoints/api/next */ 24226 Waypoint.prototype.next = function() { 24227 return this.group.next(this) 24228 } 24229 24230 /* Public */ 24231 /* http://imakewebthings.com/waypoints/api/previous */ 24232 Waypoint.prototype.previous = function() { 24233 return this.group.previous(this) 24234 } 24235 24236 /* Private */ 24237 Waypoint.invokeAll = function(method) { 24238 var allWaypointsArray = []
24239 for (var waypointKey in allWaypoints) { 24240 allWaypointsArray.push(allWaypoints[waypointKey]) 24241 } 24242 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 24243 allWaypointsArray[i][method]() 24244 } 24245 } 24246 24247 /* Public */ 24248 /* http://imakewebthings.com/waypoints/api/destroy-all */ 24249 Waypoint.destroyAll = function() { 24250 Waypoint.invokeAll('destroy') 24251 } 24252 24253 /* Public */ 24254 /* http://imakewebthings.com/waypoints/api/disable-all */ 24255 Waypoint.disableAll = function() { 24256 Waypoint.invokeAll('disable') 24257 } 24258 24259 /* Public */ 24260 /* http://imakewebthings.com/waypoints/api/enable-all */ 24261 Waypoint.enableAll = function() { 24262 Waypoint.Context.refreshAll() 24263 for (var waypointKey in allWaypoints) { 24264 allWaypoints[waypointKey].enabled = true 24265 } 24266 return this 24267 } 24268 24269 /* Public */ 24270 /* http://imakewebthings.com/waypoints/api/refresh-all */ 24271 Waypoint.refreshAll = function() { 24272 Waypoint.Context.refreshAll() 24273 } 24274 24275 /* Public */ 24276 /* http://imakewebthings.com/waypoints/api/viewport-height */ 24277 Waypoint.viewportHeight = function() { 24278 return window.innerHeight || document.documentElement.clientHeight 24279 } 24280 24281 /* Public */ 24282 /* http://imakewebthings.com/waypoints/api/viewport-width */ 24283 Waypoint.viewportWidth = function() { 24284 return document.documentElement.clientWidth 24285 } 24286 24287 Waypoint.adapters = [] 24288 24289 Waypoint.defaults = { 24290 context: window, 24291 continuous: true, 24292 enabled: true, 24293 group: 'default', 24294 horizontal: false, 24295 offset: 0 24296 } 24297 24298 Waypoint.offsetAliases = { 24299 'bottom-in-view': function() { 24300 return this.context.innerHeight() - this.adapter.outerHeight() 24301 }, 24302 'right-in-view': function() { 24303 return this.context.innerWidth() - this.adapter.outerWidth() 24304 } 24305 } 24306 24307 window.Waypoint = Waypoint 24308}()) 24309;(function() { 24310 'use strict' 24311 24312 function requestAnimationFrameShim(callback) { 24313 window.setTimeout(callback, 1000 / 60) 24314 } 24315 24316 var keyCounter = 0 24317 var contexts = {} 24318 var Waypoint = window.Waypoint 24319 var oldWindowLoad = window.onload 24320 24321 /* http://imakewebthings.com/waypoints/api/context */ 24322 function Context(element) { 24323 this.element = element 24324 this.Adapter = Waypoint.Adapter 24325 this.adapter = new this.Adapter(element) 24326 this.key = 'waypoint-context-' + keyCounter 24327 this.didScroll = false 24328 this.didResize = false 24329 this.oldScroll = { 24330 x: this.adapter.scrollLeft(), 24331 y: this.adapter.scrollTop() 24332 } 24333 this.waypoints = { 24334 vertical: {}, 24335 horizontal: {} 24336 } 24337 24338 element.waypointContextKey = this.key 24339 contexts[element.waypointContextKey] = this 24340 keyCounter += 1 24341 if (!Waypoint.windowContext) { 24342 Waypoint.windowContext = true 24343 Waypoint.windowContext = new Context(window) 24344 } 24345 24346 this.createThrottledScrollHandler() 24347 this.createThrottledResizeHandler() 24348 } 24349 24350 /* Private */ 24351 Context.prototype.add = function(waypoint) { 24352 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 24353 this.waypoints[axis][waypoint.key] = waypoint 24354 this.refresh() 24355 } 24356 24357 /* Private */ 24358 Context.prototype.checkEmpty = function() { 24359 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 24360 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 24361 var isWindow = this.element == this.element.window 24362 if (horizontalEmpty && verticalEmpty && !isWindow) { 24363 this.adapter.off('.waypoints') 24364 delete contexts[this.key] 24365 } 24366 } 24367 24368 /* Private */ 24369 Context.prototype.createThrottledResizeHandler = function() { 24370 var self = this 24371 24372 function resizeHandler() { 24373 self.handleResize() 24374 self.didResize = false 24375 } 24376 24377 this.adapter.on('resize.waypoints', function() { 24378 if (!self.didResize) { 24379 self.didResize = true 24380 Waypoint.requestAnimationFrame(resizeHandler) 24381 } 24382 }) 24383 } 24384 24385 /* Private */ 24386 Context.prototype.createThrottledScrollHandler = function() { 24387 var self = this 24388 function scrollHandler() { 24389 self.handleScroll() 24390 self.didScroll = false 24391 } 24392 24393 this.adapter.on('scroll.waypoints', function() { 24394 if (!self.didScroll || Waypoint.isTouch) { 24395 self.didScroll = true 24396 Waypoint.requestAnimationFrame(scrollHandler) 24397 } 24398 }) 24399 } 24400 24401 /* Private */ 24402 Context.prototype.handleResize = function() { 24403 Waypoint.Context.refreshAll() 24404 } 24405 24406 /* Private */ 24407 Context.prototype.handleScroll = function() { 24408 var triggeredGroups = {} 24409 var axes = { 24410 horizontal: { 24411 newScroll: this.adapter.scrollLeft(), 24412 oldScroll: this.oldScroll.x, 24413 forward: 'right', 24414 backward: 'left' 24415 }, 24416 vertical: { 24417 newScroll: this.adapter.scrollTop(), 24418 oldScroll: this.oldScroll.y, 24419 forward: 'down', 24420 backward: 'up' 24421 } 24422 } 24423 24424 for (var axisKey in axes) { 24425 var axis = axes[axisKey] 24426 var isForward = axis.newScroll > axis.oldScroll 24427 var direction = isForward ? axis.forward : axis.backward 24428
24429 for (var waypointKey in this.waypoints[axisKey]) { 24430 var waypoint = this.waypoints[axisKey][waypointKey] 24431 if (waypoint.triggerPoint === null) { 24432 continue 24433 } 24434 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 24435 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 24436 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 24437 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 24438 if (crossedForward || crossedBackward) { 24439 waypoint.queueTrigger(direction) 24440 triggeredGroups[waypoint.group.id] = waypoint.group 24441 } 24442 } 24443 } 24444 24445 for (var groupKey in triggeredGroups) { 24446 triggeredGroups[groupKey].flushTriggers() 24447 } 24448 24449 this.oldScroll = { 24450 x: axes.horizontal.newScroll, 24451 y: axes.vertical.newScroll 24452 } 24453 } 24454 24455 /* Private */ 24456 Context.prototype.innerHeight = function() { 24457 /*eslint-disable eqeqeq */ 24458 if (this.element == this.element.window) { 24459 return Waypoint.viewportHeight() 24460 } 24461 /*eslint-enable eqeqeq */ 24462 return this.adapter.innerHeight() 24463 } 24464 24465 /* Private */ 24466 Context.prototype.remove = function(waypoint) { 24467 delete this.waypoints[waypoint.axis][waypoint.key] 24468 this.checkEmpty() 24469 } 24470 24471 /* Private */ 24472 Context.prototype.innerWidth = function() { 24473 /*eslint-disable eqeqeq */ 24474 if (this.element == this.element.window) { 24475 return Waypoint.viewportWidth() 24476 } 24477 /*eslint-enable eqeqeq */ 24478 return this.adapter.innerWidth() 24479 } 24480 24481 /* Public */ 24482 /* http://imakewebthings.com/waypoints/api/context-destroy */ 24483 Context.prototype.destroy = function() { 24484 var allWaypoints = [] 24485 for (var axis in this.waypoints) {
24486 for (var waypointKey in this.waypoints[axis]) { 24487 allWaypoints.push(this.waypoints[axis][waypointKey]) 24488 } 24489 } 24490 for (var i = 0, end = allWaypoints.length; i < end; i++) { 24491 allWaypoints[i].destroy() 24492 } 24493 } 24494 24495 /* Public */ 24496 /* http://imakewebthings.com/waypoints/api/context-refresh */ 24497 Context.prototype.refresh = function() { 24498 /*eslint-disable eqeqeq */ 24499 var isWindow = this.element == this.element.window 24500 /*eslint-enable eqeqeq */ 24501 var contextOffset = isWindow ? undefined : this.adapter.offset() 24502 var triggeredGroups = {} 24503 var axes 24504 24505 this.handleScroll() 24506 axes = { 24507 horizontal: { 24508 contextOffset: isWindow ? 0 : contextOffset.left, 24509 contextScroll: isWindow ? 0 : this.oldScroll.x, 24510 contextDimension: this.innerWidth(), 24511 oldScroll: this.oldScroll.x, 24512 forward: 'right', 24513 backward: 'left', 24514 offsetProp: 'left' 24515 }, 24516 vertical: { 24517 contextOffset: isWindow ? 0 : contextOffset.top, 24518 contextScroll: isWindow ? 0 : this.oldScroll.y, 24519 contextDimension: this.innerHeight(), 24520 oldScroll: this.oldScroll.y, 24521 forward: 'down', 24522 backward: 'up', 24523 offsetProp: 'top' 24524 } 24525 } 24526 24527 for (var axisKey in axes) { 24528 var axis = axes[axisKey]
24529 for (var waypointKey in this.waypoints[axisKey]) { 24530 var waypoint = this.waypoints[axisKey][waypointKey] 24531 var adjustment = waypoint.options.offset 24532 var oldTriggerPoint = waypoint.triggerPoint 24533 var elementOffset = 0 24534 var freshWaypoint = oldTriggerPoint == null 24535 var contextModifier, wasBeforeScroll, nowAfterScroll 24536 var triggeredBackward, triggeredForward 24537 24538 if (waypoint.element !== waypoint.element.window) { 24539 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 24540 } 24541 24542 if (typeof adjustment === 'function') { 24543 adjustment = adjustment.apply(waypoint) 24544 } 24545 else if (typeof adjustment === 'string') { 24546 adjustment = parseFloat(adjustment) 24547 if (waypoint.options.offset.indexOf('%') > - 1) { 24548 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 24549 } 24550 } 24551 24552 contextModifier = axis.contextScroll - axis.contextOffset 24553 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 24554 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 24555 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 24556 triggeredBackward = wasBeforeScroll && nowAfterScroll 24557 triggeredForward = !wasBeforeScroll && !nowAfterScroll 24558 24559 if (!freshWaypoint && triggeredBackward) { 24560 waypoint.queueTrigger(axis.backward) 24561 triggeredGroups[waypoint.group.id] = waypoint.group 24562 } 24563 else if (!freshWaypoint && triggeredForward) { 24564 waypoint.queueTrigger(axis.forward) 24565 triggeredGroups[waypoint.group.id] = waypoint.group 24566 } 24567 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 24568 waypoint.queueTrigger(axis.forward) 24569 triggeredGroups[waypoint.group.id] = waypoint.group 24570 } 24571 } 24572 } 24573 24574 Waypoint.requestAnimationFrame(function() { 24575 for (var groupKey in triggeredGroups) { 24576 triggeredGroups[groupKey].flushTriggers() 24577 } 24578 }) 24579 24580 return this 24581 } 24582 24583 /* Private */ 24584 Context.findOrCreateByElement = function(element) { 24585 return Context.findByElement(element) || new Context(element) 24586 } 24587 24588 /* Private */ 24589 Context.refreshAll = function() { 24590 for (var contextId in contexts) { 24591 contexts[contextId].refresh() 24592 } 24593 } 24594 24595 /* Public */ 24596 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 24597 Context.findByElement = function(element) { 24598 return contexts[element.waypointContextKey] 24599 } 24600 24601 window.onload = function() { 24602 if (oldWindowLoad) { 24603 oldWindowLoad() 24604 } 24605 Context.refreshAll() 24606 } 24607 24608 24609 Waypoint.requestAnimationFrame = function(callback) { 24610 var requestFn = window.requestAnimationFrame || 24611 window.mozRequestAnimationFrame || 24612 window.webkitRequestAnimationFrame || 24613 requestAnimationFrameShim 24614 requestFn.call(window, callback) 24615 } 24616 Waypoint.Context = Context 24617}()) 24618;(function() { 24619 'use strict' 24620 24621 function byTriggerPoint(a, b) { 24622 return a.triggerPoint - b.triggerPoint 24623 } 24624 24625 function byReverseTriggerPoint(a, b) { 24626 return b.triggerPoint - a.triggerPoint 24627 } 24628 24629 var groups = { 24630 vertical: {}, 24631 horizontal: {} 24632 } 24633 var Waypoint = window.Waypoint 24634 24635 /* http://imakewebthings.com/waypoints/api/group */ 24636 function Group(options) { 24637 this.name = options.name 24638 this.axis = options.axis 24639 this.id = this.name + '-' + this.axis 24640 this.waypoints = [] 24641 this.clearTriggerQueues() 24642 groups[this.axis][this.name] = this 24643 } 24644 24645 /* Private */ 24646 Group.prototype.add = function(waypoint) { 24647 this.waypoints.push(waypoint) 24648 } 24649 24650 /* Private */ 24651 Group.prototype.clearTriggerQueues = function() { 24652 this.triggerQueues = { 24653 up: [], 24654 down: [], 24655 left: [], 24656 right: [] 24657 } 24658 } 24659 24660 /* Private */ 24661 Group.prototype.flushTriggers = function() { 24662 for (var direction in this.triggerQueues) { 24663 var waypoints = this.triggerQueues[direction] 24664 var reverse = direction === 'up' || direction === 'left' 24665 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 24666 for (var i = 0, end = waypoints.length; i < end; i += 1) { 24667 var waypoint = waypoints[i] 24668 if (waypoint.options.continuous || i === waypoints.length - 1) { 24669 waypoint.trigger([direction]) 24670 } 24671 } 24672 } 24673 this.clearTriggerQueues() 24674 } 24675 24676 /* Private */ 24677 Group.prototype.next = function(waypoint) { 24678 this.waypoints.sort(byTriggerPoint) 24679 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 24680 var isLast = index === this.waypoints.length - 1 24681 return isLast ? null : this.waypoints[index + 1] 24682 } 24683 24684 /* Private */ 24685 Group.prototype.previous = function(waypoint) { 24686 this.waypoints.sort(byTriggerPoint) 24687 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 24688 return index ? this.waypoints[index - 1] : null 24689 } 24690 24691 /* Private */ 24692 Group.prototype.queueTrigger = function(waypoint, direction) { 24693 this.triggerQueues[direction].push(waypoint) 24694 } 24695 24696 /* Private */ 24697 Group.prototype.remove = function(waypoint) { 24698 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 24699 if (index > -1) { 24700 this.waypoints.splice(index, 1) 24701 } 24702 } 24703 24704 /* Public */ 24705 /* http://imakewebthings.com/waypoints/api/first */ 24706 Group.prototype.first = function() { 24707 return this.waypoints[0] 24708 } 24709 24710 /* Public */ 24711 /* http://imakewebthings.com/waypoints/api/last */ 24712 Group.prototype.last = function() { 24713 return this.waypoints[this.waypoints.length - 1] 24714 } 24715 24716 /* Private */ 24717 Group.findOrCreate = function(options) { 24718 return groups[options.axis][options.name] || new Group(options) 24719 } 24720 24721 Waypoint.Group = Group 24722}()) 24723;(function() { 24724 'use strict' 24725 24726 var $ = window.jQuery 24727 var Waypoint = window.Waypoint 24728 24729 function JQueryAdapter(element) { 24730 this.$element = $(element) 24731 } 24732 24733 $.each([
24734 'innerHeight', 24735 'innerWidth', 24736 'off', 24737 'offset', 24738 'on', 24739 'outerHeight', 24740 'outerWidth', 24741 'scrollLeft', 24742 'scrollTop' 24743 ], function(i, method) { 24744 JQueryAdapter.prototype[method] = function() { 24745 var args = Array.prototype.slice.call(arguments) 24746 return this.$element[method].apply(this.$element, args) 24747 } 24748 }) 24749 24750 $.each([ 24751 'extend', 24752 'inArray', 24753 'isEmptyObject' 24754 ], function(i, method) { 24755 JQueryAdapter[method] = $[method] 24756 }) 24757 24758 Waypoint.adapters.push({ 24759 name: 'jquery', 24760 Adapter: JQueryAdapter 24761 }) 24762 Waypoint.Adapter = JQueryAdapter 24763}()) 24764;(function() { 24765 'use strict' 24766 24767 var Waypoint = window.Waypoint 24768 24769 function createExtension(framework) { 24770 return function() { 24771 var waypoints = [] 24772 var overrides = arguments[0] 24773 24774 if (framework.isFunction(arguments[0])) { 24775 overrides = framework.extend({}, arguments[1]) 24776 overrides.handler = arguments[0] 24777 } 24778 24779 this.each(function() { 24780 var options = framework.extend({}, overrides, { 24781 element: this 24782 }) 24783 if (typeof options.context === 'string') { 24784 options.context = framework(this).closest(options.context)[0] 24785 } 24786 waypoints.push(new Waypoint(options)) 24787 }) 24788 24789 return waypoints 24790 } 24791 } 24792 24793 if (window.jQuery) { 24794 window.jQuery.fn.waypoint = createExtension(window.jQuery) 24795 } 24796 if (window.Zepto) { 24797 window.Zepto.fn.waypoint = createExtension(window.Zepto) 24798 } 24799}()) 24800; 24801/*! 24802Waypoints Inview Shortcut - 4.0.1 24803Copyright © 2011-2016 Caleb Troughton 24804Licensed under the MIT license. 24805https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 24806*/ 24807(function() { 24808 'use strict' 24809 24810 function noop() {} 24811 24812 var Waypoint = window.Waypoint 24813 24814 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 24815 function Inview(options) { 24816 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 24817 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 24818 this.waypoints = [] 24819 this.element = this.options.element 24820 this.createWaypoints() 24821 } 24822 24823 /* Private */ 24824 Inview.prototype.createWaypoints = function() { 24825 var configs = { 24826 vertical: [{ 24827 down: 'enter', 24828 up: 'exited', 24829 offset: '100%' 24830 }, { 24831 down: 'entered', 24832 up: 'exit', 24833 offset: 'bottom-in-view' 24834 }, { 24835 down: 'exit', 24836 up: 'entered', 24837 offset: 0 24838 }, { 24839 down: 'exited', 24840 up: 'enter', 24841 offset: function() { 24842 return -this.adapter.outerHeight() 24843 } 24844 }], 24845 horizontal: [{ 24846 right: 'enter', 24847 left: 'exited', 24848 offset: '100%' 24849 }, { 24850 right: 'entered', 24851 left: 'exit', 24852 offset: 'right-in-view' 24853 }, { 24854 right: 'exit', 24855 left: 'entered', 24856 offset: 0 24857 }, { 24858 right: 'exited', 24859 left: 'enter', 24860 offset: function() { 24861 return -this.adapter.outerWidth() 24862 } 24863 }] 24864 } 24865 24866 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 24867 var config = configs[this.axis][i] 24868 this.createWaypoint(config) 24869 } 24870 } 24871 24872 /* Private */ 24873 Inview.prototype.createWaypoint = function(config) { 24874 var self = this 24875 this.waypoints.push(new Waypoint({ 24876 context: this.options.context, 24877 element: this.options.element, 24878 enabled: this.options.enabled, 24879 handler: (function(config) { 24880 return function(direction) { 24881 self.options[config[direction]].call(self, direction) 24882 } 24883 }(config)), 24884 offset: config.offset, 24885 horizontal: this.options.horizontal 24886 })) 24887 } 24888 24889 /* Public */ 24890 Inview.prototype.destroy = function() { 24891 for (var i = 0, end = this.waypoints.length; i < end; i++) { 24892 this.waypoints[i].destroy() 24893 } 24894 this.waypoints = [] 24895 } 24896 24897 Inview.prototype.disable = function() { 24898 for (var i = 0, end = this.waypoints.length; i < end; i++) { 24899 this.waypoints[i].disable() 24900 } 24901 } 24902 24903 Inview.prototype.enable = function() { 24904 for (var i = 0, end = this.waypoints.length; i < end; i++) { 24905 this.waypoints[i].enable() 24906 } 24907 } 24908 24909 Inview.defaults = { 24910 context: window, 24911 enabled: true, 24912 enter: noop, 24913 entered: noop,
24914 exit: noop, 24915 exited: noop 24916 } 24917 24918 Waypoint.Inview = Inview 24919}()) 24920; 24921 24922/* 24923 * SmartMenus jQuery v0.9.6 24924 * http://www.smartmenus.org/ 24925 * 24926 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 24927 * http://vadikom.com/ 24928 * 24929 * Released under the MIT license: 24930 * http://www.opensource.org/licenses/MIT 24931 */ 24932 24933(function($) { 24934 24935 var menuTrees = [], 24936 IE = !!window.createPopup, // we need to detect it, unfortunately 24937 IElt9 = IE && !document.defaultView, 24938 IElt8 = IE && !document.querySelector, 24939 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 24940 mouse = false, // optimize for touch by default - we will detect for mouse input 24941 mouseDetectionEnabled = false; 24942 24943 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 24944 function initMouseDetection(disable) { 24945 if (!mouseDetectionEnabled && !disable) { 24946 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 24947 // 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) 24948 var firstTime = true, 24949 lastMove = null; 24950 $(document).bind({ 24951 'mousemove.smartmenus_mouse': function(e) { 24952 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 24953 if (lastMove) { 24954 var deltaX = Math.abs(lastMove.x - thisMove.x), 24955 deltaY = Math.abs(lastMove.y - thisMove.y); 24956 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 24957 mouse = true; 24958 // 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 24959 if (firstTime) { 24960 var $a = $(e.target).closest('a'); 24961 if ($a.is('a')) { 24962 $.each(menuTrees, function() { 24963 if ($.contains(this.$root[0], $a[0])) { 24964 this.itemEnter({ currentTarget: $a[0] }); 24965 return false; 24966 } 24967 }); 24968 } 24969 firstTime = false; 24970 } 24971 } 24972 } 24973 lastMove = thisMove; 24974 }, 24975 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 24976 if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) { 24977 mouse = false; 24978 } 24979 } 24980 }); 24981 mouseDetectionEnabled = true; 24982 } else if (mouseDetectionEnabled && disable) { 24983 $(document).unbind('.smartmenus_mouse'); 24984 mouseDetectionEnabled = false; 24985 } 24986 }; 24987 24988 $.SmartMenus = function(elm, options) { 24989 this.$root = $(elm); 24990 this.opts = options; 24991 this.rootId = ''; // internal 24992 this.$subArrow = null; 24993 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) 24994 this.activatedItems = []; // stores last activated A's for each level 24995 this.visibleSubMenus = []; // stores visible sub menus UL's 24996 this.showTimeout = 0; 24997 this.hideTimeout = 0; 24998 this.scrollTimeout = 0; 24999 this.clickActivated = false; 25000 this.zIndexInc = 0; 25001 this.$firstLink = null; // we'll use these for some tests 25002 this.$firstSub = null; // at runtime so we'll cache them 25003 this.disabled = false; 25004 this.$disableOverlay = null; 25005 this.lastLevel = 0; 25006 this.init(); 25007 }; 25008 25009 $.extend($.SmartMenus, { 25010 hideAll: function() { 25011 $.each(menuTrees, function() { 25012 this.menuHideAll(); 25013 }); 25014 }, 25015 destroy: function() { 25016 while (menuTrees.length) { 25017 menuTrees[0].destroy(); 25018 } 25019 initMouseDetection(true); 25020 }, 25021 prototype: { 25022 init: function(refresh) { 25023 var self = this; 25024 25025 if (!refresh) { 25026 menuTrees.push(this); 25027 25028 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 25029 25030 if (this.$root.hasClass('sm-rtl')) { 25031 this.opts.rightToLeftSubMenus = true; 25032 } 25033 25034 // init root (main menu) 25035 this.$root 25036 .data('smartmenus', this) 25037 .attr('data-smartmenus-id', this.rootId) 25038 .dataSM('level', 1) 25039 .bind({ 25040 // 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
25041 // 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 25042 'mouseover.smartmenus': $.proxy(this.rootOver, this), 25043 'mouseout.smartmenus': $.proxy(this.rootOut, this) 25044 }) 25045 .delegate('a, div.logo-container', { 25046 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 25047 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 25048 'mousedown.smartmenus': $.proxy(this.itemDown, this), 25049 'focus.smartmenus': $.proxy(this.itemFocus, this), 25050 'blur.smartmenus': $.proxy(this.itemBlur, this), 25051 'click.smartmenus': $.proxy(this.itemClick, this), 25052 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 25053 }); 25054 25055 var eNamespace = '.smartmenus' + this.rootId; 25056 // hide menus on tap or click outside the root UL 25057 if (this.opts.hideOnClick) { 25058 $(document).on('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 25059 .on('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 25060 .on('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 25061 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 25062 .on('click' + eNamespace, $.proxy(this.docClick, this)); 25063 } 25064 // hide sub menus on resize 25065 $(window).on('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 25066 var $vmenu = $('body.vmenu .vmenu-container'); 25067 if ( ! $vmenu.length && UNCODE.wwidth > UNCODE.mediaQuery ) { 25068 $(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 25069 } 25070 25071 if (this.opts.subIndicators) { 25072 this.$subArrow = $('<span/>').addClass('sub-arrow'); 25073 if (this.opts.subIndicatorsText) { 25074 this.$subArrow.html(this.opts.subIndicatorsText); 25075 } 25076 } 25077 25078 // make sure mouse detection is enabled 25079 initMouseDetection(); 25080 } 25081 25082 // init sub menus 25083 this.$firstSub = this.$root.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').each(function() { self.menuInit($(this)); }).eq(0); 25084 25085 this.$firstLink = this.$root.find('a').eq(0); 25086 25087 // find current item 25088 if (this.opts.markCurrentItem) { 25089 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 25090 reHash = /#.*/, 25091 locHref = window.location.href.replace(reDefaultDoc, ''), 25092 locHrefNoHash = locHref.replace(reHash, ''); 25093 this.$root.find('a').each(function() { 25094 var href = this.href.replace(reDefaultDoc, ''), 25095 $this = $(this); 25096 if (href == locHref || href == locHrefNoHash) { 25097 $this.addClass('current'); 25098 if (self.opts.markCurrentTree) { 25099 $this.parents('li').each(function() { 25100 var $this = $(this); 25101 if ($this.dataSM('sub')) { 25102 $this.children('a').addClass('current'); 25103 } 25104 }); 25105 } 25106 } 25107 }); 25108 } 25109 }, 25110 destroy: function() { 25111 this.menuHideAll(); 25112 this.$root 25113 .removeData('smartmenus') 25114 .removeAttr('data-smartmenus-id') 25115 .removeDataSM('level') 25116 .unbind('.smartmenus') 25117 .undelegate('.smartmenus'); 25118 var eNamespace = '.smartmenus' + this.rootId; 25119 $(document).unbind(eNamespace); 25120 $(window).unbind(eNamespace); 25121 if (this.opts.subIndicators) { 25122 this.$subArrow = null; 25123 } 25124 var self = this; 25125 $.each(this.subMenus, function() { 25126 if (this.hasClass('mega-menu')) { 25127 this.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').removeDataSM('in-mega'); 25128 } 25129 if (this.dataSM('shown-before')) { 25130 if (IElt8) { 25131 this.children().css({ styleFloat: '', width: '' }); 25132 } 25133 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 25134 if (!IE6) { 25135 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 25136 } else { 25137 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 25138 } 25139 } 25140 if (this.dataSM('scroll-arrows')) { 25141 this.dataSM('scroll-arrows').remove(); 25142 } 25143 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 25144 } 25145 if (self.opts.subIndicators) { 25146 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 25147 } 25148 this.removeDataSM('shown-before') 25149 .removeDataSM('ie-shim') 25150 .removeDataSM('scroll-arrows') 25151 .removeDataSM('parent-a') 25152 .removeDataSM('level') 25153 .removeDataSM('beforefirstshowfired') 25154 .parent().removeDataSM('sub'); 25155 }); 25156 if (this.opts.markCurrentItem) { 25157 this.$root.find('a.current').removeClass('current'); 25158 } 25159 this.$root = null; 25160 this.$firstLink = null; 25161 this.$firstSub = null; 25162 if (this.$disableOverlay) { 25163 this.$disableOverlay.remove(); 25164 this.$disableOverlay = null; 25165 } 25166 menuTrees.splice($.inArray(this, menuTrees), 1); 25167 }, 25168 disable: function(noOverlay) { 25169 if (!this.disabled) { 25170 this.menuHideAll(); 25171 // display overlay over the menu to prevent interaction 25172 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 25173 var pos = this.$root.offset(); 25174 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 25175 position: 'absolute', 25176 top: pos.top, 25177 left: pos.left, 25178 width: this.$root.outerWidth(), 25179 height: this.$root.outerHeight(),
25180 zIndex: this.getStartZIndex() + 1, 25181 opacity: 0 25182 }).appendTo(document.body); 25183 } 25184 this.disabled = true; 25185 } 25186 }, 25187 docClick: function(e) { 25188 // hide on any click outside the menu or on a menu link 25189 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a:not([data-filter])')) { 25190 this.menuHideAll($(e.target)); 25191 } 25192 }, 25193 docTouchEnd: function(e) { 25194 if (!this.lastTouch) { 25195 return; 25196 } 25197 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))) { 25198 if (this.hideTimeout) { 25199 clearTimeout(this.hideTimeout); 25200 this.hideTimeout = 0; 25201 } 25202 // hide with a delay to prevent triggering accidental unwanted click on some page element 25203 var self = this; 25204 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 25205 } 25206 this.lastTouch = null; 25207 }, 25208 docTouchMove: function(e) { 25209 if (!this.lastTouch) { 25210 return; 25211 } 25212 var touchPoint = e.originalEvent.touches[0]; 25213 this.lastTouch.x2 = touchPoint.pageX; 25214 this.lastTouch.y2 = touchPoint.pageY; 25215 }, 25216 docTouchStart: function(e) { 25217 var touchPoint = e.originalEvent.touches[0]; 25218 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 25219 }, 25220 enable: function() { 25221 if (this.disabled) { 25222 if (this.$disableOverlay) { 25223 this.$disableOverlay.remove(); 25224 this.$disableOverlay = null; 25225 } 25226 this.disabled = false; 25227 } 25228 }, 25229 getHeight: function($elm) { 25230 return this.getOffset($elm, true); 25231 }, 25232 // returns precise width/height float values in IE9+, FF4+, recent WebKit 25233 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 25234 getOffset: function($elm, height) { 25235 var old, 25236 $win = $(window), 25237 winW = $win.width(); 25238 if ($elm.css('display') == 'none') { 25239 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 25240 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 25241 if ( 25242 ($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length) 25243 || 25244 (( $('body').hasClass('vmenu-offcanvas-overlay') || $('body').hasClass('vmenu') ) && winW >= 960 && $elm.closest('.main-menu-container').length && !$elm.closest('.menu-horizontal-inner').length) 25245 ) { 25246 $elm.closest('li').addClass('smartmenu-open-item'); 25247 } 25248 } 25249 var defaultView = $elm[0].ownerDocument.defaultView, 25250 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 25251 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 25252 if (val) { 25253 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 25254 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 25255 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 25256 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 25257 } else { 25258 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 25259 } 25260 if (old) { 25261 $elm.hide().css(old); 25262 } 25263 return val; 25264 }, 25265 getWidth: function($elm) { 25266 return this.getOffset($elm); 25267 }, 25268 getStartZIndex: function() { 25269 var zIndex = parseInt(this.$root.css('z-index')); 25270 return !isNaN(zIndex) ? zIndex : 1; 25271 }, 25272 handleEvents: function() { 25273 return !this.disabled && this.isCSSOn(); 25274 }, 25275 handleItemEvents: function($a) { 25276 return this.handleEvents() && !this.isLinkInMegaMenu($a); 25277 }, 25278 isCollapsible: function() { 25279 return this.$firstSub.css('position') == 'static'; 25280 }, 25281 isCSSOn: function() { 25282 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'; 25283 }, 25284 isFixed: function() { 25285 return this.$root.css('position') == 'fixed'; 25286 }, 25287 isLinkInMegaMenu: function($a) { 25288 return !$a.parent().parent().dataSM('level'); 25289 }, 25290 isTouchMode: function() { 25291 return !mouse || this.isCollapsible(); 25292 }, 25293 itemActivate: function($a, $show) { 25294 var $li = $a.parent(), 25295 $ul = $li.parent(), 25296 level = $ul.dataSM('level'), 25297 winh = $(window).height(); 25298 // 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 25299 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 25300 var self = this; 25301 $($ul.parentsUntil('[data-smartmenus-id]', 'ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').get().reverse()).add($ul).each(function() { 25302 self.itemActivate($(this).dataSM('parent-a')); 25303 }); 25304 } 25305 // hide any visible deeper level sub menus 25306 if (this.visibleSubMenus.length > level) { 25307 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--) { 25308 this.lastLevel = level; 25309 if ( typeof $show === 'undefined' && this.isCollapsible() ) { 25310 this.menuHide(this.visibleSubMenus[i], $a); 25311 return; 25312 } else { 25313 this.menuHide(this.visibleSubMenus[i]); 25314 } 25315 } 25316 } 25317 // save new active item and sub menu for this level 25318 this.activatedItems[level - 1] = $a; 25319 this.visibleSubMenus[level - 1] = $ul; 25320 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 25321 return; 25322 } 25323 // show the sub menu if this item has one 25324 var $sub = $li.dataSM('sub'); 25325 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 25326 // if ($sub && (this.isTouchMode() || (!this.opts.showOnClick))) { 25327 var aRect = $a[0].getBoundingClientRect(); 25328 if ( (aRect.y < 0 || aRect.y > winh) && this.isCollapsible() && (this.lastLevel === this.activatedItems.length) ) { 25329 setTimeout(function(){ 25330 var currentScroll = $a.closest('.main-menu-container').scrollTop(); 25331 $a.closest('.main-menu-container').scrollTop(currentScroll + aRect.y); 25332 }, 1); 25333 } 25334 this.menuShow($sub); 25335 } 25336 }, 25337 itemBlur: function(e) { 25338 var $a = $(e.currentTarget); 25339 if (!this.handleItemEvents($a)) { 25340 return; 25341 } 25342 this.$root.triggerHandler('blur.smapi', $a[0]); 25343 }, 25344 itemClick: function(e) { 25345 var $a = $(e.currentTarget); 25346 25347 if (!this.handleItemEvents($a)) { 25348 return; 25349 } 25350 $a.removeDataSM('mousedown'); 25351 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 25352 return false;
25353 } 25354 var $sub = $a.parent().dataSM('sub'); 25355 if (this.isTouchMode()) { 25356 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 25357 if ($a.dataSM('href')) { 25358 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 25359 } 25360 // if the sub is not visible 25361 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 25362 // try to activate the item and show the sub 25363 this.itemActivate($a); 25364 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 25365 // 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 25366 if ($sub.is(':visible')) { 25367 return false; 25368 } 25369 } 25370 // } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub && !$sub.is(':visible')) { 25371 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 25372 this.clickActivated = true; 25373 this.menuShow($sub); 25374 return false; 25375 } 25376 if ($a.hasClass('disabled')) { 25377 return false; 25378 } 25379 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 25380 return false; 25381 } 25382 }, 25383 itemDown: function(e) { 25384 var $a = $(e.currentTarget); 25385 if (!this.handleItemEvents($a)) { 25386 return; 25387 } 25388 $a.dataSM('mousedown', true); 25389 }, 25390 itemEnter: function(e) { 25391 // if ( this.opts.showOnClick ) { 25392 // return 25393 // } 25394 var $a = $(e.currentTarget); 25395 if (!this.handleItemEvents($a)) { 25396 return; 25397 } 25398 if (!this.isTouchMode()) { 25399 if (this.showTimeout) { 25400 clearTimeout(this.showTimeout); 25401 this.showTimeout = 0; 25402 } 25403 var self = this; 25404 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 25405 } 25406 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 25407 }, 25408 itemFocus: function(e) { 25409 var $a = $(e.currentTarget); 25410 if (!this.handleItemEvents($a)) { 25411 return; 25412 } 25413 // 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 25414 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 25415 this.itemActivate($a); 25416 } 25417 this.$root.triggerHandler('focus.smapi', $a[0]); 25418 }, 25419 itemLeave: function(e) { 25420 // if ( this.opts.showOnClick ) { 25421 // return 25422 // } 25423 var $a = $(e.currentTarget); 25424 if (!this.handleItemEvents($a)) { 25425 return; 25426 } 25427 if (!this.isTouchMode()) { 25428 if ($a[0].blur) { 25429 $a[0].blur(); 25430 } 25431 if (this.showTimeout) { 25432 clearTimeout(this.showTimeout); 25433 this.showTimeout = 0; 25434 } 25435 } 25436 $a.removeDataSM('mousedown'); 25437 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 25438 }, 25439 itemTouchEnd: function(e) { 25440 var $a = $(e.currentTarget); 25441 if (!this.handleItemEvents($a)) { 25442 return; 25443 } 25444 // prevent the address bar on iPhone from sliding down when expanding a sub menu 25445 var $sub = $a.parent().dataSM('sub'); 25446 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 25447 $a.dataSM('href', $a.attr('href')); 25448 $a.attr('href', '#'); 25449 } 25450 }, 25451 menuFixLayout: function($ul) { 25452 // fixes a menu that is being shown for the first time 25453 if (!$ul.dataSM('shown-before')) { 25454 $ul.hide().dataSM('shown-before', true); 25455 // fix the layout of the items in IE<8 25456 if (IElt8) { 25457 $ul.children().css({ styleFloat: 'left', width: '100%' }); 25458 } 25459 } 25460 }, 25461 menuHide: function($sub, $show) { 25462 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 25463 return; 25464 } 25465 $sub.stop(true, true); 25466 if ($sub.is(':visible')) { 25467 var self = this; 25468 var complete = function() { 25469 // unset z-index 25470 if (IElt9) { 25471 $sub.parent().css('z-index', ''); 25472 } else { 25473 $sub.css('z-index', ''); 25474 } 25475 if ( typeof $show !== 'undefined' ) { 25476 self.itemActivate($show, true) 25477 } 25478 }; 25479 // if sub is collapsible (mobile view) 25480 if (this.isCollapsible()) { 25481 if (this.opts.collapsibleHideFunction) { 25482 this.opts.collapsibleHideFunction.call(this, $sub, complete); 25483 } else { 25484 $sub.hide(this.opts.collapsibleHideDuration, complete); 25485 } 25486 } else { 25487 if (this.opts.hideFunction) { 25488 this.opts.hideFunction.call(this, $sub, complete); 25489 } else { 25490 $sub.hide(this.opts.hideDuration, complete); 25491 } 25492 } 25493 // remove IE iframe shim 25494 if ($sub.dataSM('ie-shim')) { 25495 $sub.dataSM('ie-shim').remove(); 25496 } 25497 // deactivate scrolling if it is activated for this sub 25498 if ($sub.dataSM('scroll')) { 25499 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 25500 } 25501 // unhighlight parent item 25502 $sub.dataSM('parent-a').removeClass('highlighted'); 25503 var level = $sub.dataSM('level'); 25504 this.activatedItems.splice(level - 1, 1); 25505 this.visibleSubMenus.splice(level - 1, 1); 25506 this.$root.triggerHandler('hide.smapi', $sub[0]); 25507 } 25508 }, 25509 menuHideAll: function($item) { 25510 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 25511 var $win = $(window), 25512 winW = $win.width(); 25513 if (this.showTimeout) { 25514 clearTimeout(this.showTimeout); 25515 this.showTimeout = 0; 25516 } 25517 // hide all subs 25518 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 25519 if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) { 25520 if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) { 25521 this.menuHide(this.visibleSubMenus[i]); 25522 $(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item'); 25523 } else { 25524 return; 25525 } 25526 } else { 25527 //if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) { 25528 this.menuHide(this.visibleSubMenus[i]); 25529 //} 25530 } 25531 } 25532 // hide root if it's popup 25533 if (this.opts.isPopup) { 25534 this.$root.stop(true, true); 25535 if (this.$root.is(':visible')) { 25536 if (this.opts.hideFunction) { 25537 this.opts.hideFunction.call(this, this.$root); 25538 } else { 25539 this.$root.hide(this.opts.hideDuration); 25540 } 25541 // remove IE iframe shim 25542 if (this.$root.dataSM('ie-shim')) { 25543 this.$root.dataSM('ie-shim').remove(); 25544 } 25545 } 25546 } 25547 this.activatedItems = []; 25548 this.visibleSubMenus = []; 25549 this.clickActivated = false;
25550 // reset z-index increment 25551 this.zIndexInc = 0; 25552 }, 25553 menuIframeShim: function($ul) { 25554 // create iframe shim for the menu 25555 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 25556 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 25557 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 25558 ); 25559 } 25560 }, 25561 menuInit: function($ul) { 25562 if (!$ul.dataSM('in-mega')) { 25563 this.subMenus.push($ul); 25564 // mark UL's in mega drop downs (if any) so we can neglect them 25565 if ($ul.hasClass('mega-menu')) { 25566 $ul.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').dataSM('in-mega', true); 25567 } 25568 // get level (much faster than, for example, using parentsUntil) 25569 var level = 2, 25570 par = $ul[0]; 25571 while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) { 25572 level++; 25573 } 25574 // cache stuff 25575 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 25576 .dataSM('level', level) 25577 .parent().dataSM('sub', $ul); 25578 // add sub indicator to parent item 25579 if (this.opts.subIndicators) { 25580 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 25581 } 25582 } 25583 if ( $('.vc_row[data-parent].has-bg', $ul).length && !$('.vc_row[data-parent]:not(.has-bg)', $ul).length ) { 25584 $ul.addClass('has-bg-items'); 25585 } 25586 }, 25587 menuPosition: function($sub) { 25588 var fixIE = $('html.ie').length; 25589 // if (fixIE) { 25590 // var $rowParent = $($sub).closest('.main-menu-container'); 25591 // $rowParent.height($rowParent.height()); 25592 // } 25593 var $a = $sub.dataSM('parent-a'), 25594 $li = $sub.parent(), 25595 $ul = $sub.parent().parent(), 25596 // $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'), 25597 $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'), 25598 level = $sub.dataSM('level'), 25599 subW = this.getWidth($sub), 25600 subH = this.getHeight($sub), 25601 itemOffset = $a.offset(), 25602 itemX = itemOffset.left, 25603 itemY = itemOffset.top, 25604 itemW = this.getWidth($a), 25605 itemH = this.getHeight($a), 25606 $win = $(window), 25607 winX = $win.scrollLeft(), 25608 winY = $win.scrollTop(), 25609 winW = $win.width(), 25610 winH = $win.height(), 25611 containerW = $container.width(), 25612 containerOffsetX = containerW + ((winW - containerW) / 2), 25613 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 25614 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 25615 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 25616 x, y, leftPos; 25617 25618 if (horizontalParent) { 25619 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 25620 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 25621 } else { 25622 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX; 25623 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 25624 } 25625 if (this.opts.keepInViewport && !this.isCollapsible()) { 25626 if (this.isFixed()) { 25627 itemX -= winX; 25628 itemY -= winY; 25629 winX = winY = 0; 25630 } 25631 var absX = itemX + x, 25632 absY = itemY + y; 25633 if (this.opts.rightToLeftSubMenus && absX < winX) { 25634 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 25635 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 25636 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 25637 } 25638 if (!horizontalParent) { 25639 if (subH < winH && absY + subH > winY + winH) { 25640 y += winY + winH - subH - absY; 25641 } else if (subH >= winH || absY < winY) { 25642 y += winY - absY; 25643 } 25644 } 25645 // do we need scrolling? 25646 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 25647 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 25648 var self = this; 25649 if (!$sub.dataSM('scroll-arrows')) { 25650 $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]]) 25651 .bind({ 25652 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 25653 mouseleave: function(e) { 25654 self.menuScrollStop($sub); 25655 self.menuScrollOut($sub, e); 25656 }, 25657 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 25658 }) 25659 .insertAfter($sub) 25660 ); 25661 } 25662 // bind events to show/hide arrows on hover and save scrolling data for this sub 25663 var vportY = winY - (itemY + itemH); 25664 $sub.dataSM('scroll', { 25665 vportY: vportY, 25666 subH: subH, 25667 winH: winH, 25668 step: 1 25669 }) 25670 .bind({ 25671 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 25672 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 25673 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 25674 }) 25675 .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
25675StartZIndex() + this.zIndexInc }) 25676 .eq(0).css('margin-top', vportY).end() 25677 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 25678 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 25679 } 25680 } 25681 if ( !$sub.closest('.menu-accordion').length ) { 25682 var rightPos = 'auto'; 25683 if ( $sub.closest('.grid-filters').length ) { 25684 if ( $sub.closest('.text-right').length ) { 25685 leftPos = '0px'; 25686 rightPos = 'auto'; 25687 } else { 25688 leftPos = 'auto'; 25689 rightPos = '0px'; 25690 } 25691 x = 0; 25692 } else { 25693 if ( $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)').length && $sub.closest('.row-menu').is('.limit-width') && level === 2) { 25694 var parentContW = $sub.closest('.menu-container').width(); 25695 $sub.css({ width: parentContW}); 25696 $sub.addClass('need-focus'); 25697 leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.menu-container').offset().left)); 25698 x = 0; 25699 } else if ( $sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)').length ) { 25700 $sub.css({ width: containerW}); 25701 $sub.addClass('need-focus'); 25702 leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left)); 25703 if ( ! $('body').hasClass('megamenu-side-to-side') ) { 25704 leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft')); 25705 } 25706 x = 0; 25707 } else { 25708 if ( $sub.is('.block-wrapper-parent') && !$sub.find('.col-custom-width').length && !$sub.find('.row-parent-limit').length && level === 2 ) { 25709 leftPos = ( $li.position().left - ( (UNCODE.wwidth - $sub.outerWidth() )/2) ) + 'px'; 25710 } else { 25711 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'; 25712 } 25713 x = (level > 2 && x >= 0) ? x + 1 : x - 1; 25714 } 25715 } 25716 } 25717 25718 // $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) }); 25719 $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) }); 25720 // IE iframe shim 25721 this.menuIframeShim($sub); 25722 if ($sub.dataSM('ie-shim')) { 25723 $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) }); 25724 } 25725 }, 25726 menuScroll: function($sub, up, wheel) { 25727 var y = parseFloat($sub.css('margin-top')), 25728 scroll = $sub.dataSM('scroll'), 25729 navH = $('.navbar-main').outerHeight(), 25730 end = scroll.vportY + (up ? navH + 54 : scroll.winH - scroll.subH), 25731 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 25732 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 25733 y = parseFloat($sub.css('margin-top')); 25734 // show opposite arrow if appropriate 25735 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 25736 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 25737 } 25738 // accelerate when not using mousewheel to scroll 25739 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 25740 $sub.dataSM('scroll').step += 0.5; 25741 } 25742 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 25743 if (Math.abs(y - end) < 1) { 25744 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 25745 $sub.dataSM('scroll').step = 1; 25746 } else if (!wheel) { 25747 var self = this; 25748 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 25749 } 25750 }, 25751 menuScrollMousewheel: function($sub, e) { 25752 var $closestSub = $(e.target).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25753 while ($closestSub.dataSM('in-mega')) { 25754 $closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25755 } 25756 if ($closestSub[0] == $sub[0]) { 25757 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 25758 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 25759 this.menuScroll($sub, up, true); 25760 } 25761 } 25762 if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) { 25763 e.preventDefault(); 25764 } 25765 }, 25766 menuScrollOut: function($sub, e) { 25767 var reClass = /^scroll-(up|down)/, 25768 $closestSub = $(e.relatedTarget).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25769 while ($closestSub.dataSM('in-mega')) { 25770 $closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25771 } 25772 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 25773 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 25774 } 25775 }, 25776 menuScrollOver: function($sub, e) { 25777 var reClass = /^scroll-(up|down)/, 25778 $closestSub = $(e.target).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25779 while ($closestSub.dataSM('in-mega')) { 25780 $closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)'); 25781 } 25782 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 25783 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 25784 } 25785 }, 25786 menuScrollStop: function($sub) { 25787 if (this.scrollTimeout) { 25788 clearTimeout(this.scrollTimeout); 25789 this.scrollTimeout = 0; 25790 $sub.dataSM('scroll').step = 1; 25791 } 25792 }, 25793 menuShow: function($sub) { 25794 if (!$sub.dataSM('beforefirstshowfired')) { 25795 $sub.dataSM('beforefirstshowfired', true); 25796 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 25797 return; 25798 } 25799 } 25800 if ( this.isCollapsible() ) {
25801 this.$root.triggerHandler('beforecollapse.smapi', $sub[0]); 25802 } 25803 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 25804 return; 25805 } 25806 this.menuFixLayout($sub); 25807 $sub.stop(true, true); 25808 if (!$sub.is(':visible')) { 25809 $sub.css({ 25810 'visibility': 'visible', 25811 'pointer-events': 'auto', 25812 }); 25813 // set z-index - for IE < 9 set it to the parent LI 25814 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 25815 if (IElt9) { 25816 $sub.parent().css('z-index', zIndex); 25817 } else { 25818 $sub.css('z-index', zIndex); 25819 } 25820 // highlight parent item 25821 if (this.opts.keepHighlighted || this.isCollapsible()) { 25822 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 25823 $sub.dataSM('parent-a').addClass('highlighted'); 25824 } 25825 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 25826 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 25827 if (!IElt8) { 25828 $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'); 25829 if (this.opts.subMenusMinWidth) { 25830 $sub.css('min-width', this.opts.subMenusMinWidth); 25831 } 25832 if (this.opts.subMenusMaxWidth) { 25833 var noMaxWidth = this.getWidth($sub); 25834 if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) { 25835 $sub.css('max-width', this.opts.subMenusMaxWidth); 25836 } 25837 if (noMaxWidth > this.getWidth($sub)) { 25838 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 25839 } 25840 } 25841 // IE6,7 25842 } else { 25843 $sub.children().css('styleFloat', 'none'); 25844 if (IE6) { 25845 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 25846 .children().children('a').css('white-space', 'nowrap'); 25847 } else { // IE7 25848 $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'); 25849 if (this.opts.subMenusMinWidth) { 25850 $sub.css('min-width', this.opts.subMenusMinWidth); 25851 } 25852 } 25853 if (this.opts.subMenusMaxWidth) { 25854 var noMaxWidth = $sub.width(); 25855 if (IE6) { 25856 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 25857 if (noMaxWidth > maxWidth) { 25858 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 25859 } else { 25860 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 25861 } 25862 } else { // IE7 25863 if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) { 25864 $sub.css('max-width', this.opts.subMenusMaxWidth); 25865 } 25866 if (noMaxWidth > $sub.width()) { 25867 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 25868 } else { 25869 $sub.width(noMaxWidth); 25870 } 25871 } 25872 } else { 25873 $sub.width($sub.width()); 25874 } 25875 $sub.children().css('styleFloat', 'left'); 25876 } 25877 } 25878 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 ) { 25879 var $nav = $('.navbar-main'), 25880 navH = 0, 25881 navTop = 0, 25882 $vmenu = $('body.vmenu .vmenu-container, body.menu-overlay .vmenu-container, body.menu-offcanvas .vmenu-container'); 25883 if ( $nav.length && typeof $nav[0] !== 'undefined' ) { 25884 var navRect = $nav[0].getBoundingClientRect(); 25885 navH = navRect.height; 25886 navTop = navRect.top; 25887 } 25888 if ( ! $vmenu.length ) { 25889 $sub.css({ maxHeight: UNCODE.wheight - navH }); 25890 if ( $('.megamenu-block-wrapper', $sub).length ) { 25891 $sub.find('> li').addClass('has-scroll').css({ maxHeight: UNCODE.wheight - navH }); 25892 } 25893 } 25894 } 25895 this.menuPosition($sub); 25896 // insert IE iframe shim 25897 if ($sub.dataSM('ie-shim')) { 25898 $sub.dataSM('ie-shim').insertBefore($sub); 25899 } 25900 var complete = function() { 25901 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 25902 $sub.css('overflow', ''); 25903 }; 25904 // if sub is collapsible (mobile view) 25905 if (this.isCollapsible()) { 25906 if (this.opts.collapsibleShowFunction) { 25907 this.opts.collapsibleShowFunction.call(this, $sub, complete); 25908 } else { 25909 $sub.show(this.opts.collapsibleShowDuration, complete); 25910 } 25911 } else { 25912 if (this.opts.showFunction) { 25913 this.opts.showFunction.call(this, $sub, complete); 25914 } else { 25915 $sub.show(this.opts.showDuration, complete); 25916 } 25917 } 25918 // save new sub menu for this level 25919 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 25920 this.$root.triggerHandler('show.smapi', $sub[0]); 25921 } 25922 }, 25923 popupHide: function(noHideTimeout) { 25924 if (this.hideTimeout) { 25925 clearTimeout(this.hideTimeout); 25926 this.hideTimeout = 0; 25927 } 25928 var self = this; 25929 this.hideTimeout = setTimeout(function() { 25930 self.menuHideAll(); 25931 }, noHideTimeout ? 1 : this.opts.hideTimeout); 25932 }, 25933 popupShow: function(left, top) { 25934 if (!this.opts.isPopup) { 25935 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 25936 return; 25937 } 25938 if (this.hideTimeout) { 25939 clearTimeout(this.hideTimeout); 25940 this.hideTimeout = 0; 25941 } 25942 this.menuFixLayout(this.$root); 25943 this.$root.stop(true, true); 25944 if (!this.$root.is(':visible')) { 25945 this.$root.css({ left: left, top: top }); 25946 // IE iframe shim 25947 this.menuIframeShim(this.$root); 25948 if (this.$root.dataSM('ie-shim')) { 25949 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
25949: left, top: top }).insertBefore(this.$root); 25950 } 25951 // show menu 25952 if (this.opts.showFunction) { 25953 this.opts.showFunction.call(this, this.$root); 25954 } else { 25955 this.$root.show(this.opts.showDuration); 25956 } 25957 this.visibleSubMenus[0] = this.$root; 25958 } 25959 }, 25960 refresh: function() { 25961 this.menuHideAll(); 25962 this.$root.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').each(function() { 25963 var $this = $(this); 25964 if ($this.dataSM('scroll-arrows')) { 25965 $this.dataSM('scroll-arrows').remove(); 25966 } 25967 }) 25968 .removeDataSM('in-mega') 25969 .removeDataSM('shown-before') 25970 .removeDataSM('ie-shim') 25971 .removeDataSM('scroll-arrows') 25972 .removeDataSM('parent-a') 25973 .removeDataSM('level') 25974 .removeDataSM('beforefirstshowfired'); 25975 this.$root.find('a.has-submenu').removeClass('has-submenu') 25976 .parent().removeDataSM('sub'); 25977 if (this.opts.subIndicators) { 25978 this.$root.find('span.sub-arrow').remove(); 25979 } 25980 if (this.opts.markCurrentItem) { 25981 this.$root.find('a.current').removeClass('current'); 25982 } 25983 this.subMenus = []; 25984 this.init(true); 25985 }, 25986 rootOut: function(e) { 25987 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 25988 return; 25989 } 25990 if (this.hideTimeout) { 25991 clearTimeout(this.hideTimeout); 25992 this.hideTimeout = 0; 25993 } 25994 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 25995 var self = this; 25996 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 25997 } 25998 }, 25999 rootOver: function(e) { 26000 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 26001 return; 26002 } 26003 if (this.hideTimeout) { 26004 clearTimeout(this.hideTimeout); 26005 this.hideTimeout = 0; 26006 } 26007 }, 26008 winResize: function(e) { 26009 if (!this.handleEvents()) { 26010 // we still need to resize the disable overlay if it's visible 26011 if (this.$disableOverlay) { 26012 var pos = this.$root.offset(); 26013 this.$disableOverlay.css({ 26014 top: pos.top, 26015 left: pos.left, 26016 width: this.$root.outerWidth(), 26017 height: this.$root.outerHeight() 26018 }); 26019 } 26020 return; 26021 } 26022 // hide sub menus on resize - on mobile do it only on orientation change 26023 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 26024 if (this.activatedItems.length) { 26025 this.activatedItems[this.activatedItems.length - 1][0].blur(); 26026 } 26027 this.menuHideAll(); 26028 } 26029 } 26030 } 26031 }); 26032 26033 $.fn.dataSM = function(key, val) { 26034 if (val) { 26035 return this.data(key + '_smartmenus', val); 26036 } 26037 return this.data(key + '_smartmenus'); 26038 } 26039 26040 $.fn.removeDataSM = function(key) { 26041 return this.removeData(key + '_smartmenus'); 26042 } 26043 26044 $.fn.smartmenus = function(options) { 26045 if (typeof options == 'string') { 26046 var args = arguments, 26047 method = options; 26048 Array.prototype.shift.call(args); 26049 return this.each(function() { 26050 var smartmenus = $(this).data('smartmenus'); 26051 if (smartmenus && smartmenus[method]) { 26052 smartmenus[method].apply(smartmenus, args); 26053 } 26054 }); 26055 } 26056 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 26057 return this.each(function() { 26058 new $.SmartMenus(this, opts); 26059 }); 26060 } 26061 26062 // default settings 26063 $.fn.smartmenus.defaults = { 26064 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 26065 mainMenuSubOffsetX: 0, // pixels offset from default position
26066 mainMenuSubOffsetY: 0, // pixels offset from default position 26067 subMenusSubOffsetX: 0, // pixels offset from default position 26068 subMenusSubOffsetY: 0, // pixels offset from default position 26069 subMenusMinWidth: false, //'10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 26070 subMenusMaxWidth: false, //'20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 26071 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 26072 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 26073 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 26074 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 26075 scrollInterval: 30, // interval between each scrolling step 26076 scrollAccelerate: true, // accelerate scrolling or use a fixed step 26077 showTimeout: 250, // timeout before showing the sub menus 26078 hideTimeout: 500, // timeout before hiding the sub menus 26079 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 26080 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 26081 // don't forget to call complete() at the end of whatever you do 26082 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 26083 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 26084 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 26085 // don't forget to call complete() at the end of whatever you do 26086 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 26087 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 26088 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 26089 // (i.e. when mobile styles are used to make the sub menus collapsible) 26090 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 26091 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 26092 // (i.e. when mobile styles are used to make the sub menus collapsible) 26093 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 26094 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 26095 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 26096 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 26097 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 26098 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 26099 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 26100 bottomToTopSubMenus: false, // bottom to top display of the sub menus 26101 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 26102 }; 26103 26104})(jQuery); 26105/* 26106 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/ 26107 * Open source under the BSD License. 26108 * Copyright © 2008 George McGinley Smith 26109 * All rights reserved. 26110 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE 26111*/ 26112 26113/* globals jQuery, define, module, require */ 26114(function (factory) { 26115 if (typeof define === "function" && define.amd) { 26116 define(['jquery'], function ($) { 26117 return factory($); 26118 }); 26119 } else if (typeof module === "object" && typeof module.exports === "object") { 26120 module.exports = factory(require('jquery')); 26121 } else { 26122 factory(jQuery); 26123 } 26124})(function($){ 26125 26126 // Preserve the original jQuery "swing" easing as "jswing" 26127 if (typeof $.easing !== 'undefined') { 26128 $.easing['jswing'] = $.easing['swing']; 26129 } 26130 26131 var pow = Math.pow, 26132 sqrt = Math.sqrt, 26133 sin = Math.sin, 26134 cos = Math.cos, 26135 PI = Math.PI,
26136 c1 = 1.70158, 26137 c2 = c1 * 1.525, 26138 c3 = c1 + 1, 26139 c4 = ( 2 * PI ) / 3, 26140 c5 = ( 2 * PI ) / 4.5; 26141 26142 // x is the fraction of animation progress, in the range 0..1 26143 function bounceOut(x) { 26144 var n1 = 7.5625, 26145 d1 = 2.75; 26146 if ( x < 1/d1 ) { 26147 return n1*x*x; 26148 } else if ( x < 2/d1 ) { 26149 return n1*(x-=(1.5/d1))*x + .75; 26150 } else if ( x < 2.5/d1 ) { 26151 return n1*(x-=(2.25/d1))*x + .9375; 26152 } else { 26153 return n1*(x-=(2.625/d1))*x + .984375; 26154 } 26155 } 26156 26157 $.extend( $.easing, { 26158 def: 'easeOutQuad', 26159 swing: function (x) { 26160 return $.easing[$.easing.def](x); 26161 }, 26162 easeInQuad: function (x) { 26163 return x * x; 26164 }, 26165 easeOutQuad: function (x) { 26166 return 1 - ( 1 - x ) * ( 1 - x ); 26167 }, 26168 easeInOutQuad: function (x) { 26169 return x < 0.5 ? 26170 2 * x * x : 26171 1 - pow( -2 * x + 2, 2 ) / 2; 26172 }, 26173 easeInCubic: function (x) { 26174 return x * x * x; 26175 }, 26176 easeOutCubic: function (x) { 26177 return 1 - pow( 1 - x, 3 ); 26178 }, 26179 easeInOutCubic: function (x) { 26180 return x < 0.5 ? 26181 4 * x * x * x : 26182 1 - pow( -2 * x + 2, 3 ) / 2; 26183 }, 26184 easeInQuart: function (x) { 26185 return x * x * x * x; 26186 }, 26187 easeOutQuart: function (x) { 26188 return 1 - pow( 1 - x, 4 ); 26189 }, 26190 easeInOutQuart: function (x) { 26191 return x < 0.5 ? 26192 8 * x * x * x * x : 26193 1 - pow( -2 * x + 2, 4 ) / 2; 26194 }, 26195 easeInQuint: function (x) { 26196 return x * x * x * x * x; 26197 }, 26198 easeOutQuint: function (x) { 26199 return 1 - pow( 1 - x, 5 ); 26200 }, 26201 easeInOutQuint: function (x) { 26202 return x < 0.5 ? 26203 16 * x * x * x * x * x : 26204 1 - pow( -2 * x + 2, 5 ) / 2; 26205 }, 26206 easeInSine: function (x) { 26207 return 1 - cos( x * PI/2 ); 26208 }, 26209 easeOutSine: function (x) { 26210 return sin( x * PI/2 ); 26211 }, 26212 easeInOutSine: function (x) { 26213 return -( cos( PI * x ) - 1 ) / 2; 26214 }, 26215 easeInExpo: function (x) { 26216 return x === 0 ? 0 : pow( 2, 10 * x - 10 ); 26217 }, 26218 easeOutExpo: function (x) { 26219 return x === 1 ? 1 : 1 - pow( 2, -10 * x ); 26220 }, 26221 easeInOutExpo: function (x) { 26222 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 26223 pow( 2, 20 * x - 10 ) / 2 : 26224 ( 2 - pow( 2, -20 * x + 10 ) ) / 2; 26225 }, 26226 easeInCirc: function (x) { 26227 return 1 - sqrt( 1 - pow( x, 2 ) ); 26228 }, 26229 easeOutCirc: function (x) { 26230 return sqrt( 1 - pow( x - 1, 2 ) ); 26231 }, 26232 easeInOutCirc: function (x) { 26233 return x < 0.5 ? 26234 ( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 : 26235 ( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2; 26236 }, 26237 easeInElastic: function (x) { 26238 return x === 0 ? 0 : x === 1 ? 1 : 26239 -pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 ); 26240 }, 26241 easeOutElastic: function (x) { 26242 return x === 0 ? 0 : x === 1 ? 1 : 26243 pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1; 26244 }, 26245 easeInOutElastic: function (x) { 26246 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 26247 -( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 : 26248 pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1; 26249 }, 26250 easeInBack: function (x) { 26251 return c3 * x * x * x - c1 * x * x; 26252 }, 26253 easeOutBack: function (x) { 26254 return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 ); 26255 }, 26256 easeInOutBack: function (x) { 26257 return x < 0.5 ? 26258 ( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 : 26259 ( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2; 26260 }, 26261 easeInBounce: function (x) { 26262 return 1 - bounceOut( 1 - x ); 26263 }, 26264 easeOutBounce: bounceOut, 26265 easeInOutBounce: function (x) { 26266 return x < 0.5 ? 26267 ( 1 - bounceOut( 1 - 2 * x ) ) / 2 : 26268 ( 1 + bounceOut( 2 * x - 1 ) ) / 2; 26269 } 26270 }); 26271 return $; 26272}); 26273 26274/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 26275 * Licensed under the MIT License (LICENSE.txt). 26276 * 26277 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 26278 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 26279 * Thanks to: Seamus Leahy for adding deltaX and deltaY 26280 * 26281 * Version: 3.0.6 26282 * 26283 * Requires: 1.2.2+ 26284 */ 26285(function($) { 26286 var types = ['DOMMouseScroll', 'mousewheel']; 26287 if ($.event.fixHooks) { 26288 for (var i = types.length; i;) { 26289 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 26290 } 26291 } 26292 $.event.special.mousewheel = { 26293 setup: function() { 26294 if (this.addEventListener) { 26295 for (var i = types.length; i;) { 26296 this.addEventListener(types[--i], handler, false); 26297 } 26298 } else { 26299 this.onmousewheel = handler; 26300 } 26301 }, 26302 teardown: function() { 26303 if (this.removeEventListener) { 26304 for (var i = types.length; i;) { 26305 this.removeEventListener(types[--i], handler, false); 26306 } 26307 } else { 26308 this.onmousewheel = null; 26309 } 26310 } 26311 }; 26312 $.fn.extend({ 26313 mousewheel: function(fn) { 26314 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 26315 }, 26316 unmousewheel: function(fn) { 26317 return this.unbind("mousewheel", fn); 26318 } 26319 }); 26320 26321 function handler(event) { 26322 var orgEvent = event || window.event, 26323 args = [].slice.call(arguments, 1), 26324 delta = 0, 26325 returnValue = true, 26326 deltaX = 0, 26327 deltaY = 0; 26328 event = $.event.fix(orgEvent); 26329 event.type = "mousewheel"; 26330 // Old school scrollwheel delta 26331 if (orgEvent.wheelDelta) { 26332 delta = orgEvent.wheelDelta / 120; 26333 } 26334 if (orgEvent.detail) { 26335 delta = -orgEvent.detail / 3; 26336 } 26337 // New school multidimensional scroll (touchpads) deltas 26338 deltaY = delta; 26339 // Gecko 26340 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 26341 deltaY = 0; 26342 deltaX = -1 * delta; 26343 } 26344 // Webkit 26345 if (orgEvent.wheelDeltaY !== undefined) { 26346 deltaY = orgEvent.wheelDeltaY / 120; 26347 } 26348 if (orgEvent.wheelDeltaX !== undefined) { 26349 deltaX = -1 * orgEvent.wheelDeltaX / 120; 26350 } 26351 // Add event and delta to the front of the arguments 26352 args.unshift(event, delta, deltaX, deltaY); 26353 return ($.event.dispatch || $.event.handle).apply(this, args); 26354 } 26355})(jQuery); 26356/** 26357 * jQuery iLightBox - Revolutionary Lightbox Plugin 26358 * http://www.ilightbox.net/ 26359 * 26360 * @version: 2.2.4 - October 14, 2017 26361 * 26362 * @author: iProDev (Hemn Chawroka) 26363 * http://www.iprodev.com/ 26364 * 26365 */ 26366(function($, window, undefined) { 26367 26368 var extensions = { 26369 flash: ['swf'], 26370 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'], 26371 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 26372 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 26373 }, 26374 26375 // Global DOM elements 26376 $win = $(window), 26377 $doc = $(document), 26378
26379 // Support indicators 26380 browser, 26381 transform, 26382 gpuAcceleration, 26383 fullScreenApi = '', 26384 userAgent = navigator.userAgent || navigator.vendor || window.opera, 26385 supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1), 26386 ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1, 26387 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)), 26388 26389 // Events 26390 clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox", 26391 touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 26392 touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 26393 touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 26394 26395 // Math shorthands 26396 abs = Math.abs, 26397 sqrt = Math.sqrt, 26398 round = Math.round, 26399 max = Math.max, 26400 min = Math.min, 26401 floor = Math.floor, 26402 random = Math.random, 26403 26404 pluginspages = { 26405 quicktime: 'http://www.apple.com/quicktime/download', 26406 flash: 'http://www.adobe.com/go/getflash' 26407 }, 26408 26409 iLightBox = function(el, options, items, instant) { 26410 var iL = this; 26411 26412 iL.options = options, 26413 iL.selector = options.selector || el, 26414 iL.context = document, 26415 iL.instant = instant; 26416 26417 if (items.length < 1) iL.attachItems(); 26418 else iL.items = items; 26419 26420 iL.vars = { 26421 total: iL.items.length, 26422 start: 0, 26423 current: null, 26424 next: null, 26425 prev: null, 26426 BODY: $('body'), 26427 loadRequests: 0, 26428 overlay: $('<div class="ilightbox-overlay"></div>'), 26429 loader: $('<div class="ilightbox-loader"><div></div></div>'), 26430 toolbar: $('<div class="ilightbox-toolbar"></div>'), 26431 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 26432 title: $('<div class="ilightbox-title"></div>'), 26433 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 26434 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 26435 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 26436 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 26437 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 26438 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 26439 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 26440 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 26441 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 26442 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
26443 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>'), 26444 thumbs: false, 26445 nextLock: false, 26446 prevLock: false, 26447 hashLock: false, 26448 isMobile: false, 26449 mobileMaxWidth: 980, 26450 isInFullScreen: false, 26451 isSwipe: false, 26452 mouseID: 0, 26453 cycleID: 0, 26454 isPaused: 0, 26455 captionHeight: 39, 26456 }; 26457 26458 // Hideable elements with mousemove event 26459 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 26460 26461 iL.normalizeItems(); 26462 26463 //Check necessary plugins 26464 iL.availPlugins(); 26465 26466 //Set startFrom 26467 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 26468 26469 //If randomStart 26470 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 26471 iL.vars.start = iL.options.startFrom; 26472 26473 if (instant) iL.instantCall(); 26474 else iL.patchItemsEvents(); 26475 26476 if (iL.options.linkId) { 26477 iL.hashChangeHandler(); 26478 $win.iLightBoxHashChange(function() { 26479 iL.hashChangeHandler(); 26480 }); 26481 } 26482 26483 if (supportTouch) { 26484 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 26485 replace = "itap"; 26486 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 26487 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 26488 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 26489 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 26490 } 26491 26492 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 26493 $.extend(iL.options.styles, { 26494 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 26495 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 26496 nextOpacity: 0, 26497 prevOpacity: 0 26498 }); 26499 } 26500 }; 26501 26502 //iLightBox helpers 26503 iLightBox.prototype = { 26504 showLoader: function() { 26505 var iL = this; 26506 iL.vars.loadRequests += 1; 26507 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 26508 //top: '-30px' 26509 opacity: '1' 26510 }, iL.options.show.speed, 'easeOutCirc'); 26511 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 26512 //left: '-30px' 26513 opacity: '1' 26514 }, iL.options.show.speed, 'easeOutCirc'); 26515 }, 26516 26517 hideLoader: function() { 26518 var iL = this; 26519 iL.vars.loadRequests -= 1; 26520 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 26521 if (iL.options.path.toLowerCase() == "horizontal") { 26522 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 26523 //top: '-192px' 26524 opacity: '0' 26525 }, iL.options.show.speed, 'easeInCirc'); 26526 } else { 26527 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 26528 //left: '-192px' 26529 opacity: '0' 26530 }, iL.options.show.speed, 'easeInCirc'); 26531 } 26532 }, 26533 26534 createUI: function() { 26535 var iL = this; 26536 26537 iL.ui = { 26538 currentElement: iL.vars.holder, 26539 nextElement: iL.vars.nextPhoto, 26540 prevElement: iL.vars.prevPhoto, 26541 currentItem: iL.vars.current, 26542 nextItem: iL.vars.next, 26543 prevItem: iL.vars.prev, 26544 hide: function() { 26545 iL.closeAction(); 26546 }, 26547 refresh: function() { 26548 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 26549 }, 26550 fullscreen: function() { 26551 iL.fullScreenAction(); 26552 } 26553 }; 26554 }, 26555 26556 attachItems: function() { 26557 var iL = this, 26558 itemsObject = new Array(), 26559 items = new Array(); 26560 26561 $(iL.selector, iL.context).each(function() { 26562 var t = $(this), 26563 URL = t.attr(iL.options.attr) || null, 26564 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 26565 caption = t.data('caption'), 26566 title = t.data('title'), 26567 type = t.data('type') || getTypeByExtension(URL), 26568 clone = t.data('lbox-clone') || false; 26569 26570 //Uncode addition ##START## 26571 if (type === false) { 26572 return; 26573 } 26574 //Uncode addition ##END## 26575 26576 if (t.data('lbox-clone') != undefined) return; 26577 26578 //Uncode addition ##START## 26579 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 26580 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 26581 URL_i, 26582 URLS_LENGHT = ALBUM_URLS.length; 26583 26584 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 26585 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 26586 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 26587 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 26588 items.push({ 26589 URL: ALBUM_URLS[URL_i].url, 26590 caption: ALBUM_URLS[URL_i].caption, 26591 title: ALBUM_URLS[URL_i].title, 26592 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 26593 options: item_opts, 26594 clone: clone 26595 }); 26596 var newT = t; 26597 newT.attr('href',ALBUM_URLS[URL_i].url); 26598 if (!iL.instant) itemsObject.push(newT); 26599 } 26600 } 26601 } else { 26602 //Uncode addition ##END## 26603 items.push({ 26604 URL: URL, 26605 caption: caption, 26606 title: title, 26607 type: type, 26608 options: options, 26609 clone: clone 26610 }); 26611 } 26612 26613 26614 if (iL.vars != undefined) iL.vars.total = items.length; 26615 26616 if (!iL.instant) itemsObject.push(t); 26617 }); 26618 26619 iL.items = items, 26620 iL.itemsObject = itemsObject; 26621 26622 }, 26623 26624 normalizeItems: function() { 26625 var iL = this, 26626 newItems = new Array(); 26627 26628 $.each(iL.items, function(key, val) { 26629 26630 if (typeof val == "string") val = { 26631 url: val 26632 }; 26633 26634 var URL = val.url || val.URL || null, 26635 options = val.options || {}, 26636 caption = val.caption || null, 26637 title = val.title || null, 26638 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 26639 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 26640 26641 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
26642 options.videoType = options.videoType || null, 26643 options.skin = options.skin || iL.options.skin, 26644 options.width = options.width || null, 26645 options.height = options.height || null, 26646 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 26647 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 26648 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 26649 26650 if (type == "video") { 26651 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 26652 26653 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 26654 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 26655 options.html5video.preload = options.html5video.preload || "metadata"; 26656 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 26657 //UNCODE addition 26658 options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false; 26659 } 26660 26661 if (!options.width || !options.height) { 26662 if (type == "video") options.width = 1280, options.height = 720; 26663 else if (type == "iframe") options.width = '100%', options.height = '90%'; 26664 else if (type == "flash") options.width = 1280, options.height = 720; 26665 } 26666 26667 delete val.url; 26668 val.index = key; 26669 val.URL = URL; 26670 val.caption = caption; 26671 val.title = title; 26672 val.type = type; 26673 val.options = options; 26674 val.ext = ext; 26675 26676 newItems.push(val); 26677 }); 26678 26679 iL.items = newItems; 26680 }, 26681 26682 instantCall: function() { 26683 var iL = this, 26684 key = iL.vars.start; 26685 26686 iL.vars.current = key; 26687 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 26688 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 26689 26690 iL.addContents(); 26691 iL.patchEvents(); 26692 }, 26693 26694 addContents: function() { 26695 var iL = this, 26696 vars = iL.vars, 26697 opts = iL.options, 26698 viewport = getViewport(), 26699 path = opts.path.toLowerCase(), 26700 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 26701 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 26702 }), 26703 needRecognition = recognizingItems.length > 0; 26704 26705 if (opts.mobileOptimizer && !opts.innerToolbar) 26706 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 26707 26708 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 26709 26710 if (opts.linkId) 26711 vars.overlay[0].setAttribute('linkid', opts.linkId); 26712 26713 //Add Toolbar Buttons 26714 if (opts.controls.toolbar) { 26715 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 26716 if (opts.controls.fullscreen) 26717 vars.toolbar.append(vars.fullScreenButton); 26718 if (opts.controls.slideshow) 26719 vars.toolbar.append(vars.innerPlayButton); 26720 if (vars.total > 1) 26721 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 26722 } 26723 26724 //Append elements to body 26725 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 26726 26727 if (!opts.innerToolbar) 26728 vars.BODY.append(vars.toolbar); 26729 if (opts.controls.arrows) 26730 vars.BODY.append(vars.nextButton).append(vars.prevButton); 26731 26732 if (opts.controls.thumbnail && vars.total > 1) { 26733 vars.BODY.append(vars.thumbnails); 26734 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 26735 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 26736 vars.thumbs = true; 26737 } 26738 26739 //Configure loader and arrows 26740 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 26741 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 26742 } : { 26743 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 26744 }; 26745 vars.loader.addClass(opts.skin).css(loaderCss); 26746 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 26747 if (path == "horizontal") 26748 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 26749 26750 // Configure arrow buttons 26751 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 26752 26753 if (!opts.infinite) { 26754 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 26755 26756 if (vars.current == 0) 26757 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 26758 if (vars.current >= vars.total - 1) 26759 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 26760 } 26761 26762 if (opts.show.effect) { 26763 vars.overlay.stop().fadeIn(opts.show.speed); 26764 vars.toolbar.stop().fadeIn(opts.show.speed); 26765 } else { 26766 vars.overlay.show(); 26767 vars.toolbar.show(); 26768 } 26769 26770 var length = recognizingItems.length; 26771 if (needRecognition) { 26772 iL.showLoader(); 26773 26774 $.each(recognizingItems, function(key, val) { 26775 var resultFnc = function(result) { 26776 var key = -1, 26777 filter = iL.items.filter(function(e, i, arr) { 26778 if (e.URL == result.url) 26779 key = i; 26780 26781 return e.URL == result.url; 26782 }), 26783 self = iL.items[key]; 26784 26785 if (result) 26786 $.extend(true, self, { 26787 URL: result.source, 26788 type: result.type, 26789 recognized: true, 26790 options: { 26791 html5video: result.html5video, 26792 width: (result.type == "image") ? 0 : (result.width || self.width), 26793 height: (result.type == "image") ? 0 : (result.height || self.height), 26794 thumbnail: self.options.thumbnail || result.thumbnail 26795 } 26796 }); 26797 26798 length--; 26799 26800 if (length == 0) { 26801 iL.hideLoader(); 26802 26803 vars.dontGenerateThumbs = false;
26804 iL.generateThumbnails(); 26805 26806 if (opts.show.effect) 26807 setTimeout(function() { 26808 iL.generateBoxes(); 26809 }, opts.show.speed); 26810 else 26811 iL.generateBoxes(); 26812 } 26813 }; 26814 26815 iL.ogpRecognition(this, resultFnc); 26816 }); 26817 } 26818 else { 26819 if (opts.show.effect) 26820 setTimeout(function() { 26821 iL.generateBoxes(); 26822 }, opts.show.speed); 26823 else 26824 iL.generateBoxes(); 26825 } 26826 26827 iL.createUI(); 26828 26829 window.iLightBox = { 26830 close: function() { 26831 iL.closeAction(); 26832 }, 26833 fullscreen: function() { 26834 iL.fullScreenAction(); 26835 }, 26836 moveNext: function() { 26837 iL.moveTo('next'); 26838 }, 26839 movePrev: function() { 26840 iL.moveTo('prev'); 26841 }, 26842 goTo: function(index) { 26843 iL.goTo(index); 26844 }, 26845 refresh: function() { 26846 iL.refresh(); 26847 }, 26848 reposition: function() { 26849 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 26850 }, 26851 setOption: function(options) { 26852 iL.setOption(options); 26853 }, 26854 destroy: function() { 26855 iL.closeAction(); 26856 iL.dispatchItemsEvents(); 26857 } 26858 }; 26859 26860 if (opts.linkId) { 26861 vars.hashLock = true; 26862 window.location.hash = opts.linkId + '/' + vars.current; 26863 setTimeout(function() { 26864 vars.hashLock = false; 26865 }, 55); 26866 } 26867 26868 if (!opts.slideshow.startPaused) { 26869 iL.resume(); 26870 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 26871 } 26872 26873 //Trigger the onOpen callback 26874 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 26875 }, 26876 26877 loadContent: function(obj, opt, speed) { 26878 var iL = this, 26879 holder, item; 26880 26881 iL.createUI(); 26882 26883 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 26884 26885 if (opt == 'current') { 26886 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 26887 else iL.vars.lockWheel = false; 26888 26889 if (!obj.options.swipe) iL.vars.lockSwipe = true; 26890 else iL.vars.lockSwipe = false; 26891 } 26892 26893 switch (opt) { 26894 case 'current': 26895 holder = iL.vars.holder, item = iL.vars.current; 26896 break; 26897 case 'next': 26898 holder = iL.vars.nextPhoto, item = iL.vars.next; 26899 break; 26900 case 'prev': 26901 holder = iL.vars.prevPhoto, item = iL.vars.prev; 26902 break; 26903 } 26904 26905 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 26906 $('div.ilightbox-inner-toolbar', holder).remove(); 26907 26908 if (obj.title || iL.options.innerToolbar) { 26909 var innerToolbar = iL.vars.innerToolbar.clone(); 26910 if (obj.title && iL.options.show.title) { 26911 var title = iL.vars.title.clone(); 26912 title.empty().html(obj.title); 26913 innerToolbar.append(title); 26914 } 26915 if (iL.options.innerToolbar) { 26916 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 26917 } 26918 holder.prepend(innerToolbar); 26919 } 26920 26921 //console.warn('loadContent', arguments); 26922 26923 iL.loadSwitcher(obj, holder, item, opt); 26924 }, 26925 26926 loadSwitcher: function(obj, holder, item, opt) { 26927 var iL = this, 26928 opts = iL.options, 26929 api = { 26930 element: holder, 26931 position: item 26932 }; 26933 26934 switch (obj.type) { 26935 case 'image': 26936 //Trigger the onBeforeLoad callback 26937 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 26938 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 26939 26940 iL.loadImage(obj.URL, function(img) { 26941 //Trigger the onAfterLoad callback 26942 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 26943 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 26944 26945 var width = (img) ? img.width : 400, 26946 height = (img) ? img.height : 200; 26947 26948 holder.data({ 26949 naturalWidth: width, 26950 naturalHeight: height 26951 }); 26952 26953 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 26954 26955 //Trigger the onRender callback 26956 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 26957 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 26958 26959 iL.configureHolder(obj, opt, holder); 26960 }); 26961 26962 break; 26963
26964 case 'video': 26965 holder.data({ 26966 naturalWidth: obj.options.width, 26967 naturalHeight: obj.options.height 26968 }); 26969 26970 if (opt === 'current') { 26971 iL.addContent(holder, obj); 26972 26973 //Trigger the onRender callback 26974 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 26975 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 26976 } else { 26977 $('div.ilightbox-container', holder).empty(); 26978 } 26979 26980 iL.configureHolder(obj, opt, holder); 26981 26982 break; 26983 26984 case 'iframe': 26985 //iL.showLoader(); 26986 holder.data({ 26987 naturalWidth: obj.options.width, 26988 naturalHeight: obj.options.height 26989 }); 26990 26991 iL.configureHolder(obj, opt, holder); 26992 26993 if (opt === 'current') { 26994 var el = iL.addContent(holder, obj); 26995 26996 //Trigger the onRender callback 26997 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 26998 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 26999 27000 //Trigger the onBeforeLoad callback 27001 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 27002 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 27003 27004 el.bind('load', function() { 27005 //Trigger the onAfterLoad callback 27006 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27007 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27008 27009 //iL.hideLoader(); 27010 el.unbind('load'); 27011 }); 27012 } else { 27013 $('div.ilightbox-container', holder).empty(); 27014 } 27015 27016 break; 27017 27018 case 'inline': 27019 var el = $(obj.URL), 27020 content = iL.addContent(holder, obj), 27021 images = findImageInElement(holder); 27022 27023 holder.data({ 27024 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 27025 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 27026 }); 27027 content.children().eq(0).show(); 27028 27029 //Trigger the onRender callback 27030 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27031 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27032 27033 //Trigger the onBeforeLoad callback 27034 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 27035 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 27036 27037 iL.loadImage(images, function() { 27038 //Trigger the onAfterLoad callback 27039 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27040 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27041 27042 iL.configureHolder(obj, opt, holder); 27043 }); 27044 27045 break; 27046 27047 case 'flash': 27048 var el = iL.addContent(holder, obj); 27049 27050 holder.data({ 27051 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 27052 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 27053 }); 27054 27055 //Trigger the onRender callback 27056 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27057 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27058 27059 iL.configureHolder(obj, opt, holder); 27060 27061 break; 27062 27063 case 'ajax': 27064 var ajax = obj.options.ajax || {}; 27065 //Trigger the onBeforeLoad callback 27066 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 27067 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 27068 27069 iL.showLoader(); 27070 $.ajax({ 27071 url: obj.URL || opts.ajaxSetup.url, 27072 data: ajax.data || null, 27073 dataType: ajax.dataType || "html", 27074 type: ajax.type || opts.ajaxSetup.type, 27075 cache: ajax.cache || opts.ajaxSetup.cache, 27076 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 27077 global: ajax.global || opts.ajaxSetup.global, 27078 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 27079 username: ajax.username || opts.ajaxSetup.username, 27080 password: ajax.password || opts.ajaxSetup.password, 27081 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 27082 complete: ajax.complete || opts.ajaxSetup.complete, 27083 success: function(data, textStatus, jqXHR) { 27084 iL.hideLoader(); 27085 27086 var el = $(data), 27087 container = $('div.ilightbox-container', holder), 27088 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 27089 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 27090 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 27091 'overflow': 'hidden' 27092 } : {}; 27093 27094 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 27095 holder.show().data({
27096 naturalWidth: (elWidth || container.outerWidth()), 27097 naturalHeight: (elHeight || container.outerHeight()) 27098 }).hide(); 27099 27100 //Trigger the onRender callback 27101 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27102 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27103 27104 var images = findImageInElement(holder); 27105 iL.loadImage(images, function() { 27106 //Trigger the onAfterLoad callback 27107 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27108 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27109 27110 iL.configureHolder(obj, opt, holder); 27111 }); 27112 27113 opts.ajaxSetup.success(data, textStatus, jqXHR); 27114 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 27115 }, 27116 error: function(jqXHR, textStatus, errorThrown) { 27117 //Trigger the onAfterLoad callback 27118 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27119 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27120 27121 iL.hideLoader(); 27122 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 27123 iL.configureHolder(obj, opt, holder); 27124 27125 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 27126 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 27127 } 27128 }); 27129 27130 break; 27131 27132 case 'html': 27133 var object = obj.URL, 27134 el 27135 container = $('div.ilightbox-container', holder); 27136 27137 if (object[0].nodeName) el = object.clone(); 27138 else { 27139 var dom = $(object); 27140 if (dom.selector) el = $('<div>' + dom + '</div>'); 27141 else el = dom; 27142 } 27143 27144 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 27145 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 27146 27147 iL.addContent(holder, obj); 27148 27149 el.appendTo(document.documentElement).hide(); 27150 27151 //Trigger the onRender callback 27152 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 27153 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 27154 27155 var images = findImageInElement(holder); 27156 27157 //Trigger the onBeforeLoad callback 27158 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 27159 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 27160 27161 iL.loadImage(images, function() { 27162 //Trigger the onAfterLoad callback 27163 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 27164 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 27165 27166 holder.show().data({ 27167 naturalWidth: (elWidth || container.outerWidth()), 27168 naturalHeight: (elHeight || container.outerHeight()) 27169 }).hide(); 27170 el.remove(); 27171 27172 iL.configureHolder(obj, opt, holder); 27173 }); 27174 27175 break; 27176 } 27177 }, 27178 27179 configureHolder: function(obj, opt, holder) { 27180 var iL = this, 27181 vars = iL.vars, 27182 opts = iL.options; 27183 27184 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 27185 27186 if (opt == "current") 27187 var item = vars.current; 27188 else if (opt == "next") 27189 var opacity = opts.styles.nextOpacity, 27190 item = vars.next; 27191 else 27192 var opacity = opts.styles.prevOpacity, 27193 item = vars.prev; 27194 27195 var api = { 27196 element: holder, 27197 position: item 27198 }; 27199 27200 iL.items[item].options.width = iL.items[item].options.width || 0, 27201 iL.items[item].options.height = iL.items[item].options.height || 0; 27202 27203 if (opt == "current") { 27204 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 27205 holder.css(transform, ''); 27206 if (obj.caption) { 27207 iL.setCaption(obj, holder); 27208 var caption = $('div.ilightbox-caption', holder), 27209 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 27210 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
27210Speed); 27211 } 27212 27213 var social = obj.options.social; 27214 if (social) { 27215 iL.setSocial(social, obj.URL, holder); 27216 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 27217 } 27218 27219 //Generate thumbnails 27220 iL.generateThumbnails(); 27221 27222 //Trigger the onShow callback 27223 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27224 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27225 }); 27226 else { 27227 holder.show(); 27228 27229 //Generate thumbnails 27230 iL.generateThumbnails(); 27231 27232 //Trigger the onShow callback 27233 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27234 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27235 } 27236 } else { 27237 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 27238 if (opt == "next") vars.nextLock = false; 27239 else vars.prevLock = false; 27240 27241 //Generate thumbnails 27242 iL.generateThumbnails(); 27243 27244 //Trigger the onShow callback 27245 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27246 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27247 }); 27248 else { 27249 holder.css({ 27250 opacity: opacity 27251 }).show(); 27252 if (opt == "next") vars.nextLock = false; 27253 else vars.prevLock = false; 27254 27255 //Generate thumbnails 27256 iL.generateThumbnails(); 27257 27258 //Trigger the onShow callback 27259 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 27260 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 27261 } 27262 } 27263 27264 setTimeout(function() { 27265 iL.repositionPhoto(); 27266 }, 0); 27267 }, 27268 27269 generateBoxes: function() { 27270 var iL = this, 27271 vars = iL.vars, 27272 opts = iL.options; 27273 27274 if (opts.infinite && vars.total >= 3) { 27275 if (vars.current == vars.total - 1) vars.next = 0; 27276 if (vars.current == 0) vars.prev = vars.total - 1; 27277 } else opts.infinite = false; 27278 27279 //UNCODE addition 27280 if ( typeof iL.items[vars.current] == 'undefined' ) 27281 vars.current = 0; 27282 27283 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 27284 27285 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 27286 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 27287 }, 27288 27289 generateThumbnails: function() { 27290 var iL = this, 27291 vars = iL.vars, 27292 opts = iL.options, 27293 timeOut = null; 27294 27295 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 27296 var thumbnails = vars.thumbnails, 27297 container = $('div.ilightbox-thumbnails-container', thumbnails), 27298 grid = $('div.ilightbox-thumbnails-grid', container), 27299 i = 0; 27300 27301 grid.removeAttr('style').empty(); 27302 27303 $.each(iL.items, function(key, val) { 27304 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 27305 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 27306 thumb = val.options.thumbnail, 27307 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 27308 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 27309 27310 thumbnail.css({ 27311 opacity: 0 27312 }).addClass(isActive); 27313 27314 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 27315 icon.addClass('ilightbox-thumbnail-video'); 27316 thumbnail.append(icon); 27317 } else if (val.options.icon) { 27318 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 27319 thumbnail.append(icon); 27320 } 27321 27322 if (thumb) iL.loadImage(thumb, function(img) { 27323 i++; 27324 if (img) thumbnail.data({ 27325 naturalWidth: img.width, 27326 naturalHeight: img.height 27327 }).append('<img src="' + thumb + '" border="0" />'); 27328 else thumbnail.data({ 27329 naturalWidth: opts.thumbnails.maxWidth, 27330 naturalHeight: opts.thumbnails.maxHeight 27331 }); 27332 27333 clearTimeout(timeOut); 27334 timeOut = setTimeout(function() { 27335 iL.positionThumbnails(thumbnails, container, grid); 27336 }, 20); 27337 setTimeout(function() { 27338 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 27339 }, i * 20); 27340 }); 27341 27342 grid.append(thumbnail); 27343 }); 27344 iL.vars.dontGenerateThumbs = true; 27345 } 27346 }, 27347
27348 positionThumbnails: function(thumbnails, container, grid) { 27349 var iL = this, 27350 vars = iL.vars, 27351 opts = iL.options, 27352 viewport = getViewport(), 27353 path = opts.path.toLowerCase(); 27354 27355 if (!thumbnails) thumbnails = vars.thumbnails; 27356 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 27357 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 27358 27359 var thumbs = $('.ilightbox-thumbnail', grid), 27360 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 27361 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 27362 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 27363 gridHeight = (path == 'horizontal') ? heightAvail : 0, 27364 active = $('.ilightbox-active', grid), 27365 gridCss = {}, 27366 css = {}; 27367 27368 if (arguments.length < 3) { 27369 thumbs.css({ 27370 opacity: opts.thumbnails.normalOpacity 27371 }); 27372 active.css({ 27373 opacity: opts.thumbnails.activeOpacity 27374 }); 27375 } 27376 27377 thumbs.each(function(i) { 27378 var t = $(this), 27379 data = t.data(), 27380 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 27381 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 27382 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 27383 27384 t.css({ 27385 width: dims.width, 27386 height: dims.height 27387 }); 27388 if (path == 'horizontal') t.css({ 27389 'float': 'left' 27390 }); 27391 27392 (path == 'horizontal') ? ( 27393 gridWidth += t.outerWidth() 27394 ) : ( 27395 gridHeight += t.outerHeight() 27396 ); 27397 }); 27398 27399 gridCss = { 27400 width: gridWidth, 27401 height: gridHeight 27402 }; 27403 27404 grid.css(gridCss); 27405 27406 gridCss = {}; 27407 27408 var gridOffset = grid.offset(), 27409 activeOffset = (active.length) ? active.offset() : { 27410 top: parseInt(heightAvail / 2), 27411 left: parseInt(widthAvail / 2) 27412 }; 27413 27414 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 27415 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 27416 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 27417 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 27418 27419 (path == 'horizontal') ? ( 27420 gridCss.top = 0, 27421 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 27422 ) : ( 27423 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 27424 gridCss.left = 0 27425 ); 27426 27427 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 27428 else grid.css(gridCss); 27429 }, 27430 27431 loadImage: function(image, callback) { 27432 if (!$.isArray(image)) image = [image]; 27433 27434 var iL = this, 27435 length = image.length; 27436 27437 if (length > 0) { 27438 iL.showLoader(); 27439 $.each(image, function(index, value) { 27440 var img = new Image(); 27441 img.onload = function() { 27442 length -= 1; 27443 if (length == 0) { 27444 iL.hideLoader(); 27445 callback(img); 27446 } 27447 }; 27448 img.onerror = img.onabort = function() { 27449 length -= 1; 27450 if (length == 0) { 27451 iL.hideLoader(); 27452 callback(false); 27453 } 27454 }; 27455 img.src = image[index]; 27456 }); 27457 } else callback(false); 27458 }, 27459 27460 patchItemsEvents: function() { 27461 var iL = this, 27462 vars = iL.vars, 27463 clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL", 27464 vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL"; 27465 27466 if (iL.context && iL.selector) { 27467 var $items = $(iL.selector, iL.context); 27468 27469 $(iL.context).on(clickEvent, iL.selector, function() { 27470 var $this = $(this), 27471 //UNCODE addition 27472 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 27473 if (UNCODE.isMobile) { 27474 var isCarousel = $this.closest('.owl-carousel'); 27475 if (isCarousel.length) { 27476 if (isCarousel.hasClass('owl-translating')) return false; 27477 } 27478 } 27479 27480 vars.current = key; 27481 vars.next = iL.items[key + 1] ? key + 1 : null; 27482 vars.prev = iL.items[key - 1] ? key - 1 : null; 27483 27484 //UNCODE addition 27485 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 27486 return false;
27487 27488 iL.addContents(); 27489 iL.patchEvents(); 27490 27491 return false; 27492 }).on(vEvent, iL.selector, function() { 27493 return false; 27494 }); 27495 } else 27496 $.each(iL.itemsObject, function(key, val) { 27497 val.on(clickEvent, function() { 27498 vars.current = key; 27499 vars.next = iL.items[key + 1] ? key + 1 : null; 27500 vars.prev = iL.items[key - 1] ? key - 1 : null; 27501 27502 iL.addContents(); 27503 iL.patchEvents(); 27504 27505 return false; 27506 }).on(vEvent, function() { 27507 return false; 27508 }); 27509 }); 27510 }, 27511 27512 dispatchItemsEvents: function() { 27513 var iL = this, 27514 vars = iL.vars, 27515 opts = iL.options; 27516 27517 if (iL.context && iL.selector) 27518 $(iL.context).off('.iL', iL.selector); 27519 else 27520 $.each(iL.itemsObject, function(key, val) { 27521 val.off('.iL'); 27522 }); 27523 }, 27524 27525 refresh: function() { 27526 var iL = this; 27527 27528 iL.dispatchItemsEvents(); 27529 iL.attachItems(); 27530 iL.normalizeItems(); 27531 iL.patchItemsEvents(); 27532 }, 27533 27534 patchEvents: function() { 27535 var iL = this, 27536 vars = iL.vars, 27537 opts = iL.options, 27538 path = opts.path.toLowerCase(), 27539 holders = $('.ilightbox-holder'), 27540 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 27541 durationThreshold = 1000, 27542 horizontalDistanceThreshold = 27543 verticalDistanceThreshold = 100, 27544 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 27545 27546 $win.bind('resize.iLightBox', function() { 27547 var viewport = getViewport(); 27548 27549 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 27550 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 27551 27552 iL.repositionPhoto(null); 27553 if (supportTouch) { 27554 clearTimeout(vars.setTime); 27555 vars.setTime = setTimeout(function() { 27556 var scrollTop = getScrollXY().y; 27557 window.scrollTo(0, scrollTop - 30); 27558 window.scrollTo(0, scrollTop + 30); 27559 window.scrollTo(0, scrollTop); 27560 }, 2000); 27561 } 27562 if (vars.thumbs) iL.positionThumbnails(); 27563 }).bind('keydown.iLightBox', function(event) { 27564 if (opts.controls.keyboard) { 27565 switch (event.keyCode) { 27566 case 13: 27567 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 27568 break; 27569 case 27: 27570 if (opts.keyboard.esc) iL.closeAction(); 27571 break; 27572 case 37: 27573 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 27574 break; 27575 case 38: 27576 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 27577 break; 27578 case 39: 27579 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 27580 break; 27581 case 40: 27582 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 27583 break; 27584 } 27585 } 27586 }); 27587 27588 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 27589 iL.doFullscreen(); 27590 }); 27591 27592 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 27593 return arr.lastIndexOf(e) === i; 27594 }), 27595 holderEvents = ""; 27596 27597 $.each(holderEventsArr, function(key, val) { 27598 if (key != 0) holderEvents += ' '; 27599 holderEvents += val; 27600 }); 27601 27602 $doc.on(clickEvent, '.ilightbox-overlay', function() { 27603 if (opts.overlay.blur) iL.closeAction(); 27604 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 27605 iL.moveTo('next'); 27606 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 27607 iL.moveTo('prev'); 27608 }).on(clickEvent, '.ilightbox-thumbnail', function() { 27609 var t = $(this), 27610 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 27611 index = thumbs.index(t); 27612 27613 if (index != vars.current) iL.goTo(index); 27614 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 27615 var caption = $('div.ilightbox-caption', vars.holder), 27616 social = $('div.ilightbox-social', vars.holder), 27617 fadeSpeed = opts.effects.fadeSpeed; 27618 27619 if (vars.nextLock || vars.prevLock) { 27620 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 27621 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 27622 27623 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 27624 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 27625 } else { 27626 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 27627 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 27628 27629 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 27630 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 27631 } 27632 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 27633 if (e.type == 'mouseenter') vars.lockWheel = true; 27634 else vars.lockWheel = false;
27635 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 27636 var t = $(this); 27637 27638 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 27639 else if (t.hasClass('ilightbox-play')) { 27640 iL.resume(); 27641 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 27642 } else if (t.hasClass('ilightbox-pause')) { 27643 iL.pause(); 27644 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 27645 } else iL.closeAction(); 27646 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 27647 // prevent scrolling 27648 e.preventDefault(); 27649 }); 27650 27651 function mouseMoveHandler(e) { 27652 if (!vars.isMobile) { 27653 if (!vars.mouseID) { 27654 vars.hideableElements.show(); 27655 } 27656 27657 vars.mouseID = clearTimeout(vars.mouseID); 27658 27659 if (buttonsArray.indexOf(e.target) === -1) 27660 vars.mouseID = setTimeout(function() { 27661 vars.hideableElements.hide(); 27662 vars.mouseID = clearTimeout(vars.mouseID); 27663 }, 3000); 27664 } 27665 } 27666 27667 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 27668 27669 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 27670 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 27671 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 27672 }); 27673 27674 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'), 27675 delay = false; 27676 27677 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 27678 event.preventDefault(); 27679 if (delay) return; 27680 delay = true; 27681 if (!vars.lockWheel) { 27682 event.preventDefault(); 27683 if (delta < 0) { 27684 iL.moveTo('next'); 27685 } else if (delta > 0) { 27686 iL.moveTo('prev'); 27687 } 27688 } 27689 setTimeout(function(){
27690 delay = false; 27691 }, 2000); 27692 }); 27693 27694 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 27695 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 27696 27697 vars.BODY.addClass('ilightbox-closedhand'); 27698 27699 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 27700 scrollTop = $doc.scrollTop(), 27701 scrollLeft = $doc.scrollLeft(), 27702 offsets = [ 27703 holders.eq(0).offset(), 27704 holders.eq(1).offset(), 27705 holders.eq(2).offset() 27706 ], 27707 offSet = [{ 27708 top: offsets[0].top - scrollTop, 27709 left: offsets[0].left - scrollLeft 27710 }, { 27711 top: offsets[1].top - scrollTop, 27712 left: offsets[1].left - scrollLeft 27713 }, { 27714 top: offsets[2].top - scrollTop, 27715 left: offsets[2].left - scrollLeft 27716 }], 27717 start = { 27718 time: (new Date()).getTime(), 27719 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 27720 }, 27721 stop; 27722 27723 function moveEachHandler(i) { 27724 var t = $(this), 27725 offset = offSet[i], 27726 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 27727 27728 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 27729 } 27730 27731 function moveHandler(event) { 27732 27733 if (!start) return; 27734 27735 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 27736 27737 stop = { 27738 time: (new Date()).getTime(), 27739 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 27740 }; 27741 27742 holders.each(moveEachHandler); 27743 27744 // prevent scrolling 27745 event.preventDefault(); 27746 } 27747 27748 function repositionHolders() { 27749 holders.each(function() { 27750 var t = $(this), 27751 offset = t.data('offset') || { 27752 top: t.offset().top - scrollTop, 27753 left: t.offset().left - scrollLeft 27754 }, 27755 top = offset.top, 27756 left = offset.left; 27757 27758 t.css(transform, gpuAcceleration).stop().animate({ 27759 top: top, 27760 left: left 27761 }, 500, 'easeOutCirc', function() { 27762 t.css(transform, ''); 27763 }); 27764 }); 27765 } 27766 27767 holders.bind(touchMoveEvent, moveHandler); 27768 $doc.one(touchStopEvent, function(event) { 27769 holders.unbind(touchMoveEvent, moveHandler); 27770 27771 vars.BODY.removeClass('ilightbox-closedhand'); 27772 27773 if (start && stop) { 27774 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 27775 if (start.coords[0] > stop.coords[0]) { 27776 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 27777 else { 27778 vars.isSwipe = true; 27779 iL.moveTo('next'); 27780 } 27781 } else { 27782 if (vars.current == 0 && !opts.infinite) repositionHolders(); 27783 else { 27784 vars.isSwipe = true; 27785 iL.moveTo('prev'); 27786 } 27787 } 27788 } 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) { 27789 if (start.coords[1] > stop.coords[1]) { 27790 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 27791 else { 27792 vars.isSwipe = true; 27793 iL.moveTo('next'); 27794 } 27795 } else { 27796 if (vars.current == 0 && !opts.infinite) repositionHolders(); 27797 else { 27798 vars.isSwipe = true; 27799 iL.moveTo('prev'); 27800 } 27801 } 27802 } else repositionHolders(); 27803 } 27804 start = stop = undefined; 27805 }); 27806 }); 27807 27808 }, 27809 27810 goTo: function(index) { 27811 var iL = this, 27812 vars = iL.vars, 27813 opts = iL.options, 27814 diff = (index - vars.current); 27815 27816 if (opts.infinite) { 27817 if (index == vars.total - 1 && vars.current == 0) diff = -1; 27818 if (vars.current == vars.total - 1 && index == 0) diff = 1; 27819 } 27820 27821 if (diff == 1) iL.moveTo('next'); 27822 else if (diff == -1) iL.moveTo('prev'); 27823 else { 27824 27825 if (vars.nextLock || vars.prevLock) return false; 27826 27827 //Trigger the onBeforeChange callback 27828 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 27829 27830 if (opts.linkId) { 27831 vars.hashLock = true; 27832 window.location.hash = opts.linkId + '/' + index; 27833 } 27834 27835 if (iL.items[index]) { 27836 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 27837 else iL.vars.lockWheel = false;
27838 27839 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 27840 else vars.lockSwipe = false; 27841 } 27842 27843 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 27844 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 27845 }); 27846 27847 vars.current = index; 27848 vars.next = index + 1; 27849 vars.prev = index - 1; 27850 27851 iL.createUI(); 27852 27853 setTimeout(function() { 27854 iL.generateBoxes(); 27855 }, opts.effects.loadedFadeSpeed + 50); 27856 27857 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 27858 iL.positionThumbnails(); 27859 27860 if (opts.linkId) setTimeout(function() { 27861 vars.hashLock = false; 27862 }, 55); 27863 27864 // Configure arrow buttons 27865 if (!opts.infinite) { 27866 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 27867 27868 if (vars.current == 0) { 27869 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 27870 } 27871 if (vars.current >= vars.total - 1) { 27872 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 27873 } 27874 } 27875 27876 // Reset next cycle timeout 27877 iL.resetCycle(); 27878 27879 //Trigger the onAfterChange callback 27880 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 27881 } 27882 }, 27883 27884 moveTo: function(side) { 27885 var iL = this, 27886 vars = iL.vars, 27887 opts = iL.options, 27888 path = opts.path.toLowerCase(), 27889 viewport = getViewport(), 27890 switchSpeed = opts.effects.switchSpeed; 27891 27892 if (vars.nextLock || vars.prevLock) return false; 27893 else { 27894 27895 var item = (side == "next") ? vars.next : vars.prev; 27896 27897 if (opts.linkId) { 27898 vars.hashLock = true; 27899 window.location.hash = opts.linkId + '/' + item; 27900 } 27901 27902 if (side == "next") { 27903 if (!iL.items[item]) return false; 27904 var firstHolder = vars.nextPhoto, 27905 secondHolder = vars.holder, 27906 lastHolder = vars.prevPhoto, 27907 firstClass = 'ilightbox-prev', 27908 secondClass = 'ilightbox-next'; 27909 } else if (side == "prev") { 27910 if (!iL.items[item]) return false; 27911 var firstHolder = vars.prevPhoto, 27912 secondHolder = vars.holder, 27913 lastHolder = vars.nextPhoto, 27914 firstClass = 'ilightbox-next', 27915 secondClass = 'ilightbox-prev'; 27916 } 27917 27918 //Trigger the onBeforeChange callback 27919 if (typeof opts.callback.onBeforeChange == 'function') 27920 opts.callback.onBeforeChange.call(iL, iL.ui); 27921 27922 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 27923 27924 var captionFirst = $('div.ilightbox-caption', secondHolder), 27925 socialFirst = $('div.ilightbox-social', secondHolder); 27926 27927 if (captionFirst.length) 27928 captionFirst.stop().fadeOut(switchSpeed, function() { 27929 $(this).remove(); 27930 }); 27931 if (socialFirst.length) 27932 socialFirst.stop().fadeOut(switchSpeed, function() { 27933 $(this).remove(); 27934 }); 27935 27936 if (iL.items[item].caption) { 27937 iL.setCaption(iL.items[item], firstHolder); 27938 var caption = $('div.ilightbox-caption', firstHolder), 27939 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 27940 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 27941 } 27942 27943 var social = iL.items[item].options.social; 27944 if (social) { 27945 iL.setSocial(social, iL.items[item].URL, firstHolder); 27946 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 27947 } 27948 27949 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 27950 val.removeClass('ilightbox-next ilightbox-prev'); 27951 }); 27952 27953 var firstOffset = firstHolder.data('offset'), 27954 winW = (viewport.width - (opts.styles.pageOffsetX)), 27955 winH = (viewport.height - (opts.styles.pageOffsetY)), 27956 width = firstOffset.newDims.width, 27957 height = firstOffset.newDims.height, 27958 thumbsOffset = firstOffset.thumbsOffset, 27959 diff = firstOffset.diff, 27960 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 27961 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 27962 27963 var secondOffset = secondHolder.data('offset'), 27964 object = secondOffset.object; 27965 27966 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 27967 var objRatio = width / height; 27968 height = height - vars.captionHeight; 27969 width = height * objRatio; 27970 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 27971 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 27972 }*/ 27973 27974 firstHolder.show().css(transform, gpuAcceleration).animate({ 27975 top: top, 27976 left: left, 27977 opacity: 1 27978 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 27979 firstHolder.css(transform, ''); 27980 }); 27981 27982 $('div.ilightbox-container', firstHolder).animate({ 27983 width: width, 27984 height: height 27985 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 27986 27987 diff = secondOffset.diff; 27988 27989 width = secondOffset.newDims.width, 27990 height = secondOffset.newDims.height; 27991 27992 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 27993 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 27994 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 27995 27996 if (side == 'prev') 27997 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 27998 else { 27999 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 28000 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 28001 } 28002 28003 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 28004 var objRatio = width / height; 28005 height = height - vars.captionHeight; 28006 width = height * objRatio; 28007 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 28008 }*/ 28009 28010 $('div.ilightbox-container', secondHolder).animate({ 28011 width: width, 28012 height: height 28013 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 28014 28015 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 28016 top: top, 28017 left: left, 28018 opacity: opts.styles.prevOpacity, 28019 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 28020 secondHolder.css(transform, ''); 28021
28022 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 28023 iL.positionThumbnails(); 28024 28025 if (iL.items[item]) { 28026 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 28027 else vars.lockWheel = false; 28028 28029 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 28030 else vars.lockSwipe = false; 28031 } 28032 28033 vars.isSwipe = false; 28034 28035 // Remove iframe & video from previous slide 28036 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 28037 $('div.ilightbox-container', secondHolder).empty(); 28038 } 28039 28040 if (side == "next") { 28041 vars.nextPhoto = lastHolder, 28042 vars.prevPhoto = secondHolder, 28043 vars.holder = firstHolder; 28044 28045 vars.nextPhoto.hide(); 28046 28047 vars.next = vars.next + 1, 28048 vars.prev = vars.current, 28049 vars.current = vars.current + 1; 28050 28051 if (opts.infinite) { 28052 if (vars.current > vars.total - 1) vars.current = 0; 28053 if (vars.current == vars.total - 1) vars.next = 0; 28054 if (vars.current == 0) vars.prev = vars.total - 1; 28055 } 28056 28057 iL.createUI(); 28058 28059 if (!iL.items[vars.next]) 28060 vars.nextLock = false; 28061 else 28062 iL.loadContent(iL.items[vars.next], 'next'); 28063 } else { 28064 vars.prevPhoto = lastHolder; 28065 vars.nextPhoto = secondHolder; 28066 vars.holder = firstHolder; 28067 28068 vars.prevPhoto.hide(); 28069 28070 vars.next = vars.current; 28071 vars.current = vars.prev; 28072 vars.prev = vars.current - 1; 28073 28074 if (opts.infinite) { 28075 if (vars.current == vars.total - 1) vars.next = 0; 28076 if (vars.current == 0) vars.prev = vars.total - 1; 28077 } 28078 28079 iL.createUI(); 28080 28081 if (!iL.items[vars.prev]) 28082 vars.prevLock = false; 28083 else 28084 iL.loadContent(iL.items[vars.prev], 'prev'); 28085 } 28086 28087 // Add iframe & video content for current slide 28088 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 28089 iL.loadContent(iL.items[vars.current], 'current'); 28090 } 28091 28092 if (opts.linkId) setTimeout(function() { 28093 vars.hashLock = false; 28094 }, 55); 28095 28096 // Configure arrow buttons 28097 if (!opts.infinite) { 28098 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 28099 28100 if (vars.current == 0) 28101 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 28102 if (vars.current >= vars.total - 1) 28103 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 28104 } 28105 28106 iL.repositionPhoto(); 28107 28108 // Reset next cycle timeout 28109 iL.resetCycle(); 28110 28111 //Trigger the onAfterChange callback 28112 if (typeof opts.callback.onAfterChange == 'function') 28113 opts.callback.onAfterChange.call(iL, iL.ui); 28114 }); 28115 28116 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 28117 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 28118 28119 lastHolder.css(transform, gpuAcceleration).animate({ 28120 top: top, 28121 left: left, 28122 opacity: opts.styles.nextOpacity 28123 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 28124 lastHolder.css(transform, ''); 28125 }).addClass(secondClass); 28126 } 28127 }, 28128 28129 setCaption: function(obj, target) { 28130 var iL = this, 28131 caption = $('<div class="ilightbox-caption"></div>'); 28132 28133 if (obj.caption) { 28134 caption.html(obj.caption); 28135 $('div.ilightbox-container', target).append(caption); 28136 } 28137 }, 28138 28139 normalizeSocial: function(obj, url) { 28140 var iL = this, 28141 vars = iL.vars, 28142 opts = iL.options, 28143 baseURL = window.location.href; 28144 28145 $.each(obj, function(key, value) { 28146 if (!value) 28147 return true; 28148 28149 var item = key.toLowerCase(), 28150 source, text; 28151 28152 switch (item) { 28153 case 'facebook': 28154 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 28155 text = "Share on Facebook"; 28156 break; 28157 case 'twitter': 28158 source = "http://twitter.com/home?status={URL}", 28159 text = "Share on Twitter"; 28160 break; 28161 case 'digg': 28162 source = "http://digg.com/submit?phase=2&url={URL}", 28163 text = "Share on Digg"; 28164 break; 28165 case 'reddit': 28166 source = "http://reddit.com/submit?url={URL}", 28167 text = "Share on reddit"; 28168 break; 28169 } 28170 28171 obj[key] = { 28172 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 28173 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 28174 text: value.text || text || "Share on " + key, 28175 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 28176 height: value.height || 360 28177 }; 28178 28179 }); 28180 28181 return obj; 28182 }, 28183 28184 setSocial: function(obj, url, target) { 28185 var iL = this, 28186 socialBar = $('<div class="ilightbox-social"></div>'), 28187 buttons = '<ul>'; 28188 28189 obj = iL.normalizeSocial(obj, url); 28190 28191 $.each(obj, function(key, value) { 28192 var item = key.toLowerCase(), 28193 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, '+')); 28194 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>'; 28195 }); 28196 28197 buttons += '</ul>'; 28198 28199 socialBar.html(buttons); 28200 $('div.ilightbox-container', target).append(socialBar); 28201 }, 28202 28203 fullScreenAction: function() { 28204 var iL = this, 28205 vars = iL.vars; 28206 28207 if (fullScreenApi.supportsFullScreen) { 28208 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 28209 else fullScreenApi.requestFullScreen(document.documentElement); 28210 } else { 28211 iL.doFullscreen(); 28212 } 28213 }, 28214 28215 doFullscreen: function() { 28216 var iL = this, 28217 vars = iL.vars, 28218 viewport = getViewport(), 28219 opts = iL.options; 28220 28221 if (opts.fullAlone) { 28222 var currentHolder = vars.holder, 28223 current = iL.items[vars.current], 28224 windowWidth = viewport.width, 28225 windowHeight = viewport.height, 28226 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 28227 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 28228 28229 if (!vars.isInFullScreen) { 28230 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 28231 vars.overlay.css({ 28232 opacity: 1 28233 }); 28234 28235 $.each(hideElements, function(i, element) { 28236 element.hide(); 28237 }); 28238 28239 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 28240 28241 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
28242 naturalWidthOld: currentHolder.data('naturalWidth'), 28243 naturalHeightOld: currentHolder.data('naturalHeight'), 28244 naturalWidth: windowWidth, 28245 naturalHeight: windowHeight 28246 }); 28247 else { 28248 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 28249 newWidth = windowWidth, 28250 newHeight = windowHeight, 28251 width = currentHolder.data('naturalWidth'), 28252 height = currentHolder.data('naturalHeight'); 28253 28254 if (viewport.toLowerCase() == 'fill') { 28255 newHeight = (newWidth / width) * height; 28256 28257 if (newHeight < windowHeight) { 28258 newWidth = (windowHeight / height) * width, 28259 newHeight = windowHeight; 28260 } 28261 } else if (viewport.toLowerCase() == 'fit') { 28262 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 28263 28264 newWidth = dims.width, 28265 newHeight = dims.height; 28266 } else if (viewport.toLowerCase() == 'stretch') { 28267 newWidth = newWidth, 28268 newHeight = newHeight; 28269 } else { 28270 var scale = (width > newWidth || height > newHeight) ? true : false, 28271 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 28272 newWidth = dims.width, 28273 newHeight = dims.height; 28274 } 28275 28276 currentHolder.data({ 28277 naturalWidthOld: currentHolder.data('naturalWidth'), 28278 naturalHeightOld: currentHolder.data('naturalHeight'), 28279 naturalWidth: newWidth, 28280 naturalHeight: newHeight 28281 }); 28282 } 28283 28284 $.each(elements, function(key, val) { 28285 val.addClass('ilightbox-fullscreen'); 28286 }); 28287 28288 //Trigger the onEnterFullScreen callback 28289 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 28290 } else { 28291 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 28292 vars.overlay.css({ 28293 opacity: iL.options.overlay.opacity 28294 }); 28295 28296 $.each(hideElements, function(i, element) { 28297 element.show(); 28298 }); 28299 28300 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 28301 28302 currentHolder.data({ 28303 naturalWidth: currentHolder.data('naturalWidthOld'), 28304 naturalHeight: currentHolder.data('naturalHeightOld'), 28305 naturalWidthOld: null, 28306 naturalHeightOld: null 28307 }); 28308 28309 $.each(elements, function(key, val) { 28310 val.removeClass('ilightbox-fullscreen'); 28311 }); 28312 28313 //Trigger the onExitFullScreen callback 28314 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 28315 } 28316 } else { 28317 if (!vars.isInFullScreen) vars.isInFullScreen = true; 28318 else vars.isInFullScreen = false; 28319 } 28320 iL.repositionPhoto(true); 28321 }, 28322 28323 closeAction: function() { 28324 var iL = this, 28325 vars = iL.vars, 28326 opts = iL.options; 28327 28328 $win.unbind('.iLightBox'); 28329 $doc.off('.iLightBox'); 28330 28331 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 28332 28333 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 28334 28335 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 28336 vars.overlay.remove(); 28337 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 28338 }); 28339 else { 28340 vars.overlay.remove(); 28341 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 28342 } 28343 28344 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 28345 28346 $.each(fadeOuts, function(i, element) { 28347 element.removeAttr('style').remove(); 28348 }); 28349 28350 vars.dontGenerateThumbs = vars.isInFullScreen = false; 28351 28352 window.iLightBox = null; 28353 28354 if (opts.linkId) { 28355 vars.hashLock = true; 28356 removeHash(); 28357 setTimeout(function() { 28358 vars.hashLock = false; 28359 }, 55); 28360 } 28361 28362 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 28363 28364 //Trigger the onHide callback 28365 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 28366 }, 28367 28368 repositionPhoto: function() { 28369 var iL = this, 28370 vars = iL.vars, 28371 opts = iL.options, 28372 path = opts.path.toLowerCase(), 28373 viewport = getViewport(), 28374 winWidth = viewport.width, 28375 winHeight = viewport.height; 28376 28377 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 28378 28379 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 28380 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 28381 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 28382 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 28383 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, 28384 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))); 28385 28386 var elObject = { 28387 type: 'current', 28388 width: width, 28389 height: height, 28390 item: iL.items[vars.current], 28391 offsetW: offsetW, 28392 offsetH: offsetH,
28393 thumbsOffsetW: thumbsOffsetW, 28394 thumbsOffsetH: thumbsOffsetH, 28395 animate: arguments.length, 28396 holder: vars.holder 28397 }; 28398 28399 iL.repositionEl(elObject); 28400 28401 if (iL.items[vars.next]) { 28402 elObject = $.extend(elObject, { 28403 type: 'next', 28404 item: iL.items[vars.next], 28405 offsetX: opts.styles.nextOffsetX, 28406 offsetY: opts.styles.nextOffsetY, 28407 holder: vars.nextPhoto 28408 }); 28409 28410 iL.repositionEl(elObject); 28411 } 28412 28413 if (iL.items[vars.prev]) { 28414 elObject = $.extend(elObject, { 28415 type: 'prev', 28416 item: iL.items[vars.prev], 28417 offsetX: opts.styles.nextOffsetX, 28418 offsetY: opts.styles.prevOffsetY, 28419 holder: vars.prevPhoto 28420 }); 28421 28422 iL.repositionEl(elObject); 28423 } 28424 28425 var loaderCss = (path == "horizontal") ? { 28426 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 28427 } : { 28428 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 28429 }; 28430 vars.loader.css(loaderCss); 28431 }, 28432 28433 repositionEl: function(obj) { 28434 var iL = this, 28435 vars = iL.vars, 28436 opts = iL.options, 28437 path = opts.path.toLowerCase(), 28438 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 28439 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 28440 itemParent = obj.item, 28441 item = obj.item.options, 28442 holder = obj.holder, 28443 offsetX = obj.offsetX || 0, 28444 offsetY = obj.offsetY || 0, 28445 //Uncode change ##START## 28446 toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0, 28447 //Uncode change ##END## 28448 thumbsOffsetW = obj.thumbsOffsetW, 28449 thumbsOffsetH = obj.thumbsOffsetH; 28450 28451 if (obj.type == 'current') { 28452 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); 28453 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); 28454 } else { 28455 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 28456 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 28457 } 28458 28459 28460 //Uncode change ##START## 28461 heightAvail = parseInt(heightAvail - toolbarHeight); 28462 // heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 28463 //Uncode change ##END## 28464 28465 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 28466 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 28467 28468 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 28469 width: width, 28470 height: height 28471 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 28472 newDims = $.extend({}, dims, {}); 28473 28474 if (obj.type == 'prev' || obj.type == 'next') 28475 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 28476 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 28477 else 28478 width = dims.width, 28479 height = dims.height; 28480 28481 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 28482 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); 28483 28484 switch (obj.type) { 28485 case 'current': 28486 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 28487 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 28488 break; 28489
28490 case 'next': 28491 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 28492 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 28493 break; 28494 28495 case 'prev': 28496 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 28497 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 28498 break; 28499 } 28500 28501 holder.data('offset', { 28502 top: top, 28503 left: left, 28504 newDims: newDims, 28505 diff: { 28506 W: widthDiff, 28507 H: heightDiff 28508 }, 28509 thumbsOffset: { 28510 W: thumbsOffsetW, 28511 H: thumbsOffsetH 28512 }, 28513 object: obj 28514 }); 28515 28516 var opacityMobile; 28517 if ( isMobile ) { 28518 opacityMobile = { 28519 opacity: 1, 28520 top: top, 28521 left: left 28522 }; 28523 } else { 28524 opacityMobile = { 28525 top: top, 28526 left: left 28527 }; 28528 } 28529 28530 if (obj.animate > 0 && opts.effects.reposition) { 28531 holder.css(transform, gpuAcceleration).stop().animate( 28532 opacityMobile, 28533 opts.effects.repositionSpeed, 'easeOutCirc', function() { 28534 holder.css(transform, ''); 28535 }); 28536 $('div.ilightbox-container', holder).stop().animate({ 28537 width: width, 28538 height: height 28539 }, opts.effects.repositionSpeed, 'easeOutCirc'); 28540 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 28541 width: width 28542 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 28543 $(this).css('overflow', 'visible'); 28544 }); 28545 } else { 28546 holder.css(opacityMobile); 28547 $('div.ilightbox-container', holder).css({ 28548 width: width, 28549 height: height 28550 }); 28551 $('div.ilightbox-inner-toolbar', holder).css({ 28552 width: width 28553 }); 28554 } 28555 }, 28556 28557 28558 resume: function(priority) { 28559 var iL = this, 28560 vars = iL.vars, 28561 opts = iL.options; 28562 28563 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 28564 return; 28565 } 28566 28567 vars.isPaused = 0; 28568 28569 if (vars.cycleID) { 28570 vars.cycleID = clearTimeout(vars.cycleID); 28571 } 28572 28573 vars.cycleID = setTimeout(function() { 28574 if (vars.current == vars.total - 1) iL.goTo(0); 28575 else iL.moveTo('next'); 28576 }, opts.slideshow.pauseTime); 28577 }, 28578 28579 pause: function(priority) { 28580 var iL = this, 28581 vars = iL.vars, 28582 opts = iL.options; 28583 28584 if (priority < vars.isPaused) { 28585 return; 28586 } 28587 28588 vars.isPaused = priority || 100; 28589 28590 if (vars.cycleID) { 28591 vars.cycleID = clearTimeout(vars.cycleID); 28592 } 28593 }, 28594 28595 resetCycle: function() { 28596 var iL = this, 28597 vars = iL.vars, 28598 opts = iL.options; 28599 28600 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 28601 iL.resume(); 28602 } 28603 }, 28604 28605 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 28606 var iL = this; 28607 28608 if (!width) factor = height / height_old; 28609 else if (!height) factor = width / width_old; 28610 else factor = min(width / width_old, height / height_old); 28611 28612 if (!thumb) { 28613 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 28614 else if (factor < iL.options.minScale) factor = iL.options.minScale; 28615 } 28616 28617 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 28618 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 28619 28620 return { 28621 width: final_width, 28622 height: final_height, 28623 ratio: factor 28624 }; 28625 }, 28626 28627 setOption: function(options) { 28628 var iL = this; 28629 28630 iL.options = $.extend(true, iL.options, options || {}); 28631 iL.refresh(); 28632 }, 28633 28634 availPlugins: function() { 28635 var iL = this, 28636 testEl = document.createElement("video"); 28637 28638 iL.plugins = { 28639 flash: !isMobile, 28640 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 28641 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 28642 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 28643 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 28644 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 28645 }; 28646 }, 28647 28648 addContent: function(element, obj) { 28649 var iL = this, 28650 el; 28651 28652 switch (obj.type) { 28653 case 'video': 28654 var HTML5 = false, 28655 videoType = obj.videoType, 28656 html5video = obj.options.html5video; 28657 28658 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 28659 obj.ext = 'mp4', 28660 obj.URL = html5video.h264 || obj.URL; 28661 else if (html5video.webm && iL.plugins.html5WebM) 28662 obj.ext = 'webm', 28663 obj.URL = html5video.webm || obj.URL; 28664 else if (html5video.ogg && iL.plugins.html5Vorbis) 28665 obj.ext = 'ogv', 28666 obj.URL = html5video.ogg || obj.URL; 28667 28668 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 28669 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 28670 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 28671 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 28672 28673 if (HTML5) { 28674 el = $('<video />
28674', { 28675 "width": "100%", 28676 "height": "100%", 28677 "preload": html5video.preload, 28678 "autoplay": html5video.autoplay, 28679 "loop": html5video.loop, 28680 "poster": html5video.poster, 28681 "controls": html5video.controls, 28682 "controlslist": "nodownload" 28683 }).append($('<source />', { 28684 "src": obj.URL, 28685 "type": videoType 28686 })); 28687 } else { 28688 if (!iL.plugins.quicktime) el = $('<span />', { 28689 "class": "ilightbox-alert", 28690 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 28691 }); 28692 else { 28693 28694 el = $('<object />', { 28695 "type": "video/quicktime", 28696 "pluginspage": pluginspages.quicktime 28697 }).attr({ 28698 "data": obj.URL, 28699 "width": "100%", 28700 "height": "100%" 28701 }).append($('<param />', { 28702 "name": "src", 28703 "value": obj.URL 28704 })).append($('<param />', { 28705 "name": "autoplay", 28706 "value": "false" 28707 })).append($('<param />', { 28708 "name": "loop", 28709 "value": "false" 28710 })).append($('<param />', { 28711 "name": "scale", 28712 "value": "tofit" 28713 })); 28714 28715 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 28716 } 28717 } 28718 28719 break; 28720 28721 case 'flash': 28722 if (!iL.plugins.flash) el = $('<span />', { 28723 "class": "ilightbox-alert", 28724 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 28725 }); 28726 else { 28727 var flashvars = "", 28728 i = 0; 28729 28730 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 28731 if (i != 0) flashvars += "&"; 28732 flashvars += k + "=" + encodeURIComponent(v); 28733 i++; 28734 }); 28735 else flashvars = null; 28736 28737 el = $('<embed />').attr({ 28738 "type": "application/x-shockwave-flash", 28739 "src": obj.URL, 28740 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 28741 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 28742 "quality": "high", 28743 "bgcolor": "#000000", 28744 "play": "true", 28745 "loop": "true", 28746 "menu": "true", 28747 "wmode": "transparent", 28748 "scale": "showall", 28749 "allowScriptAccess": "always", 28750 "allowFullScreen": "true", 28751 "flashvars": flashvars, 28752 "fullscreen": "yes" 28753 }); 28754 } 28755 28756 break; 28757 28758 case 'iframe': 28759 el = $('<iframe />').attr({ 28760 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 28761 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 28762 src: obj.URL, 28763 frameborder: 0, 28764 'hspace': 0, 28765 'vspace': 0, 28766 'scrolling': supportTouch ? 'auto' : 'scroll', 28767 'webkitAllowFullScreen': '', 28768 'mozallowfullscreen': '', 28769 'allowFullScreen': '' 28770 }); 28771 28772 break; 28773 28774 case 'inline': 28775 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 28776 28777 break; 28778 28779 case 'html': 28780 var object = obj.URL, 28781 el; 28782 28783 if (object[0].nodeName) { 28784 el = $('<div class="ilightbox-wrapper"></div>').html(object); 28785 } else { 28786 var dom = $(obj.URL), 28787 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 28788 el = $('<div class="ilightbox-wrapper"></div>').html(html); 28789 } 28790 28791 break; 28792 } 28793 28794 $('div.ilightbox-container', element).empty().html(el); 28795 28796 // For fixing Chrome about just playing the video for first time 28797 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 28798 var src = el[0].currentSrc + '?' + floor(random() * 30000); 28799 el[0].currentSrc = src; 28800 el[0].src = src; 28801 }); 28802 28803 return el; 28804 }, 28805 28806 ogpRecognition: function(obj, callback) { 28807 var iL = this, 28808 url = obj.URL; 28809 28810 iL.showLoader(); 28811 doAjax(url, function(data) { 28812 iL.hideLoader(); 28813 if (data) { 28814 var object = new Object(); 28815 28816 object.length = false, 28817 object.url = data.url; 28818 28819 if (data.status == 200) { 28820 var result = data.results, 28821 type = result.type, 28822 source = result.source; 28823 28824 object.source = source.src, 28825 object.width = source.width && parseInt(source.width) || 0, 28826 object.height = source.height && parseInt(source.height) || 0, 28827 object.type = type, 28828 object.thumbnail = source.thumbnail || result.images && result.images[0], 28829 object.html5video = result.html5video || {}, 28830 object.length = true; 28831 28832 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 28833 else if (source.type.indexOf("video/") != -1) object.type = "video"; 28834 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 28835 else if (source.type.indexOf("image/") != -1) object.type = "image"; 28836 28837 } else if (typeof data.response != 'undefined') 28838 throw data.response; 28839 28840 callback.call(this, object.length ? object : false); 28841 } 28842 }); 28843 }, 28844 28845 hashChangeHandler: function(url) { 28846 var iL = this, 28847 vars = iL.vars, 28848 opts = iL.options, 28849 URL = url || window.location.href, 28850 hash = parseURI(URL).hash, 28851 split = hash.split('/'), 28852 index = split[1]; 28853 28854 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 28855 28856 if (index) { 28857 var target = split[1] || 0; 28858 if (iL.items[target]) {
28859 var overlay = $('.ilightbox-overlay'); 28860 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 28861 iL.goTo(target); 28862 } else { 28863 iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click'); 28864 //iL.goTo(target); 28865 } 28866 } else { 28867 var overlay = $('.ilightbox-overlay'); 28868 if (overlay.length) iL.closeAction(); 28869 } 28870 } else { 28871 var overlay = $('.ilightbox-overlay'); 28872 if (overlay.length) iL.closeAction(); 28873 } 28874 } 28875 }; 28876 28877 /** 28878 * Parse style to pixels. 28879 * 28880 * @param {Object} $element jQuery object with element. 28881 * @param {Property} property CSS property to get the pixels from. 28882 * 28883 * @return {Int} 28884 */ 28885 function getPixel($element, property) { 28886 return parseInt($element.css(property), 10) || 0; 28887 } 28888 28889 /** 28890 * Make sure that number is within the limits. 28891 * 28892 * @param {Number} number 28893 * @param {Number} min 28894 * @param {Number} max 28895 * 28896 * @return {Number} 28897 */ 28898 function within(number, min, max) { 28899 return number < min ? min : number > max ? max : number; 28900 } 28901 28902 /** 28903 * Get viewport/window size (width and height). 28904 * 28905 * @return {Object} 28906 */ 28907 function getViewport() { 28908 var e = window, 28909 a = 'inner'; 28910 if (!('innerWidth' in window)) { 28911 a = 'client'; 28912 e = document.documentElement || document.body; 28913 } 28914 return { 28915 width: e[a + 'Width'], 28916 height: e[a + 'Height'] 28917 } 28918 } 28919 28920 /** 28921 * Remove hash tag from the URL 28922 * 28923 * @return {Void} 28924 */ 28925 function removeHash() { 28926 var scroll = getScrollXY(); 28927 28928 //UNCODE change 28929 // window.location.hash = ""; 28930 // history.pushState("", document.title, window.location.pathname + window.location.search); 28931 history.replaceState({}, document.title, window.location.pathname + window.location.search); 28932 28933 // Restore the scroll offset, should be flicker free 28934 window.scrollTo(scroll.x, scroll.y); 28935 } 28936 28937 /** 28938 * Do the ajax requests with callback. 28939 * 28940 * @param {String} url 28941 * @param {Function} callback 28942 * 28943 * @return {Void} 28944 */ 28945 function doAjax(url, callback) { 28946 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'); 28947 $.ajax({ 28948 url: url, 28949 dataType: 'jsonp' 28950 }); 28951 28952 iLCallback = function(data) { 28953 callback.call(this, data); 28954 }; 28955 } 28956 28957 /** 28958 * Find image from DOM elements 28959 * 28960 * @param {Element} element 28961 * 28962 * @return {Void} 28963 */ 28964 function findImageInElement(element) { 28965 var elements = $('*', element), 28966 imagesArr = new Array(); 28967 28968 elements.each(function() { 28969 var url = "", 28970 element = this; 28971 28972 if ($(element).css("background-image") != "none") { 28973 url = $(element).css("background-image"); 28974 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 28975 url = $(element).attr("src"); 28976 } 28977 28978 if (url.indexOf("gradient") == -1) { 28979 url = url.replace(/url\(\"/g, ""); 28980 url = url.replace(/url\(/g, ""); 28981 url = url.replace(/\"\)/g, ""); 28982 url = url.replace(/\)/g, ""); 28983 28984 var urls = url.split(","); 28985 28986 for (var i = 0; i < urls.length; i++) { 28987 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 28988 var extra = ""; 28989 if (browser.msie && browser.version < 9) { 28990 extra = "?" + floor(random() * 3000); 28991 } 28992 imagesArr.push(urls[i] + extra); 28993 } 28994 } 28995 } 28996 }); 28997 28998 return imagesArr; 28999 } 29000 29001 /** 29002 * Get file extension. 29003 * 29004 * @param {String} URL 29005 * 29006 * @return {String} 29007 */ 29008 function getExtension(URL) { 29009 if (URL !== null) { 29010 //UNCODE: fix issue to detect media type with query strings 29011 var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL; 29012 ext = ext.split('.').pop().toLowerCase(); 29013 29014 return ext; 29015 } 29016 } 29017 29018 /** 29019 * Get type via extension. 29020 * 29021 * @param {String} URL 29022 * 29023 * @return {String} 29024 */ 29025 function getTypeByExtension(URL) { 29026 var type, 29027 ext = getExtension(URL); 29028 29029 //Uncode addition ##START## 29030 if (URL == undefined) { 29031 return false; 29032 } 29033 //Uncode addition ##END## 29034 29035 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 29036 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 29037 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 29038 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 29039 else type = 'iframe'; 29040 29041 return type; 29042 } 29043 29044 /** 29045 * Return value from percent of a number. 29046 * 29047 * @param {Number} percent 29048 * @param {Number} total 29049 * 29050 * @return {Number} 29051 */ 29052 function percentToValue(percent, total) { 29053 return parseInt((total / 100) * percent); 29054 } 29055 29056 /** 29057 * A JavaScript equivalent of PHPâs parse_url. 29058 * 29059 * @param {String} url The URL to parse. 29060 * 29061 * @return {Mixed} 29062 */ 29063 function parseURI(url) { 29064 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 29065 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 29066 return (m ? { 29067 href: m[0] || '', 29068 protocol: m[1] || '', 29069 authority: m[2] || '', 29070 host: m[3] || '', 29071 hostname: m[4] || '', 29072 port: m[5] || '', 29073 pathname: m[6] || '', 29074 search: m[7] || '', 29075 hash: m[8] || '' 29076 } : null); 29077 } 29078 29079 /** 29080 * Gets the absolute URI. 29081 * 29082 * @param {String} href The relative URL. 29083 * @param {String} base The base URL. 29084 * 29085 * @return {String} The absolute URL. 29086 */ 29087 function absolutizeURI(base, href) { // RFC 3986 29088 var iL = this; 29089 29090 function removeDotSegments(input) { 29091 var output = []; 29092 input.replace(/^(\.\.?(\/|$))+/, '') 29093 .replace(/\/(\.(\/|$))+/g, '/') 29094 .replace(/\/\.\.$/, '/../') 29095 .replace(/\/?[^\/]*/g, function(p) { 29096 if (p === '/..') { 29097 output.pop(); 29098 } else { 29099 output.push(p); 29100 } 29101 }); 29102 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 29103 } 29104 29105 href = parseURI(href || ''); 29106 base = parseURI(base || ''); 29107 29108 return !href || !base ? null : (href.protocol || base.protocol) + 29109 (href.protocol || href.authority ? href.authority : base.authority) + 29110 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)) + 29111 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 29112 href.hash; 29113 } 29114 29115 /** 29116 * A JavaScript equivalent of PHPâs version_compare. 29117 * 29118 * @param {String} v1 29119 * @param {String} v2 29120 * @param {String} operator
29121 * 29122 * @return {Boolean} 29123 */ 29124 function version_compare(v1, v2, operator) { 29125 this.php_js = this.php_js || {}; 29126 this.php_js.ENV = this.php_js.ENV || {}; 29127 var i = 0, 29128 x = 0, 29129 compare = 0, 29130 vm = { 29131 'dev': -6, 29132 'alpha': -5, 29133 'a': -5, 29134 'beta': -4, 29135 'b': -4, 29136 'RC': -3, 29137 'rc': -3, 29138 '#': -2, 29139 'p': 1, 29140 'pl': 1 29141 }, 29142 prepVersion = function(v) { 29143 v = ('' + v).replace(/[_\-+]/g, '.'); 29144 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 29145 return (!v.length ? [-8] : v.split('.')); 29146 }, 29147 numVersion = function(v) { 29148 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 29149 }; 29150 v1 = prepVersion(v1); 29151 v2 = prepVersion(v2); 29152 x = max(v1.length, v2.length); 29153 for (i = 0; i < x; i++) { 29154 if (v1[i] == v2[i]) { 29155 continue; 29156 } 29157 v1[i] = numVersion(v1[i]); 29158 v2[i] = numVersion(v2[i]); 29159 if (v1[i] < v2[i]) { 29160 compare = -1; 29161 break; 29162 } else if (v1[i] > v2[i]) { 29163 compare = 1; 29164 break; 29165 } 29166 } 29167 if (!operator) { 29168 return compare; 29169 } 29170 29171 switch (operator) { 29172 case '>': 29173 case 'gt': 29174 return (compare > 0); 29175 case '>=': 29176 case 'ge': 29177 return (compare >= 0); 29178 case '<=': 29179 case 'le': 29180 return (compare <= 0); 29181 case '==': 29182 case '=': 29183 case 'eq': 29184 return (compare === 0); 29185 case '<>': 29186 case '!=': 29187 case 'ne': 29188 return (compare !== 0); 29189 case '': 29190 case '<': 29191 case 'lt': 29192 return (compare < 0); 29193 default: 29194 return null; 29195 } 29196 } 29197 29198 29199 // Begin the iLightBox plugin 29200 $.fn.iLightBox = function() { 29201 29202 var args = arguments, 29203 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 29204 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 29205 29206 if (!opt) opt = {}; 29207 29208 // Default options. Play carefully. 29209 var options = $.extend(true, { 29210 attr: 'href', 29211 path: 'vertical', 29212 skin: 'dark', 29213 linkId: false, 29214 infinite: false, 29215 startFrom: 0, 29216 randomStart: false, 29217 keepAspectRatio: true, 29218 maxScale: 1, 29219 minScale: .2, 29220 innerToolbar: false, 29221 smartRecognition: false, 29222 mobileOptimizer: true, 29223 fullAlone: true, 29224 fullViewPort: null, 29225 fullStretchTypes: 'flash, video', 29226 overlay: { 29227 blur: true, 29228 opacity: .85 29229 }, 29230 controls: { 29231 arrows: false, 29232 slideshow: false, 29233 toolbar: true, 29234 fullscreen: true, 29235 thumbnail: true, 29236 keyboard: true, 29237 mousewheel: true, 29238 swipe: true 29239 }, 29240 keyboard: { 29241 left: true, // previous 29242 right: true, // next 29243 up: true, // previous 29244 down: true, // next 29245 esc: true, // close 29246 shift_enter: true // fullscreen 29247 }, 29248 show: { 29249 effect: true, 29250 speed: 300, 29251 title: true 29252 }, 29253 hide: { 29254 effect: true, 29255 speed: 300 29256 }, 29257 caption: { 29258 start: true, 29259 show: 'mouseenter', 29260 hide: 'mouseleave' 29261 }, 29262 social: { 29263 start: true, 29264 show: 'mouseenter', 29265 hide: 'mouseleave',
29266 buttons: false 29267 }, 29268 styles: { 29269 pageOffsetX: 0, 29270 pageOffsetY: 0, 29271 nextOffsetX: 45, 29272 nextOffsetY: 0, 29273 nextOpacity: 1, 29274 nextScale: 1, 29275 prevOffsetX: 45, 29276 prevOffsetY: 0, 29277 prevOpacity: 1, 29278 prevScale: 1 29279 }, 29280 thumbnails: { 29281 maxWidth: 120, 29282 maxHeight: 80, 29283 normalOpacity: 1, 29284 activeOpacity: .6 29285 }, 29286 effects: { 29287 reposition: true, 29288 repositionSpeed: 200, 29289 switchSpeed: 500, 29290 loadedFadeSpeed: 180, 29291 fadeSpeed: 200 29292 }, 29293 slideshow: { 29294 pauseTime: 5000, 29295 pauseOnHover: false, 29296 startPaused: true 29297 }, 29298 text: { 29299 close: "Press Esc to close", 29300 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 29301 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 29302 slideShow: "Slideshow", 29303 next: "Next", 29304 previous: "Previous" 29305 }, 29306 errors: { 29307 loadImage: "An error occurred when trying to load photo.", 29308 loadContents: "An error occurred when trying to load contents.", 29309 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 29310 }, 29311 ajaxSetup: { 29312 url: '', 29313 beforeSend: function(jqXHR, settings) {}, 29314 cache: false, 29315 complete: function(jqXHR, textStatus) {}, 29316 crossDomain: false, 29317 error: function(jqXHR, textStatus, errorThrown) {}, 29318 success: function(data, textStatus, jqXHR) {}, 29319 global: true, 29320 ifModified: false, 29321 username: null, 29322 password: null, 29323 type: 'GET' 29324 }, 29325 callback: {} 29326 }, opt); 29327 29328 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 29329 29330 items = $.isArray(items) ? items : new Array(); 29331 29332 if (typeof args[0] == 'string') items[0] = args[0]; 29333 29334 if (version_compare($.fn.jquery, '1.8', '>=')) { 29335 var iLB = new iLightBox($(this), options, items, instant); 29336 return { 29337 close: function() { 29338 iLB.closeAction(); 29339 }, 29340 fullscreen: function() { 29341 iLB.fullScreenAction(); 29342 }, 29343 moveNext: function() { 29344 iLB.moveTo('next'); 29345 }, 29346 movePrev: function() { 29347 iLB.moveTo('prev'); 29348 }, 29349 goTo: function(index) { 29350 iLB.goTo(index); 29351 }, 29352 refresh: function() { 29353 iLB.refresh(); 29354 }, 29355 reposition: function() { 29356 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 29357 }, 29358 setOption: function(options) { 29359 iLB.setOption(options); 29360 }, 29361 destroy: function() { 29362 iLB.closeAction(); 29363 iLB.dispatchItemsEvents(); 29364 } 29365 }; 29366 } else { 29367 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 29368 } 29369 29370 }; 29371 29372 29373 $.iLightBox = function() { 29374 return $.fn.iLightBox(arguments[0], arguments[1]); 29375 }; 29376 29377 function getScrollXY() { 29378 var scrOfX = 0, 29379 scrOfY = 0; 29380 if (typeof(window.pageYOffset) == 'number') { 29381 //Netscape compliant 29382 scrOfY = window.pageYOffset; 29383 scrOfX = window.pageXOffset; 29384 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 29385 //DOM compliant 29386 scrOfY = document.body.scrollTop; 29387 scrOfX = document.body.scrollLeft; 29388 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 29389 //IE6 standards compliant mode 29390 scrOfY = document.documentElement.scrollTop; 29391 scrOfX = document.documentElement.scrollLeft; 29392 } 29393 return { 29394 x: scrOfX, 29395 y: scrOfY 29396 }; 29397 } 29398 29399 (function() { 29400 // add new event shortcuts 29401 $.each(("touchstart touchmove touchend " + 29402 "tap taphold " + 29403 "swipe swipeleft swiperight " + 29404 "scrollstart scrollstop").split(" "), function(i, name) { 29405 29406 $.fn[name] = function(fn) { 29407 return fn ? this.bind(name, fn) : this.trigger(name); 29408 }; 29409 29410 // jQuery < 1.8 29411 // if ($.attrFn) { 29412 // $.attrFn[name] = true; 29413 // } 29414 }); 29415 29416 var tapSettings = { 29417 startEvent: 'touchstart.iTap', 29418 endEvent: 'touchend.iTap' 29419 }; 29420 29421 // tap Event: 29422 $.event.special.itap = { 29423 setup: function() { 29424 29425 var self = this, 29426 $self = $(this), 29427 start, stop; 29428 29429 $self.bind(tapSettings.startEvent, function(event) { 29430 start = getScrollXY(); 29431 29432 $self.one(tapSettings.endEvent, function(event) { 29433 stop = getScrollXY(); 29434 29435 var orgEvent = event || window.event; 29436 event = $.event.fix(orgEvent); 29437 event.type = "itap"; 29438 29439 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 29440 29441 start = stop = undefined; 29442 }); 29443 }); 29444 }, 29445 29446 teardown: function() { 29447 $(this).unbind(tapSettings.startEvent); 29448 } 29449 }; 29450 }()); 29451 29452 29453 //Fullscreen API 29454 (function() { 29455 fullScreenApi = { 29456 supportsFullScreen: false, 29457 isFullScreen: function() { 29458 return false;
29459 }, 29460 requestFullScreen: function() {}, 29461 cancelFullScreen: function() {}, 29462 fullScreenEventName: '', 29463 prefix: '' 29464 }, 29465 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 29466 29467 // check for native support 29468 if (typeof document.cancelFullScreen != 'undefined') { 29469 fullScreenApi.supportsFullScreen = true; 29470 } else { 29471 // check for fullscreen support by vendor prefix 29472 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 29473 fullScreenApi.prefix = browserPrefixes[i]; 29474 29475 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 29476 fullScreenApi.supportsFullScreen = true; 29477 29478 break; 29479 } 29480 } 29481 } 29482 29483 // update methods to do something useful 29484 if (fullScreenApi.supportsFullScreen) { 29485 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 29486 29487 fullScreenApi.isFullScreen = function() { 29488 switch (this.prefix) { 29489 case '': 29490 return document.fullScreen; 29491 case 'webkit': 29492 return document.webkitIsFullScreen; 29493 default: 29494 return document[this.prefix + 'FullScreen']; 29495 } 29496 } 29497 fullScreenApi.requestFullScreen = function(el) { 29498 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 29499 } 29500 fullScreenApi.cancelFullScreen = function(el) { 29501 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 29502 } 29503 } 29504 }()); 29505 29506 // Browser detect 29507 (function() { 29508 function uaMatch(ua) { 29509 ua = ua.toLowerCase(); 29510 29511 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 29512 /(webkit)[ \/]([\w.]+)/.exec(ua) || 29513 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 29514 /(msie) ([\w.]+)/.exec(ua) || 29515 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 29516 29517 return { 29518 browser: match[1] || "", 29519 version: match[2] || "0" 29520 }; 29521 } 29522 29523 var matched = uaMatch(navigator.userAgent); 29524 browser = {}; 29525 29526 if (matched.browser) { 29527 browser[matched.browser] = true; 29528 browser.version = matched.version; 29529 } 29530 29531 // Chrome is Webkit, but Webkit is also Safari. 29532 if (browser.chrome) { 29533 browser.webkit = true; 29534 } else if (browser.webkit) { 29535 browser.safari = true; 29536 } 29537 }()); 29538 29539 // Feature detects 29540 (function() { 29541 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 29542 var el = document.createElement('div'); 29543 29544 function testProp(prop) { 29545 for (var p = 0, pl = prefixes.length; p < pl; p++) { 29546 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 29547 if (el.style[prefixedProp] !== undefined) { 29548 return prefixedProp; 29549 } 29550 } 29551 } 29552 29553 // Global support indicators 29554 transform = testProp('transform') || ''; 29555 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 29556 }()); 29557 29558 29559 /* 29560 PluginDetect v0.7.9 29561 www.pinlady.net/PluginDetect/license/ 29562 [ getVersion onWindowLoaded BetterIE ] 29563 [ Flash QuickTime Shockwave ] 29564 */ 29565 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;
29565d++){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);
29565d.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)}
29565c.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;
29565if(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(); 29566 29567 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)}; 29568 29569 29570 /* 29571 jQuery hashchange event v1.3 29572 https://github.com/cowboy/jquery-hashchange 29573 Copyright (c) 2010 "Cowboy" Ben Alman 29574 Dual licensed under the MIT and GPL licenses. 29575 */ 29576 (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= 29577 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|| 29578 "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;
29578a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 29579 29580 if (!Array.prototype.filter) { 29581 Array.prototype.filter = function(fun /*, thisp */ ) { 29582 "use strict"; 29583 29584 if (this == null) 29585 throw new TypeError(); 29586 29587 var t = Object(this); 29588 var len = t.length >>> 0; 29589 if (typeof fun != "function") 29590 throw new TypeError(); 29591 29592 var res = []; 29593 var thisp = arguments[1]; 29594 for (var i = 0; i < len; i++) { 29595 if (i in t) { 29596 var val = t[i]; // in case fun mutates this 29597 if (fun.call(thisp, val, i, t)) 29598 res.push(val); 29599 } 29600 } 29601 29602 return res; 29603 }; 29604 } 29605 29606 if (!Array.prototype.indexOf) { 29607 Array.prototype.indexOf = function(searchElement, fromIndex) { 29608 var k; 29609 29610 if (this == null) { 29611 throw new TypeError('"this" is null or not defined'); 29612 } 29613 29614 var O = Object(this); 29615 29616 var len = O.length >>> 0; 29617 29618 if (len === 0) { 29619 return -1; 29620 } 29621 29622 var n = +fromIndex || 0; 29623 29624 if (abs(n) === Infinity) { 29625 n = 0; 29626 } 29627 29628 if (n >= len) { 29629 return -1; 29630 } 29631 29632 k = max(n >= 0 ? n : len - abs(n), 0); 29633 29634 while (k < len) { 29635 var kValue; 29636 if (k in O && O[k] === searchElement) { 29637 return k; 29638 } 29639 k++; 29640 } 29641 return -1; 29642 }; 29643 } 29644 29645 if (!Array.prototype.lastIndexOf) { 29646 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 29647 "use strict"; 29648 29649 if (this == null) 29650 throw new TypeError(); 29651 29652 var t = Object(this); 29653 var len = t.length >>> 0; 29654 if (len === 0) 29655 return -1; 29656 29657 var n = len; 29658 if (arguments.length > 1) { 29659 n = Number(arguments[1]); 29660 if (n != n) 29661 n = 0; 29662 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 29663 n = (n > 0 || -1) * floor(abs(n)); 29664 } 29665 29666 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 29667 29668 for (; k >= 0; k--) { 29669 if (k in t && t[k] === searchElement) 29670 return k; 29671 } 29672 return -1; 29673 }; 29674 } 29675})(jQuery, this); 29676 29677/*! 29678 * lightgallery | 2.5.0 | June 13th 2022 29679 * http://www.lightgalleryjs.com/ 29680 * Copyright (c) 2020 Sachin Neravath; 29681 * @license GPLv3 29682 */ 29683 29684(function (global, factory) { 29685 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 29686 typeof define === 'function' && define.amd ? define(factory) : 29687 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory()); 29688}(this, (function () { 'use strict'; 29689 29690 /*! ***************************************************************************** 29691 Copyright (c) Microsoft Corporation. 29692 29693 Permission to use, copy, modify, and/or distribute this software for any 29694 purpose with or without fee is hereby granted. 29695 29696 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 29697 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 29698 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 29699 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 29700 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 29701 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29702 PERFORMANCE OF THIS SOFTWARE. 29703 ***************************************************************************** */ 29704 29705 var __assign = function() { 29706 __assign = Object.assign || function __assign(t) { 29707 for (var s, i = 1, n = arguments.length; i < n; i++) { 29708 s = arguments[i]; 29709 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 29710 } 29711 return t; 29712 }; 29713 return __assign.apply(this, arguments); 29714 }; 29715 29716 function __spreadArrays() { 29717 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 29718 for (var r = Array(s), k = 0, i = 0; i < il; i++) 29719 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 29720 r[k] = a[j]; 29721 return r; 29722 } 29723 29724 /** 29725 * List of lightGallery events 29726 * All events should be documented here 29727 * Below interfaces are used to build the website documentations 29728 * */ 29729 var lGEvents = { 29730 afterAppendSlide: 'lgAfterAppendSlide', 29731 init: 'lgInit', 29732 hasVideo: 'lgHasVideo', 29733 containerResize: 'lgContainerResize', 29734 updateSlides: 'lgUpdateSlides', 29735 afterAppendSubHtml: 'lgAfterAppendSubHtml', 29736 beforeOpen: 'lgBeforeOpen', 29737 afterOpen: 'lgAfterOpen', 29738 slideItemLoad: 'lgSlideItemLoad', 29739 beforeSlide: 'lgBeforeSlide', 29740 afterSlide: 'lgAfterSlide', 29741 posterClick: 'lgPosterClick', 29742 dragStart: 'lgDragStart', 29743 dragMove: 'lgDragMove', 29744 dragEnd: 'lgDragEnd', 29745 beforeNextSlide: 'lgBeforeNextSlide', 29746 beforePrevSlide: 'lgBeforePrevSlide', 29747 beforeClose: 'lgBeforeClose', 29748 afterClose: 'lgAfterClose', 29749 rotateLeft: 'lgRotateLeft', 29750 rotateRight: 'lgRotateRight', 29751 flipHorizontal: 'lgFlipHorizontal', 29752 flipVertical: 'lgFlipVertical', 29753 autoplay: 'lgAutoplay', 29754 autoplayStart: 'lgAutoplayStart', 29755 autoplayStop: 'lgAutoplayStop', 29756 }; 29757 29758 var lightGalleryCoreSettings = { 29759 mode: 'lg-slide', 29760 easing: 'ease', 29761 speed: 400, 29762 licenseKey: '0000-0000-000-0000', 29763 height: '100%', 29764 width: '100%', 29765 addClass: '', 29766 startClass: 'lg-start-zoom', 29767 backdropDuration: 300, 29768 container: '', 29769 startAnimationDuration: 400, 29770 zoomFromOrigin: true, 29771 hideBarsDelay: 0, 29772 showBarsAfter: 10000, 29773 slideDelay: 0, 29774 supportLegacyBrowser: true, 29775 allowMediaOverlap: false, 29776 videoMaxSize: '1280-720', 29777 loadYouTubePoster: true, 29778 defaultCaptionHeight: 0, 29779 ariaLabelledby: '', 29780 ariaDescribedby: '', 29781 resetScrollPosition: true, 29782 hideScrollbar: false, 29783 closable: true, 29784 swipeToClose: true, 29785 closeOnTap: true, 29786 showCloseIcon: true, 29787 showMaximizeIcon: false, 29788 loop: true, 29789 escKey: true, 29790 keyPress: true, 29791 trapFocus: true, 29792 controls: true, 29793 slideEndAnimation: true, 29794 hideControlOnEnd: false,
vendor: 15,066 bytes, lines 29795-30342
29795 mousewheel: false, 29796 getCaptionFromTitleOrAlt: true, 29797 appendSubHtmlTo: '.lg-sub-html', 29798 subHtmlSelectorRelative: false, 29799 preload: 2, 29800 numberOfSlideItemsInDom: 10, 29801 selector: '', 29802 selectWithin: '', 29803 nextHtml: '', 29804 prevHtml: '', 29805 index: 0, 29806 iframeWidth: '100%', 29807 iframeHeight: '100%', 29808 iframeMaxWidth: '100%', 29809 iframeMaxHeight: '100%', 29810 download: true, 29811 counter: true, 29812 appendCounterTo: '.lg-toolbar', 29813 swipeThreshold: 50, 29814 enableSwipe: true, 29815 enableDrag: true, 29816 dynamic: false, 29817 dynamicEl: [], 29818 extraProps: [], 29819 exThumbImage: '', 29820 isMobile: undefined, 29821 mobileSettings: { 29822 controls: false, 29823 showCloseIcon: false, 29824 download: false, 29825 }, 29826 plugins: [], 29827 strings: { 29828 closeGallery: 'Close gallery', 29829 toggleMaximize: 'Toggle maximize', 29830 previousSlide: 'Previous slide', 29831 nextSlide: 'Next slide', 29832 download: 'Download', 29833 playVideo: 'Play video', 29834 }, 29835 }; 29836 29837 function initLgPolyfills() { 29838 (function () { 29839 if (typeof window.CustomEvent === 'function') 29840 return false; 29841 function CustomEvent(event, params) { 29842 params = params || { 29843 bubbles: false, 29844 cancelable: false, 29845 detail: null, 29846 }; 29847 var evt = document.createEvent('CustomEvent'); 29848 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 29849 return evt; 29850 } 29851 window.CustomEvent = CustomEvent; 29852 })(); 29853 (function () { 29854 if (!Element.prototype.matches) { 29855 Element.prototype.matches = 29856 Element.prototype.msMatchesSelector || 29857 Element.prototype.webkitMatchesSelector; 29858 } 29859 })(); 29860 } 29861 var lgQuery = /** @class */ (function () { 29862 function lgQuery(selector) { 29863 this.cssVenderPrefixes = [ 29864 'TransitionDuration', 29865 'TransitionTimingFunction', 29866 'Transform', 29867 'Transition', 29868 ]; 29869 this.selector = this._getSelector(selector); 29870 this.firstElement = this._getFirstEl(); 29871 return this; 29872 } 29873 lgQuery.generateUUID = function () { 29874 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 29875 var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8; 29876 return v.toString(16); 29877 }); 29878 }; 29879 lgQuery.prototype._getSelector = function (selector, context) { 29880 if (context === void 0) { context = document; } 29881 if (typeof selector !== 'string') { 29882 return selector; 29883 } 29884 context = context || document; 29885 var fl = selector.substring(0, 1); 29886 if (fl === '#') { 29887 return context.querySelector(selector); 29888 } 29889 else { 29890 return context.querySelectorAll(selector); 29891 } 29892 }; 29893 lgQuery.prototype._each = function (func) { 29894 if (!this.selector) { 29895 return this; 29896 } 29897 if (this.selector.length !== undefined) { 29898 [].forEach.call(this.selector, func); 29899 } 29900 else { 29901 func(this.selector, 0); 29902 } 29903 return this; 29904 }; 29905 lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) { 29906 // prettier-ignore 29907 var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) { 29908 return group1.toUpperCase(); 29909 }); 29910 if (this.cssVenderPrefixes.indexOf(property) !== -1) { 29911 el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value; 29912 el.style['webkit' + property] = value; 29913 el.style['moz' + property] = value; 29914 el.style['ms' + property] = value; 29915 el.style['o' + property] = value; 29916 } 29917 else { 29918 el.style[property] = value; 29919 } 29920 }; 29921 lgQuery.prototype._getFirstEl = function () { 29922 if (this.selector && this.selector.length !== undefined) { 29923 return this.selector[0]; 29924 } 29925 else { 29926 return this.selector; 29927 } 29928 }; 29929 lgQuery.prototype.isEventMatched = function (event, eventName) { 29930 var eventNamespace = eventName.split('.'); 29931 return event 29932 .split('.') 29933 .filter(function (e) { return e; }) 29934 .every(function (e) { 29935 return eventNamespace.indexOf(e) !== -1; 29936 }); 29937 }; 29938 lgQuery.prototype.attr = function (attr, value) { 29939 if (value === undefined) { 29940 if (!this.firstElement) { 29941 return ''; 29942 } 29943 return this.firstElement.getAttribute(attr); 29944 } 29945 this._each(function (el) { 29946 el.setAttribute(attr, value); 29947 }); 29948 return this; 29949 }; 29950 lgQuery.prototype.find = function (selector) { 29951 return $LG(this._getSelector(selector, this.selector)); 29952 }; 29953 lgQuery.prototype.first = function () { 29954 if (this.selector && this.selector.length !== undefined) { 29955 return $LG(this.selector[0]); 29956 } 29957 else { 29958 return $LG(this.selector); 29959 } 29960 }; 29961 lgQuery.prototype.eq = function (index) { 29962 return $LG(this.selector[index]); 29963 }; 29964 lgQuery.prototype.parent = function () { 29965 return $LG(this.selector.parentElement); 29966 }; 29967 lgQuery.prototype.get = function () { 29968 return this._getFirstEl(); 29969 }; 29970 lgQuery.prototype.removeAttr = function (attributes) { 29971 var attrs = attributes.split(' '); 29972 this._each(function (el) { 29973 attrs.forEach(function (attr) { return el.removeAttribute(attr); }); 29974 }); 29975 return this; 29976 }; 29977 lgQuery.prototype.wrap = function (className) { 29978 if (!this.firstElement) { 29979 return this; 29980 } 29981 var wrapper = document.createElement('div'); 29982 wrapper.className = className; 29983 this.firstElement.parentNode.insertBefore(wrapper, this.firstElement); 29984 this.firstElement.parentNode.removeChild(this.firstElement); 29985 wrapper.appendChild(this.firstElement); 29986 return this; 29987 }; 29988 lgQuery.prototype.addClass = function (classNames) { 29989 if (classNames === void 0) { classNames = ''; } 29990 this._each(function (el) { 29991 // IE doesn't support multiple arguments 29992 classNames.split(' ').forEach(function (className) { 29993 if (className) { 29994 el.classList.add(className); 29995 } 29996 }); 29997 }); 29998 return this; 29999 }; 30000 lgQuery.prototype.removeClass = function (classNames) { 30001 this._each(function (el) { 30002 // IE doesn't support multiple arguments 30003 classNames.split(' ').forEach(function (className) { 30004 if (className) { 30005 el.classList.remove(className); 30006 } 30007 }); 30008 }); 30009 return this; 30010 }; 30011 lgQuery.prototype.hasClass = function (className) { 30012 if (!this.firstElement) { 30013 return false; 30014 } 30015 return this.firstElement.classList.contains(className); 30016 }; 30017 lgQuery.prototype.hasAttribute = function (attribute) { 30018 if (!this.firstElement) { 30019 return false; 30020 } 30021 return this.firstElement.hasAttribute(attribute); 30022 }; 30023 lgQuery.prototype.toggleClass = function (className) { 30024 if (!this.firstElement) { 30025 return this; 30026 } 30027 if (this.hasClass(className)) { 30028 this.removeClass(className); 30029 } 30030 else { 30031 this.addClass(className); 30032 } 30033 return this; 30034 }; 30035 lgQuery.prototype.css = function (property, value) { 30036 var _this = this; 30037 this._each(function (el) { 30038 _this._setCssVendorPrefix(el, property, value); 30039 }); 30040 return this; 30041 }; 30042 // Need to pass separate namespaces for separate elements 30043 lgQuery.prototype.on = function (events, listener) { 30044 var _this = this; 30045 if (!this.selector) { 30046 return this; 30047 } 30048 events.split(' ').forEach(function (event) { 30049 if (!Array.isArray(lgQuery.eventListeners[event])) { 30050 lgQuery.eventListeners[event] = []; 30051 } 30052 lgQuery.eventListeners[event].push(listener); 30053 _this.selector.addEventListener(event.split('.')[0], listener); 30054 }); 30055 return this; 30056 }; 30057 // @todo - test this 30058 lgQuery.prototype.once = function (event, listener) { 30059 var _this = this; 30060 this.on(event, function () { 30061 _this.off(event); 30062 listener(event); 30063 }); 30064 return this; 30065 }; 30066 lgQuery.prototype.off = function (event) { 30067 var _this = this; 30068 if (!this.selector) { 30069 return this; 30070 } 30071 Object.keys(lgQuery.eventListeners).forEach(function (eventName) { 30072 if (_this.isEventMatched(event, eventName)) { 30073 lgQuery.eventListeners[eventName].forEach(function (listener) { 30074 _this.selector.removeEventListener(eventName.split('.')[0], listener); 30075 }); 30076 lgQuery.eventListeners[eventName] = []; 30077 } 30078 }); 30079 return this; 30080 }; 30081 lgQuery.prototype.trigger = function (event, detail) { 30082 if (!this.firstElement) { 30083 return this; 30084 } 30085 var customEvent = new CustomEvent(event.split('.')[0], { 30086 detail: detail || null, 30087 }); 30088 this.firstElement.dispatchEvent(customEvent); 30089 return this; 30090 }; 30091 // Does not support IE 30092 lgQuery.prototype.load = function (url) { 30093 var _this = this; 30094 fetch(url) 30095 .then(function (res) { return res.text(); }) 30096 .then(function (html) { 30097 _this.selector.innerHTML = html; 30098 }); 30099 return this; 30100 }; 30101 lgQuery.prototype.html = function (html) { 30102 if (html === undefined) { 30103 if (!this.firstElement) { 30104 return ''; 30105 } 30106 return this.firstElement.innerHTML; 30107 } 30108 this._each(function (el) { 30109 el.innerHTML = html; 30110 }); 30111 return this; 30112 }; 30113 lgQuery.prototype.append = function (html) { 30114 this._each(function (el) { 30115 if (typeof html === 'string') { 30116 el.insertAdjacentHTML('beforeend', html); 30117 } 30118 else { 30119 el.appendChild(html); 30120 } 30121 }); 30122 return this; 30123 }; 30124 lgQuery.prototype.prepend = function (html) { 30125 this._each(function (el) { 30126 el.insertAdjacentHTML('afterbegin', html); 30127 }); 30128 return this; 30129 }; 30130 lgQuery.prototype.remove = function () { 30131 this._each(function (el) { 30132 el.parentNode.removeChild(el); 30133 }); 30134 return this; 30135 }; 30136 lgQuery.prototype.empty = function () { 30137 this._each(function (el) { 30138 el.innerHTML = ''; 30139 }); 30140 return this; 30141 }; 30142 lgQuery.prototype.scrollTop = function (scrollTop) { 30143 if (scrollTop !== undefined) { 30144 document.body.scrollTop = scrollTop; 30145 document.documentElement.scrollTop = scrollTop; 30146 return this; 30147 } 30148 else { 30149 return (window.pageYOffset || 30150 document.documentElement.scrollTop || 30151 document.body.scrollTop || 30152 0); 30153 } 30154 }; 30155 lgQuery.prototype.scrollLeft = function (scrollLeft) { 30156 if (scrollLeft !== undefined) { 30157 document.body.scrollLeft = scrollLeft; 30158 document.documentElement.scrollLeft = scrollLeft; 30159 return this; 30160 } 30161 else { 30162 return (window.pageXOffset || 30163 document.documentElement.scrollLeft || 30164 document.body.scrollLeft || 30165 0); 30166 } 30167 }; 30168 lgQuery.prototype.offset = function () { 30169 if (!this.firstElement) { 30170 return { 30171 left: 0, 30172 top: 0, 30173 }; 30174 } 30175 var rect = this.firstElement.getBoundingClientRect(); 30176 var bodyMarginLeft = $LG('body').style().marginLeft; 30177 // Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value 30178 return { 30179 left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(), 30180 top: rect.top + this.scrollTop(), 30181 }; 30182 }; 30183 lgQuery.prototype.style = function () { 30184 if (!this.firstElement) { 30185 return {}; 30186 } 30187 return (this.firstElement.currentStyle || 30188 window.getComputedStyle(this.firstElement)); 30189 }; 30190 // Width without padding and border even if box-sizing is used. 30191 lgQuery.prototype.width = function () { 30192 var style = this.style(); 30193 return (this.firstElement.clientWidth - 30194 parseFloat(style.paddingLeft) - 30195 parseFloat(style.paddingRight)); 30196 }; 30197 // Height without padding and border even if box-sizing is used. 30198 lgQuery.prototype.height = function () { 30199 var style = this.style(); 30200 return (this.firstElement.clientHeight - 30201 parseFloat(style.paddingTop) - 30202 parseFloat(style.paddingBottom)); 30203 }; 30204 lgQuery.eventListeners = {}; 30205 return lgQuery; 30206 }()); 30207 function $LG(selector) { 30208 initLgPolyfills(); 30209 return new lgQuery(selector); 30210 } 30211 30212 var defaultDynamicOptions = [ 30213 'src', 30214 'sources', 30215 'subHtml', 30216 'subHtmlUrl', 30217 'html', 30218 'video', 30219 'poster', 30220 'slideName', 30221 'responsive', 30222 'srcset', 30223 'sizes', 30224 'iframe', 30225 'downloadUrl', 30226 'download', 30227 'width', 30228 'facebookShareUrl', 30229 'tweetText', 30230 'iframeTitle', 30231 'twitterShareUrl', 30232 'pinterestShareUrl', 30233 'pinterestText', 30234 'fbHtml', 30235 'disqusIdentifier', 30236 'disqusUrl', 30237 ]; 30238 // Convert html data-attribute to camalcase 30239 function convertToData(attr) { 30240 // FInd a way for lgsize 30241 if (attr === 'href') { 30242 return 'src'; 30243 } 30244 attr = attr.replace('data-', ''); 30245 attr = attr.charAt(0).toLowerCase() + attr.slice(1); 30246 attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); 30247 return attr; 30248 } 30249 var utils = { 30250 /** 30251 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option 30252 */ 30253 //Uncode edit ##START## 30254 getSize: function (el, container, spacing, defaultLgSize, galleryItem) { 30255 // getSize: function (el, container, spacing, defaultLgSize) { 30256 //Uncode edit ##END## 30257 if (spacing === void 0) { spacing = 0; } 30258 var LGel = $LG(el); 30259 var lgSize = LGel.attr('data-lg-size') || defaultLgSize; 30260 //Uncode edit ##START## 30261 if ( typeof galleryItem.size && galleryItem.size != null ) { 30262 lgSize = galleryItem.size; 30263 } 30264 //Uncode edit ##END## 30265 if (!lgSize) { 30266 return; 30267 } 30268 var isResponsiveSizes = lgSize.split(','); 30269 // if at-least two viewport sizes are available 30270 if (isResponsiveSizes[1]) { 30271 var wWidth = window.innerWidth; 30272 for (var i = 0; i < isResponsiveSizes.length; i++) { 30273 var size_1 = isResponsiveSizes[i]; 30274 var responsiveWidth = parseInt(size_1.split('-')[2], 10); 30275 if (responsiveWidth > wWidth) { 30276 lgSize = size_1; 30277 break; 30278 } 30279 // take last item as last option 30280 if (i === isResponsiveSizes.length - 1) { 30281 lgSize = size_1; 30282 } 30283 } 30284 } 30285 var size = lgSize.split('-'); 30286 var width = parseInt(size[0], 10); 30287 var height = parseInt(size[1], 10); 30288 var cWidth = container.width(); 30289 var cHeight = container.height() - spacing; 30290 var maxWidth = Math.min(cWidth, width); 30291 var maxHeight = Math.min(cHeight, height); 30292 var ratio = Math.min(maxWidth / width, maxHeight / height); 30293 return { width: width * ratio, height: height * ratio }; 30294 }, 30295 /** 30296 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option 30297 * @param {jQuery Element} 30298 * @returns {String} Transform CSS string 30299 */ 30300 getTransform: function (el, container, top, bottom, imageSize) { 30301 if (!imageSize) { 30302 return; 30303 } 30304 var LGel = $LG(el).find('img').first(); 30305 if (!LGel.get()) { 30306 return; 30307 } 30308 var containerRect = container.get().getBoundingClientRect(); 30309 var wWidth = containerRect.width; 30310 // using innerWidth to include mobile safari bottom bar 30311 var wHeight = container.height() - (top + bottom); 30312 var elWidth = LGel.width(); 30313 var elHeight = LGel.height(); 30314 var elStyle = LGel.style(); 30315 var x = (wWidth - elWidth) / 2 - 30316 LGel.offset().left + 30317 (parseFloat(elStyle.paddingLeft) || 0) + 30318 (parseFloat(elStyle.borderLeft) || 0) + 30319 $LG(window).scrollLeft() + 30320 containerRect.left; 30321 var y = (wHeight - elHeight) / 2 - 30322 LGel.offset().top + 30323 (parseFloat(elStyle.paddingTop) || 0) + 30324 (parseFloat(elStyle.borderTop) || 0) + 30325 $LG(window).scrollTop() + 30326 top; 30327 var scX = elWidth / imageSize.width; 30328 var scY = elHeight / imageSize.height; 30329 var transform = 'translate3d(' + 30330 (x *= -1) + 30331 'px, ' + 30332 (y *= -1) + 30333 'px, 0) scale3d(' + 30334 scX + 30335 ', ' + 30336 scY + 30337 ', 1)'; 30338 return transform; 30339 }, 30340 getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) { 30341 var title = iframeTitle ? 'title="' + iframeTitle + '"' : ''; 30342 return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:"
vendor: 2,803 bytes, lines 30342-30414
30342+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\" allowfullscreen=\"true\"></iframe>\n </div>"; 30343 }, 30344 getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) { 30345 var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : ''; 30346 var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : ''; 30347 var imgMarkup = "<img " + altAttr + " " + srcsetAttr + " " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />"; 30348 var sourceTag = ''; 30349 if (sources) { 30350 var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources; 30351 sourceTag = sourceObj.map(function (source) { 30352 var attrs = ''; 30353 Object.keys(source).forEach(function (key) { 30354 // Do not remove the first space as it is required to separate the attributes 30355 attrs += " " + key + "=\"" + source[key] + "\""; 30356 }); 30357 return "<source " + attrs + "></source>"; 30358 }); 30359 } 30360 return "" + sourceTag + imgMarkup; 30361 }, 30362 // Get src from responsive src 30363 getResponsiveSrc: function (srcItms) { 30364 var rsWidth = []; 30365 var rsSrc = []; 30366 var src = ''; 30367 for (var i = 0; i < srcItms.length; i++) { 30368 var _src = srcItms[i].split(' '); 30369 // Manage empty space 30370 if (_src[0] === '') { 30371 _src.splice(0, 1); 30372 } 30373 rsSrc.push(_src[0]); 30374 rsWidth.push(_src[1]); 30375 } 30376 var wWidth = window.innerWidth; 30377 for (var j = 0; j < rsWidth.length; j++) { 30378 if (parseInt(rsWidth[j], 10) > wWidth) { 30379 src = rsSrc[j]; 30380 break; 30381 } 30382 } 30383 return src; 30384 }, 30385 isImageLoaded: function (img) { 30386 if (!img) 30387 return false; 30388 // During the onload event, IE correctly identifies any images that 30389 // werenât downloaded as not complete. Others should too. Gecko-based 30390 // browsers act like NS4 in that they report this incorrectly. 30391 if (!img.complete) { 30392 return false; 30393 } 30394 // However, they do have two very useful properties: naturalWidth and 30395 // naturalHeight. These give the true size of the image. If it failed 30396 // to load, either of these should be zero. 30397 if (img.naturalWidth === 0) { 30398 return false; 30399 } 30400 // No other way of checking: assume itâs ok. 30401 return true; 30402 }, 30403 getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) { 30404 var videoClass = ''; 30405 if (_isVideo && _isVideo.youtube) { 30406 videoClass = 'lg-has-youtube'; 30407 } 30408 else if (_isVideo && _isVideo.vimeo) { 30409 videoClass = 'lg-has-vimeo'; 30410 } 30411 else { 30412 videoClass = 'lg-has-html5'; 30413 } 30414 return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n <div class=\"lg-video-play-button\">
30414\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>"; 30415 }, 30416 getFocusableElements: function (container) { 30417 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])'); 30418 var visibleElements = [].filter.call(elements, function (element) { 30419 var style = window.getComputedStyle(element); 30420 return style.display !== 'none' && style.visibility !== 'hidden'; 30421 }); 30422 return visibleElements; 30423 }, 30424 /** 30425 * @desc Create dynamic elements array from gallery items when dynamic option is false 30426 * It helps to avoid frequent DOM interaction 30427 * and avoid multiple checks for dynamic elments 30428 * 30429 * @returns {Array} dynamicEl 30430 */ 30431 getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) { 30432 var dynamicElements = []; 30433 var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps); 30434 [].forEach.call(items, function (item) { 30435 var dynamicEl = {}; 30436 for (var i = 0; i < item.attributes.length; i++) { 30437 var attr = item.attributes[i]; 30438 if (attr.specified) { 30439 var dynamicAttr = convertToData(attr.name); 30440 var label = ''; 30441 if (availableDynamicOptions.indexOf(dynamicAttr) > -1) { 30442 label = dynamicAttr; 30443 } 30444 if (label) { 30445 dynamicEl[label] = attr.value; 30446 } 30447 } 30448 } 30449 var currentItem = $LG(item); 30450 var alt = currentItem.find('img').first().attr('alt') || currentItem.attr('data-alt'); 30451 var title = currentItem.attr('title'); 30452 //Uncode edit ##START## 30453 // var thumb = exThumbImage 30454 var thumb = exThumbImage && currentItem.attr(exThumbImage) 30455 //Uncode edit ##END## 30456 ? currentItem.attr(exThumbImage) 30457 : currentItem.find('img').first().attr('src'); 30458 dynamicEl.thumb = thumb; 30459 //Uncode edit ##START## 30460 if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) { 30461 // dynamicEl.subHtml = title || alt || ''; 30462 dynamicEl.subHtml = title || ''; 30463 } 30464 // dynamicEl.alt = alt || title || ''; 30465 dynamicEl.alt = alt || title; 30466 var inlineType = currentItem.attr('data-type'); 30467 dynamicEl.type = inlineType; 30468 //Uncode edit ##END## 30469 dynamicElements.push(dynamicEl); 30470 }); 30471 return dynamicElements; 30472 }, 30473 isMobile: function () { 30474 return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); 30475 }, 30476 /** 30477 * @desc Check the given src is video 30478 * @param {String} src 30479 * @return {Object} video type 30480 * Ex:{ youtube : ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] } 30481 * 30482 * @todo - this information can be moved to dynamicEl to avoid frequent calls 30483 */ 30484 isVideo: function (src, isHTML5VIdeo, index) { 30485 if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) { 30486 if (isHTML5VIdeo) { 30487 return { 30488 html5: true, 30489 }; 30490 } 30491 else { 30492 console.warn('lightGallery :- data-src is not provided on slide item ' + 30493 (index + 1) + 30494 '. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/'); 30495 return; 30496 } 30497 } 30498 var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i); 30499 var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i); 30500 var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/); 30501 if (youtube) { 30502 return { 30503 youtube: youtube, 30504 }; 30505 } 30506 else if (vimeo) { 30507 return { 30508 vimeo: vimeo, 30509 }; 30510 } 30511 else if (wistia) { 30512 return { 30513 wistia: wistia, 30514 }; 30515 } 30516 }, 30517 }; 30518 30519 // @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio 30520 // @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html 30521 // Unique id for each gallery 30522 var lgId = 0; 30523 var LightGallery = /** @class */ (function () { 30524 function LightGallery(element, options) { 30525 this.lgOpened = false;
vendor: 4,563 bytes, lines 30526-30660
30526 this.index = 0; 30527 // lightGallery modules 30528 this.plugins = []; 30529 // false when lightGallery load first slide content; 30530 this.lGalleryOn = false; 30531 // True when a slide animation is in progress 30532 this.lgBusy = false; 30533 this.currentItemsInDom = []; 30534 // Scroll top value before lightGallery is opened 30535 this.prevScrollTop = 0; 30536 this.bodyPaddingRight = 0; 30537 this.isDummyImageRemoved = false; 30538 this.dragOrSwipeEnabled = false; 30539 this.mediaContainerPosition = { 30540 top: 0, 30541 bottom: 0, 30542 }; 30543 if (!element) { 30544 return this; 30545 } 30546 lgId++; 30547 this.lgId = lgId; 30548 this.el = element; 30549 this.LGel = $LG(element); 30550 this.generateSettings(options); 30551 this.buildModules(); 30552 // When using dynamic mode, ensure dynamicEl is an array 30553 if (this.settings.dynamic && 30554 this.settings.dynamicEl !== undefined && 30555 !Array.isArray(this.settings.dynamicEl)) { 30556 throw 'When using dynamic mode, you must also define dynamicEl as an Array.'; 30557 } 30558 this.galleryItems = this.getItems(); 30559 this.normalizeSettings(); 30560 // Gallery items 30561 this.init(); 30562 //Uncode edit ##START## 30563 // this.validateLicense(); 30564 //Uncode edit ##END## 30565 return this; 30566 } 30567 LightGallery.prototype.generateSettings = function (options) { 30568 // lightGallery settings 30569 this.settings = __assign(__assign({}, lightGalleryCoreSettings), options); 30570 if (this.settings.isMobile && 30571 typeof this.settings.isMobile === 'function' 30572 ? this.settings.isMobile() 30573 : utils.isMobile()) { 30574 var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings); 30575 this.settings = __assign(__assign({}, this.settings), mobileSettings); 30576 } 30577 }; 30578 LightGallery.prototype.normalizeSettings = function () { 30579 if (this.settings.slideEndAnimation) { 30580 this.settings.hideControlOnEnd = false; 30581 } 30582 if (!this.settings.closable) { 30583 this.settings.swipeToClose = false; 30584 } 30585 // And reset it on close to get the correct value next time 30586 this.zoomFromOrigin = this.settings.zoomFromOrigin; 30587 // At the moment, Zoom from image doesn't support dynamic options 30588 // @todo add zoomFromOrigin support for dynamic images 30589 if (this.settings.dynamic) { 30590 this.zoomFromOrigin = false; 30591 } 30592 if (!this.settings.container) { 30593 this.settings.container = document.body; 30594 } 30595 // settings.preload should not be grater than $item.length 30596 this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length); 30597 }; 30598 LightGallery.prototype.init = function () { 30599 var _this = this; 30600 this.addSlideVideoInfo(this.galleryItems); 30601 this.buildStructure(); 30602 this.LGel.trigger(lGEvents.init, { 30603 instance: this, 30604 }); 30605 if (this.settings.keyPress) { 30606 this.keyPress(); 30607 } 30608 setTimeout(function () { 30609 _this.enableDrag(); 30610 _this.enableSwipe(); 30611 _this.triggerPosterClick(); 30612 }, 50); 30613 this.arrow(); 30614 if (this.settings.mousewheel) { 30615 this.mousewheel(); 30616 } 30617 if (!this.settings.dynamic) { 30618 this.openGalleryOnItemClick(); 30619 } 30620 }; 30621 LightGallery.prototype.openGalleryOnItemClick = function () { 30622 var _this = this; 30623 var _loop_1 = function (index) { 30624 var element = this_1.items[index]; 30625 var $element = $LG(element); 30626 // Using different namespace for click because click event should not unbind if selector is same object('this') 30627 // @todo manage all event listners - should have namespace that represent element 30628 var uuid = lgQuery.generateUUID(); 30629 $element 30630 .attr('data-lg-id', uuid) 30631 .on("click.lgcustom-item-" + uuid, function (e) { 30632 e.preventDefault(); 30633 var currentItemIndex = _this.settings.index || index; 30634 _this.openGallery(currentItemIndex, element); 30635 }); 30636 }; 30637 var this_1 = this; 30638 // Using for loop instead of using bubbling as the items can be any html element. 30639 for (var index = 0; index < this.items.length; index++) { 30640 _loop_1(index); 30641 } 30642 }; 30643 /** 30644 * Module constructor 30645 * Modules are build incrementally. 30646 * Gallery should be opened only once all the modules are initialized. 30647 * use moduleBuildTimeout to make sure this 30648 */ 30649 LightGallery.prototype.buildModules = function () { 30650 var _this = this; 30651 this.settings.plugins.forEach(function (plugin) { 30652 _this.plugins.push(new plugin(_this, $LG)); 30653 }); 30654 }; 30655 LightGallery.prototype.validateLicense = function () { 30656 if (!this.settings.licenseKey) { 30657 console.warn('Please provide a valid license key'); 30658 } 30659 else if (this.settings.licenseKey === '0000-0000-000-0000') { 30660 console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 30660-31074
30660id for production use"); 30661 } 30662 }; 30663 LightGallery.prototype.getSlideItem = function (index) { 30664 return $LG(this.getSlideItemId(index)); 30665 }; 30666 LightGallery.prototype.getSlideItemId = function (index) { 30667 return "#lg-item-" + this.lgId + "-" + index; 30668 }; 30669 LightGallery.prototype.getIdName = function (id) { 30670 return id + "-" + this.lgId; 30671 }; 30672 LightGallery.prototype.getElementById = function (id) { 30673 return $LG("#" + this.getIdName(id)); 30674 }; 30675 LightGallery.prototype.manageSingleSlideClassName = function () { 30676 if (this.galleryItems.length < 2) { 30677 this.outer.addClass('lg-single-item'); 30678 } 30679 else { 30680 this.outer.removeClass('lg-single-item'); 30681 } 30682 }; 30683 LightGallery.prototype.buildStructure = function () { 30684 var _this = this; 30685 var container = this.$container && this.$container.get(); 30686 if (container) { 30687 return; 30688 } 30689 var controls = ''; 30690 var subHtmlCont = ''; 30691 // Create controls 30692 if (this.settings.controls) { 30693 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>"; 30694 } 30695 if (this.settings.appendSubHtmlTo !== '.lg-item') { 30696 subHtmlCont = 30697 '<div class="lg-sub-html" role="status" aria-live="polite"></div>'; 30698 } 30699 var addClasses = ''; 30700 if (this.settings.allowMediaOverlap) { 30701 // Do not remove space before last single quote 30702 addClasses += 'lg-media-overlap '; 30703 } 30704 var ariaLabelledby = this.settings.ariaLabelledby 30705 ? 'aria-labelledby="' + this.settings.ariaLabelledby + '"' 30706 : ''; 30707 var ariaDescribedby = this.settings.ariaDescribedby 30708 ? 'aria-describedby="' + this.settings.ariaDescribedby + '"' 30709 : ''; 30710 var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : ''); 30711 var closeIcon = this.settings.closable && this.settings.showCloseIcon 30712 ? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>" 30713 : ''; 30714 var maximizeIcon = this.settings.showMaximizeIcon 30715 ? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>" 30716 : ''; 30717 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' 30718 ? subHtmlCont 30719 : '') + "\n <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n " + (this.settings.appendSubHtmlTo === '.lg-sub-html' 30720 ? subHtmlCont 30721 : '') + "\n </div>\n </div>\n </div>\n "; 30722 $LG(this.settings.container).append(template); 30723 if (document.body !== this.settings.container) { 30724 $LG(this.settings.container).css('position', 'relative'); 30725 } 30726 this.outer = this.getElementById('lg-outer'); 30727 this.$lgComponents = this.getElementById('lg-components'); 30728 this.$backdrop = this.getElementById('lg-backdrop'); 30729 this.$container = this.getElementById('lg-container'); 30730 this.$inner = this.getElementById('lg-inner'); 30731 this.$content = this.getElementById('lg-content'); 30732 this.$toolbar = this.getElementById('lg-toolbar'); 30733 this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms'); 30734 var outerClassNames = this.settings.mode + " "; 30735 this.manageSingleSlideClassName(); 30736 if (this.settings.enableDrag) { 30737 outerClassNames += 'lg-grab '; 30738 } 30739 this.outer.addClass(outerClassNames); 30740 this.$inner.css('transition-timing-function', this.settings.easing); 30741 this.$inner.css('transition-duration', this.settings.speed + 'ms'); 30742 if (this.settings.download) { 30743 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>"); 30744 } 30745 this.counter(); 30746 $LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () { 30747 _this.refreshOnResize(); 30748 }); 30749 this.hideBars(); 30750 this.manageCloseGallery(); 30751 this.toggleMaximize(); 30752 this.initModules(); 30753 }; 30754 LightGallery.prototype.refreshOnResize = function () { 30755 if (this.lgOpened) { 30756 var currentGalleryItem = this.galleryItems[this.index]; 30757 var __slideVideoInfo = currentGalleryItem.__slideVideoInfo; 30758 this.mediaContainerPosition = this.getMediaContainerPosition(); 30759 var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom; 30760 //Uncode edit ##START## 30761 this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 30762 // this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize); 30763 //Uncode edit ##END## 30764 if (__slideVideoInfo) { 30765 this.resizeVideoSlide(this.index, this.currentImageSize); 30766 } 30767 if (this.zoomFromOrigin && !this.isDummyImageRemoved) { 30768 var imgStyle = this.getDummyImgStyles(this.currentImageSize); 30769 this.outer 30770 .find('.lg-current .lg-dummy-img') 30771 .first() 30772 .attr('style', imgStyle); 30773 } 30774 this.LGel.trigger(lGEvents.containerResize); 30775 } 30776 }; 30777 LightGallery.prototype.resizeVideoSlide = function (index, imageSize) { 30778 var lgVideoStyle = this.getVideoContStyle(imageSize); 30779 var currentSlide = this.getSlideItem(index); 30780 currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle); 30781 }; 30782 /** 30783 * Update slides dynamically. 30784 * Add, edit or delete slides dynamically when lightGallery is opened. 30785 * Modify the current gallery items and pass it via updateSlides method 30786 * @note 30787 * - Do not mutate existing lightGallery items directly. 30788 * - Always pass new list of gallery items 30789 * - You need to take care of thumbnails outside the gallery if any 30790 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method. 30791 * @param items Gallery items 30792 * @param index After the update operation, which slide gallery should navigate to 30793 * @category lGPublicMethods 30794 * @example 30795 * const plugin = lightGallery(); 30796 * 30797 * // Adding slides dynamically 30798 * let galleryItems = [ 30799 * // Access existing lightGallery items 30800 * // galleryItems are automatically generated internally from the gallery HTML markup 30801 * // or directly from galleryItems when dynamic gallery is used 30802 * ...plugin.galleryItems, 30803 * ...[ 30804 * { 30805 * src: 'img/img-1.png', 30806 * thumb: 'img/thumb1.png', 30807 * }, 30808 * ], 30809 * ]; 30810 * plugin.updateSlides( 30811 * galleryItems, 30812 * plugin.index, 30813 * ); 30814 * 30815 * 30816 * // Remove slides dynamically 30817 * galleryItems = JSON.parse( 30818 * JSON.stringify(updateSlideInstance.galleryItems), 30819 * ); 30820 * galleryItems.shift(); 30821 * updateSlideInstance.updateSlides(galleryItems, 1); 30822 * @see <a href="/demos/update-slides/">Demo</a> 30823 */ 30824 LightGallery.prototype.updateSlides = function (items, index) { 30825 if (this.index > items.length - 1) { 30826 this.index = items.length - 1; 30827 } 30828 if (items.length === 1) { 30829 this.index = 0; 30830 } 30831 if (!items.length) { 30832 this.closeGallery(); 30833 return; 30834 } 30835 var currentSrc = this.galleryItems[index].src; 30836 this.galleryItems = items; 30837 this.updateControls(); 30838 this.$inner.empty(); 30839 this.currentItemsInDom = []; 30840 var _index = 0; 30841 // Find the current index based on source value of the slide 30842 this.galleryItems.some(function (galleryItem, itemIndex) { 30843 if (galleryItem.src === currentSrc) { 30844 _index = itemIndex; 30845 return true; 30846 } 30847 return false; 30848 }); 30849 this.currentItemsInDom = this.organizeSlideItems(_index, -1); 30850 this.loadContent(_index, true); 30851 this.getSlideItem(_index).addClass('lg-current'); 30852 this.index = _index; 30853 this.updateCurrentCounter(_index); 30854 this.LGel.trigger(lGEvents.updateSlides); 30855 }; 30856 // Get gallery items based on multiple conditions 30857 LightGallery.prototype.getItems = function () { 30858 // Gallery items 30859 this.items = []; 30860 if (!this.settings.dynamic) { 30861 if (this.settings.selector === 'this') { 30862 this.items.push(this.el); 30863 } 30864 else if (this.settings.selector) { 30865 if (typeof this.settings.selector === 'string') { 30866 if (this.settings.selectWithin) { 30867 var selectWithin = $LG(this.settings.selectWithin); 30868 this.items = selectWithin 30869 .find(this.settings.selector) 30870 .get(); 30871 } 30872 else { 30873 this.items = this.el.querySelectorAll(this.settings.selector); 30874 } 30875 } 30876 else { 30877 this.items = this.settings.selector; 30878 } 30879 } 30880 else { 30881 this.items = this.el.children; 30882 } 30883 return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage); 30884 } 30885 else { 30886 return this.settings.dynamicEl || []; 30887 } 30888 }; 30889 LightGallery.prototype.shouldHideScrollbar = function () { 30890 return (this.settings.hideScrollbar && 30891 document.body === this.settings.container); 30892 }; 30893 LightGallery.prototype.hideScrollbar = function () { 30894 if (!this.shouldHideScrollbar()) { 30895 return; 30896 } 30897 this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight); 30898 var bodyRect = document.documentElement.getBoundingClientRect(); 30899 var scrollbarWidth = window.innerWidth - bodyRect.width; 30900 $LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px'); 30901 $LG(document.body).addClass('lg-overlay-open'); 30902 }; 30903 LightGallery.prototype.resetScrollBar = function () { 30904 if (!this.shouldHideScrollbar()) { 30905 return; 30906 } 30907 $LG(document.body).css('padding-right', this.bodyPaddingRight + 'px'); 30908 $LG(document.body).removeClass('lg-overlay-open'); 30909 }; 30910 /** 30911 * Open lightGallery. 30912 * Open gallery with specific slide by passing index of the slide as parameter. 30913 * @category lGPublicMethods 30914 * @param {Number} index - index of the slide 30915 * @param {HTMLElement} element - Which image lightGallery should zoom from 30916 * 30917 * @example 30918 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo'); 30919 * const dynamicGallery = lightGallery($dynamicGallery, { 30920 * dynamic: true, 30921 * dynamicEl: [ 30922 * { 30923 * src: 'img/1.jpg', 30924 * thumb: 'img/thumb-1.jpg', 30925 * subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>', 30926 * }, 30927 * ... 30928 * ], 30929 * }); 30930 * $dynamicGallery.addEventListener('click', function () { 30931 * // Starts with third item.(Optional). 30932 * // This is useful if you want use dynamic mode with 30933 * // custom thumbnails (thumbnails outside gallery), 30934 * dynamicGallery.openGallery(2); 30935 * }); 30936 * 30937 */ 30938 LightGallery.prototype.openGallery = function (index, element) { 30939 var _this = this; 30940 if (index === void 0) { index = this.settings.index; } 30941 // prevent accidental double execution 30942 if (this.lgOpened) 30943 return; 30944 this.lgOpened = true; 30945 this.outer.removeClass('lg-hide-items'); 30946 this.hideScrollbar(); 30947 // Add display block, but still has opacity 0 30948 this.$container.addClass('lg-show'); 30949 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index); 30950 this.currentItemsInDom = itemsToBeInsertedToDom; 30951 var items = ''; 30952 itemsToBeInsertedToDom.forEach(function (item) { 30953 items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>"); 30954 }); 30955 this.$inner.append(items); 30956 this.addHtml(index); 30957 var transform = ''; 30958 this.mediaContainerPosition = this.getMediaContainerPosition(); 30959 var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 30960 if (!this.settings.allowMediaOverlap) { 30961 this.setMediaContainerPosition(top, bottom); 30962 } 30963 var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo; 30964 if (this.zoomFromOrigin && element) { 30965 //Uncode edit ##START## 30966 this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 30967 // this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize); 30968 //Uncode edit ##END## 30969 transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize); 30970 } 30971 if (!this.zoomFromOrigin || !transform) { 30972 this.outer.addClass(this.settings.startClass); 30973 this.getSlideItem(index).removeClass('lg-complete'); 30974 } 30975 var timeout = this.settings.zoomFromOrigin 30976 ? 100 30977 : this.settings.backdropDuration; 30978 setTimeout(function () { 30979 _this.outer.addClass('lg-components-open'); 30980 }, timeout); 30981 this.index = index; 30982 //Uncode edit ##START## 30983 // this.LGel.trigger(lGEvents.beforeOpen); 30984 this.LGel.trigger(lGEvents.beforeOpen, { 30985 galleryItems: this.galleryItems, 30986 items: this.items, 30987 outer: this.outer, 30988 }); 30989 //Uncode edit ##END## 30990 // add class lg-current to remove initial transition 30991 this.getSlideItem(index).addClass('lg-current'); 30992 this.lGalleryOn = false; 30993 // Store the current scroll top value to scroll back after closing the gallery.. 30994 this.prevScrollTop = $LG(window).scrollTop(); 30995 setTimeout(function () { 30996 // Need to check both zoomFromOrigin and transform values as we need to set set the 30997 // default opening animation if user missed to add the lg-size attribute 30998 if (_this.zoomFromOrigin && transform) { 30999 var currentSlide_1 = _this.getSlideItem(index); 31000 currentSlide_1.css('transform', transform); 31001 setTimeout(function () { 31002 currentSlide_1 31003 .addClass('lg-start-progress lg-start-end-progress') 31004 .css('transition-duration', _this.settings.startAnimationDuration + 'ms'); 31005 _this.outer.addClass('lg-zoom-from-image'); 31006 }); 31007 setTimeout(function () { 31008 currentSlide_1.css('transform', 'translate3d(0, 0, 0)'); 31009 }, 100); 31010 } 31011 setTimeout(function () { 31012 _this.$backdrop.addClass('in'); 31013 _this.$container.addClass('lg-show-in'); 31014 }, 10); 31015 setTimeout(function () { 31016 if (_this.settings.trapFocus && 31017 document.body === _this.settings.container) { 31018 _this.trapFocus(); 31019 } 31020 }, _this.settings.backdropDuration + 50); 31021 // lg-visible class resets gallery opacity to 1 31022 if (!_this.zoomFromOrigin || !transform) { 31023 setTimeout(function () { 31024 _this.outer.addClass('lg-visible'); 31025 }, _this.settings.backdropDuration); 31026 } 31027 // initiate slide function 31028 _this.slide(index, false, false, false); 31029 _this.LGel.trigger(lGEvents.afterOpen); 31030 }); 31031 if (document.body === this.settings.container) { 31032 $LG('html').addClass('lg-on'); 31033 } 31034 }; 31035 /** 31036 * Note - Changing the position of the media on every slide transition creates a flickering effect. 31037 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption. 31038 * if you have dynamic captions for each media, 31039 * you can provide an appropriate height for the captions via allowMediaOverlap option 31040 */ 31041 LightGallery.prototype.getMediaContainerPosition = function () { 31042 if (this.settings.allowMediaOverlap) { 31043 return { 31044 top: 0, 31045 bottom: 0, 31046 }; 31047 } 31048 var top = this.$toolbar.get().clientHeight || 0; 31049 var subHtml = this.outer.find('.lg-components .lg-sub-html').get(); 31050 var captionHeight = this.settings.defaultCaptionHeight || 31051 (subHtml && subHtml.clientHeight) || 31052 0; 31053 var thumbContainer = this.outer.find('.lg-thumb-outer').get(); 31054 var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0; 31055 var bottom = thumbHeight + captionHeight; 31056 //Uncode edit ##START## 31057 bottom = bottom < 55 ? 55 : bottom; 31058 //Uncode edit ##END## 31059 return { 31060 top: top, 31061 bottom: bottom, 31062 }; 31063 }; 31064 LightGallery.prototype.setMediaContainerPosition = function (top, bottom) { 31065 if (top === void 0) { top = 0; } 31066 if (bottom === void 0) { bottom = 0; } 31067 this.$content.css('top', top + 'px').css('bottom', bottom + 'px'); 31068 }; 31069 LightGallery.prototype.hideBars = function () { 31070 var _this = this; 31071 // Hide controllers if mouse doesn't move for some period 31072 setTimeout(function () { 31073 _this.outer.removeClass('lg-hide-items'); 31074 if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 31075-31205
31075 _this.outer.on('mousemove.lg click.lg touchstart.lg', function () { 31076 _this.outer.removeClass('lg-hide-items'); 31077 clearTimeout(_this.hideBarTimeout); 31078 // Timeout will be cleared on each slide movement also 31079 _this.hideBarTimeout = setTimeout(function () { 31080 _this.outer.addClass('lg-hide-items'); 31081 }, _this.settings.hideBarsDelay); 31082 }); 31083 _this.outer.trigger('mousemove.lg'); 31084 } 31085 }, this.settings.showBarsAfter); 31086 }; 31087 LightGallery.prototype.initPictureFill = function ($img) { 31088 if (this.settings.supportLegacyBrowser) { 31089 try { 31090 picturefill({ 31091 elements: [$img.get()], 31092 }); 31093 } 31094 catch (e) { 31095 console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.'); 31096 } 31097 } 31098 }; 31099 /** 31100 * @desc Create image counter 31101 * Ex: 1/10 31102 */ 31103 LightGallery.prototype.counter = function () { 31104 if (this.settings.counter) { 31105 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>"; 31106 this.outer.find(this.settings.appendCounterTo).append(counterHtml); 31107 } 31108 }; 31109 /** 31110 * @desc add sub-html into the slide 31111 * @param {Number} index - index of the slide 31112 */ 31113 LightGallery.prototype.addHtml = function (index) { 31114 var subHtml; 31115 var subHtmlUrl; 31116 if (this.galleryItems[index].subHtmlUrl) { 31117 subHtmlUrl = this.galleryItems[index].subHtmlUrl; 31118 } 31119 else { 31120 subHtml = this.galleryItems[index].subHtml; 31121 } 31122 if (!subHtmlUrl) { 31123 if (subHtml) { 31124 // get first letter of sub-html 31125 // if first letter starts with . or # get the html form the jQuery object 31126 var fL = subHtml.substring(0, 1); 31127 if (fL === '.' || fL === '#') { 31128 if (this.settings.subHtmlSelectorRelative && 31129 !this.settings.dynamic) { 31130 subHtml = $LG(this.items) 31131 .eq(index) 31132 .find(subHtml) 31133 .first() 31134 .html(); 31135 } 31136 else { 31137 subHtml = $LG(subHtml).first().html(); 31138 } 31139 } 31140 } 31141 else { 31142 subHtml = ''; 31143 } 31144 } 31145 if (this.settings.appendSubHtmlTo !== '.lg-item') { 31146 if (subHtmlUrl) { 31147 this.outer.find('.lg-sub-html').load(subHtmlUrl); 31148 } 31149 else { 31150 this.outer.find('.lg-sub-html').html(subHtml); 31151 } 31152 } 31153 else { 31154 var currentSlide = $LG(this.getSlideItemId(index)); 31155 if (subHtmlUrl) { 31156 currentSlide.load(subHtmlUrl); 31157 } 31158 else { 31159 currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>"); 31160 } 31161 } 31162 // Add lg-empty-html class if title doesn't exist 31163 if (typeof subHtml !== 'undefined' && subHtml !== null) { 31164 if (subHtml === '') { 31165 this.outer 31166 .find(this.settings.appendSubHtmlTo) 31167 .addClass('lg-empty-html'); 31168 } 31169 else { 31170 this.outer 31171 .find(this.settings.appendSubHtmlTo) 31172 .removeClass('lg-empty-html'); 31173 } 31174 } 31175 this.LGel.trigger(lGEvents.afterAppendSubHtml, { 31176 index: index, 31177 }); 31178 }; 31179 /** 31180 * @desc Preload slides 31181 * @param {Number} index - index of the slide 31182 * @todo preload not working for the first slide, Also, should work for the first and last slide as well 31183 */ 31184 LightGallery.prototype.preload = function (index) { 31185 for (var i = 1; i <= this.settings.preload; i++) { 31186 if (i >= this.galleryItems.length - index) { 31187 break; 31188 } 31189 this.loadContent(index + i, false); 31190 } 31191 for (var j = 1; j <= this.settings.preload; j++) { 31192 if (index - j < 0) { 31193 break; 31194 } 31195 this.loadContent(index - j, false); 31196 } 31197 }; 31198 LightGallery.prototype.getDummyImgStyles = function (imageSize) { 31199 if (!imageSize) 31200 return ''; 31201 return "width:" + imageSize.width + "px;\n margin-left: -" + imageSize.width / 2 + "px;\n margin-top: -" + imageSize.height / 2 + "px;\n height:" + imageSize.height + "px"; 31202 }; 31203 LightGallery.prototype.getVideoContStyle = function (imageSize) { 31204 if (!imageSize) 31205 return '';
31206 return "width:" + imageSize.width + "px;\n height:" + imageSize.height + "px"; 31207 }; 31208 LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) { 31209 var $currentItem; 31210 if (!this.settings.dynamic) { 31211 $currentItem = $LG(this.items).eq(index); 31212 } 31213 if ($currentItem) { 31214 var _dummyImgSrc = void 0; 31215 if (!this.settings.exThumbImage) { 31216 _dummyImgSrc = $currentItem.find('img').first().attr('src'); 31217 } 31218 else { 31219 _dummyImgSrc = $currentItem.attr(this.settings.exThumbImage); 31220 } 31221 if (!_dummyImgSrc) 31222 return ''; 31223 var imgStyle = this.getDummyImgStyles(this.currentImageSize); 31224 var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />"; 31225 $currentSlide.addClass('lg-first-slide'); 31226 this.outer.addClass('lg-first-slide-loading'); 31227 return dummyImgContent; 31228 } 31229 return ''; 31230 }; 31231 LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) { 31232 var currentGalleryItem = this.galleryItems[index]; 31233 var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources; 31234 // Use the thumbnail as dummy image which will be resized to actual image size and 31235 // displayed on top of actual image 31236 var imgContent = ''; 31237 var altAttr = alt ? 'alt="' + alt + '"' : ''; 31238 if (this.isFirstSlideWithZoomAnimation()) { 31239 imgContent = this.getDummyImageContent($currentSlide, index, altAttr); 31240 } 31241 else { 31242 imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources); 31243 } 31244 var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>"; 31245 $currentSlide.prepend(imgMarkup); 31246 }; 31247 LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) { 31248 var mediaObject = $slide.find('.lg-object').first(); 31249 if (utils.isImageLoaded(mediaObject.get()) || 31250 isHTML5VideoWithoutPoster) { 31251 onLoad(); 31252 } 31253 else { 31254 mediaObject.on('load.lg error.lg', function () { 31255 onLoad && onLoad(); 31256 }); 31257 mediaObject.on('error.lg', function () { 31258 onError && onError(); 31259 }); 31260 } 31261 }; 31262 /** 31263 * 31264 * @param $el Current slide item 31265 * @param index 31266 * @param delay Delay is 0 except first time 31267 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin 31268 * @param isFirstSlide 31269 */ 31270 LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) { 31271 var _this = this; 31272 //Uncode edit ##START## 31273 var $item = _this.galleryItems[index], 31274 type = $item.type; 31275 31276 if ( typeof $item.src !== 'undefined' ) { 31277 var inline_id = $item.src.replace('#', ''), 31278 $inline = document.getElementById(inline_id), 31279 inline_html; 31280 31281 if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) { 31282 inline_html = $inline.innerHTML; 31283 } else { 31284 inline_html = ''; 31285 } 31286 } 31287 //Uncode edit ##END## 31288 this.onSlideObjectLoad(currentSlide, true, function () { 31289 _this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide); 31290 }, function () { 31291 currentSlide.addClass('lg-complete lg-complete_'); 31292 //Uncode edit ##START## 31293 // currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>'); 31294 if ( inline_html !== '' ) { 31295 currentSlide.html(inline_html); 31296 } else { 31297 currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>'); 31298 } 31299 //Uncode edit ##END## 31300 }); 31301 }; 31302 LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) { 31303 var _this = this; 31304 var currentGalleryItem = this.galleryItems[index]; 31305 // Adding delay for video slides without poster for better performance and user experience 31306 // Videos should start playing once once the gallery is completely loaded 31307 var _speed = isFirstSlide &&
vendor: 3,676 bytes, lines 31308-31396
31308 this.getSlideType(currentGalleryItem) === 'video' && 31309 !currentGalleryItem.poster 31310 ? speed 31311 : 0; 31312 setTimeout(function () { 31313 $currentSlide.addClass('lg-complete lg-complete_'); 31314 _this.LGel.trigger(lGEvents.slideItemLoad, { 31315 index: index, 31316 delay: delay || 0, 31317 isFirstSlide: isFirstSlide, 31318 }); 31319 }, _speed); 31320 }; 31321 LightGallery.prototype.isFirstSlideWithZoomAnimation = function () { 31322 return !!(!this.lGalleryOn && 31323 this.zoomFromOrigin && 31324 this.currentImageSize); 31325 }; 31326 // Add video slideInfo 31327 LightGallery.prototype.addSlideVideoInfo = function (items) { 31328 var _this = this; 31329 items.forEach(function (element, index) { 31330 element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index); 31331 if (element.__slideVideoInfo && 31332 _this.settings.loadYouTubePoster && 31333 !element.poster && 31334 element.__slideVideoInfo.youtube) { 31335 element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg"; 31336 } 31337 }); 31338 }; 31339 /** 31340 * Load slide content into slide. 31341 * This is used to load content into slides that is not visible too 31342 * @param {Number} index - index of the slide. 31343 * @param {Boolean} rec - if true call loadcontent() function again. 31344 */ 31345 LightGallery.prototype.loadContent = function (index, rec) { 31346 var _this = this; 31347 var currentGalleryItem = this.galleryItems[index]; 31348 var $currentSlide = $LG(this.getSlideItemId(index)); 31349 var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources; 31350 var src = currentGalleryItem.src; 31351 var video = currentGalleryItem.video; 31352 var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video; 31353 if (currentGalleryItem.responsive) { 31354 var srcDyItms = currentGalleryItem.responsive.split(','); 31355 src = utils.getResponsiveSrc(srcDyItms) || src; 31356 } 31357 var videoInfo = currentGalleryItem.__slideVideoInfo; 31358 var lgVideoStyle = ''; 31359 var iframe = !!currentGalleryItem.iframe; 31360 var isFirstSlide = !this.lGalleryOn; 31361 // delay for adding complete class. it is 0 except first time. 31362 var delay = 0; 31363 if (isFirstSlide) { 31364 if (this.zoomFromOrigin && this.currentImageSize) { 31365 delay = this.settings.startAnimationDuration + 10; 31366 } 31367 else { 31368 delay = this.settings.backdropDuration + 10; 31369 } 31370 } 31371 if (!$currentSlide.hasClass('lg-loaded')) { 31372 if (videoInfo) { 31373 var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom; 31374 //Uncode edit ##START## 31375 var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 31376 // var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize); 31377 //Uncode edit ##END## 31378 lgVideoStyle = this.getVideoContStyle(videoSize); 31379 } 31380 if (iframe) { 31381 var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle); 31382 $currentSlide.prepend(markup); 31383 } 31384 else if (poster) { 31385 var dummyImg = ''; 31386 var hasStartAnimation = isFirstSlide && 31387 this.zoomFromOrigin && 31388 this.currentImageSize; 31389 if (hasStartAnimation) { 31390 dummyImg = this.getDummyImageContent($currentSlide, index, ''); 31391 } 31392 var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo); 31393 $currentSlide.prepend(markup); 31394 } 31395 //Uncode edit ##START## 31396 // else if (videoInfo) {
31397 else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') { 31398 if (! _html5Video) { 31399 var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>"; 31400 } 31401 //Uncode edit ##END## 31402 $currentSlide.prepend(markup); 31403 } 31404 else { 31405 //Uncode edit ##START## 31406 var $item = _this.galleryItems[index], 31407 type = $item.type; 31408 31409 if ( typeof $item.src !== 'undefined' ) { 31410 var inline_id = $item.src.replace('#', ''), 31411 $inline = document.getElementById(inline_id), 31412 inline_html; 31413 31414 if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) { 31415 inline_html = $inline.innerHTML; 31416 } else { 31417 inline_html = ''; 31418 } 31419 } 31420 if ( inline_html !== '' ) { 31421 $currentSlide.html(inline_html); 31422 } else { 31423 this.setImgMarkup(src, $currentSlide, index); 31424 if (srcset || sources) { 31425 var $img = $currentSlide.find('.lg-object'); 31426 this.initPictureFill($img); 31427 } 31428 } 31429 /*this.setImgMarkup(src, $currentSlide, index); 31430 if (srcset || sources) { 31431 var $img = $currentSlide.find('.lg-object'); 31432 this.initPictureFill($img); 31433 }*/ 31434 //Uncode edit ##END## 31435 } 31436 if (poster || videoInfo) { 31437 this.LGel.trigger(lGEvents.hasVideo, { 31438 index: index, 31439 src: src, 31440 html5Video: _html5Video, 31441 hasPoster: !!poster, 31442 }); 31443 } 31444 this.LGel.trigger(lGEvents.afterAppendSlide, { index: index }); 31445 if (this.lGalleryOn && 31446 this.settings.appendSubHtmlTo === '.lg-item') { 31447 this.addHtml(index); 31448 } 31449 } 31450 // For first time add some delay for displaying the start animation. 31451 var _speed = 0; 31452 // Do not change the delay value because it is required for zoom plugin. 31453 // If gallery opened from direct url (hash) speed value should be 0 31454 if (delay && !$LG(document.body).hasClass('lg-from-hash')) { 31455 _speed = delay; 31456 } 31457 // Only for first slide and zoomFromOrigin is enabled 31458 if (this.isFirstSlideWithZoomAnimation()) { 31459 setTimeout(function () { 31460 $currentSlide 31461 .removeClass('lg-start-end-progress lg-start-progress') 31462 .removeAttr('style'); 31463 }, this.settings.startAnimationDuration + 100); 31464 if (!$currentSlide.hasClass('lg-loaded')) { 31465 setTimeout(function () { 31466 if (_this.getSlideType(currentGalleryItem) === 'image') { 31467 var alt = currentGalleryItem.alt; 31468 var altAttr = alt ? 'alt="' + alt + '"' : ''; 31469 $currentSlide 31470 .find('.lg-img-wrap') 31471 .append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources)); 31472 if (srcset || sources) { 31473 var $img = $currentSlide.find('.lg-object'); 31474 _this.initPictureFill($img); 31475 } 31476 } 31477 if (_this.getSlideType(currentGalleryItem) === 'image' || 31478 (_this.getSlideType(currentGalleryItem) === 'video' && 31479 poster)) { 31480 _this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false); 31481 // load remaining slides once the slide is completely loaded 31482 _this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () { 31483 _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed); 31484 }, function () { 31485 _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed); 31486 }); 31487 } 31488 }, this.settings.startAnimationDuration + 100); 31489 } 31490 } 31491 // SLide content has been added to dom 31492 $currentSlide.addClass('lg-loaded'); 31493 if (!this.isFirstSlideWithZoomAnimation() || 31494 (this.getSlideType(currentGalleryItem) === 'video' && !poster)) { 31495 //Uncode edit ##START## 31496 // this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster)); 31497 this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.get
vendor: 31,133 bytes, lines 31497-32421
31497SlideType(currentGalleryItem) === 'audio')); 31498 //Uncode edit ##END## 31499 } 31500 // When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling 31501 if ((!this.zoomFromOrigin || !this.currentImageSize) && 31502 $currentSlide.hasClass('lg-complete_') && 31503 !this.lGalleryOn) { 31504 setTimeout(function () { 31505 $currentSlide.addClass('lg-complete'); 31506 }, this.settings.backdropDuration); 31507 } 31508 // Content loaded 31509 // Need to set lGalleryOn before calling preload function 31510 this.lGalleryOn = true; 31511 if (rec === true) { 31512 if (!$currentSlide.hasClass('lg-complete_')) { 31513 $currentSlide 31514 .find('.lg-object') 31515 .first() 31516 .on('load.lg error.lg', function () { 31517 _this.preload(index); 31518 }); 31519 } 31520 else { 31521 this.preload(index); 31522 } 31523 } 31524 }; 31525 /** 31526 * @desc Remove dummy image content and load next slides 31527 * Called only for the first time if zoomFromOrigin animation is enabled 31528 * @param index 31529 * @param $currentSlide 31530 * @param speed 31531 */ 31532 LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) { 31533 var _this = this; 31534 setTimeout(function () { 31535 $currentSlide.find('.lg-dummy-img').remove(); 31536 $currentSlide.removeClass('lg-first-slide'); 31537 _this.outer.removeClass('lg-first-slide-loading'); 31538 _this.isDummyImageRemoved = true; 31539 _this.preload(index); 31540 }, speed + 300); 31541 }; 31542 LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) { 31543 var _this = this; 31544 if (numberOfItems === void 0) { numberOfItems = 0; } 31545 var itemsToBeInsertedToDom = []; 31546 // Minimum 2 items should be there 31547 var possibleNumberOfItems = Math.max(numberOfItems, 3); 31548 possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length); 31549 var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex; 31550 if (this.galleryItems.length <= 3) { 31551 this.galleryItems.forEach(function (_element, index) { 31552 itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index); 31553 }); 31554 return itemsToBeInsertedToDom; 31555 } 31556 if (index < (this.galleryItems.length - 1) / 2) { 31557 for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) { 31558 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx); 31559 } 31560 var numberOfExistingItems = itemsToBeInsertedToDom.length; 31561 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) { 31562 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1)); 31563 } 31564 } 31565 else { 31566 for (var idx = index; idx <= this.galleryItems.length - 1 && 31567 idx < index + possibleNumberOfItems / 2; idx++) { 31568 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx); 31569 } 31570 var numberOfExistingItems = itemsToBeInsertedToDom.length; 31571 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) { 31572 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1)); 31573 } 31574 } 31575 if (this.settings.loop) { 31576 if (index === this.galleryItems.length - 1) { 31577 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0); 31578 } 31579 else if (index === 0) { 31580 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1)); 31581 } 31582 } 31583 if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) { 31584 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex); 31585 } 31586 return itemsToBeInsertedToDom; 31587 }; 31588 LightGallery.prototype.organizeSlideItems = function (index, prevIndex) { 31589 var _this = this; 31590 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom); 31591 itemsToBeInsertedToDom.forEach(function (item) { 31592 if (_this.currentItemsInDom.indexOf(item) === -1) { 31593 _this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>"); 31594 } 31595 }); 31596 this.currentItemsInDom.forEach(function (item) { 31597 if (itemsToBeInsertedToDom.indexOf(item) === -1) { 31598 $LG("#" + item).remove(); 31599 } 31600 }); 31601 return itemsToBeInsertedToDom; 31602 }; 31603 /** 31604 * Get previous index of the slide 31605 */ 31606 LightGallery.prototype.getPreviousSlideIndex = function () { 31607 var prevIndex = 0; 31608 try { 31609 var currentItemId = this.outer 31610 .find('.lg-current') 31611 .first() 31612 .attr('id'); 31613 prevIndex = parseInt(currentItemId.split('-')[3]) || 0; 31614 } 31615 catch (error) { 31616 prevIndex = 0; 31617 } 31618 return prevIndex; 31619 }; 31620 LightGallery.prototype.setDownloadValue = function (index) { 31621 if (this.settings.download) { 31622 var currentGalleryItem = this.galleryItems[index]; 31623 var hideDownloadBtn = currentGalleryItem.downloadUrl === false || 31624 currentGalleryItem.downloadUrl === 'false'; 31625 if (hideDownloadBtn) { 31626 this.outer.addClass('lg-hide-download'); 31627 } 31628 else { 31629 var $download = this.getElementById('lg-download'); 31630 this.outer.removeClass('lg-hide-download'); 31631 $download.attr('href', currentGalleryItem.downloadUrl || 31632 currentGalleryItem.src); 31633 if (currentGalleryItem.download) { 31634 //Uncode edit ##START## 31635 if ( typeof currentGalleryItem.video !== 'undefined' && currentGalleryItem.video ) { 31636 var currentVideo = JSON.parse( currentGalleryItem.video ), 31637 download_name = currentVideo.source[0].src; 31638 $download.attr('href', download_name).removeAttr('download'); 31639 } else { 31640 var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src, 31641 download_name = download_url.substring(download_url.lastIndexOf('/')+1); 31642 $download.attr('download', download_name); 31643 } 31644 // $download.attr('download', currentGalleryItem.download); 31645 //Uncode edit ##END## 31646 } 31647 } 31648 } 31649 }; 31650 LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) { 31651 var _this = this; 31652 if (this.lGalleryOn) { 31653 previousSlideItem.addClass('lg-slide-progress'); 31654 } 31655 setTimeout(function () { 31656 // remove all transitions 31657 _this.outer.addClass('lg-no-trans'); 31658 _this.outer 31659 .find('.lg-item') 31660 .removeClass('lg-prev-slide lg-next-slide'); 31661 if (direction === 'prev') { 31662 //prevslide 31663 currentSlideItem.addClass('lg-prev-slide'); 31664 previousSlideItem.addClass('lg-next-slide'); 31665 } 31666 else { 31667 // next slide 31668 currentSlideItem.addClass('lg-next-slide'); 31669 previousSlideItem.addClass('lg-prev-slide'); 31670 } 31671 // give 50 ms for browser to add/remove class 31672 setTimeout(function () { 31673 _this.outer.find('.lg-item').removeClass('lg-current'); 31674 currentSlideItem.addClass('lg-current'); 31675 // reset all transitions 31676 _this.outer.removeClass('lg-no-trans'); 31677 }, 50); 31678 }, this.lGalleryOn ? this.settings.slideDelay : 0); 31679 }; 31680 /** 31681 * Goto a specific slide. 31682 * @param {Number} index - index of the slide 31683 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag 31684 * @param {Boolean} fromThumb - true if slide function called via thumbnail click 31685 * @param {String} direction - Direction of the slide(next/prev) 31686 * @category lGPublicMethods 31687 * @example 31688 * const plugin = lightGallery(); 31689 * // to go to 3rd slide 31690 * plugin.slide(2); 31691 * 31692 */ 31693 LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) { 31694 var _this = this; 31695 var prevIndex = this.getPreviousSlideIndex(); 31696 this.currentItemsInDom = this.organizeSlideItems(index, prevIndex); 31697 // Prevent multiple call, Required for hsh plugin 31698 if (this.lGalleryOn && prevIndex === index) { 31699 return; 31700 } 31701 var numberOfGalleryItems = this.galleryItems.length; 31702 if (!this.lgBusy) { 31703 if (this.settings.counter) { 31704 this.updateCurrentCounter(index); 31705 } 31706 var currentSlideItem = this.getSlideItem(index); 31707 var previousSlideItem_1 = this.getSlideItem(prevIndex); 31708 var currentGalleryItem = this.galleryItems[index]; 31709 var videoInfo = currentGalleryItem.__slideVideoInfo; 31710 this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem)); 31711 this.setDownloadValue(index); 31712 if (videoInfo) { 31713 var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom; 31714 //Uncode edit ##START## 31715 var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 31716 // var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize); 31717 //Uncode edit ##END## 31718 this.resizeVideoSlide(index, videoSize); 31719 } 31720 this.LGel.trigger(lGEvents.beforeSlide, { 31721 prevIndex: prevIndex, 31722 index: index, 31723 fromTouch: !!fromTouch, 31724 fromThumb: !!fromThumb, 31725 //Uncode edit ##START## 31726 currentSlide: currentSlideItem, 31727 previousSlide: previousSlideItem_1, 31728 info: currentGalleryItem, 31729 item: this.items[index] 31730 //Uncode edit ##END## 31731 }); 31732 this.lgBusy = true; 31733 clearTimeout(this.hideBarTimeout); 31734 this.arrowDisable(index); 31735 if (!direction) { 31736 if (index < prevIndex) { 31737 direction = 'prev'; 31738 } 31739 else if (index > prevIndex) { 31740 direction = 'next'; 31741 } 31742 } 31743 if (!fromTouch) { 31744 this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1); 31745 } 31746 else { 31747 this.outer 31748 .find('.lg-item') 31749 .removeClass('lg-prev-slide lg-current lg-next-slide'); 31750 var touchPrev = void 0; 31751 var touchNext = void 0; 31752 if (numberOfGalleryItems > 2) { 31753 touchPrev = index - 1; 31754 touchNext = index + 1; 31755 if (index === 0 && prevIndex === numberOfGalleryItems - 1) { 31756 // next slide 31757 touchNext = 0; 31758 touchPrev = numberOfGalleryItems - 1; 31759 } 31760 else if (index === numberOfGalleryItems - 1 && 31761 prevIndex === 0) { 31762 // prev slide 31763 touchNext = 0; 31764 touchPrev = numberOfGalleryItems - 1; 31765 } 31766 } 31767 else { 31768 touchPrev = 0; 31769 touchNext = 1; 31770 } 31771 if (direction === 'prev') { 31772 this.getSlideItem(touchNext).addClass('lg-next-slide'); 31773 } 31774 else { 31775 this.getSlideItem(touchPrev).addClass('lg-prev-slide'); 31776 } 31777 currentSlideItem.addClass('lg-current'); 31778 } 31779 // Do not put load content in set timeout as it needs to load immediately when the gallery is opened 31780 if (!this.lGalleryOn) { 31781 this.loadContent(index, true); 31782 } 31783 else { 31784 setTimeout(function () { 31785 _this.loadContent(index, true); 31786 // Add title if this.settings.appendSubHtmlTo === lg-sub-html 31787 if (_this.settings.appendSubHtmlTo !== '.lg-item') { 31788 _this.addHtml(index); 31789 } 31790 }, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay)); 31791 } 31792 setTimeout(function () { 31793 _this.lgBusy = false; 31794 previousSlideItem_1.removeClass('lg-slide-progress'); 31795 _this.LGel.trigger(lGEvents.afterSlide, { 31796 prevIndex: prevIndex, 31797 index: index, 31798 fromTouch: fromTouch, 31799 fromThumb: fromThumb, 31800 }); 31801 }, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay)); 31802 } 31803 this.index = index; 31804 }; 31805 LightGallery.prototype.updateCurrentCounter = function (index) { 31806 this.getElementById('lg-counter-current').html(index + 1 + ''); 31807 }; 31808 LightGallery.prototype.updateCounterTotal = function () { 31809 this.getElementById('lg-counter-all').html(this.galleryItems.length + ''); 31810 }; 31811 LightGallery.prototype.getSlideType = function (item) { 31812 if (item.__slideVideoInfo) { 31813 return 'video'; 31814 } 31815 else if (item.iframe) { 31816 return 'iframe'; 31817 } 31818 //Uncode edit ##START## 31819 else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) { 31820 return 'audio'; 31821 } 31822 //Uncode edit ##END## 31823 else { 31824 return 'image'; 31825 } 31826 }; 31827 LightGallery.prototype.touchMove = function (startCoords, endCoords, e) { 31828 var distanceX = endCoords.pageX - startCoords.pageX; 31829 var distanceY = endCoords.pageY - startCoords.pageY; 31830 var allowSwipe = false; 31831 if (this.swipeDirection) { 31832 allowSwipe = true; 31833 } 31834 else { 31835 if (Math.abs(distanceX) > 15) { 31836 this.swipeDirection = 'horizontal'; 31837 allowSwipe = true; 31838 } 31839 else if (Math.abs(distanceY) > 15) { 31840 this.swipeDirection = 'vertical'; 31841 allowSwipe = true; 31842 } 31843 } 31844 if (!allowSwipe) { 31845 return; 31846 } 31847 var $currentSlide = this.getSlideItem(this.index); 31848 if (this.swipeDirection === 'horizontal') { 31849 e === null || e === void 0 ? void 0 : e.preventDefault(); 31850 // reset opacity and transition duration 31851 this.outer.addClass('lg-dragging'); 31852 // move current slide 31853 this.setTranslate($currentSlide, distanceX, 0); 31854 // move next and prev slide with current slide 31855 var width = $currentSlide.get().offsetWidth; 31856 var slideWidthAmount = (width * 15) / 100; 31857 var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100); 31858 this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0); 31859 this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0); 31860 } 31861 else if (this.swipeDirection === 'vertical') { 31862 if (this.settings.swipeToClose) { 31863 e === null || e === void 0 ? void 0 : e.preventDefault(); 31864 this.$container.addClass('lg-dragging-vertical'); 31865 var opacity = 1 - Math.abs(distanceY) / window.innerHeight; 31866 this.$backdrop.css('opacity', opacity); 31867 var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2); 31868 this.setTranslate($currentSlide, 0, distanceY, scale, scale); 31869 if (Math.abs(distanceY) > 100) { 31870 this.outer 31871 .addClass('lg-hide-items') 31872 .removeClass('lg-components-open'); 31873 } 31874 } 31875 } 31876 }; 31877 LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) { 31878 var _this = this; 31879 var distance; 31880 // keep slide animation for any mode while dragg/swipe 31881 if (this.settings.mode !== 'lg-slide') { 31882 this.outer.addClass('lg-slide'); 31883 } 31884 // set transition duration 31885 setTimeout(function () { 31886 _this.$container.removeClass('lg-dragging-vertical'); 31887 _this.outer 31888 .removeClass('lg-dragging lg-hide-items') 31889 .addClass('lg-components-open'); 31890 var triggerClick = true; 31891 if (_this.swipeDirection === 'horizontal') { 31892 distance = endCoords.pageX - startCoords.pageX; 31893 var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX); 31894 if (distance < 0 && 31895 distanceAbs > _this.settings.swipeThreshold) { 31896 _this.goToNextSlide(true); 31897 triggerClick = false; 31898 } 31899 else if (distance > 0 && 31900 distanceAbs > _this.settings.swipeThreshold) { 31901 _this.goToPrevSlide(true); 31902 triggerClick = false; 31903 } 31904 } 31905 else if (_this.swipeDirection === 'vertical') { 31906 distance = Math.abs(endCoords.pageY - startCoords.pageY); 31907 if (_this.settings.closable && 31908 _this.settings.swipeToClose && 31909 distance > 100) { 31910 _this.closeGallery(); 31911 return; 31912 } 31913 else { 31914 _this.$backdrop.css('opacity', 1); 31915 } 31916 } 31917 _this.outer.find('.lg-item').removeAttr('style'); 31918 if (triggerClick && 31919 Math.abs(endCoords.pageX - startCoords.pageX) < 5) { 31920 // Trigger click if distance is less than 5 pix 31921 var target = $LG(event.target); 31922 if (_this.isPosterElement(target)) { 31923 _this.LGel.trigger(lGEvents.posterClick); 31924 } 31925 } 31926 _this.swipeDirection = undefined; 31927 }); 31928 // remove slide class once drag/swipe is completed if mode is not slide 31929 setTimeout(function () { 31930 if (!_this.outer.hasClass('lg-dragging') && 31931 _this.settings.mode !== 'lg-slide') { 31932 _this.outer.removeClass('lg-slide'); 31933 } 31934 }, this.settings.speed + 100); 31935 }; 31936 LightGallery.prototype.enableSwipe = function () { 31937 var _this = this; 31938 var startCoords = {}; 31939 var endCoords = {}; 31940 var isMoved = false; 31941 var isSwiping = false; 31942 if (this.settings.enableSwipe) { 31943 this.$inner.on('touchstart.lg', function (e) { 31944 _this.dragOrSwipeEnabled = true; 31945 var $item = _this.getSlideItem(_this.index); 31946 if (($LG(e.target).hasClass('lg-item') || 31947 $item.get().contains(e.target)) && 31948 !_this.outer.hasClass('lg-zoomed') && 31949 !_this.lgBusy && 31950 e.targetTouches.length === 1) { 31951 isSwiping = true; 31952 _this.touchAction = 'swipe'; 31953 _this.manageSwipeClass(); 31954 startCoords = { 31955 pageX: e.targetTouches[0].pageX, 31956 pageY: e.targetTouches[0].pageY, 31957 }; 31958 } 31959 }); 31960 this.$inner.on('touchmove.lg', function (e) { 31961 if (isSwiping && 31962 _this.touchAction === 'swipe' && 31963 e.targetTouches.length === 1) { 31964 endCoords = { 31965 pageX: e.targetTouches[0].pageX, 31966 pageY: e.targetTouches[0].pageY, 31967 }; 31968 _this.touchMove(startCoords, endCoords, e); 31969 isMoved = true; 31970 } 31971 }); 31972 this.$inner.on('touchend.lg', function (event) { 31973 if (_this.touchAction === 'swipe') { 31974 if (isMoved) { 31975 isMoved = false; 31976 _this.touchEnd(endCoords, startCoords, event); 31977 } 31978 else if (isSwiping) { 31979 var target = $LG(event.target); 31980 if (_this.isPosterElement(target)) { 31981 _this.LGel.trigger(lGEvents.posterClick); 31982 } 31983 } 31984 _this.touchAction = undefined; 31985 isSwiping = false; 31986 } 31987 }); 31988 } 31989 }; 31990 LightGallery.prototype.enableDrag = function () { 31991 var _this = this; 31992 var startCoords = {}; 31993 var endCoords = {}; 31994 var isDraging = false; 31995 var isMoved = false; 31996 if (this.settings.enableDrag) { 31997 this.outer.on('mousedown.lg', function (e) { 31998 _this.dragOrSwipeEnabled = true; 31999 var $item = _this.getSlideItem(_this.index); 32000 if ($LG(e.target).hasClass('lg-item') || 32001 $item.get().contains(e.target)) { 32002 if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) { 32003 e.preventDefault(); 32004 if (!_this.lgBusy) { 32005 _this.manageSwipeClass(); 32006 startCoords = { 32007 pageX: e.pageX, 32008 pageY: e.pageY, 32009 }; 32010 isDraging = true; 32011 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 32012 _this.outer.get().scrollLeft += 1; 32013 _this.outer.get().scrollLeft -= 1; 32014 // * 32015 _this.outer 32016 .removeClass('lg-grab') 32017 .addClass('lg-grabbing'); 32018 _this.LGel.trigger(lGEvents.dragStart); 32019 } 32020 } 32021 } 32022 }); 32023 $LG(window).on("mousemove.lg.global" + this.lgId, function (e) { 32024 if (isDraging && _this.lgOpened) { 32025 isMoved = true; 32026 endCoords = { 32027 pageX: e.pageX, 32028 pageY: e.pageY, 32029 }; 32030 _this.touchMove(startCoords, endCoords); 32031 _this.LGel.trigger(lGEvents.dragMove); 32032 } 32033 }); 32034 $LG(window).on("mouseup.lg.global" + this.lgId, function (event) { 32035 if (!_this.lgOpened) { 32036 return; 32037 } 32038 var target = $LG(event.target); 32039 if (isMoved) { 32040 isMoved = false; 32041 _this.touchEnd(endCoords, startCoords, event); 32042 _this.LGel.trigger(lGEvents.dragEnd); 32043 } 32044 else if (_this.isPosterElement(target)) { 32045 _this.LGel.trigger(lGEvents.posterClick); 32046 } 32047 // Prevent execution on click 32048 if (isDraging) { 32049 isDraging = false; 32050 _this.outer.removeClass('lg-grabbing').addClass('lg-grab'); 32051 } 32052 }); 32053 } 32054 }; 32055 LightGallery.prototype.triggerPosterClick = function () { 32056 var _this = this; 32057 this.$inner.on('click.lg', function (event) { 32058 if (!_this.dragOrSwipeEnabled && 32059 _this.isPosterElement($LG(event.target))) { 32060 _this.LGel.trigger(lGEvents.posterClick); 32061 } 32062 }); 32063 }; 32064 LightGallery.prototype.manageSwipeClass = function () { 32065 var _touchNext = this.index + 1; 32066 var _touchPrev = this.index - 1; 32067 if (this.settings.loop && this.galleryItems.length > 2) { 32068 if (this.index === 0) { 32069 _touchPrev = this.galleryItems.length - 1; 32070 } 32071 else if (this.index === this.galleryItems.length - 1) { 32072 _touchNext = 0; 32073 } 32074 } 32075 this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide'); 32076 if (_touchPrev > -1) { 32077 this.getSlideItem(_touchPrev).addClass('lg-prev-slide'); 32078 } 32079 this.getSlideItem(_touchNext).addClass('lg-next-slide'); 32080 }; 32081 /** 32082 * Go to next slide 32083 * @param {Boolean} fromTouch - true if slide function called via touch event 32084 * @category lGPublicMethods 32085 * @example 32086 * const plugin = lightGallery(); 32087 * plugin.goToNextSlide(); 32088 * @see <a href="/demos/methods/">Demo</a> 32089 */ 32090 LightGallery.prototype.goToNextSlide = function (fromTouch) { 32091 var _this = this; 32092 var _loop = this.settings.loop; 32093 if (fromTouch && this.galleryItems.length < 3) { 32094 _loop = false; 32095 } 32096 if (!this.lgBusy) { 32097 if (this.index + 1 < this.galleryItems.length) { 32098 this.index++; 32099 this.LGel.trigger(lGEvents.beforeNextSlide, { 32100 index: this.index, 32101 }); 32102 this.slide(this.index, !!fromTouch, false, 'next'); 32103 } 32104 else { 32105 if (_loop) { 32106 this.index = 0; 32107 this.LGel.trigger(lGEvents.beforeNextSlide, { 32108 index: this.index, 32109 }); 32110 this.slide(this.index, !!fromTouch, false, 'next'); 32111 } 32112 else if (this.settings.slideEndAnimation && !fromTouch) { 32113 this.outer.addClass('lg-right-end'); 32114 setTimeout(function () { 32115 _this.outer.removeClass('lg-right-end'); 32116 }, 400); 32117 } 32118 } 32119 } 32120 }; 32121 /** 32122 * Go to previous slides 32123 * @param {Boolean} fromTouch - true if slide function called via touch event 32124 * @category lGPublicMethods 32125 * @example 32126 * const plugin = lightGallery({}); 32127 * plugin.goToPrevSlide(); 32128 * @see <a href="/demos/methods/">Demo</a> 32129 * 32130 */ 32131 LightGallery.prototype.goToPrevSlide = function (fromTouch) { 32132 var _this = this; 32133 var _loop = this.settings.loop; 32134 if (fromTouch && this.galleryItems.length < 3) { 32135 _loop = false; 32136 } 32137 if (!this.lgBusy) { 32138 if (this.index > 0) { 32139 this.index--; 32140 this.LGel.trigger(lGEvents.beforePrevSlide, { 32141 index: this.index, 32142 fromTouch: fromTouch, 32143 }); 32144 this.slide(this.index, !!fromTouch, false, 'prev'); 32145 } 32146 else { 32147 if (_loop) { 32148 this.index = this.galleryItems.length - 1; 32149 this.LGel.trigger(lGEvents.beforePrevSlide, { 32150 index: this.index, 32151 fromTouch: fromTouch, 32152 }); 32153 this.slide(this.index, !!fromTouch, false, 'prev'); 32154 } 32155 else if (this.settings.slideEndAnimation && !fromTouch) { 32156 this.outer.addClass('lg-left-end'); 32157 setTimeout(function () { 32158 _this.outer.removeClass('lg-left-end'); 32159 }, 400); 32160 } 32161 } 32162 } 32163 }; 32164 LightGallery.prototype.keyPress = function () { 32165 var _this = this; 32166 $LG(window).on("keydown.lg.global" + this.lgId, function (e) { 32167 if (_this.lgOpened && 32168 _this.settings.escKey === true && 32169 e.keyCode === 27) { 32170 e.preventDefault(); 32171 if (_this.settings.allowMediaOverlap && 32172 _this.outer.hasClass('lg-can-toggle') && 32173 _this.outer.hasClass('lg-components-open')) { 32174 _this.outer.removeClass('lg-components-open'); 32175 } 32176 else { 32177 _this.closeGallery(); 32178 } 32179 } 32180 if (_this.lgOpened && _this.galleryItems.length > 1) { 32181 if (e.keyCode === 37) { 32182 e.preventDefault(); 32183 _this.goToPrevSlide(); 32184 } 32185 if (e.keyCode === 39) { 32186 e.preventDefault(); 32187 _this.goToNextSlide(); 32188 } 32189 } 32190 }); 32191 }; 32192 LightGallery.prototype.arrow = function () { 32193 var _this = this; 32194 this.getElementById('lg-prev').on('click.lg', function () { 32195 _this.goToPrevSlide(); 32196 }); 32197 this.getElementById('lg-next').on('click.lg', function () { 32198 _this.goToNextSlide(); 32199 }); 32200 }; 32201 LightGallery.prototype.arrowDisable = function (index) { 32202 // Disable arrows if settings.hideControlOnEnd is true 32203 if (!this.settings.loop && this.settings.hideControlOnEnd) { 32204 var $prev = this.getElementById('lg-prev'); 32205 var $next = this.getElementById('lg-next'); 32206 if (index + 1 === this.galleryItems.length) { 32207 $next.attr('disabled', 'disabled').addClass('disabled'); 32208 } 32209 else { 32210 $next.removeAttr('disabled').removeClass('disabled'); 32211 } 32212 if (index === 0) { 32213 $prev.attr('disabled', 'disabled').addClass('disabled'); 32214 } 32215 else { 32216 $prev.removeAttr('disabled').removeClass('disabled'); 32217 } 32218 } 32219 }; 32220 LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) { 32221 if (scaleX === void 0) { scaleX = 1; } 32222 if (scaleY === void 0) { scaleY = 1; } 32223 $el.css('transform', 'translate3d(' + 32224 xValue + 32225 'px, ' + 32226 yValue + 32227 'px, 0px) scale3d(' + 32228 scaleX + 32229 ', ' + 32230 scaleY + 32231 ', 1)'); 32232 }; 32233 LightGallery.prototype.mousewheel = function () { 32234 var _this = this; 32235 var lastCall = 0; 32236 this.outer.on('wheel.lg', function (e) { 32237 if (!e.deltaY || _this.galleryItems.length < 2) { 32238 return; 32239 } 32240 e.preventDefault(); 32241 var now = new Date().getTime(); 32242 if (now - lastCall < 1000) { 32243 return; 32244 } 32245 lastCall = now; 32246 if (e.deltaY > 0) { 32247 _this.goToNextSlide(); 32248 } 32249 else if (e.deltaY < 0) { 32250 _this.goToPrevSlide(); 32251 } 32252 }); 32253 }; 32254 LightGallery.prototype.isSlideElement = function (target) { 32255 return (target.hasClass('lg-outer') || 32256 target.hasClass('lg-item') || 32257 target.hasClass('lg-img-wrap')); 32258 }; 32259 LightGallery.prototype.isPosterElement = function (target) { 32260 var playButton = this.getSlideItem(this.index) 32261 .find('.lg-video-play-button') 32262 .get(); 32263 return (target.hasClass('lg-video-poster') || 32264 target.hasClass('lg-video-play-button') || 32265 (playButton && playButton.contains(target.get()))); 32266 }; 32267 /** 32268 * Maximize minimize inline gallery. 32269 * @category lGPublicMethods 32270 */ 32271 LightGallery.prototype.toggleMaximize = function () { 32272 var _this = this; 32273 this.getElementById('lg-maximize').on('click.lg', function () { 32274 _this.$container.toggleClass('lg-inline'); 32275 _this.refreshOnResize(); 32276 }); 32277 }; 32278 LightGallery.prototype.invalidateItems = function () { 32279 for (var index = 0; index < this.items.length; index++) { 32280 var element = this.items[index]; 32281 var $element = $LG(element); 32282 $element.off("click.lgcustom-item-" + $element.attr('data-lg-id')); 32283 } 32284 }; 32285 LightGallery.prototype.trapFocus = function () { 32286 var _this = this; 32287 this.$container.get().focus({ 32288 preventScroll: true, 32289 }); 32290 $LG(window).on("keydown.lg.global" + this.lgId, function (e) { 32291 if (!_this.lgOpened) { 32292 return; 32293 } 32294 var isTabPressed = e.key === 'Tab' || e.keyCode === 9; 32295 if (!isTabPressed) { 32296 return; 32297 } 32298 var focusableEls = utils.getFocusableElements(_this.$container.get()); 32299 var firstFocusableEl = focusableEls[0]; 32300 var lastFocusableEl = focusableEls[focusableEls.length - 1]; 32301 if (e.shiftKey) { 32302 if (document.activeElement === firstFocusableEl) { 32303 lastFocusableEl.focus(); 32304 e.preventDefault(); 32305 } 32306 } 32307 else { 32308 if (document.activeElement === lastFocusableEl) { 32309 firstFocusableEl.focus(); 32310 e.preventDefault(); 32311 } 32312 } 32313 }); 32314 }; 32315 LightGallery.prototype.manageCloseGallery = function () { 32316 var _this = this; 32317 if (!this.settings.closable) 32318 return; 32319 var mousedown = false; 32320 this.getElementById('lg-close').on('click.lg', function () { 32321 _this.closeGallery(); 32322 }); 32323 if (this.settings.closeOnTap) { 32324 // If you drag the slide and release outside gallery gets close on chrome 32325 // for preventing this check mousedown and mouseup happened on .lg-item or lg-outer 32326 this.outer.on('mousedown.lg', function (e) { 32327 var target = $LG(e.target); 32328 if (_this.isSlideElement(target)) { 32329 mousedown = true; 32330 } 32331 else { 32332 mousedown = false; 32333 } 32334 }); 32335 this.outer.on('mousemove.lg', function () { 32336 mousedown = false; 32337 }); 32338 this.outer.on('mouseup.lg', function (e) { 32339 var target = $LG(e.target); 32340 if (_this.isSlideElement(target) && mousedown) { 32341 if (!_this.outer.hasClass('lg-dragging')) { 32342 _this.closeGallery(); 32343 } 32344 } 32345 }); 32346 } 32347 }; 32348 /** 32349 * Close lightGallery if it is opened. 32350 * 32351 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery 32352 * @return returns the estimated time to close gallery completely including the close animation duration 32353 * @category lGPublicMethods 32354 * @example 32355 * const plugin = lightGallery(); 32356 * plugin.closeGallery(); 32357 * 32358 */ 32359 LightGallery.prototype.closeGallery = function (force) { 32360 var _this = this; 32361 if (!this.lgOpened || (!this.settings.closable && !force)) { 32362 return 0; 32363 } 32364 this.LGel.trigger(lGEvents.beforeClose); 32365 if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) { 32366 $LG(window).scrollTop(this.prevScrollTop); 32367 } 32368 var currentItem = this.items[this.index]; 32369 var transform; 32370 if (this.zoomFromOrigin && currentItem) { 32371 var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom; 32372 var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster; 32373 //Uncode edit ##START## 32374 var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]); 32375 // var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize); 32376 //Uncode edit ##END## 32377 transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize); 32378 } 32379 if (this.zoomFromOrigin && transform) { 32380 this.outer.addClass('lg-closing lg-zoom-from-image'); 32381 this.getSlideItem(this.index) 32382 .addClass('lg-start-end-progress') 32383 .css('transition-duration', this.settings.startAnimationDuration + 'ms') 32384 .css('transform', transform); 32385 } 32386 else { 32387 this.outer.addClass('lg-hide-items'); 32388 // lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true 32389 // If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts 32390 this.outer.removeClass('lg-zoom-from-image'); 32391 } 32392 // Unbind all events added by lightGallery 32393 // @todo 32394 //this.$el.off('.lg.tm'); 32395 this.destroyModules(); 32396 this.lGalleryOn = false; 32397 this.isDummyImageRemoved = false; 32398 this.zoomFromOrigin = this.settings.zoomFromOrigin; 32399 clearTimeout(this.hideBarTimeout); 32400 this.hideBarTimeout = false; 32401 $LG('html').removeClass('lg-on'); 32402 this.outer.removeClass('lg-visible lg-components-open'); 32403 // Resetting opacity to 0 isd required as vertical swipe to close function adds inline opacity. 32404 this.$backdrop.removeClass('in').css('opacity', 0); 32405 var removeTimeout = this.zoomFromOrigin && transform 32406 ? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration) 32407 : this.settings.backdropDuration; 32408 this.$container.removeClass('lg-show-in'); 32409 // Once the closign animation is completed and gallery is invisible 32410 setTimeout(function () { 32411 if (_this.zoomFromOrigin && transform) { 32412 _this.outer.removeClass('lg-zoom-from-image'); 32413 } 32414 _this.$container.removeClass('lg-show'); 32415 // Reset scrollbar 32416 _this.resetScrollBar(); 32417 // Need to remove inline opacity as it is used in the stylesheet as well 32418 _this.$backdrop 32419 .removeAttr('style') 32420 .css('transition-duration', _this.settings.backdropDuration + 'ms'); 32421 _this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 32422-32625
32422 _this.getSlideItem(_this.index).removeClass('lg-start-end-progress'); 32423 _this.$inner.empty(); 32424 if (_this.lgOpened) { 32425 _this.LGel.trigger(lGEvents.afterClose, { 32426 instance: _this, 32427 }); 32428 } 32429 if (_this.$container.get()) { 32430 _this.$container.get().blur(); 32431 } 32432 _this.lgOpened = false; 32433 }, removeTimeout + 100); 32434 return removeTimeout + 100; 32435 }; 32436 LightGallery.prototype.initModules = function () { 32437 this.plugins.forEach(function (module) { 32438 try { 32439 module.init(); 32440 } 32441 catch (err) { 32442 console.warn("lightGallery:- make sure lightGallery module is properly initiated"); 32443 } 32444 }); 32445 }; 32446 LightGallery.prototype.destroyModules = function (destroy) { 32447 this.plugins.forEach(function (module) { 32448 try { 32449 if (destroy) { 32450 module.destroy(); 32451 } 32452 else { 32453 module.closeGallery && module.closeGallery(); 32454 } 32455 } 32456 catch (err) { 32457 console.warn("lightGallery:- make sure lightGallery module is properly destroyed"); 32458 } 32459 }); 32460 }; 32461 /** 32462 * Refresh lightGallery with new set of children. 32463 * 32464 * @description This is useful to update the gallery when the child elements are changed without calling destroy method. 32465 * 32466 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery 32467 * @see <a href="/demos/dynamic-mode/">Demo</a> 32468 * @category lGPublicMethods 32469 * @example 32470 * const plugin = lightGallery(); 32471 * // Delete or add children, then call 32472 * plugin.refresh(); 32473 * 32474 */ 32475 LightGallery.prototype.refresh = function (galleryItems) { 32476 if (!this.settings.dynamic) { 32477 this.invalidateItems(); 32478 } 32479 if (galleryItems) { 32480 this.galleryItems = galleryItems; 32481 } 32482 else { 32483 this.galleryItems = this.getItems(); 32484 } 32485 this.updateControls(); 32486 this.openGalleryOnItemClick(); 32487 this.LGel.trigger(lGEvents.updateSlides); 32488 }; 32489 LightGallery.prototype.updateControls = function () { 32490 this.addSlideVideoInfo(this.galleryItems); 32491 this.updateCounterTotal(); 32492 this.manageSingleSlideClassName(); 32493 }; 32494 /** 32495 * Destroy lightGallery. 32496 * Destroy lightGallery and its plugin instances completely 32497 * 32498 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance. 32499 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed. 32500 * You can use refresh method most of the times. 32501 * @category lGPublicMethods 32502 * @example 32503 * const plugin = lightGallery(); 32504 * plugin.destroy(); 32505 * 32506 */ 32507 LightGallery.prototype.destroy = function () { 32508 var _this = this; 32509 var closeTimeout = this.closeGallery(true); 32510 setTimeout(function () { 32511 _this.destroyModules(true); 32512 if (!_this.settings.dynamic) { 32513 _this.invalidateItems(); 32514 } 32515 $LG(window).off(".lg.global" + _this.lgId); 32516 _this.LGel.off('.lg'); 32517 _this.$container.remove(); 32518 }, closeTimeout); 32519 return closeTimeout; 32520 }; 32521 return LightGallery; 32522 }()); 32523 32524 function lightGallery(el, options) { 32525 return new LightGallery(el, options); 32526 } 32527 32528 return lightGallery; 32529 32530}))); 32531 32532/*! 32533 * lightgallery | 2.5.0 | June 13th 2022 32534 * http://www.lightgalleryjs.com/ 32535 * Copyright (c) 2020 Sachin Neravath; 32536 * @license GPLv3 32537 */ 32538 32539(function (global, factory) { 32540 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 32541 typeof define === 'function' && define.amd ? define(factory) : 32542 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory()); 32543}(this, (function () { 'use strict'; 32544 32545 /*! ***************************************************************************** 32546 Copyright (c) Microsoft Corporation. 32547 32548 Permission to use, copy, modify, and/or distribute this software for any 32549 purpose with or without fee is hereby granted. 32550 32551 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 32552 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 32553 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 32554 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 32555 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 32556 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 32557 PERFORMANCE OF THIS SOFTWARE. 32558 ***************************************************************************** */ 32559 32560 var __assign = function() { 32561 __assign = Object.assign || function __assign(t) { 32562 for (var s, i = 1, n = arguments.length; i < n; i++) { 32563 s = arguments[i]; 32564 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 32565 } 32566 return t; 32567 }; 32568 return __assign.apply(this, arguments); 32569 }; 32570 32571 var zoomSettings = { 32572 scale: 1, 32573 zoom: true, 32574 actualSize: true, 32575 showZoomInOutIcons: false, 32576 actualSizeIcons: { 32577 zoomIn: 'lg-zoom-in', 32578 zoomOut: 'lg-zoom-out', 32579 }, 32580 enableZoomAfter: 300, 32581 zoomPluginStrings: { 32582 zoomIn: 'Zoom in', 32583 zoomOut: 'Zoom out', 32584 viewActualSize: 'View actual size', 32585 }, 32586 }; 32587 32588 /** 32589 * List of lightGallery events 32590 * All events should be documented here 32591 * Below interfaces are used to build the website documentations 32592 * */ 32593 var lGEvents = { 32594 afterAppendSlide: 'lgAfterAppendSlide', 32595 init: 'lgInit', 32596 hasVideo: 'lgHasVideo', 32597 containerResize: 'lgContainerResize', 32598 updateSlides: 'lgUpdateSlides', 32599 afterAppendSubHtml: 'lgAfterAppendSubHtml', 32600 beforeOpen: 'lgBeforeOpen', 32601 afterOpen: 'lgAfterOpen', 32602 slideItemLoad: 'lgSlideItemLoad', 32603 beforeSlide: 'lgBeforeSlide', 32604 afterSlide: 'lgAfterSlide', 32605 posterClick: 'lgPosterClick', 32606 dragStart: 'lgDragStart', 32607 dragMove: 'lgDragMove', 32608 dragEnd: 'lgDragEnd', 32609 beforeNextSlide: 'lgBeforeNextSlide', 32610 beforePrevSlide: 'lgBeforePrevSlide', 32611 beforeClose: 'lgBeforeClose', 32612 afterClose: 'lgAfterClose', 32613 rotateLeft: 'lgRotateLeft', 32614 rotateRight: 'lgRotateRight', 32615 flipHorizontal: 'lgFlipHorizontal', 32616 flipVertical: 'lgFlipVertical', 32617 autoplay: 'lgAutoplay', 32618 autoplayStart: 'lgAutoplayStart', 32619 autoplayStop: 'lgAutoplayStop', 32620 }; 32621 32622 var Zoom = /** @class */ (function () { 32623 function Zoom(instance, $LG) { 32624 // get lightGallery core plugin instance 32625 this.core = instance;
32626 this.$LG = $LG; 32627 this.settings = __assign(__assign({}, zoomSettings), this.core.settings); 32628 return this; 32629 } 32630 // Append Zoom controls. Actual size, Zoom-in, Zoom-out 32631 Zoom.prototype.buildTemplates = function () { 32632 var zoomIcons = this.settings.showZoomInOutIcons 32633 ? "<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>" 32634 : ''; 32635 if (this.settings.actualSize) { 32636 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>"; 32637 } 32638 this.core.outer.addClass('lg-use-transition-for-zoom'); 32639 this.core.$toolbar.first().append(zoomIcons); 32640 }; 32641 /** 32642 * @desc Enable zoom option only once the image is completely loaded 32643 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted 32644 * 32645 * Zoom styles are defined under lg-zoomable CSS class. 32646 */ 32647 Zoom.prototype.enableZoom = function (event) { 32648 var _this = this; 32649 // delay will be 0 except first time 32650 var _speed = this.settings.enableZoomAfter + event.detail.delay; 32651 // set _speed value 0 if gallery opened from direct url and if it is first slide 32652 if (this.$LG('body').first().hasClass('lg-from-hash') && 32653 event.detail.delay) { 32654 // will execute only once 32655 _speed = 0; 32656 } 32657 else { 32658 // Remove lg-from-hash to enable starting animation. 32659 this.$LG('body').first().removeClass('lg-from-hash'); 32660 } 32661 this.zoomableTimeout = setTimeout(function () { 32662 if (!_this.isImageSlide()) { 32663 return; 32664 } 32665 _this.core.getSlideItem(event.detail.index).addClass('lg-zoomable'); 32666 if (event.detail.index === _this.core.index) { 32667 _this.setZoomEssentials(); 32668 } 32669 }, _speed + 30); 32670 }; 32671 Zoom.prototype.enableZoomOnSlideItemLoad = function () { 32672 // Add zoomable class 32673 this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this)); 32674 }; 32675 Zoom.prototype.getModifier = function (rotateValue, axis, el) { 32676 var originalRotate = rotateValue; 32677 rotateValue = Math.abs(rotateValue); 32678 var transformValues = this.getCurrentTransform(el); 32679 if (!transformValues) { 32680 return 1; 32681 } 32682 var modifier = 1; 32683 if (axis === 'X') { 32684 var flipHorizontalValue = Math.sign(parseFloat(transformValues[0])); 32685 if (rotateValue === 0 || rotateValue === 180) { 32686 modifier = 1; 32687 } 32688 else if (rotateValue === 90) { 32689 if ((originalRotate === -90 && flipHorizontalValue === 1) || 32690 (originalRotate === 90 && flipHorizontalValue === -1)) { 32691 modifier = -1; 32692 } 32693 else { 32694 modifier = 1; 32695 } 32696 } 32697 modifier = modifier * flipHorizontalValue; 32698 } 32699 else { 32700 var flipVerticalValue = Math.sign(parseFloat(transformValues[3])); 32701 if (rotateValue === 0 || rotateValue === 180) { 32702 modifier = 1; 32703 } 32704 else if (rotateValue === 90) { 32705 var sinX = parseFloat(transformValues[1]); 32706 var sinMinusX = parseFloat(transformValues[2]); 32707 modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue); 32708 } 32709 modifier = modifier * flipVerticalValue; 32710 } 32711 return modifier; 32712 }; 32713 Zoom.prototype.getImageSize = function ($image, rotateValue, axis) { 32714 var imageSizes = { 32715 y: 'offsetHeight', 32716 x: 'offsetWidth', 32717 }; 32718 if (Math.abs(rotateValue) === 90) { 32719 // Swap axis 32720 if (axis === 'x') { 32721 axis = 'y'; 32722 } 32723 else { 32724 axis = 'x'; 32725 } 32726 } 32727 return $image[imageSizes[axis]]; 32728 }; 32729 Zoom.prototype.getDragCords = function (e, rotateValue) { 32730 if (rotateValue === 90) { 32731 return { 32732 x: e.pageY, 32733 y: e.pageX, 32734 }; 32735 } 32736 else { 32737 return { 32738 x: e.pageX, 32739 y: e.pageY, 32740 }; 32741 } 32742 }; 32743 Zoom.prototype.getSwipeCords = function (e, rotateValue) { 32744 var x = e.targetTouches[0].pageX; 32745 var y = e.targetTouches[0].pageY; 32746 if (rotateValue === 90) { 32747 return { 32748 x: y, 32749 y: x, 32750 }; 32751 } 32752 else { 32753 return { 32754 x: x, 32755 y: y, 32756 }; 32757 } 32758 }; 32759 Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) { 32760 scale = scale || this.scale || 1; 32761 var allowY = this.imageYSize * scale > this.containerRect.height; 32762 var allowX = this.imageXSize * scale > this.containerRect.width; 32763 if (rotateValue === 90) { 32764 return { 32765 allowX: allowY, 32766 allowY: allowX, 32767 }; 32768 } 32769 else { 32770 return { 32771 allowX: allowX, 32772 allowY: allowY, 32773 }; 32774 } 32775 }; 32776 /** 32777 * 32778 * @param {Element} el 32779 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); 32780 * Get the current transform value 32781 */ 32782 Zoom.prototype.getCurrentTransform = function (el) { 32783 if (!el) { 32784 return; 32785 } 32786 var st = window.getComputedStyle(el, null); 32787 var tm = st.getPropertyValue('-webkit-transform') || 32788 st.getPropertyValue('-moz-transform') || 32789 st.getPropertyValue('-ms-transform') || 32790 st.getPropertyValue('-o-transform') || 32791 st.getPropertyValue('transform') || 32792 'none'; 32793 if (tm !== 'none') { 32794 return tm.split('(')[1].split(')')[0].split(','); 32795 } 32796 return; 32797 }; 32798 Zoom.prototype.getCurrentRotation = function (el) { 32799 if (!el) { 32800 return 0; 32801 } 32802 var values = this.getCurrentTransform(el); 32803 if (values) { 32804 return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) * 32805 (180 / Math.PI)); 32806 // If you want rotate in 360 32807 //return (angle < 0 ? angle + 360 : angle); 32808 } 32809 return 0; 32810 }; 32811 Zoom.prototype.setZoomEssentials = function () { 32812 var $image = this.core 32813 .getSlideItem(this.core.index) 32814 .find('.lg-image') 32815 .first(); 32816 var rotateEl = this.core 32817 .getSlideItem(this.core.index) 32818 .find('.lg-img-rotate') 32819 .first() 32820 .get(); 32821 this.rotateValue = this.getCurrentRotation(rotateEl); 32822 this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y'); 32823 this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x'); 32824 this.containerRect = this.core.outer.get().getBoundingClientRect(); 32825 this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl); 32826 this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl); 32827 }; 32828 /** 32829 * @desc Image zoom 32830 * Translate the wrap and scale the image to get better user experience 32831 * 32832 * @param {String} scale - Zoom decrement/increment value 32833 */ 32834 Zoom.prototype.zoomImage = function (scale) { 32835 // Find offset manually to avoid issue after zoom 32836 var offsetX = (this.containerRect.width - this.imageXSize) / 2 + 32837 this.containerRect.left; 32838 var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 32839 var topBottomSpacing = Math.abs(top - bottom) / 2; 32840 var offsetY = (this.containerRect.height - 32841 this.imageYSize - 32842 topBottomSpacing * this.modifierX) / 32843 2 + 32844 this.scrollTop + 32845 this.containerRect.top; 32846 var originalX; 32847 var originalY; 32848 if (scale === 1) { 32849 this.positionChanged = false;
32850 } 32851 var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale); 32852 var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX; 32853 if (this.positionChanged) { 32854 originalX = this.left / (this.scale - 1); 32855 originalY = this.top / (this.scale - 1); 32856 this.pageX = Math.abs(originalX) + offsetX; 32857 this.pageY = Math.abs(originalY) + offsetY; 32858 this.positionChanged = false; 32859 } 32860 var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale); 32861 var _x = offsetX - this.pageX; 32862 var _y = offsetY - this.pageY; 32863 var x = (scale - 1) * _x; 32864 var y = (scale - 1) * _y; 32865 if (allowX) { 32866 if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) { 32867 x = possibleSwipeCords.minX; 32868 } 32869 else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) { 32870 x = possibleSwipeCords.maxX; 32871 } 32872 } 32873 else { 32874 if (scale > 1) { 32875 if (x < possibleSwipeCords.minX) { 32876 x = possibleSwipeCords.minX; 32877 } 32878 else if (x > possibleSwipeCords.maxX) { 32879 x = possibleSwipeCords.maxX; 32880 } 32881 } 32882 }
32883 if (allowY) { 32884 if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) { 32885 y = possibleSwipeCords.minY; 32886 } 32887 else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) { 32888 y = possibleSwipeCords.maxY; 32889 } 32890 } 32891 else { 32892 // If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out 32893 if (scale > 1) { 32894 //If image goes beyond viewport top, use the minim possible translate value 32895 if (y < possibleSwipeCords.minY) { 32896 y = possibleSwipeCords.minY; 32897 } 32898 else if (y > possibleSwipeCords.maxY) { 32899 y = possibleSwipeCords.maxY; 32900 } 32901 } 32902 } 32903 this.setZoomStyles({ 32904 x: x, 32905 y: y, 32906 scale: scale, 32907 }); 32908 }; 32909 /** 32910 * @desc apply scale3d to image and translate to image wrap 32911 * @param {style} X,Y and scale 32912 */ 32913 Zoom.prototype.setZoomStyles = function (style) { 32914 var $image = this.core 32915 .getSlideItem(this.core.index) 32916 .find('.lg-image') 32917 .first(); 32918 var $dummyImage = this.core.outer 32919 .find('.lg-current .lg-dummy-img') 32920 .first(); 32921 var $imageWrap = $image.parent(); 32922 this.scale = style.scale; 32923 $image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)'); 32924 $dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)'); 32925 var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)'; 32926 $imageWrap.css('transform', transform); 32927 this.left = style.x; 32928 this.top = style.y; 32929 }; 32930 /** 32931 * @param index - Index of the current slide 32932 * @param event - event will be available only if the function is called on clicking/taping the imags 32933 */ 32934 Zoom.prototype.setActualSize = function (index, event) { 32935 var _this = this; 32936 // Allow zoom only on image 32937 if (!this.isImageSlide() || 32938 this.core.outer.hasClass('lg-first-slide-loading')) { 32939 return; 32940 } 32941 var scale = this.getCurrentImageActualSizeScale(); 32942 if (this.core.outer.hasClass('lg-zoomed')) { 32943 this.scale = 1; 32944 } 32945 else { 32946 this.scale = this.getScale(scale); 32947 } 32948 this.setPageCords(event); 32949 this.beginZoom(this.scale); 32950 this.zoomImage(this.scale); 32951 setTimeout(function () { 32952 _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab'); 32953 }, 10); 32954 }; 32955 Zoom.prototype.getNaturalWidth = function (index) { 32956 var $image = this.core.getSlideItem(index).find('.lg-image').first(); 32957 var naturalWidth = this.core.galleryItems[index].width; 32958 return naturalWidth 32959 ? parseFloat(naturalWidth) 32960 : $image.get().naturalWidth; 32961 }; 32962 Zoom.prototype.getActualSizeScale = function (naturalWidth, width) { 32963 var _scale; 32964 var scale;
32965 if (naturalWidth > width) { 32966 _scale = naturalWidth / width; 32967 scale = _scale || 2; 32968 } 32969 else { 32970 scale = 1; 32971 } 32972 return scale; 32973 }; 32974 Zoom.prototype.getCurrentImageActualSizeScale = function () { 32975 var $image = this.core 32976 .getSlideItem(this.core.index) 32977 .find('.lg-image') 32978 .first(); 32979 var width = $image.get().offsetWidth; 32980 var naturalWidth = this.getNaturalWidth(this.core.index) || width; 32981 return this.getActualSizeScale(naturalWidth, width); 32982 }; 32983 Zoom.prototype.getPageCords = function (event) { 32984 var cords = {}; 32985 if (event) { 32986 cords.x = event.pageX || event.targetTouches[0].pageX; 32987 cords.y = event.pageY || event.targetTouches[0].pageY; 32988 } 32989 else { 32990 var containerRect = this.core.outer.get().getBoundingClientRect(); 32991 cords.x = containerRect.width / 2 + containerRect.left; 32992 cords.y = 32993 containerRect.height / 2 + this.scrollTop + containerRect.top; 32994 } 32995 return cords; 32996 }; 32997 Zoom.prototype.setPageCords = function (event) { 32998 var pageCords = this.getPageCords(event); 32999 this.pageX = pageCords.x; 33000 this.pageY = pageCords.y; 33001 }; 33002 // If true, zoomed - in else zoomed out 33003 Zoom.prototype.beginZoom = function (scale) { 33004 this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging'); 33005 if (scale > 1) { 33006 this.core.outer.addClass('lg-zoomed'); 33007 var $actualSize = this.core.getElementById('lg-actual-size'); 33008 $actualSize 33009 .removeClass(this.settings.actualSizeIcons.zoomIn) 33010 .addClass(this.settings.actualSizeIcons.zoomOut); 33011 } 33012 else { 33013 this.resetZoom(); 33014 } 33015 return scale > 1; 33016 }; 33017 Zoom.prototype.getScale = function (scale) { 33018 var actualSizeScale = this.getCurrentImageActualSizeScale(); 33019 if (scale < 1) { 33020 scale = 1; 33021 } 33022 else if (scale > actualSizeScale) { 33023 scale = actualSizeScale; 33024 } 33025 return scale; 33026 }; 33027 Zoom.prototype.init = function () { 33028 var _this = this; 33029 if (!this.settings.zoom) { 33030 return; 33031 } 33032 this.buildTemplates(); 33033 this.enableZoomOnSlideItemLoad(); 33034 var tapped = null; 33035 this.core.outer.on('dblclick.lg', function (event) { 33036 if (!_this.$LG(event.target).hasClass('lg-image')) { 33037 return; 33038 } 33039 _this.setActualSize(_this.core.index, event); 33040 }); 33041 this.core.outer.on('touchstart.lg', function (event) { 33042 var $target = _this.$LG(event.target); 33043 if (event.targetTouches.length === 1 && 33044 $target.hasClass('lg-image')) { 33045 if (!tapped) { 33046 tapped = setTimeout(function () { 33047 tapped = null; 33048 }, 300); 33049 } 33050 else { 33051 clearTimeout(tapped); 33052 tapped = null; 33053 event.preventDefault(); 33054 _this.setActualSize(_this.core.index, event); 33055 } 33056 } 33057 }); 33058 // Update zoom on resize and orientationchange 33059 this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () { 33060 if (!_this.core.lgOpened || !_this.isImageSlide()) 33061 return; 33062 _this.setPageCords(); 33063 _this.setZoomEssentials(); 33064 _this.zoomImage(_this.scale); 33065 }); 33066 // Update zoom on resize and orientationchange 33067 this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () { 33068 if (!_this.core.lgOpened) 33069 return; 33070 _this.scrollTop = _this.$LG(window).scrollTop(); 33071 }); 33072 this.core.getElementById('lg-zoom-out').on('click.lg', function () { 33073 if (_this.core.outer.find('.lg-current .lg-image').get()) { 33074 _this.scale -= _this.settings.scale; 33075 _this.scale = _this.getScale(_this.scale); 33076 _this.beginZoom(_this.scale); 33077 _this.zoomImage(_this.scale); 33078 } 33079 }); 33080 this.core.getElementById('lg-zoom-in').on('click.lg', function () { 33081 _this.zoomIn(); 33082 }); 33083 this.core.getElementById('lg-actual-size').on('click.lg', function () { 33084 _this.setActualSize(_this.core.index); 33085 }); 33086 this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () { 33087 _this.core.outer.find('.lg-item').removeClass('lg-zoomable'); 33088 }); 33089 this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () { 33090 _this.scrollTop = _this.$LG(window).scrollTop(); 33091 // Set the initial value center 33092 _this.pageX = _this.core.outer.width() / 2;
33093 _this.pageY = _this.core.outer.height() / 2 + _this.scrollTop; 33094 _this.scale = 1; 33095 }); 33096 // Reset zoom on slide change 33097 this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) { 33098 var prevIndex = event.detail.prevIndex; 33099 _this.scale = 1; 33100 _this.positionChanged = false; 33101 _this.resetZoom(prevIndex); 33102 if (_this.isImageSlide()) { 33103 _this.setZoomEssentials(); 33104 } 33105 }); 33106 // Drag option after zoom 33107 this.zoomDrag(); 33108 this.pinchZoom(); 33109 this.zoomSwipe(); 33110 // Store the zoomable timeout value just to clear it while closing 33111 this.zoomableTimeout = false; 33112 this.positionChanged = false; 33113 }; 33114 Zoom.prototype.zoomIn = function (scale) { 33115 // Allow zoom only on image 33116 if (!this.isImageSlide()) { 33117 return; 33118 } 33119 if (scale) { 33120 this.scale = scale; 33121 } 33122 else { 33123 this.scale += this.settings.scale; 33124 } 33125 this.scale = this.getScale(this.scale); 33126 this.beginZoom(this.scale); 33127 this.zoomImage(this.scale); 33128 }; 33129 // Reset zoom effect 33130 Zoom.prototype.resetZoom = function (index) { 33131 this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition'); 33132 var $actualSize = this.core.getElementById('lg-actual-size'); 33133 var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index); 33134 $actualSize 33135 .removeClass(this.settings.actualSizeIcons.zoomOut) 33136 .addClass(this.settings.actualSizeIcons.zoomIn); 33137 $item.find('.lg-img-wrap').first().removeAttr('style'); 33138 $item.find('.lg-image').first().removeAttr('style'); 33139 this.scale = 1; 33140 this.left = 0; 33141 this.top = 0; 33142 // Reset pagx pagy values to center 33143 this.setPageCords(); 33144 }; 33145 Zoom.prototype.getTouchDistance = function (e) { 33146 return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) * 33147 (e.targetTouches[0].pageX - e.targetTouches[1].pageX) + 33148 (e.targetTouches[0].pageY - e.targetTouches[1].pageY) * 33149 (e.targetTouches[0].pageY - e.targetTouches[1].pageY)); 33150 }; 33151 Zoom.prototype.pinchZoom = function () { 33152 var _this = this; 33153 var startDist = 0; 33154 var pinchStarted = false; 33155 var initScale = 1; 33156 var $item = this.core.getSlideItem(this.core.index); 33157 this.core.$inner.on('touchstart.lg', function (e) { 33158 $item = _this.core.getSlideItem(_this.core.index); 33159 if (!_this.isImageSlide()) { 33160 return; 33161 } 33162 if (e.targetTouches.length === 2 && 33163 !_this.core.outer.hasClass('lg-first-slide-loading') && 33164 (_this.$LG(e.target).hasClass('lg-item') || 33165 $item.get().contains(e.target))) { 33166 initScale = _this.scale || 1; 33167 _this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging'); 33168 _this.core.touchAction = 'pinch'; 33169 startDist = _this.getTouchDistance(e); 33170 } 33171 }); 33172 this.core.$inner.on('touchmove.lg', function (e) { 33173 if (e.targetTouches.length === 2 && 33174 _this.core.touchAction === 'pinch' && 33175 (_this.$LG(e.target).hasClass('lg-item') || 33176 $item.get().contains(e.target))) { 33177 e.preventDefault(); 33178 var endDist = _this.getTouchDistance(e); 33179 var distance = startDist - endDist; 33180 if (!pinchStarted && Math.abs(distance) > 5) { 33181 pinchStarted = true; 33182 } 33183 if (pinchStarted) { 33184 _this.scale = Math.max(1, initScale + -distance * 0.008); 33185 _this.zoomImage(_this.scale); 33186 } 33187 } 33188 }); 33189 this.core.$inner.on('touchend.lg', function (e) { 33190 if (_this.core.touchAction === 'pinch' && 33191 (_this.$LG(e.target).hasClass('lg-item') || 33192 $item.get().contains(e.target))) { 33193 pinchStarted = false; 33194 startDist = 0; 33195 if (_this.scale <= 1) { 33196 _this.resetZoom(); 33197 } 33198 else { 33199 _this.scale = _this.getScale(_this.scale); 33200 _this.zoomImage(_this.scale); 33201 _this.core.outer.addClass('lg-zoomed'); 33202 } 33203 _this.core.touchAction = undefined; 33204 } 33205 }); 33206 }; 33207 Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) { 33208 var distanceXnew = endCoords.x - startCoords.x; 33209 var distanceYnew = endCoords.y - startCoords.y; 33210 var speedX = Math.abs(distanceXnew) / touchDuration + 1; 33211 var speedY = Math.abs(distanceYnew) / touchDuration + 1; 33212 if (speedX > 2) { 33213 speedX += 1; 33214 } 33215 if (speedY > 2) { 33216 speedY += 1; 33217 } 33218 distanceXnew = distanceXnew * speedX; 33219 distanceYnew = distanceYnew * speedY; 33220 var _LGel = this.core 33221 .getSlideItem(this.core.index) 33222 .find('.lg-img-wrap') 33223 .first(); 33224 var distance = {}; 33225 distance.x = this.left + distanceXnew * this.modifierX; 33226 distance.y = this.top + distanceYnew * this.modifierY; 33227 var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue); 33228 if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) { 33229 if (allowY) { 33230 if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) { 33231 distance.y = possibleSwipeCords.minY; 33232 } 33233 else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) { 33234 distance.y = possibleSwipeCords.maxY; 33235 } 33236 } 33237 if (allowX) { 33238 if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) { 33239 distance.x = possibleSwipeCords.minX; 33240 } 33241 else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) { 33242 distance.x = possibleSwipeCords.maxX; 33243 } 33244 } 33245 if (allowY) { 33246 this.top = distance.y; 33247 } 33248 else { 33249 distance.y = this.top; 33250 } 33251 if (allowX) { 33252 this.left = distance.x; 33253 } 33254 else { 33255 distance.x = this.left; 33256 } 33257 this.setZoomSwipeStyles(_LGel, distance); 33258 this.positionChanged = true; 33259 } 33260 }; 33261 Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) { 33262 var distance = {}; 33263 if (allowY) { 33264 distance.y = 33265 this.top + (endCoords.y - startCoords.y) * this.modifierY; 33266 if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) { 33267 var diffMinY = possibleSwipeCords.minY - distance.y; 33268 distance.y = possibleSwipeCords.minY - diffMinY / 6; 33269 } 33270 else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) { 33271 var diffMaxY = distance.y - possibleSwipeCords.maxY; 33272 distance.y = possibleSwipeCords.maxY + diffMaxY / 6; 33273 } 33274 } 33275 else { 33276 distance.y = this.top; 33277 }
33278 if (allowX) { 33279 distance.x = 33280 this.left + (endCoords.x - startCoords.x) * this.modifierX; 33281 if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) { 33282 var diffMinX = possibleSwipeCords.minX - distance.x; 33283 distance.x = possibleSwipeCords.minX - diffMinX / 6; 33284 } 33285 else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) { 33286 var difMaxX = distance.x - possibleSwipeCords.maxX; 33287 distance.x = possibleSwipeCords.maxX + difMaxX / 6; 33288 } 33289 } 33290 else { 33291 distance.x = this.left; 33292 } 33293 return distance; 33294 }; 33295 Zoom.prototype.isBeyondPossibleLeft = function (x, minX) { 33296 return x >= minX; 33297 }; 33298 Zoom.prototype.isBeyondPossibleRight = function (x, maxX) { 33299 return x <= maxX; 33300 }; 33301 Zoom.prototype.isBeyondPossibleTop = function (y, minY) { 33302 return y >= minY; 33303 }; 33304 Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) { 33305 return y <= maxY; 33306 }; 33307 Zoom.prototype.isImageSlide = function () { 33308 var currentItem = this.core.galleryItems[this.core.index]; 33309 return this.core.getSlideType(currentItem) === 'image'; 33310 }; 33311 Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) { 33312 var dataScale = scale || this.scale || 1; 33313 var elDataScale = Math.abs(dataScale); 33314 var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 33315 var topBottomSpacing = Math.abs(top - bottom) / 2; 33316 var minY = (this.imageYSize - this.containerRect.height) / 2 + 33317 topBottomSpacing * this.modifierX; 33318 var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY; 33319 var minX = (this.imageXSize - this.containerRect.width) / 2; 33320 var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX; 33321 var possibleSwipeCords = { 33322 minY: minY, 33323 maxY: maxY, 33324 minX: minX, 33325 maxX: maxX, 33326 }; 33327 if (Math.abs(rotateValue) === 90) { 33328 possibleSwipeCords = { 33329 minY: minX, 33330 maxY: maxX, 33331 minX: minY, 33332 maxX: maxY, 33333 }; 33334 } 33335 return possibleSwipeCords; 33336 }; 33337 Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) { 33338 LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)'); 33339 }; 33340 Zoom.prototype.zoomSwipe = function () { 33341 var _this = this; 33342 var startCoords = {}; 33343 var endCoords = {}; 33344 var isMoved = false; 33345 // Allow x direction drag 33346 var allowX = false; 33347 // Allow Y direction drag 33348 var allowY = false; 33349 var startTime = new Date(); 33350 var endTime = new Date(); 33351 var possibleSwipeCords; 33352 var _LGel; 33353 var $item = this.core.getSlideItem(this.core.index); 33354 this.core.$inner.on('touchstart.lg', function (e) { 33355 // Allow zoom only on image 33356 if (!_this.isImageSlide()) { 33357 return; 33358 } 33359 $item = _this.core.getSlideItem(_this.core.index); 33360 if ((_this.$LG(e.target).hasClass('lg-item') || 33361 $item.get().contains(e.target)) && 33362 e.targetTouches.length === 1 && 33363 _this.core.outer.hasClass('lg-zoomed')) { 33364 e.preventDefault(); 33365 startTime = new Date(); 33366 _this.core.touchAction = 'zoomSwipe'; 33367 _LGel = _this.core 33368 .getSlideItem(_this.core.index) 33369 .find('.lg-img-wrap') 33370 .first(); 33371 var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue)); 33372 allowY = dragAllowedAxises.allowY; 33373 allowX = dragAllowedAxises.allowX; 33374 if (allowX || allowY) { 33375 startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue)); 33376 } 33377 possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue); 33378 // reset opacity and transition duration 33379 _this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition'); 33380 } 33381 }); 33382 this.core.$inner.on('touchmove.lg', function (e) { 33383 if (e.targetTouches.length === 1 && 33384 _this.core.touchAction === 'zoomSwipe' && 33385 (_this.$LG(e.target).hasClass('lg-item') || 33386 $item.get().contains(e.target))) { 33387 e.preventDefault(); 33388 _this.core.touchAction = 'zoomSwipe'; 33389 endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue)); 33390 var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords); 33391 if (Math.abs(endCoords.x - startCoords.x) > 15 || 33392 Math.abs(endCoords.y - startCoords.y) > 15) { 33393 isMoved = true; 33394 _this.setZoomSwipeStyles(_LGel, distance); 33395 } 33396 } 33397 }); 33398 this.core.$inner.on('touchend.lg', function (e) { 33399 if (_this.core.touchAction === 'zoomSwipe' && 33400 (_this.$LG(e.target).hasClass('lg-item') || 33401 $item.get().contains(e.target))) { 33402 _this.core.touchAction = undefined; 33403 _this.core.outer.removeClass('lg-zoom-dragging'); 33404 if (!isMoved) { 33405 return; 33406 } 33407 isMoved = false;
33408 endTime = new Date(); 33409 var touchDuration = endTime.valueOf() - startTime.valueOf(); 33410 _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue); 33411 } 33412 }); 33413 }; 33414 Zoom.prototype.zoomDrag = function () { 33415 var _this = this; 33416 var startCoords = {}; 33417 var endCoords = {}; 33418 var isDragging = false; 33419 var isMoved = false; 33420 // Allow x direction drag 33421 var allowX = false; 33422 // Allow Y direction drag 33423 var allowY = false; 33424 var startTime; 33425 var endTime; 33426 var possibleSwipeCords; 33427 var _LGel; 33428 this.core.outer.on('mousedown.lg.zoom', function (e) { 33429 // Allow zoom only on image 33430 if (!_this.isImageSlide()) { 33431 return; 33432 } 33433 var $item = _this.core.getSlideItem(_this.core.index); 33434 if (_this.$LG(e.target).hasClass('lg-item') || 33435 $item.get().contains(e.target)) { 33436 startTime = new Date(); 33437 _LGel = _this.core 33438 .getSlideItem(_this.core.index) 33439 .find('.lg-img-wrap') 33440 .first(); 33441 var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue)); 33442 allowY = dragAllowedAxises.allowY; 33443 allowX = dragAllowedAxises.allowX; 33444 if (_this.core.outer.hasClass('lg-zoomed')) { 33445 if (_this.$LG(e.target).hasClass('lg-object') && 33446 (allowX || allowY)) { 33447 e.preventDefault(); 33448 startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 33449 possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue); 33450 isDragging = true; 33451 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 33452 _this.core.outer.get().scrollLeft += 1; 33453 _this.core.outer.get().scrollLeft -= 1; 33454 _this.core.outer 33455 .removeClass('lg-grab') 33456 .addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging'); 33457 // reset opacity and transition duration 33458 } 33459 } 33460 } 33461 }); 33462 this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) { 33463 if (isDragging) { 33464 isMoved = true; 33465 endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 33466 var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords); 33467 _this.setZoomSwipeStyles(_LGel, distance); 33468 } 33469 }); 33470 this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) { 33471 if (isDragging) { 33472 endTime = new Date(); 33473 isDragging = false; 33474 _this.core.outer.removeClass('lg-zoom-dragging'); 33475 // Fix for chrome mouse move on click 33476 if (isMoved && 33477 (startCoords.x !== endCoords.x || 33478 startCoords.y !== endCoords.y)) { 33479 endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 33480 var touchDuration = endTime.valueOf() - startTime.valueOf(); 33481 _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue); 33482 } 33483 isMoved = false; 33484 } 33485 _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab'); 33486 }); 33487 }; 33488 Zoom.prototype.closeGallery = function () { 33489 this.resetZoom(); 33490 }; 33491 Zoom.prototype.destroy = function () { 33492 // Unbind all events added by lightGallery zoom plugin 33493 this.$LG(window).off(".lg.zoom.global" + this.core.lgId); 33494 this.core.LGel.off('.lg.zoom'); 33495 this.core.LGel.off('.zoom'); 33496 clearTimeout(this.zoomableTimeout); 33497 this.zoomableTimeout = false; 33498 }; 33499 return Zoom; 33500 }()); 33501 33502 return Zoom; 33503 33504}))); 33505/*! 33506 * lightgallery | 2.5.0 | June 13th 2022 33507 * http://www.lightgalleryjs.com/ 33508 * Copyright (c) 2020 Sachin Neravath; 33509 * @license GPLv3 33510 */ 33511 33512(function (global, factory) { 33513 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 33514 typeof define === 'function' && define.amd ? define(factory) : 33515 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory()); 33516}(this, (function () { 'use strict'; 33517 33518 /*! ***************************************************************************** 33519 Copyright (c) Microsoft Corporation. 33520 33521 Permission to use, copy, modify, and/or distribute this software for any 33522 purpose with or without fee is hereby granted. 33523 33524 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 33525 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 33526 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 33527 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 33528 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 33529 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 33530 PERFORMANCE OF THIS SOFTWARE. 33531 ***************************************************************************** */ 33532 33533 var __assign = function() { 33534 __assign = Object.assign || function __assign(t) { 33535 for (var s, i = 1, n = arguments.length; i < n; i++) { 33536 s = arguments[i]; 33537 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 33538 } 33539 return t; 33540 }; 33541 return __assign.apply(this, arguments); 33542 }; 33543 33544 var fullscreenSettings = { 33545 fullScreen: true, 33546 fullscreenPluginStrings: { 33547 toggleFullscreen: 'Toggle Fullscreen', 33548 }, 33549 }; 33550 33551 var FullScreen = /** @class */ (function () { 33552 function FullScreen(instance, $LG) { 33553 // get lightGallery core plugin instance 33554 this.core = instance;
33555 this.$LG = $LG; 33556 // extend module default settings with lightGallery core settings 33557 this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings); 33558 return this; 33559 } 33560 FullScreen.prototype.init = function () { 33561 var fullScreen = ''; 33562 if (this.settings.fullScreen) { 33563 // check for fullscreen browser support 33564 if (!document.fullscreenEnabled && 33565 !document.webkitFullscreenEnabled && 33566 !document.mozFullScreenEnabled && 33567 !document.msFullscreenEnabled) { 33568 return; 33569 } 33570 else { 33571 fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>"; 33572 this.core.$toolbar.append(fullScreen); 33573 this.fullScreen(); 33574 } 33575 } 33576 }; 33577 FullScreen.prototype.isFullScreen = function () { 33578 return (document.fullscreenElement || 33579 document.mozFullScreenElement || 33580 document.webkitFullscreenElement || 33581 document.msFullscreenElement); 33582 }; 33583 FullScreen.prototype.requestFullscreen = function () { 33584 var el = document.documentElement; 33585 if (el.requestFullscreen) { 33586 el.requestFullscreen(); 33587 } 33588 else if (el.msRequestFullscreen) { 33589 el.msRequestFullscreen(); 33590 } 33591 else if (el.mozRequestFullScreen) { 33592 el.mozRequestFullScreen(); 33593 } 33594 else if (el.webkitRequestFullscreen) { 33595 el.webkitRequestFullscreen(); 33596 } 33597 }; 33598 FullScreen.prototype.exitFullscreen = function () { 33599 if (document.exitFullscreen) { 33600 document.exitFullscreen(); 33601 } 33602 else if (document.msExitFullscreen) { 33603 document.msExitFullscreen(); 33604 } 33605 else if (document.mozCancelFullScreen) { 33606 document.mozCancelFullScreen(); 33607 } 33608 else if (document.webkitExitFullscreen) { 33609 document.webkitExitFullscreen(); 33610 } 33611 }; 33612 // https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode 33613 FullScreen.prototype.fullScreen = function () { 33614 var _this = this; 33615 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 () { 33616 if (!_this.core.lgOpened) 33617 return; 33618 _this.core.outer.toggleClass('lg-fullscreen-on'); 33619 }); 33620 this.core.outer 33621 .find('.lg-fullscreen') 33622 .first() 33623 .on('click.lg', function () { 33624 if (_this.isFullScreen()) { 33625 _this.exitFullscreen(); 33626 } 33627 else { 33628 _this.requestFullscreen(); 33629 } 33630 }); 33631 }; 33632 FullScreen.prototype.closeGallery = function () { 33633 // exit from fullscreen if activated 33634 if (this.isFullScreen()) { 33635 this.exitFullscreen(); 33636 } 33637 }; 33638 FullScreen.prototype.destroy = function () { 33639 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); 33640 }; 33641 return FullScreen; 33642 }()); 33643 33644 return FullScreen; 33645 33646}))); 33647 33648/*! 33649 * lightgallery | 2.5.0 | June 13th 2022 33650 * http://www.lightgalleryjs.com/ 33651 * Copyright (c) 2020 Sachin Neravath; 33652 * @license GPLv3 33653 */ 33654 33655(function (global, factory) { 33656 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 33657 typeof define === 'function' && define.amd ? define(factory) : 33658 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory()); 33659}(this, (function () { 'use strict'; 33660 33661 /*! ***************************************************************************** 33662 Copyright (c) Microsoft Corporation. 33663 33664 Permission to use, copy, modify, and/or distribute this software for any 33665 purpose with or without fee is hereby granted. 33666 33667 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 33668 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 33669 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 33670 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 33671 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 33672 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 33673 PERFORMANCE OF THIS SOFTWARE. 33674 ***************************************************************************** */ 33675 33676 var __assign = function() { 33677 __assign = Object.assign || function __assign(t) { 33678 for (var s, i = 1, n = arguments.length; i < n; i++) { 33679 s = arguments[i]; 33680 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 33681 } 33682 return t; 33683 }; 33684 return __assign.apply(this, arguments); 33685 }; 33686 33687 /** 33688 * List of lightGallery events 33689 * All events should be documented here 33690 * Below interfaces are used to build the website documentations 33691 * */ 33692 var lGEvents = { 33693 afterAppendSlide: 'lgAfterAppendSlide', 33694 init: 'lgInit', 33695 hasVideo: 'lgHasVideo', 33696 containerResize: 'lgContainerResize', 33697 updateSlides: 'lgUpdateSlides', 33698 afterAppendSubHtml: 'lgAfterAppendSubHtml', 33699 beforeOpen: 'lgBeforeOpen', 33700 afterOpen: 'lgAfterOpen', 33701 slideItemLoad: 'lgSlideItemLoad', 33702 beforeSlide: 'lgBeforeSlide', 33703 afterSlide: 'lgAfterSlide', 33704 posterClick: 'lgPosterClick', 33705 dragStart: 'lgDragStart', 33706 dragMove: 'lgDragMove', 33707 dragEnd: 'lgDragEnd', 33708 beforeNextSlide: 'lgBeforeNextSlide', 33709 beforePrevSlide: 'lgBeforePrevSlide', 33710 beforeClose: 'lgBeforeClose', 33711 afterClose: 'lgAfterClose', 33712 rotateLeft: 'lgRotateLeft', 33713 rotateRight: 'lgRotateRight', 33714 flipHorizontal: 'lgFlipHorizontal', 33715 flipVertical: 'lgFlipVertical', 33716 autoplay: 'lgAutoplay', 33717 autoplayStart: 'lgAutoplayStart', 33718 autoplayStop: 'lgAutoplayStop', 33719 }; 33720 33721 var hashSettings = { 33722 hash: true, 33723 galleryId: '1', 33724 customSlideName: false, 33725 }; 33726 33727 var Hash = /** @class */ (function () { 33728 function Hash(instance, $LG) { 33729 // get lightGallery core plugin instance 33730 this.core = instance;
33731 this.$LG = $LG; 33732 // extend module default settings with lightGallery core settings 33733 this.settings = __assign(__assign({}, hashSettings), this.core.settings); 33734 return this; 33735 } 33736 Hash.prototype.init = function () { 33737 var _this = this; 33738 if (!this.settings.hash) { 33739 return; 33740 } 33741 this.oldHash = window.location.hash; 33742 setTimeout(function () { 33743 _this.buildFromHash(); 33744 }, 100); 33745 // Change hash value on after each slide transition 33746 this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this)); 33747 this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this)); 33748 // Listen hash change and change the slide according to slide value 33749 this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this)); 33750 }; 33751 Hash.prototype.onAfterSlide = function (event) { 33752 var slideName = this.core.galleryItems[event.detail.index].slideName; 33753 slideName = this.settings.customSlideName 33754 ? slideName || event.detail.index 33755 : event.detail.index; 33756 if (history.replaceState) { 33757 history.replaceState(null, '', window.location.pathname + 33758 window.location.search + 33759 '#lg=' + 33760 this.settings.galleryId + 33761 '&slide=' + 33762 slideName); 33763 } 33764 else { 33765 window.location.hash = 33766 'lg=' + this.settings.galleryId + '&slide=' + slideName; 33767 } 33768 }; 33769 /** 33770 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin 33771 * @param {String} hash 33772 * @returns {Number} Index of the slide. 33773 */ 33774 Hash.prototype.getIndexFromUrl = function (hash) { 33775 if (hash === void 0) { hash = window.location.hash; } 33776 var slideName = hash.split('&slide=')[1]; 33777 var _idx = 0; 33778 if (this.settings.customSlideName) { 33779 for (var index = 0; index < this.core.galleryItems.length; index++) { 33780 var dynamicEl = this.core.galleryItems[index]; 33781 if (dynamicEl.slideName === slideName) { 33782 _idx = index; 33783 break; 33784 } 33785 } 33786 } 33787 else { 33788 _idx = parseInt(slideName, 10); 33789 } 33790 return isNaN(_idx) ? 0 : _idx; 33791 }; 33792 // Build Gallery if gallery id exist in the URL 33793 Hash.prototype.buildFromHash = function () { 33794 // if dynamic option is enabled execute immediately 33795 var _hash = window.location.hash; 33796 //Uncode edit ##START## 33797 // if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) { 33798 if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) { 33799 //Uncode edit ##END## 33800 // This class is used to remove the initial animation if galleryId present in the URL 33801 this.$LG(document.body).addClass('lg-from-hash'); 33802 var index = this.getIndexFromUrl(_hash); 33803 this.core.openGallery(index); 33804 return true; 33805 } 33806 }; 33807 Hash.prototype.onCloseAfter = function () { 33808 // Reset to old hash value 33809 if (this.oldHash && 33810 this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) { 33811 if (history.replaceState) { 33812 history.replaceState(null, '', this.oldHash); 33813 } 33814 else { 33815 window.location.hash = this.oldHash; 33816 } 33817 } 33818 else { 33819 if (history.replaceState) { 33820 history.replaceState(null, document.title, window.location.pathname + window.location.search); 33821 } 33822 else { 33823 window.location.hash = ''; 33824 } 33825 } 33826 }; 33827 Hash.prototype.onHashchange = function () { 33828 if (!this.core.lgOpened) 33829 return; 33830 var _hash = window.location.hash; 33831 var index = this.getIndexFromUrl(_hash); 33832 // it galleryId doesn't exist in the url close the gallery 33833 if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) { 33834 this.core.slide(index, false, false); 33835 } 33836 else if (this.core.lGalleryOn) { 33837 this.core.closeGallery(); 33838 } 33839 }; 33840 Hash.prototype.closeGallery = function () { 33841 if (this.settings.hash) { 33842 this.$LG(document.body).removeClass('lg-from-hash'); 33843 } 33844 }; 33845 Hash.prototype.destroy = function () { 33846 this.core.LGel.off('.lg.hash'); 33847 this.core.LGel.off('.hash'); 33848 this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId); 33849 }; 33850 return Hash; 33851 }()); 33852 33853 return Hash; 33854 33855}))); 33856/*! 33857 * lightgallery | 2.5.0 | June 13th 2022 33858 * http://www.lightgalleryjs.com/ 33859 * Copyright (c) 2020 Sachin Neravath; 33860 * @license GPLv3 33861 */ 33862 33863(function (global, factory) { 33864 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 33865 typeof define === 'function' && define.amd ? define(factory) : 33866 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory()); 33867}(this, (function () { 'use strict'; 33868 33869 /*! ***************************************************************************** 33870 Copyright (c) Microsoft Corporation. 33871 33872 Permission to use, copy, modify, and/or distribute this software for any 33873 purpose with or without fee is hereby granted. 33874 33875 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 33876 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 33877 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 33878 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 33879 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 33880 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 33881 PERFORMANCE OF THIS SOFTWARE. 33882 ***************************************************************************** */ 33883 33884 var __assign = function() { 33885 __assign = Object.assign || function __assign(t) { 33886 for (var s, i = 1, n = arguments.length; i < n; i++) { 33887 s = arguments[i]; 33888 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 33889 } 33890 return t; 33891 }; 33892 return __assign.apply(this, arguments); 33893 }; 33894 33895 function __spreadArrays() { 33896 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 33897 for (var r = Array(s), k = 0, i = 0; i < il; i++) 33898 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 33899 r[k] = a[j]; 33900 return r; 33901 } 33902 33903 var shareSettings = { 33904 share: true, 33905 facebook: true, 33906 facebookDropdownText: 'Facebook', 33907 twitter: true, 33908 twitterDropdownText: 'Twitter', 33909 pinterest: true, 33910 pinterestDropdownText: 'Pinterest', 33911 additionalShareOptions: [], 33912 sharePluginStrings: { share: 'Share' }, 33913 }; 33914 33915 function getFacebookShareLink(galleryItem) { 33916 var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u='; 33917 return (facebookBaseUrl + 33918 encodeURIComponent(galleryItem.facebookShareUrl || window.location.href)); 33919 } 33920 33921 function getTwitterShareLink(galleryItem) { 33922 var twitterBaseUrl = '//twitter.com/intent/tweet?text='; 33923 var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href); 33924 var text = galleryItem.tweetText;
33925 return twitterBaseUrl + text + '&url=' + url; 33926 } 33927 33928 function getPinterestShareLink(galleryItem) { 33929 var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url='; 33930 var description = galleryItem.pinterestText; 33931 var media = encodeURIComponent(galleryItem.src); 33932 var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href); 33933 return (pinterestBaseUrl + 33934 url + 33935 '&media=' + 33936 media + 33937 '&description=' + 33938 description); 33939 } 33940 33941 /** 33942 * List of lightGallery events 33943 * All events should be documented here 33944 * Below interfaces are used to build the website documentations 33945 * */ 33946 var lGEvents = { 33947 afterAppendSlide: 'lgAfterAppendSlide', 33948 init: 'lgInit', 33949 hasVideo: 'lgHasVideo', 33950 containerResize: 'lgContainerResize', 33951 updateSlides: 'lgUpdateSlides', 33952 afterAppendSubHtml: 'lgAfterAppendSubHtml', 33953 beforeOpen: 'lgBeforeOpen', 33954 afterOpen: 'lgAfterOpen', 33955 slideItemLoad: 'lgSlideItemLoad', 33956 beforeSlide: 'lgBeforeSlide', 33957 afterSlide: 'lgAfterSlide', 33958 posterClick: 'lgPosterClick', 33959 dragStart: 'lgDragStart', 33960 dragMove: 'lgDragMove', 33961 dragEnd: 'lgDragEnd', 33962 beforeNextSlide: 'lgBeforeNextSlide', 33963 beforePrevSlide: 'lgBeforePrevSlide', 33964 beforeClose: 'lgBeforeClose', 33965 afterClose: 'lgAfterClose', 33966 rotateLeft: 'lgRotateLeft', 33967 rotateRight: 'lgRotateRight', 33968 flipHorizontal: 'lgFlipHorizontal', 33969 flipVertical: 'lgFlipVertical', 33970 autoplay: 'lgAutoplay', 33971 autoplayStart: 'lgAutoplayStart', 33972 autoplayStop: 'lgAutoplayStop', 33973 }; 33974 33975 var Share = /** @class */ (function () { 33976 function Share(instance) { 33977 this.shareOptions = []; 33978 // get lightGallery core plugin instance 33979 this.core = instance; 33980 // extend module default settings with lightGallery core settings 33981 this.settings = __assign(__assign({}, shareSettings), this.core.settings); 33982 return this; 33983 } 33984 Share.prototype.init = function () { 33985 if (!this.settings.share) { 33986 return; 33987 } 33988 this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions); 33989 this.setLgShareMarkup(); 33990 this.core.outer 33991 .find('.lg-share .lg-dropdown') 33992 .append(this.getShareListHtml()); 33993 this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this)); 33994 }; 33995 Share.prototype.getShareListHtml = function () { 33996 var shareHtml = ''; 33997 this.shareOptions.forEach(function (shareOption) { 33998 shareHtml += shareOption.dropdownHTML; 33999 }); 34000 return shareHtml; 34001 }; 34002 Share.prototype.setLgShareMarkup = function () { 34003 var _this = this; 34004 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>"); 34005 this.core.outer.append('<div class="lg-dropdown-overlay"></div>'); 34006 var $shareButton = this.core.outer.find('.lg-share'); 34007 $shareButton.first().on('click.lg', function () { 34008 _this.core.outer.toggleClass('lg-dropdown-active'); 34009 if (_this.core.outer.hasClass('lg-dropdown-active')) { 34010 _this.core.outer.attr('aria-expanded', true); 34011 } 34012 else { 34013 _this.core.outer.attr('aria-expanded', false); 34014 } 34015 }); 34016 this.core.outer 34017 .find('.lg-dropdown-overlay') 34018 .first() 34019 .on('click.lg', function () { 34020 _this.core.outer.removeClass('lg-dropdown-active'); 34021 _this.core.outer.attr('aria-expanded', false); 34022 }); 34023 }; 34024 Share.prototype.onAfterSlide = function (event) { 34025 var _this = this; 34026 var index = event.detail.index; 34027 var currentItem = this.core.galleryItems[index]; 34028 setTimeout(function () { 34029 _this.shareOptions.forEach(function (shareOption) { 34030 var selector = shareOption.selector; 34031 _this.core.outer 34032 .find(selector) 34033 .attr('href', shareOption.generateLink(currentItem)); 34034 }); 34035 }, 100); 34036 }; 34037 Share.prototype.getShareListItemHTML = function (type, text) { 34038 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>"; 34039 }; 34040 Share.prototype.getDefaultShareOptions = function () { 34041 return __spreadArrays((this.settings.facebook 34042 ? [ 34043 { 34044 type: 'facebook', 34045 generateLink: getFacebookShareLink,
34046 dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText), 34047 selector: '.lg-share-facebook', 34048 }, 34049 ] 34050 : []), (this.settings.twitter 34051 ? [ 34052 { 34053 type: 'twitter', 34054 generateLink: getTwitterShareLink, 34055 dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText), 34056 selector: '.lg-share-twitter', 34057 }, 34058 ] 34059 : []), (this.settings.pinterest 34060 ? [ 34061 { 34062 type: 'pinterest', 34063 generateLink: getPinterestShareLink, 34064 dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText), 34065 selector: '.lg-share-pinterest', 34066 }, 34067 ] 34068 : [])); 34069 }; 34070 Share.prototype.destroy = function () { 34071 this.core.outer.find('.lg-dropdown-overlay').remove(); 34072 this.core.outer.find('.lg-share').remove(); 34073 this.core.LGel.off('.lg.share'); 34074 this.core.LGel.off('.share'); 34075 }; 34076 return Share; 34077 }()); 34078 34079 return Share; 34080 34081}))); 34082/*! 34083 * lightgallery | 2.5.0 | June 13th 2022 34084 * http://www.lightgalleryjs.com/ 34085 * Copyright (c) 2020 Sachin Neravath; 34086 * @license GPLv3 34087 */ 34088 34089(function (global, factory) { 34090 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 34091 typeof define === 'function' && define.amd ? define(factory) : 34092 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory()); 34093}(this, (function () { 'use strict'; 34094 34095 /*! ***************************************************************************** 34096 Copyright (c) Microsoft Corporation. 34097 34098 Permission to use, copy, modify, and/or distribute this software for any 34099 purpose with or without fee is hereby granted. 34100 34101 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 34102 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 34103 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 34104 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 34105 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 34106 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 34107 PERFORMANCE OF THIS SOFTWARE. 34108 ***************************************************************************** */ 34109 34110 var __assign = function() { 34111 __assign = Object.assign || function __assign(t) { 34112 for (var s, i = 1, n = arguments.length; i < n; i++) { 34113 s = arguments[i]; 34114 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 34115 } 34116 return t; 34117 }; 34118 return __assign.apply(this, arguments); 34119 }; 34120 34121 var thumbnailsSettings = { 34122 thumbnail: true, 34123 animateThumb: true, 34124 currentPagerPosition: 'middle', 34125 alignThumbnails: 'middle', 34126 thumbWidth: 100, 34127 thumbHeight: '80px', 34128 thumbMargin: 5, 34129 appendThumbnailsTo: '.lg-components', 34130 toggleThumb: false, 34131 enableThumbDrag: true, 34132 enableThumbSwipe: true, 34133 thumbnailSwipeThreshold: 10, 34134 loadYouTubeThumbnail: true, 34135 youTubeThumbSize: 1, 34136 thumbnailPluginStrings: { 34137 toggleThumbnails: 'Toggle thumbnails', 34138 }, 34139 }; 34140 34141 /** 34142 * List of lightGallery events 34143 * All events should be documented here 34144 * Below interfaces are used to build the website documentations 34145 * */ 34146 var lGEvents = { 34147 afterAppendSlide: 'lgAfterAppendSlide', 34148 init: 'lgInit', 34149 hasVideo: 'lgHasVideo', 34150 containerResize: 'lgContainerResize', 34151 updateSlides: 'lgUpdateSlides', 34152 afterAppendSubHtml: 'lgAfterAppendSubHtml', 34153 beforeOpen: 'lgBeforeOpen', 34154 afterOpen: 'lgAfterOpen', 34155 slideItemLoad: 'lgSlideItemLoad', 34156 beforeSlide: 'lgBeforeSlide', 34157 afterSlide: 'lgAfterSlide', 34158 posterClick: 'lgPosterClick', 34159 dragStart: 'lgDragStart', 34160 dragMove: 'lgDragMove', 34161 dragEnd: 'lgDragEnd', 34162 beforeNextSlide: 'lgBeforeNextSlide', 34163 beforePrevSlide: 'lgBeforePrevSlide', 34164 beforeClose: 'lgBeforeClose', 34165 afterClose: 'lgAfterClose', 34166 rotateLeft: 'lgRotateLeft', 34167 rotateRight: 'lgRotateRight', 34168 flipHorizontal: 'lgFlipHorizontal', 34169 flipVertical: 'lgFlipVertical', 34170 autoplay: 'lgAutoplay', 34171 autoplayStart: 'lgAutoplayStart', 34172 autoplayStop: 'lgAutoplayStop', 34173 }; 34174 34175 var Thumbnail = /** @class */ (function () { 34176 function Thumbnail(instance, $LG) { 34177 this.thumbOuterWidth = 0; 34178 this.thumbTotalWidth = 0; 34179 this.translateX = 0; 34180 this.thumbClickable = false;
34181 // get lightGallery core plugin instance 34182 this.core = instance; 34183 this.$LG = $LG; 34184 return this; 34185 } 34186 Thumbnail.prototype.init = function () { 34187 // extend module default settings with lightGallery core settings 34188 this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings); 34189 this.thumbOuterWidth = 0; 34190 this.thumbTotalWidth = 34191 this.core.galleryItems.length * 34192 (this.settings.thumbWidth + this.settings.thumbMargin); 34193 // Thumbnail animation value 34194 this.translateX = 0; 34195 this.setAnimateThumbStyles(); 34196 if (!this.core.settings.allowMediaOverlap) { 34197 this.settings.toggleThumb = false; 34198 } 34199 if (this.settings.thumbnail) { 34200 this.build(); 34201 if (this.settings.animateThumb) { 34202 if (this.settings.enableThumbDrag) { 34203 this.enableThumbDrag(); 34204 } 34205 if (this.settings.enableThumbSwipe) { 34206 this.enableThumbSwipe(); 34207 } 34208 this.thumbClickable = false; 34209 } 34210 else { 34211 this.thumbClickable = true; 34212 } 34213 this.toggleThumbBar(); 34214 this.thumbKeyPress(); 34215 } 34216 }; 34217 Thumbnail.prototype.build = function () { 34218 var _this = this; 34219 this.setThumbMarkup(); 34220 this.manageActiveClassOnSlideChange(); 34221 this.$lgThumb.first().on('click.lg touchend.lg', function (e) { 34222 var $target = _this.$LG(e.target); 34223 if (!$target.hasAttribute('data-lg-item-id')) { 34224 return; 34225 } 34226 setTimeout(function () { 34227 // In IE9 and bellow touch does not support 34228 // Go to slide if browser does not support css transitions 34229 if (_this.thumbClickable && !_this.core.lgBusy) { 34230 var index = parseInt($target.attr('data-lg-item-id')); 34231 _this.core.slide(index, false, true, false); 34232 } 34233 }, 50); 34234 }); 34235 //Uncode edit ##START## 34236 // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) { 34237 this.core.LGel.on(lGEvents.beforeSlide, function (event) { 34238 //Uncode edit ##END## 34239 var index = event.detail.index; 34240 _this.animateThumb(index); 34241 }); 34242 //Uncode edit ##START## 34243 // this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () { 34244 this.core.LGel.on(lGEvents.beforeOpen, function () { 34245 //Uncode edit ##END## 34246 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 34247 }); 34248 //Uncode edit ##START## 34249 // this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () { 34250 this.core.LGel.on(lGEvents.updateSlides, function () { 34251 //Uncode edit ##END## 34252 _this.rebuildThumbnails(); 34253 }); 34254 //Uncode edit ##START## 34255 // this.core.LGel.on(lGEvents.containerResize + ".thumb", function () { 34256 this.core.LGel.on(lGEvents.containerResize, function () { 34257 //Uncode edit ##END## 34258 if (!_this.core.lgOpened) 34259 return; 34260 setTimeout(function () { 34261 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 34262 _this.animateThumb(_this.core.index); 34263 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 34264 }, 50); 34265 }); 34266 }; 34267 Thumbnail.prototype.setThumbMarkup = function () { 34268 var thumbOuterClassNames = 'lg-thumb-outer '; 34269 if (this.settings.alignThumbnails) { 34270 thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails; 34271 } 34272 var html = "<div class=\"" + thumbOuterClassNames + "\">\n <div class=\"lg-thumb lg-group\">\n </div>\n </div>"; 34273 this.core.outer.addClass('lg-has-thumb'); 34274 if (this.settings.appendThumbnailsTo === '.lg-components') { 34275 this.core.$lgComponents.append(html); 34276 } 34277 else { 34278 this.core.outer.append(html); 34279 } 34280 this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first(); 34281 this.$lgThumb = this.core.outer.find('.lg-thumb').first(); 34282 if (this.settings.animateThumb) { 34283 this.core.outer 34284 .find('.lg-thumb') 34285 .css('transition-duration', this.core.settings.speed + 'ms') 34286 .css('width', this.thumbTotalWidth + 'px') 34287 .css('position', 'relative'); 34288 } 34289 this.setThumbItemHtml(this.core.galleryItems); 34290 }; 34291 Thumbnail.prototype.enableThumbDrag = function () { 34292 var _this = this; 34293 var thumbDragUtils = { 34294 cords: { 34295 startX: 0, 34296 endX: 0, 34297 }, 34298 isMoved: false, 34299 newTranslateX: 0, 34300 startTime: new Date(), 34301 endTime: new Date(), 34302 touchMoveTime: 0, 34303 }; 34304 var isDragging = false;
34305 this.$thumbOuter.addClass('lg-grab'); 34306 this.core.outer 34307 .find('.lg-thumb') 34308 .first() 34309 .on('mousedown.lg.thumb', function (e) { 34310 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 34311 // execute only on .lg-object 34312 e.preventDefault(); 34313 thumbDragUtils.cords.startX = e.pageX; 34314 thumbDragUtils.startTime = new Date(); 34315 _this.thumbClickable = false; 34316 isDragging = true; 34317 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 34318 _this.core.outer.get().scrollLeft += 1; 34319 _this.core.outer.get().scrollLeft -= 1; 34320 // * 34321 _this.$thumbOuter 34322 .removeClass('lg-grab') 34323 .addClass('lg-grabbing'); 34324 } 34325 }); 34326 this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) { 34327 if (!_this.core.lgOpened) 34328 return; 34329 if (isDragging) { 34330 thumbDragUtils.cords.endX = e.pageX; 34331 thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils); 34332 } 34333 }); 34334 this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () { 34335 if (!_this.core.lgOpened) 34336 return; 34337 if (thumbDragUtils.isMoved) { 34338 thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils); 34339 } 34340 else { 34341 _this.thumbClickable = true; 34342 } 34343 if (isDragging) { 34344 isDragging = false; 34345 _this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab'); 34346 } 34347 }); 34348 }; 34349 Thumbnail.prototype.enableThumbSwipe = function () { 34350 var _this = this; 34351 var thumbDragUtils = { 34352 cords: { 34353 startX: 0, 34354 endX: 0, 34355 }, 34356 isMoved: false, 34357 newTranslateX: 0, 34358 startTime: new Date(), 34359 endTime: new Date(), 34360 touchMoveTime: 0, 34361 }; 34362 this.$lgThumb.on('touchstart.lg', function (e) { 34363 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 34364 e.preventDefault(); 34365 thumbDragUtils.cords.startX = e.targetTouches[0].pageX; 34366 _this.thumbClickable = false; 34367 thumbDragUtils.startTime = new Date(); 34368 } 34369 }); 34370 this.$lgThumb.on('touchmove.lg', function (e) { 34371 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 34372 e.preventDefault(); 34373 thumbDragUtils.cords.endX = e.targetTouches[0].pageX; 34374 thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils); 34375 } 34376 }); 34377 this.$lgThumb.on('touchend.lg', function () { 34378 if (thumbDragUtils.isMoved) { 34379 thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils); 34380 } 34381 else { 34382 _this.thumbClickable = true; 34383 } 34384 }); 34385 }; 34386 // Rebuild thumbnails 34387 Thumbnail.prototype.rebuildThumbnails = function () { 34388 var _this = this; 34389 // Remove transitions 34390 this.$thumbOuter.addClass('lg-rebuilding-thumbnails'); 34391 setTimeout(function () { 34392 _this.thumbTotalWidth = 34393 _this.core.galleryItems.length * 34394 (_this.settings.thumbWidth + _this.settings.thumbMargin); 34395 _this.$lgThumb.css('width', _this.thumbTotalWidth + 'px'); 34396 _this.$lgThumb.empty(); 34397 _this.setThumbItemHtml(_this.core.galleryItems); 34398 _this.animateThumb(_this.core.index); 34399 }, 50); 34400 setTimeout(function () { 34401 _this.$thumbOuter.removeClass('lg-rebuilding-thumbnails'); 34402 }, 200); 34403 }; 34404 // @ts-check 34405 Thumbnail.prototype.setTranslate = function (value) { 34406 this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)'); 34407 }; 34408 Thumbnail.prototype.getPossibleTransformX = function (left) { 34409 if (left > this.thumbTotalWidth - this.thumbOuterWidth) { 34410 left = this.thumbTotalWidth - this.thumbOuterWidth; 34411 } 34412 if (left < 0) { 34413 left = 0; 34414 } 34415 return left; 34416 }; 34417 Thumbnail.prototype.animateThumb = function (index) { 34418 this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms'); 34419 if (this.settings.animateThumb) { 34420 var position = 0; 34421 switch (this.settings.currentPagerPosition) { 34422 case 'left': 34423 position = 0; 34424 break; 34425 case 'middle': 34426 position = 34427 this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2; 34428 break; 34429 case 'right': 34430 position = this.thumbOuterWidth - this.settings.thumbWidth; 34431 } 34432 this.translateX = 34433 (this.settings.thumbWidth + this.settings.thumbMargin) * index - 34434 1 - 34435 position; 34436 if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) { 34437 this.translateX = this.thumbTotalWidth - this.thumbOuterWidth; 34438 } 34439 if (this.translateX < 0) { 34440 this.translateX = 0; 34441 } 34442 this.setTranslate(this.translateX); 34443 } 34444 };
34445 Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) { 34446 thumbDragUtils.newTranslateX = this.translateX; 34447 thumbDragUtils.isMoved = true; 34448 thumbDragUtils.touchMoveTime = new Date().valueOf(); 34449 thumbDragUtils.newTranslateX -= 34450 thumbDragUtils.cords.endX - thumbDragUtils.cords.startX; 34451 thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX); 34452 // move current slide 34453 this.setTranslate(thumbDragUtils.newTranslateX); 34454 this.$thumbOuter.addClass('lg-dragging'); 34455 return thumbDragUtils; 34456 }; 34457 Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) { 34458 thumbDragUtils.isMoved = false; 34459 thumbDragUtils.endTime = new Date(); 34460 this.$thumbOuter.removeClass('lg-dragging'); 34461 var touchDuration = thumbDragUtils.endTime.valueOf() - 34462 thumbDragUtils.startTime.valueOf(); 34463 var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX; 34464 var speedX = Math.abs(distanceXnew) / touchDuration; 34465 // Some magical numbers 34466 // Can be improved 34467 if (speedX > 0.15 && 34468 thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) { 34469 speedX += 1; 34470 if (speedX > 2) { 34471 speedX += 1; 34472 } 34473 speedX = 34474 speedX + 34475 speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth); 34476 this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings'); 34477 distanceXnew = distanceXnew * speedX; 34478 this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew); 34479 this.setTranslate(this.translateX); 34480 } 34481 else { 34482 this.translateX = thumbDragUtils.newTranslateX; 34483 } 34484 if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) < 34485 this.settings.thumbnailSwipeThreshold) { 34486 this.thumbClickable = true; 34487 } 34488 return thumbDragUtils; 34489 }; 34490 Thumbnail.prototype.getThumbHtml = function (thumb, index, alt) { 34491 var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 34492 var thumbImg, 34493 altTh = this.core.galleryItems[index].subHtml, 34494 altApp = ''; 34495 if (slideVideoInfo.youtube) { 34496 if (this.settings.loadYouTubeThumbnail) { 34497 thumbImg = 34498 '//img.youtube.com/vi/' + 34499 slideVideoInfo.youtube[1] + 34500 '/' + 34501 this.settings.youTubeThumbSize + 34502 '.jpg'; 34503 } 34504 else { 34505 thumbImg = thumb; 34506 } 34507 } 34508 else { 34509 thumbImg = thumb; 34510 } 34511 34512 if ( altTh ) { 34513 altTh = altTh.replace(/<\/?[^>]+(>|$)/g, ""); 34514 altApp = 'alt=\"' + altTh + ' \" '; 34515 } else if ( typeof alt !== 'undefined' ) { 34516 altApp = 'alt=\"' + alt + ' \" '; 34517 } 34518 34519 if ( thumbImg ) { 34520 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>"; 34521 } else { 34522 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>"; 34523 } 34524 }; 34525 Thumbnail.prototype.getThumbItemHtml = function (items) { 34526 var thumbList = ''; 34527 for (var i = 0; i < items.length; i++) { 34528 thumbList += this.getThumbHtml(items[i].thumb, i, items[i].alt); 34529 } 34530 return thumbList; 34531 }; 34532 Thumbnail.prototype.setThumbItemHtml = function (items) { 34533 var thumbList = this.getThumbItemHtml(items); 34534 this.$lgThumb.html(thumbList); 34535 }; 34536 Thumbnail.prototype.setAnimateThumbStyles = function () { 34537 if (this.settings.animateThumb) { 34538 this.core.outer.addClass('lg-animate-thumb'); 34539 } 34540 }; 34541 // Manage thumbnail active calss
34542 Thumbnail.prototype.manageActiveClassOnSlideChange = function () { 34543 var _this = this; 34544 // manage active class for thumbnail 34545 //Uncode edit ##START## 34546 // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) { 34547 this.core.LGel.on(lGEvents.beforeSlide, function (event) { 34548 //Uncode edit ##END## 34549 var $thumb = _this.core.outer.find('.lg-thumb-item'); 34550 var index = event.detail.index; 34551 $thumb.removeClass('active'); 34552 $thumb.eq(index).addClass('active'); 34553 }); 34554 }; 34555 // Toggle thumbnail bar 34556 Thumbnail.prototype.toggleThumbBar = function () { 34557 var _this = this; 34558 if (this.settings.toggleThumb) { 34559 this.core.outer.addClass('lg-can-toggle'); 34560 this.core.$toolbar.append('<button type="button" aria-label="' + 34561 this.settings.thumbnailPluginStrings['toggleThumbnails'] + 34562 '" class="lg-toggle-thumb lg-icon"></button>'); 34563 this.core.outer 34564 .find('.lg-toggle-thumb') 34565 .first() 34566 .on('click.lg', function () { 34567 _this.core.outer.toggleClass('lg-components-open'); 34568 }); 34569 } 34570 }; 34571 Thumbnail.prototype.thumbKeyPress = function () { 34572 var _this = this; 34573 this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) { 34574 if (!_this.core.lgOpened || !_this.settings.toggleThumb) 34575 return; 34576 if (e.keyCode === 38) { 34577 e.preventDefault(); 34578 _this.core.outer.addClass('lg-components-open'); 34579 } 34580 else if (e.keyCode === 40) { 34581 e.preventDefault(); 34582 _this.core.outer.removeClass('lg-components-open'); 34583 } 34584 }); 34585 }; 34586 Thumbnail.prototype.destroy = function () { 34587 if (this.settings.thumbnail) { 34588 this.$LG(window).off(".lg.thumb.global" + this.core.lgId); 34589 this.core.LGel.off('.lg.thumb'); 34590 this.core.LGel.off('.thumb'); 34591 this.$thumbOuter.remove(); 34592 this.core.outer.removeClass('lg-has-thumb'); 34593 } 34594 }; 34595 return Thumbnail; 34596 }()); 34597 34598 return Thumbnail; 34599 34600}))); 34601/*! 34602 * lightgallery | 2.5.0 | June 13th 2022 34603 * http://www.lightgalleryjs.com/ 34604 * Copyright (c) 2020 Sachin Neravath; 34605 * @license GPLv3 34606 */ 34607 34608(function (global, factory) { 34609 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 34610 typeof define === 'function' && define.amd ? define(factory) : 34611 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory()); 34612}(this, (function () { 'use strict'; 34613 34614 /*! ***************************************************************************** 34615 Copyright (c) Microsoft Corporation. 34616 34617 Permission to use, copy, modify, and/or distribute this software for any 34618 purpose with or without fee is hereby granted. 34619 34620 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 34621 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 34622 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 34623 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 34624 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 34625 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 34626 PERFORMANCE OF THIS SOFTWARE. 34627 ***************************************************************************** */ 34628 34629 var __assign = function() { 34630 __assign = Object.assign || function __assign(t) { 34631 for (var s, i = 1, n = arguments.length; i < n; i++) { 34632 s = arguments[i]; 34633 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 34634 } 34635 return t; 34636 }; 34637 return __assign.apply(this, arguments); 34638 }; 34639 34640 var videoSettings = { 34641 autoplayFirstVideo: true, 34642 youTubePlayerParams: false, 34643 vimeoPlayerParams: false, 34644 wistiaPlayerParams: false, 34645 gotoNextSlideOnVideoEnd: true, 34646 autoplayVideoOnSlide: false, 34647 videojs: false, 34648 videojsTheme: '', 34649 videojsOptions: {}, 34650 }; 34651 34652 /** 34653 * List of lightGallery events 34654 * All events should be documented here 34655 * Below interfaces are used to build the website documentations 34656 * */ 34657 var lGEvents = { 34658 afterAppendSlide: 'lgAfterAppendSlide', 34659 init: 'lgInit', 34660 hasVideo: 'lgHasVideo', 34661 containerResize: 'lgContainerResize', 34662 updateSlides: 'lgUpdateSlides', 34663 afterAppendSubHtml: 'lgAfterAppendSubHtml', 34664 beforeOpen: 'lgBeforeOpen', 34665 afterOpen: 'lgAfterOpen', 34666 slideItemLoad: 'lgSlideItemLoad', 34667 beforeSlide: 'lgBeforeSlide', 34668 afterSlide: 'lgAfterSlide', 34669 posterClick: 'lgPosterClick', 34670 dragStart: 'lgDragStart', 34671 dragMove: 'lgDragMove', 34672 dragEnd: 'lgDragEnd', 34673 beforeNextSlide: 'lgBeforeNextSlide', 34674 beforePrevSlide: 'lgBeforePrevSlide', 34675 beforeClose: 'lgBeforeClose', 34676 afterClose: 'lgAfterClose', 34677 rotateLeft: 'lgRotateLeft', 34678 rotateRight: 'lgRotateRight', 34679 flipHorizontal: 'lgFlipHorizontal', 34680 flipVertical: 'lgFlipVertical', 34681 autoplay: 'lgAutoplay', 34682 autoplayStart: 'lgAutoplayStart', 34683 autoplayStop: 'lgAutoplayStop', 34684 }; 34685 34686 var param = function (obj) { 34687 return Object.keys(obj) 34688 .map(function (k) { 34689 return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]); 34690 }) 34691 .join('&'); 34692 }; 34693 var getVimeoURLParams = function (defaultParams, videoInfo) { 34694 if (!videoInfo || !videoInfo.vimeo) 34695 return '';
34696 var urlParams = videoInfo.vimeo[2] || ''; 34697 var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0 34698 ? '&' + param(defaultParams) 34699 : ''; 34700 // Support private video 34701 var urlWithHash = videoInfo.vimeo[0].split('/').pop() || ''; 34702 var urlWithHashWithParams = urlWithHash.split('?')[0] || ''; 34703 var hash = urlWithHashWithParams.split('#')[0]; 34704 var isPrivate = videoInfo.vimeo[1] !== hash; 34705 if (isPrivate) { 34706 urlParams = urlParams.replace("/" + hash, ''); 34707 } 34708 urlParams = 34709 urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || ''; 34710 // For vimeo last params gets priority if duplicates found 34711 // Uncode edit ##START## 34712 var vimeoPlayerParams = '?autoplay=0'; 34713 if ( videoInfo.autoplay !== '' ) { 34714 vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' ); 34715 vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' ); 34716 } else { 34717 if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) { 34718 vimeoPlayerParams = SiteParameters.vimeoPlayerParams; 34719 } 34720 } 34721 if ( videoInfo.muted !== '' ) { 34722 vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes'); 34723 } else { 34724 if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) { 34725 vimeoPlayerParams += '&muted=1'; 34726 } 34727 } 34728 // var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams; 34729 vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams; 34730 // Uncode edit ##END## 34731 return vimeoPlayerParams; 34732 }; 34733 34734 /** 34735 * Video module for lightGallery 34736 * Supports HTML5, YouTube, Vimeo, wistia videos 34737 * 34738 * 34739 * @ref Wistia 34740 * https://wistia.com/support/integrations/wordpress(How to get url) 34741 * https://wistia.com/support/developers/embed-options#using-embed-options 34742 * https://wistia.com/support/developers/player-api 34743 * https://wistia.com/support/developers/construct-an-embed-code 34744 * http://jsfiddle.net/xvnm7xLm/ 34745 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video 34746 * https://wistia.com/support/embed-and-share/sharing-videos 34747 * https://private-sharing.wistia.com/medias/mwhrulrucj 34748 * 34749 * @ref Youtube 34750 * https://developers.google.com/youtube/player_parameters#enablejsapi 34751 * https://developers.google.com/youtube/iframe_api_reference 34752 * https://developer.chrome.com/blog/autoplay/#iframe-delegation 34753 * 34754 * @ref Vimeo 34755 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url 34756 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode 34757 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters 34758 */ 34759 var Video = /** @class */ (function () { 34760 function Video(instance) { 34761 // get lightGallery core plugin instance 34762 this.core = instance; 34763 this.settings = __assign(__assign({}, videoSettings), this.core.settings); 34764 return this; 34765 } 34766 Video.prototype.init = function () { 34767 var _this = this; 34768 /** 34769 * Event triggered when video url found without poster 34770 * Append video HTML 34771 * Play if autoplayFirstVideo is true 34772 */ 34773 this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this)); 34774 this.core.LGel.on(lGEvents.posterClick + ".video", function () { 34775 var $el = _this.core.getSlideItem(_this.core.index); 34776 _this.loadVideoOnPosterClick($el); 34777 }); 34778 this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this)); 34779 // @desc fired immediately before each slide transition. 34780 this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this)); 34781 // @desc fired immediately after each slide transition. 34782 this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this)); 34783 }; 34784 /** 34785 * @desc Event triggered when a slide is completely loaded 34786 * 34787 * @param {Event} event - lightGalley custom event 34788 */ 34789 Video.prototype.onSlideItemLoad = function (event) { 34790 var _this = this; 34791 var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index; 34792 // Should check the active slide as well as user may have moved to different slide before the first slide is loaded 34793 if (this.settings.autoplayFirstVideo && 34794 isFirstSlide && 34795 index === this.core.index) { 34796 // Delay is just for the transition effect on video load 34797 setTimeout(function () { 34798 _this.loadAndPlayVideo(index); 34799 }, 200); 34800 } 34801 // Should not call on first slide. should check only if the slide is active 34802 if (!isFirstSlide && 34803 this.settings.autoplayVideoOnSlide && 34804 index === this.core.index) { 34805 setTimeout(function () { 34806 _this.loadAndPlayVideo(index); 34807 }, 500); 34808 } 34809 }; 34810 /** 34811 * @desc Event triggered when video url or poster found 34812 * Append video HTML is poster is not given 34813 * Play if autoplayFirstVideo is true 34814 * 34815 * @param {Event} event - Javascript Event object. 34816 */ 34817 Video.prototype.onHasVideo = function (event) { 34818 var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster; 34819 if (!hasPoster) { 34820 // All functions are called separately if poster exist in loadVideoOnPosterClick function 34821 this.appendVideos(this.core.getSlideItem(index), { 34822 src: src, 34823 addClass: 'lg-object', 34824 index: index, 34825 html5Video: html5Video, 34826 // Uncode edit ##START## 34827 autoplay: event.target.getAttribute('data-lb-autoplay'), 34828 muted: event.target.getAttribute('data-lb-muted'), 34829 // Uncode edit ##END## 34830 }); 34831 // Automatically navigate to next slide once video reaches the end. 34832 this.gotoNextSlideOnVideoEnd(src, index); 34833 } 34834 }; 34835 /** 34836 * @desc fired immediately before each slide transition. 34837 * Pause the previous video 34838 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos. 34839 * 34840 * @param {Event} event - Javascript Event object. 34841 * @param {number} prevIndex - Previous index of the slide. 34842 * @param {number} index - Current index of the slide 34843 */ 34844 Video.prototype.onBeforeSlide = function (event) { 34845 if (this.core.lGalleryOn) { 34846 var prevIndex = event.detail.prevIndex; 34847 this.pauseVideo(prevIndex); 34848 } 34849 // Uncode edit ##START## 34850 var _a = event.detail, index = _a.index; 34851 var $slide = this.core.getSlideItem(index); 34852
34853 var iframe = $slide.selector.querySelector('iframe'); 34854 if ( iframe != null ) { 34855 34856 var data_play = iframe.getAttribute('data-autoplay'); 34857 if ( typeof data_play !== 'undefined' && data_play === '1' ) { 34858 this.loadAndPlayVideo(index); 34859 34860 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}, 34861 $videoElement = this.core.getSlideItem(index).find('.lg-video-object').first(); 34862 if (videoInfo.vimeo) { 34863 var vimeoPlayer = new Vimeo.Player($videoElement.get()); 34864 vimeoPlayer.on('play', function () { 34865 vimeoPlayer.setCurrentTime(0); 34866 }); 34867 } else if ( videoInfo.youtube ) { 34868 try { 34869 $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*'); 34870 } 34871 catch (e) { 34872 console.warn(e); 34873 } 34874 } 34875 } 34876 } 34877 // Uncode edit ##END## 34878 }; 34879 /** 34880 * @desc fired immediately after each slide transition. 34881 * Play video if autoplayVideoOnSlide option is enabled. 34882 * 34883 * @param {Event} event - Javascript Event object. 34884 * @param {number} prevIndex - Previous index of the slide. 34885 * @param {number} index - Current index of the slide 34886 * @todo should check on onSlideLoad as well if video is not loaded on after slide 34887 */ 34888 Video.prototype.onAfterSlide = function (event) { 34889 var _this = this; 34890 var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex; 34891 // Do not call on first slide 34892 var $slide = this.core.getSlideItem(index); 34893 if (this.settings.autoplayVideoOnSlide && index !== prevIndex) { 34894 if ($slide.hasClass('lg-complete')) { 34895 setTimeout(function () { 34896 _this.loadAndPlayVideo(index); 34897 }, 100); 34898 } 34899 } 34900 }; 34901 Video.prototype.loadAndPlayVideo = function (index) { 34902 var $slide = this.core.getSlideItem(index); 34903 var currentGalleryItem = this.core.galleryItems[index]; 34904 if (currentGalleryItem.poster) { 34905 this.loadVideoOnPosterClick($slide, true); 34906 } 34907 else { 34908 //Uncode edit ##START## 34909 // this.playVideo(index); 34910 var iframe = $slide.selector.querySelector('iframe'); 34911 if ( iframe != null ) { 34912 var data_play = iframe.getAttribute('data-autoplay'); 34913 if ( typeof data_play !== 'undefined' ) { 34914 if ( data_play === '1' && this.core.index == index ) { 34915 this.playVideo(index); 34916 } else { 34917 this.pauseVideo(index); 34918 } 34919 } 34920 } 34921 //Uncode edit ##END## 34922 } 34923 }; 34924 /** 34925 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide. 34926 * @param {number} index - Index of the slide 34927 */ 34928 Video.prototype.playVideo = function (index) { 34929 this.controlVideo(index, 'play'); 34930 }; 34931 /** 34932 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide. 34933 * @param {number} index - Index of the slide 34934 */ 34935 Video.prototype.pauseVideo = function (index) { 34936 this.controlVideo(index, 'pause'); 34937 }; 34938 // Uncode edit ##START## 34939 //Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) { 34940 Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) { 34941 // Uncode edit ##END## 34942 var video = ''; 34943 var videoInfo = this.core.galleryItems[index] 34944 .__slideVideoInfo || {}; 34945 var currentGalleryItem = this.core.galleryItems[index]; 34946 var videoTitle = currentGalleryItem.title || currentGalleryItem.alt; 34947 videoTitle = videoTitle ? 'title="' + videoTitle + '"' : ''; 34948 var commonIframeProps = "allowtransparency=\"true\"\n frameborder=\"0\"\n scrolling=\"no\"\n allowfullscreen\n mozallowfullscreen\n webkitallowfullscreen\n oallowfullscreen\n msallowfullscreen"; 34949 if (videoInfo.youtube) { 34950 var videoId = 'lg-youtube' + index; 34951 var slideUrlParams = videoInfo.youtube[2] 34952 ? videoInfo.youtube[2] + '&' 34953 : ''; 34954 // For youtube first parms gets priority if duplicates found 34955 // Uncode edit ##START## 34956 // var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1"; 34957 var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1"; 34958 if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) { 34959 youTubePlayerParams += '&autoplay=0'; 34960 } 34961 if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) { 34962 youTubePlayerParams += '&mute=1'; 34963 } 34964 var data_video = ''; 34965 if ( autoplay !== '' ) { 34966 //youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' ); 34967 youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' ); 34968 youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' ); 34969 data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"'; 34970 } 34971 // if ( muted !== '' ) { 34972 // youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' ); 34973 // } 34974 youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' ); 34975 34976 youTubePlayerParams = youTubePlayerParams.replace('??', '?'); 34977 // Uncode edit ##END## 34978 var playerParams = youTubePlayerParams + 34979 (this.settings.youTubePlayerParams 34980 ? '&' + param(this.settings.youTubePlayerParams) 34981 : ''); 34982 // Uncode edit ##START## 34983 // 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>"; 34984 var nocookie = typeof SiteParameters.uncode_nocookie !== 'undefined' ? SiteParameters.uncode_nocookie : ''; 34985 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>"; 34986 var tag = document.createElement('script'); 34987 tag.src = "//www.youtube.com/player_api"; 34988 var firstScriptTag = document.getElementsByTagName('script')[0]; 34989 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 34990 34991 // Replace the 'ytplayer' element with an <iframe> and 34992 // YouTube player after the API code downloads. 34993 var ytIframeplayer, 34994 setMute = muted === 'yes' ? 0 : 100; 34995 window.onYouTubePlayerAPIReady = function() { 34996 ytIframeplayer = new YT.Player(videoId, { 34997 videoId: videoInfo.youtube[1], 34998 events: { 34999 'onReady': function (event) { 35000 event.target.setVolume(setMute); 35001 } 35002 } 35003 }); 35004 } 35005 // Uncode edit ##END## 35006 } 35007 else if (videoInfo.vimeo) { 35008 var videoId = 'lg-vimeo' + index; 35009 // Uncode edit ##START## 35010 videoInfo.autoplay = autoplay; 35011 videoInfo.muted = muted; 35012 // Uncode edit ##END## 35013 var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo); 35014 // Uncode edit ##START## 35015 // 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>"; 35016 var data_video = ''; 35017 if ( autoplay !== '' ) { 35018 data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"'; 35019 } 35020 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>"; 35021 // Uncode edit ##END## 35022 } 35023 else if (videoInfo.wistia) { 35024 var wistiaId = 'lg-wistia' + index; 35025 var playerParams = param(this.settings.wistiaPlayerParams); 35026 playerParams = playerParams ? '?' + playerParams : ''; 35027 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>"; 35028 } 35029 else if (videoInfo.html5) { 35030 var html5VideoMarkup = ''; 35031 for (var i = 0; i < html5Video.source.length; i++) { 35032 html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">"; 35033 } 35034 if (html5Video.tracks) { 35035 var _loop_1 = function (i) { 35036 var trackAttributes = ''; 35037 var track = html5Video.tracks[i]; 35038 Object.keys(track || {}
35038).forEach(function (key) { 35039 trackAttributes += key + "=\"" + track[key] + "\" "; 35040 }); 35041 html5VideoMarkup += "<track " + trackAttributes + ">"; 35042 }; 35043 for (var i = 0; i < html5Video.tracks.length; i++) { 35044 _loop_1(i); 35045 } 35046 } 35047 var html5VideoAttrs_1 = ''; 35048 var videoAttributes_1 = html5Video.attributes || {}; 35049 Object.keys(videoAttributes_1 || {}).forEach(function (key) { 35050 html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" "; 35051 }); 35052 video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme 35053 ? this.settings.videojsTheme + ' ' 35054 : '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n " + html5VideoMarkup + "\n Your browser does not support HTML5 video.\n </video>"; 35055 } 35056 return video; 35057 }; 35058 /** 35059 * @desc - Append videos to the slide 35060 * 35061 * @param {HTMLElement} el - slide element 35062 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo 35063 */ 35064 Video.prototype.appendVideos = function (el, videoParams) { 35065 var _a; 35066 // Uncode edit ##START## 35067 // var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video); 35068 var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted); 35069 // Uncode edit ##END## 35070 el.find('.lg-video-cont').append(videoHtml); 35071 var $videoElement = el.find('.lg-video-object').first(); 35072 if (videoParams.html5Video) { 35073 $videoElement.on('mousedown.lg.video', function (e) { 35074 e.stopPropagation(); 35075 }); 35076 } 35077 if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) { 35078 try { 35079 return videojs($videoElement.get(), this.settings.videojsOptions); 35080 } 35081 catch (e) { 35082 console.warn('lightGallery:- Make sure you have included videojs'); 35083 } 35084 } 35085 }; 35086 Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) { 35087 var _this = this; 35088 var $videoElement = this.core 35089 .getSlideItem(index) 35090 .find('.lg-video-object') 35091 .first(); 35092 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 35093 if (this.settings.gotoNextSlideOnVideoEnd) { 35094 if (videoInfo.html5) { 35095 $videoElement.on('ended', function () { 35096 _this.core.goToNextSlide(); 35097 }); 35098 } 35099 else if (videoInfo.vimeo) { 35100 try { 35101 // https://github.com/vimeo/player.js/#ended 35102 new Vimeo.Player($videoElement.get()).on('ended', function () { 35103 _this.core.goToNextSlide(); 35104 }); 35105 } 35106 catch (e) { 35107 console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js'); 35108 } 35109 } 35110 else if (videoInfo.wistia) { 35111 try { 35112 window._wq = window._wq || []; 35113 // @todo Event is gettign triggered multiple times 35114 window._wq.push({ 35115 id: $videoElement.attr('id'), 35116 onReady: function (video) { 35117 video.bind('end', function () { 35118 _this.core.goToNextSlide(); 35119 }); 35120 }, 35121 }); 35122 } 35123 catch (e) { 35124 console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js'); 35125 } 35126 } 35127 } 35128 }; 35129 Video.prototype.controlVideo = function (index, action) { 35130 var $videoElement = this.core 35131 .getSlideItem(index) 35132 .find('.lg-video-object') 35133 .first(); 35134 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 35135 if (!$videoElement.get()) 35136 return; 35137 if (videoInfo.youtube) { 35138 try { 35139 $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*'); 35140 } 35141 catch (e) { 35142 console.warn("lightGallery:- " + e); 35143 } 35144 } 35145 else if (videoInfo.vimeo) { 35146 try { 35147 new Vimeo.Player($videoElement.get())[action](); 35148 } 35149 catch (e) { 35150 console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js'); 35151 } 35152 } 35153 else if (videoInfo.html5) { 35154 if (this.settings.videojs) { 35155 try { 35156 videojs($videoElement.get())[action](); 35157 } 35158 catch (e) { 35159 console.warn('lightGallery:- Make sure you have included videojs'); 35160 } 35161 } 35162 else { 35163 $videoElement.get()[action](); 35164 } 35165 } 35166 else if (videoInfo.wistia) { 35167 try { 35168 window._wq = window._wq || []; 35169 // @todo Find a way to destroy wistia player instance 35170 window._wq.push({ 35171 id: $videoElement.attr('id'), 35172 onReady: function (video) { 35173 video[action](); 35174 }, 35175 }); 35176 } 35177 catch (e) { 35178 console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js'); 35179 } 35180 } 35181 }; 35182 Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) { 35183 var _this = this; 35184 // check slide has poster 35185 if (!$el.hasClass('lg-video-loaded')) { 35186 // check already video element present
35187 if (!$el.hasClass('lg-has-video')) { 35188 $el.addClass('lg-has-video'); 35189 var _html = void 0; 35190 var _src = this.core.galleryItems[this.core.index].src; 35191 var video = this.core.galleryItems[this.core.index].video; 35192 if (video) { 35193 _html = 35194 typeof video === 'string' ? JSON.parse(video) : video; 35195 } 35196 var videoJsPlayer_1 = this.appendVideos($el, { 35197 src: _src, 35198 addClass: '', 35199 index: this.core.index, 35200 html5Video: _html, 35201 }); 35202 this.gotoNextSlideOnVideoEnd(_src, this.core.index); 35203 var $tempImg = $el.find('.lg-object').first().get(); 35204 // @todo make sure it is working 35205 $el.find('.lg-video-cont').first().append($tempImg); 35206 $el.addClass('lg-video-loading'); 35207 videoJsPlayer_1 && 35208 videoJsPlayer_1.ready(function () { 35209 videoJsPlayer_1.on('loadedmetadata', function () { 35210 _this.onVideoLoadAfterPosterClick($el, _this.core.index); 35211 }); 35212 }); 35213 $el.find('.lg-video-object') 35214 .first() 35215 .on('load.lg error.lg loadedmetadata.lg', function () { 35216 setTimeout(function () { 35217 _this.onVideoLoadAfterPosterClick($el, _this.core.index); 35218 }, 50); 35219 }); 35220 } 35221 else { 35222 this.playVideo(this.core.index); 35223 } 35224 } 35225 else if (forcePlay) { 35226 this.playVideo(this.core.index); 35227 } 35228 }; 35229 Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) { 35230 $el.addClass('lg-video-loaded'); 35231 this.playVideo(index); 35232 }; 35233 Video.prototype.destroy = function () { 35234 this.core.LGel.off('.lg.video'); 35235 this.core.LGel.off('.video'); 35236 }; 35237 return Video; 35238 }()); 35239 35240 return Video; 35241 35242}))); 35243 35244 35245/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */ 35246!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:{}}
35246),p.exports),g=new WeakMap;function w(e,t,n){var r=g.get(e.element)||{};t in r||(r[t]=[]),r[t].push(n),g.set(e.element,r)}function b(e,t){return(g.get(e.element)||{})[t]||[]}function k(e,t,n){var r=g.get(e.element)||{};if(!r[t])return!0;if(!n)return r[t]=[],g.set(e.element,r),!0;var o=r[t].indexOf(n);return-1!==o&&r[t].splice(o,1),g.set(e.element,r),r[t]&&0===r[t].length}function E(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){return console.warn(e),{}}return e}function T(e,t,n){var r,o;e.element.contentWindow&&e.element.contentWindow.postMessage&&(r={method:t},void 0!==n&&(r.value=n),8<=(o=parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/,"$1")))&&o<10&&(r=JSON.stringify(r)),e.element.contentWindow.postMessage(r,e.origin))}function P(n,r){var t,e,o=[];(r=E(r)).event?("error"===r.event&&b(n,r.data.method).forEach(function(e){var t=new Error(r.data.message);t.name=r.data.name,e.reject(t),k(n,r.data.method,e)}),o=b(n,"event:".concat(r.event)),t=r.data):!r.method||(e=function(e,t){var n=b(e,t);if(n.length<1)return!1;var r=n.shift();return k(e,t,r),r}(n,r.method))&&(o.push(e),t=r.value),o.forEach(function(e){try{if("function"==typeof e)return void e.call(n,t);e.resolve(t)}catch(e){}})}var M=["autopause","autoplay","background","byline","color","controls","dnt","height","id","interactive_params","keyboard","loop","maxheight","maxwidth","muted","playsinline","portrait","responsive","speed","texttrack","title","transparent","url","width"];function _(r,e){var t=1<arguments.length&&void 0!==e?e:{};return M.reduce(function(e,t){var n=r.getAttribute("data-vimeo-".concat(t));return!n&&""!==n||(e[t]=""===n?1:n),e},t)}function N(e,t){var n=e.html;if(!t)throw new TypeError("An element must be provided");if(null!==t.getAttribute("data-vimeo-initialized"))return t.querySelector("iframe");var r=document.createElement("div");return r.innerHTML=n,t.appendChild(r.firstChild),t.setAttribute("data-vimeo-initialized","true"),t.querySelector("iframe")}function F(i,e,t){var a=1<arguments.length&&void 0!==e?e:{},u=2<arguments.length?t:void 0;return new Promise(function(t,n){if(!c(i))throw new TypeError("â".concat(i,"â is not a vimeo.com url."));var e="https://vimeo.com/api/oembed.json?url=".concat(encodeURIComponent(i));for(var r in a)a.hasOwnProperty(r)&&(e+="&".concat(r,"=").concat(encodeURIComponent(a[r])));var o=new("XDomainRequest"in window?XDomainRequest:XMLHttpRequest);o.open("GET",e,!0),o.onload=function(){if(404!==o.status)if(403!==o.status)try{var e=JSON.parse(o.responseText);if(403===e.domain_status_code)return N(e,u),void n(new Error("â".concat(i,"â is not embeddable.")));t(e)}catch(e){n(e)}else n(new Error("â".concat(i,"â is not embeddable.")));else n(new Error("â".concat(i,"â was not found.")))},o.onerror=function(){var e=o.status?" (".concat(o.status,")"):"";n(new Error("There was an error fetching the embed code from Vimeo".concat(e,".")))},o.send()})}var x,C,j,A=new WeakMap,S=new WeakMap,q={},Player=function(){function Player(u){var e,t,l=this,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};if(!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,Player),window.jQuery&&u instanceof jQuery&&(1<u.length&&window.console&&console.warn&&console.warn("A jQuery object with multiple elements was passed, using the first element."),u=u[0]),"undefined"!=typeof document&&"string"==typeof u&&(u=document.getElementById(u)),e=u,!Boolean(e&&1===e.nodeType&&"nodeName"in e&&e.ownerDocument&&e.ownerDocument.defaultView))throw new TypeError("You must pass either a valid element or a valid id.");if("IFRAME"===u.nodeName||(t=u.querySelector("iframe"))&&(u=t),"IFRAME"===u.nodeName&&!c(u.getAttribute("src")||""))throw new Error("The player element passed isnât a Vimeo embed.");if(A.has(u))return A.get(u);this._window=u.ownerDocument.defaultView,this.element=u,this.origin="*";var r,o=new y(function(i,a){var e;l._onMessage=function(e){if(c(e.origin)&&l.element.contentWindow===e.source){"*"===l.origin&&(l.origin=e.origin);var t=E(e.data);if(t&&"error"===t.event&&t.data&&"ready"===t.data.method){var n=new Error(t.data.message);return n.name=t.data.name,void a(n)}
vendor: 5,252 bytes, line 35246
35246var 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)}
35246},{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: 6,940 bytes, lines 35246-35573
35246))}(),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}); 35247 35248/** 35249 * Owl carousel 35250 * @version 2.0.0-beta.3 35251 * @author Bartosz Wojciechowski 35252 * @license The MIT License (MIT) 35253 * @todo Lazy Load Icon 35254 * @todo prevent animationend bubling 35255 * @todo itemsScaleUp 35256 * @todo Test Zepto 35257 * @todo stagePadding calculate wrong active classes 35258 */ 35259;(function($, window, document, undefined) { 35260 35261 /** 35262 * Creates a carousel. 35263 * @class The Owl Carousel. 35264 * @public 35265 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 35266 * @param {Object} [options] - The options 35267 */ 35268 function Owl(element, options) { 35269 35270 /** 35271 * Current settings for the carousel. 35272 * @public 35273 */ 35274 this.settings = null; 35275 35276 /** 35277 * Current options set by the caller including defaults. 35278 * @public 35279 */ 35280 this.options = $.extend({}, Owl.Defaults, options); 35281 35282 /** 35283 * Plugin element. 35284 * @public 35285 */ 35286 this.$element = $(element); 35287 35288 /** 35289 * Proxied event handlers. 35290 * @protected 35291 */ 35292 this._handlers = {}; 35293 35294 /** 35295 * References to the running plugins of this carousel. 35296 * @protected 35297 */ 35298 this._plugins = {}; 35299 35300 /** 35301 * Currently suppressed events to prevent them from beeing retriggered. 35302 * @protected 35303 */ 35304 this._supress = {}; 35305 35306 /** 35307 * Absolute current position. 35308 * @protected 35309 */ 35310 this._current = null; 35311 35312 /** 35313 * Animation speed in milliseconds. 35314 * @protected 35315 */ 35316 this._speed = null; 35317 35318 /** 35319 * Coordinates of all items in pixel. 35320 * @todo The name of this member is missleading. 35321 * @protected 35322 */ 35323 this._coordinates = []; 35324 35325 /** 35326 * Current breakpoint. 35327 * @todo Real media queries would be nice. 35328 * @protected 35329 */ 35330 this._breakpoint = null; 35331 35332 /** 35333 * Current width of the plugin element. 35334 */ 35335 this._width = null; 35336 35337 /** 35338 * All real items. 35339 * @protected 35340 */ 35341 this._items = []; 35342 35343 /** 35344 * All cloned items. 35345 * @protected 35346 */ 35347 this._clones = []; 35348 35349 /** 35350 * Merge values of all items. 35351 * @todo Maybe this could be part of a plugin. 35352 * @protected 35353 */ 35354 this._mergers = []; 35355 35356 /** 35357 * Widths of all items. 35358 */ 35359 this._widths = []; 35360 35361 /** 35362 * Invalidated parts within the update process. 35363 * @protected 35364 */ 35365 this._invalidated = {}; 35366 35367 /** 35368 * Ordered list of workers for the update process. 35369 * @protected 35370 */ 35371 this._pipe = []; 35372 35373 /** 35374 * Current state information for the drag operation. 35375 * @todo #261 35376 * @protected 35377 */ 35378 this._drag = { 35379 time: null, 35380 target: null, 35381 pointer: null, 35382 stage: { 35383 start: null, 35384 current: null 35385 }, 35386 direction: null 35387 }; 35388 35389 /** 35390 * Current state information and their tags. 35391 * @type {Object} 35392 * @protected 35393 */ 35394 this._states = { 35395 current: {}, 35396 tags: { 35397 'initializing': [ 'busy' ], 35398 'animating': [ 'busy' ], 35399 'dragging': [ 'interacting' ] 35400 } 35401 }; 35402 35403 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 35404 this._handlers[handler] = $.proxy(this[handler], this); 35405 }, this)); 35406 35407 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 35408 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 35409 = new plugin(this); 35410 }, this)); 35411 35412 $.each(Owl.Workers, $.proxy(function(priority, worker) { 35413 this._pipe.push({ 35414 'filter': worker.filter, 35415 'run': $.proxy(worker.run, this) 35416 }); 35417 }, this)); 35418 35419 this.setup(); 35420 this.initialize(); 35421 } 35422 35423 /** 35424 * Default options for the carousel. 35425 * @public 35426 */ 35427 Owl.Defaults = { 35428 items: 3, 35429 loop: false, 35430 center: false, 35431 rewind: false, 35432 35433 mouseDrag: true, 35434 touchDrag: true, 35435 pullDrag: true, 35436 freeDrag: false, 35437 35438 margin: 0, 35439 stagePadding: 0, 35440 35441 merge: false, 35442 mergeFit: true, 35443 autoWidth: false, 35444 35445 startPosition: 0, 35446 rtl: false, 35447 35448 smartSpeed: 250, 35449 fluidSpeed: false, 35450 dragEndSpeed: false, 35451 35452 responsive: {}, 35453 responsiveRefreshRate: 200, 35454 responsiveBaseElement: window, 35455 35456 fallbackEasing: 'swing', 35457 35458 info: false, 35459 35460 nestedItemSelector: false, 35461 itemSelector: false, 35462 itemElement: 'div', 35463 stageElement: 'div', 35464 35465 refreshClass: 'owl-refresh', 35466 loadedClass: 'owl-loaded', 35467 loadingClass: 'owl-loading', 35468 rtlClass: 'owl-rtl', 35469 responsiveClass: 'owl-responsive', 35470 dragClass: 'owl-drag', 35471 itemClass: 'owl-item', 35472 stageClass: 'owl-stage', 35473 stageOuterClass: 'owl-stage-outer', 35474 grabClass: 'owl-grab' 35475 }; 35476 35477 /** 35478 * Enumeration for width. 35479 * @public 35480 * @readonly 35481 * @enum {String} 35482 */ 35483 Owl.Width = { 35484 Default: 'default', 35485 Inner: 'inner', 35486 Outer: 'outer' 35487 }; 35488 35489 /** 35490 * Enumeration for types. 35491 * @public 35492 * @readonly 35493 * @enum {String} 35494 */ 35495 Owl.Type = { 35496 Event: 'event', 35497 State: 'state' 35498 }; 35499 35500 /** 35501 * Contains all registered plugins. 35502 * @public 35503 */ 35504 Owl.Plugins = {}; 35505 35506 /** 35507 * List of workers involved in the update process. 35508 */ 35509 Owl.Workers = [ { 35510 filter: [ 'width', 'settings' ], 35511 run: function() { 35512 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 35513 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 35514 } 35515 }, { 35516 filter: [ 'width', 'items', 'settings' ], 35517 run: function(cache) { 35518 cache.current = this._items && this._items[this.relative(this._current)]; 35519 } 35520 }, { 35521 filter: [ 'items', 'settings' ], 35522 run: function() { 35523 this.$stage.children('.cloned').remove(); 35524 } 35525 }, { 35526 filter: [ 'width', 'items', 'settings' ], 35527 run: function(cache) { 35528 var margin = this.settings.margin || '', 35529 grid = !this.settings.autoWidth, 35530 rtl = this.settings.rtl, 35531 css = { 35532 'width': 'auto', 35533 'margin-left': rtl ? margin : '', 35534 'margin-right': rtl ? '' : margin 35535 }; 35536 35537 !grid && this.$stage.children().css(css); 35538 35539 cache.css = css; 35540 } 35541 }, { 35542 filter: [ 'width', 'items', 'settings' ], 35543 run: function(cache) { 35544 //UNCODE edit to fix Chrome stage padding issue 35545 var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin), 35546 merge = null, 35547 iterator = this._items.length, 35548 grid = !this.settings.autoWidth, 35549 widths = []; 35550 35551 cache.items = { 35552 merge: false, 35553 width: width 35554 }; 35555 35556 while (iterator--) { 35557 merge = this._mergers[iterator]; 35558 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 35559 35560 cache.items.merge = merge > 1 || cache.items.merge; 35561 35562 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 35563 } 35564 35565 this._widths = widths; 35566 } 35567 }, { 35568 filter: [ 'items', 'settings' ], 35569 run: function() { 35570 var clones = [], 35571 items = this._items, 35572 settings = this.settings, 35573 view = Math.max(settings.items * 2, 4),
vendor: 4,968 bytes, lines 35574-35726
35574 size = Math.ceil(items.length / 2) * 2, 35575 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 35576 append = '', 35577 prepend = ''; 35578 35579 repeat /= 2; 35580 35581 while (repeat--) { 35582 clones.push(this.normalize(clones.length / 2, true)); 35583 append = append + items[clones[clones.length - 1]][0].outerHTML; 35584 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 35585 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 35586 } 35587 35588 this._clones = clones; 35589 35590 // var appendVideo = $(append).find('.uncode-video-container'); 35591 // if (appendVideo.length) { 35592 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 35593 // } 35594 // var prependVideo = $(prepend).find('.uncode-video-container'); 35595 // if (prependVideo.length) { 35596 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 35597 // } 35598 $(append).addClass('cloned').appendTo(this.$stage); 35599 $(prepend).addClass('cloned').prependTo(this.$stage); 35600 } 35601 }, { 35602 filter: [ 'width', 'items', 'settings' ], 35603 run: function() { 35604 var rtl = this.settings.rtl ? 1 : -1, 35605 size = this._clones.length + this._items.length, 35606 iterator = -1, 35607 previous = 0, 35608 current = 0, 35609 coordinates = []; 35610 35611 while (++iterator < size) { 35612 previous = coordinates[iterator - 1] || 0; 35613 current = this._widths[this.relative(iterator)] + this.settings.margin; 35614 coordinates.push(previous + current * rtl); 35615 } 35616 35617 this._coordinates = coordinates; 35618 } 35619 }, { 35620 filter: [ 'width', 'items', 'settings' ], 35621 run: function() { 35622 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 35623 padding = stagePadding, 35624 coordinates = this._coordinates, 35625 css = { 35626 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 35627 'padding-left': padding || '', 35628 'padding-right': padding || '' 35629 }; 35630 35631 this.$stage.css(css); 35632 } 35633 }, { 35634 filter: [ 'width', 'items', 'settings' ], 35635 run: function(cache) { 35636 var iterator = this._coordinates.length, 35637 grid = !this.settings.autoWidth, 35638 items = this.$stage.children(); 35639 35640 if (grid && cache.items.merge) { 35641 while (iterator--) { 35642 cache.css.width = this._widths[this.relative(iterator)]; 35643 items.eq(iterator).css(cache.css); 35644 } 35645 } else if (grid) { 35646 cache.css.width = cache.items.width; 35647 items.css(cache.css); 35648 } 35649 } 35650 }, { 35651 filter: [ 'items' ], 35652 run: function() { 35653 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 35654 } 35655 }, { 35656 filter: [ 'width', 'items', 'settings' ], 35657 run: function(cache) { 35658 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 35659 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 35660 this.reset(cache.current); 35661 } 35662 }, { 35663 filter: [ 'position' ], 35664 run: function() { 35665 this.animate(this.coordinates(this._current)); 35666 } 35667 }, { 35668 filter: [ 'width', 'position', 'items', 'settings' ], 35669 run: function() { 35670 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 35671 rtl = this.settings.rtl ? 1 : -1, 35672 padding = this.settings.stagePadding * 2, 35673 begin = this.coordinates(this.current()) + padding, 35674 end = begin + this.width() * rtl, 35675 inner, outer, matches = [], i, n; 35676 35677 for (i = 0, n = this._coordinates.length; i < n; i++) { 35678 inner = this._coordinates[i - 1] || 0; 35679 outer = Math.abs(this._coordinates[i]) + padding * rtl; 35680 35681 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 35682 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 35683 matches.push(i); 35684 } 35685 } 35686 35687 this.$stage.children('.active').removeClass('active'); 35688 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 35689 35690 if (this.settings.center) { 35691 this.$stage.children('.center').removeClass('center'); 35692 this.$stage.children().eq(this.current()).addClass('center'); 35693 } 35694 } 35695 } ]; 35696 35697 /** 35698 * Initializes the carousel. 35699 * @protected 35700 */ 35701 Owl.prototype.initialize = function() { 35702 this.enter('initializing'); 35703 this.trigger('initialize'); 35704 35705 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 35706 35707 if (this.settings.autoWidth && !this.is('pre-loading')) { 35708 var imgs, nestedSelector, width; 35709 imgs = this.$element.find('img'); 35710 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 35711 width = this.$element.children(nestedSelector).width(); 35712 35713 if (imgs.length && width <= 0) { 35714 this.preloadAutoWidthImages(imgs); 35715 } 35716 } 35717 35718 this.$element.addClass(this.options.loadingClass); 35719 35720 // create stage 35721 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 35722 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 35723 35724 //UNCODE edit to exclude hidden items 35725 if ( this.settings.itemSelector ) { 35726 // append stage
35727 this.$element.prepend(this.$stage.parent()); 35728 // append content 35729 this.replace(this.$element.find(' > ' + this.settings.itemSelector).not(this.$stage.parent())); 35730 } else { 35731 // append stage 35732 this.$element.append(this.$stage.parent()); 35733 // append content 35734 this.replace(this.$element.children().not(this.$stage.parent())); 35735 } 35736 35737 // check visibility 35738 if (this.$element.is(':visible')) { 35739 // update view 35740 this.refresh(); 35741 } else { 35742 // invalidate width 35743 this.invalidate('width'); 35744 } 35745 35746 this.$element 35747 .removeClass(this.options.loadingClass) 35748 .addClass(this.options.loadedClass); 35749 35750 // register event handlers 35751 this.registerEventHandlers(); 35752 35753 this.leave('initializing'); 35754 this.trigger('initialized'); 35755 }; 35756 35757 /** 35758 * Setups the current settings. 35759 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 35760 * @todo Support for media queries by using `matchMedia` would be nice. 35761 * @public 35762 */ 35763 Owl.prototype.setup = function() { 35764 var viewport = this.viewport(), 35765 overwrites = this.options.responsive, 35766 match = -1, 35767 settings = null; 35768 35769 if (!overwrites) { 35770 settings = $.extend({}, this.options); 35771 } else { 35772 $.each(overwrites, function(breakpoint) { 35773 if (breakpoint <= viewport && breakpoint > match) { 35774 match = Number(breakpoint); 35775 } 35776 }); 35777 35778 settings = $.extend({}, this.options, overwrites[match]); 35779 delete settings.responsive; 35780 35781 // responsive class 35782 if (settings.responsiveClass) { 35783 this.$element.attr('class', 35784 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 35785 ); 35786 } 35787 } 35788 35789 if (this.settings === null || this._breakpoint !== match) { 35790 this.trigger('change', { property: { name: 'settings', value: settings } }); 35791 this._breakpoint = match; 35792 this.settings = settings; 35793 this.invalidate('settings'); 35794 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 35795 } 35796 }; 35797 35798 /** 35799 * Updates option logic if necessery. 35800 * @protected 35801 */ 35802 Owl.prototype.optionsLogic = function() { 35803 if (this.settings.autoWidth) { 35804 this.settings.stagePadding = false; 35805 this.settings.merge = false; 35806 } 35807 }; 35808 35809 /** 35810 * Prepares an item before add. 35811 * @todo Rename event parameter `content` to `item`. 35812 * @protected 35813 * @returns {jQuery|HTMLElement} - The item container. 35814 */ 35815 Owl.prototype.prepare = function(item, index) { 35816 var event = this.trigger('prepare', { content: item }); 35817 if (!event.data) { 35818 event.data = $('<' + this.settings.itemElement + '/>') 35819 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 35820 } 35821 35822 this.trigger('prepared', { content: event.data }); 35823 35824 return event.data; 35825 }; 35826 35827 /** 35828 * Updates the view. 35829 * @public 35830 */ 35831 Owl.prototype.update = function() { 35832 var i = 0, 35833 n = this._pipe.length, 35834 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 35835 cache = {}; 35836 35837 while (i < n) { 35838 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 35839 this._pipe[i].run(cache); 35840 } 35841 i++; 35842 } 35843 35844 this._invalidated = {}; 35845 35846 !this.is('valid') && this.enter('valid'); 35847 }; 35848 35849 /** 35850 * Gets the width of the view. 35851 * @public 35852 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 35853 * @returns {Number} - The width of the view in pixel. 35854 */ 35855 Owl.prototype.width = function(dimension) { 35856 dimension = dimension || Owl.Width.Default; 35857 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 35858 switch (dimension) { 35859 case Owl.Width.Inner: 35860 case Owl.Width.Outer: 35861 return this._width; 35862 default: 35863 return this._width - stagePadding * 2 + this.settings.margin; 35864 } 35865 }; 35866 35867 /** 35868 * Refreshes the carousel primarily for adaptive purposes. 35869 * @public 35870 */ 35871 Owl.prototype.refresh = function() { 35872 this.enter('refreshing'); 35873 this.trigger('refresh'); 35874 35875 this.setup(); 35876 35877 this.optionsLogic(); 35878 35879 this.$element.addClass(this.options.refreshClass); 35880 35881 this.update(); 35882 35883 this.$element.removeClass(this.options.refreshClass); 35884 35885 this.leave('refreshing'); 35886 this.trigger('refreshed'); 35887 }; 35888 35889 /** 35890 * Checks window `resize` event. 35891 * @protected 35892 */ 35893 Owl.prototype.onThrottledResize = function() { 35894 window.clearTimeout(this.resizeTimer); 35895 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 35896 }; 35897 35898 /** 35899 * Checks window `resize` event. 35900 * @protected 35901 */ 35902 Owl.prototype.onResize = function() { 35903 if (!this._items.length) { 35904 return false;
vendor: 15,850 bytes, lines 35905-36461
35905 } 35906 35907 if (this._width === this.$element.width()) { 35908 return false; 35909 } 35910 35911 if (!this.$element.is(':visible')) { 35912 return false; 35913 } 35914 35915 this.enter('resizing'); 35916 35917 if (this.trigger('resize').isDefaultPrevented()) { 35918 this.leave('resizing'); 35919 return false; 35920 } 35921 35922 this.invalidate('width'); 35923 35924 this.refresh(); 35925 35926 this.leave('resizing'); 35927 this.trigger('resized'); 35928 }; 35929 35930 /** 35931 * Registers event handlers. 35932 * @todo Check `msPointerEnabled` 35933 * @todo #261 35934 * @protected 35935 */ 35936 Owl.prototype.registerEventHandlers = function() { 35937 if ($.support.transition) { 35938 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 35939 } 35940 35941 if (this.settings.responsive !== false) { 35942 this.on(window, 'resize', this._handlers.onThrottledResize); 35943 } 35944 35945 if (this.settings.mouseDrag) { 35946 this.$element.addClass(this.options.dragClass); 35947 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 35948 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 35949 } 35950 35951 if (this.settings.touchDrag){ 35952 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 35953 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 35954 } 35955 }; 35956 35957 /** 35958 * Handles `touchstart` and `mousedown` events. 35959 * @todo Horizontal swipe threshold as option 35960 * @todo #261 35961 * @protected 35962 * @param {Event} event - The event arguments. 35963 */ 35964 Owl.prototype.onDragStart = function(event) { 35965 var stage = null; 35966 35967 if (event.which === 3) { 35968 return; 35969 } 35970 35971 if ($.support.transform) { 35972 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 35973 stage = { 35974 x: stage[stage.length === 16 ? 12 : 4], 35975 y: stage[stage.length === 16 ? 13 : 5] 35976 }; 35977 } else { 35978 stage = this.$stage.position(); 35979 stage = { 35980 x: this.settings.rtl ? 35981 stage.left + this.$stage.width() - this.width() + this.settings.margin : 35982 stage.left, 35983 y: stage.top 35984 }; 35985 } 35986 35987 if (this.is('animating')) { 35988 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 35989 this.invalidate('position'); 35990 } 35991 35992 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 35993 35994 this.speed(0); 35995 35996 this._drag.time = new Date().getTime(); 35997 this._drag.target = $(event.target); 35998 this._drag.stage.start = stage; 35999 this._drag.stage.current = stage; 36000 this._drag.pointer = this.pointer(event); 36001 36002 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 36003 36004 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 36005 var delta = this.difference(this._drag.pointer, this.pointer(event)); 36006 36007 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 36008 36009 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 36010 return; 36011 } 36012 36013 event.preventDefault(); 36014 36015 this.enter('dragging'); 36016 this.trigger('drag'); 36017 }, this)); 36018 }; 36019 36020 /** 36021 * Handles the `touchmove` and `mousemove` events. 36022 * @todo #261 36023 * @protected 36024 * @param {Event} event - The event arguments. 36025 */ 36026 Owl.prototype.onDragMove = function(event) { 36027 var minimum = null, 36028 maximum = null, 36029 pull = null, 36030 delta = this.difference(this._drag.pointer, this.pointer(event)), 36031 stage = this.difference(this._drag.stage.start, delta); 36032 36033 if (!this.is('dragging')) { 36034 return; 36035 } 36036 36037 event.preventDefault(); 36038 36039 if (this.settings.loop) { 36040 minimum = this.coordinates(this.minimum()); 36041 maximum = this.coordinates(this.maximum() + 1) - minimum; 36042 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 36043 } else { 36044 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 36045 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 36046 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 36047 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 36048 } 36049 36050 this._drag.stage.current = stage; 36051 36052 this.animate(stage.x); 36053 }; 36054 36055 /** 36056 * Handles the `touchend` and `mouseup` events. 36057 * @todo #261 36058 * @todo Threshold for click event 36059 * @protected 36060 * @param {Event} event - The event arguments. 36061 */ 36062 Owl.prototype.onDragEnd = function(event) { 36063 var delta = this.difference(this._drag.pointer, this.pointer(event)), 36064 stage = this._drag.stage.current, 36065 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 36066 36067 $(document).off('.owl.core'); 36068 36069 this.$element.removeClass(this.options.grabClass); 36070 36071 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 36072 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 36073 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 36074 this.invalidate('position'); 36075 this.update(); 36076 36077 this._drag.direction = direction; 36078 36079 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 36080 this._drag.target.one('click.owl.core', function() { return false; }); 36081 } 36082 } 36083 36084 if (!this.is('dragging')) { 36085 return; 36086 } 36087 36088 this.leave('dragging'); 36089 this.trigger('dragged'); 36090 }; 36091 36092 /** 36093 * Gets absolute position of the closest item for a coordinate. 36094 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 36095 * @protected 36096 * @param {Number} coordinate - The coordinate in pixel. 36097 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 36098 * @return {Number} - The absolute position of the closest item. 36099 */ 36100 Owl.prototype.closest = function(coordinate, direction) { 36101 var position = -1, 36102 pull = 30, 36103 width = this.width(), 36104 coordinates = this.coordinates(); 36105 36106 if (!this.settings.freeDrag) { 36107 // check closest item 36108 $.each(coordinates, $.proxy(function(index, value) { 36109 if (coordinate > value - pull && coordinate < value + pull) { 36110 position = index; 36111 } else if (this.op(coordinate, '<', value) 36112 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 36113 position = direction === 'left' ? index + 1 : index; 36114 } 36115 return position === -1; 36116 }, this)); 36117 } 36118 36119 if (!this.settings.loop) { 36120 // non loop boundries 36121 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 36122 position = coordinate = this.minimum(); 36123 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 36124 position = coordinate = this.maximum(); 36125 } 36126 } 36127 36128 return position; 36129 }; 36130 36131 /** 36132 * Animates the stage. 36133 * @todo #270 36134 * @public 36135 * @param {Number} coordinate - The coordinate in pixels. 36136 */ 36137 Owl.prototype.animate = function(coordinate) { 36138 var animate = this.speed() > 0; 36139 36140 this.is('animating') && this.onTransitionEnd(); 36141 36142 if (animate) { 36143 this.enter('animating'); 36144 this.trigger('translate'); 36145 } 36146 36147 if ($.support.transform3d && $.support.transition) { 36148 this.$stage.css({ 36149 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 36150 transition: (this.speed() / 1000) + 's' 36151 }); 36152 } else if (animate) { 36153 this.$stage.animate({ 36154 left: coordinate + 'px' 36155 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 36156 } else { 36157 this.$stage.css({ 36158 left: coordinate + 'px' 36159 }); 36160 } 36161 }; 36162 36163 /** 36164 * Checks whether the carousel is in a specific state or not. 36165 * @param {String} state - The state to check. 36166 * @returns {Boolean} - The flag which indicates if the carousel is busy. 36167 */ 36168 Owl.prototype.is = function(state) { 36169 return this._states.current[state] && this._states.current[state] > 0; 36170 }; 36171 36172 /** 36173 * Sets the absolute position of the current item. 36174 * @public 36175 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 36176 * @returns {Number} - The absolute position of the current item. 36177 */ 36178 Owl.prototype.current = function(position) { 36179 if (position === undefined) { 36180 return this._current; 36181 } 36182 36183 if (this._items.length === 0) { 36184 return undefined; 36185 } 36186 36187 position = this.normalize(position); 36188 36189 if (this._current !== position) { 36190 var event = this.trigger('change', { property: { name: 'position', value: position } }); 36191 36192 if (event.data !== undefined) { 36193 position = this.normalize(event.data); 36194 } 36195 36196 this._current = position; 36197 36198 this.invalidate('position'); 36199 36200 this.trigger('changed', { property: { name: 'position', value: this._current } }); 36201 } 36202 36203 return this._current; 36204 }; 36205 36206 /** 36207 * Invalidates the given part of the update routine. 36208 * @param {String} [part] - The part to invalidate. 36209 * @returns {Array.<String>} - The invalidated parts. 36210 */ 36211 Owl.prototype.invalidate = function(part) { 36212 if ($.type(part) === 'string') { 36213 this._invalidated[part] = true; 36214 this.is('valid') && this.leave('valid'); 36215 } 36216 return $.map(this._invalidated, function(v, i) { return i }); 36217 }; 36218 36219 /** 36220 * Resets the absolute position of the current item. 36221 * @public 36222 * @param {Number} position - The absolute position of the new item. 36223 */ 36224 Owl.prototype.reset = function(position) { 36225 position = this.normalize(position); 36226 36227 if (position === undefined) { 36228 return; 36229 } 36230 36231 this._speed = 0; 36232 this._current = position; 36233 36234 this.suppress([ 'translate', 'translated' ]); 36235 36236 this.animate(this.coordinates(position)); 36237 36238 this.release([ 'translate', 'translated' ]); 36239 }; 36240 36241 /** 36242 * Normalizes an absolute or a relative position of an item. 36243 * @public 36244 * @param {Number} position - The absolute or relative position to normalize. 36245 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 36246 * @returns {Number} - The normalized position. 36247 */ 36248 Owl.prototype.normalize = function(position, relative) { 36249 var n = this._items.length, 36250 m = relative ? 0 : this._clones.length; 36251 36252 if (!$.isNumeric(position) || n < 1) { 36253 position = undefined; 36254 } else if (position < 0 || position >= n + m) { 36255 position = ((position - m / 2) % n + n) % n + m / 2; 36256 } 36257 36258 return position; 36259 }; 36260 36261 /** 36262 * Converts an absolute position of an item into a relative one. 36263 * @public 36264 * @param {Number} position - The absolute position to convert. 36265 * @returns {Number} - The converted position. 36266 */ 36267 Owl.prototype.relative = function(position) { 36268 position -= this._clones.length / 2; 36269 return this.normalize(position, true); 36270 }; 36271 36272 /** 36273 * Gets the maximum position for the current item. 36274 * @public 36275 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 36276 * @returns {Number} 36277 */ 36278 Owl.prototype.maximum = function(relative) { 36279 var settings = this.settings, 36280 maximum = this._coordinates.length, 36281 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 36282 i = -1, j; 36283 36284 if (settings.loop) { 36285 maximum = this._clones.length / 2 + this._items.length - 1; 36286 } else if (settings.autoWidth || settings.merge) { 36287 // binary search 36288 while (maximum - i > 1) { 36289 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 36290 ? i = j : maximum = j; 36291 } 36292 } else if (settings.center) { 36293 maximum = this._items.length - 1; 36294 } else { 36295 maximum = this._items.length - settings.items; 36296 } 36297 36298 if (relative) { 36299 maximum -= this._clones.length / 2; 36300 } 36301 36302 return Math.max(maximum, 0); 36303 }; 36304 36305 /** 36306 * Gets the minimum position for the current item. 36307 * @public 36308 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 36309 * @returns {Number} 36310 */ 36311 Owl.prototype.minimum = function(relative) { 36312 return relative ? 0 : this._clones.length / 2; 36313 }; 36314 36315 /** 36316 * Gets an item at the specified relative position. 36317 * @public 36318 * @param {Number} [position] - The relative position of the item. 36319 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 36320 */ 36321 Owl.prototype.items = function(position) { 36322 if (position === undefined) { 36323 return this._items.slice(); 36324 } 36325 36326 position = this.normalize(position, true); 36327 return this._items[position]; 36328 }; 36329 36330 /** 36331 * Gets an item at the specified relative position. 36332 * @public 36333 * @param {Number} [position] - The relative position of the item. 36334 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 36335 */ 36336 Owl.prototype.mergers = function(position) { 36337 if (position === undefined) { 36338 return this._mergers.slice(); 36339 } 36340 36341 position = this.normalize(position, true); 36342 return this._mergers[position]; 36343 }; 36344 36345 /** 36346 * Gets the absolute positions of clones for an item. 36347 * @public 36348 * @param {Number} [position] - The relative position of the item. 36349 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 36350 */ 36351 Owl.prototype.clones = function(position) { 36352 var odd = this._clones.length / 2, 36353 even = odd + this._items.length, 36354 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 36355 36356 if (position === undefined) { 36357 return $.map(this._clones, function(v, i) { return map(i) }); 36358 } 36359 36360 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 36361 }; 36362 36363 /** 36364 * Sets the current animation speed. 36365 * @public 36366 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 36367 * @returns {Number} - The current animation speed in milliseconds. 36368 */ 36369 Owl.prototype.speed = function(speed) { 36370 if (speed !== undefined) { 36371 this._speed = speed; 36372 } 36373 36374 return this._speed; 36375 }; 36376 36377 /** 36378 * Gets the coordinate of an item. 36379 * @todo The name of this method is missleanding. 36380 * @public 36381 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 36382 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 36383 */ 36384 Owl.prototype.coordinates = function(position) { 36385 var coordinate = null; 36386 36387 if (position === undefined) { 36388 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 36389 return this.coordinates(index); 36390 }, this)); 36391 } 36392 36393 if (this.settings.center) { 36394 coordinate = this._coordinates[position]; 36395 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 36396 } else { 36397 coordinate = this._coordinates[position - 1] || 0; 36398 } 36399 36400 return coordinate; 36401 }; 36402 36403 /** 36404 * Calculates the speed for a translation. 36405 * @protected 36406 * @param {Number} from - The absolute position of the start item. 36407 * @param {Number} to - The absolute position of the target item. 36408 * @param {Number} [factor=undefined] - The time factor in milliseconds. 36409 * @returns {Number} - The time in milliseconds for the translation. 36410 */ 36411 Owl.prototype.duration = function(from, to, factor) { 36412 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 36413 }; 36414 36415 /** 36416 * Slides to the specified item. 36417 * @public 36418 * @param {Number} position - The position of the item. 36419 * @param {Number} [speed] - The time in milliseconds for the transition. 36420 */ 36421 Owl.prototype.to = function(position, speed) { 36422 var current = this.current(), 36423 revert = null, 36424 distance = position - this.relative(current), 36425 direction = (distance > 0) - (distance < 0), 36426 items = this._items.length, 36427 minimum = this.minimum(), 36428 maximum = this.maximum(); 36429 36430 if (this.settings.loop) { 36431 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 36432 distance += direction * -1 * items; 36433 } 36434 36435 position = current + distance; 36436 revert = ((position - minimum) % items + items) % items + minimum; 36437 36438 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 36439 current = revert - distance; 36440 position = revert; 36441 this.reset(current); 36442 } 36443 } else if (this.settings.rewind) { 36444 maximum += 1; 36445 position = (position % maximum + maximum) % maximum; 36446 } else { 36447 position = Math.max(minimum, Math.min(maximum, position)); 36448 } 36449 36450 this.speed(this.duration(current, position, speed)); 36451 this.current(position); 36452 36453 if (this.$element.is(':visible')) { 36454 this.update(); 36455 } 36456 }; 36457 36458 /** 36459 * Slides to the next item. 36460 * @public 36461 * @param {Number}
vendor: 12,284 bytes, lines 36461-36881
36461 [speed] - The time in milliseconds for the transition. 36462 */ 36463 Owl.prototype.next = function(speed) { 36464 speed = speed || false; 36465 this.to(this.relative(this.current()) + 1, speed); 36466 }; 36467 36468 /** 36469 * Slides to the previous item. 36470 * @public 36471 * @param {Number} [speed] - The time in milliseconds for the transition. 36472 */ 36473 Owl.prototype.prev = function(speed) { 36474 speed = speed || false; 36475 this.to(this.relative(this.current()) - 1, speed); 36476 }; 36477 36478 /** 36479 * Handles the end of an animation. 36480 * @protected 36481 * @param {Event} event - The event arguments. 36482 */ 36483 Owl.prototype.onTransitionEnd = function(event) { 36484 36485 // if css2 animation then event object is undefined 36486 if (event !== undefined) { 36487 event.stopPropagation(); 36488 36489 // Catch only owl-stage transitionEnd event 36490 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 36491 return false; 36492 } 36493 } 36494 36495 this.leave('animating'); 36496 this.trigger('translated'); 36497 }; 36498 36499 /** 36500 * Gets viewport width. 36501 * @protected 36502 * @return {Number} - The width in pixel. 36503 */ 36504 Owl.prototype.viewport = function() { 36505 var width; 36506 if (this.options.responsiveBaseElement !== window) { 36507 width = $(this.options.responsiveBaseElement).width(); 36508 } else if (window.innerWidth) { 36509 width = window.innerWidth; 36510 } else if (document.documentElement && document.documentElement.clientWidth) { 36511 width = document.documentElement.clientWidth; 36512 } else { 36513 throw 'Can not detect viewport width.'; 36514 } 36515 36516 return width; 36517 }; 36518 36519 /** 36520 * Replaces the current content. 36521 * @public 36522 * @param {HTMLElement|jQuery|String} content - The new content. 36523 */ 36524 Owl.prototype.replace = function(content) { 36525 this.$stage.empty(); 36526 this._items = []; 36527 36528 if (content) { 36529 content = (content instanceof jQuery) ? content : $(content); 36530 } 36531 36532 if (this.settings.nestedItemSelector) { 36533 content = content.find('.' + this.settings.nestedItemSelector); 36534 } 36535 36536 content.filter(function() { 36537 return this.nodeType === 1; 36538 }).each($.proxy(function(index, item) { 36539 item = this.prepare(item, index); 36540 this.$stage.append(item); 36541 this._items.push(item); 36542 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 36543 }, this)); 36544 36545 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 36546 36547 this.invalidate('items'); 36548 }; 36549 36550 /** 36551 * Adds an item. 36552 * @todo Use `item` instead of `content` for the event arguments. 36553 * @public 36554 * @param {HTMLElement|jQuery|String} content - The item content to add. 36555 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 36556 */ 36557 Owl.prototype.add = function(content, position) { 36558 var current = this.relative(this._current); 36559 36560 position = position === undefined ? this._items.length : this.normalize(position, true); 36561 content = content instanceof jQuery ? content : $(content); 36562 36563 this.trigger('add', { content: content, position: position }); 36564 36565 content = this.prepare(content, this._items[current].index()); 36566 36567 if (this._items.length === 0 || position === this._items.length) { 36568 this._items.length === 0 && this.$stage.append(content); 36569 this._items.length !== 0 && this._items[position - 1].after(content); 36570 this._items.push(content); 36571 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 36572 } else { 36573 this._items[position].before(content); 36574 this._items.splice(position, 0, content); 36575 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 36576 } 36577 36578 this._items[current] && this.reset(this._items[current].index()); 36579 36580 this.invalidate('items'); 36581 36582 this.trigger('added', { content: content, position: position }); 36583 }; 36584 36585 /** 36586 * Removes an item by its position. 36587 * @todo Use `item` instead of `content` for the event arguments. 36588 * @public 36589 * @param {Number} position - The relative position of the item to remove. 36590 */ 36591 Owl.prototype.remove = function(position) { 36592 position = this.normalize(position, true); 36593 36594 if (position === undefined) { 36595 return; 36596 } 36597 36598 this.trigger('remove', { content: this._items[position], position: position }); 36599 36600 this._items[position].remove(); 36601 this._items.splice(position, 1); 36602 this._mergers.splice(position, 1); 36603 36604 this.invalidate('items'); 36605 36606 this.trigger('removed', { content: null, position: position }); 36607 }; 36608 36609 /** 36610 * Preloads images with auto width. 36611 * @todo Replace by a more generic approach 36612 * @protected 36613 */ 36614 Owl.prototype.preloadAutoWidthImages = function(images) { 36615 images.each($.proxy(function(i, element) { 36616 this.enter('pre-loading'); 36617 element = $(element); 36618 $(new Image()).one('load', $.proxy(function(e) { 36619 element.attr('src', e.target.src); 36620 element.css('opacity', 1); 36621 this.leave('pre-loading'); 36622 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 36623 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 36624 }, this)); 36625 }; 36626 36627 /** 36628 * Destroys the carousel. 36629 * @public 36630 */ 36631 Owl.prototype.destroy = function() { 36632 36633 this.$element.off('.owl.core'); 36634 this.$stage.off('.owl.core'); 36635 $(document).off('.owl.core'); 36636 36637 if (this.settings.responsive !== false) { 36638 window.clearTimeout(this.resizeTimer); 36639 this.off(window, 'resize', this._handlers.onThrottledResize); 36640 } 36641 36642 for (var i in this._plugins) { 36643 this._plugins[i].destroy(); 36644 } 36645 36646 this.$stage.children('.cloned').remove(); 36647 36648 this.$stage.unwrap(); 36649 this.$stage.children().contents().unwrap(); 36650 this.$stage.children().unwrap(); 36651 36652 this.$element 36653 .removeClass(this.options.refreshClass) 36654 .removeClass(this.options.loadingClass) 36655 .removeClass(this.options.loadedClass) 36656 .removeClass(this.options.rtlClass) 36657 .removeClass(this.options.dragClass) 36658 .removeClass(this.options.grabClass) 36659 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 36660 .removeData('owl.carousel'); 36661 }; 36662 36663 /** 36664 * Operators to calculate right-to-left and left-to-right. 36665 * @protected 36666 * @param {Number} [a] - The left side operand. 36667 * @param {String} [o] - The operator. 36668 * @param {Number} [b] - The right side operand. 36669 */ 36670 Owl.prototype.op = function(a, o, b) { 36671 var rtl = this.settings.rtl; 36672 switch (o) { 36673 case '<': 36674 return rtl ? a > b : a < b; 36675 case '>': 36676 return rtl ? a < b : a > b; 36677 case '>=': 36678 return rtl ? a <= b : a >= b; 36679 case '<=': 36680 return rtl ? a >= b : a <= b; 36681 default: 36682 break; 36683 } 36684 }; 36685 36686 /** 36687 * Attaches to an internal event. 36688 * @protected 36689 * @param {HTMLElement} element - The event source. 36690 * @param {String} event - The event name. 36691 * @param {Function} listener - The event handler to attach. 36692 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 36693 */ 36694 Owl.prototype.on = function(element, event, listener, capture) { 36695 if (element.addEventListener) { 36696 element.addEventListener(event, listener, capture); 36697 } else if (element.attachEvent) { 36698 element.attachEvent('on' + event, listener); 36699 } 36700 }; 36701 36702 /** 36703 * Detaches from an internal event. 36704 * @protected 36705 * @param {HTMLElement} element - The event source. 36706 * @param {String} event - The event name. 36707 * @param {Function} listener - The attached event handler to detach. 36708 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 36709 */ 36710 Owl.prototype.off = function(element, event, listener, capture) { 36711 if (element.removeEventListener) { 36712 element.removeEventListener(event, listener, capture); 36713 } else if (element.detachEvent) { 36714 element.detachEvent('on' + event, listener); 36715 } 36716 }; 36717 36718 /** 36719 * Triggers a public event. 36720 * @todo Remove `status`, `relatedTarget` should be used instead. 36721 * @protected 36722 * @param {String} name - The event name. 36723 * @param {*} [data=null] - The event data. 36724 * @param {String} [namespace=carousel] - The event namespace. 36725 * @param {String} [state] - The state which is associated with the event. 36726 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 36727 * @returns {Event} - The event arguments. 36728 */ 36729 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 36730 var status = { 36731 item: { count: this._items.length, index: this.current() } 36732 }, handler = $.camelCase( 36733 $.grep([ 'on', name, namespace ], function(v) { return v }) 36734 .join('-').toLowerCase() 36735 ), event = $.Event( 36736 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 36737 $.extend({ relatedTarget: this }, status, data) 36738 ); 36739 36740 if (!this._supress[name]) { 36741 $.each(this._plugins, function(name, plugin) { 36742 if (plugin.onTrigger) { 36743 plugin.onTrigger(event); 36744 } 36745 }); 36746 36747 this.register({ type: Owl.Type.Event, name: name }); 36748 this.$element.trigger(event); 36749 36750 if (this.settings && typeof this.settings[handler] === 'function') { 36751 this.settings[handler].call(this, event); 36752 } 36753 } 36754 36755 return event; 36756 }; 36757 36758 /** 36759 * Enters a state. 36760 * @param name - The state name. 36761 */ 36762 Owl.prototype.enter = function(name) { 36763 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 36764 if (this._states.current[name] === undefined) { 36765 this._states.current[name] = 0; 36766 } 36767 36768 this._states.current[name]++; 36769 }, this)); 36770 }; 36771 36772 /** 36773 * Leaves a state. 36774 * @param name - The state name. 36775 */ 36776 Owl.prototype.leave = function(name) { 36777 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 36778 this._states.current[name]--; 36779 }, this)); 36780 }; 36781 36782 /** 36783 * Registers an event or state. 36784 * @public 36785 * @param {Object} object - The event or state to register. 36786 */ 36787 Owl.prototype.register = function(object) { 36788 if (object.type === Owl.Type.Event) { 36789 if (!$.event.special[object.name]) { 36790 $.event.special[object.name] = {}; 36791 } 36792 36793 if (!$.event.special[object.name].owl) { 36794 var _default = $.event.special[object.name]._default; 36795 $.event.special[object.name]._default = function(e) { 36796 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 36797 return _default.apply(this, arguments); 36798 } 36799 return e.namespace && e.namespace.indexOf('owl') > -1; 36800 }; 36801 $.event.special[object.name].owl = true; 36802 } 36803 } else if (object.type === Owl.Type.State) { 36804 if (!this._states.tags[object.name]) { 36805 this._states.tags[object.name] = object.tags; 36806 } else { 36807 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 36808 } 36809 36810 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 36811 return $.inArray(tag, this._states.tags[object.name]) === i; 36812 }, this)); 36813 } 36814 }; 36815 36816 /** 36817 * Suppresses events. 36818 * @protected 36819 * @param {Array.<String>} events - The events to suppress. 36820 */ 36821 Owl.prototype.suppress = function(events) { 36822 $.each(events, $.proxy(function(index, event) { 36823 this._supress[event] = true; 36824 }, this)); 36825 }; 36826 36827 /** 36828 * Releases suppressed events. 36829 * @protected 36830 * @param {Array.<String>} events - The events to release. 36831 */ 36832 Owl.prototype.release = function(events) { 36833 $.each(events, $.proxy(function(index, event) { 36834 delete this._supress[event]; 36835 }, this)); 36836 }; 36837 36838 /** 36839 * Gets unified pointer coordinates from event. 36840 * @todo #261 36841 * @protected 36842 * @param {Event} - The `mousedown` or `touchstart` event. 36843 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 36844 */ 36845 Owl.prototype.pointer = function(event) { 36846 var result = { x: null, y: null }; 36847 36848 event = event.originalEvent || event || window.event; 36849 36850 event = event.touches && event.touches.length ? 36851 event.touches[0] : event.changedTouches && event.changedTouches.length ? 36852 event.changedTouches[0] : event; 36853 36854 if (event.pageX) { 36855 result.x = event.pageX; 36856 result.y = event.pageY; 36857 } else { 36858 result.x = event.clientX; 36859 result.y = event.clientY; 36860 } 36861 36862 return result; 36863 }; 36864 36865 /** 36866 * Gets the difference of two vectors. 36867 * @todo #261 36868 * @protected 36869 * @param {Object} - The first vector. 36870 * @param {Object} - The second vector. 36871 * @returns {Object} - The difference. 36872 */ 36873 Owl.prototype.difference = function(first, second) { 36874 return { 36875 x: first.x - second.x, 36876 y: first.y - second.y 36877 }; 36878 }; 36879 36880 /** 36881 * The jQuery Plugin for the Owl Carousel
vendor: 32,302 bytes, lines 36882-38164
36882 * @todo Navigation plugin `next` and `prev` 36883 * @public 36884 */ 36885 $.fn.owlCarousel = function(option) { 36886 var args = Array.prototype.slice.call(arguments, 1); 36887 36888 return this.each(function() { 36889 var $this = $(this), 36890 data = $this.data('owl.carousel'); 36891 36892 if (!data) { 36893 data = new Owl(this, typeof option == 'object' && option); 36894 $this.data('owl.carousel', data); 36895 36896 $.each([ 36897 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 36898 ], function(i, event) { 36899 data.register({ type: Owl.Type.Event, name: event }); 36900 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 36901 if (e.namespace && e.relatedTarget !== this) { 36902 this.suppress([ event ]); 36903 data[event].apply(this, [].slice.call(arguments, 1)); 36904 this.release([ event ]); 36905 } 36906 }, data)); 36907 }); 36908 } 36909 36910 if (typeof option == 'string' && option.charAt(0) !== '_') { 36911 data[option].apply(data, args); 36912 } 36913 }); 36914 }; 36915 36916 /** 36917 * The constructor for the jQuery Plugin 36918 * @public 36919 */ 36920 $.fn.owlCarousel.Constructor = Owl; 36921 36922})(window.Zepto || window.jQuery, window, document); 36923 36924/** 36925 * AutoRefresh Plugin 36926 * @version 2.0.0-beta.3 36927 * @author Artus Kolanowski 36928 * @license The MIT License (MIT) 36929 */ 36930;(function($, window, document, undefined) { 36931 36932 /** 36933 * Creates the auto refresh plugin. 36934 * @class The Auto Refresh Plugin 36935 * @param {Owl} carousel - The Owl Carousel 36936 */ 36937 var AutoRefresh = function(carousel) { 36938 /** 36939 * Reference to the core. 36940 * @protected 36941 * @type {Owl} 36942 */ 36943 this._core = carousel; 36944 36945 /** 36946 * Refresh interval. 36947 * @protected 36948 * @type {number} 36949 */ 36950 this._interval = null; 36951 36952 /** 36953 * Whether the element is currently visible or not. 36954 * @protected 36955 * @type {Boolean} 36956 */ 36957 this._visible = null; 36958 36959 /** 36960 * All event handlers. 36961 * @protected 36962 * @type {Object} 36963 */ 36964 this._handlers = { 36965 'initialized.owl.carousel': $.proxy(function(e) { 36966 if (e.namespace && this._core.settings.autoRefresh) { 36967 this.watch(); 36968 } 36969 }, this) 36970 }; 36971 36972 // set default options 36973 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 36974 36975 // register event handlers 36976 this._core.$element.on(this._handlers); 36977 }; 36978 36979 /** 36980 * Default options. 36981 * @public 36982 */ 36983 AutoRefresh.Defaults = { 36984 autoRefresh: true, 36985 autoRefreshInterval: 500 36986 }; 36987 36988 /** 36989 * Watches the element. 36990 */ 36991 AutoRefresh.prototype.watch = function() { 36992 if (this._interval) { 36993 return; 36994 } 36995 36996 this._visible = this._core.$element.is(':visible'); 36997 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 36998 }; 36999 37000 /** 37001 * Refreshes the element. 37002 */ 37003 AutoRefresh.prototype.refresh = function() { 37004 if (this._core.$element.is(':visible') === this._visible || this._core.$element.closest('.drop-menu').length) { 37005 return; 37006 } 37007 37008 this._visible = !this._visible; 37009 37010 this._core.$element.toggleClass('owl-hidden', !this._visible); 37011 37012 this._visible && (this._core.invalidate('width') && this._core.refresh()); 37013 }; 37014 37015 /** 37016 * Destroys the plugin. 37017 */ 37018 AutoRefresh.prototype.destroy = function() { 37019 var handler, property; 37020 37021 window.clearInterval(this._interval); 37022 37023 for (handler in this._handlers) { 37024 this._core.$element.off(handler, this._handlers[handler]); 37025 } 37026 for (property in Object.getOwnPropertyNames(this)) { 37027 typeof this[property] != 'function' && (this[property] = null); 37028 } 37029 }; 37030 37031 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 37032 37033})(window.Zepto || window.jQuery, window, document); 37034 37035/** 37036 * Lazy Plugin 37037 * @version 2.0.0-beta.3 37038 * @author Bartosz Wojciechowski 37039 * @license The MIT License (MIT) 37040 */ 37041;(function($, window, document, undefined) { 37042 37043 /** 37044 * Creates the lazy plugin. 37045 * @class The Lazy Plugin 37046 * @param {Owl} carousel - The Owl Carousel 37047 */ 37048 var Lazy = function(carousel) { 37049 37050 /** 37051 * Reference to the core. 37052 * @protected 37053 * @type {Owl} 37054 */ 37055 this._core = carousel; 37056 37057 /** 37058 * Already loaded items. 37059 * @protected 37060 * @type {Array.<jQuery>} 37061 */ 37062 this._loaded = []; 37063 37064 /** 37065 * Event handlers. 37066 * @protected 37067 * @type {Object} 37068 */ 37069 this._handlers = { 37070 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 37071 if (!e.namespace) { 37072 return; 37073 } 37074 37075 if (!this._core.settings || !this._core.settings.lazyLoad) { 37076 return; 37077 } 37078 37079 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 37080 var settings = this._core.settings, 37081 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 37082 i = ((settings.center && n * -1) || 0), 37083 position = ((e.property && e.property.value) || this._core.current()) + i, 37084 clones = this._core.clones().length, 37085 load = $.proxy(function(i, v) { this.load(v) }, this); 37086 37087 while (i++ < n) { 37088 this.load(clones / 2 + this._core.relative(position)); 37089 clones && $.each(this._core.clones(this._core.relative(position)), load); 37090 position++; 37091 } 37092 } 37093 }, this) 37094 }; 37095 37096 // set the default options 37097 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 37098 37099 // register event handler 37100 this._core.$element.on(this._handlers); 37101 } 37102 37103 /** 37104 * Default options. 37105 * @public 37106 */ 37107 Lazy.Defaults = { 37108 lazyLoad: false 37109 } 37110 37111 /** 37112 * Loads all resources of an item at the specified position. 37113 * @param {Number} position - The absolute position of the item. 37114 * @protected 37115 */ 37116 Lazy.prototype.load = function(position) { 37117 var $item = this._core.$stage.children().eq(position), 37118 $elements = $item && $item.find('.owl-lazy'); 37119 37120 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 37121 return; 37122 } 37123 37124 $elements.each($.proxy(function(index, element) { 37125 var $element = $(element), image, 37126 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 37127 37128 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 37129 37130 if ($element.is('img')) { 37131 $element.one('load.owl.lazy', $.proxy(function() { 37132 $element.css('opacity', 1); 37133 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 37134 }, this)).attr('src', url); 37135 } else { 37136 image = new Image(); 37137 image.onload = $.proxy(function() { 37138 $element.css({ 37139 'background-image': 'url(' + url + ')', 37140 'opacity': '1' 37141 }); 37142 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 37143 }, this); 37144 image.src = url; 37145 } 37146 }, this)); 37147 37148 this._loaded.push($item.get(0)); 37149 } 37150 37151 /** 37152 * Destroys the plugin. 37153 * @public 37154 */ 37155 Lazy.prototype.destroy = function() { 37156 var handler, property; 37157 37158 for (handler in this.handlers) { 37159 this._core.$element.off(handler, this.handlers[handler]); 37160 } 37161 for (property in Object.getOwnPropertyNames(this)) { 37162 typeof this[property] != 'function' && (this[property] = null); 37163 } 37164 }; 37165 37166 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 37167 37168})(window.Zepto || window.jQuery, window, document); 37169 37170/** 37171 * AutoHeight Plugin 37172 * @version 2.0.0-beta.3 37173 * @author Bartosz Wojciechowski 37174 * @license The MIT License (MIT) 37175 */ 37176;(function($, window, document, undefined) { 37177 37178 /** 37179 * Creates the auto height plugin. 37180 * @class The Auto Height Plugin 37181 * @param {Owl} carousel - The Owl Carousel 37182 */ 37183 var AutoHeight = function(carousel) { 37184 /** 37185 * Reference to the core. 37186 * @protected 37187 * @type {Owl} 37188 */ 37189 this._core = carousel; 37190 37191 /** 37192 * All event handlers. 37193 * @protected 37194 * @type {Object} 37195 */ 37196 this._handlers = { 37197 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 37198 if (e.namespace && this._core.settings.autoHeight) { 37199 this.update(); 37200 } 37201 }, this), 37202 'changed.owl.carousel': $.proxy(function(e) { 37203 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 37204 this.update(); 37205 } 37206 }, this), 37207 'loaded.owl.lazy': $.proxy(function(e) { 37208 if (e.namespace && this._core.settings.autoHeight 37209 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 37210 this.update(); 37211 } 37212 }, this) 37213 }; 37214 37215 // set default options 37216 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 37217 37218 // register event handlers 37219 this._core.$element.on(this._handlers); 37220 }; 37221 37222 /** 37223 * Default options. 37224 * @public 37225 */ 37226 AutoHeight.Defaults = { 37227 autoHeight: false, 37228 autoHeightClass: 'owl-height' 37229 }; 37230 37231 /** 37232 * Updates the view. 37233 */ 37234 AutoHeight.prototype.update = function() { 37235 var start = this._core._current, 37236 end = start + this._core.settings.items, 37237 visible = this._core.$stage.children().toArray().slice(start, end); 37238 heights = [], 37239 maxheight = 0; 37240 37241 $.each(visible, function(index, item) { 37242 heights.push($(item).height()); 37243 }); 37244 37245 maxheight = Math.max.apply(null, heights); 37246 37247 this._core.$stage.parent() 37248 .height(maxheight) 37249 .addClass(this._core.settings.autoHeightClass); 37250 }; 37251 37252 AutoHeight.prototype.destroy = function() { 37253 var handler, property; 37254 37255 for (handler in this._handlers) { 37256 this._core.$element.off(handler, this._handlers[handler]); 37257 } 37258 for (property in Object.getOwnPropertyNames(this)) { 37259 typeof this[property] != 'function' && (this[property] = null); 37260 } 37261 }; 37262 37263 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 37264 37265})(window.Zepto || window.jQuery, window, document); 37266 37267/** 37268 * Video Plugin 37269 * @version 2.0.0-beta.3 37270 * @author Bartosz Wojciechowski 37271 * @license The MIT License (MIT) 37272 */ 37273;(function($, window, document, undefined) { 37274 37275 /** 37276 * Creates the video plugin. 37277 * @class The Video Plugin 37278 * @param {Owl} carousel - The Owl Carousel 37279 */ 37280 var Video = function(carousel) { 37281 /** 37282 * Reference to the core. 37283 * @protected 37284 * @type {Owl} 37285 */ 37286 this._core = carousel; 37287 37288 /** 37289 * Cache all video URLs. 37290 * @protected 37291 * @type {Object} 37292 */ 37293 this._videos = {}; 37294 37295 /** 37296 * Current playing item. 37297 * @protected 37298 * @type {jQuery} 37299 */ 37300 this._playing = null; 37301 37302 /** 37303 * All event handlers. 37304 * @todo The cloned content removale is too late 37305 * @protected 37306 * @type {Object} 37307 */ 37308 this._handlers = { 37309 'initialized.owl.carousel': $.proxy(function(e) { 37310 if (e.namespace) { 37311 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 37312 } 37313 }, this), 37314 'resize.owl.carousel': $.proxy(function(e) { 37315 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 37316 e.preventDefault(); 37317 } 37318 }, this), 37319 'refreshed.owl.carousel': $.proxy(function(e) { 37320 if (e.namespace && this._core.is('resizing')) { 37321 this._core.$stage.find('.cloned .owl-video-frame').remove(); 37322 } 37323 }, this), 37324 'changed.owl.carousel': $.proxy(function(e) { 37325 if (e.namespace && e.property.name === 'position' && this._playing) { 37326 this.stop(); 37327 } 37328 }, this), 37329 'prepared.owl.carousel': $.proxy(function(e) { 37330 if (!e.namespace) { 37331 return; 37332 } 37333 37334 var $element = $(e.content).find('.owl-video'); 37335 37336 if ($element.length) { 37337 $element.css('display', 'none'); 37338 this.fetch($element, $(e.content)); 37339 } 37340 }, this) 37341 }; 37342 37343 // set default options 37344 this._core.options = $.extend({}, Video.Defaults, this._core.options); 37345 37346 // register event handlers 37347 this._core.$element.on(this._handlers); 37348 37349 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 37350 this.play(e); 37351 }, this)); 37352 }; 37353 37354 /** 37355 * Default options. 37356 * @public 37357 */ 37358 Video.Defaults = { 37359 video: false, 37360 videoHeight: false, 37361 videoWidth: false 37362 }; 37363 37364 /** 37365 * Gets the video ID and the type (YouTube/Vimeo only). 37366 * @protected 37367 * @param {jQuery} target - The target containing the video data. 37368 * @param {jQuery} item - The item containing the video. 37369 */ 37370 Video.prototype.fetch = function(target, item) { 37371 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 37372 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 37373 width = target.attr('data-width') || this._core.settings.videoWidth, 37374 height = target.attr('data-height') || this._core.settings.videoHeight, 37375 url = target.attr('href'); 37376 37377 if (url) { 37378 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+)?/); 37379 37380 if (id[3].indexOf('youtu') > -1) { 37381 type = 'youtube'; 37382 } else if (id[3].indexOf('vimeo') > -1) { 37383 type = 'vimeo'; 37384 } else { 37385 throw new Error('Video URL not supported.'); 37386 } 37387 id = id[6]; 37388 } else { 37389 throw new Error('Missing video URL.'); 37390 } 37391 37392 this._videos[url] = { 37393 type: type, 37394 id: id, 37395 width: width, 37396 height: height 37397 }; 37398 37399 item.attr('data-video', url); 37400 37401 this.thumbnail(target, this._videos[url]); 37402 }; 37403 37404 /** 37405 * Creates video thumbnail. 37406 * @protected 37407 * @param {jQuery} target - The target containing the video data. 37408 * @param {Object} info - The video info object. 37409 * @see `fetch` 37410 */ 37411 Video.prototype.thumbnail = function(target, video) { 37412 var tnLink, 37413 icon, 37414 path, 37415 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 37416 customTn = target.find('img'), 37417 srcType = 'src', 37418 lazyClass = '', 37419 settings = this._core.settings, 37420 create = function(path) { 37421 icon = '<div class="owl-video-play-icon"></div>'; 37422 37423 if (settings.lazyLoad) { 37424 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 37425 } else { 37426 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 37427 } 37428 target.after(tnLink); 37429 target.after(icon); 37430 }; 37431 37432 // wrap video content into owl-video-wrapper div 37433 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 37434 37435 if (this._core.settings.lazyLoad) { 37436 srcType = 'data-src'; 37437 lazyClass = 'owl-lazy'; 37438 } 37439 37440 // custom thumbnail 37441 if (customTn.length) { 37442 create(customTn.attr(srcType)); 37443 customTn.remove(); 37444 return false; 37445 } 37446 37447 if (video.type === 'youtube') { 37448 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 37449 create(path); 37450 } else if (video.type === 'vimeo') { 37451 $.ajax({ 37452 type: 'GET', 37453 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 37454 jsonp: 'callback', 37455 dataType: 'jsonp', 37456 success: function(data) { 37457 path = data[0].thumbnail_large; 37458 create(path); 37459 } 37460 }); 37461 } 37462 }; 37463 37464 /** 37465 * Stops the current video. 37466 * @public 37467 */ 37468 Video.prototype.stop = function() { 37469 this._core.trigger('stop', null, 'video'); 37470 this._playing.find('.owl-video-frame').remove(); 37471 this._playing.removeClass('owl-video-playing'); 37472 this._playing = null; 37473 this._core.leave('playing'); 37474 this._core.trigger('stopped', null, 'video'); 37475 }; 37476 37477 /** 37478 * Starts the current video. 37479 * @public 37480 * @param {Event} event - The event arguments. 37481 */ 37482 Video.prototype.play = function(event) { 37483 var target = $(event.target), 37484 item = target.closest('.' + this._core.settings.itemClass), 37485 video = this._videos[item.attr('data-video')], 37486 width = video.width || '100%', 37487 height = video.height || this._core.$stage.height(), 37488 html; 37489 37490 if (this._playing) { 37491 return; 37492 } 37493 37494 this._core.enter('playing'); 37495 this._core.trigger('play', null, 'video'); 37496 37497 item = this._core.items(this._core.relative(item.index())); 37498 37499 this._core.reset(item.index()); 37500 37501 if (video.type === 'youtube') { 37502 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 37503 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 37504 } else if (video.type === 'vimeo') { 37505 html = '<iframe src="//player.vimeo.com/video/' + video.id + 37506 '?autoplay=1" width="' + width + '" height="' + height + 37507 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 37508 } 37509 37510 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 37511 37512 this._playing = item.addClass('owl-video-playing'); 37513 }; 37514 37515 /** 37516 * Checks whether an video is currently in full screen mode or not. 37517 * @todo Bad style because looks like a readonly method but changes members. 37518 * @protected 37519 * @returns {Boolean} 37520 */ 37521 Video.prototype.isInFullScreen = function() { 37522 var element = document.fullscreenElement || document.mozFullScreenElement || 37523 document.webkitFullscreenElement; 37524 37525 return element && $(element).parent().hasClass('owl-video-frame'); 37526 }; 37527 37528 /** 37529 * Destroys the plugin. 37530 */ 37531 Video.prototype.destroy = function() { 37532 var handler, property; 37533 37534 this._core.$element.off('click.owl.video'); 37535 37536 for (handler in this._handlers) { 37537 this._core.$element.off(handler, this._handlers[handler]); 37538 } 37539 for (property in Object.getOwnPropertyNames(this)) { 37540 typeof this[property] != 'function' && (this[property] = null); 37541 } 37542 }; 37543 37544 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 37545 37546})(window.Zepto || window.jQuery, window, document); 37547 37548/** 37549 * Animate Plugin 37550 * @version 2.0.0-beta.3 37551 * @author Bartosz Wojciechowski 37552 * @license The MIT License (MIT) 37553 */ 37554;(function($, window, document, undefined) { 37555 37556 /** 37557 * Creates the animate plugin. 37558 * @class The Navigation Plugin 37559 * @param {Owl} scope - The Owl Carousel 37560 */ 37561 var Animate = function(scope) { 37562 this.core = scope; 37563 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 37564 this.swapping = true; 37565 this.previous = undefined; 37566 this.next = undefined; 37567 37568 this.handlers = { 37569 'change.owl.carousel': $.proxy(function(e) { 37570 if (e.namespace && e.property.name == 'position') { 37571 this.previous = this.core.current(); 37572 this.next = e.property.value; 37573 } 37574 }, this), 37575 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 37576 if (e.namespace) { 37577 this.swapping = e.type == 'translated'; 37578 } 37579 }, this), 37580 'translate.owl.carousel': $.proxy(function(e) { 37581 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 37582 this.swap(); 37583 } 37584 }, this) 37585 }; 37586 37587 this.core.$element.on(this.handlers); 37588 }; 37589 37590 /** 37591 * Default options. 37592 * @public 37593 */ 37594 Animate.Defaults = { 37595 animateOut: false, 37596 animateIn: false 37597 }; 37598 37599 /** 37600 * Toggles the animation classes whenever an translations starts. 37601 * @protected 37602 * @returns {Boolean|undefined} 37603 */ 37604 Animate.prototype.swap = function() { 37605 37606 if (this.core.settings.items !== 1) { 37607 return; 37608 } 37609 37610 if (!$.support.animation || !$.support.transition) { 37611 return; 37612 } 37613 37614 this.core.speed(0); 37615 37616 var left, 37617 clear = $.proxy(this.clear, this), 37618 previous = this.core.$stage.children().eq(this.previous), 37619 next = this.core.$stage.children().eq(this.next), 37620 incoming = this.core.settings.animateIn, 37621 outgoing = this.core.settings.animateOut; 37622 37623 if (this.core.current() === this.previous) { 37624 return; 37625 } 37626 37627 if (outgoing) { 37628 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 37629 previous.css( { 'left': left + 'px' } ) 37630 .addClass('animated owl-animated-out') 37631 .addClass(outgoing) 37632 .on($.support.animation.end, clear); 37633 } 37634 37635 if (incoming) { 37636 next.addClass('animated owl-animated-in') 37637 .addClass(incoming) 37638 .on($.support.animation.end, clear); 37639 } 37640 }; 37641 37642 Animate.prototype.clear = function(e) { 37643 if ($(e.target).hasClass('animated')) { 37644 $(e.target).css( { 'left': '' } ) 37645 .removeClass('animated owl-animated-out owl-animated-in') 37646 .removeClass(this.core.settings.animateIn) 37647 .removeClass(this.core.settings.animateOut); 37648 this.core.onTransitionEnd(); 37649 } 37650 }; 37651 37652 /** 37653 * Destroys the plugin. 37654 * @public 37655 */ 37656 Animate.prototype.destroy = function() { 37657 var handler, property; 37658 37659 for (handler in this.handlers) { 37660 this.core.$element.off(handler, this.handlers[handler]); 37661 } 37662 for (property in Object.getOwnPropertyNames(this)) { 37663 typeof this[property] != 'function' && (this[property] = null); 37664 } 37665 }; 37666 37667 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 37668 37669})(window.Zepto || window.jQuery, window, document); 37670 37671/** 37672 * Autoplay Plugin 37673 * @version 2.0.0-beta.3 37674 * @author Bartosz Wojciechowski 37675 * @author Artus Kolanowski 37676 * @license The MIT License (MIT) 37677 */ 37678;(function($, window, document, undefined) { 37679 37680 /** 37681 * Creates the autoplay plugin. 37682 * @class The Autoplay Plugin 37683 * @param {Owl} scope - The Owl Carousel 37684 */ 37685 var Autoplay = function(carousel) { 37686 /** 37687 * Reference to the core. 37688 * @protected 37689 * @type {Owl} 37690 */ 37691 this._core = carousel; 37692 37693 /** 37694 * The autoplay interval. 37695 * @type {Number} 37696 */ 37697 this._interval = null; 37698 37699 /** 37700 * Indicates whenever the autoplay is paused. 37701 * @type {Boolean} 37702 */ 37703 this._paused = false; 37704 37705 /** 37706 * All event handlers. 37707 * @protected 37708 * @type {Object} 37709 */ 37710 this._handlers = { 37711 'changed.owl.carousel': $.proxy(function(e) { 37712 if (e.namespace && e.property.name === 'settings') { 37713 if (this._core.settings.autoplay) { 37714 this.play(); 37715 } else { 37716 this.stop(); 37717 } 37718 } 37719 }, this), 37720 'initialized.owl.carousel': $.proxy(function(e) { 37721 if (e.namespace && this._core.settings.autoplay) { 37722 this.play(); 37723 } 37724 }, this), 37725 'play.owl.autoplay': $.proxy(function(e, t, s) { 37726 if (e.namespace) { 37727 this.play(t, s); 37728 } 37729 }, this), 37730 'stop.owl.autoplay': $.proxy(function(e) { 37731 if (e.namespace) { 37732 this.stop(); 37733 } 37734 }, this), 37735 'mouseover.owl.autoplay': $.proxy(function() { 37736 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 37737 this.pause(); 37738 } 37739 }, this), 37740 'mouseleave.owl.autoplay': $.proxy(function() { 37741 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 37742 this.play(); 37743 } 37744 }, this) 37745 }; 37746 37747 // register event handlers 37748 this._core.$element.on(this._handlers); 37749 37750 // set default options 37751 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 37752 }; 37753 37754 /** 37755 * Default options. 37756 * @public 37757 */ 37758 Autoplay.Defaults = { 37759 autoplay: false, 37760 autoplayTimeout: 5000, 37761 autoplayHoverPause: false, 37762 autoplaySpeed: false 37763 }; 37764 37765 /** 37766 * Starts the autoplay. 37767 * @public 37768 * @param {Number} [timeout] - The interval before the next animation starts. 37769 * @param {Number} [speed] - The animation speed for the animations. 37770 */ 37771 Autoplay.prototype.play = function(timeout, speed) { 37772 this._paused = false; 37773 37774 if (this._core.is('rotating')) { 37775 return; 37776 } 37777 37778 this._core.enter('rotating'); 37779 37780 this._interval = window.setInterval($.proxy(function() { 37781 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 37782 return; 37783 } 37784 this._core.next(speed || this._core.settings.autoplaySpeed); 37785 }, this), timeout || this._core.settings.autoplayTimeout); 37786 }; 37787 37788 /** 37789 * Stops the autoplay. 37790 * @public 37791 */ 37792 Autoplay.prototype.stop = function() { 37793 if (!this._core.is('rotating')) { 37794 return; 37795 } 37796 37797 window.clearInterval(this._interval); 37798 this._core.leave('rotating'); 37799 }; 37800 37801 /** 37802 * Stops the autoplay. 37803 * @public 37804 */ 37805 Autoplay.prototype.pause = function() { 37806 if (!this._core.is('rotating')) { 37807 return; 37808 } 37809 37810 this._paused = true; 37811 }; 37812 37813 /** 37814 * Destroys the plugin. 37815 */ 37816 Autoplay.prototype.destroy = function() { 37817 var handler, property; 37818 37819 this.stop(); 37820 37821 for (handler in this._handlers) { 37822 this._core.$element.off(handler, this._handlers[handler]); 37823 } 37824 for (property in Object.getOwnPropertyNames(this)) { 37825 typeof this[property] != 'function' && (this[property] = null); 37826 } 37827 }; 37828 37829 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 37830 37831})(window.Zepto || window.jQuery, window, document); 37832 37833/** 37834 * Navigation Plugin 37835 * @version 2.0.0-beta.3 37836 * @author Artus Kolanowski 37837 * @license The MIT License (MIT) 37838 */ 37839;(function($, window, document, undefined) { 37840 'use strict'; 37841 37842 /** 37843 * Creates the navigation plugin. 37844 * @class The Navigation Plugin 37845 * @param {Owl} carousel - The Owl Carousel. 37846 */ 37847 var Navigation = function(carousel) { 37848 /** 37849 * Reference to the core. 37850 * @protected 37851 * @type {Owl} 37852 */ 37853 this._core = carousel; 37854 37855 /** 37856 * Indicates whether the plugin is initialized or not. 37857 * @protected 37858 * @type {Boolean} 37859 */ 37860 this._initialized = false; 37861 37862 /** 37863 * The current paging indexes. 37864 * @protected 37865 * @type {Array} 37866 */ 37867 this._pages = []; 37868 37869 /** 37870 * All DOM elements of the user interface. 37871 * @protected 37872 * @type {Object} 37873 */ 37874 this._controls = {}; 37875 37876 /** 37877 * Markup for an indicator. 37878 * @protected 37879 * @type {Array.<String>} 37880 */ 37881 this._templates = []; 37882 37883 /** 37884 * The carousel element. 37885 * @type {jQuery} 37886 */ 37887 this.$element = this._core.$element; 37888 37889 /** 37890 * Overridden methods of the carousel. 37891 * @protected 37892 * @type {Object} 37893 */ 37894 this._overrides = { 37895 next: this._core.next, 37896 prev: this._core.prev, 37897 to: this._core.to 37898 }; 37899 37900 /** 37901 * All event handlers. 37902 * @protected 37903 * @type {Object} 37904 */ 37905 this._handlers = { 37906 'prepared.owl.carousel': $.proxy(function(e) { 37907 if (e.namespace && this._core.settings.dotsData) { 37908 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 37909 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 37910 } 37911 }, this), 37912 'added.owl.carousel': $.proxy(function(e) { 37913 if (e.namespace && this._core.settings.dotsData) { 37914 this._templates.splice(e.position, 0, this._templates.pop()); 37915 } 37916 }, this), 37917 'remove.owl.carousel': $.proxy(function(e) { 37918 if (e.namespace && this._core.settings.dotsData) { 37919 this._templates.splice(e.position, 1); 37920 } 37921 }, this), 37922 'changed.owl.carousel': $.proxy(function(e) { 37923 if (e.namespace && e.property.name == 'position') { 37924 this.draw(); 37925 } 37926 }, this), 37927 'initialized.owl.carousel': $.proxy(function(e) { 37928 if (e.namespace && !this._initialized) { 37929 this._core.trigger('initialize', null, 'navigation'); 37930 this.initialize(); 37931 this.update(); 37932 this.draw(); 37933 this._initialized = true; 37934 this._core.trigger('initialized', null, 'navigation'); 37935 } 37936 }, this), 37937 'refreshed.owl.carousel': $.proxy(function(e) { 37938 if (e.namespace && this._initialized) { 37939 this._core.trigger('refresh', null, 'navigation'); 37940 this.update(); 37941 this.draw(); 37942 this._core.trigger('refreshed', null, 'navigation'); 37943 } 37944 }, this) 37945 }; 37946 37947 // set default options 37948 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 37949 37950 // register event handlers 37951 this.$element.on(this._handlers); 37952 }; 37953 37954 /** 37955 * Default options. 37956 * @public 37957 * @todo Rename `slideBy` to `navBy` 37958 */ 37959 Navigation.Defaults = { 37960 nav: false, 37961 navText: [ 'prev', 'next' ], 37962 navSpeed: false, 37963 navElement: 'button type="button"', 37964 navContainer: false, 37965 navContainerClass: 'owl-nav', 37966 navClass: [ 'owl-prev', 'owl-next' ], 37967 slideBy: 1, 37968 dotClass: 'owl-dot', 37969 dotsClass: 'owl-dots', 37970 dots: true, 37971 dotsEach: false, 37972 dotsData: false, 37973 dotsSpeed: false, 37974 dotsContainer: false 37975 }; 37976 37977 /** 37978 * Initializes the layout of the plugin and extends the carousel. 37979 * @protected 37980 */ 37981 Navigation.prototype.initialize = function() { 37982 var override, 37983 settings = this._core.settings; 37984 37985 // create DOM structure for relative navigation 37986 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 37987 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 37988 37989 this._controls.$previous = $('<' + settings.navElement[0] + '>') 37990 .addClass(settings.navClass[0]) 37991 .html(settings.navText[0]) 37992 .prependTo(this._controls.$relative) 37993 .on('click', $.proxy(function(e) { 37994 this.prev(settings.navSpeed); 37995 }, this)); 37996 this._controls.$next = $('<' + settings.navElement[1] + '>') 37997 .addClass(settings.navClass[1]) 37998 .html(settings.navText[1]) 37999 .appendTo(this._controls.$relative) 38000 .on('click', $.proxy(function(e) { 38001 this.next(settings.navSpeed); 38002 }, this)); 38003 38004 // create DOM structure for absolute navigation 38005 if (!settings.dotsData) { 38006 this._templates = [ $('<button>') 38007 .addClass(settings.dotClass) 38008 .append($('<span>')) 38009 .prop('outerHTML') ]; 38010 } 38011 38012 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 38013 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 38014 38015 this._controls.$absolute.on('click', 'div, button', $.proxy(function(e) { 38016 var index = $(e.target).parent().is(this._controls.$absolute) 38017 ? $(e.target).index() : $(e.target).parent().index(); 38018 38019 e.preventDefault(); 38020 38021 this.to(index, settings.dotsSpeed); 38022 }, this)); 38023 38024 // override public methods of the carousel 38025 for (override in this._overrides) { 38026 this._core[override] = $.proxy(this[override], this); 38027 } 38028 }; 38029 38030 /** 38031 * Destroys the plugin. 38032 * @protected 38033 */ 38034 Navigation.prototype.destroy = function() { 38035 var handler, control, property, override; 38036 38037 for (handler in this._handlers) { 38038 this.$element.off(handler, this._handlers[handler]); 38039 } 38040 for (control in this._controls) { 38041 this._controls[control].remove(); 38042 } 38043 for (override in this.overides) { 38044 this._core[override] = this._overrides[override]; 38045 } 38046 for (property in Object.getOwnPropertyNames(this)) { 38047 typeof this[property] != 'function' && (this[property] = null); 38048 } 38049 }; 38050 38051 /** 38052 * Updates the internal state. 38053 * @protected 38054 */ 38055 Navigation.prototype.update = function() { 38056 var i, j, k, 38057 lower = this._core.clones().length / 2, 38058 upper = lower + this._core.items().length, 38059 maximum = this._core.maximum(true), 38060 settings = this._core.settings, 38061 size = settings.center || settings.autoWidth || settings.dotsData 38062 ? 1 : settings.dotsEach || settings.items; 38063 38064 if (settings.slideBy !== 'page') { 38065 settings.slideBy = Math.min(settings.slideBy, settings.items); 38066 } 38067 38068 if (settings.dots || settings.slideBy == 'page') { 38069 this._pages = []; 38070 38071 for (i = lower, j = 0, k = 0; i < upper; i++) { 38072 if (j >= size || j === 0) { 38073 this._pages.push({ 38074 start: Math.min(maximum, i - lower), 38075 end: i - lower + size - 1 38076 }); 38077 if (Math.min(maximum, i - lower) === maximum) { 38078 break; 38079 } 38080 j = 0, ++k; 38081 } 38082 j += this._core.mergers(this._core.relative(i)); 38083 } 38084 } 38085 }; 38086 38087 /** 38088 * Draws the user interface. 38089 * @todo The option `dotsData` wont work. 38090 * @protected 38091 */ 38092 Navigation.prototype.draw = function() { 38093 var difference, 38094 settings = this._core.settings, 38095 disabled = this._core.items().length <= settings.items, 38096 index = this._core.relative(this._core.current()), 38097 loop = settings.loop || settings.rewind; 38098 38099 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 38100 38101 if (settings.nav) { 38102 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 38103 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 38104 } 38105 38106 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 38107 38108 if (settings.dots) { 38109 difference = this._pages.length - this._controls.$absolute.children().length; 38110 38111 if (settings.dotsData && difference !== 0) { 38112 this._controls.$absolute.html(this._templates.join('')); 38113 } else if (difference > 0) { 38114 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 38115 } else if (difference < 0) { 38116 this._controls.$absolute.children().slice(difference).remove(); 38117 } 38118 38119 this._controls.$absolute.find('.active').removeClass('active'); 38120 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 38121 } 38122 }; 38123 38124 /** 38125 * Extends event data. 38126 * @protected 38127 * @param {Event} event - The event object which gets thrown. 38128 */ 38129 Navigation.prototype.onTrigger = function(event) { 38130 var settings = this._core.settings; 38131 38132 event.page = { 38133 index: $.inArray(this.current(), this._pages), 38134 count: this._pages.length, 38135 size: settings && (settings.center || settings.autoWidth || settings.dotsData 38136 ? 1 : settings.dotsEach || settings.items) 38137 }; 38138 }; 38139 38140 /** 38141 * Gets the current page position of the carousel. 38142 * @protected 38143 * @returns {Number} 38144 */ 38145 Navigation.prototype.current = function() { 38146 var current = this._core.relative(this._core.current()); 38147 return $.grep(this._pages, $.proxy(function(page, index) { 38148 return page.start <= current && page.end >= current; 38149 }, this)).pop(); 38150 }; 38151 38152 /** 38153 * Gets the current succesor/predecessor position. 38154 * @protected 38155 * @returns {Number} 38156 */ 38157 Navigation.prototype.getPosition = function(successor) { 38158 var position, length, 38159 settings = this._core.settings; 38160 38161 if (settings.slideBy == 'page') { 38162 position = $.inArray(this.current(), this._pages); 38163 length = this._pages.length; 38164 successor ? ++position : --position;
vendor: 5,674 bytes, lines 38165-38389
38165 position = this._pages[((position % length) + length) % length].start; 38166 } else { 38167 position = this._core.relative(this._core.current()); 38168 length = this._core.items().length; 38169 successor ? position += settings.slideBy : position -= settings.slideBy; 38170 } 38171 38172 return position; 38173 }; 38174 38175 /** 38176 * Slides to the next item or page. 38177 * @public 38178 * @param {Number} [speed=false] - The time in milliseconds for the transition. 38179 */ 38180 Navigation.prototype.next = function(speed) { 38181 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 38182 }; 38183 38184 /** 38185 * Slides to the previous item or page. 38186 * @public 38187 * @param {Number} [speed=false] - The time in milliseconds for the transition. 38188 */ 38189 Navigation.prototype.prev = function(speed) { 38190 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 38191 }; 38192 38193 /** 38194 * Slides to the specified item or page. 38195 * @public 38196 * @param {Number} position - The position of the item or page. 38197 * @param {Number} [speed] - The time in milliseconds for the transition. 38198 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 38199 */ 38200 Navigation.prototype.to = function(position, speed, standard) { 38201 var length; 38202 38203 if (!standard) { 38204 length = this._pages.length; 38205 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 38206 } else { 38207 $.proxy(this._overrides.to, this._core)(position, speed); 38208 } 38209 }; 38210 38211 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 38212 38213})(window.Zepto || window.jQuery, window, document); 38214 38215/** 38216 * Hash Plugin 38217 * @version 2.0.0-beta.3 38218 * @author Artus Kolanowski 38219 * @license The MIT License (MIT) 38220 */ 38221;(function($, window, document, undefined) { 38222 'use strict'; 38223 38224 /** 38225 * Creates the hash plugin. 38226 * @class The Hash Plugin 38227 * @param {Owl} carousel - The Owl Carousel 38228 */ 38229 var Hash = function(carousel) { 38230 /** 38231 * Reference to the core. 38232 * @protected 38233 * @type {Owl} 38234 */ 38235 this._core = carousel; 38236 38237 /** 38238 * Hash index for the items. 38239 * @protected 38240 * @type {Object} 38241 */ 38242 this._hashes = {}; 38243 38244 /** 38245 * The carousel element. 38246 * @type {jQuery} 38247 */ 38248 this.$element = this._core.$element; 38249 38250 /** 38251 * All event handlers. 38252 * @protected 38253 * @type {Object} 38254 */ 38255 this._handlers = { 38256 'initialized.owl.carousel': $.proxy(function(e) { 38257 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 38258 $(window).trigger('hashchange.owl.navigation'); 38259 } 38260 }, this), 38261 'prepared.owl.carousel': $.proxy(function(e) { 38262 if (e.namespace) { 38263 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 38264 38265 if (!hash) { 38266 return; 38267 } 38268 38269 this._hashes[hash] = e.content; 38270 } 38271 }, this), 38272 'changed.owl.carousel': $.proxy(function(e) { 38273 if (e.namespace && e.property.name === 'position') { 38274 var current = this._core.items(this._core.relative(this._core.current())), 38275 hash = $.map(this._hashes, function(item, hash) { 38276 return item === current ? hash : null; 38277 }).join(); 38278 38279 if (!hash || window.location.hash.slice(1) === hash) { 38280 return; 38281 } 38282 38283 window.location.hash = hash; 38284 } 38285 }, this) 38286 }; 38287 38288 // set default options 38289 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 38290 38291 // register the event handlers 38292 this.$element.on(this._handlers); 38293 38294 // register event listener for hash navigation 38295 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 38296 var hash = window.location.hash.substring(1), 38297 items = this._core.$stage.children(), 38298 position = this._hashes[hash] && items.index(this._hashes[hash]); 38299 38300 if (position === undefined || position === this._core.current()) { 38301 return; 38302 } 38303 38304 this._core.to(this._core.relative(position), false, true); 38305 }, this));*/ 38306 }; 38307 38308 /** 38309 * Default options. 38310 * @public 38311 */ 38312 Hash.Defaults = { 38313 URLhashListener: false 38314 }; 38315 38316 /** 38317 * Destroys the plugin. 38318 * @public 38319 */ 38320 Hash.prototype.destroy = function() { 38321 var handler, property; 38322 38323 $(window).off('hashchange.owl.navigation'); 38324 38325 for (handler in this._handlers) { 38326 this._core.$element.off(handler, this._handlers[handler]); 38327 } 38328 for (property in Object.getOwnPropertyNames(this)) { 38329 typeof this[property] != 'function' && (this[property] = null); 38330 } 38331 }; 38332 38333 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 38334 38335})(window.Zepto || window.jQuery, window, document); 38336 38337/** 38338 * Support Plugin 38339 * 38340 * @version 2.0.0-beta.3 38341 * @author Vivid Planet Software GmbH 38342 * @author Artus Kolanowski 38343 * @license The MIT License (MIT) 38344 */ 38345;(function($, window, document, undefined) { 38346 38347 var style = $('<support>').get(0).style, 38348 prefixes = 'Webkit Moz O ms'.split(' '), 38349 events = { 38350 transition: { 38351 end: { 38352 WebkitTransition: 'webkitTransitionEnd', 38353 MozTransition: 'transitionend', 38354 OTransition: 'oTransitionEnd', 38355 transition: 'transitionend' 38356 } 38357 }, 38358 animation: { 38359 end: { 38360 WebkitAnimation: 'webkitAnimationEnd', 38361 MozAnimation: 'animationend', 38362 OAnimation: 'oAnimationEnd', 38363 animation: 'animationend' 38364 } 38365 } 38366 }, 38367 tests = { 38368 csstransforms: function() { 38369 return !!test('transform'); 38370 }, 38371 csstransforms3d: function() { 38372 return !!test('perspective'); 38373 }, 38374 csstransitions: function() { 38375 return !!test('transition'); 38376 }, 38377 cssanimations: function() { 38378 return !!test('animation'); 38379 } 38380 }; 38381 38382 function test(property, prefixed) { 38383 var result = false, 38384 upper = property.charAt(0).toUpperCase() + property.slice(1); 38385 38386 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 38387 if (style[property] !== undefined) { 38388 result = prefixed ? property : true; 38389 return false;
38390 } 38391 }); 38392 38393 return result; 38394 } 38395 38396 function prefixed(property) { 38397 return test(property, true); 38398 } 38399 38400 if (tests.csstransitions()) { 38401 /* jshint -W053 */ 38402 $.support.transition = new String(prefixed('transition')) 38403 $.support.transition.end = events.transition.end[ $.support.transition ]; 38404 } 38405 38406 if (tests.cssanimations()) { 38407 /* jshint -W053 */ 38408 $.support.animation = new String(prefixed('animation')) 38409 $.support.animation.end = events.animation.end[ $.support.animation ]; 38410 } 38411 38412 if (tests.csstransforms()) { 38413 /* jshint -W053 */ 38414 $.support.transform = new String(prefixed('transform')); 38415 $.support.transform3d = tests.csstransforms3d(); 38416 } 38417 38418})(window.Zepto || window.jQuery, window, document); 38419 38420(function(window, document, undefined) { 38421 38422 /** 38423 * Find the absolute position of an element 38424 */ 38425 var absPos = function(element) { 38426 var offsetLeft, offsetTop; 38427 offsetLeft = offsetTop = 0; 38428 if (element.offsetParent) { 38429 do { 38430 offsetLeft += element.offsetLeft; 38431 offsetTop += element.offsetTop; 38432 } while (element = element.offsetParent); 38433 } 38434 return [offsetLeft, offsetTop]; 38435 }; 38436 38437 /** 38438 * @constructor Progress Circle class 38439 * @param params.canvas Canvas on which the circles will be drawn. 38440 * @param params.minRadius Inner radius of the innermost circle, in px. 38441 * @param params.arcWidth Width of each circle(to be more accurate, ring). 38442 * @param params.gapWidth Space between each circle. 38443 * @param params.centerX X coordinate of the center of circles. 38444 * @param params.centerY Y coordinate of the center of circles. 38445 * @param params.infoLineBaseAngle Base angle of the info line. 38446 * @param params.infoLineAngleInterval Angles between the info lines. 38447 */ 38448 var ProgressCircle = function(params) { 38449 this.canvas = params.canvas; 38450 this.minRadius = params.minRadius || 15; 38451 this.arcWidth = params.arcWidth || 5; 38452 this.gapWidth = params.gapWidth || 3; 38453 this.centerX = params.centerX || this.canvas.width / 2; 38454 this.centerY = params.centerY || this.canvas.height / 2;
38455 this.infoLineLength = params.infoLineLength || 60; 38456 this.horizLineLength = params.horizLineLength || 10; 38457 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 38458 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 38459 38460 this.context = this.canvas.getContext('2d'); 38461 38462 this.width = this.canvas.width; 38463 this.height = this.canvas.height; 38464 38465 this.circles = []; 38466 this.runningCount = 0; 38467 }; 38468 38469 ProgressCircle.prototype = { 38470 constructor: ProgressCircle, 38471 38472 /** 38473 * @method Adds an progress monitor entry. 38474 * @param params.fillColor Color to fill in the circle. 38475 * @param params.outlineColor Color to outline the circle. 38476 * @param params.progressListener Callback function to fetch the progress. 38477 * @param params.infoListener Callback function to fetch the info. 38478 * @returns this 38479 */ 38480 addEntry: function(params) { 38481 this.circles.push(new Circle({ 38482 canvas: this.canvas, 38483 context: this.context, 38484 centerX: this.centerX, 38485 centerY: this.centerY, 38486 innerRadius: this.minRadius + this.circles.length * 38487 (this.gapWidth + this.arcWidth), 38488 arcWidth: this.arcWidth,
38489 infoLineLength: this.infoLineLength, 38490 horizLineLength: this.horizLineLength, 38491 38492 id: this.circles.length, 38493 fillColor: params.fillColor, 38494 outlineColor: params.outlineColor, 38495 progressListener: params.progressListener, 38496 infoListener: params.infoListener, 38497 infoLineAngle: this.infoLineBaseAngle + 38498 this.circles.length * this.infoLineAngleInterval, 38499 })); 38500 38501 return this; 38502 }, 38503 38504 /** 38505 * @method Starts the monitor and updates with the given interval. 38506 * @param interval Interval between updates, in millisecond. 38507 * @returns this 38508 */ 38509 start: function(interval) { 38510 var self = this; 38511 this.timer = setInterval(function() { 38512 self._update(); 38513 }, interval || 33); 38514 38515 return this; 38516 }, 38517 38518 /** 38519 * @method Stop the animation. 38520 */ 38521 stop: function() { 38522 clearTimeout(this.timer); 38523 }, 38524 38525 /** 38526 * @private 38527 * @method Call update on each circle and redraw them. 38528 * @returns this 38529 */ 38530 _update: function() { 38531 this._clear(); 38532 this.circles.forEach(function(circle, idx, array) { 38533 circle.update(); 38534 }); 38535 38536 return this; 38537 }, 38538 38539 /** 38540 * @private 38541 * @method Clear the canvas. 38542 * @returns this 38543 */ 38544 _clear: function() { 38545 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 38546 38547 return this; 38548 }, 38549 38550 }; 38551 38552 /** 38553 * @private 38554 * @class Individual progress circle. 38555 * @param params.canvas Canvas on which the circle will be drawn. 38556 * @param params.context Context of the canvas. 38557 * @param params.innerRadius Inner radius of the circle, in px. 38558 * @param params.arcWidth Width of each arc(circle). 38559 * @param params.gapWidth Distance between each arc. 38560 * @param params.centerX X coordinate of the center of circles. 38561 * @param params.centerY Y coordinate of the center of circles. 38562 * @param params.fillColor Color to fill in the circle. 38563 * @param params.outlineColor Color to outline the circle. 38564 * @param params.progressListener Callback function to fetch the progress. 38565 * @param params.infoListener Callback function to fetch the info. 38566 * @param params.infoLineAngle Angle of info line. 38567 */ 38568 var Circle = function(params) { 38569 this.id = params.id; 38570 this.canvas = params.canvas; 38571 this.context = params.context; 38572 this.centerX = params.centerX; 38573 this.centerY = params.centerY; 38574 this.arcWidth = params.arcWidth; 38575 this.innerRadius = params.innerRadius || 0; 38576 this.fillColor = params.fillColor || '#fff'; 38577 this.outlineColor = params.outlineColor || this.fillColor; 38578 this.progressListener = params.progressListener;
38579 this.infoLineLength = params.infoLineLength || 250; 38580 this.horizLineLength = params.horizLineLength || 50; 38581 this.infoListener = params.infoListener; 38582 this.infoLineAngle = params.infoLineAngle; 38583 38584 this.outerRadius = this.innerRadius + this.arcWidth; 38585 38586 // If the info listener is not registered, then don't calculate 38587 // the related coordinates 38588 if (!this.infoListener) return; 38589 38590 // calculate the info-line turning points 38591 var angle = this.infoLineAngle, 38592 arcDistance = (this.innerRadius + this.outerRadius) / 2, 38593 38594 sinA = Math.sin(angle), 38595 cosA = Math.cos(angle); 38596 38597 this.infoLineStartX = this.centerX + sinA * arcDistance; 38598 this.infoLineStartY = this.centerY - cosA * arcDistance; 38599 38600 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 38601 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 38602 38603 this.infoLineEndX = this.infoLineMidX + 38604 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 38605 this.infoLineEndY = this.infoLineMidY; 38606 38607 var infoText = document.createElement('div'), 38608 style = infoText.style; 38609 38610 style.color = this.fillColor; 38611 style.position = 'absolute'; 38612 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 38613 // style.top will be calculated in the `drawInfo` method. Since 38614 // user may want to change the size of the font, so the top offset 38615 // must be updated in each loop. 38616 infoText.className = 'ProgressCircleInfo'; // For css styling 38617 infoText.id = 'progress_circle_info_' + this.id; 38618 document.body.appendChild(infoText); 38619 this.infoText = infoText; 38620 }; 38621 38622 Circle.prototype = { 38623 constructor: Circle, 38624 38625 update: function() { 38626 this.progress = this.progressListener(); 38627 this._draw(); 38628 38629 if (this.infoListener) { 38630 this.info = this.infoListener(); 38631 this._drawInfo(); 38632 } 38633 }, 38634 38635 /** 38636 * @private 38637 * @method Draw the circle on the canvas. 38638 * @returns this 38639 */ 38640 _draw: function() { 38641 var ctx = this.context, 38642 38643 ANGLE_OFFSET = -Math.PI / 2, 38644 38645 startAngle = 0 + ANGLE_OFFSET, 38646 endAngle= startAngle + this.progress * Math.PI * 2, 38647 38648 x = this.centerX, 38649 y = this.centerY, 38650 38651 innerRadius = this.innerRadius - this.arcWidth - 1, 38652 outerRadius = this.outerRadius - this.arcWidth - 1; 38653 38654 if ( innerRadius < 0 ) 38655 return; 38656 38657 ctx.fillStyle = this.fillColor; 38658 ctx.strokeStyle = this.outlineColor; 38659 38660 ctx.beginPath(); 38661 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 38662 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 38663 ctx.closePath(); 38664 ctx.stroke(); 38665 ctx.fill(); 38666 38667 return this; 38668 }, 38669 38670 /** 38671 * @private 38672 * @method Draw the info lines and info text. 38673 * @returns this 38674 */ 38675 _drawInfo: function() { 38676 38677 var pointList, lineHeight; 38678 38679 pointList = [ 38680 [this.infoLineStartX, this.infoLineStartY], 38681 [this.infoLineMidX, this.infoLineMidY], 38682 [this.infoLineEndX, this.infoLineEndY], 38683 ]; 38684 this._drawSegments(pointList, false); 38685 38686 this.infoText.innerHTML = this.info; 38687 38688 lineHeight = this.infoText.offsetHeight; 38689 this.infoText.style.top = this.infoLineEndY + 38690 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 38691 38692 return this; 38693 }, 38694 38695 /** 38696 * @private 38697 * @method Helper function to draw the segments 38698 * @param pointList An array of points in the form of [x, y]. 38699 * @param close Whether to connect the first and last point. 38700 */ 38701 _drawSegments: function(pointList, close) { 38702 var ctx = this.context; 38703 38704 ctx.beginPath(); 38705 ctx.moveTo(pointList[0][0], pointList[0][1]); 38706 for (var i = 1; i < pointList.length; ++i) { 38707 ctx.lineTo(pointList[i][0], pointList[i][1]); 38708 } 38709 38710 if (close) { 38711 ctx.closePath(); 38712 } 38713 ctx.stroke(); 38714 }, 38715 }; 38716 38717 window.ProgressCircle = ProgressCircle; 38718 38719})(window, document); 38720 38721 38722 38723 38724/* ========================================================= 38725 * jquery.vc_chart.js v1.0 38726 * ========================================================= 38727 * Copyright 2013 Wpbakery 38728 * 38729 * Jquery chart plugin for the Visual Composer. 38730 * ========================================================= */ 38731(function($){ 38732 /** 38733 * Pie chart animated. 38734 * @param element - DOM element 38735 * @param options - settings object. 38736 * @constructor 38737 */ 38738 var VcChart = function(element, options) { 38739 this.el = element; 38740 this.$el = $(this.el); 38741 var $this = this; 38742 $this.options = $.extend({ 38743 color: 'wpb_button', 38744 units: '', 38745 width: '', 38746 label_selector: '.vc_pie_chart_value', 38747 back_selector: '.vc_pie_chart_back', 38748 responsive: true 38749 }, options); 38750 $this.init(); 38751 }; 38752 VcChart.prototype = { 38753 constructor: VcChart, 38754 _progress_v: 0, 38755 animated: false, 38756 colors: { 38757 'wpb_button': 'rgba(247, 247, 247, 1)', 38758 'btn-primary': 'rgba(0, 136, 204, 1)', 38759 'btn-info': 'rgba(88, 185, 218, 1)', 38760 'btn-success': 'rgba(106, 177, 101, 1)', 38761 'btn-warning': 'rgba(255, 153, 0, 1)', 38762 'btn-danger': 'rgba(255, 103, 91, 1)', 38763 'btn-inverse': 'rgba(85, 85, 85, 1)' 38764 }, 38765 init: function() { 38766 this.setupColor(); 38767 this.value = this.$el.data('pie-value')/100; 38768 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 38769 this.$wrapper = $('.vc_pie_wrapper', this.$el); 38770 this.$label = $(this.options.label_selector, this.$el); 38771 this.$back = $(this.options.back_selector, this.$el); 38772 this.$canvas = this.$el.find('canvas'); 38773 this.arcWidth = this.$el.data('pie-width') * 2; 38774 this.draw(); 38775 this.setWayPoint(); 38776 if(this.options.responsive === true) this.setResponsive(); 38777 if (UNCODE.isMobile) this._progress_v = this.value; 38778 }, 38779 setupColor: function() { 38780 // if(typeof this.colors[this.options.color] !== 'undefined') { 38781 // this.color = this.colors[this.options.color]; 38782 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 38783 // this.color = this.options.color; 38784 // } else { 38785 // this.color = 'rgba(247, 247, 247, 0.2)'; 38786 // } 38787 if(typeof this.options.color !== 'undefined') { 38788 this.color = this.options.color; 38789 } else this.color = 'rgba(247, 247, 247, 0.2)'; 38790 38791 }, 38792 setResponsive: function() { 38793 var that = this; 38794 if (!UNCODE.isMobile) { 38795 $(window).resize(function(){ 38796 if(that.animated === true) that.circle.stop(); 38797 that.draw(true); 38798 }); 38799 } 38800 }, 38801 draw: function(redraw) { 38802 var w = this.$el.addClass('vc_ready').width() * 2, 38803 border_w = this.arcWidth, 38804 radius; 38805 if(!w) w = this.$el.parents(':visible').first().width()-2; 38806 //w = Math.round(w/100*80); 38807 //if (w < 250) w = 250; 38808 radius = w/2; 38809 this.$wrapper.css({"width" : (w / 2) + "px"}); 38810 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 38811 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 38812 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 38813 this.$el.addClass('vc_ready'); 38814 this.circle = new ProgressCircle({ 38815 canvas: this.$canvas.get(0), 38816 minRadius: radius, 38817 arcWidth: border_w 38818 }); 38819 if(redraw === true && this.animated === true) { 38820 this._progress_v = this.value; 38821 this.circle.addEntry({ 38822 fillColor: this.color, 38823 progressListener: $.proxy(this.setProgress, this) 38824 }).start(); 38825 } 38826 }, 38827 setProgress: function() { 38828 if (this._progress_v >= this.value) { 38829 this.circle.stop(); 38830 this.animated = true; 38831 this.$label.html(this.label_value + this.options.units); 38832 return this._progress_v; 38833 } 38834 this._progress_v += 0.01; 38835 if (!isNaN(this.label_value)) { 38836 var label_value = this._progress_v/this.value*this.label_value; 38837 var val = Math.round(label_value) + this.options.units; 38838 this.$label.html(val); 38839 } else this.$label.html(this.label_value + this.options.units); 38840 return this._progress_v; 38841 }, 38842 animate: function() { 38843 if(this.animated !== true) { 38844 this.circle.addEntry({ 38845 fillColor: this.color, 38846 progressListener: $.proxy(this.setProgress, this) 38847 }).start(10); 38848 } 38849 }, 38850 setWayPoint: function() { 38851 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 38852 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 38853 } else { 38854 this.animate(); 38855 } 38856 } 38857 }; 38858 /** 38859 * jQuery plugin 38860 * @param option - object with settings 38861 * @return {*} 38862 */ 38863 $.fn.vcChat = function(option, value) { 38864 return this.each(function () { 38865 var $this = $(this), 38866 data = $this.data('vc_chart'), 38867 options = typeof option === 'object' ? option : { 38868 color: $this.data('pie-color'), 38869 units: $this.data('pie-units') 38870 }; 38871 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 38872 if (typeof option == 'string') data[option](value); 38873 }); 38874 }; 38875 /** 38876 * Allows users to rewrite function inside theme. 38877 */ 38878 if ( typeof window['vc_pieChart'] !== 'function' ) { 38879 window.vc_pieChart = function() { 38880 $('.vc_pie_chart:visible:not(.vc_ready)').vcChat(); 38881 } 38882 } 38883 $(document).ready(function(){ 38884 !window.vc_iframe && vc_pieChart(); 38885 38886 /** 38887 * Tab and collapse integration. 38888 */ 38889 $('.nav-tabs a').on('shown.bs.tab', function(e){ 38890 var $cont = $(e.target).closest('.tab-container'), 38891 $active = $('.tab-pane.active', $cont); 38892 $('.vc_pie_chart:not(.vc_ready)', $active).vcChat(); 38893 }); 38894 38895 $('.panel-collapse').on('shown.bs.collapse', function (e) { 38896 $('.vc_pie_chart:not(.vc_ready)', e.target).vcChat(); 38897 }) 38898 }); 38899 38900})(window.jQuery); 38901 38902/* Progress bar 38903 ---------------------------------------------------------- */ 38904function uncode_progress_bar() { 38905 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 38906 if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) { 38907 return; 38908 } 38909 if (!UNCODE.isMobile) { 38910 new Waypoint({ 38911 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 38912 element: val, 38913 handler: function() { 38914 var element = jQuery(this.element); 38915 element.find('.vc_single_bar').each(function(index) { 38916 var $this = jQuery(this), 38917 bar = $this.find('.vc_bar'), 38918 val = bar.data('percentage-value'); 38919 setTimeout(function() { 38920 bar.css({ 38921 "width": val + '%' 38922 }); 38923 }, index * 200); 38924 }); 38925 }, 38926 offset: '80%' 38927 }); 38928 } else { 38929 var element = jQuery(val); 38930 element.find('.vc_single_bar').each(function(index) { 38931 var $this = jQuery(this), 38932 bar = $this.find('.vc_bar'), 38933 val = bar.data('percentage-value'); 38934 setTimeout(function() { 38935 bar.css({ 38936 "width": val + '%' 38937 }); 38938 }, index * 200); 38939 }); 38940 } 38941 }); 38942}; 38943uncode_progress_bar(); 38944 38945/*! 38946 * jquery.counterup.js 1.0 38947 * 38948 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 38949 * Released under the GPL v2 License 38950 * 38951 * Date: Nov 26, 2013 38952 */ 38953(function($) { 38954 "use strict"; 38955 $.fn.counterUp = function(options) { 38956 // Defaults 38957 var settings = $.extend({ 38958 'time': 400, 38959 'delay': 10 38960 }, options); 38961 return this.each(function() { 38962 // Store the object 38963 var $this = $(this); 38964 var $settings = settings; 38965 var counterUpper = function() { 38966 var nums = []; 38967 var divisions = $settings.time / $settings.delay; 38968 var numReal = $this.attr('data-val'), 38969 num = numReal; 38970 var isComma = /[0-9]+,[0-9]+/.test(num); 38971 num = num.replace(/,/g, ''); 38972 var isInt = /^[0-9]+$/.test(num); 38973 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 38974 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 38975 // Generate list of incremental numbers to display 38976 for (var i = divisions; i >= 1; i--) { 38977 // Preserve as int if input was int 38978 var newNum = parseInt(num / divisions * i); 38979 // Preserve float if input was float 38980 if (isFloat) { 38981 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 38982 } 38983 // Preserve commas if input had commas 38984 if (isComma) { 38985 while (/(\d+)(\d{3})/.test(newNum.toString())) { 38986 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 38987 } 38988 } 38989 nums.unshift(newNum); 38990 } 38991 nums.push(numReal); 38992 $this.data('counterup-nums', nums); 38993 $this.text('0'); 38994 // Updates the number until we're done 38995 var f = function() { 38996 if ($this.data('counterup-nums') != null) { 38997 $this.text($this.data('counterup-nums').shift()); 38998 if ($this.data('counterup-nums').length) { 38999 setTimeout($this.data('counterup-func'), $settings.delay); 39000 } else { 39001 delete $this.data('counterup-nums'); 39002 $this.data('counterup-nums', null); 39003 $this.data('counterup-func', null); 39004 } 39005 } 39006 }; 39007 $this.data('counterup-func', f); 39008 // Start the count up 39009 setTimeout($this.data('counterup-func'), $settings.delay); 39010 }; 39011 // Perform counts when the element gets into view 39012 new Waypoint({ 39013 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 39014 element: this, 39015 handler: function() { 39016 counterUpper(); 39017 if (!UNCODE.isUnmodalOpen) { 39018 this.destroy(); 39019 } 39020 }, 39021 offset: '100%' 39022 }); 39023 }); 39024 }; 39025})(jQuery); 39026 39027/*! 39028 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/) 39029 * Copyright (c) 2016 Edson Hilios 39030 * 39031 * Permission is hereby granted, free of charge, to any person obtaining a copy of 39032 * this software and associated documentation files (the "Software"), to deal in 39033 * the Software without restriction, including without limitation the rights to 39034 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 39035 * the Software, and to permit persons to whom the Software is furnished to do so, 39036 * subject to the following conditions: 39037 * 39038 * The above copyright notice and this permission notice shall be included in all 39039 * copies or substantial portions of the Software. 39040 * 39041 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39042 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 39043 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 39044 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 39045 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 39046 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 39047 */ 39048(function(factory) { 39049 "use strict"; 39050 if (typeof define === "function" && define.amd) { 39051 define([ "jquery" ], factory); 39052 } else { 39053 factory(jQuery); 39054 } 39055})(function($) { 39056 "use strict"; 39057 var instances = [], matchers = [], defaultOptions = { 39058 precision: 100, 39059 elapse: false, 39060 defer: false 39061 }; 39062 matchers.push(/^[0-9]*$/.source); 39063 matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 39064 matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 39065 matchers = new RegExp(matchers.join("|")); 39066 function parseDateString(dateString) { 39067 if (dateString instanceof Date) { 39068 return dateString; 39069 } 39070 if (String(dateString).match(matchers)) { 39071 if (String(dateString).match(/^[0-9]*$/)) { 39072 dateString = Number(dateString); 39073 } 39074 if (String(dateString).match(/\-/)) { 39075 dateString = String(dateString).replace(/\-/g, "/"); 39076 } 39077 return new Date(dateString); 39078 } else { 39079 throw new Error("Couldn't cast `" + dateString + "` to a date object."); 39080 } 39081 } 39082 var DIRECTIVE_KEY_MAP = { 39083 Y: "years", 39084 m: "months", 39085 n: "daysToMonth", 39086 d: "daysToWeek", 39087 w: "weeks", 39088 W: "weeksToMonth", 39089 H: "hours", 39090 M: "minutes", 39091 S: "seconds", 39092 D: "totalDays", 39093 I: "totalHours", 39094 N: "totalMinutes", 39095 T: "totalSeconds" 39096 }; 39097 function escapedRegExp(str) { 39098 var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); 39099 return new RegExp(sanitize); 39100 } 39101 function strftime(offsetObject) { 39102 return function(format) { 39103 var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi); 39104 if (directives) { 39105 for (var i = 0, len = directives.length; i < len; ++i) { 39106 var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null; 39107 directive = directive[2]; 39108 if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) { 39109 value = DIRECTIVE_KEY_MAP[directive]; 39110 value = Number(offsetObject[value]); 39111 } 39112 if (value !== null) { 39113 if (modifier === "!") { 39114 value = pluralize(plural, value); 39115 } 39116 if (modifier === "") { 39117 if (value < 10) { 39118 value = "0" + value.toString(); 39119 } 39120 } 39121 format = format.replace(regexp, value.toString()); 39122 } 39123 } 39124 } 39125 format = format.replace(/%%/, "%"); 39126 return format; 39127 }; 39128 } 39129 function pluralize(format, count) { 39130 var plural = "s", singular = ""; 39131 if (format) { 39132 format = format.rep
vendor: 8,618 bytes, lines 39132-39276
39132lace(/(:|;|\s)/gi, "").split(/\,/); 39133 if (format.length === 1) { 39134 plural = format[0]; 39135 } else { 39136 singular = format[0]; 39137 plural = format[1]; 39138 } 39139 } 39140 if (Math.abs(count) > 1) { 39141 return plural; 39142 } else { 39143 return singular; 39144 } 39145 } 39146 var Countdown = function(el, finalDate, options) { 39147 this.el = el; 39148 this.$el = $(el); 39149 this.interval = null; 39150 this.offset = {}; 39151 this.options = $.extend({}, defaultOptions); 39152 this.instanceNumber = instances.length; 39153 instances.push(this); 39154 this.$el.data("countdown-instance", this.instanceNumber); 39155 if (options) { 39156 if (typeof options === "function") { 39157 this.$el.on("update.countdown", options); 39158 this.$el.on("stoped.countdown", options); 39159 this.$el.on("finish.countdown", options); 39160 } else { 39161 this.options = $.extend({}, defaultOptions, options); 39162 } 39163 } 39164 this.setFinalDate(finalDate); 39165 if (this.options.defer === false) { 39166 this.start(); 39167 } 39168 }; 39169 $.extend(Countdown.prototype, { 39170 start: function() { 39171 if (this.interval !== null) { 39172 clearInterval(this.interval); 39173 } 39174 var self = this; 39175 this.update(); 39176 this.interval = setInterval(function() { 39177 self.update.call(self); 39178 }, this.options.precision); 39179 }, 39180 stop: function() { 39181 clearInterval(this.interval); 39182 this.interval = null; 39183 this.dispatchEvent("stoped"); 39184 }, 39185 toggle: function() { 39186 if (this.interval) { 39187 this.stop(); 39188 } else { 39189 this.start(); 39190 } 39191 }, 39192 pause: function() { 39193 this.stop(); 39194 }, 39195 resume: function() { 39196 this.start(); 39197 }, 39198 remove: function() { 39199 this.stop.call(this); 39200 instances[this.instanceNumber] = null; 39201 delete this.$el.data().countdownInstance; 39202 }, 39203 setFinalDate: function(value) { 39204 this.finalDate = parseDateString(value); 39205 }, 39206 update: function() { 39207 if (this.$el.closest("html").length === 0) { 39208 this.remove(); 39209 return; 39210 } 39211 var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft; 39212 newTotalSecsLeft = this.finalDate.getTime() - now.getTime(); 39213 newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3); 39214 newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft); 39215 if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) { 39216 return; 39217 } else { 39218 this.totalSecsLeft = newTotalSecsLeft; 39219 } 39220 this.elapsed = now >= this.finalDate; 39221 this.offset = { 39222 seconds: this.totalSecsLeft % 60, 39223 minutes: Math.floor(this.totalSecsLeft / 60) % 60, 39224 hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24, 39225 days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 39226 daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 39227 daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368), 39228 weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7), 39229 weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4, 39230 months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368), 39231 years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()), 39232 totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24), 39233 totalHours: Math.floor(this.totalSecsLeft / 60 / 60), 39234 totalMinutes: Math.floor(this.totalSecsLeft / 60), 39235 totalSeconds: this.totalSecsLeft 39236 }; 39237 if (!this.options.elapse && this.totalSecsLeft === 0) { 39238 this.stop(); 39239 this.dispatchEvent("finish"); 39240 } else { 39241 this.dispatchEvent("update"); 39242 } 39243 }, 39244 dispatchEvent: function(eventName) { 39245 var event = $.Event(eventName + ".countdown"); 39246 event.finalDate = this.finalDate; 39247 event.elapsed = this.elapsed; 39248 event.offset = $.extend({}, this.offset); 39249 event.strftime = strftime(this.offset); 39250 this.$el.trigger(event); 39251 } 39252 }); 39253 $.fn.countdown = function() { 39254 var argumentsArray = Array.prototype.slice.call(arguments, 0); 39255 return this.each(function() { 39256 var instanceNumber = $(this).data("countdown-instance"); 39257 if (instanceNumber !== undefined) { 39258 var instance = instances[instanceNumber], method = argumentsArray[0]; 39259 if (Countdown.prototype.hasOwnProperty(method)) { 39260 instance[method].apply(instance, argumentsArray.slice(1)); 39261 } else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) { 39262 instance.setFinalDate.call(instance, method); 39263 instance.start(); 39264 } else { 39265 $.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method)); 39266 } 39267 } else { 39268 new Countdown(this, argumentsArray[0], argumentsArray[1]); 39269 } 39270 }); 39271 }; 39272}); 39273 39274!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; 39275function getStyles(config){ 39276 // 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;
39276left: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+"}" 39277}; 39278 var ShareUtils; 39279 39280if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 39281 Object.defineProperty(HTMLElement.prototype, "classList", { 39282 get: function() { 39283 var ret, self, update; 39284 update = function(fn) { 39285 return function(value) { 39286 var classes, index; 39287 classes = self.className.split(/\s+/); 39288 index = classes.indexOf(value); 39289 fn(classes, index, value); 39290 self.className = classes.join(" "); 39291 }; 39292 }; 39293 self = this; 39294 ret = { 39295 add: update(function(classes, index, value) { 39296 ~index || classes.push(value); 39297 }), 39298 remove: update(function(classes, index) { 39299 ~index && classes.splice(index, 1); 39300 }), 39301 toggle: update(function(classes, index, value) { 39302 if (~index) { 39303 classes.splice(index, 1); 39304 } else { 39305 classes.push(value); 39306 } 39307 }), 39308 contains: function(value) { 39309 return !!~self.className.split(/\s+/).indexOf(value); 39310 }, 39311 item: function(i) { 39312 return self.className.split(/\s+/)[i] || null; 39313 } 39314 }; 39315 Object.defineProperty(ret, "length", { 39316 get: function() { 39317 return self.className.split(/\s+/).length; 39318 } 39319 }); 39320 return ret; 39321 } 39322 }); 39323} 39324 39325String.prototype.to_rfc3986 = function() { 39326 var tmp; 39327 tmp = encodeURIComponent(this); 39328 return tmp.replace(/[!'()*]/g, function(c) { 39329 return "%" + c.charCodeAt(0).toString(16); 39330 }); 39331}; 39332 39333ShareUtils = (function() { 39334 function ShareUtils() {} 39335 39336 ShareUtils.prototype.extend = function(to, from, overwrite) { 39337 var hasProp, prop; 39338 for (prop in from) { 39339 hasProp = to[prop] !== undefined; 39340 if (hasProp && typeof from[prop] === "object") { 39341 this.extend(to[prop], from[prop], overwrite); 39342 } else { 39343 if (overwrite || !hasProp) { 39344 to[prop] = from[prop]; 39345 } 39346 } 39347 } 39348 }; 39349 39350 ShareUtils.prototype.hide = function(el) { 39351 return el.style.display = "none"; 39352 }; 39353 39354 ShareUtils.prototype.show = function(el) { 39355 return el.style.display = "block"; 39356 }; 39357 39358 ShareUtils.prototype.has_class = function(el, class_name) { 39359 return el.classList.contains(class_name); 39360 }; 39361 39362 ShareUtils.prototype.add_class = function(el, class_name) { 39363 return el.classList.add(class_name); 39364 }; 39365 39366 ShareUtils.prototype.remove_class = function(el, class_name) { 39367 return el.classList.remove(class_name); 39368 }; 39369 39370 ShareUtils.prototype.is_encoded = function(str) { 39371 str = str.to_rfc3986(); 39372 return decodeURIComponent(str) !== str; 39373 }; 39374 39375 ShareUtils.prototype.encode = function(str) { 39376 if (typeof str === "undefined" || this.is_encoded(str)) { 39377 return str; 39378 } else { 39379 return str.to_rfc3986(); 39380 } 39381 }; 39382 39383 ShareUtils.prototype.popup = function(url, params) { 39384 var k, popup, qs, v; 39385 if (params == null) { 39386 params = {}; 39387 } 39388 popup = { 39389 width: 500, 39390 height: 350 39391 }; 39392 popup.top = (screen.height / 2) - (popup.height / 2); 39393 popup.left = (screen.width / 2) - (popup.width / 2); 39394 qs = ((function() { 39395 var _results; 39396 _results = []; 39397 for (k in params) { 39398 v = params[k]; 39399 _results.push("" + k + "=" + (this.encode(v))); 39400 } 39401 return _results; 39402 }).call(this)).join('&'); 39403 if (qs) { 39404 qs = "?" + qs; 39405 } 39406 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="
39406+ popup.width + ",height=" + popup.height); 39407 }; 39408 39409 return ShareUtils; 39410 39411})(); 39412var Share, 39413 __hasProp = {}.hasOwnProperty, 39414 __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; }; 39415 39416Share = (function(_super) { 39417 __extends(Share, _super); 39418 39419 function Share(element, options) { 39420 this.element = element; 39421 this.el = { 39422 head: document.getElementsByTagName('head')[0], 39423 body: document.getElementsByTagName('body')[0] 39424 }; 39425 this.config = { 39426 enabled_networks: 0, 39427 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 39428 url: window.location.href.replace("&", "%26"), 39429 caption: null, 39430 title: this.default_title(), 39431 image: this.default_image(), 39432 description: this.default_description(), 39433 ui: { 39434 flyout: 'top center', 39435 button_text: 'Share', 39436 button_font: true, 39437 icon_font: true 39438 }, 39439 networks: { 39440 twitter: { 39441 enabled: true, 39442 url: null, 39443 title: null, 39444 description: null 39445 }, 39446 facebook: { 39447 enabled: true, 39448 load_sdk: true, 39449 url: null, 39450 app_id: null, 39451 title: null, 39452 caption: null, 39453 description: null, 39454 image: null 39455 }, 39456 threads: { 39457 enabled: true, 39458 url: null, 39459 title: null, 39460 description: null 39461 }, 39462 bluesky: { 39463 enabled: true, 39464 url: null, 39465 title: null, 39466 description: null 39467 }, 39468 pinterest: { 39469 enabled: true, 39470 url: null, 39471 image: null, 39472 description: null 39473 }, 39474 reddit: { 39475 enabled: true, 39476 url: null, 39477 title: null 39478 }, 39479 linkedin: { 39480 enabled: true, 39481 url: null, 39482 title: null, 39483 description: null 39484 }, 39485 xing: { 39486 enabled: true, 39487 url: null, 39488 title: null, 39489 image: null, 39490 description: null 39491 }, 39492 whatsapp: { 39493 enabled: true, 39494 title: null, 39495 url: null 39496 }, 39497 email: { 39498 enabled: true, 39499 title: null, 39500 description: null, 39501 url: null 39502 } 39503 } 39504 }; 39505 this.setup(element, options); 39506 return this; 39507 } 39508 39509 Share.prototype.setup = function(element, opts) { 39510 var index, instance, instances, _i, _len; 39511 instances = document.querySelectorAll(element); 39512 this.extend(this.config, opts, true); 39513 this.set_global_configuration(); 39514 this.normalize_network_configuration(); 39515 if (this.config.ui.icon_font) { 39516 this.inject_icons(); 39517 } 39518 if (this.config.ui.button_font) { 39519 this.inject_fonts(); 39520 } 39521 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 39522 this.inject_facebook_sdk(); 39523 } 39524 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 39525 instance = instances[index]; 39526 this.setup_instance(element, index); 39527 } 39528 }; 39529 39530 Share.prototype.setup_instance = function(element, index) { 39531 var button, instance, label, network, networks, _i, _len, _results, 39532 _this = this; 39533 instance = document.querySelectorAll(element)[index]; 39534 this.hide(instance); 39535 this.add_class(instance, "sharer-" + index); 39536 instance = document.querySelectorAll(element)[index]; 39537 this.inject_css(instance); 39538 this.inject_html(instance); 39539 this.show(instance); 39540 label = instance.getElementsByTagName("label")[0]; 39541 button = instance.getElementsByClassName("social")[0]; 39542 networks = instance.getElementsByTagName('li'); 39543 this.add_class(button, "networks-" + this.config.enabled_networks); 39544 label.addEventListener("click", function() { 39545 return _this.event_toggle(button); 39546 }); 39547 _this = this; 39548 _results = []; 39549 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 39550 network = networks[index]; 39551 _results.push(network.addEventListener("click", function() { 39552 _this.event_network(instance, this); 39553 return _this.event_close(button); 39554 })); 39555 } 39556 return _results; 39557 }; 39558 39559 Share.prototype.event_toggle = function(button) { 39560 if (this.has_class(button, "active")) { 39561 return this.event_close(button); 39562 } else { 39563 return this.event_open(button); 39564 } 39565 }; 39566 39567 Share.prototype.event_open = function(button) { 39568 if (this.has_class(button, "load")) { 39569 this.remove_class(button, "load"); 39570 } 39571 return this.add_class(button, "active"); 39572 }; 39573 39574 Share.prototype.event_close = function(button) { 39575 return this.remove_class(button, "active"); 39576 }; 39577 39578 Share.prototype.event_network = function(instance, network) { 39579 var name; 39580 name = network.getAttribute("data-network"); 39581 this.hook("before", name, instance);
39582 this["network_" + name](); 39583 return this.hook("after", name, instance); 39584 }; 39585 39586 Share.prototype.open = function() { 39587 return this["public"]("open"); 39588 }; 39589 39590 Share.prototype.close = function() { 39591 return this["public"]("close"); 39592 }; 39593 39594 Share.prototype.toggle = function() { 39595 return this["public"]("toggle"); 39596 }; 39597 39598 Share.prototype["public"] = function(action) { 39599 var button, index, instance, _i, _len, _ref, _results; 39600 _ref = document.querySelectorAll(this.element); 39601 _results = []; 39602 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 39603 instance = _ref[index]; 39604 button = instance.getElementsByClassName("social")[0]; 39605 _results.push(this["event_" + action](button)); 39606 } 39607 return _results; 39608 }; 39609 39610 Share.prototype.network_facebook = function() { 39611 if (this.config.networks.facebook.load_sdk) { 39612 if (!window.FB) { 39613 return console.error("The Facebook JS SDK hasn't loaded yet."); 39614 } 39615 return FB.ui({ 39616 method: 'feed', 39617 name: this.config.networks.facebook.title, 39618 link: this.config.networks.facebook.url, 39619 picture: this.config.networks.facebook.image, 39620 caption: this.config.networks.facebook.caption, 39621 description: this.config.networks.facebook.description 39622 }); 39623 } else { 39624 return this.popup('https://www.facebook.com/sharer/sharer.php', { 39625 u: this.config.networks.facebook.url 39626 }); 39627 } 39628 }; 39629 39630 Share.prototype.network_threads = function() { 39631 return this.popup('https://threads.net/intent/post', { 39632 text: this.config.networks.threads.title, 39633 url: this.config.networks.threads.url 39634 }); 39635 }; 39636 39637 Share.prototype.network_bluesky = function() { 39638 return this.popup('https://bsky.app/intent/compose', { 39639 text: this.config.networks.bluesky.title + ' ' + this.config.networks.bluesky.url 39640 }); 39641 }; 39642 39643 Share.prototype.network_twitter = function() { 39644 return this.popup('https://twitter.com/intent/tweet', { 39645 text: this.config.networks.twitter.title, 39646 url: this.config.networks.twitter.url 39647 }); 39648 }; 39649 39650 Share.prototype.network_pinterest = function() { 39651 return this.popup('https://www.pinterest.com/pin/create/button', { 39652 url: this.config.networks.pinterest.url, 39653 media: this.config.networks.pinterest.image, 39654 description: this.config.networks.pinterest.description 39655 }); 39656 }; 39657 39658 Share.prototype.network_linkedin = function() { 39659 return this.popup('https://www.linkedin.com/shareArticle', { 39660 url: this.config.networks.linkedin.url, 39661 title: this.config.networks.linkedin.title, 39662 summary: this.config.networks.linkedin.description 39663 }); 39664 } 39665 39666 Share.prototype.network_xing = function() { 39667 return this.popup('https://www.xing.com/spi/shares/new', { 39668 url: this.config.networks.xing.url, 39669 image: this.config.networks.xing.image, 39670 title: this.config.networks.xing.title, 39671 summary: this.config.networks.xing.description 39672 }); 39673 } 39674 39675 Share.prototype.network_whatsapp = function() { 39676 return this.popup('https://api.whatsapp.com/send', { 39677 text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url, 39678 }); 39679 } 39680 39681 Share.prototype.network_email = function() { 39682 return this.popup('mailto:', { 39683 subject: this.config.networks.email.title, 39684 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 39685 }); 39686 }; 39687 39688 Share.prototype.inject_icons = function() { 39689 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 39690 }; 39691 39692 Share.prototype.inject_fonts = function() { 39693 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 39694 }; 39695 39696 Share.prototype.inject_stylesheet = function(url) { 39697 var link; 39698 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 39699 link = document.createElement("link"); 39700 link.setAttribute("rel", "stylesheet"); 39701 link.setAttribute("href", url); 39702 return this.el.head.appendChild(link); 39703 } 39704 }; 39705 39706 Share.prototype.inject_css = function(instance) { 39707 var css, meta, selector, style; 39708 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 39709 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 39710 this.config.selector = selector; 39711 css = getStyles(this.config); 39712 style = document.createElement("style"); 39713 style.type = "text/css"; 39714 if (style.styleSheet) { 39715 style.styleSheet.cssText = css; 39716 } else { 39717 style.appendChild(document.createTextNode(css)); 39718 } 39719 this.el.head.appendChild(style); 39720 delete this.config.selector; 39721 meta = document.createElement("meta"); 39722 meta.setAttribute("name", "sharer" + selector); 39723 return this.el.head.appendChild(meta); 39724 } 39725 }; 39726 39727 Share.prototype.inject_html = function(instance) { 39728 // 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>"; 39729 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>"; 39730 }; 39731 39732 Share.prototype.inject_facebook_sdk = function() { 39733 var fb_root, script; 39734 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 39735 script = document.createElement("script"); 39736 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')"; 39737 fb_root = document.createElement("div"); 39738 fb_root.id = "fb-root"; 39739 this.el.body.appendChild(fb_root); 39740 return this.el.body.appendChild(script); 39741 } 39742 }; 39743 39744 Share.prototype.hook = function(type, network, instance) { 39745 var fn, opts; 39746 fn = this.config.networks[network][type]; 39747 if (typeof fn === "function") { 39748 opts = fn.call(this.config.networks[network], instance); 39749 if (opts !== void 0) { 39750 opts = this.normalize_filter_config_updates(opts); 39751 this.extend(this.config.networks[network], opts, true); 39752 this.normalize_network_configuration(); 39753 } 39754 } 39755 }; 39756 39757 Share.prototype.default_title = function() { 39758 var content; 39759 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 39760 return encodeURIComponent(content.getAttribute('content')); 39761 } else if (content = document.querySelector('title')) { 39762 return encodeURIComponent(content.innerText); 39763 } 39764 }; 39765 39766 Share.prototype.default_image = function() { 39767 var content; 39768 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 39769 return content.getAttribute('content'); 39770 } 39771 }; 39772 39773 Share.prototype.default_description = function() { 39774 var content; 39775 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 39776 return encodeURIComponent(content.getAttribute('content')); 39777 } else { 39778 return ''; 39779 } 39780 }; 39781 39782 Share.prototype.set_global_configuration = function() { 39783 var display, network, option, options, _ref, _results; 39784 _ref = this.config.networks; 39785 _results = []; 39786 for (network in _ref) { 39787 options = _ref[network]; 39788 for (option in options) { 39789 if (this.config.networks[network][option] == null) { 39790 this.config.networks[network][option] = this.config[option]; 39791 } 39792 } 39793 if (this.config.networks[network].enabled) { 39794 display = 'block'; 39795 this.config.enabled_networks += 1; 39796 } else { 39797 display = 'none'; 39798 } 39799 _results.push(this.config.networks[network].display = display); 39800 } 39801 return _results; 39802 }; 39803 39804 Share.prototype.normalize_network_configuration = function() { 39805 if (!this.config.networks.facebook.app_id) { 39806 this.config.networks.facebook.load_sdk = false;
39807 } 39808 if (!this.is_encoded(this.config.networks.twitter.description)) { 39809 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 39810 } 39811 if (typeof this.config.networks.facebook.app_id === 'number') { 39812 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 39813 } 39814 }; 39815 39816 Share.prototype.normalize_filter_config_updates = function(opts) { 39817 if (this.config.networks.facebook.app_id !== opts.app_id) { 39818 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."); 39819 delete opts.app_id; 39820 } 39821 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 39822 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."); 39823 delete opts.app_id; 39824 } 39825 return opts; 39826 }; 39827 39828 return Share; 39829 39830})(ShareUtils); 39831 return Share; 39832}); 39833 39834// Generated by CoffeeScript 1.9.2 39835 39836// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 39837 39838(function() { 39839 var $, win; 39840 39841 $ = this.jQuery || window.jQuery; 39842 39843 win = $(window); 39844 39845 $.fn.stick_in_parent = function(opts) { 39846 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 39847 if (opts == null) { 39848 opts = {}; 39849 } 39850 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; 39851 if (offset_top == null) { 39852 offset_top = 0; 39853 } 39854 if (parent_selector == null) { 39855 parent_selector = void 0; 39856 } 39857 if (inner_scrolling == null) { 39858 inner_scrolling = true; 39859 } 39860 if (sticky_class == null) { 39861 sticky_class = "is_stuck"; 39862 } 39863 doc = $(document); 39864 if (enable_bottoming == null) { 39865 enable_bottoming = true; 39866 } 39867 outer_width = function(el) { 39868 var _el, computed, w; 39869 if (window.getComputedStyle) { 39870 _el = el[0]; 39871 computed = window.getComputedStyle(el[0]); 39872 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 39873 if (computed.getPropertyValue("box-sizing") !== "border-box") { 39874 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 39875 } 39876 return w; 39877 } else { 39878 return el.outerWidth(true); 39879 } 39880 }; 39881 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 39882 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 39883 if (elm.data("sticky_kit")) { 39884 return; 39885 } 39886 elm.data("sticky_kit", true); 39887 last_scroll_height = doc.height(); 39888 parent = elm.parent(); 39889 if (parent_selector != null) { 39890 parent = parent.closest(parent_selector); 39891 } 39892 if (!parent.length) { 39893 throw "failed to find stick parent"; 39894 } 39895 fixed = false; 39896 bottomed = false; 39897 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 39898 if (spacer) { 39899 spacer.css('position', elm.css('position')); 39900 } 39901 recalc = function() { 39902 var border_top, padding_top, restore; 39903 if (detached) { 39904 return; 39905 } 39906 last_scroll_height = doc.height(); 39907 border_top = parseInt(parent.css("border-top-width"), 10); 39908 padding_top = parseInt(parent.css("padding-top"), 10); 39909 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 39910 parent_top = parent.offset().top + border_top + padding_top; 39911 parent_height = parent.height(); 39912 if (fixed) { 39913 fixed = false;
vendor: 6,068 bytes, lines 39914-40108
39914 bottomed = false; 39915 if (manual_spacer == null) { 39916 elm.insertAfter(spacer); 39917 spacer.detach(); 39918 } 39919 elm.css({ 39920 position: "", 39921 top: "", 39922 width: "", 39923 bottom: "" 39924 }).removeClass(sticky_class); 39925 restore = true; 39926 } 39927 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 39928 height = elm.outerHeight(true); 39929 el_float = elm.css("float"); 39930 if (spacer) { 39931 spacer.css({ 39932 width: outer_width(elm), 39933 height: height, 39934 display: elm.css("display"), 39935 "vertical-align": elm.css("vertical-align"), 39936 "float": el_float 39937 }); 39938 } 39939 if (restore) { 39940 return tick(); 39941 } 39942 }; 39943 recalc(); 39944 if (height === parent_height) { 39945 return; 39946 } 39947 last_pos = void 0; 39948 offset = offset_top; 39949 recalc_counter = recalc_every; 39950 tick = function() { 39951 var css, delta, recalced, scroll, will_bottom, win_height; 39952 if (detached) { 39953 return; 39954 } 39955 recalced = false; 39956 if (recalc_counter != null) { 39957 recalc_counter -= 1; 39958 if (recalc_counter <= 0) { 39959 recalc_counter = recalc_every; 39960 recalc(); 39961 recalced = true; 39962 } 39963 } 39964 if (!recalced && doc.height() !== last_scroll_height) { 39965 recalc(); 39966 recalced = true; 39967 } 39968 scroll = win.scrollTop(); 39969 if (last_pos != null) { 39970 delta = scroll - last_pos; 39971 } 39972 last_pos = scroll; 39973 if (fixed) { 39974 if (enable_bottoming) { 39975 will_bottom = scroll + height + offset > parent_height + parent_top; 39976 if (bottomed && !will_bottom) { 39977 bottomed = false; 39978 elm.css({ 39979 position: "fixed", 39980 bottom: "", 39981 top: offset 39982 }).trigger("sticky_kit:unbottom"); 39983 } 39984 } 39985 if (scroll < top) { 39986 fixed = false; 39987 offset = offset_top; 39988 if (manual_spacer == null) { 39989 if (el_float === "left" || el_float === "right") { 39990 elm.insertAfter(spacer); 39991 } 39992 spacer.detach(); 39993 } 39994 css = { 39995 position: "", 39996 width: "", 39997 top: "" 39998 }; 39999 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 40000 } 40001 if (inner_scrolling) { 40002 win_height = win.height(); 40003 if (height + offset_top > win_height) { 40004 if (!bottomed) { 40005 offset -= delta; 40006 offset = Math.max(win_height - height, offset); 40007 offset = Math.min(offset_top, offset); 40008 if (fixed) { 40009 elm.css({ 40010 top: offset + "px" 40011 }); 40012 } 40013 } 40014 } 40015 } 40016 } else { 40017 if (scroll > top) { 40018 fixed = true; 40019 css = { 40020 position: "fixed", 40021 top: offset 40022 }; 40023 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 40024 elm.css(css).addClass(sticky_class); 40025 if (manual_spacer == null) { 40026 elm.after(spacer); 40027 if (el_float === "left" || el_float === "right") { 40028 spacer.append(elm); 40029 } 40030 } 40031 elm.trigger("sticky_kit:stick"); 40032 } 40033 } 40034 if (fixed && enable_bottoming) { 40035 if (will_bottom == null) { 40036 will_bottom = scroll + height + offset > parent_height + parent_top; 40037 } 40038 if (!bottomed && will_bottom) { 40039 bottomed = true; 40040 if (parent.css("position") === "static") { 40041 parent.css({ 40042 position: "relative" 40043 }); 40044 } 40045 return elm.css({ 40046 position: "absolute", 40047 bottom: padding_bottom, 40048 top: "auto" 40049 }).trigger("sticky_kit:bottom"); 40050 } 40051 } 40052 }; 40053 recalc_and_tick = function() { 40054 recalc(); 40055 return tick(); 40056 }; 40057 detach = function() { 40058 detached = true; 40059 win.off("touchmove", tick); 40060 win.off("scroll", tick); 40061 win.off("resize", recalc_and_tick); 40062 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 40063 elm.off("sticky_kit:detach", detach); 40064 elm.removeData("sticky_kit"); 40065 elm.css({ 40066 position: "", 40067 bottom: "", 40068 top: "", 40069 width: "" 40070 }); 40071 parent.position("position", ""); 40072 if (fixed) { 40073 if (manual_spacer == null) { 40074 if (el_float === "left" || el_float === "right") { 40075 elm.insertAfter(spacer); 40076 } 40077 spacer.remove(); 40078 } 40079 return elm.removeClass(sticky_class); 40080 } 40081 }; 40082 win.on("touchmove", tick); 40083 win.on("scroll", tick); 40084 win.on("resize", recalc_and_tick); 40085 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 40086 elm.on("sticky_kit:detach", detach); 40087 return setTimeout(tick, 0); 40088 }; 40089 for (i = 0, len = this.length; i < len; i++) { 40090 elm = this[i]; 40091 fn($(elm)); 40092 } 40093 return this; 40094 }; 40095 40096}).call(this); 40097/* ========================================================================== 40098 * bootstrap-tab-history.js 40099 * Author: Michael Narayan <[email protected]> 40100 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 40101 * ========================================================================== 40102 * Licensed under the Apache License, Version 2.0 (the "License"); you may 40103 * not use this file except in compliance with the License. You may obtain a 40104 * copy of the License at 40105 * 40106 * http://www.apache.org/licenses/LICENSE-2.0 40107 * 40108 * Unless required by applicable law or agreed to in writing, softw
40108are 40109 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 40110 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 40111 * License for the specific language governing permissions and limitations 40112 * under the License. 40113 * ========================================================================== */ 40114 40115/* ========================================================================== */ 40116/* JSHint directives */ 40117/* */ 40118/* global BootstrapTabHistory: true */ 40119/* */ 40120/* global document */ 40121/* global jQuery */ 40122/* global history */ 40123/* global window */ 40124/* ========================================================================== */ 40125 40126/** 40127 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 40128 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 40129 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 40130 * 40131 * See the README for additional information. 40132 * 40133 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 40134 */ 40135 40136BootstrapTabHistory = { 40137 options: { 40138 /** 40139 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 40140 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 40141 * 40142 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 40143 * 40144 * @public 40145 * @type {?number} 40146 */ 40147 defaultAnchorYOffset: 0, 40148 /** 40149 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 40150 * 40151 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 40152 * 40153 * @public 40154 * @type {string} 40155 */ 40156 defaultChanger: 'replace', 40157 /** 40158 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 40159 * `null` is passed as the third parameter to these calls. 40160 * 40161 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 40162 * 40163 * @public 40164 * @type {boolean} 40165 */ 40166 defaultUpdateURL: false, 40167 /** 40168 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 40169 * load. 40170 * 40171 * @public 40172 * @type {boolean} 40173 */ 40174 showTabsBasedOnAnchor: true 40175 } 40176}; 40177 40178(function () { 40179 'use strict'; 40180 40181 jQuery(function () { 40182 if(history && history.pushState && history.replaceState) { 40183 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 40184 40185 if(bootstrapTabHistory) { 40186 showTabsBasedOnState(bootstrapTabHistory); 40187 } else { 40188 showTabsBasedOnAnchor(); 40189 } 40190 40191 backfillHistoryState(); 40192 40193 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 40194 jQuery(window).on('popstate', onPopState); 40195 } else { 40196 showTabsBasedOnAnchor(); 40197 } 40198 }); 40199 40200 /** 40201 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 40202 * 40203 * @type {boolean} 40204 */ 40205 var showingTabsBasedOnState = false; 40206 40207 /** 40208 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 40209 * `history.back` handling when `data-tab-history-update-url` is true. 40210 */ 40211 function backfillHistoryState() { 40212 var newState = null; 40213 40214 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 40215 var $activeTabElement = jQuery(this); 40216 var selector = getTabSelector($activeTabElement); 40217 40218 if(selector) { 40219 var tabGroup = getTabGroup($activeTabElement); 40220 40221 if(tabGroup) { 40222 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 40223 } 40224 } 40225 }); 40226 40227 if(newState) { 40228 history.replaceState(newState, '', null); 40229 } 40230 } 40231 40232 /** 40233 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 40234 * said bootstrapTabHistory attribute. 40235 * 40236 * @param {?object} existingState 40237 * @param {!string} tabGroup 40238 * @param {!string} selector 40239 * @returns {!object} 40240 */ 40241 function createNewHistoryState(existingState, tabGroup, selector) { 40242 // Clone history.state and ensure it has a bootstrapTabHistory entry. 40243 var newState = jQuery.extend(true, {}, existingState, { 40244 bootstrapTabHistory: {} 40245 }); 40246 40247 newState.bootstrapTabHistory[tabGroup] = selector; 40248 40249 return newState; 40250 } 40251 40252 /** 40253 * @param {jQuery} $tab
40254 * @returns {?string} 40255 */ 40256 function getTabGroup($tab) { 40257 return parseTruthyAttributeValue($tab.data('tab-history')); 40258 } 40259 40260 /** 40261 * @param {jQuery} $tab 40262 * @returns {?string} 40263 */ 40264 function getTabSelector($tab) { 40265 return $tab.data('target') || $tab.attr('href'); 40266 } 40267 40268 /** 40269 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 40270 * 40271 * @param {jQuery.Event} shownEvt 40272 */ 40273 function onShownTab(shownEvt) { 40274 if(!showingTabsBasedOnState) { 40275 var $activatedTab = jQuery(shownEvt.target); 40276 if ( $activatedTab.hasClass('panel-collapse') ) 40277 $activatedTab = $activatedTab.closest('.panel').find('a'); 40278 var selector = getTabSelector($activatedTab); 40279 40280 if(selector) { 40281 var tabGroup = getTabGroup($activatedTab); 40282 40283 if(tabGroup) { 40284 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 40285 var newState = createNewHistoryState(history.state, tabGroup, selector); 40286 var updateURL = (function ($activatedTab) { 40287 if(selector[0] === '#') { 40288 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 40289 40290 if(elementUpdateURLOption === undefined) { 40291 return BootstrapTabHistory.options.defaultUpdateURL; 40292 } else { 40293 return elementUpdateURLOption; 40294 } 40295 } else { 40296 return false; 40297 } 40298 })($activatedTab); 40299 40300 switch(historyChanger) { 40301 case 'push': 40302 history.pushState(newState, '', updateURL ? selector : null); 40303 break; 40304 case 'replace': 40305 history.replaceState(newState, '', updateURL ? selector : null); 40306 break; 40307 default: 40308 throw new Error('Unknown tab-history-changer: ' + historyChanger); 40309 } 40310 } 40311 } 40312 } 40313 } 40314 40315 /** 40316 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 40317 */ 40318 function onPopState() { 40319 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 40320 40321 if(bootstrapTabHistory) { 40322 showTabsBasedOnState(bootstrapTabHistory); 40323 } 40324 } 40325 40326 /** 40327 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 40328 * 40329 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 40330 * 40331 * @param {*} value 40332 * @returns {*} 40333 */ 40334 function parseTruthyAttributeValue(value) { 40335 if(value) { 40336 return value; 40337 } else if(value === '') { 40338 return true; 40339 } else { 40340 return value; 40341 } 40342 } 40343 40344 /** 40345 * Show tabs based upon the anchor component of `window.location`. 40346 */ 40347 function showTabsBasedOnAnchor() { 40348 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 40349 var anchor = window.location && window.location.hash; 40350 40351 if(anchor) { 40352 var $tabElement = showTabForSelector(anchor); 40353 40354 if($tabElement && window.addEventListener && window.removeEventListener) { 40355 var anchorYOffset = (function ($tabElement) { 40356 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 40357 40358 if(elementSetting === undefined) { 40359 return BootstrapTabHistory.options.defaultAnchorYOffset; 40360 } else { 40361 return elementSetting; 40362 } 40363 })($tabElement); 40364 40365 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 40366 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 40367 // `history.state` object should have been used (unless the browser did not support the modern History API). 40368 if(anchorYOffset || anchorYOffset === 0) { 40369 var scrollListener = function resetAnchorScroll () { 40370 window.removeEventListener('scroll', scrollListener); 40371 window.scrollTo(0, anchorYOffset); 40372 }; 40373 40374 window.addEventListener('scroll', scrollListener); 40375 } 40376 } 40377 } 40378 } 40379 } 40380 40381 /** 40382 * Show a tab which corresponds to the provided selector. 40383 * 40384 * @param {string} selector - A CSS selector. 40385 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 40386 */ 40387 function showTabForSelector(selector) { 40388 var $tabElement = (function (selector) { 40389 var $ret = null; 40390 40391 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 40392 var $potentialTab = jQuery(this); 40393 40394 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 40395 $ret = $potentialTab; 40396 return false;
vendor: 43,483 bytes, lines 40397-41613
40397 } else { 40398 return null; 40399 } 40400 }); 40401 40402 return $ret; 40403 })(selector); 40404 40405 if($tabElement) { 40406 if ( !$tabElement.parent().hasClass('active') ) { 40407 $tabElement.trigger('click'); 40408 } 40409 //$tabElement.tab('show'); 40410 } 40411 40412 return $tabElement; 40413 } 40414 40415 /** 40416 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 40417 * 40418 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 40419 */ 40420 function showTabsBasedOnState(bootstrapTabHistory) { 40421 showingTabsBasedOnState = true; 40422 40423 try { 40424 for(var k in bootstrapTabHistory) { 40425 if(bootstrapTabHistory.hasOwnProperty(k)) { 40426 showTabForSelector(bootstrapTabHistory[k]); 40427 } 40428 } 40429 } finally { 40430 showingTabsBasedOnState = false; 40431 } 40432 } 40433})(); 40434 40435/*! 40436 * justifiedGallery - v3.8.1 40437 * http://miromannino.github.io/Justified-Gallery/ 40438 * Copyright (c) 2020 Miro Mannino 40439 * Licensed under the MIT license. 40440 */ 40441(function (factory) { 40442 if (typeof define === 'function' && define.amd) { 40443 // AMD. Register as an anonymous module. 40444 define(['jquery'], factory); 40445 } else if (typeof module === 'object' && module.exports) { 40446 // Node/CommonJS 40447 module.exports = function (root, jQuery) { 40448 if (jQuery === undefined) { 40449 // require('jQuery') returns a factory that requires window to 40450 // build a jQuery instance, we normalize how we use modules 40451 // that require this pattern but the window provided is a noop 40452 // if it's defined (how jquery works) 40453 if (typeof window !== 'undefined') { 40454 jQuery = require('jquery'); 40455 } 40456 else { 40457 jQuery = require('jquery')(root); 40458 } 40459 } 40460 factory(jQuery); 40461 return jQuery; 40462 }; 40463 } else { 40464 // Browser globals 40465 factory(jQuery); 40466 } 40467}(function ($) { 40468 40469 /** 40470 * Justified Gallery controller constructor 40471 * 40472 * @param $gallery the gallery to build 40473 * @param settings the settings (the defaults are in JustifiedGallery.defaults) 40474 * @constructor 40475 */ 40476 var JustifiedGallery = function ($gallery, settings) { 40477 40478 this.settings = settings; 40479 this.checkSettings(); 40480 40481 this.imgAnalyzerTimeout = null; 40482 this.entries = null; 40483 this.buildingRow = { 40484 entriesBuff: [], 40485 width: 0, 40486 height: 0, 40487 aspectRatio: 0 40488 }; 40489 this.lastFetchedEntry = null; 40490 this.lastAnalyzedIndex = -1; 40491 this.yield = { 40492 every: 2, // do a flush every n flushes (must be greater than 1) 40493 flushed: 0 // flushed rows without a yield 40494 }; 40495 this.border = settings.border >= 0 ? settings.border : settings.margins; 40496 this.maxRowHeight = this.retrieveMaxRowHeight(); 40497 this.suffixRanges = this.retrieveSuffixRanges(); 40498 this.offY = this.border; 40499 this.rows = 0; 40500 this.spinner = { 40501 phase: 0, 40502 timeSlot: 150, 40503 $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'), 40504 intervalId: null 40505 }; 40506 this.scrollBarOn = false; 40507 this.checkWidthIntervalId = null; 40508 this.galleryWidth = $gallery.width(); 40509 this.$gallery = $gallery; 40510 40511 }; 40512 40513 /** @returns {String} the best suffix given the width and the height */ 40514 JustifiedGallery.prototype.getSuffix = function (width, height) { 40515 var longestSide, i; 40516 longestSide = (width > height) ? width : height; 40517 for (i = 0; i < this.suffixRanges.length; i++) { 40518 if (longestSide <= this.suffixRanges[i]) { 40519 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 40520 } 40521 } 40522 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 40523 }; 40524 40525 /** 40526 * Remove the suffix from the string 40527 * 40528 * @returns {string} a new string without the suffix 40529 */ 40530 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 40531 return str.substring(0, str.length - suffix.length); 40532 }; 40533 40534 /** 40535 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 40536 */ 40537 JustifiedGallery.prototype.endsWith = function (str, suffix) { 40538 return str.indexOf(suffix, str.length - suffix.length) !== -1; 40539 }; 40540 40541 /** 40542 * Get the used suffix of a particular url 40543 * 40544 * @param str 40545 * @returns {String} return the used suffix 40546 */ 40547 JustifiedGallery.prototype.getUsedSuffix = function (str) { 40548 for (var si in this.settings.sizeRangeSuffixes) { 40549 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 40550 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 40551 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 40552 } 40553 } 40554 return ''; 40555 }; 40556 40557 /** 40558 * Given an image src, with the width and the height, returns the new image src with the 40559 * best suffix to show the best quality thumbnail. 40560 * 40561 * @returns {String} the suffix to use 40562 */ 40563 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 40564 var newImageSrc; 40565 40566 if (this.settings.thumbnailPath) { 40567 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 40568 } else { 40569 var matchRes = imageSrc.match(this.settings.extension); 40570 var ext = (matchRes !== null) ? matchRes[0] : ''; 40571 newImageSrc = imageSrc.replace(this.settings.extension, ''); 40572 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc)); 40573 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 40574 } 40575 40576 return newImageSrc; 40577 }; 40578 40579 /** 40580 * Shows the images that is in the given entry 40581 * 40582 * @param $entry the entry 40583 * @param callback the callback that is called when the show animation is finished 40584 */ 40585 JustifiedGallery.prototype.showImg = function ($entry, callback) { 40586 if (this.settings.cssAnimation) { 40587 $entry.addClass('jg-entry-visible'); 40588 if (callback) callback(); 40589 } else { 40590 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 40591 $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 40592 } 40593 }; 40594 40595 /** 40596 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 40597 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 40598 * 40599 * @param $image the image to analyze 40600 * @returns {String} the extracted src 40601 */ 40602 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 40603 var imageSrc = $image.data('safe-src'); 40604 var imageSrcLoc = 'data-safe-src'; 40605 // Begin Uncode edit 40606 if (typeof imageSrc === 'undefined') { 40607 var imageCurrentSrc = $image[0].currentSrc; 40608 if (imageCurrentSrc) { 40609 imageSrc = imageCurrentSrc; 40610 } else { 40611 imageSrc = $image.attr('src'); 40612 } 40613 imageSrcLoc = 'src'; 40614 } 40615 // End Uncode edit 40616 $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method 40617 $image.data('jg.src', imageSrc); // this will change overtime 40618 $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method 40619 return imageSrc; 40620 }; 40621 40622 /** @returns {jQuery} the image in the given entry */ 40623 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 40624 var $img = $entry.find(this.settings.imgSelector); 40625 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 40626 return $img.length === 0 ? null : $img; 40627 }; 40628 40629 /** @returns {jQuery} the caption in the given entry */ 40630 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 40631 var $caption = $entry.find('> .jg-caption'); 40632 return $caption.length === 0 ? null : $caption; 40633 }; 40634 40635 /** 40636 * Display the entry 40637 * 40638 * @param {jQuery} $entry the entry to display 40639 * @param {int} x the x position where the entry must be positioned 40640 * @param y the y position where the entry must be positioned 40641 * @param imgWidth the image width 40642 * @param imgHeight the image height 40643 * @param rowHeight the row height of the row that owns the entry 40644 */ 40645 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 40646 $entry.width(imgWidth); 40647 $entry.height(Math.floor(rowHeight));//hacked by Uncode 40648 $entry.css('top', Math.floor(y));//hacked by Uncode 40649 $entry.css('left', x); 40650 40651 var $image = this.imgFromEntry($entry); 40652 if ($image !== null) { 40653 $image.css('width', imgWidth); 40654 $image.css('height', imgHeight); 40655 $image.css('margin-left', - imgWidth / 2); 40656 $image.css('margin-top', - imgHeight / 2); 40657 40658 // Image reloading for an high quality of thumbnails 40659 var imageSrc = $image.data('jg.src'); 40660 if (imageSrc) { 40661 imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 40662 40663 $image.one('error', function () { 40664 this.resetImgSrc($image); //revert to the original thumbnail 40665 }); 40666 40667 var loadNewImage = function () { 40668 // if (imageSrc !== newImageSrc) { 40669 $image.attr('src', imageSrc); 40670 // } 40671 }; 40672 40673 if ($entry.data('jg.loaded') === 'skipped' && imageSrc) { 40674 this.onImageEvent(imageSrc, (function() { 40675 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 40676 $entry.data('jg.loaded', true); 40677 }).bind(this)); 40678 } else { 40679 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 40680 } 40681 40682 } 40683 40684 } else { 40685 this.showImg($entry); 40686 } 40687 40688 this.displayEntryCaption($entry); 40689 }; 40690 40691 /** 40692 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 40693 * or the 'title' attributes. 40694 * 40695 * @param {jQuery} $entry the entry to process 40696 */ 40697 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 40698 var $image = this.imgFromEntry($entry); 40699 if ($image !== null && this.settings.captions) { 40700 var $imgCaption = this.captionFromEntry($entry); 40701 40702 // Create it if it doesn't exists 40703 if ($imgCaption === null) { 40704 var caption = $image.attr('alt'); 40705 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 40706 if (this.isValidCaption(caption)) { // Create only we found something 40707 $imgCaption = $('<div class="jg-caption">' + caption + '</div>'); 40708 $entry.append($imgCaption); 40709 $entry.data('jg.createdCaption', true); 40710 } 40711 } 40712 40713 // Create events (we check again the $imgCaption because it can be still inexistent) 40714 if ($imgCaption !== null) { 40715 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 40716 this.addCaptionEventsHandlers($entry); 40717 } 40718 } else { 40719 this.removeCaptionEventsHandlers($entry); 40720 } 40721 }; 40722 40723 /** 40724 * Validates the caption 40725 * 40726 * @param caption The caption that should be validated 40727 * @return {boolean} Validation result 40728 */ 40729 JustifiedGallery.prototype.isValidCaption = function (caption) { 40730 return (typeof caption !== 'undefined' && caption.length > 0); 40731 }; 40732 40733 /** 40734 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 40735 * It shows the caption using jQuery (or using CSS if it is configured so) 40736 * 40737 * @param {Event} eventObject the event object 40738 */ 40739 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 40740 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 40741 if (this.settings.cssAnimation) { 40742 $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden'); 40743 } else { 40744 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 40745 this.settings.captionSettings.visibleOpacity); 40746 } 40747 }; 40748 40749 /** 40750 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 40751 * It hides the caption using jQuery (or using CSS if it is configured so) 40752 * 40753 * @param {Event} eventObject the event object 40754 */ 40755 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 40756 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 40757 if (this.settings.cssAnimation) { 40758 $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden'); 40759 } else { 40760 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 40761 this.settings.captionSettings.nonVisibleOpacity); 40762 } 40763 }; 40764 40765 /** 40766 * Add the handlers of the entry for the caption 40767 * 40768 * @param $entry the entry to modify 40769 */ 40770 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 40771 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 40772 if (typeof captionMouseEvents === 'undefined') { 40773 captionMouseEvents = { 40774 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 40775 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 40776 }; 40777 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 40778 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 40779 $entry.data('jg.captionMouseEvents', captionMouseEvents); 40780 } 40781 }; 40782 40783 /** 40784 * Remove the handlers of the entry for the caption 40785 * 40786 * @param $entry the entry to modify 40787 */ 40788 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 40789 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 40790 if (typeof captionMouseEvents !== 'undefined') { 40791 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 40792 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 40793 $entry.removeData('jg.captionMouseEvents'); 40794 } 40795 }; 40796 40797 /** 40798 * Clear the building row data to be used for a new row 40799 */ 40800 JustifiedGallery.prototype.clearBuildingRow = function () { 40801 this.buildingRow.entriesBuff = []; 40802 this.buildingRow.aspectRatio = 0; 40803 this.buildingRow.width = 0; 40804 }; 40805 40806 /** 40807 * Justify the building row, preparing it to 40808 * 40809 * @param isLastRow 40810 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 40811 * @returns a boolean to know if the row has been justified or not 40812 */ 40813 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) { 40814 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 40815 var minHeight = 0; 40816 var availableWidth = this.galleryWidth - 2 * this.border - ( 40817 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 40818 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 40819 var defaultRowHeight = this.settings.rowHeight; 40820 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 40821 40822 //Skip the last row if we can't justify it and the lastRow == 'hide' 40823 if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) { 40824 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 40825 $entry = this.buildingRow.entriesBuff[i]; 40826 if (this.settings.cssAnimation) 40827 $entry.removeClass('jg-entry-visible'); 40828 else { 40829 $entry.stop().fadeTo(0, 0.1); 40830 $entry.find('> img, > a > img').fadeTo(0, 0); 40831 } 40832 } 40833 return -1; 40834 } 40835 40836 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 40837 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 40838 justify = false; 40839 40840 if (this.rows > 0) { 40841 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 40842 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 40843 } 40844 } 40845 40846 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 40847 $entry = this.buildingRow.entriesBuff[i]; 40848 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 40849 40850 if (justify) { 40851 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 40852 newImgH = rowHeight; 40853 } else { 40854 newImgW = defaultRowHeight * imgAspectRatio; 40855 newImgH = defaultRowHeight; 40856 } 40857 40858 availableWidth -= Math.round(newImgW); 40859 $entry.data('jg.jwidth', Math.round(newImgW)); 40860 $entry.data('jg.jheight', Math.ceil(newImgH)); 40861 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 40862 } 40863 40864 this.buildingRow.height = minHeight; 40865 return justify; 40866 }; 40867 40868 /** 40869 * Flush a row: justify it, modify the gallery height accordingly to the row height 40870 * 40871 * @param isLastRow 40872 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 40873 */ 40874 JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) { 40875 var settings = this.settings; 40876 var $entry, buildingRowRes, offX = this.border, i; 40877 40878 buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow); 40879 if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) { 40880 this.clearBuildingRow(); 40881 return; 40882 } 40883 40884 if (this.maxRowHeight) { 40885 if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight; 40886 } 40887 40888 //Align last (unjustified) row 40889 if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) { 40890 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 40891 40892 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 40893 $entry = this.buildingRow.entriesBuff[i]; 40894 availableWidth -= $entry.data('jg.jwidth'); 40895 } 40896 40897 if (settings.lastRow === 'center') 40898 offX += Math.round(availableWidth / 2); 40899 else if (settings.lastRow === 'right') 40900 offX += availableWidth; 40901 } 40902 40903 var lastEntryIdx = this.buildingRow.entriesBuff.length - 1; 40904 for (i = 0; i <= lastEntryIdx; i++) { 40905 $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i]; 40906 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 40907 offX += $entry.data('jg.jwidth') + settings.margins; 40908 } 40909 40910 //Gallery Height 40911 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 40912 this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight()); 40913 40914 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 40915 //Ready for a new row 40916 this.offY += this.buildingRow.height + settings.margins; 40917 this.rows += 1; 40918 this.clearBuildingRow(); 40919 this.settings.triggerEvent.call(this, 'jg.rowflush'); 40920 } 40921 }; 40922 40923 40924 // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221 40925 var galleryPrevStaticHeight = 0; 40926 40927 JustifiedGallery.prototype.rememberGalleryHeight = function () { 40928 galleryPrevStaticHeight = this.$gallery.height(); 40929 this.$gallery.height(galleryPrevStaticHeight); 40930 }; 40931 40932 // grow only 40933 JustifiedGallery.prototype.setGalleryTempHeight = function (height) { 40934 galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight); 40935 this.$gallery.height(galleryPrevStaticHeight); 40936 }; 40937 40938 JustifiedGallery.prototype.setGalleryFinalHeight = function (height) { 40939 galleryPrevStaticHeight = height; 40940 this.$gallery.height(height); 40941 }; 40942 40943 /** 40944 * Checks the width of the gallery container, to know if a new justification is needed 40945 */ 40946 JustifiedGallery.prototype.checkWidth = function () { 40947 this.checkWidthIntervalId = setInterval($.proxy(function () { 40948 40949 // if the gallery is not currently visible, abort. 40950 if (!this.$gallery.is(":visible")) return; 40951 40952 var galleryWidth = parseFloat(this.$gallery.width()); 40953 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 40954 this.galleryWidth = galleryWidth; 40955 this.rewind(); 40956 40957 this.rememberGalleryHeight(); 40958 40959 // Restart to analyze 40960 this.startImgAnalyzer(true); 40961 } 40962 }, this), this.settings.refreshTime); 40963 }; 40964 40965 /** 40966 * @returns {boolean} a boolean saying if the spinner is active or not 40967 */ 40968 JustifiedGallery.prototype.isSpinnerActive = function () { 40969 return this.spinner.intervalId !== null; 40970 }; 40971 40972 /** 40973 * @returns {int} the spinner height 40974 */ 40975 JustifiedGallery.prototype.getSpinnerHeight = function () { 40976 return this.spinner.$el.innerHeight(); 40977 }; 40978 40979 /** 40980 * Stops the spinner animation and modify the gallery height to exclude the spinner 40981 */ 40982 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 40983 clearInterval(this.spinner.intervalId); 40984 this.spinner.intervalId = null; 40985 this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight()); 40986 this.spinner.$el.detach(); 40987 }; 40988 40989 /** 40990 * Starts the spinner animation 40991 */ 40992 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 40993 var spinnerContext = this.spinner; 40994 var $spinnerPoints = spinnerContext.$el.find('span'); 40995 clearInterval(spinnerContext.intervalId); 40996 this.$gallery.append(spinnerContext.$el); 40997 this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 40998 spinnerContext.intervalId = setInterval(function () { 40999 if (spinnerContext.phase < $spinnerPoints.length) { 41000 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 41001 } else { 41002 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 41003 } 41004 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 41005 }, spinnerContext.timeSlot); 41006 }; 41007 41008 /** 41009 * Rewind the image analysis to start from the first entry. 41010 */ 41011 JustifiedGallery.prototype.rewind = function () { 41012 this.lastFetchedEntry = null; 41013 this.lastAnalyzedIndex = -1; 41014 this.offY = this.border; 41015 this.rows = 0; 41016 this.clearBuildingRow(); 41017 }; 41018 41019 /** 41020 * @returns {String} `settings.selector` rejecting spinner element 41021 */ 41022 JustifiedGallery.prototype.getSelectorWithoutSpinner = function () { 41023 return this.settings.selector + ', div:not(.jg-spinner)'; 41024 }; 41025 41026 /** 41027 * @returns {Array} all entries matched by `settings.selector` 41028 */ 41029 JustifiedGallery.prototype.getAllEntries = function () { 41030 var selector = this.getSelectorWithoutSpinner(); 41031 return this.$gallery.children(selector).toArray(); 41032 }; 41033 41034 /** 41035 * Update the entries searching it from the justified gallery HTML element 41036 * 41037 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 41038 * @returns {boolean} true if some entries has been founded 41039 */ 41040 JustifiedGallery.prototype.updateEntries = function (norewind) { 41041 var newEntries; 41042 41043 if (norewind && this.lastFetchedEntry != null) { 41044 var selector = this.getSelectorWithoutSpinner(); 41045 newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray(); 41046 } else { 41047 this.entries = []; 41048 newEntries = this.getAllEntries(); 41049 } 41050 41051 if (newEntries.length > 0) { 41052 41053 // Sort or randomize 41054 if ($.isFunction(this.settings.sort)) { 41055 newEntries = this.sortArray(newEntries); 41056 } else if (this.settings.randomize) { 41057 newEntries = this.shuffleArray(newEntries); 41058 } 41059 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 41060 41061 // Filter 41062 if (this.settings.filter) { 41063 newEntries = this.filterArray(newEntries); 41064 } else { 41065 this.resetFilters(newEntries); 41066 } 41067 41068 } 41069 41070 this.entries = this.entries.concat(newEntries); 41071 return true; 41072 }; 41073 41074 /** 41075 * Apply the entries order to the DOM, iterating the entries and appending the images 41076 * 41077 * @param entries the entries that has been modified and that must be re-ordered in the DOM 41078 */ 41079 JustifiedGallery.prototype.insertToGallery = function (entries) { 41080 var that = this; 41081 $.each(entries, function () { 41082 $(this).appendTo(that.$gallery); 41083 }); 41084 }; 41085 41086 /** 41087 * Shuffle the array using the Fisher-Yates shuffle algorithm 41088 * 41089 * @param a the array to shuffle 41090 * @return the shuffled array 41091 */ 41092 JustifiedGallery.prototype.shuffleArray = function (a) { 41093 var i, j, temp; 41094 for (i = a.length - 1; i > 0; i--) { 41095 j = Math.floor(Math.random() * (i + 1)); 41096 temp = a[i]; 41097 a[i] = a[j]; 41098 a[j] = temp; 41099 } 41100 this.insertToGallery(a); 41101 return a; 41102 }; 41103 41104 /** 41105 * Sort the array using settings.comparator as comparator 41106 * 41107 * @param a the array to sort (it is sorted) 41108 * @return the sorted array 41109 */ 41110 JustifiedGallery.prototype.sortArray = function (a) { 41111 a.sort(this.settings.sort); 41112 this.insertToGallery(a); 41113 return a; 41114 }; 41115 41116 /** 41117 * Reset the filters removing the 'jg-filtered' class from all the entries 41118 * 41119 * @param a the array to reset 41120 */ 41121 JustifiedGallery.prototype.resetFilters = function (a) { 41122 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 41123 }; 41124 41125 /** 41126 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 41127 * 41128 * @param a the array to filter 41129 * @return the filtered array 41130 */ 41131 JustifiedGallery.prototype.filterArray = function (a) { 41132 var settings = this.settings; 41133 if ($.type(settings.filter) === 'string') { 41134 // Filter only keeping the entries passed in the string 41135 return a.filter(function (el) { 41136 var $el = $(el); 41137 if ($el.is(settings.filter)) { 41138 $el.removeClass('jg-filtered'); 41139 return true; 41140 } else { 41141 $el.addClass('jg-filtered').removeClass('jg-visible'); 41142 return false; 41143 } 41144 }); 41145 } else if ($.isFunction(settings.filter)) { 41146 // Filter using the passed function 41147 var filteredArr = a.filter(settings.filter); 41148 for (var i = 0; i < a.length; i++) { 41149 if (filteredArr.indexOf(a[i]) === -1) { 41150 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 41151 } else { 41152 $(a[i]).removeClass('jg-filtered'); 41153 } 41154 } 41155 return filteredArr; 41156 } 41157 }; 41158 41159 /** 41160 * Revert the image src to the default value. 41161 */ 41162 JustifiedGallery.prototype.resetImgSrc = function ($img) { 41163 if ($img.data('jg.originalSrcLoc') === 'src') { 41164 $img.attr('src', $img.data('jg.originalSrc')); 41165 } else { 41166 $img.attr('src', ''); 41167 } 41168 }; 41169 41170 /** 41171 * Destroy the Justified Gallery instance. 41172 * 41173 * It clears all the css properties added in the style attributes. We doesn't backup the original 41174 * values for those css attributes, because it costs (performance) and because in general one 41175 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 41176 * classes). Creating a backup is also difficult because JG could be called multiple times and 41177 * with different style attributes. 41178 */ 41179 JustifiedGallery.prototype.destroy = function () { 41180 clearInterval(this.checkWidthIntervalId); 41181 this.stopImgAnalyzerStarter(); 41182 41183 // Get fresh entries list since filtered entries are absent in `this.entries` 41184 $.each(this.getAllEntries(), $.proxy(function (_, entry) { 41185 var $entry = $(entry); 41186 41187 // Reset entry style 41188 $entry.css('width', ''); 41189 $entry.css('height', ''); 41190 $entry.css('top', ''); 41191 $entry.css('left', ''); 41192 $entry.data('jg.loaded', undefined); 41193 $entry.removeClass('jg-entry jg-filtered jg-entry-visible'); 41194 41195 // Reset image style 41196 var $img = this.imgFromEntry($entry); 41197 if ($img) { 41198 $img.css('width', ''); 41199 $img.css('height', ''); 41200 $img.css('margin-left', ''); 41201 $img.css('margin-top', ''); 41202 this.resetImgSrc($img); 41203 $img.data('jg.originalSrc', undefined); 41204 $img.data('jg.originalSrcLoc', undefined); 41205 $img.data('jg.src', undefined); 41206 } 41207 41208 // Remove caption 41209 this.removeCaptionEventsHandlers($entry); 41210 var $caption = this.captionFromEntry($entry); 41211 if ($entry.data('jg.createdCaption')) { 41212 // remove also the caption element (if created by jg) 41213 $entry.data('jg.createdCaption', undefined); 41214 if ($caption !== null) $caption.remove(); 41215 } else { 41216 if ($caption !== null) $caption.fadeTo(0, 1); 41217 } 41218 41219 }, this)); 41220 41221 this.$gallery.css('height', ''); 41222 this.$gallery.removeClass('justified-gallery'); 41223 this.$gallery.data('jg.controller', undefined); 41224 this.settings.triggerEvent.call(this, 'jg.destroy'); 41225 }; 41226 41227 /** 41228 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 41229 * 41230 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 41231 */ 41232 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 41233 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 41234 var $entry = $(this.entries[i]); 41235 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 41236 var availableWidth = this.galleryWidth - 2 * this.border - ( 41237 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 41238 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 41239 41240 this.buildingRow.entriesBuff.push($entry); 41241 this.buildingRow.aspectRatio += imgAspectRatio; 41242 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 41243 this.lastAnalyzedIndex = i; 41244 41245 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 41246 this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 41247 41248 if (++this.yield.flushed >= this.yield.every) { 41249 this.startImgAnalyzer(isForResize); 41250 return; 41251 } 41252 } 41253 } else if ($entry.data('jg.loaded') !== 'error') { 41254 return; 41255 } 41256 } 41257 41258 // Last row flush (the row is not full) 41259 if (this.buildingRow.entriesBuff.length > 0) { 41260 this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 41261 } 41262 41263 if (this.isSpinnerActive()) { 41264 this.stopLoadingSpinnerAnimation(); 41265 } 41266 41267 /* Stop, if there is, the timeout to start the analyzeImages. 41268 This is because an image can be set loaded, and the timeout can be set, 41269 but this image can be analyzed yet. 41270 */ 41271 this.stopImgAnalyzerStarter(); 41272 41273 this.setGalleryFinalHeight(this.galleryHeightToSet); 41274 41275 //On complete callback 41276 this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete'); 41277 }; 41278 41279 /** 41280 * Stops any ImgAnalyzer starter (that has an assigned timeout) 41281 */ 41282 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 41283 this.yield.flushed = 0; 41284 if (this.imgAnalyzerTimeout !== null) { 41285 clearTimeout(this.imgAnalyzerTimeout); 41286 this.imgAnalyzerTimeout = null; 41287 } 41288 }; 41289 41290 /** 41291 * Starts the image analyzer. It is not immediately called to let the browser to update the view 41292 * 41293 * @param isForResize specifies if the image analyzer must be called for resizing or not 41294 */ 41295 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 41296 var that = this; 41297 this.stopImgAnalyzerStarter(); 41298 this.imgAnalyzerTimeout = setTimeout(function () { 41299 that.analyzeImages(isForResize); 41300 }, 0.001); // we can't start it immediately due to a IE different behaviour 41301 }; 41302 41303 /** 41304 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 41305 * because some browsers, with a 404 set complete = true. 41306 * 41307 * @param imageSrc the image src to load 41308 * @param onLoad callback that is called when the image has been loaded 41309 * @param onError callback that is called in case of an error 41310 */ 41311 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 41312 if (!onLoad && !onError) return; 41313 41314 var memImage = new Image(); 41315 var $memImage = $(memImage); 41316 if (onLoad) { 41317 $memImage.one('load', function () { 41318 $memImage.off('load error'); 41319 onLoad(memImage); 41320 }); 41321 } 41322 if (onError) { 41323 $memImage.one('error', function () { 41324 $memImage.off('load error'); 41325 onError(memImage); 41326 }); 41327 } 41328 memImage.src = imageSrc; 41329 }; 41330 41331 /** 41332 * Init of Justified Gallery controlled 41333 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 41334 */ 41335 JustifiedGallery.prototype.init = function () { 41336 var imagesToLoad = false, skippedImages = false, that = this; 41337 $.each(this.entries, function (index, entry) { 41338 var $entry = $(entry); 41339 var $image = that.imgFromEntry($entry); 41340 41341 $entry.addClass('jg-entry'); 41342 41343 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 41344 41345 // Link Rel global overwrite 41346 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 41347 41348 // Link Target global overwrite 41349 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 41350 41351 if ($image !== null) { 41352 41353 // Image src 41354 var imageSrc = that.extractImgSrcFromImage($image); 41355 41356 /* If we have the height and the width, we don't wait that the image is loaded, 41357 but we start directly with the justification */ 41358 if (that.settings.waitThumbnailsLoad === false || !imageSrc) { 41359 var width = parseFloat($image.attr('width')); 41360 var height = parseFloat($image.attr('height')); 41361 if ($image.prop('tagName') === 'svg') { 41362 width = parseFloat($image[0].getBBox().width); 41363 height = parseFloat($image[0].getBBox().height); 41364 } 41365 if (!isNaN(width) && !isNaN(height)) { 41366 $entry.data('jg.width', width); 41367 $entry.data('jg.height', height); 41368 $entry.data('jg.loaded', 'skipped'); 41369 skippedImages = true; 41370 that.startImgAnalyzer(false); 41371 return true; // continue 41372 } 41373 } 41374 41375 $entry.data('jg.loaded', false); 41376 imagesToLoad = true; 41377 41378 // Spinner start 41379 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 41380 41381 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 41382 $entry.data('jg.width', loadImg.width); 41383 $entry.data('jg.height', loadImg.height); 41384 $entry.data('jg.loaded', true); 41385 that.startImgAnalyzer(false); 41386 }, function () { // image load error 41387 $entry.data('jg.loaded', 'error'); 41388 that.startImgAnalyzer(false); 41389 }); 41390 41391 } else { 41392 $entry.data('jg.loaded', true); 41393 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 41394 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 41395 } 41396 41397 } 41398 41399 }); 41400 41401 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 41402 this.checkWidth(); 41403 }; 41404 41405 /** 41406 * Checks that it is a valid number. If a string is passed it is converted to a number 41407 * 41408 * @param settingContainer the object that contains the setting (to allow the conversion) 41409 * @param settingName the setting name 41410 */ 41411 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 41412 if ($.type(settingContainer[settingName]) === 'string') { 41413 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 41414 } 41415 41416 if ($.type(settingContainer[settingName]) === 'number') { 41417 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 41418 } else { 41419 throw settingName + ' must be a number'; 41420 } 41421 }; 41422 41423 /** 41424 * Checks the sizeRangeSuffixes and, if necessary, converts 41425 * its keys from string (e.g. old settings with 'lt100') to int. 41426 */ 41427 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 41428 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 41429 throw 'sizeRangeSuffixes must be defined and must be an object'; 41430 } 41431 41432 var suffixRanges = []; 41433 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 41434 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 41435 } 41436 41437 var newSizeRngSuffixes = { 0: '' }; 41438 for (var i = 0; i < suffixRanges.length; i++) { 41439 if ($.type(suffixRanges[i]) === 'string') { 41440 try { 41441 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 41442 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 41443 } catch (e) { 41444 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 41445 } 41446 } else { 41447 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 41448 } 41449 } 41450 41451 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 41452 }; 41453 41454 /** 41455 * check and convert the maxRowHeight setting 41456 * requires rowHeight to be already set 41457 * TODO: should be always called when only rowHeight is changed 41458 * @return number or null 41459 */ 41460 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 41461 var newMaxRowHeight = null; 41462 var rowHeight = this.settings.rowHeight; 41463 41464 if ($.type(this.settings.maxRowHeight) === 'string') { 41465 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 41466 newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 41467 } else { 41468 newMaxRowHeight = parseFloat(this.settings.maxRowHeight); 41469 } 41470 } else if ($.type(this.settings.maxRowHeight) === 'number') { 41471 newMaxRowHeight = this.settings.maxRowHeight; 41472 } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) { 41473 return null; 41474 } else { 41475 throw 'maxRowHeight must be a number or a percentage'; 41476 } 41477 41478 // check if the converted value is not a number 41479 if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight'; 41480 41481 // check values, maxRowHeight must be >= rowHeight 41482 if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight; 41483 41484 return newMaxRowHeight; 41485 }; 41486 41487 /** 41488 * Checks the settings 41489 */ 41490 JustifiedGallery.prototype.checkSettings = function () { 41491 this.checkSizeRangesSuffixes(); 41492 41493 this.checkOrConvertNumber(this.settings, 'rowHeight'); 41494 this.checkOrConvertNumber(this.settings, 'margins'); 41495 this.checkOrConvertNumber(this.settings, 'border'); 41496 this.checkOrConvertNumber(this.settings, 'maxRowsCount'); 41497 41498 var lastRowModes = [ 41499 'justify', 41500 'nojustify', 41501 'left', 41502 'center', 41503 'right', 41504 'hide' 41505 ]; 41506 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 41507 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 41508 } 41509 41510 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 41511 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 41512 throw 'justifyThreshold must be in the interval [0,1]'; 41513 } 41514 if ($.type(this.settings.cssAnimation) !== 'boolean') { 41515 throw 'cssAnimation must be a boolean'; 41516 } 41517 41518 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 41519 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 41520 41521 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 41522 if (this.settings.captionSettings.visibleOpacity < 0 || 41523 this.settings.captionSettings.visibleOpacity > 1) { 41524 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 41525 } 41526 41527 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 41528 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 41529 this.settings.captionSettings.nonVisibleOpacity > 1) { 41530 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 41531 } 41532 41533 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 41534 this.checkOrConvertNumber(this.settings, 'refreshTime'); 41535 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 41536 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 41537 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 41538 41539 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 41540 throw 'sort must be false or a comparison function'; 41541 } 41542 41543 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 41544 $.type(this.settings.filter) !== 'string') { 41545 throw 'filter must be false, a string or a filter function'; 41546 } 41547 }; 41548 41549 /** 41550 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 41551 * @returns {Array} sorted suffix ranges 41552 */ 41553 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 41554 var suffixRanges = []; 41555 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 41556 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 41557 } 41558 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 41559 return suffixRanges; 41560 }; 41561 41562 /** 41563 * Update the existing settings only changing some of them 41564 * 41565 * @param newSettings the new settings (or a subgroup of them) 41566 */ 41567 JustifiedGallery.prototype.updateSettings = function (newSettings) { 41568 // In this case Justified Gallery has been called again changing only some options 41569 this.settings = $.extend({}, this.settings, newSettings); 41570 this.checkSettings(); 41571 41572 // As reported in the settings: negative value = same as margins, 0 = disabled 41573 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 41574 41575 this.maxRowHeight = this.retrieveMaxRowHeight(); 41576 this.suffixRanges = this.retrieveSuffixRanges(); 41577 }; 41578 41579 JustifiedGallery.prototype.defaults = { 41580 sizeRangeSuffixes: {}, /* e.g. Flickr configuration 41581 { 41582 100: '_t', // used when longest is less than 100px 41583 240: '_m', // used when longest is between 101px and 240px 41584 320: '_n', // ... 41585 500: '', 41586 640: '_z', 41587 1024: '_b' // used as else case because it is the last 41588 } 41589 */ 41590 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 41591 path relative to a specific thumbnail size. The function should accept respectively three arguments: 41592 current path, width and height */ 41593 rowHeight: 120, // required? required to be > 0? 41594 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 41595 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 41596 // can't exceed 3 * rowHeight) 41597 maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled) 41598 margins: 1, 41599 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 41600 41601 lastRow: 'nojustify', // ⦠which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 41602 41603 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 41604 * (i.e. lastRow setting is not considered) */ 41605 waitThumbnailsLoad: true, 41606 captions: true, 41607 cssAnimation: true, 41608 imagesAnimationDuration: 500, // ignored with css animations 41609 captionSettings: { // ignored with css animations 41610 animationDuration: 500, 41611 visibleOpacity: 0.7, 41612 nonVisibleOpacity: 0.0 41613 },
41614 rel: null, // rewrite the rel of each analyzed links 41615 target: null, // rewrite the target of all links 41616 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 41617 refreshTime: 200, // time interval (in ms) to check if the page changes its width 41618 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 41619 randomize: false, 41620 rtl: false, // right-to-left mode 41621 sort: false, /* 41622 - false: to do not sort 41623 - function: to sort them using the function as comparator (see Array.prototype.sort()) 41624 */ 41625 filter: false, /* 41626 - false, null or undefined: for a disabled filter 41627 - a string: an entry is kept if entry.is(filter string) returns true 41628 see jQuery's .is() function for further information 41629 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 41630 It follows the specifications of the Array.prototype.filter() function of JavaScript. 41631 */ 41632 selector: 'a', // The selector that is used to know what are the entries of the gallery 41633 imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry 41634 triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger 41635 this.$gallery.trigger(event); // Consider that 'this' is this set to the JustifiedGallery object, so it can 41636 } // access to fields such as $gallery, useful to trigger events with jQuery. 41637 }; 41638 41639 41640 /** 41641 * Justified Gallery plugin for jQuery 41642 * 41643 * Events 41644 * - jg.complete : called when all the gallery has been created 41645 * - jg.resize : called when the gallery has been resized 41646 * - jg.rowflush : when a new row appears 41647 * 41648 * @param arg the action (or the settings) passed when the plugin is called 41649 * @returns {*} the object itself 41650 */ 41651 $.fn.justifiedGallery = function (arg) { 41652 return this.each(function (index, gallery) { 41653 41654 var $gallery = $(gallery); 41655 $gallery.addClass('justified-gallery'); 41656 41657 var controller = $gallery.data('jg.controller'); 41658 if (typeof controller === 'undefined') { 41659 // Create controller and assign it to the object data 41660 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 41661 if (arg === 'destroy') return; // Just a call to an unexisting object 41662 throw 'The argument must be an object'; 41663 } 41664 controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg)); 41665 $gallery.data('jg.controller', controller); 41666 } else if (arg === 'norewind') { 41667 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 41668 // ... left to be more readable 41669 } else if (arg === 'destroy') { 41670 controller.destroy(); 41671 return; 41672 } else { 41673 // In this case Justified Gallery has been called again changing only some options 41674 controller.updateSettings(arg); 41675 controller.rewind(); 41676 } 41677 41678 // Update the entries list 41679 if (!controller.updateEntries(arg === 'norewind')) return; 41680 41681 // Init justified gallery 41682 controller.init(); 41683 41684 }); 41685 }; 41686 41687})); 41688 41689/*! 41690* Customized version of iScroll.js 0.0.1 41691* It fixes bugs affecting its integration with fullpage.js 41692*/ 41693/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 41694(function (window, document, Math) { 41695var rAF = window.requestAnimationFrame || 41696 window.webkitRequestAnimationFrame || 41697 window.mozRequestAnimationFrame || 41698 window.oRequestAnimationFrame || 41699 window.msRequestAnimationFrame || 41700 function (callback) { window.setTimeout(callback, 1000 / 60); }; 41701 41702var utils = (function () { 41703 var me = {}; 41704 41705 var _elementStyle = document.createElement('div').style; 41706 var _vendor = (function () { 41707 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 41708 transform, 41709 i = 0, 41710 l = vendors.length; 41711 41712 for ( ; i < l; i++ ) { 41713 transform = vendors[i] + 'ransform'; 41714 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 41715 } 41716 41717 return false;
vendor: 5,154 bytes, lines 41718-41870
41718 })(); 41719 41720 function _prefixStyle (style) { 41721 if ( _vendor === false ) return false; 41722 if ( _vendor === '' ) return style; 41723 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 41724 } 41725 41726 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 41727 41728 me.extend = function (target, obj) { 41729 for ( var i in obj ) { 41730 target[i] = obj[i]; 41731 } 41732 }; 41733 41734 me.addEvent = function (el, type, fn, capture) { 41735 el.addEventListener(type, fn, !!capture); 41736 }; 41737 41738 me.removeEvent = function (el, type, fn, capture) { 41739 el.removeEventListener(type, fn, !!capture); 41740 }; 41741 41742 me.prefixPointerEvent = function (pointerEvent) { 41743 return window.MSPointerEvent ? 41744 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 41745 pointerEvent; 41746 }; 41747 41748 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 41749 var distance = current - start, 41750 speed = Math.abs(distance) / time, 41751 destination, 41752 duration; 41753 41754 deceleration = deceleration === undefined ? 0.0006 : deceleration; 41755 41756 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 41757 duration = speed / deceleration; 41758 41759 if ( destination < lowerMargin ) { 41760 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 41761 distance = Math.abs(destination - current); 41762 duration = distance / speed; 41763 } else if ( destination > 0 ) { 41764 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 41765 distance = Math.abs(current) + destination; 41766 duration = distance / speed; 41767 } 41768 41769 return { 41770 destination: Math.round(destination), 41771 duration: duration 41772 }; 41773 }; 41774 41775 var _transform = _prefixStyle('transform'); 41776 41777 me.extend(me, { 41778 hasTransform: _transform !== false, 41779 hasPerspective: _prefixStyle('perspective') in _elementStyle, 41780 hasTouch: 'ontouchstart' in window, 41781 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 41782 hasTransition: _prefixStyle('transition') in _elementStyle 41783 }); 41784 41785 /* 41786 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 41787 - galaxy S2 is ok 41788 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 41789 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 41790 - galaxy S3 is badAndroid (stock brower, webview) 41791 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 41792 - galaxy S4 is badAndroid (stock brower, webview) 41793 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 41794 - galaxy S5 is OK 41795 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 41796 - galaxy S6 is OK 41797 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 41798 */ 41799 me.isBadAndroid = (function() { 41800 var appVersion = window.navigator.appVersion; 41801 // Android browser is not a chrome browser. 41802 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 41803 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 41804 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 41805 return parseFloat(safariVersion[1]) < 535.19; 41806 } else { 41807 return true; 41808 } 41809 } else { 41810 return false; 41811 } 41812 })(); 41813 41814 me.extend(me.style = {}, { 41815 transform: _transform, 41816 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 41817 transitionDuration: _prefixStyle('transitionDuration'), 41818 transitionDelay: _prefixStyle('transitionDelay'), 41819 transformOrigin: _prefixStyle('transformOrigin') 41820 }); 41821 41822 me.hasClass = function (e, c) { 41823 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 41824 return re.test(e.className); 41825 }; 41826 41827 me.addClass = function (e, c) { 41828 if ( me.hasClass(e, c) ) { 41829 return; 41830 } 41831 41832 var newclass = e.className.split(' '); 41833 newclass.push(c); 41834 e.className = newclass.join(' '); 41835 }; 41836 41837 me.removeClass = function (e, c) { 41838 if ( !me.hasClass(e, c) ) { 41839 return; 41840 } 41841 41842 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 41843 e.className = e.className.replace(re, ' '); 41844 }; 41845 41846 me.offset = function (el) { 41847 var left = -el.offsetLeft, 41848 top = -el.offsetTop; 41849 41850 // jshint -W084 41851 while (el = el.offsetParent) { 41852 left -= el.offsetLeft; 41853 top -= el.offsetTop; 41854 } 41855 // jshint +W084 41856 41857 return { 41858 left: left, 41859 top: top 41860 }; 41861 }; 41862 41863 me.preventDefaultException = function (el, exceptions) { 41864 for ( var i in exceptions ) { 41865 if ( exceptions[i].test(el[i]) ) { 41866 return true; 41867 } 41868 } 41869 41870 return false;
vendor: 5,660 bytes, lines 41871-42036
41871 }; 41872 41873 me.extend(me.eventType = {}, { 41874 touchstart: 1, 41875 touchmove: 1, 41876 touchend: 1, 41877 41878 mousedown: 2, 41879 mousemove: 2, 41880 mouseup: 2, 41881 41882 pointerdown: 3, 41883 pointermove: 3, 41884 pointerup: 3, 41885 41886 MSPointerDown: 3, 41887 MSPointerMove: 3, 41888 MSPointerUp: 3 41889 }); 41890 41891 me.extend(me.ease = {}, { 41892 quadratic: { 41893 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 41894 fn: function (k) { 41895 return k * ( 2 - k ); 41896 } 41897 }, 41898 circular: { 41899 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) 41900 fn: function (k) { 41901 return Math.sqrt( 1 - ( --k * k ) ); 41902 } 41903 }, 41904 back: { 41905 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 41906 fn: function (k) { 41907 var b = 4; 41908 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 41909 } 41910 }, 41911 bounce: { 41912 style: '', 41913 fn: function (k) { 41914 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 41915 return 7.5625 * k * k; 41916 } else if ( k < ( 2 / 2.75 ) ) { 41917 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 41918 } else if ( k < ( 2.5 / 2.75 ) ) { 41919 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 41920 } else { 41921 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 41922 } 41923 } 41924 }, 41925 elastic: { 41926 style: '', 41927 fn: function (k) { 41928 var f = 0.22, 41929 e = 0.4; 41930 41931 if ( k === 0 ) { return 0; } 41932 if ( k == 1 ) { return 1; } 41933 41934 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 41935 } 41936 } 41937 }); 41938 41939 me.tap = function (e, eventName) { 41940 var ev = document.createEvent('Event'); 41941 ev.initEvent(eventName, true, true); 41942 ev.pageX = e.pageX; 41943 ev.pageY = e.pageY; 41944 e.target.dispatchEvent(ev); 41945 }; 41946 41947 me.click = function (e) { 41948 var target = e.target, 41949 ev; 41950 41951 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 41952 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 41953 // initMouseEvent is deprecated. 41954 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 41955 ev.initEvent('click', true, true); 41956 ev.view = e.view || window; 41957 ev.detail = 1; 41958 ev.screenX = target.screenX || 0; 41959 ev.screenY = target.screenY || 0; 41960 ev.clientX = target.clientX || 0; 41961 ev.clientY = target.clientY || 0; 41962 ev.ctrlKey = !!e.ctrlKey; 41963 ev.altKey = !!e.altKey; 41964 ev.shiftKey = !!e.shiftKey; 41965 ev.metaKey = !!e.metaKey; 41966 ev.button = 0; 41967 ev.relatedTarget = null; 41968 ev._constructed = true; 41969 target.dispatchEvent(ev); 41970 } 41971 }; 41972 41973 return me; 41974})(); 41975function IScroll (el, options) { 41976 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 41977 this.scroller = this.wrapper.children[0]; 41978 this.scrollerStyle = this.scroller.style; // cache style for better performance 41979 41980 this.options = { 41981 41982 resizeScrollbars: true, 41983 41984 mouseWheelSpeed: 20, 41985 41986 snapThreshold: 0.334, 41987 41988// INSERT POINT: OPTIONS 41989 disablePointer : !utils.hasPointer, 41990 disableTouch : utils.hasPointer || !utils.hasTouch, 41991 disableMouse : utils.hasPointer || utils.hasTouch, 41992 startX: 0, 41993 startY: 0, 41994 scrollY: true, 41995 directionLockThreshold: 5, 41996 momentum: true, 41997 41998 bounce: true, 41999 bounceTime: 600, 42000 bounceEasing: '', 42001 42002 preventDefault: true, 42003 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ }, 42004 42005 HWCompositing: true, 42006 useTransition: true, 42007 useTransform: true, 42008 bindToWrapper: typeof window.onmousedown === "undefined" 42009 }; 42010 42011 for ( var i in options ) { 42012 this.options[i] = options[i]; 42013 } 42014 42015 // Normalize options 42016 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 42017 42018 this.options.useTransition = utils.hasTransition && this.options.useTransition; 42019 this.options.useTransform = utils.hasTransform && this.options.useTransform; 42020 42021 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 42022 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 42023 42024 // If you want eventPassthrough I have to lock one of the axes 42025 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 42026 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 42027 42028 // With eventPassthrough we also need lockDirection mechanism 42029 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 42030 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 42031 42032 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 42033 42034 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 42035 42036 if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 42037-42208
42037 this.options.tap = 'tap'; 42038 } 42039 42040 // https://github.com/cubiq/iscroll/issues/1029 42041 if (!this.options.useTransition && !this.options.useTransform) { 42042 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 42043 this.scrollerStyle.position = "relative"; 42044 } 42045 } 42046 42047 if ( this.options.shrinkScrollbars == 'scale' ) { 42048 this.options.useTransition = false; 42049 } 42050 42051 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 42052 42053// INSERT POINT: NORMALIZATION 42054 42055 // Some defaults 42056 this.x = 0; 42057 this.y = 0; 42058 this.directionX = 0; 42059 this.directionY = 0; 42060 this._events = {}; 42061 42062// INSERT POINT: DEFAULTS 42063 42064 this._init(); 42065 this.refresh(); 42066 42067 this.scrollTo(this.options.startX, this.options.startY); 42068 this.enable(); 42069} 42070 42071IScroll.prototype = { 42072 version: '5.2.0', 42073 42074 _init: function () { 42075 this._initEvents(); 42076 42077 if ( this.options.scrollbars || this.options.indicators ) { 42078 this._initIndicators(); 42079 } 42080 42081 if ( this.options.mouseWheel ) { 42082 this._initWheel(); 42083 } 42084 42085 if ( this.options.snap ) { 42086 this._initSnap(); 42087 } 42088 42089 if ( this.options.keyBindings ) { 42090 this._initKeys(); 42091 } 42092 42093// INSERT POINT: _init 42094 42095 }, 42096 42097 destroy: function () { 42098 this._initEvents(true); 42099 clearTimeout(this.resizeTimeout); 42100 this.resizeTimeout = null; 42101 this._execEvent('destroy'); 42102 }, 42103 42104 _transitionEnd: function (e) { 42105 if ( e.target != this.scroller || !this.isInTransition ) { 42106 return; 42107 } 42108 42109 this._transitionTime(); 42110 if ( !this.resetPosition(this.options.bounceTime) ) { 42111 this.isInTransition = false; 42112 this._execEvent('scrollEnd'); 42113 } 42114 }, 42115 42116 _start: function (e) { 42117 // React to left mouse button only 42118 if ( utils.eventType[e.type] != 1 ) { 42119 // for button property 42120 // http://unixpapa.com/js/mouse.html 42121 var button; 42122 if (!e.which) { 42123 /* IE case */ 42124 button = (e.button < 2) ? 0 : 42125 ((e.button == 4) ? 1 : 2); 42126 } else { 42127 /* All others */ 42128 button = e.button; 42129 } 42130 if ( button !== 0 ) { 42131 return; 42132 } 42133 } 42134 42135 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 42136 return; 42137 } 42138 42139 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 42140 e.preventDefault(); 42141 } 42142 42143 var point = e.touches ? e.touches[0] : e, 42144 pos; 42145 42146 this.initiated = utils.eventType[e.type]; 42147 this.moved = false; 42148 this.distX = 0; 42149 this.distY = 0; 42150 this.directionX = 0; 42151 this.directionY = 0; 42152 this.directionLocked = 0; 42153 42154 this.startTime = utils.getTime(); 42155 42156 if ( this.options.useTransition && this.isInTransition ) { 42157 this._transitionTime(); 42158 this.isInTransition = false; 42159 pos = this.getComputedPosition(); 42160 this._translate(Math.round(pos.x), Math.round(pos.y)); 42161 this._execEvent('scrollEnd'); 42162 } else if ( !this.options.useTransition && this.isAnimating ) { 42163 this.isAnimating = false; 42164 this._execEvent('scrollEnd'); 42165 } 42166 42167 this.startX = this.x; 42168 this.startY = this.y; 42169 this.absStartX = this.x; 42170 this.absStartY = this.y; 42171 this.pointX = point.pageX; 42172 this.pointY = point.pageY; 42173 42174 this._execEvent('beforeScrollStart'); 42175 }, 42176 42177 _move: function (e) { 42178 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 42179 return; 42180 } 42181 42182 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 42183 e.preventDefault(); 42184 } 42185 42186 var point = e.touches ? e.touches[0] : e, 42187 deltaX = point.pageX - this.pointX, 42188 deltaY = point.pageY - this.pointY, 42189 timestamp = utils.getTime(), 42190 newX, newY, 42191 absDistX, absDistY; 42192 42193 this.pointX = point.pageX; 42194 this.pointY = point.pageY; 42195 42196 this.distX += deltaX; 42197 this.distY += deltaY; 42198 absDistX = Math.abs(this.distX); 42199 absDistY = Math.abs(this.distY); 42200 42201 // We need to move at least 10 pixels for the scrolling to initiate 42202 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 42203 return; 42204 } 42205 42206 // If you are scrolling in one direction lock the other 42207 if ( !this.directionLocked && !this.options.freeScroll ) { 42208 if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 42209-42395
42209 this.directionLocked = 'h'; // lock horizontally 42210 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 42211 this.directionLocked = 'v'; // lock vertically 42212 } else { 42213 this.directionLocked = 'n'; // no lock 42214 } 42215 } 42216 42217 if ( this.directionLocked == 'h' ) { 42218 if ( this.options.eventPassthrough == 'vertical' ) { 42219 e.preventDefault(); 42220 } else if ( this.options.eventPassthrough == 'horizontal' ) { 42221 this.initiated = false; 42222 return; 42223 } 42224 42225 deltaY = 0; 42226 } else if ( this.directionLocked == 'v' ) { 42227 if ( this.options.eventPassthrough == 'horizontal' ) { 42228 e.preventDefault(); 42229 } else if ( this.options.eventPassthrough == 'vertical' ) { 42230 this.initiated = false; 42231 return; 42232 } 42233 42234 deltaX = 0; 42235 } 42236 42237 deltaX = this.hasHorizontalScroll ? deltaX : 0; 42238 deltaY = this.hasVerticalScroll ? deltaY : 0; 42239 42240 newX = this.x + deltaX; 42241 newY = this.y + deltaY; 42242 42243 // Slow down if outside of the boundaries 42244 if ( newX > 0 || newX < this.maxScrollX ) { 42245 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 42246 } 42247 if ( newY > 0 || newY < this.maxScrollY ) { 42248 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 42249 } 42250 42251 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 42252 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 42253 42254 if ( !this.moved ) { 42255 this._execEvent('scrollStart'); 42256 } 42257 42258 this.moved = true; 42259 42260 this._translate(newX, newY); 42261 42262/* REPLACE START: _move */ 42263 42264 if ( timestamp - this.startTime > 300 ) { 42265 this.startTime = timestamp; 42266 this.startX = this.x; 42267 this.startY = this.y; 42268 } 42269 42270/* REPLACE END: _move */ 42271 42272 }, 42273 42274 _end: function (e) { 42275 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 42276 return; 42277 } 42278 42279 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 42280 e.preventDefault(); 42281 } 42282 42283 var point = e.changedTouches ? e.changedTouches[0] : e, 42284 momentumX, 42285 momentumY, 42286 duration = utils.getTime() - this.startTime, 42287 newX = Math.round(this.x), 42288 newY = Math.round(this.y), 42289 distanceX = Math.abs(newX - this.startX), 42290 distanceY = Math.abs(newY - this.startY), 42291 time = 0, 42292 easing = ''; 42293 42294 this.isInTransition = 0; 42295 this.initiated = 0; 42296 this.endTime = utils.getTime(); 42297 42298 // reset if we are outside of the boundaries 42299 if ( this.resetPosition(this.options.bounceTime) ) { 42300 return; 42301 } 42302 42303 this.scrollTo(newX, newY); // ensures that the last position is rounded 42304 42305 // we scrolled less than 10 pixels 42306 if ( !this.moved ) { 42307 if ( this.options.tap ) { 42308 utils.tap(e, this.options.tap); 42309 } 42310 42311 if ( this.options.click ) { 42312 utils.click(e); 42313 } 42314 42315 this._execEvent('scrollCancel'); 42316 return; 42317 } 42318 42319 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 42320 this._execEvent('flick'); 42321 return; 42322 } 42323 42324 // start momentum animation if needed 42325 if ( this.options.momentum && duration < 300 ) { 42326 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 }; 42327 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 }; 42328 newX = momentumX.destination; 42329 newY = momentumY.destination; 42330 time = Math.max(momentumX.duration, momentumY.duration); 42331 this.isInTransition = 1; 42332 } 42333 42334 42335 if ( this.options.snap ) { 42336 var snap = this._nearestSnap(newX, newY); 42337 this.currentPage = snap; 42338 time = this.options.snapSpeed || Math.max( 42339 Math.max( 42340 Math.min(Math.abs(newX - snap.x), 1000), 42341 Math.min(Math.abs(newY - snap.y), 1000) 42342 ), 300); 42343 newX = snap.x; 42344 newY = snap.y; 42345 42346 this.directionX = 0; 42347 this.directionY = 0; 42348 easing = this.options.bounceEasing; 42349 } 42350 42351// INSERT POINT: _end 42352 42353 if ( newX != this.x || newY != this.y ) { 42354 // change easing function when scroller goes out of the boundaries 42355 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 42356 easing = utils.ease.quadratic; 42357 } 42358 42359 this.scrollTo(newX, newY, time, easing); 42360 return; 42361 } 42362 42363 this._execEvent('scrollEnd'); 42364 }, 42365 42366 _resize: function () { 42367 var that = this; 42368 42369 clearTimeout(this.resizeTimeout); 42370 42371 this.resizeTimeout = setTimeout(function () { 42372 that.refresh(); 42373 }, this.options.resizePolling); 42374 }, 42375 42376 resetPosition: function (time) { 42377 var x = this.x, 42378 y = this.y; 42379 42380 time = time || 0; 42381 42382 if ( !this.hasHorizontalScroll || this.x > 0 ) { 42383 x = 0; 42384 } else if ( this.x < this.maxScrollX ) { 42385 x = this.maxScrollX; 42386 } 42387 42388 if ( !this.hasVerticalScroll || this.y > 0 ) { 42389 y = 0; 42390 } else if ( this.y < this.maxScrollY ) { 42391 y = this.maxScrollY; 42392 } 42393 42394 if ( x == this.x && y == this.y ) { 42395 return false;
vendor: 5,509 bytes, lines 42396-42600
42396 } 42397 42398 this.scrollTo(x, y, time, this.options.bounceEasing); 42399 42400 return true; 42401 }, 42402 42403 disable: function () { 42404 this.enabled = false; 42405 }, 42406 42407 enable: function () { 42408 this.enabled = true; 42409 }, 42410 42411 refresh: function () { 42412 var rf = this.wrapper.offsetHeight; // Force reflow 42413 42414 this.wrapperWidth = this.wrapper.clientWidth; 42415 this.wrapperHeight = this.wrapper.clientHeight; 42416 42417/* REPLACE START: refresh */ 42418 42419 this.scrollerWidth = this.scroller.offsetWidth; 42420 this.scrollerHeight = this.scroller.offsetHeight; 42421 42422 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 42423 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 42424 42425/* REPLACE END: refresh */ 42426 42427 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 42428 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 42429 42430 if ( !this.hasHorizontalScroll ) { 42431 this.maxScrollX = 0; 42432 this.scrollerWidth = this.wrapperWidth; 42433 } 42434 42435 if ( !this.hasVerticalScroll ) { 42436 this.maxScrollY = 0; 42437 this.scrollerHeight = this.wrapperHeight; 42438 } 42439 42440 this.endTime = 0; 42441 this.directionX = 0; 42442 this.directionY = 0; 42443 42444 this.wrapperOffset = utils.offset(this.wrapper); 42445 42446 this._execEvent('refresh'); 42447 42448 this.resetPosition(); 42449 42450// INSERT POINT: _refresh 42451 42452 }, 42453 42454 42455 on: function (type, fn) { 42456 if ( !this._events[type] ) { 42457 this._events[type] = []; 42458 } 42459 42460 this._events[type].push(fn); 42461 }, 42462 42463 off: function (type, fn) { 42464 if ( !this._events[type] ) { 42465 return; 42466 } 42467 42468 var index = this._events[type].indexOf(fn); 42469 42470 if ( index > -1 ) { 42471 this._events[type].splice(index, 1); 42472 } 42473 }, 42474 42475 _execEvent: function (type) { 42476 if ( !this._events[type] ) { 42477 return; 42478 } 42479 42480 var i = 0, 42481 l = this._events[type].length; 42482 42483 if ( !l ) { 42484 return; 42485 } 42486 42487 for ( ; i < l; i++ ) { 42488 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 42489 } 42490 }, 42491 42492 scrollBy: function (x, y, time, easing) { 42493 x = this.x + x; 42494 y = this.y + y; 42495 time = time || 0; 42496 42497 this.scrollTo(x, y, time, easing); 42498 }, 42499 42500 scrollTo: function (x, y, time, easing) { 42501 easing = easing || utils.ease.circular; 42502 42503 this.isInTransition = this.options.useTransition && time > 0; 42504 var transitionType = this.options.useTransition && easing.style; 42505 if ( !time || transitionType ) { 42506 if(transitionType) { 42507 this._transitionTimingFunction(easing.style); 42508 this._transitionTime(time); 42509 } 42510 this._translate(x, y); 42511 } else { 42512 this._animate(x, y, time, easing.fn); 42513 } 42514 }, 42515 42516 scrollToElement: function (el, time, offsetX, offsetY, easing) { 42517 el = el.nodeType ? el : this.scroller.querySelector(el); 42518 42519 if ( !el ) { 42520 return; 42521 } 42522 42523 var pos = utils.offset(el); 42524 42525 pos.left -= this.wrapperOffset.left; 42526 pos.top -= this.wrapperOffset.top; 42527 42528 // if offsetX/Y are true we center the element to the screen 42529 if ( offsetX === true ) { 42530 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 42531 } 42532 if ( offsetY === true ) { 42533 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 42534 } 42535 42536 pos.left -= offsetX || 0; 42537 pos.top -= offsetY || 0; 42538 42539 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 42540 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 42541 42542 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 42543 42544 this.scrollTo(pos.left, pos.top, time, easing); 42545 }, 42546 42547 _transitionTime: function (time) { 42548 if (!this.options.useTransition) { 42549 return; 42550 } 42551 time = time || 0; 42552 var durationProp = utils.style.transitionDuration; 42553 if(!durationProp) { 42554 return; 42555 } 42556 42557 this.scrollerStyle[durationProp] = time + 'ms'; 42558 42559 if ( !time && utils.isBadAndroid ) { 42560 this.scrollerStyle[durationProp] = '0.0001ms'; 42561 // remove 0.0001ms 42562 var self = this; 42563 rAF(function() { 42564 if(self.scrollerStyle[durationProp] === '0.0001ms') { 42565 self.scrollerStyle[durationProp] = '0s'; 42566 } 42567 }); 42568 } 42569 42570 42571 if ( this.indicators ) { 42572 for ( var i = this.indicators.length; i--; ) { 42573 this.indicators[i].transitionTime(time); 42574 } 42575 } 42576 42577 42578// INSERT POINT: _transitionTime 42579 42580 }, 42581 42582 _transitionTimingFunction: function (easing) { 42583 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 42584 42585 42586 if ( this.indicators ) { 42587 for ( var i = this.indicators.length; i--; ) { 42588 this.indicators[i].transitionTimingFunction(easing); 42589 } 42590 } 42591 42592 42593// INSERT POINT: _transitionTimingFunction 42594 42595 }, 42596 42597 _translate: function (x, y) { 42598 //Uncode addition 42599 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 42600 return false;
vendor: 9,939 bytes, lines 42601-42912
42601 42602 if ( this.options.useTransform ) { 42603 42604/* REPLACE START: _translate */ 42605 42606 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 42607 42608/* REPLACE END: _translate */ 42609 42610 } else { 42611 x = Math.round(x); 42612 y = Math.round(y); 42613 this.scrollerStyle.left = x + 'px'; 42614 this.scrollerStyle.top = y + 'px'; 42615 } 42616 42617 this.x = x; 42618 this.y = y; 42619 42620 42621 if ( this.indicators ) { 42622 for ( var i = this.indicators.length; i--; ) { 42623 this.indicators[i].updatePosition(); 42624 } 42625 } 42626 42627 //Uncode addition 42628 var uncodevent = new CustomEvent('fp-slide-scroll'); 42629 window.dispatchEvent(uncodevent); 42630 42631// INSERT POINT: _translate 42632 42633 }, 42634 42635 _initEvents: function (remove) { 42636 var eventType = remove ? utils.removeEvent : utils.addEvent, 42637 target = this.options.bindToWrapper ? this.wrapper : window; 42638 42639 eventType(window, 'orientationchange', this); 42640 eventType(window, 'resize', this); 42641 42642 if ( this.options.click ) { 42643 eventType(this.wrapper, 'click', this, true); 42644 } 42645 42646 if ( !this.options.disableMouse ) { 42647 eventType(this.wrapper, 'mousedown', this); 42648 eventType(target, 'mousemove', this); 42649 eventType(target, 'mousecancel', this); 42650 eventType(target, 'mouseup', this); 42651 } 42652 42653 if ( utils.hasPointer && !this.options.disablePointer ) { 42654 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 42655 eventType(target, utils.prefixPointerEvent('pointermove'), this); 42656 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 42657 eventType(target, utils.prefixPointerEvent('pointerup'), this); 42658 } 42659 42660 if ( utils.hasTouch && !this.options.disableTouch ) { 42661 eventType(this.wrapper, 'touchstart', this); 42662 eventType(target, 'touchmove', this); 42663 eventType(target, 'touchcancel', this); 42664 eventType(target, 'touchend', this); 42665 } 42666 42667 eventType(this.scroller, 'transitionend', this); 42668 eventType(this.scroller, 'webkitTransitionEnd', this); 42669 eventType(this.scroller, 'oTransitionEnd', this); 42670 eventType(this.scroller, 'MSTransitionEnd', this); 42671 }, 42672 42673 getComputedPosition: function () { 42674 var matrix = window.getComputedStyle(this.scroller, null), 42675 x, y; 42676 42677 if ( this.options.useTransform ) { 42678 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 42679 x = +(matrix[12] || matrix[4]); 42680 y = +(matrix[13] || matrix[5]); 42681 } else { 42682 x = +matrix.left.replace(/[^-\d.]/g, ''); 42683 y = +matrix.top.replace(/[^-\d.]/g, ''); 42684 } 42685 42686 return { x: x, y: y }; 42687 }, 42688 _initIndicators: function () { 42689 var interactive = this.options.interactiveScrollbars, 42690 customStyle = typeof this.options.scrollbars != 'string', 42691 indicators = [], 42692 indicator; 42693 42694 var that = this; 42695 42696 this.indicators = []; 42697 42698 if ( this.options.scrollbars ) { 42699 // Vertical scrollbar 42700 if ( this.options.scrollY ) { 42701 indicator = { 42702 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 42703 interactive: interactive, 42704 defaultScrollbars: true, 42705 customStyle: customStyle, 42706 resize: this.options.resizeScrollbars, 42707 shrink: this.options.shrinkScrollbars, 42708 fade: this.options.fadeScrollbars, 42709 listenX: false 42710 }; 42711 42712 this.wrapper.appendChild(indicator.el); 42713 indicators.push(indicator); 42714 } 42715 42716 // Horizontal scrollbar 42717 if ( this.options.scrollX ) { 42718 indicator = { 42719 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 42720 interactive: interactive, 42721 defaultScrollbars: true, 42722 customStyle: customStyle, 42723 resize: this.options.resizeScrollbars, 42724 shrink: this.options.shrinkScrollbars, 42725 fade: this.options.fadeScrollbars, 42726 listenY: false 42727 }; 42728 42729 this.wrapper.appendChild(indicator.el); 42730 indicators.push(indicator); 42731 } 42732 } 42733 42734 if ( this.options.indicators ) { 42735 // TODO: check concat compatibility 42736 indicators = indicators.concat(this.options.indicators); 42737 } 42738 42739 for ( var i = indicators.length; i--; ) { 42740 this.indicators.push( new Indicator(this, indicators[i]) ); 42741 } 42742 42743 // TODO: check if we can use array.map (wide compatibility and performance issues) 42744 function _indicatorsMap (fn) { 42745 if (that.indicators) { 42746 for ( var i = that.indicators.length; i--; ) { 42747 fn.call(that.indicators[i]); 42748 } 42749 } 42750 } 42751 42752 if ( this.options.fadeScrollbars ) { 42753 this.on('scrollEnd', function () { 42754 _indicatorsMap(function () { 42755 this.fade(); 42756 }); 42757 }); 42758 42759 this.on('scrollCancel', function () { 42760 _indicatorsMap(function () { 42761 this.fade(); 42762 }); 42763 }); 42764 42765 this.on('scrollStart', function () { 42766 _indicatorsMap(function () { 42767 this.fade(1); 42768 }); 42769 }); 42770 42771 this.on('beforeScrollStart', function () { 42772 _indicatorsMap(function () { 42773 this.fade(1, true); 42774 }); 42775 }); 42776 } 42777 42778 42779 this.on('refresh', function () { 42780 _indicatorsMap(function () { 42781 this.refresh(); 42782 }); 42783 }); 42784 42785 this.on('destroy', function () { 42786 _indicatorsMap(function () { 42787 this.destroy(); 42788 }); 42789 42790 delete this.indicators; 42791 }); 42792 }, 42793 42794 _initWheel: function () { 42795 utils.addEvent(this.wrapper, 'wheel', this); 42796 utils.addEvent(this.wrapper, 'mousewheel', this); 42797 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 42798 42799 this.on('destroy', function () { 42800 clearTimeout(this.wheelTimeout); 42801 this.wheelTimeout = null; 42802 utils.removeEvent(this.wrapper, 'wheel', this); 42803 utils.removeEvent(this.wrapper, 'mousewheel', this); 42804 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 42805 }); 42806 }, 42807 42808 _wheel: function (e) { 42809 if ( !this.enabled ) { 42810 return; 42811 } 42812 42813 var wheelDeltaX, wheelDeltaY, 42814 newX, newY, 42815 that = this; 42816 42817 if ( this.wheelTimeout === undefined ) { 42818 that._execEvent('scrollStart'); 42819 } 42820 42821 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 42822 clearTimeout(this.wheelTimeout); 42823 this.wheelTimeout = setTimeout(function () { 42824 if(!that.options.snap) { 42825 that._execEvent('scrollEnd'); 42826 } 42827 that.wheelTimeout = undefined; 42828 }, 400); 42829 42830 if ( 'deltaX' in e ) { 42831 if (e.deltaMode === 1) { 42832 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 42833 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 42834 } else { 42835 wheelDeltaX = -e.deltaX; 42836 wheelDeltaY = -e.deltaY; 42837 } 42838 } else if ( 'wheelDeltaX' in e ) { 42839 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 42840 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 42841 } else if ( 'wheelDelta' in e ) { 42842 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 42843 } else if ( 'detail' in e ) { 42844 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 42845 } else { 42846 return; 42847 } 42848 42849 wheelDeltaX *= this.options.invertWheelDirection; 42850 wheelDeltaY *= this.options.invertWheelDirection; 42851 42852 if ( !this.hasVerticalScroll ) { 42853 wheelDeltaX = wheelDeltaY; 42854 wheelDeltaY = 0; 42855 } 42856 42857 if ( this.options.snap ) { 42858 newX = this.currentPage.pageX; 42859 newY = this.currentPage.pageY; 42860 42861 if ( wheelDeltaX > 0 ) { 42862 newX--; 42863 } else if ( wheelDeltaX < 0 ) { 42864 newX++; 42865 } 42866 42867 if ( wheelDeltaY > 0 ) { 42868 newY--; 42869 } else if ( wheelDeltaY < 0 ) { 42870 newY++; 42871 } 42872 42873 this.goToPage(newX, newY); 42874 42875 return; 42876 } 42877 42878 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 42879 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 42880 42881 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 42882 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 42883 42884 if ( newX > 0 ) { 42885 newX = 0; 42886 } else if ( newX < this.maxScrollX ) { 42887 newX = this.maxScrollX; 42888 } 42889 42890 if ( newY > 0 ) { 42891 newY = 0; 42892 } else if ( newY < this.maxScrollY ) { 42893 newY = this.maxScrollY; 42894 } 42895 42896 this.scrollTo(newX, newY, 0); 42897 42898// INSERT POINT: _wheel 42899 }, 42900 42901 _initSnap: function () { 42902 this.currentPage = {}; 42903 42904 if ( typeof this.options.snap == 'string' ) { 42905 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 42906 } 42907 42908 this.on('refresh', function () { 42909 var i = 0, l, 42910 m = 0, n, 42911 cx, cy, 42912 x = 0, y,
vendor: 7,339 bytes, lines 42913-43166
42913 stepX = this.options.snapStepX || this.wrapperWidth, 42914 stepY = this.options.snapStepY || this.wrapperHeight, 42915 el; 42916 42917 this.pages = []; 42918 42919 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 42920 return; 42921 } 42922 42923 if ( this.options.snap === true ) { 42924 cx = Math.round( stepX / 2 ); 42925 cy = Math.round( stepY / 2 ); 42926 42927 while ( x > -this.scrollerWidth ) { 42928 this.pages[i] = []; 42929 l = 0; 42930 y = 0; 42931 42932 while ( y > -this.scrollerHeight ) { 42933 this.pages[i][l] = { 42934 x: Math.max(x, this.maxScrollX), 42935 y: Math.max(y, this.maxScrollY), 42936 width: stepX, 42937 height: stepY, 42938 cx: x - cx, 42939 cy: y - cy 42940 }; 42941 42942 y -= stepY; 42943 l++; 42944 } 42945 42946 x -= stepX; 42947 i++; 42948 } 42949 } else { 42950 el = this.options.snap; 42951 l = el.length; 42952 n = -1; 42953 42954 for ( ; i < l; i++ ) { 42955 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 42956 m = 0; 42957 n++; 42958 } 42959 42960 if ( !this.pages[m] ) { 42961 this.pages[m] = []; 42962 } 42963 42964 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 42965 y = Math.max(-el[i].offsetTop, this.maxScrollY); 42966 cx = x - Math.round(el[i].offsetWidth / 2); 42967 cy = y - Math.round(el[i].offsetHeight / 2); 42968 42969 this.pages[m][n] = { 42970 x: x, 42971 y: y, 42972 width: el[i].offsetWidth, 42973 height: el[i].offsetHeight, 42974 cx: cx, 42975 cy: cy 42976 }; 42977 42978 if ( x > this.maxScrollX ) { 42979 m++; 42980 } 42981 } 42982 } 42983 42984 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 42985 42986 // Update snap threshold if needed 42987 if ( this.options.snapThreshold % 1 === 0 ) { 42988 this.snapThresholdX = this.options.snapThreshold; 42989 this.snapThresholdY = this.options.snapThreshold; 42990 } else { 42991 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 42992 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 42993 } 42994 }); 42995 42996 this.on('flick', function () { 42997 var time = this.options.snapSpeed || Math.max( 42998 Math.max( 42999 Math.min(Math.abs(this.x - this.startX), 1000), 43000 Math.min(Math.abs(this.y - this.startY), 1000) 43001 ), 300); 43002 43003 this.goToPage( 43004 this.currentPage.pageX + this.directionX, 43005 this.currentPage.pageY + this.directionY, 43006 time 43007 ); 43008 }); 43009 }, 43010 43011 _nearestSnap: function (x, y) { 43012 if ( !this.pages.length ) { 43013 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 43014 } 43015 43016 var i = 0, 43017 l = this.pages.length, 43018 m = 0; 43019 43020 // Check if we exceeded the snap threshold 43021 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 43022 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 43023 return this.currentPage; 43024 } 43025 43026 if ( x > 0 ) { 43027 x = 0; 43028 } else if ( x < this.maxScrollX ) { 43029 x = this.maxScrollX; 43030 } 43031 43032 if ( y > 0 ) { 43033 y = 0; 43034 } else if ( y < this.maxScrollY ) { 43035 y = this.maxScrollY; 43036 } 43037 43038 for ( ; i < l; i++ ) { 43039 if ( x >= this.pages[i][0].cx ) { 43040 x = this.pages[i][0].x; 43041 break; 43042 } 43043 } 43044 43045 l = this.pages[i].length; 43046 43047 for ( ; m < l; m++ ) { 43048 if ( y >= this.pages[0][m].cy ) { 43049 y = this.pages[0][m].y; 43050 break; 43051 } 43052 } 43053 43054 if ( i == this.currentPage.pageX ) { 43055 i += this.directionX; 43056 43057 if ( i < 0 ) { 43058 i = 0; 43059 } else if ( i >= this.pages.length ) { 43060 i = this.pages.length - 1; 43061 } 43062 43063 x = this.pages[i][0].x; 43064 } 43065 43066 if ( m == this.currentPage.pageY ) { 43067 m += this.directionY; 43068 43069 if ( m < 0 ) { 43070 m = 0; 43071 } else if ( m >= this.pages[0].length ) { 43072 m = this.pages[0].length - 1; 43073 } 43074 43075 y = this.pages[0][m].y; 43076 } 43077 43078 return { 43079 x: x, 43080 y: y, 43081 pageX: i, 43082 pageY: m 43083 }; 43084 }, 43085 43086 goToPage: function (x, y, time, easing) { 43087 easing = easing || this.options.bounceEasing; 43088 43089 if ( x >= this.pages.length ) { 43090 x = this.pages.length - 1; 43091 } else if ( x < 0 ) { 43092 x = 0; 43093 } 43094 43095 if ( y >= this.pages[x].length ) { 43096 y = this.pages[x].length - 1; 43097 } else if ( y < 0 ) { 43098 y = 0; 43099 } 43100 43101 var posX = this.pages[x][y].x, 43102 posY = this.pages[x][y].y; 43103 43104 time = time === undefined ? this.options.snapSpeed || Math.max( 43105 Math.max( 43106 Math.min(Math.abs(posX - this.x), 1000), 43107 Math.min(Math.abs(posY - this.y), 1000) 43108 ), 300) : time; 43109 43110 this.currentPage = { 43111 x: posX, 43112 y: posY, 43113 pageX: x, 43114 pageY: y 43115 }; 43116 43117 this.scrollTo(posX, posY, time, easing); 43118 }, 43119 43120 next: function (time, easing) { 43121 var x = this.currentPage.pageX, 43122 y = this.currentPage.pageY; 43123 43124 x++; 43125 43126 if ( x >= this.pages.length && this.hasVerticalScroll ) { 43127 x = 0; 43128 y++; 43129 } 43130 43131 this.goToPage(x, y, time, easing); 43132 }, 43133 43134 prev: function (time, easing) { 43135 var x = this.currentPage.pageX, 43136 y = this.currentPage.pageY; 43137 43138 x--; 43139 43140 if ( x < 0 && this.hasVerticalScroll ) { 43141 x = 0; 43142 y--; 43143 } 43144 43145 this.goToPage(x, y, time, easing); 43146 }, 43147 43148 _initKeys: function (e) { 43149 // default key bindings 43150 var keys = { 43151 pageUp: 33, 43152 pageDown: 34, 43153 end: 35, 43154 home: 36, 43155 left: 37, 43156 up: 38, 43157 right: 39, 43158 down: 40 43159 }; 43160 var i; 43161 43162 // if you give me characters I give you keycode 43163 if ( typeof this.options.keyBindings == 'object' ) { 43164 for ( i in this.options.keyBindings ) { 43165 if ( typeof this.options.keyBindings[i] == 'string' ) { 43166 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 43166-43519
43166deAt(0); 43167 } 43168 } 43169 } else { 43170 this.options.keyBindings = {}; 43171 } 43172 43173 for ( i in keys ) { 43174 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 43175 } 43176 43177 utils.addEvent(window, 'keydown', this); 43178 43179 this.on('destroy', function () { 43180 utils.removeEvent(window, 'keydown', this); 43181 }); 43182 }, 43183 43184 _key: function (e) { 43185 if ( !this.enabled ) { 43186 return; 43187 } 43188 43189 var snap = this.options.snap, // we are using this alot, better to cache it 43190 newX = snap ? this.currentPage.pageX : this.x, 43191 newY = snap ? this.currentPage.pageY : this.y, 43192 now = utils.getTime(), 43193 prevTime = this.keyTime || 0, 43194 acceleration = 0.250, 43195 pos; 43196 43197 if ( this.options.useTransition && this.isInTransition ) { 43198 pos = this.getComputedPosition(); 43199 43200 this._translate(Math.round(pos.x), Math.round(pos.y)); 43201 this.isInTransition = false; 43202 } 43203 43204 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 43205 43206 switch ( e.keyCode ) { 43207 case this.options.keyBindings.pageUp: 43208 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 43209 newX += snap ? 1 : this.wrapperWidth; 43210 } else { 43211 newY += snap ? 1 : this.wrapperHeight; 43212 } 43213 break; 43214 case this.options.keyBindings.pageDown: 43215 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 43216 newX -= snap ? 1 : this.wrapperWidth; 43217 } else { 43218 newY -= snap ? 1 : this.wrapperHeight; 43219 } 43220 break; 43221 case this.options.keyBindings.end: 43222 newX = snap ? this.pages.length-1 : this.maxScrollX; 43223 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 43224 break; 43225 case this.options.keyBindings.home: 43226 newX = 0; 43227 newY = 0; 43228 break; 43229 case this.options.keyBindings.left: 43230 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 43231 break; 43232 case this.options.keyBindings.up: 43233 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 43234 break; 43235 case this.options.keyBindings.right: 43236 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 43237 break; 43238 case this.options.keyBindings.down: 43239 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 43240 break; 43241 default: 43242 return; 43243 } 43244 43245 if ( snap ) { 43246 this.goToPage(newX, newY); 43247 return; 43248 } 43249 43250 if ( newX > 0 ) { 43251 newX = 0; 43252 this.keyAcceleration = 0; 43253 } else if ( newX < this.maxScrollX ) { 43254 newX = this.maxScrollX; 43255 this.keyAcceleration = 0; 43256 } 43257 43258 if ( newY > 0 ) { 43259 newY = 0; 43260 this.keyAcceleration = 0; 43261 } else if ( newY < this.maxScrollY ) { 43262 newY = this.maxScrollY; 43263 this.keyAcceleration = 0; 43264 } 43265 43266 this.scrollTo(newX, newY, 0); 43267 43268 this.keyTime = now; 43269 }, 43270 43271 _animate: function (destX, destY, duration, easingFn) { 43272 var that = this, 43273 startX = this.x, 43274 startY = this.y, 43275 startTime = utils.getTime(), 43276 destTime = startTime + duration; 43277 43278 function step () { 43279 var now = utils.getTime(), 43280 newX, newY, 43281 easing; 43282 43283 if ( now >= destTime ) { 43284 that.isAnimating = false; 43285 that._translate(destX, destY); 43286 43287 if ( !that.resetPosition(that.options.bounceTime) ) { 43288 that._execEvent('scrollEnd'); 43289 } 43290 43291 return; 43292 } 43293 43294 now = ( now - startTime ) / duration; 43295 easing = easingFn(now); 43296 newX = ( destX - startX ) * easing + startX; 43297 newY = ( destY - startY ) * easing + startY; 43298 that._translate(newX, newY); 43299 43300 if ( that.isAnimating ) { 43301 rAF(step); 43302 } 43303 } 43304 43305 this.isAnimating = true; 43306 step(); 43307 }, 43308 handleEvent: function (e) { 43309 switch ( e.type ) { 43310 case 'touchstart': 43311 case 'pointerdown': 43312 case 'MSPointerDown': 43313 case 'mousedown': 43314 this._start(e); 43315 break; 43316 case 'touchmove': 43317 case 'pointermove': 43318 case 'MSPointerMove': 43319 case 'mousemove': 43320 this._move(e); 43321 break; 43322 case 'touchend': 43323 case 'pointerup': 43324 case 'MSPointerUp': 43325 case 'mouseup': 43326 case 'touchcancel': 43327 case 'pointercancel': 43328 case 'MSPointerCancel': 43329 case 'mousecancel': 43330 this._end(e); 43331 break; 43332 case 'orientationchange': 43333 case 'resize': 43334 this._resize(); 43335 break; 43336 case 'transitionend': 43337 case 'webkitTransitionEnd': 43338 case 'oTransitionEnd': 43339 case 'MSTransitionEnd': 43340 this._transitionEnd(e); 43341 break; 43342 case 'wheel': 43343 case 'DOMMouseScroll': 43344 case 'mousewheel': 43345 this._wheel(e); 43346 break; 43347 case 'keydown': 43348 this._key(e); 43349 break; 43350 case 'click': 43351 if ( this.enabled && !e._constructed ) { 43352 e.preventDefault(); 43353 e.stopPropagation(); 43354 } 43355 break; 43356 } 43357 } 43358}; 43359function createDefaultScrollbar (direction, interactive, type) { 43360 var scrollbar = document.createElement('div'), 43361 indicator = document.createElement('div'); 43362 43363 if ( type === true ) { 43364 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 43365 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'; 43366 } 43367 43368 indicator.className = 'iScrollIndicator'; 43369 43370 if ( direction == 'h' ) { 43371 if ( type === true ) { 43372 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 43373 indicator.style.height = '100%'; 43374 } 43375 scrollbar.className = 'iScrollHorizontalScrollbar'; 43376 } else { 43377 if ( type === true ) { 43378 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 43379 indicator.style.width = '100%'; 43380 } 43381 scrollbar.className = 'iScrollVerticalScrollbar'; 43382 } 43383 43384 scrollbar.style.cssText += ';overflow:hidden'; 43385 43386 if ( !interactive ) { 43387 scrollbar.style.pointerEvents = 'none'; 43388 } 43389 43390 scrollbar.appendChild(indicator); 43391 43392 return scrollbar; 43393} 43394 43395function Indicator (scroller, options) { 43396 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 43397 this.wrapperStyle = this.wrapper.style; 43398 this.indicator = this.wrapper.children[0]; 43399 this.indicatorStyle = this.indicator.style; 43400 this.scroller = scroller; 43401 43402 this.options = { 43403 listenX: true, 43404 listenY: true, 43405 interactive: false, 43406 resize: true, 43407 defaultScrollbars: false, 43408 shrink: false, 43409 fade: false, 43410 speedRatioX: 0, 43411 speedRatioY: 0 43412 }; 43413 43414 for ( var i in options ) { 43415 this.options[i] = options[i]; 43416 } 43417 43418 this.sizeRatioX = 1; 43419 this.sizeRatioY = 1; 43420 this.maxPosX = 0; 43421 this.maxPosY = 0; 43422 43423 if ( this.options.interactive ) { 43424 if ( !this.options.disableTouch ) { 43425 utils.addEvent(this.indicator, 'touchstart', this); 43426 utils.addEvent(window, 'touchend', this); 43427 } 43428 if ( !this.options.disablePointer ) { 43429 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 43430 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 43431 } 43432 if ( !this.options.disableMouse ) { 43433 utils.addEvent(this.indicator, 'mousedown', this); 43434 utils.addEvent(window, 'mouseup', this); 43435 } 43436 } 43437 43438 if ( this.options.fade ) { 43439 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 43440 var durationProp = utils.style.transitionDuration; 43441 if(!durationProp) { 43442 return; 43443 } 43444 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 43445 // remove 0.0001ms 43446 var self = this; 43447 if(utils.isBadAndroid) { 43448 rAF(function() { 43449 if(self.wrapperStyle[durationProp] === '0.0001ms') { 43450 self.wrapperStyle[durationProp] = '0s'; 43451 } 43452 }); 43453 } 43454 this.wrapperStyle.opacity = '0'; 43455 } 43456} 43457 43458Indicator.prototype = { 43459 handleEvent: function (e) { 43460 switch ( e.type ) { 43461 case 'touchstart': 43462 case 'pointerdown': 43463 case 'MSPointerDown': 43464 case 'mousedown': 43465 this._start(e); 43466 break; 43467 case 'touchmove': 43468 case 'pointermove': 43469 case 'MSPointerMove': 43470 case 'mousemove': 43471 this._move(e); 43472 break; 43473 case 'touchend': 43474 case 'pointerup': 43475 case 'MSPointerUp': 43476 case 'mouseup': 43477 case 'touchcancel': 43478 case 'pointercancel': 43479 case 'MSPointerCancel': 43480 case 'mousecancel': 43481 this._end(e); 43482 break; 43483 } 43484 }, 43485 43486 destroy: function () { 43487 if ( this.options.fadeScrollbars ) { 43488 clearTimeout(this.fadeTimeout); 43489 this.fadeTimeout = null; 43490 } 43491 if ( this.options.interactive ) { 43492 utils.removeEvent(this.indicator, 'touchstart', this); 43493 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 43494 utils.removeEvent(this.indicator, 'mousedown', this); 43495 43496 utils.removeEvent(window, 'touchmove', this); 43497 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 43498 utils.removeEvent(window, 'mousemove', this); 43499 43500 utils.removeEvent(window, 'touchend', this); 43501 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 43502 utils.removeEvent(window, 'mouseup', this); 43503 } 43504 43505 if ( this.options.defaultScrollbars ) { 43506 this.wrapper.parentNode.removeChild(this.wrapper); 43507 } 43508 }, 43509 43510 _start: function (e) { 43511 var point = e.touches ? e.touches[0] : e; 43512 43513 e.preventDefault(); 43514 e.stopPropagation(); 43515 43516 this.transitionTime(); 43517 43518 this.initiated = true; 43519 this.moved = false;
vendor: 9,615 bytes, lines 43520-43778
43520 this.lastPointX = point.pageX; 43521 this.lastPointY = point.pageY; 43522 43523 this.startTime = utils.getTime(); 43524 43525 if ( !this.options.disableTouch ) { 43526 utils.addEvent(window, 'touchmove', this); 43527 } 43528 if ( !this.options.disablePointer ) { 43529 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 43530 } 43531 if ( !this.options.disableMouse ) { 43532 utils.addEvent(window, 'mousemove', this); 43533 } 43534 43535 this.scroller._execEvent('beforeScrollStart'); 43536 }, 43537 43538 _move: function (e) { 43539 var point = e.touches ? e.touches[0] : e, 43540 deltaX, deltaY, 43541 newX, newY, 43542 timestamp = utils.getTime(); 43543 43544 if ( !this.moved ) { 43545 this.scroller._execEvent('scrollStart'); 43546 } 43547 43548 this.moved = true; 43549 43550 deltaX = point.pageX - this.lastPointX; 43551 this.lastPointX = point.pageX; 43552 43553 deltaY = point.pageY - this.lastPointY; 43554 this.lastPointY = point.pageY; 43555 43556 newX = this.x + deltaX; 43557 newY = this.y + deltaY; 43558 43559 this._pos(newX, newY); 43560 43561// INSERT POINT: indicator._move 43562 43563 e.preventDefault(); 43564 e.stopPropagation(); 43565 }, 43566 43567 _end: function (e) { 43568 if ( !this.initiated ) { 43569 return; 43570 } 43571 43572 this.initiated = false; 43573 43574 e.preventDefault(); 43575 e.stopPropagation(); 43576 43577 utils.removeEvent(window, 'touchmove', this); 43578 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 43579 utils.removeEvent(window, 'mousemove', this); 43580 43581 if ( this.scroller.options.snap ) { 43582 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 43583 43584 var time = this.options.snapSpeed || Math.max( 43585 Math.max( 43586 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 43587 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 43588 ), 300); 43589 43590 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 43591 this.scroller.directionX = 0; 43592 this.scroller.directionY = 0; 43593 this.scroller.currentPage = snap; 43594 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 43595 } 43596 } 43597 43598 if ( this.moved ) { 43599 this.scroller._execEvent('scrollEnd'); 43600 } 43601 }, 43602 43603 transitionTime: function (time) { 43604 time = time || 0; 43605 var durationProp = utils.style.transitionDuration; 43606 if(!durationProp) { 43607 return; 43608 } 43609 43610 this.indicatorStyle[durationProp] = time + 'ms'; 43611 43612 if ( !time && utils.isBadAndroid ) { 43613 this.indicatorStyle[durationProp] = '0.0001ms'; 43614 // remove 0.0001ms 43615 var self = this; 43616 rAF(function() { 43617 if(self.indicatorStyle[durationProp] === '0.0001ms') { 43618 self.indicatorStyle[durationProp] = '0s'; 43619 } 43620 }); 43621 } 43622 }, 43623 43624 transitionTimingFunction: function (easing) { 43625 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 43626 }, 43627 43628 refresh: function () { 43629 this.transitionTime(); 43630 43631 if ( this.options.listenX && !this.options.listenY ) { 43632 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 43633 } else if ( this.options.listenY && !this.options.listenX ) { 43634 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 43635 } else { 43636 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 43637 } 43638 43639 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 43640 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 43641 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 43642 43643 if ( this.options.defaultScrollbars && this.options.customStyle ) { 43644 if ( this.options.listenX ) { 43645 this.wrapper.style.right = '8px'; 43646 } else { 43647 this.wrapper.style.bottom = '8px'; 43648 } 43649 } 43650 } else { 43651 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 43652 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 43653 43654 if ( this.options.defaultScrollbars && this.options.customStyle ) { 43655 if ( this.options.listenX ) { 43656 this.wrapper.style.right = '2px'; 43657 } else { 43658 this.wrapper.style.bottom = '2px'; 43659 } 43660 } 43661 } 43662 43663 var r = this.wrapper.offsetHeight; // force refresh 43664 43665 if ( this.options.listenX ) { 43666 this.wrapperWidth = this.wrapper.clientWidth; 43667 if ( this.options.resize ) { 43668 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 43669 this.indicatorStyle.width = this.indicatorWidth + 'px'; 43670 } else { 43671 this.indicatorWidth = this.indicator.clientWidth; 43672 } 43673 43674 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 43675 43676 if ( this.options.shrink == 'clip' ) { 43677 this.minBoundaryX = -this.indicatorWidth + 8; 43678 this.maxBoundaryX = this.wrapperWidth - 8; 43679 } else { 43680 this.minBoundaryX = 0; 43681 this.maxBoundaryX = this.maxPosX; 43682 } 43683 43684 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 43685 } 43686 43687 if ( this.options.listenY ) { 43688 this.wrapperHeight = this.wrapper.clientHeight; 43689 if ( this.options.resize ) { 43690 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 43691 this.indicatorStyle.height = this.indicatorHeight + 'px'; 43692 } else { 43693 this.indicatorHeight = this.indicator.clientHeight; 43694 } 43695 43696 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 43697 43698 if ( this.options.shrink == 'clip' ) { 43699 this.minBoundaryY = -this.indicatorHeight + 8; 43700 this.maxBoundaryY = this.wrapperHeight - 8; 43701 } else { 43702 this.minBoundaryY = 0; 43703 this.maxBoundaryY = this.maxPosY; 43704 } 43705 43706 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 43707 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 43708 } 43709 43710 this.updatePosition(); 43711 }, 43712 43713 updatePosition: function () { 43714 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 43715 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 43716 43717 if ( !this.options.ignoreBoundaries ) { 43718 if ( x < this.minBoundaryX ) { 43719 if ( this.options.shrink == 'scale' ) { 43720 this.width = Math.max(this.indicatorWidth + x, 8); 43721 this.indicatorStyle.width = this.width + 'px'; 43722 } 43723 x = this.minBoundaryX; 43724 } else if ( x > this.maxBoundaryX ) { 43725 if ( this.options.shrink == 'scale' ) { 43726 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 43727 this.indicatorStyle.width = this.width + 'px'; 43728 x = this.maxPosX + this.indicatorWidth - this.width; 43729 } else { 43730 x = this.maxBoundaryX; 43731 } 43732 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 43733 this.width = this.indicatorWidth; 43734 this.indicatorStyle.width = this.width + 'px'; 43735 } 43736 43737 if ( y < this.minBoundaryY ) { 43738 if ( this.options.shrink == 'scale' ) { 43739 this.height = Math.max(this.indicatorHeight + y * 3, 8); 43740 this.indicatorStyle.height = this.height + 'px'; 43741 } 43742 y = this.minBoundaryY; 43743 } else if ( y > this.maxBoundaryY ) { 43744 if ( this.options.shrink == 'scale' ) { 43745 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 43746 this.indicatorStyle.height = this.height + 'px'; 43747 y = this.maxPosY + this.indicatorHeight - this.height; 43748 } else { 43749 y = this.maxBoundaryY; 43750 } 43751 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 43752 this.height = this.indicatorHeight; 43753 this.indicatorStyle.height = this.height + 'px'; 43754 } 43755 } 43756 43757 this.x = x; 43758 this.y = y; 43759 43760 if ( this.scroller.options.useTransform ) { 43761 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 43762 } else { 43763 this.indicatorStyle.left = x + 'px'; 43764 this.indicatorStyle.top = y + 'px'; 43765 } 43766 }, 43767 43768 _pos: function (x, y) { 43769 if ( x < 0 ) { 43770 x = 0; 43771 } else if ( x > this.maxPosX ) { 43772 x = this.maxPosX; 43773 } 43774 43775 if ( y < 0 ) { 43776 y = 0; 43777 } else if ( y > this.maxPosY ) { 43778 y = this.maxPosY;
43779 } 43780 43781 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 43782 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 43783 43784 this.scroller.scrollTo(x, y); 43785 }, 43786 43787 fade: function (val, hold) { 43788 if ( hold && !this.visible ) { 43789 return; 43790 } 43791 43792 clearTimeout(this.fadeTimeout); 43793 this.fadeTimeout = null; 43794 43795 var time = val ? 250 : 500, 43796 delay = val ? 0 : 300; 43797 43798 val = val ? '1' : '0'; 43799 43800 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 43801 43802 this.fadeTimeout = setTimeout((function (val) { 43803 this.wrapperStyle.opacity = val; 43804 this.visible = +val; 43805 }).bind(this, val), delay); 43806 } 43807}; 43808 43809IScroll.utils = utils; 43810 43811if ( typeof module != 'undefined' && module.exports ) { 43812 module.exports = IScroll; 43813} else if ( typeof define == 'function' && define.amd ) { 43814 define( function () { return IScroll; } ); 43815} else { 43816 window.IScroll = IScroll; 43817} 43818 43819})(window, document, Math); 43820/*! 43821 * fullPage 2.9.4 43822 * https://github.com/alvarotrigo/fullPage.js 43823 * @license MIT licensed 43824 * 43825 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 43826 */ 43827(function(global, factory) { 43828 'use strict'; 43829 if (typeof define === 'function' && define.amd) { 43830 define(['jquery'], function($) { 43831 return factory($, global, global.document, global.Math); 43832 }); 43833 } else if (typeof exports === "object" && exports) { 43834 module.exports = factory(require('jquery'), global, global.document, global.Math); 43835 } else { 43836 factory(jQuery, global, global.document, global.Math); 43837 } 43838})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 43839 'use strict'; 43840 43841 // keeping central set of classnames and selectors 43842 var WRAPPER = 'fullpage-wrapper'; 43843 var WRAPPER_SEL = '.' + WRAPPER; 43844 43845 // slimscroll 43846 var SCROLLABLE = 'fp-scrollable'; 43847 var SCROLLABLE_SEL = '.' + SCROLLABLE; 43848 43849 // util 43850 var RESPONSIVE = 'fp-responsive'; 43851 var NO_TRANSITION = 'fp-notransition'; 43852 var DESTROYED = 'fp-destroyed'; 43853 var ENABLED = 'fp-enabled'; 43854 var VIEWING_PREFIX = 'fp-viewing'; 43855 var ACTIVE = 'active'; 43856 var ACTIVE_SEL = '.' + ACTIVE; 43857 var COMPLETELY = 'fp-completely'; 43858 var COMPLETELY_SEL = '.' + COMPLETELY; 43859 43860 // section 43861 var SECTION_DEFAULT_SEL = '.section'; 43862 var SECTION = 'fp-section'; 43863 var SECTION_SEL = '.' + SECTION; 43864 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 43865 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 43866 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 43867 var TABLE_CELL = 'fp-tableCell'; 43868 var TABLE_CELL_SEL = '.' + TABLE_CELL; 43869 var AUTO_HEIGHT = 'fp-auto-height'; 43870 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 43871 var NORMAL_SCROLL = 'fp-normal-scroll'; 43872 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 43873 43874 // section nav 43875 var SECTION_NAV = 'fp-nav'; 43876 var SECTION_NAV_SEL = '#' + SECTION_NAV; 43877 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 43878 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 43879 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 43880 43881 // slide 43882 var SLIDE_DEFAULT_SEL = '.slide'; 43883 var SLIDE = 'fp-slide'; 43884 var SLIDE_SEL = '.' + SLIDE; 43885 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 43886 var SLIDES_WRAPPER = 'fp-slides'; 43887 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 43888 var SLIDES_CONTAINER = 'fp-slidesContainer'; 43889 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 43890 var TABLE = 'fp-table'; 43891 43892 // slide nav 43893 var SLIDES_NAV = 'fp-slidesNav'; 43894 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 43895 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 43896 var SLIDES_ARROW = 'fp-controlArrow'; 43897 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 43898 var SLIDES_PREV = 'fp-prev'; 43899 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 43900 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 43901 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 43902 var SLIDES_NEXT = 'fp-next';
43903 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 43904 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 43905 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 43906 43907 var $window = $(window); 43908 var $document = $(document); 43909 43910 // Default options for iScroll.js used when using scrollOverflow 43911 var iscrollOptions = { 43912 scrollbars: true, 43913 mouseWheel: true, 43914 hideScrollbars: false, 43915 fadeScrollbars: false, 43916 disableMouse: true, 43917 interactiveScrollbars: true, 43918 bounce: false, 43919 }; 43920 43921 $.fn.fullpage = function(options) { 43922 //only once my friend! 43923 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 43924 43925 // common jQuery objects 43926 var $htmlBody = $('html, body'); 43927 var $body = $('body'); 43928 43929 var FP = $.fn.fullpage; 43930 43931 // Creating some defaults, extending them with any options that were provided 43932 options = $.extend({ 43933 //navigation 43934 menu: false, 43935 anchors:[], 43936 lockAnchors: false, 43937 navigation: false, 43938 navigationPosition: 'right', 43939 navigationTooltips: [], 43940 showActiveTooltip: false, 43941 slidesNavigation: false, 43942 slidesNavPosition: 'bottom', 43943 scrollBar: false, 43944 hybrid: false, 43945 43946 //scrolling 43947 css3: true, 43948 scrollingSpeed: 700, 43949 autoScrolling: true, 43950 fitToSection: true, 43951 fitToSectionDelay: 1000, 43952 easing: 'easeInOutCubic', 43953 easingcss3: 'ease', 43954 loopBottom: false, 43955 loopTop: false, 43956 loopHorizontal: true, 43957 continuousVertical: false, 43958 continuousHorizontal: false, 43959 scrollHorizontally: false, 43960 interlockedSlides: false, 43961 dragAndMove: false, 43962 offsetSections: false, 43963 resetSliders: false, 43964 fadingEffect: false, 43965 normalScrollElements: null, 43966 scrollOverflow: false, 43967 scrollOverflowReset: false, 43968 scrollOverflowHandler: iscrollHandler, 43969 scrollOverflowOptions: null, 43970 touchSensitivity: 5, 43971 normalScrollElementTouchThreshold: 5, 43972 bigSectionsDestination: null, 43973 43974 //Accessibility 43975 keyboardScrolling: true, 43976 animateAnchor: true, 43977 recordHistory: true, 43978 43979 //design 43980 controlArrows: true, 43981 controlArrowColor: '#fff', 43982 verticalCentered: true, 43983 sectionsColor : [], 43984 paddingTop: 0, 43985 paddingBottom: 0, 43986 fixedElements: null, 43987 responsive: 0, //backwards compabitility with responsiveWiddth 43988 responsiveWidth: 0, 43989 responsiveHeight: 0, 43990 responsiveSlides: false, 43991 parallax: false, 43992 parallaxOptions: { 43993 type: 'reveal', 43994 percentage: 62, 43995 property: 'translate' 43996 }, 43997 43998 //Custom selectors 43999 sectionSelector: SECTION_DEFAULT_SEL, 44000 slideSelector: SLIDE_DEFAULT_SEL, 44001 44002 //events 44003 afterLoad: null, 44004 onLeave: null, 44005 afterRender: null, 44006 afterResize: null, 44007 afterReBuild: null, 44008 afterSlideLoad: null, 44009 onSlideLeave: null, 44010 afterResponsive: null, 44011 44012 lazyLoading: true 44013 }, options); 44014 44015 //flag to avoid very fast sliding for landscape sliders 44016 var slideMoving = false; 44017 44018 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 44019 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 44020 var container = $(this); 44021 var windowsHeight = $window.height(); 44022 var isResizing = false; 44023 var isWindowFocused = true; 44024 var lastScrolledDestiny; 44025 var lastScrolledSlide; 44026 var canScroll = true; 44027 var scrollings = []; 44028 var controlPressed; 44029 var startingSection; 44030 var isScrollAllowed = {}; 44031 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 44032 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 44033 var MSPointer = getMSPointer(); 44034 var events = { 44035 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 44036 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 44037 }; 44038 44039 //cheks for passive event support 44040 //added by Uncode from new fullPage updates 44041 var g_supportsPassive = false;
44042 try { 44043 var opts = Object.defineProperty({}, 'passive', { 44044 get: function() { 44045 g_supportsPassive = true; 44046 } 44047 }); 44048 window.addEventListener("testPassive", null, opts); 44049 window.removeEventListener("testPassive", null, opts); 44050 } catch (e) {} 44051 44052 //timeouts 44053 var resizeId; 44054 var afterSectionLoadsId; 44055 var afterSlideLoadsId; 44056 var scrollId; 44057 var scrollId2; 44058 var keydownId; 44059 var originals = $.extend(true, {}, options); //deep copy 44060 44061 //Uncode addition 44062 var $masthead = $('#masthead'); 44063 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 44064 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 44065 var bodyBorder = UNCODE.bodyBorder; 44066 var adminBarHeight = UNCODE.adminBarHeight; 44067 44068 displayWarnings(); 44069 44070 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 44071 iscrollOptions.click = isTouch; // see #2035 44072 44073 //extending iScroll options with the user custom ones 44074 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 44075 44076 //easeInOutCubic animation included in the plugin 44077 $.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;}}); 44078 44079 /** 44080 * Sets the autoScroll option. 44081 * It changes the scroll bar visibility and the history of the site as a result. 44082 */ 44083 function setAutoScrolling(value, type){ 44084 //removing the transformation 44085 if(!value){ 44086 silentScroll(0); 44087 } 44088 44089 setVariableState('autoScrolling', value, type); 44090 44091 var element = $(SECTION_ACTIVE_SEL); 44092 44093 if(options.autoScrolling && !options.scrollBar){ 44094 $htmlBody.css({ 44095 'overflow' : 'hidden !important', 44096 'height' : '100%' 44097 }); 44098 44099 //Uncode addition 44100 //setRecordHistory(originals.recordHistory, 'internal'); 44101 44102 //for IE touch devices 44103 container.css({ 44104 '-ms-touch-action': 'none', 44105 'touch-action': 'none' 44106 }); 44107 44108 if(element.length){ 44109 //moving the container up 44110 silentScroll(element.position().top); 44111 } 44112 44113 }else{ 44114 $htmlBody.css({ 44115 'overflow' : 'visible !important', 44116 'height' : 'initial' 44117 }); 44118 44119 //Uncode addition 44120 //setRecordHistory(false, 'internal'); 44121 44122 //for IE touch devices 44123 container.css({ 44124 '-ms-touch-action': '', 44125 'touch-action': '' 44126 }); 44127 44128 //scrolling the page to the section with no animation 44129 if (element.length) { 44130 $htmlBody.scrollTop(element.position().top); 44131 } 44132 } 44133 } 44134 44135 /** 44136 * Defines wheter to record the history for each hash change in the URL. 44137 */ 44138 function setRecordHistory(value, type){ 44139 setVariableState('recordHistory', value, type); 44140 } 44141 44142 /** 44143 * Defines the scrolling speed 44144 */ 44145 function setScrollingSpeed(value, type){ 44146 setVariableState('scrollingSpeed', value, type); 44147 } 44148 44149 /** 44150 * Sets fitToSection 44151 */ 44152 function setFitToSection(value, type){ 44153 setVariableState('fitToSection', value, type); 44154 } 44155 44156 /** 44157 * Sets lockAnchors 44158 */ 44159 function setLockAnchors(value){ 44160 options.lockAnchors = value; 44161 } 44162 44163 /** 44164 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 44165 */ 44166 function setMouseWheelScrolling(value){ 44167 if(value){ 44168 addMouseWheelHandler(); 44169 addMiddleWheelHandler(); 44170 }else{ 44171 removeMouseWheelHandler(); 44172 removeMiddleWheelHandler(); 44173 } 44174 } 44175 44176 /** 44177 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 44178 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 44179 * 44180 * @param directions string containing the direction or directions separated by comma. 44181 */ 44182 function setAllowScrolling(value, directions){ 44183 if(typeof directions !== 'undefined'){ 44184 directions = directions.replace(/ /g,'').split(','); 44185 44186 $.each(directions, function (index, direction){ 44187 setIsScrollAllowed(value, direction, 'm'); 44188 }); 44189 } 44190 else if(value){ 44191 setMouseWheelScrolling(true); 44192 addTouchHandler(); 44193 }else{ 44194 setMouseWheelScrolling(false); 44195 removeTouchHandler(); 44196 } 44197 } 44198 44199 /** 44200 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 44201 */ 44202 function setKeyboardScrolling(value, directions){ 44203 if(typeof directions !== 'undefined'){ 44204 directions = directions.replace(/ /g,'').split(','); 44205 44206 $.each(directions, function (index, direction){ 44207 setIsScrollAllowed(value, direction, 'k'); 44208 }); 44209 }else{ 44210 options.keyboardScrolling = value; 44211 } 44212 } 44213 44214 /** 44215 * Moves the page up one section. 44216 */ 44217 function moveSectionUp(){ 44218 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 44219 44220 //looping to the bottom if there's no more sections above 44221 if (!prev.length && (options.loopTop || options.continuousVertical)) {
44222 prev = $(SECTION_SEL).last(); 44223 } 44224 44225 if (prev.length) { 44226 scrollPage(prev, null, true); 44227 } 44228 } 44229 44230 /** 44231 * Moves the page down one section. 44232 */ 44233 function moveSectionDown(){ 44234 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 44235 44236 //looping to the top if there's no more sections below 44237 if(!next.length && 44238 (options.loopBottom || options.continuousVertical)){ 44239 next = $(SECTION_SEL).first(); 44240 } 44241 44242 if(next.length){ 44243 scrollPage(next, null, false); 44244 } 44245 } 44246 44247 /** 44248 * Moves the page to the given section and slide with no animation. 44249 * Anchors or index positions can be used as params. 44250 */ 44251 function silentMoveTo(sectionAnchor, slideAnchor){ 44252 setScrollingSpeed (0, 'internal'); 44253 moveTo(sectionAnchor, slideAnchor); 44254 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 44255 } 44256 44257 /** 44258 * Moves the page to the given section and slide. 44259 * Anchors or index positions can be used as params. 44260 */ 44261 function moveTo(sectionAnchor, slideAnchor){ 44262 var destiny = getSectionByAnchor(sectionAnchor); 44263 44264 if (typeof slideAnchor !== 'undefined'){ 44265 scrollPageAndSlide(sectionAnchor, slideAnchor); 44266 }else if(destiny.length > 0){ 44267 scrollPage(destiny); 44268 } 44269 } 44270 44271 /** 44272 * Slides right the slider of the active section. 44273 * Optional `section` param. 44274 */ 44275 function moveSlideRight(section){ 44276 moveSlide('right', section); 44277 } 44278 44279 /** 44280 * Slides left the slider of the active section. 44281 * Optional `section` param. 44282 */ 44283 function moveSlideLeft(section){ 44284 moveSlide('left', section); 44285 } 44286 44287 /** 44288 * When resizing is finished, we adjust the slides sizes and positions 44289 */ 44290 function reBuild(resizing){ 44291 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 44292 44293 isResizing = true; 44294 44295 windowsHeight = $window.height(); //updating global var 44296 44297 $(SECTION_SEL).each(function(){ 44298 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 44299 var slides = $(this).find(SLIDE_SEL); 44300 44301 //adjusting the height of the table-cell for IE and Firefox 44302 if(options.verticalCentered){ 44303 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 44304 } 44305 44306 $(this).css('height', windowsHeight + 'px'); 44307 44308 //resizing the scrolling divs 44309 if(options.scrollOverflow){ 44310 if(slides.length){ 44311 slides.each(function(){ 44312 createScrollBar($(this)); 44313 }); 44314 }else{ 44315 createScrollBar($(this)); 44316 } 44317 } 44318 44319 //adjusting the position fo the FULL WIDTH slides... 44320 if (slides.length > 1) { 44321 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 44322 } 44323 }); 44324 44325 var activeSection = $(SECTION_ACTIVE_SEL); 44326 var sectionIndex = activeSection.index(SECTION_SEL); 44327 44328 //isn't it the first section? 44329 if(sectionIndex){ 44330 //adjusting the position for the current section 44331 silentMoveTo(sectionIndex + 1); 44332 } 44333 44334 isResizing = false; 44335 // Uncode change 44336 // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 44337 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight()); 44338 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 44339 } 44340 44341 /** 44342 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 44343 * are smaller than the set limit values. 44344 */ 44345 function setResponsive(active){ 44346 var isResponsive = $body.hasClass(RESPONSIVE); 44347 44348 if(active){ 44349 if(!isResponsive){ 44350 setAutoScrolling(false, 'internal'); 44351 setFitToSection(false, 'internal'); 44352 $(SECTION_NAV_SEL).hide(); 44353 $body.addClass(RESPONSIVE); 44354 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 44355 } 44356 } 44357 else if(isResponsive){ 44358 setAutoScrolling(originals.autoScrolling, 'internal'); 44359 setFitToSection(originals.autoScrolling, 'internal'); 44360 $(SECTION_NAV_SEL).show(); 44361 $body.removeClass(RESPONSIVE); 44362 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 44363 } 44364 } 44365 44366 if($(this).length){ 44367 //public functions 44368 FP.setAutoScrolling = setAutoScrolling; 44369 FP.setRecordHistory = setRecordHistory; 44370 FP.setScrollingSpeed = setScrollingSpeed; 44371 FP.setFitToSection = setFitToSection; 44372 FP.setLockAnchors = setLockAnchors; 44373 FP.setMouseWheelScrolling = setMouseWheelScrolling; 44374 FP.setAllowScrolling = setAllowScrolling; 44375 FP.setKeyboardScrolling = setKeyboardScrolling; 44376 FP.moveSectionUp = moveSectionUp; 44377 FP.moveSectionDown = moveSectionDown; 44378 FP.silentMoveTo = silentMoveTo; 44379 FP.moveTo = moveTo; 44380 FP.moveSlideRight = moveSlideRight; 44381 FP.moveSlideLeft = moveSlideLeft; 44382 FP.fitToSection = fitToSection; 44383 FP.reBuild = reBuild; 44384 FP.setResponsive = setResponsive; 44385 FP.destroy = destroy; 44386 44387 init(); 44388 44389 bindEvents(); 44390 } 44391
44392 function init(){ 44393 //if css3 is not supported, it will use jQuery animations 44394 if(options.css3){ 44395 options.css3 = support3d(); 44396 } 44397 44398 options.scrollBar = options.scrollBar || options.hybrid; 44399 44400 setOptionsFromDOM(); 44401 prepareDom(); 44402 setAllowScrolling(true); 44403 setAutoScrolling(options.autoScrolling, 'internal'); 44404 responsive(); 44405 44406 //setting the class for the body element 44407 setBodyClass(); 44408 44409 //Uncode addition 44410 // if(document.readyState === 'complete'){ 44411 // scrollToAnchor(); 44412 // } 44413 // $window.on('load', scrollToAnchor); 44414 } 44415 44416 function bindEvents(){ 44417 $window 44418 //when scrolling... 44419 //.on('scroll', scrollHandler) 44420 44421 //detecting any change on the URL to scroll to the given anchor link 44422 //(a way to detect back history button as we play with the hashes on the URL) 44423 .on('hashchange', hashChangeHandler) 44424 44425 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 44426 .blur(blurHandler) 44427 44428 //when resizing the site, we adjust the heights of the sections, slimScroll... 44429 .resize(resizeHandler); 44430 44431 $document 44432 //Sliding with arrow keys, both, vertical and horizontal 44433 .keydown(keydownHandler) 44434 44435 //to prevent scrolling while zooming 44436 .keyup(keyUpHandler) 44437 44438 //Scrolls to the section when clicking the navigation bullet 44439 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 44440 44441 //Scrolls the slider to the given slide destination for the given section 44442 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 44443 44444 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 44445 44446 //Scrolling horizontally when clicking on the slider controls. 44447 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 44448 44449 /** 44450 * Applying normalScroll elements. 44451 * Ignoring the scrolls over the specified selectors. 44452 */ 44453 if(options.normalScrollElements){ 44454 $document.on('mouseenter', options.normalScrollElements, function () { 44455 setMouseWheelScrolling(false); 44456 }); 44457 44458 $document.on('mouseleave', options.normalScrollElements, function(){ 44459 setMouseWheelScrolling(true); 44460 }); 44461 } 44462 } 44463 44464 /** 44465 * Setting options from DOM elements if they are not provided. 44466 */ 44467 function setOptionsFromDOM(){ 44468 var sections = container.find(options.sectionSelector); 44469 44470 //no anchors option? Checking for them in the DOM attributes 44471 if(!options.anchors.length){ 44472 options.anchors = sections.filter('[data-anchor]').map(function(){ 44473 return $(this).data('anchor').toString(); 44474 }).get(); 44475 } 44476 44477 //no tooltips option? Checking for them in the DOM attributes 44478 if(!options.navigationTooltips.length){ 44479 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 44480 return $(this).data('tooltip').toString(); 44481 }).get(); 44482 } 44483 } 44484 44485 /** 44486 * Works over the DOM structure to set it up for the current fullpage options. 44487 */ 44488 function prepareDom(){ 44489 container.css({ 44490 'height': '100%', 44491 'position': 'relative' 44492 }); 44493 44494 //adding a class to recognize the container internally in the code 44495 container.addClass(WRAPPER); 44496 $('html').addClass(ENABLED); 44497 44498 windowsHeight = $window.height(); 44499 44500 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 44501 44502 addInternalSelectors(); 44503 44504 //styling the sections / slides / menu 44505 $(SECTION_SEL).each(function(index){ 44506 var section = $(this); 44507 var slides = section.find(SLIDE_SEL); 44508 var numSlides = slides.length; 44509 44510 styleSection(section, index); 44511 styleMenu(section, index); 44512 44513 // if there's any slide 44514 if (numSlides > 0) { 44515 styleSlides(section, slides, numSlides); 44516 }else{ 44517 if(options.verticalCentered){ 44518 addTableClass(section); 44519 } 44520 } 44521 }); 44522 44523 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 44524 if(options.fixedElements && options.css3){ 44525 $(options.fixedElements).appendTo($body); 44526 } 44527 44528 //vertical centered of the navigation + active bullet 44529 if(options.navigation){ 44530 addVerticalNavigation(); 44531 } 44532 44533 enableYoutubeAPI(); 44534 44535 if(options.scrollOverflow){ 44536 if(document.readyState === 'complete'){ 44537 createScrollBarHandler(); 44538 } 44539 //after DOM and images are loaded 44540 $window.on('load', createScrollBarHandler); 44541 }else{ 44542 afterRenderActions(); 44543 } 44544 } 44545 44546 /** 44547 * Styles the horizontal slides for a section. 44548 */ 44549 function styleSlides(section, slides, numSlides){ 44550 var sliderWidth = numSlides * 100; 44551 var slideWidth = 100 / numSlides; 44552 44553 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 44554 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 44555 44556 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 44557 44558 if(numSlides > 1){ 44559 if(options.controlArrows){ 44560 createSlideArrows(section); 44561 } 44562 44563 if(options.slidesNavigation){ 44564 addSlidesNavigation(section, numSlides); 44565 } 44566 } 44567 44568 slides.each(function(index) { 44569 $(this).css('width', slideWidth + '%'); 44570 44571 if(options.verticalCentered){ 44572 addTableClass($(this)); 44573 } 44574 }); 44575 44576 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 44577 44578 //if the slide won't be an starting point, the default will be the first one 44579 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
44579ide by default. 44580 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 44581 silentLandscapeScroll(startingSlide, 'internal'); 44582 }else{ 44583 slides.eq(0).addClass(ACTIVE); 44584 } 44585 } 44586 44587 /** 44588 * Styling vertical sections 44589 */ 44590 function styleSection(section, index){ 44591 //if no active section is defined, the 1st one will be the default one 44592 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 44593 section.addClass(ACTIVE); 44594 } 44595 startingSection = $(SECTION_ACTIVE_SEL); 44596 44597 section.css('height', windowsHeight + 'px'); 44598 44599 if(options.paddingTop){ 44600 section.css('padding-top', options.paddingTop); 44601 } 44602 44603 if(options.paddingBottom){ 44604 section.css('padding-bottom', options.paddingBottom); 44605 } 44606 44607 if (typeof options.sectionsColor[index] !== 'undefined') { 44608 section.css('background-color', options.sectionsColor[index]); 44609 } 44610 44611 if (typeof options.anchors[index] !== 'undefined') { 44612 section.attr('data-anchor', options.anchors[index]); 44613 } 44614 } 44615 44616 /** 44617 * Sets the data-anchor attributes to the menu elements and activates the current one. 44618 */ 44619 function styleMenu(section, index){ 44620 if (typeof options.anchors[index] !== 'undefined') { 44621 //activating the menu / nav element on load 44622 if(section.hasClass(ACTIVE)){ 44623 activateMenuAndNav(options.anchors[index], index); 44624 } 44625 } 44626 44627 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 44628 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 44629 $(options.menu).appendTo($body); 44630 } 44631 } 44632 44633 /** 44634 * Adds internal classes to be able to provide customizable selectors 44635 * keeping the link with the style sheet. 44636 */ 44637 function addInternalSelectors(){ 44638 container.find(options.sectionSelector).addClass(SECTION); 44639 container.find(options.slideSelector).addClass(SLIDE); 44640 } 44641 44642 /** 44643 * Creates the control arrows for the given section 44644 */ 44645 function createSlideArrows(section){ 44646 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 44647 44648 if(options.controlArrowColor!='#fff'){ 44649 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 44650 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 44651 } 44652 44653 if(!options.loopHorizontal){ 44654 section.find(SLIDES_ARROW_PREV_SEL).hide(); 44655 } 44656 } 44657 44658 /** 44659 * Creates a vertical navigation bar. 44660 */ 44661 function addVerticalNavigation(){ 44662 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 44663 var nav = $(SECTION_NAV_SEL); 44664 44665 nav.addClass(function() { 44666 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 44667 }); 44668 44669 for (var i = 0; i < $(SECTION_SEL).length; i++) { 44670 var link = ''; 44671 if (options.anchors.length) { 44672 link = options.anchors[i]; 44673 } 44674 44675 var li = '<li><a href="#' + link + '"><span></span></a>'; 44676 44677 // Only add tooltip if needed (defined by user) 44678 var tooltip = options.navigationTooltips[i]; 44679 44680 if (typeof tooltip !== 'undefined' && tooltip !== '') { 44681 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 44682 } 44683 44684 li += '</li>'; 44685 44686 nav.find('ul').append(li); 44687 } 44688 44689 //centering it vertically 44690 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 44691 44692 //activating the current active section 44693 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 44694 } 44695 44696 /** 44697 * Creates the slim scroll scrollbar for the sections and slides inside them. 44698 */ 44699 function createScrollBarHandler(){ 44700 $(SECTION_SEL).each(function(){ 44701 var slides = $(this).find(SLIDE_SEL); 44702 44703 if(slides.length){ 44704 slides.each(function(){ 44705 createScrollBar($(this)); 44706 }); 44707 }else{ 44708 createScrollBar($(this)); 44709 } 44710 44711 }); 44712 afterRenderActions(); 44713 } 44714 44715 /*
44716 * Enables the Youtube videos API so we can control their flow if necessary. 44717 */ 44718 function enableYoutubeAPI(){ 44719 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 44720 addURLParam($(this), 'enablejsapi=1'); 44721 }); 44722 } 44723 44724 /** 44725 * Adds a new parameter and its value to the `src` of a given element 44726 */ 44727 function addURLParam(element, newParam){ 44728 var originalSrc = element.attr('src'); 44729 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 44730 } 44731 44732 /* 44733 * Returns the prefix sign to use for a new parameter in an existen URL. 44734 * 44735 * @return {String} ? | & 44736 */ 44737 function getUrlParamSign(url){ 44738 return ( !/\?/.test( url ) ) ? '?' : '&'; 44739 } 44740 44741 /** 44742 * Actions and callbacks to fire afterRender 44743 */ 44744 function afterRenderActions(){ 44745 var section = $(SECTION_ACTIVE_SEL); 44746 44747 section.addClass(COMPLETELY); 44748 44749 if(options.scrollOverflowHandler.afterRender){ 44750 options.scrollOverflowHandler.afterRender(section); 44751 } 44752 lazyLoad(section); 44753 playMedia(section); 44754 options.scrollOverflowHandler.afterLoad(); 44755 44756 if(isDestinyTheStartingSection()){ 44757 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 44758 } 44759 44760 // Uncode change 44761 // $.isFunction( options.afterRender ) && options.afterRender.call(container); 44762 $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight()); 44763 } 44764 44765 /** 44766 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 44767 */ 44768 function isDestinyTheStartingSection(){ 44769 var anchors = window.location.hash.replace('#', '').split('/'); 44770 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 44771 44772 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 44773 } 44774 44775 44776 var isScrolling = false; 44777 var lastScroll = 0; 44778 44779 //when scrolling... 44780 function scrollHandler(){ 44781 var currentSection; 44782 44783 if(!options.autoScrolling || options.scrollBar){ 44784 var currentScroll = $window.scrollTop(); 44785 var scrollDirection = getScrollDirection(currentScroll); 44786 var visibleSectionIndex = 0; 44787 var screen_mid = currentScroll + ($window.height() / 2.0); 44788 var isAtBottom = $body.height() - $window.height() === currentScroll; 44789 var sections = document.querySelectorAll(SECTION_SEL); 44790 44791 //when using `auto-height` for a small last section it won't be centered in the viewport 44792 if(isAtBottom){ 44793 visibleSectionIndex = sections.length - 1; 44794 } 44795 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 44796 else if(!currentScroll){ 44797 visibleSectionIndex = 0; 44798 } 44799 44800 //taking the section which is showing more content in the viewport 44801 else{ 44802 for (var i = 0; i < sections.length; ++i) { 44803 var section = sections[i]; 44804 44805 // Pick the the last section which passes the middle line of the screen. 44806 if (section.offsetTop <= screen_mid) 44807 { 44808 visibleSectionIndex = i; 44809 } 44810 } 44811 } 44812 44813 if(isCompletelyInViewPort(scrollDirection)){ 44814 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 44815 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 44816 } 44817 } 44818 44819 //geting the last one, the current one on the screen 44820 currentSection = $(sections).eq(visibleSectionIndex); 44821 44822 //setting the visible section as active when manually scrolling 44823 //executing only once the first time we reach the section 44824 if(!currentSection.hasClass(ACTIVE)){ 44825 isScrolling = true; 44826 var leavingSection = $(SECTION_ACTIVE_SEL); 44827 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 44828 var yMovement = getYmovement(currentSection); 44829 var anchorLink = currentSection.data('anchor'); 44830 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 44831 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 44832 var slideIndex; 44833 var slideAnchorLink; 44834 44835 if(activeSlide.length){ 44836 slideAnchorLink = activeSlide.data('anchor'); 44837 slideIndex = activeSlide.index(); 44838 } 44839 44840 if(canScroll){ 44841 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 44842 44843 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 44844 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 44845 44846 stopMedia(leavingSection); 44847 lazyLoad(currentSection); 44848 playMedia(currentSection); 44849 44850 activateMenuAndNav(anchorLink, sectionIndex - 1); 44851 44852 if(options.anchors.length){ 44853 //needed to enter in hashChange event when using the menu with anchor links 44854 lastScrolledDestiny = anchorLink; 44855 } 44856 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 44857 } 44858 44859 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 44860 clearTimeout(scrollId); 44861 scrollId = setTimeout(function(){ 44862 isScrolling = false;
44863 }, 100); 44864 } 44865 44866 if(options.fitToSection){ 44867 //for the auto adjust of the viewport to fit a whole section 44868 clearTimeout(scrollId2); 44869 44870 scrollId2 = setTimeout(function(){ 44871 //checking it again in case it changed during the delay 44872 if(options.fitToSection){ 44873 fitToSection(); 44874 } 44875 }, options.fitToSectionDelay); 44876 } 44877 } 44878 } 44879 44880 /** 44881 * Fits the site to the nearest active section 44882 */ 44883 function fitToSection(){ 44884 //checking fitToSection again in case it was set to false before the timeout delay 44885 if(canScroll){ 44886 //allows to scroll to an active section and 44887 //if the section is already active, we prevent firing callbacks 44888 isResizing = true; 44889 44890 scrollPage($(SECTION_ACTIVE_SEL)); 44891 isResizing = false; 44892 } 44893 } 44894 44895 /** 44896 * Determines whether the active section has seen in its whole or not. 44897 */ 44898 function isCompletelyInViewPort(movement){ 44899 var top = $(SECTION_ACTIVE_SEL).position().top; 44900 var bottom = top + $window.height(); 44901 44902 if(movement == 'up'){ 44903 return bottom >= ($window.scrollTop() + $window.height()); 44904 } 44905 return top <= $window.scrollTop(); 44906 } 44907 44908 /** 44909 * Gets the directon of the the scrolling fired by the scroll event. 44910 */ 44911 function getScrollDirection(currentScroll){ 44912 var direction = currentScroll > lastScroll ? 'down' : 'up'; 44913 44914 lastScroll = currentScroll; 44915 44916 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 44917 previousDestTop = currentScroll; 44918 44919 return direction; 44920 } 44921 44922 /** 44923 * Determines the way of scrolling up or down: 44924 * by 'automatically' scrolling a section or by using the default and normal scrolling. 44925 */ 44926 function scrolling(type, scrollable){ 44927 if (!isScrollAllowed.m[type]){ 44928 return; 44929 } 44930 var check = (type === 'down') ? 'bottom' : 'top'; 44931 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 44932 44933 if(scrollable.length > 0 ){ 44934 //is the scrollbar at the start/end of the scroll? 44935 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 44936 scrollSection(); 44937 }else{ 44938 return true; 44939 } 44940 }else{ 44941 // moved up/down 44942 scrollSection(); 44943 } 44944 } 44945 44946 /* 44947 * Preventing bouncing in iOS #2285 44948 */ 44949 function preventBouncing(event){ 44950 var e = event.originalEvent; 44951 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){ 44952 //preventing the easing on iOS devices 44953 event.preventDefault(); 44954 } 44955 } 44956 44957 var touchStartY = 0; 44958 var touchStartX = 0; 44959 var touchEndY = 0; 44960 var touchEndX = 0; 44961 44962 /* Detecting touch events 44963 44964 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 44965 * This way, the touchstart and the touch moves shows an small difference between them which is the 44966 * used one to determine the direction. 44967 */ 44968 function touchMoveHandler(event){ 44969 var e = event.originalEvent; 44970 var activeSection = $(e.target).closest(SECTION_SEL); 44971 44972 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 44973 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 44974 44975 if(options.autoScrolling){ 44976 //preventing the easing on iOS devices 44977 event.preventDefault(); 44978 } 44979 44980 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 44981 var touchEvents = getEventsPage(e); 44982 44983 touchEndY = touchEvents.y; 44984 touchEndX = touchEvents.x; 44985 44986 //if movement in the X axys is greater than in the Y and the currect section has slides... 44987 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 44988 44989 //is the movement greater than the minimum resistance to scroll? 44990 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 44991 if (touchStartX > touchEndX) { 44992 if(isScrollAllowed.m.right){ 44993 moveSlideRight(activeSection); //next 44994 } 44995 } else { 44996 if(isScrollAllowed.m.left){ 44997 moveSlideLeft(activeSection); //prev 44998 } 44999 } 45000 } 45001 } 45002 45003 //vertical scrolling (only when autoScrolling is enabled) 45004 else if(options.autoScrolling && canScroll){ 45005 45006 //is the movement greater than the minimum resistance to scroll? 45007 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 45008 if (touchStartY > touchEndY) { 45009 scrolling('down', scrollable); 45010 } else if (touchEndY > touchStartY) { 45011 scrolling('up', scrollable); 45012 } 45013 } 45014 } 45015 } 45016 } 45017 45018 /** 45019 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 45020 * Currently works well for iOS - Android might need some testing 45021 * @param {Element} el target element / jquery selector (in subsequent nodes) 45022 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 45023 * @return {boolean} true if there is a match to options.normalScrollElements 45024 */ 45025 function checkParentForNormalScrollElement (el, hop) { 45026 hop = hop || 0; 45027 var parent = $(el).parent(); 45028 45029 if (hop < options.normalScrollElementTouchThreshold && 45030 parent.is(options.normalScrollElements) ) { 45031 return true; 45032 } else if (hop == options.normalScrollElementTouchThreshold) { 45033 return false;
45034 } else { 45035 return checkParentForNormalScrollElement(parent, ++hop); 45036 } 45037 } 45038 45039 /** 45040 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 45041 * this way we make sure that is really a touch event what IE is detecting. 45042 */ 45043 function isReallyTouch(e){ 45044 //if is not IE || IE is detecting `touch` or `pen` 45045 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 45046 } 45047 45048 /** 45049 * Handler for the touch start event. 45050 */ 45051 function touchStartHandler(event){ 45052 var e = event.originalEvent; 45053 45054 //stopping the auto scroll to adjust to a section 45055 if(options.fitToSection){ 45056 $htmlBody.stop(); 45057 } 45058 45059 if(isReallyTouch(e)){ 45060 var touchEvents = getEventsPage(e); 45061 touchStartY = touchEvents.y; 45062 touchStartX = touchEvents.x; 45063 } 45064 } 45065 45066 /** 45067 * Gets the average of the last `number` elements of the given array. 45068 */ 45069 function getAverage(elements, number){ 45070 var sum = 0; 45071 45072 //taking `number` elements from the end to make the average, if there are not enought, 1 45073 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 45074 45075 for(var i = 0; i < lastElements.length; i++){ 45076 sum = sum + lastElements[i]; 45077 } 45078 45079 return Math.ceil(sum/number); 45080 } 45081 45082 /** 45083 * Detecting mousewheel scrolling 45084 * 45085 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 45086 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 45087 */ 45088 var prevTime = new Date().getTime(); 45089 45090 function MouseWheelHandler(e) { 45091 var curTime = new Date().getTime(); 45092 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 45093 45094 //autoscrolling and not zooming? 45095 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 45096 // cross-browser wheel delta 45097 e = e || window.event; 45098 var value = e.wheelDelta || -e.deltaY || -e.detail; 45099 var delta = Math.max(-1, Math.min(1, value)); 45100 45101 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 45102 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 45103 45104 //Limiting the array to 150 (lets not waste memory!) 45105 if(scrollings.length > 149){ 45106 scrollings.shift(); 45107 } 45108 45109 //keeping record of the previous scrollings 45110 scrollings.push(Math.abs(value)); 45111 45112 //preventing to scroll the site on mouse wheel when scrollbar is present 45113 if(options.scrollBar){ 45114 e.preventDefault ? e.preventDefault() : e.returnValue = false; 45115 } 45116 45117 var activeSection = $(SECTION_ACTIVE_SEL); 45118 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 45119 45120 //time difference between the last scroll and the current one 45121 var timeDiff = curTime-prevTime; 45122 prevTime = curTime; 45123 45124 //haven't they scrolled in a while? 45125 //(enough to be consider a different scrolling action to scroll another section) 45126 if(timeDiff > 200){ 45127 //emptying the array, we dont care about old scrollings for our averages 45128 scrollings = []; 45129 } 45130 45131 if(canScroll){ 45132 var averageEnd = getAverage(scrollings, 10); 45133 var averageMiddle = getAverage(scrollings, 70); 45134 var isAccelerating = averageEnd >= averageMiddle; 45135 45136 //to avoid double swipes... 45137 if(isAccelerating && isScrollingVertically){ 45138 //scrolling down? 45139 if (delta < 0) { 45140 scrolling('down', scrollable); 45141 45142 //scrolling up? 45143 }else { 45144 scrolling('up', scrollable); 45145 } 45146 } 45147 } 45148 45149 return false;
45150 } 45151 45152 if(options.fitToSection){ 45153 //stopping the auto scroll to adjust to a section 45154 $htmlBody.stop(); 45155 } 45156 } 45157 45158 /** 45159 * Slides a slider to the given direction. 45160 * Optional `section` param. 45161 */ 45162 function moveSlide(direction, section){ 45163 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 45164 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 45165 var numSlides = slides.find(SLIDE_SEL).length; 45166 45167 // more than one slide needed and nothing should be sliding 45168 if (!slides.length || slideMoving || numSlides < 2) { 45169 return; 45170 } 45171 45172 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 45173 var destiny = null; 45174 45175 if(direction === 'left'){ 45176 destiny = currentSlide.prev(SLIDE_SEL); 45177 }else{ 45178 destiny = currentSlide.next(SLIDE_SEL); 45179 } 45180 45181 //isn't there a next slide in the secuence? 45182 if(!destiny.length){ 45183 //respect loopHorizontal settin 45184 if (!options.loopHorizontal) return; 45185 45186 if(direction === 'left'){ 45187 destiny = currentSlide.siblings(':last'); 45188 }else{ 45189 destiny = currentSlide.siblings(':first'); 45190 } 45191 } 45192 45193 slideMoving = true; 45194 45195 landscapeScroll(slides, destiny, direction); 45196 } 45197 45198 /** 45199 * Maintains the active slides in the viewport 45200 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 45201 */ 45202 function keepSlidesPosition(){ 45203 $(SLIDE_ACTIVE_SEL).each(function(){ 45204 silentLandscapeScroll($(this), 'internal'); 45205 }); 45206 } 45207 45208 var previousDestTop = 0; 45209 /** 45210 * Returns the destination Y position based on the scrolling direction and 45211 * the height of the section. 45212 */ 45213 function getDestinationPosition(element){ 45214 var elemPosition = element.position(); 45215 45216 //top of the desination will be at the top of the viewport 45217 var position = elemPosition.top; 45218 var isScrollingDown = elemPosition.top > previousDestTop; 45219 var sectionBottom = position - windowsHeight + element.outerHeight(); 45220 var bigSectionsDestination = options.bigSectionsDestination; 45221 45222 //Uncode addition 45223 var containerH = container.outerHeight(); 45224 var containerPosition = container.offset(); 45225 45226 //########### Commented by Uncode - START ########### 45227 //is the destination element bigger than the viewport? 45228 // if(element.outerHeight() > windowsHeight){ 45229 // //scrolling up? 45230 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 45231 // position = sectionBottom; 45232 // } 45233 // } 45234 45235 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 45236 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 45237 // //The bottom of the destination will be at the bottom of the viewport 45238 // position = sectionBottom; 45239 // } 45240 //########### Commented by Uncode - END ########### 45241 45242 //Uncode addition 45243 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 45244 position += 18; 45245 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 45246 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 45247 } 45248 45249 /* 45250 Keeping record of the last scrolled position to determine the scrolling direction. 45251 No conventional methods can be used as the scroll bar might not be present 45252 AND the section might not be active if it is auto-height and didnt reach the middle 45253 of the viewport. 45254 */ 45255 previousDestTop = position; 45256 return position; 45257 } 45258 45259 /** 45260 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 45261 */ 45262 function scrollPage(element, callback, isMovementUp){ 45263 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 45264 45265 var dtop = getDestinationPosition(element); 45266 var slideAnchorLink; 45267 var slideIndex; 45268 45269 //local variables 45270 var v = { 45271 element: element, 45272 callback: callback, 45273 isMovementUp: isMovementUp, 45274 dtop: dtop, 45275 yMovement: getYmovement(element), 45276 anchorLink: element.data('anchor'), 45277 sectionIndex: element.index(SECTION_SEL), 45278 activeSlide: element.find(SLIDE_ACTIVE_SEL), 45279 activeSection: $(SECTION_ACTIVE_SEL), 45280 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 45281 45282 //caching the value of isResizing at the momment the function is called 45283 //because it will be checked later inside a setTimeout and the value might change 45284 localIsResizing: isResizing 45285 }; 45286 45287 //quiting when destination scroll is the same as the current one 45288 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 45289 45290 if(v.activeSlide.length){ 45291 slideAnchorLink = v.activeSlide.data('anchor'); 45292 slideIndex = v.activeSlide.index(); 45293 } 45294 45295 // If continuousVertical && we need to wrap around 45296 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 45297 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 45298 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 45299 45300 v = createInfiniteSections(v); 45301 } 45302 45303 //callback (onLeave) if the site is not just resizing and readjusting the slides 45304 if($.isFunction(options.onLeave) && !v.localIsResizing){ 45305 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 45306 return; 45307 } 45308 } 45309 45310 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 45311 if(!v.localIsResizing){ 45312 stopMedia(v.activeSection); 45313 } 45314 45315 options.scrollOverflowHandler.beforeLeave(); 45316 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 45317 lazyLoad(element); 45318 options.scrollOverflowHandler.onLeave(); 45319 45320 45321 //preventing from activating the MouseWheelHandler event 45322 //more than once if the page is scrolling 45323 canScroll = false;
45324 45325 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 45326 45327 performMovement(v); 45328 45329 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 45330 lastScrolledDestiny = v.anchorLink; 45331 45332 //avoid firing it twice (as it does also on scroll) 45333 activateMenuAndNav(v.anchorLink, v.sectionIndex); 45334 } 45335 45336 /** 45337 * Performs the vertical movement (by CSS3 or by jQuery) 45338 */ 45339 function performMovement(v){ 45340 // using CSS3 translate functionality 45341 if (options.css3 && options.autoScrolling && !options.scrollBar) { 45342 45343 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 45344 // that's why we round it to 0. 45345 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 45346 transformContainer(translate3d, true); 45347 45348 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 45349 //scrollingSpeed to change in case of using silentMoveTo(); 45350 if(options.scrollingSpeed){ 45351 clearTimeout(afterSectionLoadsId); 45352 afterSectionLoadsId = setTimeout(function () { 45353 afterSectionLoads(v); 45354 }, options.scrollingSpeed); 45355 }else{ 45356 afterSectionLoads(v); 45357 } 45358 } 45359 45360 // using jQuery animate 45361 else{ 45362 var scrollSettings = getScrollSettings(v); 45363 45364 $(scrollSettings.element).animate( 45365 scrollSettings.options, 45366 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 45367 if(options.scrollBar){ 45368 45369 /* Hack! 45370 The timeout prevents setting the most dominant section in the viewport as "active" when the user 45371 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 45372 45373 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 45374 */ 45375 setTimeout(function(){ 45376 afterSectionLoads(v); 45377 },30); 45378 }else{ 45379 afterSectionLoads(v); 45380 } 45381 }); 45382 } 45383 } 45384 45385 /** 45386 * Gets the scrolling settings depending on the plugin autoScrolling option 45387 */ 45388 function getScrollSettings(v){ 45389 var scroll = {}; 45390 45391 if(options.autoScrolling && !options.scrollBar){ 45392 scroll.options = { 'top': -v.dtop}; 45393 scroll.element = WRAPPER_SEL; 45394 }else{ 45395 scroll.options = { 'scrollTop': v.dtop}; 45396 scroll.element = 'html, body'; 45397 } 45398 45399 return scroll; 45400 } 45401 45402 /** 45403 * Adds sections before or after the current one to create the infinite effect. 45404 */ 45405 function createInfiniteSections(v){ 45406 // Scrolling down 45407 if (!v.isMovementUp) { 45408 // Move all previous sections to after the active section 45409 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 45410 } 45411 else { // Scrolling up 45412 // Move all next sections to before the active section 45413 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 45414 } 45415 45416 // Maintain the displayed position (now that we changed the element order) 45417 silentScroll($(SECTION_ACTIVE_SEL).position().top); 45418 45419 // Maintain the active slides visible in the viewport 45420 keepSlidesPosition(); 45421 45422 // save for later the elements that still need to be reordered 45423 v.wrapAroundElements = v.activeSection; 45424 45425 // Recalculate animation variables 45426 v.dtop = v.element.position().top; 45427 v.yMovement = getYmovement(v.element); 45428 45429 return v; 45430 } 45431 45432 /** 45433 * Fix section order after continuousVertical changes have been animated 45434 */ 45435 function continuousVerticalFixSectionOrder (v) {
45436 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 45437 // finish moving the elements around so the direct navigation will function more simply 45438 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 45439 return; 45440 } 45441 45442 if (v.isMovementUp) { 45443 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 45444 } 45445 else { 45446 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 45447 } 45448 45449 silentScroll($(SECTION_ACTIVE_SEL).position().top); 45450 45451 // Maintain the active slides visible in the viewport 45452 keepSlidesPosition(); 45453 } 45454 45455 45456 /** 45457 * Actions to do once the section is loaded. 45458 */ 45459 function afterSectionLoads (v){ 45460 continuousVerticalFixSectionOrder(v); 45461 45462 //callback (afterLoad) if the site is not just resizing and readjusting the slides 45463 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 45464 options.scrollOverflowHandler.afterLoad(); 45465 45466 if(!v.localIsResizing){ 45467 playMedia(v.element); 45468 } 45469 45470 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 45471 45472 canScroll = true; 45473 45474 $.isFunction(v.callback) && v.callback.call(this); 45475 } 45476 45477 /** 45478 * Sets the value for the given attribute from the `data-` attribute with the same suffix 45479 * ie: data-srcset ==> srcset | data-src ==> src 45480 */ 45481 function setSrc(element, attribute){ 45482 element 45483 .attr(attribute, element.data(attribute)) 45484 .removeAttr('data-' + attribute); 45485 } 45486 45487 /** 45488 * Lazy loads image, video and audio elements. 45489 */ 45490 function lazyLoad(destiny){ 45491 if (!options.lazyLoading){ 45492 return; 45493 } 45494 45495 var panel = getSlideOrSection(destiny); 45496 var element; 45497 45498 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 45499 element = $(this); 45500 45501 $.each(['src', 'srcset'], function(index, type){ 45502 var attribute = element.attr('data-' + type); 45503 if(typeof attribute !== 'undefined' && attribute){ 45504 setSrc(element, type); 45505 } 45506 }); 45507 45508 if(element.is('source')){ 45509 element.closest('video').get(0).load(); 45510 } 45511 }); 45512 } 45513 45514 /** 45515 * Plays video and audio elements. 45516 */ 45517 function playMedia(destiny){ 45518 var panel = getSlideOrSection(destiny); 45519 45520 //playing HTML5 media elements 45521 panel.find('video, audio').each(function(){ 45522 var element = $(this).get(0); 45523 45524 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 45525 element.play(); 45526 } 45527 }); 45528 45529 //youtube videos 45530 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 45531 var element = $(this).get(0); 45532 45533 if ( element.hasAttribute('data-autoplay') ){ 45534 playYoutube(element); 45535 } 45536 45537 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 45538 element.onload = function() { 45539 if ( element.hasAttribute('data-autoplay') ){ 45540 playYoutube(element); 45541 } 45542 }; 45543 }); 45544 } 45545 45546 /** 45547 * Plays a youtube video 45548 */ 45549 function playYoutube(element){ 45550 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 45551 } 45552 45553 /** 45554 * Stops video and audio elements. 45555 */ 45556 function stopMedia(destiny){ 45557 var panel = getSlideOrSection(destiny); 45558 45559 //stopping HTML5 media elements 45560 panel.find('video, audio').each(function(){ 45561 var element = $(this).get(0); 45562 45563 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 45564 element.pause(); 45565 } 45566 }); 45567 45568 //youtube videos 45569 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 45570 var element = $(this).get(0); 45571 45572 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 45573 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 45574 } 45575 }); 45576 } 45577 45578 /** 45579 * Gets the active slide (or section) for the given section 45580 */ 45581 function getSlideOrSection(destiny){ 45582 var slide = destiny.find(SLIDE_ACTIVE_SEL); 45583 if( slide.length ) { 45584 destiny = $(slide); 45585 } 45586 45587 return destiny; 45588 } 45589 45590 /**
45591 * Scrolls to the anchor in the URL when loading the site 45592 */ 45593 function scrollToAnchor(){ 45594 //getting the anchor link in the URL and deleting the `#` 45595 var value = window.location.hash.replace('#', '').split('/'); 45596 var sectionAnchor = decodeURIComponent(value[0]); 45597 var slideAnchor = decodeURIComponent(value[1]); 45598 45599 if(sectionAnchor){ //if theres any # 45600 if(options.animateAnchor){ 45601 scrollPageAndSlide(sectionAnchor, slideAnchor); 45602 }else{ 45603 silentMoveTo(sectionAnchor, slideAnchor); 45604 } 45605 } 45606 } 45607 45608 /** 45609 * Detecting any change on the URL to scroll to the given anchor link 45610 * (a way to detect back history button as we play with the hashes on the URL) 45611 */ 45612 function hashChangeHandler(){ 45613 if(!isScrolling && !options.lockAnchors){ 45614 var value = window.location.hash.replace('#', '').split('/'); 45615 var sectionAnchor = decodeURIComponent(value[0]); 45616 var slideAnchor = decodeURIComponent(value[1]); 45617 45618 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 45619 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 45620 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 45621 45622 45623 if(sectionAnchor.length){ 45624 /*in order to call scrollpage() only once for each destination at a time 45625 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 45626 event is fired on every scroll too.*/ 45627 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 45628 scrollPageAndSlide(sectionAnchor, slideAnchor); 45629 } 45630 } 45631 } 45632 } 45633 45634 //Sliding with arrow keys, both, vertical and horizontal 45635 function keydownHandler(e) { 45636 45637 clearTimeout(keydownId); 45638 45639 var activeElement = $(':focus'); 45640 45641 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 45642 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 45643 options.keyboardScrolling && options.autoScrolling){ 45644 var keyCode = e.which; 45645 45646 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 45647 var keyControls = [40, 38, 32, 33, 34]; 45648 if($.inArray(keyCode, keyControls) > -1){ 45649 e.preventDefault(); 45650 } 45651 45652 controlPressed = e.ctrlKey; 45653 45654 keydownId = setTimeout(function(){ 45655 onkeydown(e); 45656 },150); 45657 } 45658 } 45659 45660 function tooltipTextHandler(){ 45661 $(this).prev().trigger('click'); 45662 } 45663 45664 //to prevent scrolling while zooming 45665 function keyUpHandler(e){ 45666 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 45667 controlPressed = e.ctrlKey; 45668 } 45669 } 45670 45671 //binding the mousemove when the mouse's middle button is released 45672 function mouseDownHandler(e){ 45673 //middle button 45674 if (e.which == 2){ 45675 oldPageY = e.pageY; 45676 container.on('mousemove', mouseMoveHandler); 45677 } 45678 } 45679 45680 //unbinding the mousemove when the mouse's middle button is released 45681 function mouseUpHandler(e){ 45682 //middle button 45683 if (e.which == 2){ 45684 container.off('mousemove'); 45685 } 45686 } 45687 45688 //Scrolling horizontally when clicking on the slider controls. 45689 function slideArrowHandler(){ 45690 var section = $(this).closest(SECTION_SEL); 45691 45692 if ($(this).hasClass(SLIDES_PREV)) { 45693 if(isScrollAllowed.m.left){ 45694 moveSlideLeft(section); 45695 } 45696 } else { 45697 if(isScrollAllowed.m.right){ 45698 moveSlideRight(section); 45699 } 45700 } 45701 } 45702 45703 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 45704 function blurHandler(){ 45705 isWindowFocused = false;
45706 controlPressed = false; 45707 } 45708 45709 //Scrolls to the section when clicking the navigation bullet 45710 function sectionBulletHandler(e){ 45711 e.preventDefault(); 45712 var index = $(this).parent().index(); 45713 scrollPage($(SECTION_SEL).eq(index)); 45714 } 45715 45716 //Scrolls the slider to the given slide destination for the given section 45717 function slideBulletHandler(e){ 45718 e.preventDefault(); 45719 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 45720 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 45721 45722 landscapeScroll(slides, destiny); 45723 } 45724 45725 /** 45726 * Keydown event 45727 */ 45728 function onkeydown(e){ 45729 var shiftPressed = e.shiftKey; 45730 45731 //do nothing if we can not scroll or we are not using horizotnal key arrows. 45732 if(!canScroll && [37,39].indexOf(e.which) < 0){ 45733 return; 45734 } 45735 45736 switch (e.which) { 45737 //up 45738 case 38: 45739 case 33: 45740 if(isScrollAllowed.k.up){ 45741 moveSectionUp(); 45742 } 45743 break; 45744 45745 //down 45746 case 32: //spacebar 45747 if(shiftPressed && isScrollAllowed.k.up){ 45748 moveSectionUp(); 45749 break; 45750 } 45751 /* falls through */ 45752 case 40: 45753 case 34: 45754 if(isScrollAllowed.k.down){ 45755 moveSectionDown(); 45756 } 45757 break; 45758 45759 //Home 45760 case 36: 45761 if(isScrollAllowed.k.up){ 45762 moveTo(1); 45763 } 45764 break; 45765 45766 //End 45767 case 35: 45768 if(isScrollAllowed.k.down){ 45769 moveTo( $(SECTION_SEL).length ); 45770 } 45771 break; 45772 45773 //left 45774 case 37: 45775 if(isScrollAllowed.k.left){ 45776 moveSlideLeft(); 45777 } 45778 break; 45779 45780 //right 45781 case 39: 45782 if(isScrollAllowed.k.right){ 45783 moveSlideRight(); 45784 } 45785 break; 45786 45787 default: 45788 return; // exit this handler for other keys 45789 } 45790 } 45791 45792 /** 45793 * Detecting the direction of the mouse movement. 45794 * Used only for the middle button of the mouse. 45795 */ 45796 var oldPageY = 0; 45797 function mouseMoveHandler(e){ 45798 if(canScroll){ 45799 // moving up 45800 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 45801 moveSectionUp(); 45802 } 45803 45804 // moving down 45805 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 45806 moveSectionDown(); 45807 } 45808 } 45809 oldPageY = e.pageY; 45810 } 45811 45812 /** 45813 * Scrolls horizontal sliders. 45814 */ 45815 function landscapeScroll(slides, destiny, direction){ 45816 var section = slides.closest(SECTION_SEL); 45817 var v = { 45818 slides: slides, 45819 destiny: destiny, 45820 direction: direction, 45821 destinyPos: destiny.position(), 45822 slideIndex: destiny.index(), 45823 section: section, 45824 sectionIndex: section.index(SECTION_SEL), 45825 anchorLink: section.data('anchor'), 45826 slidesNav: section.find(SLIDES_NAV_SEL), 45827 slideAnchor: getAnchor(destiny), 45828 prevSlide: section.find(SLIDE_ACTIVE_SEL), 45829 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 45830 45831 //caching the value of isResizing at the momment the function is called 45832 //because it will be checked later inside a setTimeout and the value might change 45833 localIsResizing: isResizing 45834 }; 45835 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 45836 v.direction = v.direction ? v.direction : v.xMovement; 45837 45838 //important!! Only do it when not resizing 45839 if(!v.localIsResizing){ 45840 //preventing from scrolling to the next/prev section when using scrollHorizontally 45841 canScroll = false;
45842 } 45843 45844 if(options.onSlideLeave){ 45845 45846 //if the site is not just resizing and readjusting the slides 45847 if(!v.localIsResizing && v.xMovement!=='none'){ 45848 if($.isFunction( options.onSlideLeave )){ 45849 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 45850 slideMoving = false; 45851 return; 45852 } 45853 } 45854 } 45855 } 45856 45857 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 45858 45859 if(!v.localIsResizing){ 45860 stopMedia(v.prevSlide); 45861 lazyLoad(destiny); 45862 } 45863 45864 if(!options.loopHorizontal && options.controlArrows){ 45865 //hidding it for the fist slide, showing for the rest 45866 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 45867 45868 //hidding it for the last slide, showing for the rest 45869 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 45870 } 45871 45872 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 45873 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 45874 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 45875 } 45876 45877 performHorizontalMove(slides, v, true); 45878 } 45879 45880 45881 function afterSlideLoads(v){ 45882 activeSlidesNavigation(v.slidesNav, v.slideIndex); 45883 45884 //if the site is not just resizing and readjusting the slides 45885 if(!v.localIsResizing){ 45886 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 45887 45888 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 45889 //and to prevent double scroll right after a windows resize 45890 canScroll = true; 45891 45892 playMedia(v.destiny); 45893 } 45894 45895 //letting them slide again 45896 slideMoving = false; 45897 } 45898 45899 /** 45900 * Performs the horizontal movement. (CSS3 or jQuery) 45901 * 45902 * @param fireCallback {Bool} - determines whether or not to fire the callback 45903 */ 45904 function performHorizontalMove(slides, v, fireCallback){ 45905 var destinyPos = v.destinyPos; 45906 45907 if(options.css3){ 45908 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 45909 45910 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 45911 45912 afterSlideLoadsId = setTimeout(function(){ 45913 fireCallback && afterSlideLoads(v); 45914 }, options.scrollingSpeed, options.easing); 45915 }else{ 45916 slides.animate({ 45917 scrollLeft : Math.round(destinyPos.left) 45918 }, options.scrollingSpeed, options.easing, function() { 45919 45920 fireCallback && afterSlideLoads(v); 45921 }); 45922 } 45923 } 45924 45925 /** 45926 * Sets the state for the horizontal bullet navigations. 45927 */ 45928 function activeSlidesNavigation(slidesNav, slideIndex){ 45929 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 45930 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 45931 } 45932 45933 var previousHeight = windowsHeight; 45934 45935 //when resizing the site, we adjust the heights of the sections, slimScroll... 45936 function resizeHandler(){ 45937 //checking if it needs to get responsive 45938 responsive(); 45939 45940 // rebuild immediately on touch devices 45941 if (isTouchDevice) { 45942 var activeElement = $(document.activeElement); 45943 45944 //if the keyboard is NOT visible 45945 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 45946 var currentHeight = $window.height(); 45947 45948 //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) 45949 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 45950 reBuild(true); 45951 previousHeight = currentHeight; 45952 } 45953 } 45954 }else{ 45955 //in order to call the functions only when the resize is finished 45956 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 45957 clearTimeout(resizeId); 45958 45959 resizeId = setTimeout(function(){ 45960 reBuild(true); 45961 }, 350); 45962 } 45963 } 45964 45965 /** 45966 * Checks if the site needs to get responsive and disables autoScrolling if so. 45967 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 45968 */ 45969 function responsive(){ 45970 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 45971 var heightLimit = options.responsiveHeight; 45972 45973 //only calculating what we need. Remember its called on the resize event. 45974 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 45975 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 45976 45977 if(widthLimit && heightLimit){ 45978 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 45979 } 45980 else if(widthLimit){ 45981 setResponsive(isBreakingPointWidth); 45982 } 45983 else if(heightLimit){ 45984 setResponsive(isBreakingPointHeight); 45985 } 45986 } 45987 45988 /** 45989 * Adds transition animations for the given element 45990 */ 45991 function addAnimation(container, element){ 45992 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 45993 45994 container.removeClass(NO_TRANSITION); 45995 return container.css({
45996 '-webkit-transition': transition, 45997 'transition': transition 45998 }); 45999 } 46000 46001 /** 46002 * Remove transition animations for the given element 46003 */ 46004 function removeAnimation(element){ 46005 return element.addClass(NO_TRANSITION); 46006 } 46007 46008 /** 46009 * Activating the vertical navigation bullets according to the given slide name. 46010 */ 46011 function activateNavDots(name, sectionIndex){ 46012 if(options.navigation){ 46013 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 46014 if(name){ 46015 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 46016 }else{ 46017 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 46018 } 46019 } 46020 } 46021 46022 /** 46023 * Activating the website main menu elements according to the given slide name. 46024 */ 46025 function activateMenuElement(name){ 46026 if(options.menu){ 46027 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 46028 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 46029 } 46030 } 46031 46032 /** 46033 * Sets to active the current menu and vertical nav items. 46034 */ 46035 function activateMenuAndNav(anchor, index){ 46036 activateMenuElement(anchor); 46037 activateNavDots(anchor, index); 46038 } 46039 46040 /** 46041 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 46042 * from the current section. 46043 */ 46044 function getYmovement(destiny){ 46045 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 46046 var toIndex = destiny.index(SECTION_SEL); 46047 if( fromIndex == toIndex){ 46048 return 'none'; 46049 } 46050 if(fromIndex > toIndex){ 46051 return 'up'; 46052 } 46053 return 'down'; 46054 } 46055 46056 /** 46057 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 46058 * from the current slide. 46059 */ 46060 function getXmovement(fromIndex, toIndex){ 46061 if( fromIndex == toIndex){ 46062 return 'none'; 46063 } 46064 if(fromIndex > toIndex){ 46065 return 'left'; 46066 } 46067 return 'right'; 46068 } 46069 46070 /** 46071 * Checks if the element needs scrollbar and if the user wants to apply it. 46072 * If so it creates it. 46073 * 46074 * @param {Object} element jQuery object of the section or slide 46075 */ 46076 function createScrollBar(element){ 46077 //User doesn't want scrollbar here? Sayonara baby! 46078 if(element.hasClass('fp-noscroll')) return; 46079 46080 //needed to make `scrollHeight` work under Opera 12 46081 element.css('overflow', 'hidden'); 46082 46083 var scrollOverflowHandler = options.scrollOverflowHandler; 46084 var wrap = scrollOverflowHandler.wrapContent(); 46085 //in case element is a slide 46086 var section = element.closest(SECTION_SEL); 46087 var scrollable = scrollOverflowHandler.scrollable(element); 46088 var contentHeight; 46089 46090 //if there was scroll, the contentHeight will be the one in the scrollable section 46091 if(scrollable.length){ 46092 contentHeight = scrollOverflowHandler.scrollHeight(element); 46093 }else{ 46094 contentHeight = element.get(0).scrollHeight; 46095 if(options.verticalCentered){ 46096 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 46097 } 46098 } 46099 46100 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 46101 46102 //needs scroll? 46103 if ( contentHeight > scrollHeight) { 46104 //did we already have an scrollbar ? Updating it 46105 if(scrollable.length){ 46106 scrollOverflowHandler.update(element, scrollHeight); 46107 } 46108 //creating the scrolling 46109 else{ 46110 if(options.verticalCentered){ 46111 element.find(TABLE_CELL_SEL).wrapInner(wrap); 46112 }else{ 46113 element.wrapInner(wrap); 46114 } 46115 scrollOverflowHandler.create(element, scrollHeight); 46116 } 46117 } 46118 //removing the scrolling when it is not necessary anymore 46119 else{ 46120 scrollOverflowHandler.remove(element); 46121 } 46122 46123 //undo 46124 element.css('overflow', ''); 46125 } 46126 46127 function addTableClass(element){ 46128 //In case we are styling for the 2nd time as in with reponsiveSlides 46129 if(!element.hasClass(TABLE)){ 46130 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 46131 } 46132 } 46133 46134 function getTableHeight(element){ 46135 var sectionHeight = windowsHeight; 46136 46137 if(options.paddingTop || options.paddingBottom){ 46138 var section = element; 46139 if(!section.hasClass(SECTION)){ 46140 section = element.closest(SECTION_SEL); 46141 } 46142 46143 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 46144 sectionHeight = (windowsHeight - paddings); 46145 } 46146 46147 return sectionHeight; 46148 } 46149 46150 /** 46151 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 46152 */ 46153 function transformContainer(translate3d, animated){ 46154 if(animated){ 46155 addAnimation(container); 46156 }else{ 46157 removeAnimation(container); 46158 } 46159 46160 container.css(getTransforms(translate3d)); 46161 46162 //syncronously removing the class after the animation has been applied. 46163 setTimeout(function(){ 46164 container.removeClass(NO_TRANSITION); 46165 },10); 46166 } 46167 46168 /** 46169 * Gets a section by its anchor / index 46170 */ 46171 function getSectionByAnchor(sectionAnchor){ 46172 if(!sectionAnchor) return []; 46173 46174 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 46175 if(!section.length){ 46176 section = $(SECTION_SEL).eq( sectionAnchor -1); 46177 } 46178 46179 return section; 46180 } 46181 46182 /** 46183 * Gets a slide inside a given section by its anchor / index 46184 */ 46185 function getSlideByAnchor(slideAnchor, section){ 46186 var slides = section.find(SLIDES_WRAPPER_SEL); 46187 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 46188
46189 if(!slide.length){ 46190 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 46191 } 46192 46193 return slide; 46194 } 46195 46196 /** 46197 * Scrolls to the given section and slide anchors 46198 */ 46199 function scrollPageAndSlide(destiny, slide){ 46200 var section = getSectionByAnchor(destiny); 46201 46202 //do nothing if there's no section with the given anchor name 46203 if(!section.length) return; 46204 46205 //default slide 46206 if (typeof slide === 'undefined') { 46207 slide = 0; 46208 } 46209 46210 //we need to scroll to the section and then to the slide 46211 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 46212 scrollPage(section, function(){ 46213 scrollSlider(section, slide); 46214 }); 46215 } 46216 //if we were already in the section 46217 else{ 46218 scrollSlider(section, slide); 46219 } 46220 } 46221 46222 /** 46223 * Scrolls the slider to the given slide destination for the given section 46224 */ 46225 function scrollSlider(section, slideAnchor){ 46226 if(typeof slideAnchor !== 'undefined'){ 46227 var slides = section.find(SLIDES_WRAPPER_SEL); 46228 var destiny = getSlideByAnchor(slideAnchor, section); 46229 46230 if(destiny.length){ 46231 landscapeScroll(slides, destiny); 46232 } 46233 } 46234 } 46235 46236 /** 46237 * Creates a landscape navigation bar with dots for horizontal sliders. 46238 */ 46239 function addSlidesNavigation(section, numSlides){ 46240 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 46241 var nav = section.find(SLIDES_NAV_SEL); 46242 46243 //top or bottom 46244 nav.addClass(options.slidesNavPosition); 46245 46246 for(var i=0; i< numSlides; i++){ 46247 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 46248 } 46249 46250 //centering it 46251 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 46252 46253 nav.find('li').first().find('a').addClass(ACTIVE); 46254 } 46255 46256 46257 /** 46258 * Sets the state of the website depending on the active section/slide. 46259 * It changes the URL hash when needed and updates the body class. 46260 */ 46261 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 46262 var sectionHash = ''; 46263 46264 if(options.anchors.length && !options.lockAnchors){ 46265 46266 //isn't it the first slide? 46267 if(slideIndex){ 46268 if(typeof anchorLink !== 'undefined'){ 46269 sectionHash = anchorLink; 46270 } 46271 46272 //slide without anchor link? We take the index instead. 46273 if(typeof slideAnchor === 'undefined'){ 46274 slideAnchor = slideIndex; 46275 } 46276 46277 lastScrolledSlide = slideAnchor; 46278 setUrlHash(sectionHash + '/' + slideAnchor); 46279 46280 //first slide won't have slide anchor, just the section one 46281 }else if(typeof slideIndex !== 'undefined'){ 46282 lastScrolledSlide = slideAnchor; 46283 setUrlHash(anchorLink); 46284 } 46285 46286 //section without slides 46287 else{ 46288 setUrlHash(anchorLink); 46289 } 46290 } 46291 46292 setBodyClass(); 46293 } 46294 46295 /** 46296 * Sets the URL hash. 46297 */ 46298 function setUrlHash(url){ 46299 //Uncode addition 46300 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 46301 return false; 46302 46303 if(options.recordHistory){ 46304 location.hash = url; 46305 }else{ 46306 //Uncode addition 46307 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 46308 // if(isTouchDevice || isTouch){ 46309 // window.history.replaceState(undefined, undefined, '#' + url); 46310 // }else{ 46311 // var baseUrl = window.location.href.split('#')[0]; 46312 // window.location.replace( baseUrl + '#' + url ); 46313 // } 46314 return false;
46315 } 46316 } 46317 46318 /** 46319 * Gets the anchor for the given slide / section. Its index will be used if there's none. 46320 */ 46321 function getAnchor(element){ 46322 var anchor = element.data('anchor'); 46323 var index = element.index(); 46324 46325 //Slide without anchor link? We take the index instead. 46326 if(typeof anchor === 'undefined'){ 46327 anchor = index; 46328 } 46329 46330 return anchor; 46331 } 46332 46333 /** 46334 * Sets a class for the body of the page depending on the active section / slide 46335 */ 46336 function setBodyClass(){ 46337 var section = $(SECTION_ACTIVE_SEL); 46338 var slide = section.find(SLIDE_ACTIVE_SEL); 46339 46340 var sectionAnchor = getAnchor(section); 46341 var slideAnchor = getAnchor(slide); 46342 46343 var text = String(sectionAnchor); 46344 46345 if(slide.length){ 46346 text = text + '-' + slideAnchor; 46347 } 46348 46349 //changing slash for dash to make it a valid CSS style 46350 text = text.replace('/', '-').replace('#',''); 46351 46352 //removing previous anchor classes 46353 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 46354 $body[0].className = $body[0].className.replace(classRe, ''); 46355 46356 //adding the current anchor 46357 $body.addClass(VIEWING_PREFIX + '-' + text); 46358 } 46359 46360 /** 46361 * Checks for translate3d support 46362 * @return boolean 46363 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 46364 */ 46365 function support3d() { 46366 var el = document.createElement('p'), 46367 has3d, 46368 transforms = { 46369 'webkitTransform':'-webkit-transform', 46370 'OTransform':'-o-transform', 46371 'msTransform':'-ms-transform', 46372 'MozTransform':'-moz-transform', 46373 'transform':'transform' 46374 }; 46375 46376 // Add it to the body to get the computed style. 46377 document.body.insertBefore(el, null); 46378 46379 for (var t in transforms) { 46380 if (el.style[t] !== undefined) { 46381 el.style[t] = 'translate3d(1px,1px,1px)'; 46382 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 46383 } 46384 } 46385 46386 document.body.removeChild(el); 46387 46388 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 46389 } 46390 46391 /** 46392 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 46393 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 46394 */ 46395 function removeMouseWheelHandler(){ 46396 if (document.addEventListener) { 46397 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 46398 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 46399 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 46400 } else { 46401 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 46402 } 46403 } 46404 46405 /** 46406 * Adds the auto scrolling action for the mouse wheel and trackpad. 46407 * After this function is called, the mousewheel and trackpad movements will scroll through sections 46408 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 46409 */ 46410 function addMouseWheelHandler(){ 46411 var prefix = ''; 46412 var _addEventListener; 46413 46414 if (window.addEventListener){ 46415 _addEventListener = "addEventListener"; 46416 }else{ 46417 _addEventListener = "attachEvent"; 46418 prefix = 'on'; 46419 } 46420 46421 // detect available wheel event 46422 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 46423 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 46424 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 46425 var passiveEvent = g_supportsPassive ? {passive: false }
46425: false; 46426 46427 46428 if(support == 'DOMMouseScroll'){ 46429 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent); 46430 } 46431 46432 //handle MozMousePixelScroll in older Firefox 46433 else{ 46434 document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent); 46435 } 46436 } 46437 46438 /** 46439 * Binding the mousemove when the mouse's middle button is pressed 46440 */ 46441 function addMiddleWheelHandler(){ 46442 container 46443 .on('mousedown', mouseDownHandler) 46444 .on('mouseup', mouseUpHandler); 46445 } 46446 46447 /** 46448 * Unbinding the mousemove when the mouse's middle button is released 46449 */ 46450 function removeMiddleWheelHandler(){ 46451 container 46452 .off('mousedown', mouseDownHandler) 46453 .off('mouseup', mouseUpHandler); 46454 } 46455 46456 /** 46457 * Adds the possibility to auto scroll through sections on touch devices. 46458 */ 46459 function addTouchHandler(){ 46460 if(isTouchDevice || isTouch){ 46461 if(options.autoScrolling){ 46462 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 46463 } 46464 46465 $(WRAPPER_SEL) 46466 .off(events.touchstart).on(events.touchstart, touchStartHandler) 46467 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 46468 } 46469 } 46470 46471 /** 46472 * Removes the auto scrolling for touch devices. 46473 */ 46474 function removeTouchHandler(){ 46475 if(isTouchDevice || isTouch){ 46476 $(WRAPPER_SEL) 46477 .off(events.touchstart) 46478 .off(events.touchmove); 46479 } 46480 } 46481 46482 /* 46483 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11) 46484 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 46485 */ 46486 function getMSPointer(){ 46487 var pointer; 46488 46489 //IE >= 11 & rest of browsers 46490 if(window.PointerEvent){ 46491 pointer = { down: 'pointerdown', move: 'pointermove'}; 46492 } 46493 46494 //IE < 11 46495 else{ 46496 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 46497 } 46498 46499 return pointer; 46500 } 46501 46502 /** 46503 * Gets the pageX and pageY properties depending on the browser. 46504 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 46505 */ 46506 function getEventsPage(e){ 46507 var events = []; 46508 46509 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 46510 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 46511 46512 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 46513 if(isTouch && isReallyTouch(e) && options.scrollBar){ 46514 events.y = e.touches[0].pageY; 46515 events.x = e.touches[0].pageX; 46516 } 46517 46518 return events; 46519 } 46520 46521 /** 46522 * Slides silently (with no animation) the active slider to the given slide. 46523 * @param noCallback {bool} true or defined -> no callbacks 46524 */ 46525 function silentLandscapeScroll(activeSlide, noCallbacks){ 46526 setScrollingSpeed (0, 'internal'); 46527 46528 if(typeof noCallbacks !== 'undefined'){ 46529 //preventing firing callbacks afterSlideLoad etc. 46530 isResizing = true; 46531 } 46532 46533 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 46534 46535 if(typeof noCallbacks !== 'undefined'){ 46536 isResizing = false; 46537 } 46538 46539 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 46540 } 46541 46542 /** 46543 * Scrolls silently (with no animation) the page to the given Y position. 46544 */ 46545 function silentScroll(top){ 46546 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 46547 // that's why we round it to 0. 46548 var roundedTop = Math.round(top); 46549 46550 if (options.css3 && options.autoScrolling && !options.scrollBar){ 46551 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 46552 transformContainer(translate3d, false); 46553 } 46554 else if(options.autoScrolling && !options.scrollBar){ 46555 container.css('top', -roundedTop); 46556 } 46557 else{ 46558 $htmlBody.scrollTop(roundedTop); 46559 } 46560 } 46561 46562 /** 46563 * Returns the cross-browser transform string. 46564 */ 46565 function getTransforms(translate3d){ 46566 return {
46567 '-webkit-transform': translate3d, 46568 '-moz-transform': translate3d, 46569 '-ms-transform':translate3d, 46570 'transform': translate3d 46571 }; 46572 } 46573 46574 /** 46575 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 46576 * @type m (mouse) or k (keyboard) 46577 */ 46578 function setIsScrollAllowed(value, direction, type){ 46579 switch (direction){ 46580 case 'up': isScrollAllowed[type].up = value; break; 46581 case 'down': isScrollAllowed[type].down = value; break; 46582 case 'left': isScrollAllowed[type].left = value; break; 46583 case 'right': isScrollAllowed[type].right = value; break; 46584 case 'all': 46585 if(type == 'm'){ 46586 setAllowScrolling(value); 46587 }else{ 46588 setKeyboardScrolling(value); 46589 } 46590 } 46591 } 46592 46593 /* 46594 * Destroys fullpage.js plugin events and optinally its html markup and styles 46595 */ 46596 function destroy(all){ 46597 setAutoScrolling(false, 'internal'); 46598 setAllowScrolling(false); 46599 setKeyboardScrolling(false); 46600 container.addClass(DESTROYED); 46601 46602 clearTimeout(afterSlideLoadsId); 46603 clearTimeout(afterSectionLoadsId); 46604 clearTimeout(resizeId); 46605 clearTimeout(scrollId); 46606 clearTimeout(scrollId2); 46607 46608 $window 46609 .off('scroll', scrollHandler) 46610 .off('hashchange', hashChangeHandler) 46611 .off('resize', resizeHandler); 46612 46613 $document 46614 .off('click touchstart', SECTION_NAV_SEL + ' a') 46615 .off('mouseenter', SECTION_NAV_SEL + ' li') 46616 .off('mouseleave', SECTION_NAV_SEL + ' li') 46617 .off('click touchstart', SLIDES_NAV_LINK_SEL) 46618 .off('mouseover', options.normalScrollElements) 46619 .off('mouseout', options.normalScrollElements); 46620 46621 $(SECTION_SEL) 46622 .off('click touchstart', SLIDES_ARROW_SEL); 46623 46624 clearTimeout(afterSlideLoadsId); 46625 clearTimeout(afterSectionLoadsId); 46626 46627 //lets make a mess! 46628 if(all){ 46629 destroyStructure(); 46630 } 46631 } 46632 46633 /* 46634 * Removes inline styles added by fullpage.js 46635 */ 46636 function destroyStructure(){ 46637 //reseting the `top` or `translate` properties to 0 46638 silentScroll(0); 46639 46640 //loading all the lazy load content 46641 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 46642 setSrc($(this), 'src'); 46643 }); 46644 46645 container.find('img[data-srcset]').each(function(){ 46646 setSrc($(this), 'srcset'); 46647 }); 46648 46649 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 46650 46651 //removing inline styles 46652 $(SECTION_SEL).css( { 46653 'height': '', 46654 'background-color' : '', 46655 'padding': '' 46656 }); 46657 46658 $(SLIDE_SEL).css( { 46659 'width': '' 46660 }); 46661 46662 container.css({ 46663 'height': '', 46664 'position': '', 46665 '-ms-touch-action': '', 46666 'touch-action': '' 46667 }); 46668 46669 $htmlBody.css({ 46670 'overflow': '', 46671 'height': '' 46672 }); 46673 46674 // remove .fp-enabled class 46675 $('html').removeClass(ENABLED); 46676 46677 // remove .fp-responsive class 46678 $body.removeClass(RESPONSIVE); 46679 46680 // remove all of the .fp-viewing- classes 46681 $.each($body.get(0).className.split(/\s+/), function (index, className) { 46682 if (className.indexOf(VIEWING_PREFIX) === 0) { 46683 $body.removeClass(className); 46684 } 46685 }); 46686 46687 //removing added classes 46688 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 46689 options.scrollOverflowHandler.remove($(this)); 46690 $(this).removeClass(TABLE + ' ' + ACTIVE); 46691 }); 46692 46693 removeAnimation(container); 46694 46695 //Unwrapping content 46696 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 46697 //unwrap not being use in case there's no child element inside and its just text 46698 $(this).replaceWith(this.childNodes); 46699 }); 46700 46701 //removing the applied transition from the fullpage wrapper 46702 container.css({
46703 '-webkit-transition': 'none', 46704 'transition': 'none' 46705 }); 46706 46707 //scrolling the page to the top with no animation 46708 $htmlBody.scrollTop(0); 46709 46710 //removing selectors 46711 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 46712 $.each(usedSelectors, function(index, value){ 46713 $('.' + value).removeClass(value); 46714 }); 46715 } 46716 46717 /* 46718 * Sets the state for a variable with multiple states (original, and temporal) 46719 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 46720 * This function is used to keep track of both states, the original and the temporal one. 46721 * If type is not 'internal', then we assume the user is globally changing the variable. 46722 */ 46723 function setVariableState(variable, value, type){ 46724 options[variable] = value; 46725 if(type !== 'internal'){ 46726 originals[variable] = value; 46727 } 46728 } 46729 46730 /** 46731 * Displays warnings 46732 */ 46733 function displayWarnings(){ 46734 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 46735 //UNCODE.addition 46736 // if($('html').hasClass(ENABLED)){ 46737 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 46738 // return; 46739 // } 46740 46741 // Disable mutually exclusive settings 46742 //UNCODE.addition 46743 // if (options.continuousVertical && 46744 // (options.loopTop || options.loopBottom)) { 46745 // options.continuousVertical = false;
46746 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 46747 // } 46748 46749 // if(options.scrollBar && options.scrollOverflow){ 46750 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 46751 // } 46752 46753 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 46754 // options.continuousVertical = false; 46755 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 46756 // } 46757 46758 //using extensions? Wrong file! 46759 $.each(extensions, function(index, extension){ 46760 //is the option set to true? 46761 if(options[extension]){ 46762 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 46763 } 46764 }); 46765 46766 //anchors can not have the same value as any element ID or NAME 46767 $.each(options.anchors, function(index, name){ 46768 46769 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 46770 var nameAttr = $document.find('[name]').filter(function() { 46771 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 46772 }); 46773 46774 var idAttr = $document.find('[id]').filter(function() { 46775 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 46776 }); 46777 46778 if(idAttr.length || nameAttr.length ){ 46779 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 46780 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 46781 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 46782 } 46783 }); 46784 } 46785 46786 /** 46787 * Shows a message in the console of the given type. 46788 */ 46789 function showError(type, text){ 46790 console && console[type] && console[type]('fullPage: ' + text); 46791 } 46792 46793 }; //end of $.fn.fullpage 46794 46795 if(typeof IScroll !== 'undefined'){ 46796 /* 46797 * Turns iScroll `mousewheel` option off dynamically 46798 * https://github.com/cubiq/iscroll/issues/1036 46799 */ 46800 IScroll.prototype.wheelOn = function () { 46801 this.wrapper.addEventListener('wheel', this); 46802 this.wrapper.addEventListener('mousewheel', this); 46803 this.wrapper.addEventListener('DOMMouseScroll', this); 46804 }; 46805 46806 /* 46807 * Turns iScroll `mousewheel` option on dynamically 46808 * https://github.com/cubiq/iscroll/issues/1036 46809 */ 46810 IScroll.prototype.wheelOff = function () { 46811 this.wrapper.removeEventListener('wheel', this); 46812 this.wrapper.removeEventListener('mousewheel', this); 46813 this.wrapper.removeEventListener('DOMMouseScroll', this); 46814 }; 46815 } 46816 46817 /** 46818 * An object to handle overflow scrolling. 46819 * This uses jquery.slimScroll to accomplish overflow scrolling. 46820 * It is possible to pass in an alternate scrollOverflowHandler 46821 * to the fullpage.js option that implements the same functions 46822 * as this handler. 46823 * 46824 * @type {Object} 46825 */ 46826 var iscrollHandler = { 46827 refreshId: null, 46828 iScrollInstances: [], 46829 46830 // Enables or disables the mouse wheel for the active section or all slides in it 46831 toggleWheel: function(value){ 46832 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 46833 scrollable.each(function(){ 46834 var iScrollInstance = $(this).data('iscrollInstance'); 46835 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 46836 if(value){ 46837 iScrollInstance.wheelOn(); 46838 } 46839 else{ 46840 iScrollInstance.wheelOff(); 46841 } 46842 } 46843 }); 46844 }, 46845 46846 /** 46847 * Turns off iScroll for the destination section. 46848 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
46849 * scroll the destination section/slide before the sections animations ends. 46850 */ 46851 onLeave: function(){ 46852 iscrollHandler.toggleWheel(false); 46853 }, 46854 46855 // Turns off iScroll for the leaving section 46856 beforeLeave: function(){ 46857 iscrollHandler.onLeave() 46858 }, 46859 46860 // Turns on iScroll on section load 46861 afterLoad: function(){ 46862 iscrollHandler.toggleWheel(true); 46863 }, 46864 46865 /** 46866 * Called when overflow scrolling is needed for a section. 46867 * 46868 * @param {Object} element jQuery object containing current section 46869 * @param {Number} scrollHeight Current window height in pixels 46870 */ 46871 create: function(element, scrollHeight) { 46872 var scrollable = element.find(SCROLLABLE_SEL); 46873 46874 scrollable.height(scrollHeight); 46875 scrollable.each(function() { 46876 var $this = $(this); 46877 var iScrollInstance = $this.data('iscrollInstance'); 46878 if (iScrollInstance) { 46879 $.each(iscrollHandler.iScrollInstances, function(){ 46880 $(this).destroy(); 46881 }); 46882 } 46883 46884 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 46885 iscrollHandler.iScrollInstances.push(iScrollInstance); 46886 46887 //off by default until the section gets active 46888 iScrollInstance.wheelOff(); 46889 46890 $this.data('iscrollInstance', iScrollInstance); 46891 }); 46892 }, 46893 46894 /** 46895 * Return a boolean depending on whether the scrollable element is a 46896 * the end or at the start of the scrolling depending on the given type. 46897 * 46898 * @param {String} type Either 'top' or 'bottom' 46899 * @param {Object} scrollable jQuery object for the scrollable element 46900 * @return {Boolean} 46901 */ 46902 isScrolled: function(type, scrollable) { 46903 var scroller = scrollable.data('iscrollInstance'); 46904 46905 //no scroller? 46906 if (!scroller) { 46907 return true; 46908 } 46909 46910 //Uncode addition 46911 var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0; 46912 //End Uncode addition 46913 46914 if (type === 'top') { 46915 return scroller.y >= 0 && !scrollable.scrollTop(); 46916 } else if (type === 'bottom') { 46917 //Uncode change 46918 // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight; 46919 return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight; 46920 //End Uncode change 46921 } 46922 }, 46923 46924 /** 46925 * Returns the scrollable element for the given section. 46926 * If there are landscape slides, will only return a scrollable element 46927 * if it is in the active slide. 46928 * 46929 * @param {Object} activeSection jQuery object containing current section 46930 * @return {Boolean} 46931 */ 46932 scrollable: function(activeSection){ 46933 // if there are landscape slides, we check if the scrolling bar is in the current one or not 46934 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 46935 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 46936 } 46937 return activeSection.find(SCROLLABLE_SEL); 46938 }, 46939 46940 /** 46941 * Returns the scroll height of the wrapped content. 46942 * If this is larger than the window height minus section padding, 46943 * overflow scrolling is needed. 46944 * 46945 * @param {Object} element jQuery object containing current section 46946 * @return {Number} 46947 */ 46948 scrollHeight: function(element) { 46949 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 46950 }, 46951 46952 /** 46953 * Called when overflow scrolling is no longer needed for a section. 46954 * 46955 * @param {Object}
vendor: 5,435 bytes, lines 46955-47106
46955 element jQuery object containing current section 46956 */ 46957 remove: function(element) { 46958 var scrollable = element.find(SCROLLABLE_SEL); 46959 if (scrollable.length) { 46960 var iScrollInstance = scrollable.data('iscrollInstance'); 46961 iScrollInstance.destroy(); 46962 46963 scrollable.data('iscrollInstance', null); 46964 } 46965 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 46966 }, 46967 46968 /** 46969 * Called when overflow scrolling has already been setup but the 46970 * window height has potentially changed. 46971 * 46972 * @param {Object} element jQuery object containing current section 46973 * @param {Number} scrollHeight Current window height in pixels 46974 */ 46975 update: function(element, scrollHeight) { 46976 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 46977 //short period of time. 46978 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 46979 clearTimeout(iscrollHandler.refreshId); 46980 iscrollHandler.refreshId = setTimeout(function(){ 46981 $.each(iscrollHandler.iScrollInstances, function(){ 46982 $(this).get(0).refresh(); 46983 }); 46984 }, 150); 46985 46986 //updating the wrappers height 46987 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 46988 }, 46989 46990 /** 46991 * Called to get any additional elements needed to wrap the section 46992 * content in order to facilitate overflow scrolling. 46993 * 46994 * @return {String|Object} Can be a string containing HTML, 46995 * a DOM element, or jQuery object. 46996 */ 46997 wrapContent: function() { 46998 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 46999 } 47000 }; 47001}); 47002 47003(function (global, factory) { 47004 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 47005 typeof define === 'function' && define.amd ? define(['exports'], factory) : 47006 (global = global || self, factory(global.window = global.window || {})); 47007 }(this, (function (exports) { 'use strict'; 47008 47009 function _defineProperties(target, props) { 47010 for (var i = 0; i < props.length; i++) { 47011 var descriptor = props[i]; 47012 descriptor.enumerable = descriptor.enumerable || false; 47013 descriptor.configurable = true; 47014 if ("value" in descriptor) descriptor.writable = true; 47015 Object.defineProperty(target, descriptor.key, descriptor); 47016 } 47017 } 47018 47019 function _createClass(Constructor, protoProps, staticProps) { 47020 if (protoProps) _defineProperties(Constructor.prototype, protoProps); 47021 if (staticProps) _defineProperties(Constructor, staticProps); 47022 return Constructor; 47023 } 47024 47025 /*! 47026 * Observer 3.12.5 47027 * https://gsap.com 47028 * 47029 * @license Copyright 2008-2024, GreenSock. All rights reserved. 47030 * Subject to the terms at https://gsap.com/standard-license or for 47031 * Club GSAP members, the agreement issued with that membership. 47032 * @author: Jack Doyle, [email protected] 47033 */ 47034 var gsap, 47035 _coreInitted, 47036 _clamp, 47037 _win, 47038 _doc, 47039 _docEl, 47040 _body, 47041 _isTouch, 47042 _pointerType, 47043 ScrollTrigger, 47044 _root, 47045 _normalizer, 47046 _eventTypes, 47047 _context, 47048 _getGSAP = function _getGSAP() { 47049 return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap; 47050 }, 47051 _startup = 1, 47052 _observers = [], 47053 _scrollers = [], 47054 _proxies = [], 47055 _getTime = Date.now, 47056 _bridge = function _bridge(name, value) { 47057 return value; 47058 }, 47059 _integrate = function _integrate() { 47060 var core = ScrollTrigger.core, 47061 data = core.bridge || {}, 47062 scrollers = core._scrollers, 47063 proxies = core._proxies; 47064 scrollers.push.apply(scrollers, _scrollers); 47065 proxies.push.apply(proxies, _proxies); 47066 _scrollers = scrollers; 47067 _proxies = proxies; 47068 47069 _bridge = function _bridge(name, value) { 47070 return data[name](value); 47071 }; 47072 }, 47073 _getProxyProp = function _getProxyProp(element, property) { 47074 return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property]; 47075 }, 47076 _isViewport = function _isViewport(el) { 47077 return !!~_root.indexOf(el); 47078 }, 47079 _addListener = function _addListener(element, type, func, passive, capture) { 47080 return element.addEventListener(type, func, { 47081 passive: passive !== false, 47082 capture: !!capture 47083 }); 47084 }, 47085 _removeListener = function _removeListener(element, type, func, capture) { 47086 return element.removeEventListener(type, func, !!capture); 47087 }, 47088 _scrollLeft = "scrollLeft", 47089 _scrollTop = "scrollTop", 47090 _onScroll = function _onScroll() { 47091 return _normalizer && _normalizer.isPressed || _scrollers.cache++; 47092 }, 47093 _scrollCacheFunc = function _scrollCacheFunc(f, doNotCache) { 47094 var cachingFunc = function cachingFunc(value) { 47095 if (value || value === 0) { 47096 _startup && (_win.history.scrollRestoration = "manual"); 47097 var isNormalizing = _normalizer && _normalizer.isPressed; 47098 value = cachingFunc.v = Math.round(value) || (_normalizer && _normalizer.iOS ? 1 : 0); 47099 f(value); 47100 cachingFunc.cacheID = _scrollers.cache; 47101 isNormalizing && _bridge("ss", value); 47102 } else if (doNotCache || _scrollers.cache !== cachingFunc.cacheID || _bridge("ref")) { 47103 cachingFunc.cacheID = _scrollers.cache; 47104 cachingFunc.v = f(); 47105 } 47106
vendor: 4,462 bytes, lines 47107-47243
47107 return cachingFunc.v + cachingFunc.offset; 47108 }; 47109 47110 cachingFunc.offset = 0; 47111 return f && cachingFunc; 47112 }, 47113 _horizontal = { 47114 s: _scrollLeft, 47115 p: "left", 47116 p2: "Left", 47117 os: "right", 47118 os2: "Right", 47119 d: "width", 47120 d2: "Width", 47121 a: "x", 47122 sc: _scrollCacheFunc(function (value) { 47123 return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0; 47124 }) 47125 }, 47126 _vertical = { 47127 s: _scrollTop, 47128 p: "top", 47129 p2: "Top", 47130 os: "bottom", 47131 os2: "Bottom", 47132 d: "height", 47133 d2: "Height", 47134 a: "y", 47135 op: _horizontal, 47136 sc: _scrollCacheFunc(function (value) { 47137 return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0; 47138 }) 47139 }, 47140 _getTarget = function _getTarget(t, self) { 47141 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); 47142 }, 47143 _getScrollFunc = function _getScrollFunc(element, _ref) { 47144 var s = _ref.s, 47145 sc = _ref.sc; 47146 _isViewport(element) && (element = _doc.scrollingElement || _docEl); 47147 47148 var i = _scrollers.indexOf(element), 47149 offset = sc === _vertical.sc ? 1 : 2; 47150 47151 !~i && (i = _scrollers.push(element) - 1); 47152 _scrollers[i + offset] || _addListener(element, "scroll", _onScroll); 47153 var prev = _scrollers[i + offset], 47154 func = prev || (_scrollers[i + offset] = _scrollCacheFunc(_getProxyProp(element, s), true) || (_isViewport(element) ? sc : _scrollCacheFunc(function (value) { 47155 return arguments.length ? element[s] = value : element[s]; 47156 }))); 47157 func.target = element; 47158 prev || (func.smooth = gsap.getProperty(element, "scrollBehavior") === "smooth"); 47159 return func; 47160 }, 47161 _getVelocityProp = function _getVelocityProp(value, minTimeRefresh, useDelta) { 47162 var v1 = value, 47163 v2 = value, 47164 t1 = _getTime(), 47165 t2 = t1, 47166 min = minTimeRefresh || 50, 47167 dropToZeroTime = Math.max(500, min * 3), 47168 update = function update(value, force) { 47169 var t = _getTime(); 47170 47171 if (force || t - t1 > min) { 47172 v2 = v1; 47173 v1 = value; 47174 t2 = t1; 47175 t1 = t; 47176 } else if (useDelta) { 47177 v1 += value; 47178 } else { 47179 v1 = v2 + (value - v2) / (t - t2) * (t1 - t2); 47180 } 47181 }, 47182 reset = function reset() { 47183 v2 = v1 = useDelta ? 0 : v1; 47184 t2 = t1 = 0; 47185 }, 47186 getVelocity = function getVelocity(latestValue) { 47187 var tOld = t2, 47188 vOld = v2, 47189 t = _getTime(); 47190 47191 (latestValue || latestValue === 0) && latestValue !== v1 && update(latestValue); 47192 return t1 === t2 || t - t2 > dropToZeroTime ? 0 : (v1 + (useDelta ? vOld : -vOld)) / ((useDelta ? t : t1) - tOld) * 1000; 47193 }; 47194 47195 return { 47196 update: update, 47197 reset: reset, 47198 getVelocity: getVelocity 47199 }; 47200 }, 47201 _getEvent = function _getEvent(e, preventDefault) { 47202 preventDefault && !e._gsapAllow && e.preventDefault(); 47203 return e.changedTouches ? e.changedTouches[0] : e; 47204 }, 47205 _getAbsoluteMax = function _getAbsoluteMax(a) { 47206 var max = Math.max.apply(Math, a), 47207 min = Math.min.apply(Math, a); 47208 return Math.abs(max) >= Math.abs(min) ? max : min; 47209 }, 47210 _setScrollTrigger = function _setScrollTrigger() { 47211 ScrollTrigger = gsap.core.globals().ScrollTrigger; 47212 ScrollTrigger && ScrollTrigger.core && _integrate(); 47213 }, 47214 _initCore = function _initCore(core) { 47215 gsap = core || _getGSAP(); 47216 47217 if (!_coreInitted && gsap && typeof document !== "undefined" && document.body) { 47218 _win = window; 47219 _doc = document; 47220 _docEl = _doc.documentElement; 47221 _body = _doc.body; 47222 _root = [_win, _doc, _docEl, _body]; 47223 _clamp = gsap.utils.clamp; 47224 47225 _context = gsap.core.context || function () {}; 47226 47227 _pointerType = "onpointerenter" in _body ? "pointer" : "mouse"; 47228 _isTouch = Observer.isTouch = _win.matchMedia && _win.matchMedia("(hover: none), (pointer: coarse)").matches ? 1 : "ontouchstart" in _win || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 ? 2 : 0; 47229 _eventTypes = Observer.eventTypes = ("ontouchstart" in _docEl ? "touchstart,touchmove,touchcancel,touchend" : !("onpointerdown" in _docEl) ? "mousedown,mousemove,mouseup,mouseup" : "pointerdown,pointermove,pointercancel,pointerup").split(","); 47230 setTimeout(function () { 47231 return _startup = 0; 47232 }, 500); 47233 47234 _setScrollTrigger(); 47235 47236 _coreInitted = 1; 47237 } 47238 47239 return _coreInitted; 47240 }; 47241 47242 _horizontal.op = _vertical; 47243 _scrollers.cache = 0;
vendor: 9,292 bytes, lines 47244-47560
47244 var Observer = function () { 47245 function Observer(vars) { 47246 this.init(vars); 47247 } 47248 47249 var _proto = Observer.prototype; 47250 47251 _proto.init = function init(vars) { 47252 _coreInitted || _initCore(gsap) || console.warn("Please gsap.registerPlugin(Observer)"); 47253 ScrollTrigger || _setScrollTrigger(); 47254 var tolerance = vars.tolerance, 47255 dragMinimum = vars.dragMinimum, 47256 type = vars.type, 47257 target = vars.target, 47258 lineHeight = vars.lineHeight, 47259 debounce = vars.debounce, 47260 preventDefault = vars.preventDefault, 47261 onStop = vars.onStop, 47262 onStopDelay = vars.onStopDelay, 47263 ignore = vars.ignore, 47264 wheelSpeed = vars.wheelSpeed, 47265 event = vars.event, 47266 onDragStart = vars.onDragStart, 47267 onDragEnd = vars.onDragEnd, 47268 onDrag = vars.onDrag, 47269 onPress = vars.onPress, 47270 onRelease = vars.onRelease, 47271 onRight = vars.onRight, 47272 onLeft = vars.onLeft, 47273 onUp = vars.onUp, 47274 onDown = vars.onDown, 47275 onChangeX = vars.onChangeX, 47276 onChangeY = vars.onChangeY, 47277 onChange = vars.onChange, 47278 onToggleX = vars.onToggleX, 47279 onToggleY = vars.onToggleY, 47280 onHover = vars.onHover, 47281 onHoverEnd = vars.onHoverEnd, 47282 onMove = vars.onMove, 47283 ignoreCheck = vars.ignoreCheck, 47284 isNormalizer = vars.isNormalizer, 47285 onGestureStart = vars.onGestureStart, 47286 onGestureEnd = vars.onGestureEnd, 47287 onWheel = vars.onWheel, 47288 onEnable = vars.onEnable, 47289 onDisable = vars.onDisable, 47290 onClick = vars.onClick, 47291 scrollSpeed = vars.scrollSpeed, 47292 capture = vars.capture, 47293 allowClicks = vars.allowClicks, 47294 lockAxis = vars.lockAxis, 47295 onLockAxis = vars.onLockAxis; 47296 this.target = target = _getTarget(target) || _docEl; 47297 this.vars = vars; 47298 ignore && (ignore = gsap.utils.toArray(ignore)); 47299 tolerance = tolerance || 1e-9; 47300 dragMinimum = dragMinimum || 0; 47301 wheelSpeed = wheelSpeed || 1; 47302 scrollSpeed = scrollSpeed || 1; 47303 type = type || "wheel,touch,pointer"; 47304 debounce = debounce !== false; 47305 lineHeight || (lineHeight = parseFloat(_win.getComputedStyle(_body).lineHeight) || 22); 47306 47307 var id, 47308 onStopDelayedCall, 47309 dragged, 47310 moved, 47311 wheeled, 47312 locked, 47313 axis, 47314 self = this, 47315 prevDeltaX = 0, 47316 prevDeltaY = 0, 47317 passive = vars.passive || !preventDefault, 47318 scrollFuncX = _getScrollFunc(target, _horizontal), 47319 scrollFuncY = _getScrollFunc(target, _vertical), 47320 scrollX = scrollFuncX(), 47321 scrollY = scrollFuncY(), 47322 limitToTouch = ~type.indexOf("touch") && !~type.indexOf("pointer") && _eventTypes[0] === "pointerdown", 47323 isViewport = _isViewport(target), 47324 ownerDoc = target.ownerDocument || _doc, 47325 deltaX = [0, 0, 0], 47326 deltaY = [0, 0, 0], 47327 onClickTime = 0, 47328 clickCapture = function clickCapture() { 47329 return onClickTime = _getTime(); 47330 }, 47331 _ignoreCheck = function _ignoreCheck(e, isPointerOrTouch) { 47332 return (self.event = e) && ignore && ~ignore.indexOf(e.target) || isPointerOrTouch && limitToTouch && e.pointerType !== "touch" || ignoreCheck && ignoreCheck(e, isPointerOrTouch); 47333 }, 47334 onStopFunc = function onStopFunc() { 47335 self._vx.reset(); 47336 47337 self._vy.reset(); 47338 47339 onStopDelayedCall.pause(); 47340 onStop && onStop(self); 47341 }, 47342 update = function update() { 47343 var dx = self.deltaX = _getAbsoluteMax(deltaX), 47344 dy = self.deltaY = _getAbsoluteMax(deltaY), 47345 changedX = Math.abs(dx) >= tolerance, 47346 changedY = Math.abs(dy) >= tolerance; 47347 47348 onChange && (changedX || changedY) && onChange(self, dx, dy, deltaX, deltaY); 47349 47350 if (changedX) { 47351 onRight && self.deltaX > 0 && onRight(self); 47352 onLeft && self.deltaX < 0 && onLeft(self); 47353 onChangeX && onChangeX(self); 47354 onToggleX && self.deltaX < 0 !== prevDeltaX < 0 && onToggleX(self); 47355 prevDeltaX = self.deltaX; 47356 deltaX[0] = deltaX[1] = deltaX[2] = 0; 47357 } 47358 47359 if (changedY) { 47360 onDown && self.deltaY > 0 && onDown(self); 47361 onUp && self.deltaY < 0 && onUp(self); 47362 onChangeY && onChangeY(self); 47363 onToggleY && self.deltaY < 0 !== prevDeltaY < 0 && onToggleY(self); 47364 prevDeltaY = self.deltaY; 47365 deltaY[0] = deltaY[1] = deltaY[2] = 0; 47366 } 47367 47368 if (moved || dragged) { 47369 onMove && onMove(self); 47370 47371 if (dragged) { 47372 onDrag(self); 47373 dragged = false; 47374 } 47375 47376 moved = false; 47377 } 47378 47379 locked && !(locked = false) && onLockAxis && onLockAxis(self); 47380 47381 if (wheeled) { 47382 onWheel(self); 47383 wheeled = false; 47384 } 47385 47386 id = 0; 47387 }, 47388 onDelta = function onDelta(x, y, index) { 47389 deltaX[index] += x; 47390 deltaY[index] += y; 47391 47392 self._vx.update(x); 47393 47394 self._vy.update(y); 47395 47396 debounce ? id || (id = requestAnimationFrame(update)) : update(); 47397 }, 47398 onTouchOrPointerDelta = function onTouchOrPointerDelta(x, y) { 47399 if (lockAxis && !axis) { 47400 self.axis = axis = Math.abs(x) > Math.abs(y) ? "x" : "y"; 47401 locked = true; 47402 } 47403 47404 if (axis !== "y") { 47405 deltaX[2] += x; 47406 47407 self._vx.update(x, true); 47408 } 47409 47410 if (axis !== "x") { 47411 deltaY[2] += y; 47412 47413 self._vy.update(y, true); 47414 } 47415 47416 debounce ? id || (id = requestAnimationFrame(update)) : update(); 47417 }, 47418 _onDrag = function _onDrag(e) { 47419 if (_ignoreCheck(e, 1)) { 47420 return; 47421 } 47422 47423 e = _getEvent(e, preventDefault); 47424 var x = e.clientX, 47425 y = e.clientY, 47426 dx = x - self.x, 47427 dy = y - self.y, 47428 isDragging = self.isDragging; 47429 self.x = x; 47430 self.y = y; 47431 47432 if (isDragging || Math.abs(self.startX - x) >= dragMinimum || Math.abs(self.startY - y) >= dragMinimum) { 47433 onDrag && (dragged = true); 47434 isDragging || (self.isDragging = true); 47435 onTouchOrPointerDelta(dx, dy); 47436 isDragging || onDragStart && onDragStart(self); 47437 } 47438 }, 47439 _onPress = self.onPress = function (e) { 47440 if (_ignoreCheck(e, 1) || e && e.button) { 47441 return; 47442 } 47443 47444 self.axis = axis = null; 47445 onStopDelayedCall.pause(); 47446 self.isPressed = true; 47447 e = _getEvent(e); 47448 prevDeltaX = prevDeltaY = 0; 47449 self.startX = self.x = e.clientX; 47450 self.startY = self.y = e.clientY; 47451 47452 self._vx.reset(); 47453 47454 self._vy.reset(); 47455 47456 _addListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, passive, true); 47457 47458 self.deltaX = self.deltaY = 0; 47459 onPress && onPress(self); 47460 }, 47461 _onRelease = self.onRelease = function (e) { 47462 if (_ignoreCheck(e, 1)) { 47463 return; 47464 } 47465 47466 _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true); 47467 47468 var isTrackingDrag = !isNaN(self.y - self.startY), 47469 wasDragging = self.isDragging, 47470 isDragNotClick = wasDragging && (Math.abs(self.x - self.startX) > 3 || Math.abs(self.y - self.startY) > 3), 47471 eventData = _getEvent(e); 47472 47473 if (!isDragNotClick && isTrackingDrag) { 47474 self._vx.reset(); 47475 47476 self._vy.reset(); 47477 47478 if (preventDefault && allowClicks) { 47479 gsap.delayedCall(0.08, function () { 47480 if (_getTime() - onClickTime > 300 && !e.defaultPrevented) { 47481 if (e.target.click) { 47482 e.target.click(); 47483 } else if (ownerDoc.createEvent) { 47484 var syntheticEvent = ownerDoc.createEvent("MouseEvents"); 47485 syntheticEvent.initMouseEvent("click", true, true, _win, 1, eventData.screenX, eventData.screenY, eventData.clientX, eventData.clientY, false, false, false, false, 0, null); 47486 e.target.dispatchEvent(syntheticEvent); 47487 } 47488 } 47489 }); 47490 } 47491 } 47492 47493 self.isDragging = self.isGesturing = self.isPressed = false; 47494 onStop && wasDragging && !isNormalizer && onStopDelayedCall.restart(true); 47495 onDragEnd && wasDragging && onDragEnd(self); 47496 onRelease && onRelease(self, isDragNotClick); 47497 }, 47498 _onGestureStart = function _onGestureStart(e) { 47499 return e.touches && e.touches.length > 1 && (self.isGesturing = true) && onGestureStart(e, self.isDragging); 47500 }, 47501 _onGestureEnd = function _onGestureEnd() { 47502 return (self.isGesturing = false) || onGestureEnd(self); 47503 }, 47504 onScroll = function onScroll(e) { 47505 if (_ignoreCheck(e)) { 47506 return; 47507 } 47508 47509 var x = scrollFuncX(), 47510 y = scrollFuncY(); 47511 onDelta((x - scrollX) * scrollSpeed, (y - scrollY) * scrollSpeed, 1); 47512 scrollX = x; 47513 scrollY = y; 47514 onStop && onStopDelayedCall.restart(true); 47515 }, 47516 _onWheel = function _onWheel(e) { 47517 if (_ignoreCheck(e)) { 47518 return; 47519 } 47520 47521 e = _getEvent(e, preventDefault); 47522 onWheel && (wheeled = true); 47523 var multiplier = (e.deltaMode === 1 ? lineHeight : e.deltaMode === 2 ? _win.innerHeight : 1) * wheelSpeed; 47524 onDelta(e.deltaX * multiplier, e.deltaY * multiplier, 0); 47525 onStop && !isNormalizer && onStopDelayedCall.restart(true); 47526 }, 47527 _onMove = function _onMove(e) { 47528 if (_ignoreCheck(e)) { 47529 return; 47530 } 47531 47532 var x = e.clientX, 47533 y = e.clientY, 47534 dx = x - self.x, 47535 dy = y - self.y; 47536 self.x = x; 47537 self.y = y; 47538 moved = true; 47539 onStop && onStopDelayedCall.restart(true); 47540 (dx || dy) && onTouchOrPointerDelta(dx, dy); 47541 }, 47542 _onHover = function _onHover(e) { 47543 self.event = e; 47544 onHover(self); 47545 }, 47546 _onHoverEnd = function _onHoverEnd(e) { 47547 self.event = e; 47548 onHoverEnd(self); 47549 }, 47550 _onClick = function _onClick(e) { 47551 return _ignoreCheck(e) || _getEvent(e, preventDefault) && onClick(self); 47552 }; 47553 47554 onStopDelayedCall = self._dc = gsap.delayedCall(onStopDelay || 0.25, onStopFunc).pause(); 47555 self.deltaX = self.deltaY = 0; 47556 self._vx = _getVelocityProp(0, 50, true); 47557 self._vy = _getVelocityProp(0, 50, true); 47558 self.scrollX = scrollFuncX; 47559 self.scrollY = scrollFuncY; 47560 self.isDragging = self.isGesturing = self.isPressed = false;
vendor: 7,173 bytes, lines 47561-47803
47561 47562 _context(this); 47563 47564 self.enable = function (e) { 47565 if (!self.isEnabled) { 47566 _addListener(isViewport ? ownerDoc : target, "scroll", _onScroll); 47567 47568 type.indexOf("scroll") >= 0 && _addListener(isViewport ? ownerDoc : target, "scroll", onScroll, passive, capture); 47569 type.indexOf("wheel") >= 0 && _addListener(target, "wheel", _onWheel, passive, capture); 47570 47571 if (type.indexOf("touch") >= 0 && _isTouch || type.indexOf("pointer") >= 0) { 47572 _addListener(target, _eventTypes[0], _onPress, passive, capture); 47573 47574 _addListener(ownerDoc, _eventTypes[2], _onRelease); 47575 47576 _addListener(ownerDoc, _eventTypes[3], _onRelease); 47577 47578 allowClicks && _addListener(target, "click", clickCapture, true, true); 47579 onClick && _addListener(target, "click", _onClick); 47580 onGestureStart && _addListener(ownerDoc, "gesturestart", _onGestureStart); 47581 onGestureEnd && _addListener(ownerDoc, "gestureend", _onGestureEnd); 47582 onHover && _addListener(target, _pointerType + "enter", _onHover); 47583 onHoverEnd && _addListener(target, _pointerType + "leave", _onHoverEnd); 47584 onMove && _addListener(target, _pointerType + "move", _onMove); 47585 } 47586 47587 self.isEnabled = true; 47588 e && e.type && _onPress(e); 47589 onEnable && onEnable(self); 47590 } 47591 47592 return self; 47593 }; 47594 47595 self.disable = function () { 47596 if (self.isEnabled) { 47597 _observers.filter(function (o) { 47598 return o !== self && _isViewport(o.target); 47599 }).length || _removeListener(isViewport ? ownerDoc : target, "scroll", _onScroll); 47600 47601 if (self.isPressed) { 47602 self._vx.reset(); 47603 47604 self._vy.reset(); 47605 47606 _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true); 47607 } 47608 47609 _removeListener(isViewport ? ownerDoc : target, "scroll", onScroll, capture); 47610 47611 _removeListener(target, "wheel", _onWheel, capture); 47612 47613 _removeListener(target, _eventTypes[0], _onPress, capture); 47614 47615 _removeListener(ownerDoc, _eventTypes[2], _onRelease); 47616 47617 _removeListener(ownerDoc, _eventTypes[3], _onRelease); 47618 47619 _removeListener(target, "click", clickCapture, true); 47620 47621 _removeListener(target, "click", _onClick); 47622 47623 _removeListener(ownerDoc, "gesturestart", _onGestureStart); 47624 47625 _removeListener(ownerDoc, "gestureend", _onGestureEnd); 47626 47627 _removeListener(target, _pointerType + "enter", _onHover); 47628 47629 _removeListener(target, _pointerType + "leave", _onHoverEnd); 47630 47631 _removeListener(target, _pointerType + "move", _onMove); 47632 47633 self.isEnabled = self.isPressed = self.isDragging = false; 47634 onDisable && onDisable(self); 47635 } 47636 }; 47637 47638 self.kill = self.revert = function () { 47639 self.disable(); 47640 47641 var i = _observers.indexOf(self); 47642 47643 i >= 0 && _observers.splice(i, 1); 47644 _normalizer === self && (_normalizer = 0); 47645 }; 47646 47647 _observers.push(self); 47648 47649 isNormalizer && _isViewport(target) && (_normalizer = self); 47650 self.enable(event); 47651 }; 47652 47653 _createClass(Observer, [{ 47654 key: "velocityX", 47655 get: function get() { 47656 return this._vx.getVelocity(); 47657 } 47658 }, { 47659 key: "velocityY", 47660 get: function get() { 47661 return this._vy.getVelocity(); 47662 } 47663 }]); 47664 47665 return Observer; 47666 }(); 47667 Observer.version = "3.12.5"; 47668 47669 Observer.create = function (vars) { 47670 return new Observer(vars); 47671 }; 47672 47673 Observer.register = _initCore; 47674 47675 Observer.getAll = function () { 47676 return _observers.slice(); 47677 }; 47678 47679 Observer.getById = function (id) { 47680 return _observers.filter(function (o) { 47681 return o.vars.id === id; 47682 })[0]; 47683 }; 47684 47685 _getGSAP() && gsap.registerPlugin(Observer); 47686 47687 /*! 47688 * ScrollTrigger 3.12.5 47689 * https://gsap.com 47690 * 47691 * @license Copyright 2008-2024, GreenSock. All rights reserved. 47692 * Subject to the terms at https://gsap.com/standard-license or for 47693 * Club GSAP members, the agreement issued with that membership. 47694 * @author: Jack Doyle, [email protected] 47695 */ 47696 47697 var gsap$1, 47698 _coreInitted$1, 47699 _win$1, 47700 _doc$1, 47701 _docEl$1, 47702 _body$1, 47703 _root$1, 47704 _resizeDelay, 47705 _toArray, 47706 _clamp$1, 47707 _time2, 47708 _syncInterval, 47709 _refreshing, 47710 _pointerIsDown, 47711 _transformProp, 47712 _i, 47713 _prevWidth, 47714 _prevHeight, 47715 _autoRefresh, 47716 _sort, 47717 _suppressOverwrites, 47718 _ignoreResize, 47719 _normalizer$1, 47720 _ignoreMobileResize, 47721 _baseScreenHeight, 47722 _baseScreenWidth, 47723 _fixIOSBug, 47724 _context$1, 47725 _scrollRestoration, 47726 _div100vh, 47727 _100vh, 47728 _isReverted, 47729 _clampingMax, 47730 _limitCallbacks, 47731 _startup$1 = 1, 47732 _getTime$1 = Date.now, 47733 _time1 = _getTime$1(), 47734 _lastScrollTime = 0, 47735 _enabled = 0, 47736 _parseClamp = function _parseClamp(value, type, self) { 47737 var clamp = _isString(value) && (value.substr(0, 6) === "clamp(" || value.indexOf("max") > -1); 47738 self["_" + type + "Clamp"] = clamp; 47739 return clamp ? value.substr(6, value.length - 7) : value; 47740 }, 47741 _keepClamp = function _keepClamp(value, clamp) { 47742 return clamp && (!_isString(value) || value.substr(0, 6) !== "clamp(") ? "clamp(" + value + ")" : value; 47743 }, 47744 _rafBugFix = function _rafBugFix() { 47745 return _enabled && requestAnimationFrame(_rafBugFix); 47746 }, 47747 _pointerDownHandler = function _pointerDownHandler() { 47748 return _pointerIsDown = 1; 47749 }, 47750 _pointerUpHandler = function _pointerUpHandler() { 47751 return _pointerIsDown = 0; 47752 }, 47753 _passThrough = function _passThrough(v) { 47754 return v; 47755 }, 47756 _round = function _round(value) { 47757 return Math.round(value * 100000) / 100000 || 0; 47758 }, 47759 _windowExists = function _windowExists() { 47760 return typeof window !== "undefined"; 47761 }, 47762 _getGSAP$1 = function _getGSAP() { 47763 return gsap$1 || _windowExists() && (gsap$1 = window.gsap) && gsap$1.registerPlugin && gsap$1; 47764 }, 47765 _isViewport$1 = function _isViewport(e) { 47766 return !!~_root$1.indexOf(e); 47767 }, 47768 _getViewportDimension = function _getViewportDimension(dimensionProperty) { 47769 return (dimensionProperty === "Height" ? _100vh : _win$1["inner" + dimensionProperty]) || _docEl$1["client" + dimensionProperty] || _body$1["client" + dimensionProperty]; 47770 }, 47771 _getBoundsFunc = function _getBoundsFunc(element) { 47772 return _getProxyProp(element, "getBoundingClientRect") || (_isViewport$1(element) ? function () { 47773 _winOffsets.width = _win$1.innerWidth; 47774 _winOffsets.height = _100vh; 47775 return _winOffsets; 47776 } : function () { 47777 return _getBounds(element); 47778 }); 47779 }, 47780 _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref) { 47781 var d = _ref.d, 47782 d2 = _ref.d2, 47783 a = _ref.a; 47784 return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () { 47785 return a()[d]; 47786 } : function () { 47787 return (isViewport ? _getViewportDimension(d2) : scroller["client" + d2]) || 0; 47788 }; 47789 }, 47790 _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) { 47791 return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () { 47792 return _winOffsets; 47793 }; 47794 }, 47795 _maxScroll = function _maxScroll(element, _ref2) { 47796 var s = _ref2.s, 47797 d2 = _ref2.d2, 47798 d = _ref2.d, 47799 a = _ref2.a; 47800 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]); 47801 }, 47802 _iterateAutoRefresh = function _iterateAutoRefresh(func, events) { 47803 for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 14,082 bytes, lines 47804-48275
47804 (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]); 47805 } 47806 }, 47807 _isString = function _isString(value) { 47808 return typeof value === "string"; 47809 }, 47810 _isFunction = function _isFunction(value) { 47811 return typeof value === "function"; 47812 }, 47813 _isNumber = function _isNumber(value) { 47814 return typeof value === "number"; 47815 }, 47816 _isObject = function _isObject(value) { 47817 return typeof value === "object"; 47818 }, 47819 _endAnimation = function _endAnimation(animation, reversed, pause) { 47820 return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause(); 47821 }, 47822 _callback = function _callback(self, func) { 47823 if (self.enabled) { 47824 var result = self._ctx ? self._ctx.add(function () { 47825 return func(self); 47826 }) : func(self); 47827 result && result.totalTime && (self.callbackAnimation = result); 47828 } 47829 }, 47830 _abs = Math.abs, 47831 _left = "left", 47832 _top = "top", 47833 _right = "right", 47834 _bottom = "bottom", 47835 _width = "width", 47836 _height = "height", 47837 _Right = "Right", 47838 _Left = "Left", 47839 _Top = "Top", 47840 _Bottom = "Bottom", 47841 _padding = "padding", 47842 _margin = "margin", 47843 _Width = "Width", 47844 _Height = "Height", 47845 _px = "px", 47846 _getComputedStyle = function _getComputedStyle(element) { 47847 return _win$1.getComputedStyle(element); 47848 }, 47849 _makePositionable = function _makePositionable(element) { 47850 var position = _getComputedStyle(element).position; 47851 47852 element.style.position = position === "absolute" || position === "fixed" ? position : "relative"; 47853 }, 47854 _setDefaults = function _setDefaults(obj, defaults) { 47855 for (var p in defaults) { 47856 p in obj || (obj[p] = defaults[p]); 47857 } 47858 47859 return obj; 47860 }, 47861 _getBounds = function _getBounds(element, withoutTransforms) { 47862 var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap$1.to(element, { 47863 x: 0, 47864 y: 0, 47865 xPercent: 0, 47866 yPercent: 0, 47867 rotation: 0, 47868 rotationX: 0, 47869 rotationY: 0, 47870 scale: 1, 47871 skewX: 0, 47872 skewY: 0 47873 }).progress(1), 47874 bounds = element.getBoundingClientRect(); 47875 tween && tween.progress(0).kill(); 47876 return bounds; 47877 }, 47878 _getSize = function _getSize(element, _ref3) { 47879 var d2 = _ref3.d2; 47880 return element["offset" + d2] || element["client" + d2] || 0; 47881 }, 47882 _getLabelRatioArray = function _getLabelRatioArray(timeline) { 47883 var a = [], 47884 labels = timeline.labels, 47885 duration = timeline.duration(), 47886 p; 47887 47888 for (p in labels) { 47889 a.push(labels[p] / duration); 47890 } 47891 47892 return a; 47893 }, 47894 _getClosestLabel = function _getClosestLabel(animation) { 47895 return function (value) { 47896 return gsap$1.utils.snap(_getLabelRatioArray(animation), value); 47897 }; 47898 }, 47899 _snapDirectional = function _snapDirectional(snapIncrementOrArray) { 47900 var snap = gsap$1.utils.snap(snapIncrementOrArray), 47901 a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) { 47902 return a - b; 47903 }); 47904 return a ? function (value, direction, threshold) { 47905 if (threshold === void 0) { 47906 threshold = 1e-3; 47907 } 47908 47909 var i; 47910 47911 if (!direction) { 47912 return snap(value); 47913 } 47914 47915 if (direction > 0) { 47916 value -= threshold; 47917 47918 for (i = 0; i < a.length; i++) { 47919 if (a[i] >= value) { 47920 return a[i]; 47921 } 47922 } 47923 47924 return a[i - 1]; 47925 } else { 47926 i = a.length; 47927 value += threshold; 47928 47929 while (i--) { 47930 if (a[i] <= value) { 47931 return a[i]; 47932 } 47933 } 47934 } 47935 47936 return a[0]; 47937 } : function (value, direction, threshold) { 47938 if (threshold === void 0) { 47939 threshold = 1e-3; 47940 } 47941 47942 var snapped = snap(value); 47943 return !direction || Math.abs(snapped - value) < threshold || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray); 47944 }; 47945 }, 47946 _getLabelAtDirection = function _getLabelAtDirection(timeline) { 47947 return function (value, st) { 47948 return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction); 47949 }; 47950 }, 47951 _multiListener = function _multiListener(func, element, types, callback) { 47952 return types.split(",").forEach(function (type) { 47953 return func(element, type, callback); 47954 }); 47955 }, 47956 _addListener$1 = function _addListener(element, type, func, nonPassive, capture) { 47957 return element.addEventListener(type, func, { 47958 passive: !nonPassive, 47959 capture: !!capture 47960 }); 47961 }, 47962 _removeListener$1 = function _removeListener(element, type, func, capture) { 47963 return element.removeEventListener(type, func, !!capture); 47964 }, 47965 _wheelListener = function _wheelListener(func, el, scrollFunc) { 47966 scrollFunc = scrollFunc && scrollFunc.wheelHandler; 47967 47968 if (scrollFunc) { 47969 func(el, "wheel", scrollFunc); 47970 func(el, "touchmove", scrollFunc); 47971 } 47972 }, 47973 _markerDefaults = { 47974 startColor: "green", 47975 endColor: "red", 47976 indent: 0, 47977 fontSize: "16px", 47978 fontWeight: "normal" 47979 }, 47980 _defaults = { 47981 toggleActions: "play", 47982 anticipatePin: 0 47983 }, 47984 _keywords = { 47985 top: 0, 47986 left: 0, 47987 center: 0.5, 47988 bottom: 1, 47989 right: 1 47990 }, 47991 _offsetToPx = function _offsetToPx(value, size) { 47992 if (_isString(value)) { 47993 var eqIndex = value.indexOf("="), 47994 relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0; 47995 47996 if (~eqIndex) { 47997 value.indexOf("%") > eqIndex && (relative *= size / 100); 47998 value = value.substr(0, eqIndex - 1); 47999 } 48000 48001 value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0); 48002 } 48003 48004 return value; 48005 }, 48006 _createMarker = function _createMarker(type, name, container, direction, _ref4, offset, matchWidthEl, containerAnimation) { 48007 var startColor = _ref4.startColor, 48008 endColor = _ref4.endColor, 48009 fontSize = _ref4.fontSize, 48010 indent = _ref4.indent, 48011 fontWeight = _ref4.fontWeight; 48012 48013 var e = _doc$1.createElement("div"), 48014 useFixedPosition = _isViewport$1(container) || _getProxyProp(container, "pinType") === "fixed", 48015 isScroller = type.indexOf("scroller") !== -1, 48016 parent = useFixedPosition ? _body$1 : container, 48017 isStart = type.indexOf("start") !== -1, 48018 color = isStart ? startColor : endColor, 48019 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;"; 48020 48021 css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;"); 48022 (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;"); 48023 matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;"); 48024 e._isStart = isStart; 48025 e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : "")); 48026 e.style.cssText = css; 48027 e.innerText = name || name === 0 ? type + "-" + name : type; 48028 parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e); 48029 e._offset = e["offset" + direction.op.d2]; 48030 48031 _positionMarker(e, 0, direction, isStart); 48032 48033 return e; 48034 }, 48035 _positionMarker = function _positionMarker(marker, start, direction, flipped) { 48036 var vars = { 48037 display: "block" 48038 }, 48039 side = direction[flipped ? "os2" : "p2"], 48040 oppositeSide = direction[flipped ? "p2" : "os2"]; 48041 marker._isFlipped = flipped; 48042 vars[direction.a + "Percent"] = flipped ? -100 : 0; 48043 vars[direction.a] = flipped ? "1px" : 0; 48044 vars["border" + side + _Width] = 1; 48045 vars["border" + oppositeSide + _Width] = 0; 48046 vars[direction.p] = start + "px"; 48047 gsap$1.set(marker, vars); 48048 }, 48049 _triggers = [], 48050 _ids = {}, 48051 _rafID, 48052 _sync = function _sync() { 48053 return _getTime$1() - _lastScrollTime > 34 && (_rafID || (_rafID = requestAnimationFrame(_updateAll))); 48054 }, 48055 _onScroll$1 = function _onScroll() { 48056 if (!_normalizer$1 || !_normalizer$1.isPressed || _normalizer$1.startX > _body$1.clientWidth) { 48057 _scrollers.cache++; 48058 48059 if (_normalizer$1) { 48060 _rafID || (_rafID = requestAnimationFrame(_updateAll)); 48061 } else { 48062 _updateAll(); 48063 } 48064 48065 _lastScrollTime || _dispatch("scrollStart"); 48066 _lastScrollTime = _getTime$1(); 48067 } 48068 }, 48069 _setBaseDimensions = function _setBaseDimensions() { 48070 _baseScreenWidth = _win$1.innerWidth; 48071 _baseScreenHeight = _win$1.innerHeight; 48072 }, 48073 _onResize = function _onResize() { 48074 _scrollers.cache++; 48075 !_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); 48076 }, 48077 _listeners = {}, 48078 _emptyArray = [], 48079 _softRefresh = function _softRefresh() { 48080 return _removeListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh) || _refreshAll(true); 48081 }, 48082 _dispatch = function _dispatch(type) { 48083 return _listeners[type] && _listeners[type].map(function (f) { 48084 return f(); 48085 }) || _emptyArray; 48086 }, 48087 _savedStyles = [], 48088 _revertRecorded = function _revertRecorded(media) { 48089 for (var i = 0; i < _savedStyles.length; i += 5) { 48090 if (!media || _savedStyles[i + 4] && _savedStyles[i + 4].query === media) { 48091 _savedStyles[i].style.cssText = _savedStyles[i + 1]; 48092 _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || ""); 48093 _savedStyles[i + 3].uncache = 1; 48094 } 48095 } 48096 }, 48097 _revertAll = function _revertAll(kill, media) { 48098 var trigger; 48099 48100 for (_i = 0; _i < _triggers.length; _i++) { 48101 trigger = _triggers[_i]; 48102 48103 if (trigger && (!media || trigger._ctx === media)) { 48104 if (kill) { 48105 trigger.kill(1); 48106 } else { 48107 trigger.revert(true, true); 48108 } 48109 } 48110 } 48111 48112 _isReverted = true; 48113 media && _revertRecorded(media); 48114 media || _dispatch("revert"); 48115 }, 48116 _clearScrollMemory = function _clearScrollMemory(scrollRestoration, force) { 48117 _scrollers.cache++; 48118 (force || !_refreshingAll) && _scrollers.forEach(function (obj) { 48119 return _isFunction(obj) && obj.cacheID++ && (obj.rec = 0); 48120 }); 48121 _isString(scrollRestoration) && (_win$1.history.scrollRestoration = _scrollRestoration = scrollRestoration); 48122 }, 48123 _refreshingAll, 48124 _refreshID = 0, 48125 _queueRefreshID, 48126 _queueRefreshAll = function _queueRefreshAll() { 48127 if (_queueRefreshID !== _refreshID) { 48128 var id = _queueRefreshID = _refreshID; 48129 requestAnimationFrame(function () { 48130 return id === _refreshID && _refreshAll(true); 48131 }); 48132 } 48133 }, 48134 _refresh100vh = function _refresh100vh() { 48135 _body$1.appendChild(_div100vh); 48136 48137 _100vh = !_normalizer$1 && _div100vh.offsetHeight || _win$1.innerHeight; 48138 48139 _body$1.removeChild(_div100vh); 48140 }, 48141 _hideAllMarkers = function _hideAllMarkers(hide) { 48142 return _toArray(".gsap-marker-start, .gsap-marker-end, .gsap-marker-scroller-start, .gsap-marker-scroller-end").forEach(function (el) { 48143 return el.style.display = hide ? "none" : "block"; 48144 }); 48145 }, 48146 _refreshAll = function _refreshAll(force, skipRevert) { 48147 if (_lastScrollTime && !force && !_isReverted) { 48148 _addListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh); 48149 48150 return; 48151 } 48152 48153 _refresh100vh(); 48154 48155 _refreshingAll = ScrollTrigger$1.isRefreshing = true; 48156 48157 _scrollers.forEach(function (obj) { 48158 return _isFunction(obj) && ++obj.cacheID && (obj.rec = obj()); 48159 }); 48160 48161 var refreshInits = _dispatch("refreshInit"); 48162 48163 _sort && ScrollTrigger$1.sort(); 48164 skipRevert || _revertAll(); 48165 48166 _scrollers.forEach(function (obj) { 48167 if (_isFunction(obj)) { 48168 obj.smooth && (obj.target.style.scrollBehavior = "auto"); 48169 obj(0); 48170 } 48171 }); 48172 48173 _triggers.slice(0).forEach(function (t) { 48174 return t.refresh(); 48175 }); 48176 48177 _isReverted = false; 48178 48179 _triggers.forEach(function (t) { 48180 if (t._subPinOffset && t.pin) { 48181 var prop = t.vars.horizontal ? "offsetWidth" : "offsetHeight", 48182 original = t.pin[prop]; 48183 t.revert(true, 1); 48184 t.adjustPinSpacing(t.pin[prop] - original); 48185 t.refresh(); 48186 } 48187 }); 48188 48189 _clampingMax = 1; 48190 48191 _hideAllMarkers(true); 48192 48193 _triggers.forEach(function (t) { 48194 var max = _maxScroll(t.scroller, t._dir), 48195 endClamp = t.vars.end === "max" || t._endClamp && t.end > max, 48196 startClamp = t._startClamp && t.start >= max; 48197 48198 (endClamp || startClamp) && t.setPositions(startClamp ? max - 1 : t.start, endClamp ? Math.max(startClamp ? max : t.start + 1, max) : t.end, true); 48199 }); 48200 48201 _hideAllMarkers(false); 48202 48203 _clampingMax = 0; 48204 refreshInits.forEach(function (result) { 48205 return result && result.render && result.render(-1); 48206 }); 48207 48208 _scrollers.forEach(function (obj) { 48209 if (_isFunction(obj)) { 48210 obj.smooth && requestAnimationFrame(function () { 48211 return obj.target.style.scrollBehavior = "smooth"; 48212 }); 48213 obj.rec && obj(obj.rec); 48214 } 48215 }); 48216 48217 _clearScrollMemory(_scrollRestoration, 1); 48218 48219 _resizeDelay.pause(); 48220 48221 _refreshID++; 48222 _refreshingAll = 2; 48223 48224 _updateAll(2); 48225 48226 _triggers.forEach(function (t) { 48227 return _isFunction(t.vars.onRefresh) && t.vars.onRefresh(t); 48228 }); 48229 48230 _refreshingAll = ScrollTrigger$1.isRefreshing = false; 48231 48232 _dispatch("refresh"); 48233 }, 48234 _lastScroll = 0, 48235 _direction = 1, 48236 _primary, 48237 _updateAll = function _updateAll(force) { 48238 if (force === 2 || !_refreshingAll && !_isReverted) { 48239 ScrollTrigger$1.isUpdating = true; 48240 _primary && _primary.update(0); 48241 48242 var l = _triggers.length, 48243 time = _getTime$1(), 48244 recordVelocity = time - _time1 >= 50, 48245 scroll = l && _triggers[0].scroll(); 48246 48247 _direction = _lastScroll > scroll ? -1 : 1; 48248 _refreshingAll || (_lastScroll = scroll); 48249 48250 if (recordVelocity) { 48251 if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) { 48252 _lastScrollTime = 0; 48253 48254 _dispatch("scrollEnd"); 48255 } 48256 48257 _time2 = _time1; 48258 _time1 = time; 48259 } 48260 48261 if (_direction < 0) { 48262 _i = l; 48263 48264 while (_i-- > 0) { 48265 _triggers[_i] && _triggers[_i].update(0, recordVelocity); 48266 } 48267 48268 _direction = 1; 48269 } else { 48270 for (_i = 0; _i < l; _i++) { 48271 _triggers[_i] && _triggers[_i].update(0, recordVelocity); 48272 } 48273 } 48274 48275 ScrollTrigger$1.isUpdating = false;
vendor: 4,937 bytes, lines 48276-48426
48276 } 48277 48278 _rafID = 0; 48279 }, 48280 _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"], 48281 _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]), 48282 _swapPinOut = function _swapPinOut(pin, spacer, state) { 48283 _setState(state); 48284 48285 var cache = pin._gsap; 48286 48287 if (cache.spacerIsNative) { 48288 _setState(cache.spacerState); 48289 } else if (pin._gsap.swappedIn) { 48290 var parent = spacer.parentNode; 48291 48292 if (parent) { 48293 parent.insertBefore(pin, spacer); 48294 parent.removeChild(spacer); 48295 } 48296 } 48297 48298 pin._gsap.swappedIn = false; 48299 }, 48300 _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) { 48301 if (!pin._gsap.swappedIn) { 48302 var i = _propNamesToCopy.length, 48303 spacerStyle = spacer.style, 48304 pinStyle = pin.style, 48305 p; 48306 48307 while (i--) { 48308 p = _propNamesToCopy[i]; 48309 spacerStyle[p] = cs[p]; 48310 } 48311 48312 spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative"; 48313 cs.display === "inline" && (spacerStyle.display = "inline-block"); 48314 pinStyle[_bottom] = pinStyle[_right] = "auto"; 48315 spacerStyle.flexBasis = cs.flexBasis || "auto"; 48316 spacerStyle.overflow = "visible"; 48317 spacerStyle.boxSizing = "border-box"; 48318 spacerStyle[_width] = _getSize(pin, _horizontal) + _px; 48319 spacerStyle[_height] = _getSize(pin, _vertical) + _px; 48320 spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0"; 48321 48322 _setState(spacerState); 48323 48324 pinStyle[_width] = pinStyle["max" + _Width] = cs[_width]; 48325 pinStyle[_height] = pinStyle["max" + _Height] = cs[_height]; 48326 pinStyle[_padding] = cs[_padding]; 48327 48328 if (pin.parentNode !== spacer) { 48329 pin.parentNode.insertBefore(spacer, pin); 48330 spacer.appendChild(pin); 48331 } 48332 48333 pin._gsap.swappedIn = true; 48334 } 48335 }, 48336 _capsExp = /([A-Z])/g, 48337 _setState = function _setState(state) { 48338 if (state) { 48339 var style = state.t.style, 48340 l = state.length, 48341 i = 0, 48342 p, 48343 value; 48344 (state.t._gsap || gsap$1.core.getCache(state.t)).uncache = 1; 48345 48346 for (; i < l; i += 2) { 48347 value = state[i + 1]; 48348 p = state[i]; 48349 48350 if (value) { 48351 style[p] = value; 48352 } else if (style[p]) { 48353 style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase()); 48354 } 48355 } 48356 } 48357 }, 48358 _getState = function _getState(element) { 48359 var l = _stateProps.length, 48360 style = element.style, 48361 state = [], 48362 i = 0; 48363 48364 for (; i < l; i++) { 48365 state.push(_stateProps[i], style[_stateProps[i]]); 48366 } 48367 48368 state.t = element; 48369 return state; 48370 }, 48371 _copyState = function _copyState(state, override, omitOffsets) { 48372 var result = [], 48373 l = state.length, 48374 i = omitOffsets ? 8 : 0, 48375 p; 48376 48377 for (; i < l; i += 2) { 48378 p = state[i]; 48379 result.push(p, p in override ? override[p] : state[i + 1]); 48380 } 48381 48382 result.t = state.t; 48383 return result; 48384 }, 48385 _winOffsets = { 48386 left: 0, 48387 top: 0 48388 }, 48389 _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation, clampZeroProp) { 48390 _isFunction(value) && (value = value(self)); 48391 48392 if (_isString(value) && value.substr(0, 3) === "max") { 48393 value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0); 48394 } 48395 48396 var time = containerAnimation ? containerAnimation.time() : 0, 48397 p1, 48398 p2, 48399 element; 48400 containerAnimation && containerAnimation.seek(0); 48401 isNaN(value) || (value = +value); 48402 48403 if (!_isNumber(value)) { 48404 _isFunction(trigger) && (trigger = trigger(self)); 48405 var offsets = (value || "0").split(" "), 48406 bounds, 48407 localOffset, 48408 globalOffset, 48409 display; 48410 element = _getTarget(trigger, self) || _body$1; 48411 bounds = _getBounds(element) || {}; 48412 48413 if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") { 48414 display = element.style.display; 48415 element.style.display = "block"; 48416 bounds = _getBounds(element); 48417 display ? element.style.display = display : element.style.removeProperty("display"); 48418 } 48419 48420 localOffset = _offsetToPx(offsets[0], bounds[direction.d]); 48421 globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize); 48422 value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset; 48423 markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20); 48424 scrollerSize -= scrollerSize - globalOffset; 48425 } else { 48426 containerAnimation && (value = gsap$1.utils.mapRange(containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, 0, scrollerMa
vendor: 4,541 bytes, lines 48426-48582
48426x, value)); 48427 markerScroller && _positionMarker(markerScroller, scrollerSize, direction, true); 48428 } 48429 48430 if (clampZeroProp) { 48431 self[clampZeroProp] = value || -0.001; 48432 value < 0 && (value = 0); 48433 } 48434 48435 if (marker) { 48436 var position = value + scrollerSize, 48437 isStart = marker._isStart; 48438 p1 = "scroll" + direction.d2; 48439 48440 _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body$1[p1], _docEl$1[p1]) : marker.parentNode[p1]) <= position + 1); 48441 48442 if (useFixedPosition) { 48443 scrollerBounds = _getBounds(markerScroller); 48444 useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px); 48445 } 48446 } 48447 48448 if (containerAnimation && element) { 48449 p1 = _getBounds(element); 48450 containerAnimation.seek(scrollerMax); 48451 p2 = _getBounds(element); 48452 containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p]; 48453 value = value / containerAnimation._caScrollDist * scrollerMax; 48454 } 48455 48456 containerAnimation && containerAnimation.seek(time); 48457 return containerAnimation ? value : Math.round(value); 48458 }, 48459 _prefixExp = /(webkit|moz|length|cssText|inset)/i, 48460 _reparent = function _reparent(element, parent, top, left) { 48461 if (element.parentNode !== parent) { 48462 var style = element.style, 48463 p, 48464 cs; 48465 48466 if (parent === _body$1) { 48467 element._stOrig = style.cssText; 48468 cs = _getComputedStyle(element); 48469 48470 for (p in cs) { 48471 if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") { 48472 style[p] = cs[p]; 48473 } 48474 } 48475 48476 style.top = top; 48477 style.left = left; 48478 } else { 48479 style.cssText = element._stOrig; 48480 } 48481 48482 gsap$1.core.getCache(element).uncache = 1; 48483 parent.appendChild(element); 48484 } 48485 }, 48486 _interruptionTracker = function _interruptionTracker(getValueFunc, initialValue, onInterrupt) { 48487 var last1 = initialValue, 48488 last2 = last1; 48489 return function (value) { 48490 var current = Math.round(getValueFunc()); 48491 48492 if (current !== last1 && current !== last2 && Math.abs(current - last1) > 3 && Math.abs(current - last2) > 3) { 48493 value = current; 48494 onInterrupt && onInterrupt(); 48495 } 48496 48497 last2 = last1; 48498 last1 = value; 48499 return value; 48500 }; 48501 }, 48502 _shiftMarker = function _shiftMarker(marker, direction, value) { 48503 var vars = {}; 48504 vars[direction.p] = "+=" + value; 48505 gsap$1.set(marker, vars); 48506 }, 48507 _getTweenCreator = function _getTweenCreator(scroller, direction) { 48508 var getScroll = _getScrollFunc(scroller, direction), 48509 prop = "_scroll" + direction.p2, 48510 getTween = function getTween(scrollTo, vars, initialValue, change1, change2) { 48511 var tween = getTween.tween, 48512 onComplete = vars.onComplete, 48513 modifiers = {}; 48514 initialValue = initialValue || getScroll(); 48515 48516 var checkForInterruption = _interruptionTracker(getScroll, initialValue, function () { 48517 tween.kill(); 48518 getTween.tween = 0; 48519 }); 48520 48521 change2 = change1 && change2 || 0; 48522 change1 = change1 || scrollTo - initialValue; 48523 tween && tween.kill(); 48524 vars[prop] = scrollTo; 48525 vars.inherit = false; 48526 vars.modifiers = modifiers; 48527 48528 modifiers[prop] = function () { 48529 return checkForInterruption(initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio); 48530 }; 48531 48532 vars.onUpdate = function () { 48533 _scrollers.cache++; 48534 getTween.tween && _updateAll(); 48535 }; 48536 48537 vars.onComplete = function () { 48538 getTween.tween = 0; 48539 onComplete && onComplete.call(tween); 48540 }; 48541 48542 tween = getTween.tween = gsap$1.to(scroller, vars); 48543 return tween; 48544 }; 48545 48546 scroller[prop] = getScroll; 48547 48548 getScroll.wheelHandler = function () { 48549 return getTween.tween && getTween.tween.kill() && (getTween.tween = 0); 48550 }; 48551 48552 _addListener$1(scroller, "wheel", getScroll.wheelHandler); 48553 48554 ScrollTrigger$1.isTouch && _addListener$1(scroller, "touchmove", getScroll.wheelHandler); 48555 return getTween; 48556 }; 48557 48558 var ScrollTrigger$1 = function () { 48559 function ScrollTrigger(vars, animation) { 48560 _coreInitted$1 || ScrollTrigger.register(gsap$1) || console.warn("Please gsap.registerPlugin(ScrollTrigger)"); 48561 48562 _context$1(this); 48563 48564 this.init(vars, animation); 48565 } 48566 48567 var _proto = ScrollTrigger.prototype; 48568 48569 _proto.init = function init(vars, animation) { 48570 this.progress = this.start = 0; 48571 this.vars && this.kill(true, true); 48572 48573 if (!_enabled) { 48574 this.update = this.refresh = this.kill = _passThrough; 48575 return; 48576 } 48577 48578 vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? { 48579 trigger: vars 48580 } : vars, _defaults); 48581 48582 var _vars = vars,
vendor: 4,184 bytes, lines 48583-48723
48583 onUpdate = _vars.onUpdate, 48584 toggleClass = _vars.toggleClass, 48585 id = _vars.id, 48586 onToggle = _vars.onToggle, 48587 onRefresh = _vars.onRefresh, 48588 scrub = _vars.scrub, 48589 trigger = _vars.trigger, 48590 pin = _vars.pin, 48591 pinSpacing = _vars.pinSpacing, 48592 invalidateOnRefresh = _vars.invalidateOnRefresh, 48593 anticipatePin = _vars.anticipatePin, 48594 onScrubComplete = _vars.onScrubComplete, 48595 onSnapComplete = _vars.onSnapComplete, 48596 once = _vars.once, 48597 snap = _vars.snap, 48598 pinReparent = _vars.pinReparent, 48599 pinSpacer = _vars.pinSpacer, 48600 containerAnimation = _vars.containerAnimation, 48601 fastScrollEnd = _vars.fastScrollEnd, 48602 preventOverlaps = _vars.preventOverlaps, 48603 direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical, 48604 isToggle = !scrub && scrub !== 0, 48605 scroller = _getTarget(vars.scroller || _win$1), 48606 scrollerCache = gsap$1.core.getCache(scroller), 48607 isViewport = _isViewport$1(scroller), 48608 useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed", 48609 callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack], 48610 toggleActions = isToggle && vars.toggleActions.split(" "), 48611 markers = "markers" in vars ? vars.markers : _defaults.markers, 48612 borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0, 48613 self = this, 48614 onRefreshInit = vars.onRefreshInit && function () { 48615 return vars.onRefreshInit(self); 48616 }, 48617 getScrollerSize = _getSizeFunc(scroller, isViewport, direction), 48618 getScrollerOffsets = _getOffsetsFunc(scroller, isViewport), 48619 lastSnap = 0, 48620 lastRefresh = 0, 48621 prevProgress = 0, 48622 scrollFunc = _getScrollFunc(scroller, direction), 48623 tweenTo, 48624 pinCache, 48625 snapFunc, 48626 scroll1, 48627 scroll2, 48628 start, 48629 end, 48630 markerStart, 48631 markerEnd, 48632 markerStartTrigger, 48633 markerEndTrigger, 48634 markerVars, 48635 executingOnRefresh, 48636 change, 48637 pinOriginalState, 48638 pinActiveState, 48639 pinState, 48640 spacer, 48641 offset, 48642 pinGetter, 48643 pinSetter, 48644 pinStart, 48645 pinChange, 48646 spacingStart, 48647 spacerState, 48648 markerStartSetter, 48649 pinMoves, 48650 markerEndSetter, 48651 cs, 48652 snap1, 48653 snap2, 48654 scrubTween, 48655 scrubSmooth, 48656 snapDurClamp, 48657 snapDelayedCall, 48658 prevScroll, 48659 prevAnimProgress, 48660 caMarkerSetter, 48661 customRevertReturn; 48662 48663 self._startClamp = self._endClamp = false; 48664 self._dir = direction; 48665 anticipatePin *= 45; 48666 self.scroller = scroller; 48667 self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc; 48668 scroll1 = scrollFunc(); 48669 self.vars = vars; 48670 animation = animation || vars.animation; 48671 48672 if ("refreshPriority" in vars) { 48673 _sort = 1; 48674 vars.refreshPriority === -9999 && (_primary = self); 48675 } 48676 48677 scrollerCache.tweenScroll = scrollerCache.tweenScroll || { 48678 top: _getTweenCreator(scroller, _vertical), 48679 left: _getTweenCreator(scroller, _horizontal) 48680 }; 48681 self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p]; 48682 48683 self.scrubDuration = function (value) { 48684 scrubSmooth = _isNumber(value) && value; 48685 48686 if (!scrubSmooth) { 48687 scrubTween && scrubTween.progress(1).kill(); 48688 scrubTween = 0; 48689 } else { 48690 scrubTween ? scrubTween.duration(value) : scrubTween = gsap$1.to(animation, { 48691 ease: "expo", 48692 totalProgress: "+=0", 48693 inherit: false, 48694 duration: scrubSmooth, 48695 paused: true, 48696 onComplete: function onComplete() { 48697 return onScrubComplete && onScrubComplete(self); 48698 } 48699 }); 48700 } 48701 }; 48702 48703 if (animation) { 48704 animation.vars.lazy = false; 48705 animation._initted && !self.isReverted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.duration() && animation.render(0, true, true); 48706 self.animation = animation.pause(); 48707 animation.scrollTrigger = self; 48708 self.scrubDuration(scrub); 48709 snap1 = 0; 48710 id || (id = animation.vars.id); 48711 } 48712 48713 if (snap) { 48714 if (!_isObject(snap) || snap.push) { 48715 snap = { 48716 snapTo: snap 48717 }; 48718 } 48719 48720 "scrollBehavior" in _body$1.style && gsap$1.set(isViewport ? [_body$1, _docEl$1] : scroller, { 48721 scrollBehavior: "auto" 48722 }); 48723
vendor: 4,259 bytes, lines 48724-48819
48724 _scrollers.forEach(function (o) { 48725 return _isFunction(o) && o.target === (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller) && (o.smooth = false); 48726 }); 48727 48728 snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) { 48729 return _snapDirectional(snap.snapTo)(value, _getTime$1() - lastRefresh < 500 ? 0 : st.direction); 48730 } : gsap$1.utils.snap(snap.snapTo); 48731 snapDurClamp = snap.duration || { 48732 min: 0.1, 48733 max: 2 48734 }; 48735 snapDurClamp = _isObject(snapDurClamp) ? _clamp$1(snapDurClamp.min, snapDurClamp.max) : _clamp$1(snapDurClamp, snapDurClamp); 48736 snapDelayedCall = gsap$1.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () { 48737 var scroll = scrollFunc(), 48738 refreshedRecently = _getTime$1() - lastRefresh < 500, 48739 tween = tweenTo.tween; 48740 48741 if ((refreshedRecently || Math.abs(self.getVelocity()) < 10) && !tween && !_pointerIsDown && lastSnap !== scroll) { 48742 var progress = (scroll - start) / change, 48743 totalProgress = animation && !isToggle ? animation.totalProgress() : progress, 48744 velocity = refreshedRecently ? 0 : (totalProgress - snap2) / (_getTime$1() - _time2) * 1000 || 0, 48745 change1 = gsap$1.utils.clamp(-progress, 1 - progress, _abs(velocity / 2) * velocity / 0.185), 48746 naturalEnd = progress + (snap.inertia === false ? 0 : change1), 48747 endValue, 48748 endScroll, 48749 _snap = snap, 48750 onStart = _snap.onStart, 48751 _onInterrupt = _snap.onInterrupt, 48752 _onComplete = _snap.onComplete; 48753 endValue = snapFunc(naturalEnd, self); 48754 _isNumber(endValue) || (endValue = naturalEnd); 48755 endScroll = Math.round(start + endValue * change); 48756 48757 if (scroll <= end && scroll >= start && endScroll !== scroll) { 48758 if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) { 48759 return; 48760 } 48761 48762 if (snap.inertia === false) { 48763 change1 = endValue - progress; 48764 } 48765 48766 tweenTo(endScroll, { 48767 duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)), 48768 ease: snap.ease || "power3", 48769 data: _abs(endScroll - scroll), 48770 onInterrupt: function onInterrupt() { 48771 return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self); 48772 }, 48773 onComplete: function onComplete() { 48774 self.update(); 48775 lastSnap = scrollFunc(); 48776 48777 if (animation) { 48778 scrubTween ? scrubTween.resetTo("totalProgress", endValue, animation._tTime / animation._tDur) : animation.progress(endValue); 48779 } 48780 48781 snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress; 48782 onSnapComplete && onSnapComplete(self); 48783 _onComplete && _onComplete(self); 48784 } 48785 }, scroll, change1 * change, endScroll - scroll - change1 * change); 48786 onStart && onStart(self, tweenTo.tween); 48787 } 48788 } else if (self.isActive && lastSnap !== scroll) { 48789 snapDelayedCall.restart(true); 48790 } 48791 }).pause(); 48792 } 48793 48794 id && (_ids[id] = self); 48795 trigger = self.trigger = _getTarget(trigger || pin !== true && pin); 48796 customRevertReturn = trigger && trigger._gsap && trigger._gsap.stRevert; 48797 customRevertReturn && (customRevertReturn = customRevertReturn(self)); 48798 pin = pin === true ? trigger : _getTarget(pin); 48799 _isString(toggleClass) && (toggleClass = { 48800 targets: trigger, 48801 className: toggleClass 48802 }); 48803 48804 if (pin) { 48805 pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && pin.parentNode && pin.parentNode.style && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding); 48806 self.pin = pin; 48807 pinCache = gsap$1.core.getCache(pin); 48808 48809 if (!pinCache.spacer) { 48810 if (pinSpacer) { 48811 pinSpacer = _getTarget(pinSpacer); 48812 pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement); 48813 pinCache.spacerIsNative = !!pinSpacer; 48814 pinSpacer && (pinCache.spacerState = _getState(pinSpacer)); 48815 } 48816 48817 pinCache.spacer = spacer = pinSpacer || _doc$1.createElement("div"); 48818 spacer.classList.add("pin-spacer"); 48819 id && spacer.classList.add("pin-spacer-" + id);
vendor: 4,987 bytes, lines 48820-48974
48820 pinCache.pinState = pinOriginalState = _getState(pin); 48821 } else { 48822 pinOriginalState = pinCache.pinState; 48823 } 48824 48825 vars.force3D !== false && gsap$1.set(pin, { 48826 force3D: true 48827 }); 48828 self.spacer = spacer = pinCache.spacer; 48829 cs = _getComputedStyle(pin); 48830 spacingStart = cs[pinSpacing + direction.os2]; 48831 pinGetter = gsap$1.getProperty(pin); 48832 pinSetter = gsap$1.quickSetter(pin, direction.a, _px); 48833 48834 _swapPinIn(pin, spacer, cs); 48835 48836 pinState = _getState(pin); 48837 } 48838 48839 if (markers) { 48840 markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults; 48841 markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0); 48842 markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger); 48843 offset = markerStartTrigger["offset" + direction.op.d2]; 48844 48845 var content = _getTarget(_getProxyProp(scroller, "content") || scroller); 48846 48847 markerStart = this.markerStart = _createMarker("start", id, content, direction, markerVars, offset, 0, containerAnimation); 48848 markerEnd = this.markerEnd = _createMarker("end", id, content, direction, markerVars, offset, 0, containerAnimation); 48849 containerAnimation && (caMarkerSetter = gsap$1.quickSetter([markerStart, markerEnd], direction.a, _px)); 48850 48851 if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) { 48852 _makePositionable(isViewport ? _body$1 : scroller); 48853 48854 gsap$1.set([markerStartTrigger, markerEndTrigger], { 48855 force3D: true 48856 }); 48857 markerStartSetter = gsap$1.quickSetter(markerStartTrigger, direction.a, _px); 48858 markerEndSetter = gsap$1.quickSetter(markerEndTrigger, direction.a, _px); 48859 } 48860 } 48861 48862 if (containerAnimation) { 48863 var oldOnUpdate = containerAnimation.vars.onUpdate, 48864 oldParams = containerAnimation.vars.onUpdateParams; 48865 containerAnimation.eventCallback("onUpdate", function () { 48866 self.update(0, 0, 1); 48867 oldOnUpdate && oldOnUpdate.apply(containerAnimation, oldParams || []); 48868 }); 48869 } 48870 48871 self.previous = function () { 48872 return _triggers[_triggers.indexOf(self) - 1]; 48873 }; 48874 48875 self.next = function () { 48876 return _triggers[_triggers.indexOf(self) + 1]; 48877 }; 48878 48879 self.revert = function (revert, temp) { 48880 if (!temp) { 48881 return self.kill(true); 48882 } 48883 48884 var r = revert !== false || !self.enabled, 48885 prevRefreshing = _refreshing; 48886 48887 if (r !== self.isReverted) { 48888 if (r) { 48889 prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0); 48890 prevProgress = self.progress; 48891 prevAnimProgress = animation && animation.progress(); 48892 } 48893 48894 markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) { 48895 return m.style.display = r ? "none" : "block"; 48896 }); 48897 48898 if (r) { 48899 _refreshing = self; 48900 self.update(r); 48901 } 48902 48903 if (pin && (!pinReparent || !self.isActive)) { 48904 if (r) { 48905 _swapPinOut(pin, spacer, pinOriginalState); 48906 } else { 48907 _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState); 48908 } 48909 } 48910 48911 r || self.update(r); 48912 _refreshing = prevRefreshing; 48913 self.isReverted = r; 48914 } 48915 }; 48916 48917 self.refresh = function (soft, force, position, pinOffset) { 48918 if ((_refreshing || !self.enabled) && !force) { 48919 return; 48920 } 48921 48922 if (pin && soft && _lastScrollTime) { 48923 _addListener$1(ScrollTrigger, "scrollEnd", _softRefresh); 48924 48925 return; 48926 } 48927 48928 !_refreshingAll && onRefreshInit && onRefreshInit(self); 48929 _refreshing = self; 48930 48931 if (tweenTo.tween && !position) { 48932 tweenTo.tween.kill(); 48933 tweenTo.tween = 0; 48934 } 48935 48936 scrubTween && scrubTween.pause(); 48937 invalidateOnRefresh && animation && animation.revert({ 48938 kill: false 48939 }).invalidate(); 48940 self.isReverted || self.revert(true, true); 48941 self._subPinOffset = false; 48942 48943 var size = getScrollerSize(), 48944 scrollerBounds = getScrollerOffsets(), 48945 max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction), 48946 isFirstRefresh = change <= 0.01, 48947 offset = 0, 48948 otherPinOffset = pinOffset || 0, 48949 parsedEnd = _isObject(position) ? position.end : vars.end, 48950 parsedEndTrigger = vars.endTrigger || trigger, 48951 parsedStart = _isObject(position) ? position.start : vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"), 48952 pinnedContainer = self.pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer, self), 48953 triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0, 48954 i = triggerIndex, 48955 cs, 48956 bounds, 48957 scroll, 48958 isVertical, 48959 override, 48960 curTrigger, 48961 curPin, 48962 oppositeScroll, 48963 initted, 48964 revertedPins, 48965 forcedOverflow, 48966 markerStartOffset, 48967 markerEndOffset; 48968 48969 if (markers && _isObject(position)) { 48970 markerStartOffset = gsap$1.getProperty(markerStartTrigger, direction.p); 48971 markerEndOffset = gsap$1.getProperty(markerEndTrigger, direction.p); 48972 } 48973 48974 while (i--) {
vendor: 4,360 bytes, lines 48975-49086
48975 curTrigger = _triggers[i]; 48976 curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = self); 48977 curPin = curTrigger.pin; 48978 48979 if (curPin && (curPin === trigger || curPin === pin || curPin === pinnedContainer) && !curTrigger.isReverted) { 48980 revertedPins || (revertedPins = []); 48981 revertedPins.unshift(curTrigger); 48982 curTrigger.revert(true, true); 48983 } 48984 48985 if (curTrigger !== _triggers[i]) { 48986 triggerIndex--; 48987 i--; 48988 } 48989 } 48990 48991 _isFunction(parsedStart) && (parsedStart = parsedStart(self)); 48992 parsedStart = _parseClamp(parsedStart, "start", self); 48993 start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._startClamp && "_startClamp") || (pin ? -0.001 : 0); 48994 _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self)); 48995 48996 if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) { 48997 if (~parsedEnd.indexOf(" ")) { 48998 parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd; 48999 } else { 49000 offset = _offsetToPx(parsedEnd.substr(2), size); 49001 parsedEnd = _isString(parsedStart) ? parsedStart : (containerAnimation ? gsap$1.utils.mapRange(0, containerAnimation.duration(), containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, start) : start) + offset; 49002 parsedEndTrigger = trigger; 49003 } 49004 } 49005 49006 parsedEnd = _parseClamp(parsedEnd, "end", self); 49007 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; 49008 offset = 0; 49009 i = triggerIndex; 49010 49011 while (i--) { 49012 curTrigger = _triggers[i]; 49013 curPin = curTrigger.pin; 49014 49015 if (curPin && curTrigger.start - curTrigger._pinPush <= start && !containerAnimation && curTrigger.end > 0) { 49016 cs = curTrigger.end - (self._startClamp ? Math.max(0, curTrigger.start) : curTrigger.start); 49017 49018 if ((curPin === trigger && curTrigger.start - curTrigger._pinPush < start || curPin === pinnedContainer) && isNaN(parsedStart)) { 49019 offset += cs * (1 - curTrigger.progress); 49020 } 49021 49022 curPin === pin && (otherPinOffset += cs); 49023 } 49024 } 49025 49026 start += offset; 49027 end += offset; 49028 self._startClamp && (self._startClamp += offset); 49029 49030 if (self._endClamp && !_refreshingAll) { 49031 self._endClamp = end || -0.001; 49032 end = Math.min(end, _maxScroll(scroller, direction)); 49033 } 49034 49035 change = end - start || (start -= 0.01) && 0.001; 49036 49037 if (isFirstRefresh) { 49038 prevProgress = gsap$1.utils.clamp(0, 1, gsap$1.utils.normalize(start, end, prevScroll)); 49039 } 49040 49041 self._pinPush = otherPinOffset; 49042 49043 if (markerStart && offset) { 49044 cs = {}; 49045 cs[direction.a] = "+=" + offset; 49046 pinnedContainer && (cs[direction.p] = "-=" + scrollFunc()); 49047 gsap$1.set([markerStart, markerEnd], cs); 49048 } 49049 49050 if (pin && !(_clampingMax && self.end >= _maxScroll(scroller, direction))) { 49051 cs = _getComputedStyle(pin); 49052 isVertical = direction === _vertical; 49053 scroll = scrollFunc(); 49054 pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset; 49055 49056 if (!max && end > 1) { 49057 forcedOverflow = (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller).style; 49058 forcedOverflow = { 49059 style: forcedOverflow, 49060 value: forcedOverflow["overflow" + direction.a.toUpperCase()] 49061 }; 49062 49063 if (isViewport && _getComputedStyle(_body$1)["overflow" + direction.a.toUpperCase()] !== "scroll") { 49064 forcedOverflow.style["overflow" + direction.a.toUpperCase()] = "scroll"; 49065 } 49066 } 49067 49068 _swapPinIn(pin, spacer, cs); 49069 49070 pinState = _getState(pin); 49071 bounds = _getBounds(pin, true); 49072 oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)(); 49073 49074 if (pinSpacing) { 49075 spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px]; 49076 spacerState.t = spacer; 49077 i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0; 49078 49079 if (i) { 49080 spacerState.push(direction.d, i + _px); 49081 spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px); 49082 } 49083 49084 _setState(spacerState); 49085 49086 if (pinnedContainer) {
vendor: 9,034 bytes, lines 49087-49329
49087 _triggers.forEach(function (t) { 49088 if (t.pin === pinnedContainer && t.vars.pinSpacing !== false) { 49089 t._subPinOffset = true; 49090 } 49091 }); 49092 } 49093 49094 useFixedPosition && scrollFunc(prevScroll); 49095 } else { 49096 i = _getSize(pin, direction); 49097 i && spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px); 49098 } 49099 49100 if (useFixedPosition) { 49101 override = { 49102 top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px, 49103 left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px, 49104 boxSizing: "border-box", 49105 position: "fixed" 49106 }; 49107 override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px; 49108 override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px; 49109 override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0"; 49110 override[_padding] = cs[_padding]; 49111 override[_padding + _Top] = cs[_padding + _Top]; 49112 override[_padding + _Right] = cs[_padding + _Right]; 49113 override[_padding + _Bottom] = cs[_padding + _Bottom]; 49114 override[_padding + _Left] = cs[_padding + _Left]; 49115 pinActiveState = _copyState(pinOriginalState, override, pinReparent); 49116 _refreshingAll && scrollFunc(0); 49117 } 49118 49119 if (animation) { 49120 initted = animation._initted; 49121 49122 _suppressOverwrites(1); 49123 49124 animation.render(animation.duration(), true, true); 49125 pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset; 49126 pinMoves = Math.abs(change - pinChange) > 1; 49127 useFixedPosition && pinMoves && pinActiveState.splice(pinActiveState.length - 2, 2); 49128 animation.render(0, true, true); 49129 initted || animation.invalidate(true); 49130 animation.parent || animation.totalTime(animation.totalTime()); 49131 49132 _suppressOverwrites(0); 49133 } else { 49134 pinChange = change; 49135 } 49136 49137 forcedOverflow && (forcedOverflow.value ? forcedOverflow.style["overflow" + direction.a.toUpperCase()] = forcedOverflow.value : forcedOverflow.style.removeProperty("overflow-" + direction.a)); 49138 } else if (trigger && scrollFunc() && !containerAnimation) { 49139 bounds = trigger.parentNode; 49140 49141 while (bounds && bounds !== _body$1) { 49142 if (bounds._pinOffset) { 49143 start -= bounds._pinOffset; 49144 end -= bounds._pinOffset; 49145 } 49146 49147 bounds = bounds.parentNode; 49148 } 49149 } 49150 49151 revertedPins && revertedPins.forEach(function (t) { 49152 return t.revert(false, true); 49153 }); 49154 self.start = start; 49155 self.end = end; 49156 scroll1 = scroll2 = _refreshingAll ? prevScroll : scrollFunc(); 49157 49158 if (!containerAnimation && !_refreshingAll) { 49159 scroll1 < prevScroll && scrollFunc(prevScroll); 49160 self.scroll.rec = 0; 49161 } 49162 49163 self.revert(false, true); 49164 lastRefresh = _getTime$1(); 49165 49166 if (snapDelayedCall) { 49167 lastSnap = -1; 49168 snapDelayedCall.restart(true); 49169 } 49170 49171 _refreshing = 0; 49172 animation && isToggle && (animation._initted || prevAnimProgress) && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress || 0, true).render(animation.time(), true, true); 49173 49174 if (isFirstRefresh || prevProgress !== self.progress || containerAnimation || invalidateOnRefresh) { 49175 animation && !isToggle && animation.totalProgress(containerAnimation && start < -0.001 && !prevProgress ? gsap$1.utils.normalize(start, end, 0) : prevProgress, true); 49176 self.progress = isFirstRefresh || (scroll1 - start) / change === prevProgress ? 0 : prevProgress; 49177 } 49178 49179 pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange)); 49180 scrubTween && scrubTween.invalidate(); 49181 49182 if (!isNaN(markerStartOffset)) { 49183 markerStartOffset -= gsap$1.getProperty(markerStartTrigger, direction.p); 49184 markerEndOffset -= gsap$1.getProperty(markerEndTrigger, direction.p); 49185 49186 _shiftMarker(markerStartTrigger, direction, markerStartOffset); 49187 49188 _shiftMarker(markerStart, direction, markerStartOffset - (pinOffset || 0)); 49189 49190 _shiftMarker(markerEndTrigger, direction, markerEndOffset); 49191 49192 _shiftMarker(markerEnd, direction, markerEndOffset - (pinOffset || 0)); 49193 } 49194 49195 isFirstRefresh && !_refreshingAll && self.update(); 49196 49197 if (onRefresh && !_refreshingAll && !executingOnRefresh) { 49198 executingOnRefresh = true; 49199 onRefresh(self); 49200 executingOnRefresh = false; 49201 } 49202 }; 49203 49204 self.getVelocity = function () { 49205 return (scrollFunc() - scroll2) / (_getTime$1() - _time2) * 1000 || 0; 49206 }; 49207 49208 self.endAnimation = function () { 49209 _endAnimation(self.callbackAnimation); 49210 49211 if (animation) { 49212 scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1); 49213 } 49214 }; 49215 49216 self.labelToScroll = function (label) { 49217 return animation && animation.labels && (start || self.refresh() || start) + animation.labels[label] / animation.duration() * change || 0; 49218 }; 49219 49220 self.getTrailing = function (name) { 49221 var i = _triggers.indexOf(self), 49222 a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1); 49223 49224 return (_isString(name) ? a.filter(function (t) { 49225 return t.vars.preventOverlaps === name; 49226 }) : a).filter(function (t) { 49227 return self.direction > 0 ? t.end <= start : t.start >= end; 49228 }); 49229 }; 49230 49231 self.update = function (reset, recordVelocity, forceFake) { 49232 if (containerAnimation && !forceFake && !reset) { 49233 return; 49234 } 49235 49236 var scroll = _refreshingAll === true ? prevScroll : self.scroll(), 49237 p = reset ? 0 : (scroll - start) / change, 49238 clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0, 49239 prevProgress = self.progress, 49240 isActive, 49241 wasActive, 49242 toggleState, 49243 action, 49244 stateChanged, 49245 toggled, 49246 isAtMax, 49247 isTakingAction; 49248 49249 if (recordVelocity) { 49250 scroll2 = scroll1; 49251 scroll1 = containerAnimation ? scrollFunc() : scroll; 49252 49253 if (snap) { 49254 snap2 = snap1; 49255 snap1 = animation && !isToggle ? animation.totalProgress() : clipped; 49256 } 49257 } 49258 49259 if (anticipatePin && pin && !_refreshing && !_startup$1 && _lastScrollTime) { 49260 if (!clipped && start < scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) { 49261 clipped = 0.0001; 49262 } else if (clipped === 1 && end > scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) { 49263 clipped = 0.9999; 49264 } 49265 } 49266 49267 if (clipped !== prevProgress && self.enabled) { 49268 isActive = self.isActive = !!clipped && clipped < 1; 49269 wasActive = !!prevProgress && prevProgress < 1; 49270 toggled = isActive !== wasActive; 49271 stateChanged = toggled || !!clipped !== !!prevProgress; 49272 self.direction = clipped > prevProgress ? 1 : -1; 49273 self.progress = clipped; 49274 49275 if (stateChanged && !_refreshing) { 49276 toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3; 49277 49278 if (isToggle) { 49279 action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState]; 49280 isTakingAction = animation && (action === "complete" || action === "reset" || action in animation); 49281 } 49282 } 49283 49284 preventOverlaps && (toggled || isTakingAction) && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) { 49285 return t.endAnimation(); 49286 })); 49287 49288 if (!isToggle) { 49289 if (scrubTween && !_refreshing && !_startup$1) { 49290 scrubTween._dp._time - scrubTween._start !== scrubTween._time && scrubTween.render(scrubTween._dp._time - scrubTween._start); 49291 49292 if (scrubTween.resetTo) { 49293 scrubTween.resetTo("totalProgress", clipped, animation._tTime / animation._tDur); 49294 } else { 49295 scrubTween.vars.totalProgress = clipped; 49296 scrubTween.invalidate().restart(); 49297 } 49298 } else if (animation) { 49299 animation.totalProgress(clipped, !!(_refreshing && (lastRefresh || reset))); 49300 } 49301 } 49302 49303 if (pin) { 49304 reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart); 49305 49306 if (!useFixedPosition) { 49307 pinSetter(_round(pinStart + pinChange * clipped)); 49308 } else if (stateChanged) { 49309 isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction); 49310 49311 if (pinReparent) { 49312 if (!reset && (isActive || isAtMax)) { 49313 var bounds = _getBounds(pin, true), 49314 _offset = scroll - start; 49315 49316 _reparent(pin, _body$1, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px); 49317 } else { 49318 _reparent(pin, spacer); 49319 } 49320 } 49321 49322 _setState(isActive || isAtMax ? pinActiveState : pinState); 49323 49324 pinMoves && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0)); 49325 } 49326 } 49327 49328 snap && !tweenTo.tween && !_refreshing && !_startup$1 && snapDelayedCall.restart(true); 49329 toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEac
vendor: 10,394 bytes, lines 49329-49696
49329h(function (el) { 49330 return el.classList[isActive || once ? "add" : "remove"](toggleClass.className); 49331 }); 49332 onUpdate && !isToggle && !reset && onUpdate(self); 49333 49334 if (stateChanged && !_refreshing) { 49335 if (isToggle) { 49336 if (isTakingAction) { 49337 if (action === "complete") { 49338 animation.pause().totalProgress(1); 49339 } else if (action === "reset") { 49340 animation.restart(true).pause(); 49341 } else if (action === "restart") { 49342 animation.restart(true); 49343 } else { 49344 animation[action](); 49345 } 49346 } 49347 49348 onUpdate && onUpdate(self); 49349 } 49350 49351 if (toggled || !_limitCallbacks) { 49352 onToggle && toggled && _callback(self, onToggle); 49353 callbacks[toggleState] && _callback(self, callbacks[toggleState]); 49354 once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0); 49355 49356 if (!toggled) { 49357 toggleState = clipped === 1 ? 1 : 3; 49358 callbacks[toggleState] && _callback(self, callbacks[toggleState]); 49359 } 49360 } 49361 49362 if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) { 49363 _endAnimation(self.callbackAnimation); 49364 49365 scrubTween ? scrubTween.progress(1) : _endAnimation(animation, action === "reverse" ? 1 : !clipped, 1); 49366 } 49367 } else if (isToggle && onUpdate && !_refreshing) { 49368 onUpdate(self); 49369 } 49370 } 49371 49372 if (markerEndSetter) { 49373 var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll; 49374 markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0)); 49375 markerEndSetter(n); 49376 } 49377 49378 caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0)); 49379 }; 49380 49381 self.enable = function (reset, refresh) { 49382 if (!self.enabled) { 49383 self.enabled = true; 49384 49385 _addListener$1(scroller, "resize", _onResize); 49386 49387 isViewport || _addListener$1(scroller, "scroll", _onScroll$1); 49388 onRefreshInit && _addListener$1(ScrollTrigger, "refreshInit", onRefreshInit); 49389 49390 if (reset !== false) { 49391 self.progress = prevProgress = 0; 49392 scroll1 = scroll2 = lastSnap = scrollFunc(); 49393 } 49394 49395 refresh !== false && self.refresh(); 49396 } 49397 }; 49398 49399 self.getTween = function (snap) { 49400 return snap && tweenTo ? tweenTo.tween : scrubTween; 49401 }; 49402 49403 self.setPositions = function (newStart, newEnd, keepClamp, pinOffset) { 49404 if (containerAnimation) { 49405 var st = containerAnimation.scrollTrigger, 49406 duration = containerAnimation.duration(), 49407 _change = st.end - st.start; 49408 49409 newStart = st.start + _change * newStart / duration; 49410 newEnd = st.start + _change * newEnd / duration; 49411 } 49412 49413 self.refresh(false, false, { 49414 start: _keepClamp(newStart, keepClamp && !!self._startClamp), 49415 end: _keepClamp(newEnd, keepClamp && !!self._endClamp) 49416 }, pinOffset); 49417 self.update(); 49418 }; 49419 49420 self.adjustPinSpacing = function (amount) { 49421 if (spacerState && amount) { 49422 var i = spacerState.indexOf(direction.d) + 1; 49423 spacerState[i] = parseFloat(spacerState[i]) + amount + _px; 49424 spacerState[1] = parseFloat(spacerState[1]) + amount + _px; 49425 49426 _setState(spacerState); 49427 } 49428 }; 49429 49430 self.disable = function (reset, allowAnimation) { 49431 if (self.enabled) { 49432 reset !== false && self.revert(true, true); 49433 self.enabled = self.isActive = false; 49434 allowAnimation || scrubTween && scrubTween.pause(); 49435 prevScroll = 0; 49436 pinCache && (pinCache.uncache = 1); 49437 onRefreshInit && _removeListener$1(ScrollTrigger, "refreshInit", onRefreshInit); 49438 49439 if (snapDelayedCall) { 49440 snapDelayedCall.pause(); 49441 tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0); 49442 } 49443 49444 if (!isViewport) { 49445 var i = _triggers.length; 49446 49447 while (i--) { 49448 if (_triggers[i].scroller === scroller && _triggers[i] !== self) { 49449 return; 49450 } 49451 } 49452 49453 _removeListener$1(scroller, "resize", _onResize); 49454 49455 isViewport || _removeListener$1(scroller, "scroll", _onScroll$1); 49456 } 49457 } 49458 }; 49459 49460 self.kill = function (revert, allowAnimation) { 49461 self.disable(revert, allowAnimation); 49462 scrubTween && !allowAnimation && scrubTween.kill(); 49463 id && delete _ids[id]; 49464 49465 var i = _triggers.indexOf(self); 49466 49467 i >= 0 && _triggers.splice(i, 1); 49468 i === _i && _direction > 0 && _i--; 49469 i = 0; 49470 49471 _triggers.forEach(function (t) { 49472 return t.scroller === self.scroller && (i = 1); 49473 }); 49474 49475 i || _refreshingAll || (self.scroll.rec = 0); 49476 49477 if (animation) { 49478 animation.scrollTrigger = null; 49479 revert && animation.revert({ 49480 kill: false 49481 }); 49482 allowAnimation || animation.kill(); 49483 } 49484 49485 markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) { 49486 return m.parentNode && m.parentNode.removeChild(m); 49487 }); 49488 _primary === self && (_primary = 0); 49489 49490 if (pin) { 49491 pinCache && (pinCache.uncache = 1); 49492 i = 0; 49493 49494 _triggers.forEach(function (t) { 49495 return t.pin === pin && i++; 49496 }); 49497 49498 i || (pinCache.spacer = 0); 49499 } 49500 49501 vars.onKill && vars.onKill(self); 49502 }; 49503 49504 _triggers.push(self); 49505 49506 self.enable(false, false); 49507 customRevertReturn && customRevertReturn(self); 49508 49509 if (animation && animation.add && !change) { 49510 var updateFunc = self.update; 49511 49512 self.update = function () { 49513 self.update = updateFunc; 49514 start || end || self.refresh(); 49515 }; 49516 49517 gsap$1.delayedCall(0.01, self.update); 49518 change = 0.01; 49519 start = end = 0; 49520 } else { 49521 self.refresh(); 49522 } 49523 49524 pin && _queueRefreshAll(); 49525 }; 49526 49527 ScrollTrigger.register = function register(core) { 49528 if (!_coreInitted$1) { 49529 gsap$1 = core || _getGSAP$1(); 49530 _windowExists() && window.document && ScrollTrigger.enable(); 49531 _coreInitted$1 = _enabled; 49532 } 49533 49534 return _coreInitted$1; 49535 }; 49536 49537 ScrollTrigger.defaults = function defaults(config) { 49538 if (config) { 49539 for (var p in config) { 49540 _defaults[p] = config[p]; 49541 } 49542 } 49543 49544 return _defaults; 49545 }; 49546 49547 ScrollTrigger.disable = function disable(reset, kill) { 49548 _enabled = 0; 49549 49550 _triggers.forEach(function (trigger) { 49551 return trigger[kill ? "kill" : "disable"](reset); 49552 }); 49553 49554 _removeListener$1(_win$1, "wheel", _onScroll$1); 49555 49556 _removeListener$1(_doc$1, "scroll", _onScroll$1); 49557 49558 clearInterval(_syncInterval); 49559 49560 _removeListener$1(_doc$1, "touchcancel", _passThrough); 49561 49562 _removeListener$1(_body$1, "touchstart", _passThrough); 49563 49564 _multiListener(_removeListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler); 49565 49566 _multiListener(_removeListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler); 49567 49568 _resizeDelay.kill(); 49569 49570 _iterateAutoRefresh(_removeListener$1); 49571 49572 for (var i = 0; i < _scrollers.length; i += 3) { 49573 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]); 49574 49575 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]); 49576 } 49577 }; 49578 49579 ScrollTrigger.enable = function enable() { 49580 _win$1 = window; 49581 _doc$1 = document; 49582 _docEl$1 = _doc$1.documentElement; 49583 _body$1 = _doc$1.body; 49584 49585 if (gsap$1) { 49586 _toArray = gsap$1.utils.toArray; 49587 _clamp$1 = gsap$1.utils.clamp; 49588 _context$1 = gsap$1.core.context || _passThrough; 49589 _suppressOverwrites = gsap$1.core.suppressOverwrites || _passThrough; 49590 _scrollRestoration = _win$1.history.scrollRestoration || "auto"; 49591 _lastScroll = _win$1.pageYOffset; 49592 gsap$1.core.globals("ScrollTrigger", ScrollTrigger); 49593 49594 if (_body$1) { 49595 _enabled = 1; 49596 _div100vh = document.createElement("div"); 49597 _div100vh.style.height = "100vh"; 49598 _div100vh.style.position = "absolute"; 49599 49600 _refresh100vh(); 49601 49602 _rafBugFix(); 49603 49604 Observer.register(gsap$1); 49605 ScrollTrigger.isTouch = Observer.isTouch; 49606 _fixIOSBug = Observer.isTouch && /(iPad|iPhone|iPod|Mac)/g.test(navigator.userAgent); 49607 _ignoreMobileResize = Observer.isTouch === 1; 49608 49609 _addListener$1(_win$1, "wheel", _onScroll$1); 49610 49611 _root$1 = [_win$1, _doc$1, _docEl$1, _body$1]; 49612 49613 if (gsap$1.matchMedia) { 49614 ScrollTrigger.matchMedia = function (vars) { 49615 var mm = gsap$1.matchMedia(), 49616 p; 49617 49618 for (p in vars) { 49619 mm.add(p, vars[p]); 49620 } 49621 49622 return mm; 49623 }; 49624 49625 gsap$1.addEventListener("matchMediaInit", function () { 49626 return _revertAll(); 49627 }); 49628 gsap$1.addEventListener("matchMediaRevert", function () { 49629 return _revertRecorded(); 49630 }); 49631 gsap$1.addEventListener("matchMedia", function () { 49632 _refreshAll(0, 1); 49633 49634 _dispatch("matchMedia"); 49635 }); 49636 gsap$1.matchMedia("(orientation: portrait)", function () { 49637 _setBaseDimensions(); 49638 49639 return _setBaseDimensions; 49640 }); 49641 } else { 49642 console.warn("Requires GSAP 3.11.0 or later"); 49643 } 49644 49645 _setBaseDimensions(); 49646 49647 _addListener$1(_doc$1, "scroll", _onScroll$1); 49648 49649 var bodyStyle = _body$1.style, 49650 border = bodyStyle.borderTopStyle, 49651 AnimationProto = gsap$1.core.Animation.prototype, 49652 bounds, 49653 i; 49654 AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", { 49655 value: function value() { 49656 return this.time(-0.01, true); 49657 } 49658 }); 49659 bodyStyle.borderTopStyle = "solid"; 49660 bounds = _getBounds(_body$1); 49661 _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0; 49662 _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0; 49663 border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style"); 49664 _syncInterval = setInterval(_sync, 250); 49665 gsap$1.delayedCall(0.5, function () { 49666 return _startup$1 = 0; 49667 }); 49668 49669 _addListener$1(_doc$1, "touchcancel", _passThrough); 49670 49671 _addListener$1(_body$1, "touchstart", _passThrough); 49672 49673 _multiListener(_addListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler); 49674 49675 _multiListener(_addListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler); 49676 49677 _transformProp = gsap$1.utils.checkPrefix("transform"); 49678 49679 _stateProps.push(_transformProp); 49680 49681 _coreInitted$1 = _getTime$1(); 49682 _resizeDelay = gsap$1.delayedCall(0.2, _refreshAll).pause(); 49683 _autoRefresh = [_doc$1, "visibilitychange", function () { 49684 var w = _win$1.innerWidth, 49685 h = _win$1.innerHeight; 49686 49687 if (_doc$1.hidden) { 49688 _prevWidth = w; 49689 _prevHeight = h; 49690 } else if (_prevWidth !== w || _prevHeight !== h) { 49691 _onResize(); 49692 } 49693 }, _doc$1, "DOMContentLoaded", _refreshAll, _win$1, "load", _refreshAll, _win$1, "resize", _onResize]; 49694 49695 _iterateAutoRefresh(_addListener$1); 49696
vendor: 4,962 bytes, lines 49697-49842
49697 _triggers.forEach(function (trigger) { 49698 return trigger.enable(0, 1); 49699 }); 49700 49701 for (i = 0; i < _scrollers.length; i += 3) { 49702 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]); 49703 49704 _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]); 49705 } 49706 } 49707 } 49708 }; 49709 49710 ScrollTrigger.config = function config(vars) { 49711 "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks); 49712 var ms = vars.syncInterval; 49713 ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms); 49714 "ignoreMobileResize" in vars && (_ignoreMobileResize = ScrollTrigger.isTouch === 1 && vars.ignoreMobileResize); 49715 49716 if ("autoRefreshEvents" in vars) { 49717 _iterateAutoRefresh(_removeListener$1) || _iterateAutoRefresh(_addListener$1, vars.autoRefreshEvents || "none"); 49718 _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1; 49719 } 49720 }; 49721 49722 ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) { 49723 var t = _getTarget(target), 49724 i = _scrollers.indexOf(t), 49725 isViewport = _isViewport$1(t); 49726 49727 if (~i) { 49728 _scrollers.splice(i, isViewport ? 6 : 2); 49729 } 49730 49731 if (vars) { 49732 isViewport ? _proxies.unshift(_win$1, vars, _body$1, vars, _docEl$1, vars) : _proxies.unshift(t, vars); 49733 } 49734 }; 49735 49736 ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) { 49737 _triggers.forEach(function (t) { 49738 return t._ctx && t._ctx.query === query && t._ctx.kill(true, true); 49739 }); 49740 }; 49741 49742 ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) { 49743 var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(), 49744 offset = bounds[horizontal ? _width : _height] * ratio || 0; 49745 return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win$1.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win$1.innerHeight; 49746 }; 49747 49748 ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) { 49749 _isString(element) && (element = _getTarget(element)); 49750 var bounds = element.getBoundingClientRect(), 49751 size = bounds[horizontal ? _width : _height], 49752 offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0; 49753 return horizontal ? (bounds.left + offset) / _win$1.innerWidth : (bounds.top + offset) / _win$1.innerHeight; 49754 }; 49755 49756 ScrollTrigger.killAll = function killAll(allowListeners) { 49757 _triggers.slice(0).forEach(function (t) { 49758 return t.vars.id !== "ScrollSmoother" && t.kill(); 49759 }); 49760 49761 if (allowListeners !== true) { 49762 var listeners = _listeners.killAll || []; 49763 _listeners = {}; 49764 listeners.forEach(function (f) { 49765 return f(); 49766 }); 49767 } 49768 }; 49769 49770 return ScrollTrigger; 49771 }(); 49772 ScrollTrigger$1.version = "3.12.5"; 49773 49774 ScrollTrigger$1.saveStyles = function (targets) { 49775 return targets ? _toArray(targets).forEach(function (target) { 49776 if (target && target.style) { 49777 var i = _savedStyles.indexOf(target); 49778 49779 i >= 0 && _savedStyles.splice(i, 5); 49780 49781 _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap$1.core.getCache(target), _context$1()); 49782 } 49783 }) : _savedStyles; 49784 }; 49785 49786 ScrollTrigger$1.revert = function (soft, media) { 49787 return _revertAll(!soft, media); 49788 }; 49789 49790 ScrollTrigger$1.create = function (vars, animation) { 49791 return new ScrollTrigger$1(vars, animation); 49792 }; 49793 49794 ScrollTrigger$1.refresh = function (safe) { 49795 return safe ? _onResize() : (_coreInitted$1 || ScrollTrigger$1.register()) && _refreshAll(true); 49796 }; 49797 49798 ScrollTrigger$1.update = function (force) { 49799 return ++_scrollers.cache && _updateAll(force === true ? 2 : 0); 49800 }; 49801 49802 ScrollTrigger$1.clearScrollMemory = _clearScrollMemory; 49803 49804 ScrollTrigger$1.maxScroll = function (element, horizontal) { 49805 return _maxScroll(element, horizontal ? _horizontal : _vertical); 49806 }; 49807 49808 ScrollTrigger$1.getScrollFunc = function (element, horizontal) { 49809 return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical); 49810 }; 49811 49812 ScrollTrigger$1.getById = function (id) { 49813 return _ids[id]; 49814 }; 49815 49816 ScrollTrigger$1.getAll = function () { 49817 return _triggers.filter(function (t) { 49818 return t.vars.id !== "ScrollSmoother"; 49819 }); 49820 }; 49821 49822 ScrollTrigger$1.isScrolling = function () { 49823 return !!_lastScrollTime; 49824 }; 49825 49826 ScrollTrigger$1.snapDirectional = _snapDirectional; 49827 49828 ScrollTrigger$1.addEventListener = function (type, callback) { 49829 var a = _listeners[type] || (_listeners[type] = []); 49830 ~a.indexOf(callback) || a.push(callback); 49831 }; 49832 49833 ScrollTrigger$1.removeEventListener = function (type, callback) { 49834 var a = _listeners[type], 49835 i = a && a.indexOf(callback); 49836 i >= 0 && a.splice(i, 1); 49837 }; 49838 49839 ScrollTrigger$1.batch = function (targets, vars) { 49840 var result = [], 49841 varsCopy = {}, 49842 interval = vars.interval || 0.016,
vendor: 4,448 bytes, lines 49843-49977
49843 batchMax = vars.batchMax || 1e9, 49844 proxyCallback = function proxyCallback(type, callback) { 49845 var elements = [], 49846 triggers = [], 49847 delay = gsap$1.delayedCall(interval, function () { 49848 callback(elements, triggers); 49849 elements = []; 49850 triggers = []; 49851 }).pause(); 49852 return function (self) { 49853 elements.length || delay.restart(true); 49854 elements.push(self.trigger); 49855 triggers.push(self); 49856 batchMax <= elements.length && delay.progress(1); 49857 }; 49858 }, 49859 p; 49860 49861 for (p in vars) { 49862 varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p]; 49863 } 49864 49865 if (_isFunction(batchMax)) { 49866 batchMax = batchMax(); 49867 49868 _addListener$1(ScrollTrigger$1, "refresh", function () { 49869 return batchMax = vars.batchMax(); 49870 }); 49871 } 49872 49873 _toArray(targets).forEach(function (target) { 49874 var config = {}; 49875 49876 for (p in varsCopy) { 49877 config[p] = varsCopy[p]; 49878 } 49879 49880 config.trigger = target; 49881 result.push(ScrollTrigger$1.create(config)); 49882 }); 49883 49884 return result; 49885 }; 49886 49887 var _clampScrollAndGetDurationMultiplier = function _clampScrollAndGetDurationMultiplier(scrollFunc, current, end, max) { 49888 current > max ? scrollFunc(max) : current < 0 && scrollFunc(0); 49889 return end > max ? (max - current) / (end - current) : end < 0 ? current / (current - end) : 1; 49890 }, 49891 _allowNativePanning = function _allowNativePanning(target, direction) { 49892 if (direction === true) { 49893 target.style.removeProperty("touch-action"); 49894 } else { 49895 target.style.touchAction = direction === true ? "auto" : direction ? "pan-" + direction + (Observer.isTouch ? " pinch-zoom" : "") : "none"; 49896 } 49897 49898 target === _docEl$1 && _allowNativePanning(_body$1, direction); 49899 }, 49900 _overflow = { 49901 auto: 1, 49902 scroll: 1 49903 }, 49904 _nestedScroll = function _nestedScroll(_ref5) { 49905 var event = _ref5.event, 49906 target = _ref5.target, 49907 axis = _ref5.axis; 49908 49909 var node = (event.changedTouches ? event.changedTouches[0] : event).target, 49910 cache = node._gsap || gsap$1.core.getCache(node), 49911 time = _getTime$1(), 49912 cs; 49913 49914 if (!cache._isScrollT || time - cache._isScrollT > 2000) { 49915 while (node && node !== _body$1 && (node.scrollHeight <= node.clientHeight && node.scrollWidth <= node.clientWidth || !(_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]))) { 49916 node = node.parentNode; 49917 } 49918 49919 cache._isScroll = node && node !== target && !_isViewport$1(node) && (_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]); 49920 cache._isScrollT = time; 49921 } 49922 49923 if (cache._isScroll || axis === "x") { 49924 event.stopPropagation(); 49925 event._gsapAllow = true; 49926 } 49927 }, 49928 _inputObserver = function _inputObserver(target, type, inputs, nested) { 49929 return Observer.create({ 49930 target: target, 49931 capture: true, 49932 debounce: false, 49933 lockAxis: true, 49934 type: type, 49935 onWheel: nested = nested && _nestedScroll, 49936 onPress: nested, 49937 onDrag: nested, 49938 onScroll: nested, 49939 onEnable: function onEnable() { 49940 return inputs && _addListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, false, true); 49941 }, 49942 onDisable: function onDisable() { 49943 return _removeListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, true); 49944 } 49945 }); 49946 }, 49947 _inputExp = /(input|label|select|textarea)/i, 49948 _inputIsFocused, 49949 _captureInputs = function _captureInputs(e) { 49950 var isInput = _inputExp.test(e.target.tagName); 49951 49952 if (isInput || _inputIsFocused) { 49953 e._gsapAllow = true; 49954 _inputIsFocused = isInput; 49955 } 49956 }, 49957 _getScrollNormalizer = function _getScrollNormalizer(vars) { 49958 _isObject(vars) || (vars = {}); 49959 vars.preventDefault = vars.isNormalizer = vars.allowClicks = true; 49960 vars.type || (vars.type = "wheel,touch"); 49961 vars.debounce = !!vars.debounce; 49962 vars.id = vars.id || "normalizer"; 49963 49964 var _vars2 = vars, 49965 normalizeScrollX = _vars2.normalizeScrollX, 49966 momentum = _vars2.momentum, 49967 allowNestedScroll = _vars2.allowNestedScroll, 49968 onRelease = _vars2.onRelease, 49969 self, 49970 maxY, 49971 target = _getTarget(vars.target) || _docEl$1, 49972 smoother = gsap$1.core.globals().ScrollSmoother, 49973 smootherInstance = smoother && smoother.get(), 49974 content = _fixIOSBug && (vars.content && _getTarget(vars.content) || smootherInstance && vars.content !== false && !smootherInstance.smooth() && smootherInstance.content()), 49975 scrollFuncY = _getScrollFunc(target, _vertical), 49976 scrollFuncX = _getScrollFunc(target, _horizontal), 49977 scale = 1,
vendor: 4,132 bytes, lines 49978-50099
49978 initialScale = (Observer.isTouch && _win$1.visualViewport ? _win$1.visualViewport.scale * _win$1.visualViewport.width : _win$1.outerWidth) / _win$1.innerWidth, 49979 wheelRefresh = 0, 49980 resolveMomentumDuration = _isFunction(momentum) ? function () { 49981 return momentum(self); 49982 } : function () { 49983 return momentum || 2.8; 49984 }, 49985 lastRefreshID, 49986 skipTouchMove, 49987 inputObserver = _inputObserver(target, vars.type, true, allowNestedScroll), 49988 resumeTouchMove = function resumeTouchMove() { 49989 return skipTouchMove = false; 49990 }, 49991 scrollClampX = _passThrough, 49992 scrollClampY = _passThrough, 49993 updateClamps = function updateClamps() { 49994 maxY = _maxScroll(target, _vertical); 49995 scrollClampY = _clamp$1(_fixIOSBug ? 1 : 0, maxY); 49996 normalizeScrollX && (scrollClampX = _clamp$1(0, _maxScroll(target, _horizontal))); 49997 lastRefreshID = _refreshID; 49998 }, 49999 removeContentOffset = function removeContentOffset() { 50000 content._gsap.y = _round(parseFloat(content._gsap.y) + scrollFuncY.offset) + "px"; 50001 content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + parseFloat(content._gsap.y) + ", 0, 1)"; 50002 scrollFuncY.offset = scrollFuncY.cacheID = 0; 50003 }, 50004 ignoreDrag = function ignoreDrag() { 50005 if (skipTouchMove) { 50006 requestAnimationFrame(resumeTouchMove); 50007 50008 var offset = _round(self.deltaY / 2), 50009 scroll = scrollClampY(scrollFuncY.v - offset); 50010 50011 if (content && scroll !== scrollFuncY.v + scrollFuncY.offset) { 50012 scrollFuncY.offset = scroll - scrollFuncY.v; 50013 50014 var y = _round((parseFloat(content && content._gsap.y) || 0) - scrollFuncY.offset); 50015 50016 content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + y + ", 0, 1)"; 50017 content._gsap.y = y + "px"; 50018 scrollFuncY.cacheID = _scrollers.cache; 50019 50020 _updateAll(); 50021 } 50022 50023 return true; 50024 } 50025 50026 scrollFuncY.offset && removeContentOffset(); 50027 skipTouchMove = true; 50028 }, 50029 tween, 50030 startScrollX, 50031 startScrollY, 50032 onStopDelayedCall, 50033 onResize = function onResize() { 50034 updateClamps(); 50035 50036 if (tween.isActive() && tween.vars.scrollY > maxY) { 50037 scrollFuncY() > maxY ? tween.progress(1) && scrollFuncY(maxY) : tween.resetTo("scrollY", maxY); 50038 } 50039 }; 50040 50041 content && gsap$1.set(content, { 50042 y: "+=0" 50043 }); 50044 50045 vars.ignoreCheck = function (e) { 50046 return _fixIOSBug && e.type === "touchmove" && ignoreDrag() || scale > 1.05 && e.type !== "touchstart" || self.isGesturing || e.touches && e.touches.length > 1; 50047 }; 50048 50049 vars.onPress = function () { 50050 skipTouchMove = false; 50051 var prevScale = scale; 50052 scale = _round((_win$1.visualViewport && _win$1.visualViewport.scale || 1) / initialScale); 50053 tween.pause(); 50054 prevScale !== scale && _allowNativePanning(target, scale > 1.01 ? true : normalizeScrollX ? false : "x"); 50055 startScrollX = scrollFuncX(); 50056 startScrollY = scrollFuncY(); 50057 updateClamps(); 50058 lastRefreshID = _refreshID; 50059 }; 50060 50061 vars.onRelease = vars.onGestureStart = function (self, wasDragging) { 50062 scrollFuncY.offset && removeContentOffset(); 50063 50064 if (!wasDragging) { 50065 onStopDelayedCall.restart(true); 50066 } else { 50067 _scrollers.cache++; 50068 var dur = resolveMomentumDuration(), 50069 currentScroll, 50070 endScroll; 50071 50072 if (normalizeScrollX) { 50073 currentScroll = scrollFuncX(); 50074 endScroll = currentScroll + dur * 0.05 * -self.velocityX / 0.227; 50075 dur *= _clampScrollAndGetDurationMultiplier(scrollFuncX, currentScroll, endScroll, _maxScroll(target, _horizontal)); 50076 tween.vars.scrollX = scrollClampX(endScroll); 50077 } 50078 50079 currentScroll = scrollFuncY(); 50080 endScroll = currentScroll + dur * 0.05 * -self.velocityY / 0.227; 50081 dur *= _clampScrollAndGetDurationMultiplier(scrollFuncY, currentScroll, endScroll, _maxScroll(target, _vertical)); 50082 tween.vars.scrollY = scrollClampY(endScroll); 50083 tween.invalidate().duration(dur).play(0.01); 50084 50085 if (_fixIOSBug && tween.vars.scrollY >= maxY || currentScroll >= maxY - 1) { 50086 gsap$1.to({}, { 50087 onUpdate: onResize, 50088 duration: dur 50089 }); 50090 } 50091 } 50092 50093 onRelease && onRelease(self); 50094 }; 50095 50096 vars.onWheel = function () { 50097 tween._ts && tween.pause(); 50098 50099 if (_getTime$1() - wheelRefresh > 1000) {
vendor: 28,617 bytes, lines 50100-51154
50100 lastRefreshID = 0; 50101 wheelRefresh = _getTime$1(); 50102 } 50103 }; 50104 50105 vars.onChange = function (self, dx, dy, xArray, yArray) { 50106 _refreshID !== lastRefreshID && updateClamps(); 50107 dx && normalizeScrollX && scrollFuncX(scrollClampX(xArray[2] === dx ? startScrollX + (self.startX - self.x) : scrollFuncX() + dx - xArray[1])); 50108 50109 if (dy) { 50110 scrollFuncY.offset && removeContentOffset(); 50111 var isTouch = yArray[2] === dy, 50112 y = isTouch ? startScrollY + self.startY - self.y : scrollFuncY() + dy - yArray[1], 50113 yClamped = scrollClampY(y); 50114 isTouch && y !== yClamped && (startScrollY += yClamped - y); 50115 scrollFuncY(yClamped); 50116 } 50117 50118 (dy || dx) && _updateAll(); 50119 }; 50120 50121 vars.onEnable = function () { 50122 _allowNativePanning(target, normalizeScrollX ? false : "x"); 50123 50124 ScrollTrigger$1.addEventListener("refresh", onResize); 50125 50126 _addListener$1(_win$1, "resize", onResize); 50127 50128 if (scrollFuncY.smooth) { 50129 scrollFuncY.target.style.scrollBehavior = "auto"; 50130 scrollFuncY.smooth = scrollFuncX.smooth = false; 50131 } 50132 50133 inputObserver.enable(); 50134 }; 50135 50136 vars.onDisable = function () { 50137 _allowNativePanning(target, true); 50138 50139 _removeListener$1(_win$1, "resize", onResize); 50140 50141 ScrollTrigger$1.removeEventListener("refresh", onResize); 50142 inputObserver.kill(); 50143 }; 50144 50145 vars.lockAxis = vars.lockAxis !== false; 50146 self = new Observer(vars); 50147 self.iOS = _fixIOSBug; 50148 _fixIOSBug && !scrollFuncY() && scrollFuncY(1); 50149 _fixIOSBug && gsap$1.ticker.add(_passThrough); 50150 onStopDelayedCall = self._dc; 50151 tween = gsap$1.to(self, { 50152 ease: "power4", 50153 paused: true, 50154 inherit: false, 50155 scrollX: normalizeScrollX ? "+=0.1" : "+=0", 50156 scrollY: "+=0.1", 50157 modifiers: { 50158 scrollY: _interruptionTracker(scrollFuncY, scrollFuncY(), function () { 50159 return tween.pause(); 50160 }) 50161 }, 50162 onUpdate: _updateAll, 50163 onComplete: onStopDelayedCall.vars.onComplete 50164 }); 50165 return self; 50166 }; 50167 50168 ScrollTrigger$1.sort = function (func) { 50169 return _triggers.sort(func || function (a, b) { 50170 return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6); 50171 }); 50172 }; 50173 50174 ScrollTrigger$1.observe = function (vars) { 50175 return new Observer(vars); 50176 }; 50177 50178 ScrollTrigger$1.normalizeScroll = function (vars) { 50179 if (typeof vars === "undefined") { 50180 return _normalizer$1; 50181 } 50182 50183 if (vars === true && _normalizer$1) { 50184 return _normalizer$1.enable(); 50185 } 50186 50187 if (vars === false) { 50188 _normalizer$1 && _normalizer$1.kill(); 50189 _normalizer$1 = vars; 50190 return; 50191 } 50192 50193 var normalizer = vars instanceof Observer ? vars : _getScrollNormalizer(vars); 50194 _normalizer$1 && _normalizer$1.target === normalizer.target && _normalizer$1.kill(); 50195 _isViewport$1(normalizer.target) && (_normalizer$1 = normalizer); 50196 return normalizer; 50197 }; 50198 50199 ScrollTrigger$1.core = { 50200 _getVelocityProp: _getVelocityProp, 50201 _inputObserver: _inputObserver, 50202 _scrollers: _scrollers, 50203 _proxies: _proxies, 50204 bridge: { 50205 ss: function ss() { 50206 _lastScrollTime || _dispatch("scrollStart"); 50207 _lastScrollTime = _getTime$1(); 50208 }, 50209 ref: function ref() { 50210 return _refreshing; 50211 } 50212 } 50213 }; 50214 _getGSAP$1() && gsap$1.registerPlugin(ScrollTrigger$1); 50215 50216 exports.ScrollTrigger = ScrollTrigger$1; 50217 exports.default = ScrollTrigger$1; 50218 50219 if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;} 50220 50221 }))); 50222 50223/*! 50224 * CustomEase 3.12.7 50225 * https://gsap.com 50226 * 50227 * @license Copyright 2025, GreenSock. All rights reserved. 50228 * Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership. 50229 * @author: Jack Doyle, [email protected] 50230 */ 50231 50232 (function (global, factory) { 50233 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 50234 typeof define === 'function' && define.amd ? define(['exports'], factory) : 50235 (global = global || self, factory(global.window = global.window || {})); 50236}(this, (function (exports) { 'use strict'; 50237 50238 var _svgPathExp = /[achlmqstvz]|(-?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig, 50239 _scientific = /[\+\-]?\d*\.?\d+e[\+\-]?\d+/ig, 50240 _DEG2RAD = Math.PI / 180, 50241 _sin = Math.sin, 50242 _cos = Math.cos, 50243 _abs = Math.abs, 50244 _sqrt = Math.sqrt, 50245 _isNumber = function _isNumber(value) { 50246 return typeof value === "number"; 50247 }, 50248 _roundingNum = 1e5, 50249 _round = function _round(value) { 50250 return Math.round(value * _roundingNum) / _roundingNum || 0; 50251 }; 50252 function transformRawPath(rawPath, a, b, c, d, tx, ty) { 50253 var j = rawPath.length, 50254 segment, 50255 l, 50256 i, 50257 x, 50258 y; 50259 50260 while (--j > -1) { 50261 segment = rawPath[j]; 50262 l = segment.length; 50263 50264 for (i = 0; i < l; i += 2) { 50265 x = segment[i]; 50266 y = segment[i + 1]; 50267 segment[i] = x * a + y * c + tx; 50268 segment[i + 1] = x * b + y * d + ty; 50269 } 50270 } 50271 50272 rawPath._dirty = 1; 50273 return rawPath; 50274 } 50275 50276 function arcToSegment(lastX, lastY, rx, ry, angle, largeArcFlag, sweepFlag, x, y) { 50277 if (lastX === x && lastY === y) { 50278 return; 50279 } 50280 50281 rx = _abs(rx); 50282 ry = _abs(ry); 50283 50284 var angleRad = angle % 360 * _DEG2RAD, 50285 cosAngle = _cos(angleRad), 50286 sinAngle = _sin(angleRad), 50287 PI = Math.PI, 50288 TWOPI = PI * 2, 50289 dx2 = (lastX - x) / 2, 50290 dy2 = (lastY - y) / 2, 50291 x1 = cosAngle * dx2 + sinAngle * dy2, 50292 y1 = -sinAngle * dx2 + cosAngle * dy2, 50293 x1_sq = x1 * x1, 50294 y1_sq = y1 * y1, 50295 radiiCheck = x1_sq / (rx * rx) + y1_sq / (ry * ry); 50296 50297 if (radiiCheck > 1) { 50298 rx = _sqrt(radiiCheck) * rx; 50299 ry = _sqrt(radiiCheck) * ry; 50300 } 50301 50302 var rx_sq = rx * rx, 50303 ry_sq = ry * ry, 50304 sq = (rx_sq * ry_sq - rx_sq * y1_sq - ry_sq * x1_sq) / (rx_sq * y1_sq + ry_sq * x1_sq); 50305 50306 if (sq < 0) { 50307 sq = 0; 50308 } 50309 50310 var coef = (largeArcFlag === sweepFlag ? -1 : 1) * _sqrt(sq), 50311 cx1 = coef * (rx * y1 / ry), 50312 cy1 = coef * -(ry * x1 / rx), 50313 sx2 = (lastX + x) / 2, 50314 sy2 = (lastY + y) / 2, 50315 cx = sx2 + (cosAngle * cx1 - sinAngle * cy1), 50316 cy = sy2 + (sinAngle * cx1 + cosAngle * cy1), 50317 ux = (x1 - cx1) / rx, 50318 uy = (y1 - cy1) / ry, 50319 vx = (-x1 - cx1) / rx, 50320 vy = (-y1 - cy1) / ry, 50321 temp = ux * ux + uy * uy, 50322 angleStart = (uy < 0 ? -1 : 1) * Math.acos(ux / _sqrt(temp)), 50323 angleExtent = (ux * vy - uy * vx < 0 ? -1 : 1) * Math.acos((ux * vx + uy * vy) / _sqrt(temp * (vx * vx + vy * vy))); 50324 50325 isNaN(angleExtent) && (angleExtent = PI); 50326 50327 if (!sweepFlag && angleExtent > 0) { 50328 angleExtent -= TWOPI; 50329 } else if (sweepFlag && angleExtent < 0) { 50330 angleExtent += TWOPI; 50331 } 50332 50333 angleStart %= TWOPI; 50334 angleExtent %= TWOPI; 50335 50336 var segments = Math.ceil(_abs(angleExtent) / (TWOPI / 4)), 50337 rawPath = [], 50338 angleIncrement = angleExtent / segments, 50339 controlLength = 4 / 3 * _sin(angleIncrement / 2) / (1 + _cos(angleIncrement / 2)), 50340 ma = cosAngle * rx, 50341 mb = sinAngle * rx, 50342 mc = sinAngle * -ry, 50343 md = cosAngle * ry, 50344 i; 50345 50346 for (i = 0; i < segments; i++) { 50347 angle = angleStart + i * angleIncrement; 50348 x1 = _cos(angle); 50349 y1 = _sin(angle); 50350 ux = _cos(angle += angleIncrement); 50351 uy = _sin(angle); 50352 rawPath.push(x1 - controlLength * y1, y1 + controlLength * x1, ux + controlLength * uy, uy - controlLength * ux, ux, uy); 50353 } 50354 50355 for (i = 0; i < rawPath.length; i += 2) { 50356 x1 = rawPath[i]; 50357 y1 = rawPath[i + 1]; 50358 rawPath[i] = x1 * ma + y1 * mc + cx; 50359 rawPath[i + 1] = x1 * mb + y1 * md + cy; 50360 } 50361 50362 rawPath[i - 2] = x; 50363 rawPath[i - 1] = y; 50364 return rawPath; 50365 } 50366 50367 function stringToRawPath(d) { 50368 var a = (d + "").replace(_scientific, function (m) { 50369 var n = +m; 50370 return n < 0.0001 && n > -0.0001 ? 0 : n; 50371 }).match(_svgPathExp) || [], 50372 path = [], 50373 relativeX = 0, 50374 relativeY = 0, 50375 twoThirds = 2 / 3, 50376 elements = a.length, 50377 points = 0, 50378 errorMessage = "ERROR: malformed path: " + d, 50379 i, 50380 j, 50381 x, 50382 y, 50383 command, 50384 isRelative, 50385 segment, 50386 startX, 50387 startY, 50388 difX, 50389 difY, 50390 beziers, 50391 prevCommand, 50392 flag1, 50393 flag2, 50394 line = function line(sx, sy, ex, ey) { 50395 difX = (ex - sx) / 3; 50396 difY = (ey - sy) / 3; 50397 segment.push(sx + difX, sy + difY, ex - difX, ey - difY, ex, ey); 50398 }; 50399 50400 if (!d || !isNaN(a[0]) || isNaN(a[1])) { 50401 console.log(errorMessage); 50402 return path; 50403 } 50404 50405 for (i = 0; i < elements; i++) { 50406 prevCommand = command; 50407 50408 if (isNaN(a[i])) { 50409 command = a[i].toUpperCase(); 50410 isRelative = command !== a[i]; 50411 } else { 50412 i--; 50413 } 50414 50415 x = +a[i + 1]; 50416 y = +a[i + 2]; 50417 50418 if (isRelative) { 50419 x += relativeX; 50420 y += relativeY; 50421 } 50422 50423 if (!i) { 50424 startX = x; 50425 startY = y; 50426 } 50427 50428 if (command === "M") { 50429 if (segment) { 50430 if (segment.length < 8) { 50431 path.length -= 1; 50432 } else { 50433 points += segment.length; 50434 } 50435 } 50436 50437 relativeX = startX = x; 50438 relativeY = startY = y; 50439 segment = [x, y]; 50440 path.push(segment); 50441 i += 2; 50442 command = "L"; 50443 } else if (command === "C") { 50444 if (!segment) { 50445 segment = [0, 0]; 50446 } 50447 50448 if (!isRelative) { 50449 relativeX = relativeY = 0; 50450 } 50451 50452 segment.push(x, y, relativeX + a[i + 3] * 1, relativeY + a[i + 4] * 1, relativeX += a[i + 5] * 1, relativeY += a[i + 6] * 1); 50453 i += 6; 50454 } else if (command === "S") { 50455 difX = relativeX; 50456 difY = relativeY; 50457 50458 if (prevCommand === "C" || prevCommand === "S") { 50459 difX += relativeX - segment[segment.length - 4]; 50460 difY += relativeY - segment[segment.length - 3]; 50461 } 50462 50463 if (!isRelative) { 50464 relativeX = relativeY = 0; 50465 } 50466 50467 segment.push(difX, difY, x, y, relativeX += a[i + 3] * 1, relativeY += a[i + 4] * 1); 50468 i += 4; 50469 } else if (command === "Q") { 50470 difX = relativeX + (x - relativeX) * twoThirds; 50471 difY = relativeY + (y - relativeY) * twoThirds; 50472 50473 if (!isRelative) { 50474 relativeX = relativeY = 0; 50475 } 50476 50477 relativeX += a[i + 3] * 1; 50478 relativeY += a[i + 4] * 1; 50479 segment.push(difX, difY, relativeX + (x - relativeX) * twoThirds, relativeY + (y - relativeY) * twoThirds, relativeX, relativeY); 50480 i += 4; 50481 } else if (command === "T") { 50482 difX = relativeX - segment[segment.length - 4]; 50483 difY = relativeY - segment[segment.length - 3]; 50484 segment.push(relativeX + difX, relativeY + difY, x + (relativeX + difX * 1.5 - x) * twoThirds, y + (relativeY + difY * 1.5 - y) * twoThirds, relativeX = x, relativeY = y); 50485 i += 2; 50486 } else if (command === "H") { 50487 line(relativeX, relativeY, relativeX = x, relativeY); 50488 i += 1; 50489 } else if (command === "V") { 50490 line(relativeX, relativeY, relativeX, relativeY = x + (isRelative ? relativeY - relativeX : 0)); 50491 i += 1; 50492 } else if (command === "L" || command === "Z") { 50493 if (command === "Z") { 50494 x = startX; 50495 y = startY; 50496 segment.closed = true; 50497 } 50498 50499 if (command === "L" || _abs(relativeX - x) > 0.5 || _abs(relativeY - y) > 0.5) { 50500 line(relativeX, relativeY, x, y); 50501 50502 if (command === "L") { 50503 i += 2; 50504 } 50505 } 50506 50507 relativeX = x; 50508 relativeY = y; 50509 } else if (command === "A") { 50510 flag1 = a[i + 4]; 50511 flag2 = a[i + 5]; 50512 difX = a[i + 6]; 50513 difY = a[i + 7]; 50514 j = 7; 50515 50516 if (flag1.length > 1) { 50517 if (flag1.length < 3) { 50518 difY = difX; 50519 difX = flag2; 50520 j--; 50521 } else { 50522 difY = flag2; 50523 difX = flag1.substr(2); 50524 j -= 2; 50525 } 50526 50527 flag2 = flag1.charAt(1); 50528 flag1 = flag1.charAt(0); 50529 } 50530 50531 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); 50532 i += j; 50533 50534 if (beziers) { 50535 for (j = 0; j < beziers.length; j++) { 50536 segment.push(beziers[j]); 50537 } 50538 } 50539 50540 relativeX = segment[segment.length - 2]; 50541 relativeY = segment[segment.length - 1]; 50542 } else { 50543 console.log(errorMessage); 50544 } 50545 } 50546 50547 i = segment.length; 50548 50549 if (i < 6) { 50550 path.pop(); 50551 i = 0; 50552 } else if (segment[0] === segment[i - 2] && segment[1] === segment[i - 1]) { 50553 segment.closed = true; 50554 } 50555 50556 path.totalPoints = points + i; 50557 return path; 50558 } 50559 function rawPathToString(rawPath) { 50560 if (_isNumber(rawPath[0])) { 50561 rawPath = [rawPath]; 50562 } 50563 50564 var result = "", 50565 l = rawPath.length, 50566 sl, 50567 s, 50568 i, 50569 segment; 50570 50571 for (s = 0; s < l; s++) { 50572 segment = rawPath[s]; 50573 result += "M" + _round(segment[0]) + "," + _round(segment[1]) + " C"; 50574 sl = segment.length; 50575 50576 for (i = 2; i < sl; i++) { 50577 result += _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i]) + " "; 50578 } 50579 50580 if (segment.closed) { 50581 result += "z"; 50582 } 50583 } 50584 50585 return result; 50586 } 50587 50588 /*! 50589 * CustomEase 3.12.7 50590 * https://gsap.com 50591 * 50592 * @license Copyright 2008-2025, GreenSock. All rights reserved. 50593 * Subject to the terms at https://gsap.com/standard-license or for 50594 * Club GSAP members, the agreement issued with that membership. 50595 * @author: Jack Doyle, [email protected] 50596 */ 50597 50598 var gsap, 50599 _coreInitted, 50600 _getGSAP = function _getGSAP() { 50601 return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap; 50602 }, 50603 _initCore = function _initCore() { 50604 gsap = _getGSAP(); 50605 50606 if (gsap) { 50607 gsap.registerEase("_CE", CustomEase.create); 50608 _coreInitted = 1; 50609 } else { 50610 console.warn("Please gsap.registerPlugin(CustomEase)"); 50611 } 50612 }, 50613 _bigNum = 1e20, 50614 _round$1 = function _round(value) { 50615 return ~~(value * 1000 + (value < 0 ? -.5 : .5)) / 1000; 50616 }, 50617 _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/gi, 50618 _needsParsingExp = /[cLlsSaAhHvVtTqQ]/g, 50619 _findMinimum = function _findMinimum(values) { 50620 var l = values.length, 50621 min = _bigNum, 50622 i; 50623 50624 for (i = 1; i < l; i += 6) { 50625 +values[i] < min && (min = +values[i]); 50626 } 50627 50628 return min; 50629 }, 50630 _normalize = function _normalize(values, height, originY) { 50631 if (!originY && originY !== 0) { 50632 originY = Math.max(+values[values.length - 1], +values[1]); 50633 } 50634 50635 var tx = +values[0] * -1, 50636 ty = -originY, 50637 l = values.length, 50638 sx = 1 / (+values[l - 2] + tx), 50639 sy = -height || (Math.abs(+values[l - 1] - +values[1]) < 0.01 * (+values[l - 2] - +values[0]) ? _findMinimum(values) + ty : +values[l - 1] + ty), 50640 i; 50641 50642 if (sy) { 50643 sy = 1 / sy; 50644 } else { 50645 sy = -sx; 50646 } 50647 50648 for (i = 0; i < l; i += 2) { 50649 values[i] = (+values[i] + tx) * sx; 50650 values[i + 1] = (+values[i + 1] + ty) * sy; 50651 } 50652 }, 50653 _bezierToPoints = function _bezierToPoints(x1, y1, x2, y2, x3, y3, x4, y4, threshold, points, index) { 50654 var x12 = (x1 + x2) / 2, 50655 y12 = (y1 + y2) / 2, 50656 x23 = (x2 + x3) / 2, 50657 y23 = (y2 + y3) / 2, 50658 x34 = (x3 + x4) / 2, 50659 y34 = (y3 + y4) / 2, 50660 x123 = (x12 + x23) / 2, 50661 y123 = (y12 + y23) / 2, 50662 x234 = (x23 + x34) / 2, 50663 y234 = (y23 + y34) / 2, 50664 x1234 = (x123 + x234) / 2, 50665 y1234 = (y123 + y234) / 2, 50666 dx = x4 - x1, 50667 dy = y4 - y1, 50668 d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx), 50669 d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx), 50670 length; 50671 50672 if (!points) { 50673 points = [{ 50674 x: x1, 50675 y: y1 50676 }, { 50677 x: x4, 50678 y: y4 50679 }]; 50680 index = 1; 50681 } 50682 50683 points.splice(index || points.length - 1, 0, { 50684 x: x1234, 50685 y: y1234 50686 }); 50687 50688 if ((d2 + d3) * (d2 + d3) > threshold * (dx * dx + dy * dy)) { 50689 length = points.length; 50690 50691 _bezierToPoints(x1, y1, x12, y12, x123, y123, x1234, y1234, threshold, points, index); 50692 50693 _bezierToPoints(x1234, y1234, x234, y234, x34, y34, x4, y4, threshold, points, index + 1 + (points.length - length)); 50694 } 50695 50696 return points; 50697 }; 50698 50699 var CustomEase = function () { 50700 function CustomEase(id, data, config) { 50701 _coreInitted || _initCore(); 50702 this.id = id; 50703 this.setData(data, config); 50704 } 50705 50706 var _proto = CustomEase.prototype; 50707 50708 _proto.setData = function setData(data, config) { 50709 config = config || {}; 50710 data = data || "0,0,1,1"; 50711 var values = data.match(_numExp), 50712 closest = 1, 50713 points = [], 50714 lookup = [], 50715 precision = config.precision || 1, 50716 fast = precision <= 1, 50717 l, 50718 a1, 50719 a2, 50720 i, 50721 inc, 50722 j, 50723 point, 50724 prevPoint, 50725 p; 50726 this.data = data; 50727 50728 if (_needsParsingExp.test(data) || ~data.indexOf("M") && data.indexOf("C") < 0) { 50729 values = stringToRawPath(data)[0]; 50730 } 50731 50732 l = values.length; 50733 50734 if (l === 4) { 50735 values.unshift(0, 0); 50736 values.push(1, 1); 50737 l = 8; 50738 } else if ((l - 2) % 6) { 50739 throw "Invalid CustomEase"; 50740 } 50741 50742 if (+values[0] !== 0 || +values[l - 2] !== 1) { 50743 _normalize(values, config.height, config.originY); 50744 } 50745 50746 this.segment = values; 50747 50748 for (i = 2; i < l; i += 6) { 50749 a1 = { 50750 x: +values[i - 2], 50751 y: +values[i - 1] 50752 }; 50753 a2 = { 50754 x: +values[i + 4], 50755 y: +values[i + 5] 50756 }; 50757 points.push(a1, a2); 50758 50759 _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); 50760 } 50761 50762 l = points.length; 50763 50764 for (i = 0; i < l; i++) { 50765 point = points[i]; 50766 prevPoint = points[i - 1] || point; 50767 50768 if ((point.x > prevPoint.x || prevPoint.y !== point.y && prevPoint.x === point.x || point === prevPoint) && point.x <= 1) { 50769 prevPoint.cx = point.x - prevPoint.x; 50770 prevPoint.cy = point.y - prevPoint.y; 50771 prevPoint.n = point; 50772 prevPoint.nx = point.x; 50773 50774 if (fast && i > 1 && Math.abs(prevPoint.cy / prevPoint.cx - points[i - 2].cy / points[i - 2].cx) > 2) { 50775 fast = 0; 50776 } 50777 50778 if (prevPoint.cx < closest) { 50779 if (!prevPoint.cx) { 50780 prevPoint.cx = 0.001; 50781 50782 if (i === l - 1) { 50783 prevPoint.x -= 0.001; 50784 closest = Math.min(closest, 0.001); 50785 fast = 0; 50786 } 50787 } else { 50788 closest = prevPoint.cx; 50789 } 50790 } 50791 } else { 50792 points.splice(i--, 1); 50793 l--; 50794 } 50795 } 50796 50797 l = 1 / closest + 1 | 0; 50798 inc = 1 / l; 50799 j = 0; 50800 point = points[0]; 50801 50802 if (fast) { 50803 for (i = 0; i < l; i++) { 50804 p = i * inc; 50805 50806 if (point.nx < p) { 50807 point = points[++j]; 50808 } 50809 50810 a1 = point.y + (p - point.x) / point.cx * point.cy; 50811 lookup[i] = { 50812 x: p, 50813 cx: inc, 50814 y: a1, 50815 cy: 0, 50816 nx: 9 50817 }; 50818 50819 if (i) { 50820 lookup[i - 1].cy = a1 - lookup[i - 1].y; 50821 } 50822 } 50823 50824 j = points[points.length - 1]; 50825 lookup[l - 1].cy = j.y - a1; 50826 lookup[l - 1].cx = j.x - lookup[lookup.length - 1].x; 50827 } else { 50828 for (i = 0; i < l; i++) { 50829 if (point.nx < i * inc) { 50830 point = points[++j]; 50831 } 50832 50833 lookup[i] = point; 50834 } 50835 50836 if (j < points.length - 1) { 50837 lookup[i - 1] = points[points.length - 2]; 50838 } 50839 } 50840 50841 this.ease = function (p) { 50842 var point = lookup[p * l | 0] || lookup[l - 1]; 50843 50844 if (point.nx < p) { 50845 point = point.n; 50846 } 50847 50848 return point.y + (p - point.x) / point.cx * point.cy; 50849 }; 50850 50851 this.ease.custom = this; 50852 this.id && gsap && gsap.registerEase(this.id, this.ease); 50853 return this; 50854 }; 50855 50856 _proto.getSVGData = function getSVGData(config) { 50857 return CustomEase.getSVGData(this, config); 50858 }; 50859 50860 CustomEase.create = function create(id, data, config) { 50861 return new CustomEase(id, data, config).ease; 50862 }; 50863 50864 CustomEase.register = function register(core) { 50865 gsap = core; 50866 50867 _initCore(); 50868 }; 50869 50870 CustomEase.get = function get(id) { 50871 return gsap.parseEase(id); 50872 }; 50873 50874 CustomEase.getSVGData = function getSVGData(ease, config) { 50875 config = config || {}; 50876 var width = config.width || 100, 50877 height = config.height || 100, 50878 x = config.x || 0, 50879 y = (config.y || 0) + height, 50880 e = gsap.utils.toArray(config.path)[0], 50881 a, 50882 slope, 50883 i, 50884 inc, 50885 tx, 50886 ty, 50887 precision, 50888 threshold, 50889 prevX, 50890 prevY; 50891 50892 if (config.invert) { 50893 height = -height; 50894 y = 0; 50895 } 50896 50897 if (typeof ease === "string") { 50898 ease = gsap.parseEase(ease); 50899 } 50900 50901 if (ease.custom) { 50902 ease = ease.custom; 50903 } 50904 50905 if (ease instanceof CustomEase) { 50906 a = rawPathToString(transformRawPath([ease.segment], width, 0, 0, -height, x, y)); 50907 } else { 50908 a = [x, y]; 50909 precision = Math.max(5, (config.precision || 1) * 200); 50910 inc = 1 / precision; 50911 precision += 2; 50912 threshold = 5 / precision; 50913 prevX = _round$1(x + inc * width); 50914 prevY = _round$1(y + ease(inc) * -height); 50915 slope = (prevY - y) / (prevX - x); 50916 50917 for (i = 2; i < precision; i++) { 50918 tx = _round$1(x + i * inc * width); 50919 ty = _round$1(y + ease(i * inc) * -height); 50920 50921 if (Math.abs((ty - prevY) / (tx - prevX) - slope) > threshold || i === precision - 1) { 50922 a.push(prevX, prevY); 50923 slope = (ty - prevY) / (tx - prevX); 50924 } 50925 50926 prevX = tx; 50927 prevY = ty; 50928 } 50929 50930 a = "M" + a.join(","); 50931 } 50932 50933 e && e.setAttribute("d", a); 50934 return a; 50935 }; 50936 50937 return CustomEase; 50938 }(); 50939 CustomEase.version = "3.12.7"; 50940 CustomEase.headless = true; 50941 _getGSAP() && gsap.registerPlugin(CustomEase); 50942 50943 exports.CustomEase = CustomEase; 50944 exports.default = CustomEase; 50945 50946 Object.defineProperty(exports, '__esModule', { value: true }); 50947 50948}))); 50949(function (global, factory) { 50950 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 50951 typeof define === 'function' && define.amd ? define(['exports'], factory) : 50952 (global = global || self, factory(global.window = global.window || {})); 50953}(this, (function (exports) { 'use strict'; 50954 50955 function _inheritsLoose(subClass, superClass) { 50956 subClass.prototype = Object.create(superClass.prototype); 50957 subClass.prototype.constructor = subClass; 50958 subClass.__proto__ = superClass; 50959 } 50960 50961 function _assertThisInitialized(self) { 50962 if (self === void 0) { 50963 throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 50964 } 50965 50966 return self; 50967 } 50968 50969 var _doc, 50970 _win, 50971 _docElement, 50972 _body, 50973 _divContainer, 50974 _svgContainer, 50975 _identityMatrix, 50976 _gEl, 50977 _transformProp = "transform", 50978 _transformOriginProp = _transformProp + "Origin", 50979 _hasOffsetBug, 50980 _setDoc = function _setDoc(element) { 50981 var doc = element.ownerDocument || element; 50982 50983 if (!(_transformProp in element.style) && "msTransform" in element.style) { 50984 _transformProp = "msTransform"; 50985 _transformOriginProp = _transformProp + "Origin"; 50986 } 50987 50988 while (doc.parentNode && (doc = doc.parentNode)) {} 50989 50990 _win = window; 50991 _identityMatrix = new Matrix2D(); 50992 50993 if (doc) { 50994 _doc = doc; 50995 _docElement = doc.documentElement; 50996 _body = doc.body; 50997 _gEl = _doc.createElementNS("http://www.w3.org/2000/svg", "g"); 50998 _gEl.style.transform = "none"; 50999 var d1 = doc.createElement("div"), 51000 d2 = doc.createElement("div"), 51001 root = doc && (doc.body || doc.firstElementChild); 51002 51003 if (root && root.appendChild) { 51004 root.appendChild(d1); 51005 d1.appendChild(d2); 51006 d1.setAttribute("style", "position:static;transform:translate3d(0,0,1px)"); 51007 _hasOffsetBug = d2.offsetParent !== d1; 51008 root.removeChild(d1); 51009 } 51010 } 51011 51012 return doc; 51013 }, 51014 _forceNonZeroScale = function _forceNonZeroScale(e) { 51015 var a, cache; 51016 51017 while (e && e !== _body) { 51018 cache = e._gsap; 51019 cache && cache.uncache && cache.get(e, "x"); 51020 51021 if (cache && !cache.scaleX && !cache.scaleY && cache.renderTransform) { 51022 cache.scaleX = cache.scaleY = 1e-4; 51023 cache.renderTransform(1, cache); 51024 a ? a.push(cache) : a = [cache]; 51025 } 51026 51027 e = e.parentNode; 51028 } 51029 51030 return a; 51031 }, 51032 _svgTemps = [], 51033 _divTemps = [], 51034 _getDocScrollTop = function _getDocScrollTop() { 51035 return _win.pageYOffset || _doc.scrollTop || _docElement.scrollTop || _body.scrollTop || 0; 51036 }, 51037 _getDocScrollLeft = function _getDocScrollLeft() { 51038 return _win.pageXOffset || _doc.scrollLeft || _docElement.scrollLeft || _body.scrollLeft || 0; 51039 }, 51040 _svgOwner = function _svgOwner(element) { 51041 return element.ownerSVGElement || ((element.tagName + "").toLowerCase() === "svg" ? element : null); 51042 }, 51043 _isFixed = function _isFixed(element) { 51044 if (_win.getComputedStyle(element).position === "fixed") { 51045 return true; 51046 } 51047 51048 element = element.parentNode; 51049 51050 if (element && element.nodeType === 1) { 51051 return _isFixed(element); 51052 } 51053 }, 51054 _createSibling = function _createSibling(element, i) { 51055 if (element.parentNode && (_doc || _setDoc(element))) { 51056 var svg = _svgOwner(element), 51057 ns = svg ? svg.getAttribute("xmlns") || "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml", 51058 type = svg ? i ? "rect" : "g" : "div", 51059 x = i !== 2 ? 0 : 100, 51060 y = i === 3 ? 100 : 0, 51061 css = "position:absolute;display:block;pointer-events:none;margin:0;padding:0;", 51062 e = _doc.createElementNS ? _doc.createElementNS(ns.replace(/^https/, "http"), type) : _doc.createElement(type); 51063 51064 if (i) { 51065 if (!svg) { 51066 if (!_divContainer) { 51067 _divContainer = _createSibling(element); 51068 _divContainer.style.cssText = css; 51069 } 51070 51071 e.style.cssText = css + "width:0.1px;height:0.1px;top:" + y + "px;left:" + x + "px"; 51072 51073 _divContainer.appendChild(e); 51074 } else { 51075 _svgContainer || (_svgContainer = _createSibling(element)); 51076 e.setAttribute("width", 0.01); 51077 e.setAttribute("height", 0.01); 51078 e.setAttribute("transform", "translate(" + x + "," + y + ")"); 51079 51080 _svgContainer.appendChild(e); 51081 } 51082 } 51083 51084 return e; 51085 } 51086 51087 throw "Need document and parent."; 51088 }, 51089 _consolidate = function _consolidate(m) { 51090 var c = new Matrix2D(), 51091 i = 0; 51092 51093 for (; i < m.numberOfItems; i++) { 51094 c.multiply(m.getItem(i).matrix); 51095 } 51096 51097 return c; 51098 }, 51099 _getCTM = function _getCTM(svg) { 51100 var m = svg.getCTM(), 51101 transform; 51102 51103 if (!m) { 51104 transform = svg.style[_transformProp]; 51105 svg.style[_transformProp] = "none"; 51106 svg.appendChild(_gEl); 51107 m = _gEl.getCTM(); 51108 svg.removeChild(_gEl); 51109 transform ? svg.style[_transformProp] = transform : svg.style.removeProperty(_transformProp.replace(/([A-Z])/g, "-$1").toLowerCase()); 51110 } 51111 51112 return m || _identityMatrix.clone(); 51113 }, 51114 _placeSiblings = function _placeSiblings(element, adjustGOffset) { 51115 var svg = _svgOwner(element), 51116 isRootSVG = element === svg, 51117 siblings = svg ? _svgTemps : _divTemps, 51118 parent = element.parentNode, 51119 container, 51120 m, 51121 b, 51122 x, 51123 y, 51124 cs; 51125 51126 if (element === _win) { 51127 return element; 51128 } 51129 51130 siblings.length || siblings.push(_createSibling(element, 1), _createSibling(element, 2), _createSibling(element, 3)); 51131 container = svg ? _svgContainer : _divContainer; 51132 51133 if (svg) { 51134 if (isRootSVG) { 51135 b = _getCTM(element); 51136 x = -b.e / b.a; 51137 y = -b.f / b.d; 51138 m = _identityMatrix; 51139 } else if (element.getBBox) { 51140 b = element.getBBox(); 51141 m = element.transform ? element.transform.baseVal : {}; 51142 m = !m.numberOfItems ? _identityMatrix : m.numberOfItems > 1 ? _consolidate(m) : m.getItem(0).matrix; 51143 x = m.a * b.x + m.c * b.y; 51144 y = m.b * b.x + m.d * b.y; 51145 } else { 51146 m = new Matrix2D(); 51147 x = y = 0; 51148 } 51149 51150 if (adjustGOffset && element.tagName.toLowerCase() === "g") { 51151 x = y = 0; 51152 } 51153 51154 (isRootSVG ? svg : parent).appendChild(container);
vendor: 1,139 bytes, lines 51155-51190
51155 container.setAttribute("transform", "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + (m.e + x) + "," + (m.f + y) + ")"); 51156 } else { 51157 x = y = 0; 51158 51159 if (_hasOffsetBug) { 51160 m = element.offsetParent; 51161 b = element; 51162 51163 while (b && (b = b.parentNode) && b !== m && b.parentNode) { 51164 if ((_win.getComputedStyle(b)[_transformProp] + "").length > 4) { 51165 x = b.offsetLeft; 51166 y = b.offsetTop; 51167 b = 0; 51168 } 51169 } 51170 } 51171 51172 cs = _win.getComputedStyle(element); 51173 51174 if (cs.position !== "absolute" && cs.position !== "fixed") { 51175 m = element.offsetParent; 51176 51177 while (parent && parent !== m) { 51178 x += parent.scrollLeft || 0; 51179 y += parent.scrollTop || 0; 51180 parent = parent.parentNode; 51181 } 51182 } 51183 51184 b = container.style; 51185 b.top = element.offsetTop - y + "px"; 51186 b.left = element.offsetLeft - x + "px"; 51187 b[_transformProp] = cs[_transformProp]; 51188 b[_transformOriginProp] = cs[_transformOriginProp]; 51189 b.position = cs.position === "fixed" ? "fixed" : "absolute"; 51190 element.parentNode
vendor: 37,456 bytes, lines 51190-52445
51190.appendChild(container); 51191 } 51192 51193 return container; 51194 }, 51195 _setMatrix = function _setMatrix(m, a, b, c, d, e, f) { 51196 m.a = a; 51197 m.b = b; 51198 m.c = c; 51199 m.d = d; 51200 m.e = e; 51201 m.f = f; 51202 return m; 51203 }; 51204 51205 var Matrix2D = function () { 51206 function Matrix2D(a, b, c, d, e, f) { 51207 if (a === void 0) { 51208 a = 1; 51209 } 51210 51211 if (b === void 0) { 51212 b = 0; 51213 } 51214 51215 if (c === void 0) { 51216 c = 0; 51217 } 51218 51219 if (d === void 0) { 51220 d = 1; 51221 } 51222 51223 if (e === void 0) { 51224 e = 0; 51225 } 51226 51227 if (f === void 0) { 51228 f = 0; 51229 } 51230 51231 _setMatrix(this, a, b, c, d, e, f); 51232 } 51233 51234 var _proto = Matrix2D.prototype; 51235 51236 _proto.inverse = function inverse() { 51237 var a = this.a, 51238 b = this.b, 51239 c = this.c, 51240 d = this.d, 51241 e = this.e, 51242 f = this.f, 51243 determinant = a * d - b * c || 1e-10; 51244 return _setMatrix(this, d / determinant, -b / determinant, -c / determinant, a / determinant, (c * f - d * e) / determinant, -(a * f - b * e) / determinant); 51245 }; 51246 51247 _proto.multiply = function multiply(matrix) { 51248 var a = this.a, 51249 b = this.b, 51250 c = this.c, 51251 d = this.d, 51252 e = this.e, 51253 f = this.f, 51254 a2 = matrix.a, 51255 b2 = matrix.c, 51256 c2 = matrix.b, 51257 d2 = matrix.d, 51258 e2 = matrix.e, 51259 f2 = matrix.f; 51260 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); 51261 }; 51262 51263 _proto.clone = function clone() { 51264 return new Matrix2D(this.a, this.b, this.c, this.d, this.e, this.f); 51265 }; 51266 51267 _proto.equals = function equals(matrix) { 51268 var a = this.a, 51269 b = this.b, 51270 c = this.c, 51271 d = this.d, 51272 e = this.e, 51273 f = this.f; 51274 return a === matrix.a && b === matrix.b && c === matrix.c && d === matrix.d && e === matrix.e && f === matrix.f; 51275 }; 51276 51277 _proto.apply = function apply(point, decoratee) { 51278 if (decoratee === void 0) { 51279 decoratee = {}; 51280 } 51281 51282 var x = point.x, 51283 y = point.y, 51284 a = this.a, 51285 b = this.b, 51286 c = this.c, 51287 d = this.d, 51288 e = this.e, 51289 f = this.f; 51290 decoratee.x = x * a + y * c + e || 0; 51291 decoratee.y = x * b + y * d + f || 0; 51292 return decoratee; 51293 }; 51294 51295 return Matrix2D; 51296 }(); 51297 function getGlobalMatrix(element, inverse, adjustGOffset, includeScrollInFixed) { 51298 if (!element || !element.parentNode || (_doc || _setDoc(element)).documentElement === element) { 51299 return new Matrix2D(); 51300 } 51301 51302 var zeroScales = _forceNonZeroScale(element), 51303 svg = _svgOwner(element), 51304 temps = svg ? _svgTemps : _divTemps, 51305 container = _placeSiblings(element, adjustGOffset), 51306 b1 = temps[0].getBoundingClientRect(), 51307 b2 = temps[1].getBoundingClientRect(), 51308 b3 = temps[2].getBoundingClientRect(), 51309 parent = container.parentNode, 51310 isFixed = !includeScrollInFixed && _isFixed(element), 51311 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())); 51312 51313 parent.removeChild(container); 51314 51315 if (zeroScales) { 51316 b1 = zeroScales.length; 51317 51318 while (b1--) { 51319 b2 = zeroScales[b1]; 51320 b2.scaleX = b2.scaleY = 0; 51321 b2.renderTransform(1, b2); 51322 } 51323 } 51324 51325 return inverse ? m.inverse() : m; 51326 } 51327 51328 var gsap, 51329 _win$1, 51330 _doc$1, 51331 _docElement$1, 51332 _body$1, 51333 _tempDiv, 51334 _placeholderDiv, 51335 _coreInitted, 51336 _checkPrefix, 51337 _toArray, 51338 _supportsPassive, 51339 _isTouchDevice, 51340 _touchEventLookup, 51341 _isMultiTouching, 51342 _isAndroid, 51343 InertiaPlugin, 51344 _defaultCursor, 51345 _supportsPointer, 51346 _context, 51347 _getStyleSaver, 51348 _dragCount = 0, 51349 _windowExists = function _windowExists() { 51350 return typeof window !== "undefined"; 51351 }, 51352 _getGSAP = function _getGSAP() { 51353 return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap; 51354 }, 51355 _isFunction = function _isFunction(value) { 51356 return typeof value === "function"; 51357 }, 51358 _isObject = function _isObject(value) { 51359 return typeof value === "object"; 51360 }, 51361 _isUndefined = function _isUndefined(value) { 51362 return typeof value === "undefined"; 51363 }, 51364 _emptyFunc = function _emptyFunc() { 51365 return false; 51366 }, 51367 _transformProp$1 = "transform", 51368 _transformOriginProp$1 = "transformOrigin", 51369 _round = function _round(value) { 51370 return Math.round(value * 10000) / 10000; 51371 }, 51372 _isArray = Array.isArray, 51373 _createElement = function _createElement(type, ns) { 51374 var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type); 51375 return e.style ? e : _doc$1.createElement(type); 51376 }, 51377 _RAD2DEG = 180 / Math.PI, 51378 _bigNum = 1e20, 51379 _identityMatrix$1 = new Matrix2D(), 51380 _getTime = Date.now || function () { 51381 return new Date().getTime(); 51382 }, 51383 _renderQueue = [], 51384 _lookup = {}, 51385 _lookupCount = 0, 51386 _clickableTagExp = /^(?:a|input|textarea|button|select)$/i, 51387 _lastDragTime = 0, 51388 _temp1 = {}, 51389 _windowProxy = {}, 51390 _copy = function _copy(obj, factor) { 51391 var copy = {}, 51392 p; 51393 51394 for (p in obj) { 51395 copy[p] = factor ? obj[p] * factor : obj[p]; 51396 } 51397 51398 return copy; 51399 }, 51400 _extend = function _extend(obj, defaults) { 51401 for (var p in defaults) { 51402 if (!(p in obj)) { 51403 obj[p] = defaults[p]; 51404 } 51405 } 51406 51407 return obj; 51408 }, 51409 _setTouchActionForAllDescendants = function _setTouchActionForAllDescendants(elements, value) { 51410 var i = elements.length, 51411 children; 51412 51413 while (i--) { 51414 value ? elements[i].style.touchAction = value : elements[i].style.removeProperty("touch-action"); 51415 children = elements[i].children; 51416 children && children.length && _setTouchActionForAllDescendants(children, value); 51417 } 51418 }, 51419 _renderQueueTick = function _renderQueueTick() { 51420 return _renderQueue.forEach(function (func) { 51421 return func(); 51422 }); 51423 }, 51424 _addToRenderQueue = function _addToRenderQueue(func) { 51425 _renderQueue.push(func); 51426 51427 if (_renderQueue.length === 1) { 51428 gsap.ticker.add(_renderQueueTick); 51429 } 51430 }, 51431 _renderQueueTimeout = function _renderQueueTimeout() { 51432 return !_renderQueue.length && gsap.ticker.remove(_renderQueueTick); 51433 }, 51434 _removeFromRenderQueue = function _removeFromRenderQueue(func) { 51435 var i = _renderQueue.length; 51436 51437 while (i--) { 51438 if (_renderQueue[i] === func) { 51439 _renderQueue.splice(i, 1); 51440 } 51441 } 51442 51443 gsap.to(_renderQueueTimeout, { 51444 overwrite: true, 51445 delay: 15, 51446 duration: 0, 51447 onComplete: _renderQueueTimeout, 51448 data: "_draggable" 51449 }); 51450 }, 51451 _setDefaults = function _setDefaults(obj, defaults) { 51452 for (var p in defaults) { 51453 if (!(p in obj)) { 51454 obj[p] = defaults[p]; 51455 } 51456 } 51457 51458 return obj; 51459 }, 51460 _addListener = function _addListener(element, type, func, capture) { 51461 if (element.addEventListener) { 51462 var touchType = _touchEventLookup[type]; 51463 capture = capture || (_supportsPassive ? { 51464 passive: false 51465 } : null); 51466 element.addEventListener(touchType || type, func, capture); 51467 touchType && type !== touchType && element.addEventListener(type, func, capture); 51468 } 51469 }, 51470 _removeListener = function _removeListener(element, type, func, capture) { 51471 if (element.removeEventListener) { 51472 var touchType = _touchEventLookup[type]; 51473 element.removeEventListener(touchType || type, func, capture); 51474 touchType && type !== touchType && element.removeEventListener(type, func, capture); 51475 } 51476 }, 51477 _preventDefault = function _preventDefault(event) { 51478 event.preventDefault && event.preventDefault(); 51479 event.preventManipulation && event.preventManipulation(); 51480 }, 51481 _hasTouchID = function _hasTouchID(list, ID) { 51482 var i = list.length; 51483 51484 while (i--) { 51485 if (list[i].identifier === ID) { 51486 return true; 51487 } 51488 } 51489 }, 51490 _onMultiTouchDocumentEnd = function _onMultiTouchDocumentEnd(event) { 51491 _isMultiTouching = event.touches && _dragCount < event.touches.length; 51492 51493 _removeListener(event.target, "touchend", _onMultiTouchDocumentEnd); 51494 }, 51495 _onMultiTouchDocument = function _onMultiTouchDocument(event) { 51496 _isMultiTouching = event.touches && _dragCount < event.touches.length; 51497 51498 _addListener(event.target, "touchend", _onMultiTouchDocumentEnd); 51499 }, 51500 _getDocScrollTop$1 = function _getDocScrollTop(doc) { 51501 return _win$1.pageYOffset || doc.scrollTop || doc.documentElement.scrollTop || doc.body.scrollTop || 0; 51502 }, 51503 _getDocScrollLeft$1 = function _getDocScrollLeft(doc) { 51504 return _win$1.pageXOffset || doc.scrollLeft || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0; 51505 }, 51506 _addScrollListener = function _addScrollListener(e, callback) { 51507 _addListener(e, "scroll", callback); 51508 51509 if (!_isRoot(e.parentNode)) { 51510 _addScrollListener(e.parentNode, callback); 51511 } 51512 }, 51513 _removeScrollListener = function _removeScrollListener(e, callback) { 51514 _removeListener(e, "scroll", callback); 51515 51516 if (!_isRoot(e.parentNode)) { 51517 _removeScrollListener(e.parentNode, callback); 51518 } 51519 }, 51520 _isRoot = function _isRoot(e) { 51521 return !!(!e || e === _docElement$1 || e.nodeType === 9 || e === _doc$1.body || e === _win$1 || !e.nodeType || !e.parentNode); 51522 }, 51523 _getMaxScroll = function _getMaxScroll(element, axis) { 51524 var dim = axis === "x" ? "Width" : "Height", 51525 scroll = "scroll" + dim, 51526 client = "client" + dim; 51527 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]); 51528 }, 51529 _recordMaxScrolls = function _recordMaxScrolls(e, skipCurrent) { 51530 var x = _getMaxScroll(e, "x"), 51531 y = _getMaxScroll(e, "y"); 51532 51533 if (_isRoot(e)) { 51534 e = _windowProxy; 51535 } else { 51536 _recordMaxScrolls(e.parentNode, skipCurrent); 51537 } 51538 51539 e._gsMaxScrollX = x; 51540 e._gsMaxScrollY = y; 51541 51542 if (!skipCurrent) { 51543 e._gsScrollX = e.scrollLeft || 0; 51544 e._gsScrollY = e.scrollTop || 0; 51545 } 51546 }, 51547 _setStyle = function _setStyle(element, property, value) { 51548 var style = element.style; 51549 51550 if (!style) { 51551 return; 51552 } 51553 51554 if (_isUndefined(style[property])) { 51555 property = _checkPrefix(property, element) || property; 51556 } 51557 51558 if (value == null) { 51559 style.removeProperty && style.removeProperty(property.replace(/([A-Z])/g, "-$1").toLowerCase()); 51560 } else { 51561 style[property] = value; 51562 } 51563 }, 51564 _getComputedStyle = function _getComputedStyle(element) { 51565 return _win$1.getComputedStyle(element instanceof Element ? element : element.host || (element.parentNode || {}).host || element); 51566 }, 51567 _tempRect = {}, 51568 _parseRect = function _parseRect(e) { 51569 if (e === _win$1) { 51570 _tempRect.left = _tempRect.top = 0; 51571 _tempRect.width = _tempRect.right = _docElement$1.clientWidth || e.innerWidth || _body$1.clientWidth || 0; 51572 _tempRect.height = _tempRect.bottom = (e.innerHeight || 0) - 20 < _docElement$1.clientHeight ? _docElement$1.clientHeight : e.innerHeight || _body$1.clientHeight || 0; 51573 return _tempRect; 51574 } 51575 51576 var doc = e.ownerDocument || _doc$1, 51577 r = !_isUndefined(e.pageX) ? { 51578 left: e.pageX - _getDocScrollLeft$1(doc), 51579 top: e.pageY - _getDocScrollTop$1(doc), 51580 right: e.pageX - _getDocScrollLeft$1(doc) + 1, 51581 bottom: e.pageY - _getDocScrollTop$1(doc) + 1 51582 } : !e.nodeType && !_isUndefined(e.left) && !_isUndefined(e.top) ? e : _toArray(e)[0].getBoundingClientRect(); 51583 51584 if (_isUndefined(r.right) && !_isUndefined(r.width)) { 51585 r.right = r.left + r.width; 51586 r.bottom = r.top + r.height; 51587 } else if (_isUndefined(r.width)) { 51588 r = { 51589 width: r.right - r.left, 51590 height: r.bottom - r.top, 51591 right: r.right, 51592 left: r.left, 51593 bottom: r.bottom, 51594 top: r.top 51595 }; 51596 } 51597 51598 return r; 51599 }, 51600 _dispatchEvent = function _dispatchEvent(target, type, callbackName) { 51601 var vars = target.vars, 51602 callback = vars[callbackName], 51603 listeners = target._listeners[type], 51604 result; 51605 51606 if (_isFunction(callback)) { 51607 result = callback.apply(vars.callbackScope || target, vars[callbackName + "Params"] || [target.pointerEvent]); 51608 } 51609 51610 if (listeners && target.dispatchEvent(type) === false) { 51611 result = false; 51612 } 51613 51614 return result; 51615 }, 51616 _getBounds = function _getBounds(target, context) { 51617 var e = _toArray(target)[0], 51618 top, 51619 left, 51620 offset; 51621 51622 if (!e.nodeType && e !== _win$1) { 51623 if (!_isUndefined(target.left)) { 51624 offset = { 51625 x: 0, 51626 y: 0 51627 }; 51628 return { 51629 left: target.left - offset.x, 51630 top: target.top - offset.y, 51631 width: target.width, 51632 height: target.height 51633 }; 51634 } 51635 51636 left = target.min || target.minX || target.minRotation || 0; 51637 top = target.min || target.minY || 0; 51638 return { 51639 left: left, 51640 top: top, 51641 width: (target.max || target.maxX || target.maxRotation || 0) - left, 51642 height: (target.max || target.maxY || 0) - top 51643 }; 51644 } 51645 51646 return _getElementBounds(e, context); 51647 }, 51648 _point1 = {}, 51649 _getElementBounds = function _getElementBounds(element, context) { 51650 context = _toArray(context)[0]; 51651 var isSVG = element.getBBox && element.ownerSVGElement, 51652 doc = element.ownerDocument || _doc$1, 51653 left, 51654 right, 51655 top, 51656 bottom, 51657 matrix, 51658 p1, 51659 p2, 51660 p3, 51661 p4, 51662 bbox, 51663 width, 51664 height, 51665 cs; 51666 51667 if (element === _win$1) { 51668 top = _getDocScrollTop$1(doc); 51669 left = _getDocScrollLeft$1(doc); 51670 right = left + (doc.documentElement.clientWidth || element.innerWidth || doc.body.clientWidth || 0); 51671 bottom = top + ((element.innerHeight || 0) - 20 < doc.documentElement.clientHeight ? doc.documentElement.clientHeight : element.innerHeight || doc.body.clientHeight || 0); 51672 } else if (context === _win$1 || _isUndefined(context)) { 51673 return element.getBoundingClientRect(); 51674 } else { 51675 left = top = 0; 51676 51677 if (isSVG) { 51678 bbox = element.getBBox(); 51679 width = bbox.width; 51680 height = bbox.height; 51681 } else { 51682 if (element.viewBox && (bbox = element.viewBox.baseVal)) { 51683 left = bbox.x || 0; 51684 top = bbox.y || 0; 51685 width = bbox.width; 51686 height = bbox.height; 51687 } 51688 51689 if (!width) { 51690 cs = _getComputedStyle(element); 51691 bbox = cs.boxSizing === "border-box"; 51692 width = (parseFloat(cs.width) || element.clientWidth || 0) + (bbox ? 0 : parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth)); 51693 height = (parseFloat(cs.height) || element.clientHeight || 0) + (bbox ? 0 : parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth)); 51694 } 51695 } 51696 51697 right = width; 51698 bottom = height; 51699 } 51700 51701 if (element === context) { 51702 return { 51703 left: left, 51704 top: top, 51705 width: right - left, 51706 height: bottom - top 51707 }; 51708 } 51709 51710 matrix = getGlobalMatrix(context, true).multiply(getGlobalMatrix(element)); 51711 p1 = matrix.apply({ 51712 x: left, 51713 y: top 51714 }); 51715 p2 = matrix.apply({ 51716 x: right, 51717 y: top 51718 }); 51719 p3 = matrix.apply({ 51720 x: right, 51721 y: bottom 51722 }); 51723 p4 = matrix.apply({ 51724 x: left, 51725 y: bottom 51726 }); 51727 left = Math.min(p1.x, p2.x, p3.x, p4.x); 51728 top = Math.min(p1.y, p2.y, p3.y, p4.y); 51729 return { 51730 left: left, 51731 top: top, 51732 width: Math.max(p1.x, p2.x, p3.x, p4.x) - left, 51733 height: Math.max(p1.y, p2.y, p3.y, p4.y) - top 51734 }; 51735 }, 51736 _parseInertia = function _parseInertia(draggable, snap, max, min, factor, forceZeroVelocity) { 51737 var vars = {}, 51738 a, 51739 i, 51740 l; 51741 51742 if (snap) { 51743 if (factor !== 1 && snap instanceof Array) { 51744 vars.end = a = []; 51745 l = snap.length; 51746 51747 if (_isObject(snap[0])) { 51748 for (i = 0; i < l; i++) { 51749 a[i] = _copy(snap[i], factor); 51750 } 51751 } else { 51752 for (i = 0; i < l; i++) { 51753 a[i] = snap[i] * factor; 51754 } 51755 } 51756 51757 max += 1.1; 51758 min -= 1.1; 51759 } else if (_isFunction(snap)) { 51760 vars.end = function (value) { 51761 var result = snap.call(draggable, value), 51762 copy, 51763 p; 51764 51765 if (factor !== 1) { 51766 if (_isObject(result)) { 51767 copy = {}; 51768 51769 for (p in result) { 51770 copy[p] = result[p] * factor; 51771 } 51772 51773 result = copy; 51774 } else { 51775 result *= factor; 51776 } 51777 } 51778 51779 return result; 51780 }; 51781 } else { 51782 vars.end = snap; 51783 } 51784 } 51785 51786 if (max || max === 0) { 51787 vars.max = max; 51788 } 51789 51790 if (min || min === 0) { 51791 vars.min = min; 51792 } 51793 51794 if (forceZeroVelocity) { 51795 vars.velocity = 0; 51796 } 51797 51798 return vars; 51799 }, 51800 _isClickable = function _isClickable(element) { 51801 var data; 51802 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); 51803 }, 51804 _setSelectable = function _setSelectable(elements, selectable) { 51805 var i = elements.length, 51806 e; 51807 51808 while (i--) { 51809 e = elements[i]; 51810 e.ondragstart = e.onselectstart = selectable ? null : _emptyFunc; 51811 gsap.set(e, { 51812 lazy: true, 51813 userSelect: selectable ? "text" : "none" 51814 }); 51815 } 51816 }, 51817 _isFixed$1 = function _isFixed(element) { 51818 if (_getComputedStyle(element).position === "fixed") { 51819 return true; 51820 } 51821 51822 element = element.parentNode; 51823 51824 if (element && element.nodeType === 1) { 51825 return _isFixed(element); 51826 } 51827 }, 51828 _supports3D, 51829 _addPaddingBR, 51830 ScrollProxy = function ScrollProxy(element, vars) { 51831 element = gsap.utils.toArray(element)[0]; 51832 vars = vars || {}; 51833 var content = document.createElement("div"), 51834 style = content.style, 51835 node = element.firstChild, 51836 offsetTop = 0, 51837 offsetLeft = 0, 51838 prevTop = element.scrollTop, 51839 prevLeft = element.scrollLeft, 51840 scrollWidth = element.scrollWidth, 51841 scrollHeight = element.scrollHeight, 51842 extraPadRight = 0, 51843 maxLeft = 0, 51844 maxTop = 0, 51845 elementWidth, 51846 elementHeight, 51847 contentHeight, 51848 nextNode, 51849 transformStart, 51850 transformEnd; 51851 51852 if (_supports3D && vars.force3D !== false) { 51853 transformStart = "translate3d("; 51854 transformEnd = "px,0px)"; 51855 } else if (_transformProp$1) { 51856 transformStart = "translate("; 51857 transformEnd = "px)"; 51858 } 51859 51860 this.scrollTop = function (value, force) { 51861 if (!arguments.length) { 51862 return -this.top(); 51863 } 51864 51865 this.top(-value, force); 51866 }; 51867 51868 this.scrollLeft = function (value, force) { 51869 if (!arguments.length) { 51870 return -this.left(); 51871 } 51872 51873 this.left(-value, force); 51874 }; 51875 51876 this.left = function (value, force) { 51877 if (!arguments.length) { 51878 return -(element.scrollLeft + offsetLeft); 51879 } 51880 51881 var dif = element.scrollLeft - prevLeft, 51882 oldOffset = offsetLeft; 51883 51884 if ((dif > 2 || dif < -2) && !force) { 51885 prevLeft = element.scrollLeft; 51886 gsap.killTweensOf(this, { 51887 left: 1, 51888 scrollLeft: 1 51889 }); 51890 this.left(-prevLeft); 51891 51892 if (vars.onKill) { 51893 vars.onKill(); 51894 } 51895 51896 return; 51897 } 51898 51899 value = -value; 51900 51901 if (value < 0) { 51902 offsetLeft = value - 0.5 | 0; 51903 value = 0; 51904 } else if (value > maxLeft) { 51905 offsetLeft = value - maxLeft | 0; 51906 value = maxLeft; 51907 } else { 51908 offsetLeft = 0; 51909 } 51910 51911 if (offsetLeft || oldOffset) { 51912 if (!this._skip) { 51913 style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd; 51914 } 51915 51916 if (offsetLeft + extraPadRight >= 0) { 51917 style.paddingRight = offsetLeft + extraPadRight + "px"; 51918 } 51919 } 51920 51921 element.scrollLeft = value | 0; 51922 prevLeft = element.scrollLeft; 51923 }; 51924 51925 this.top = function (value, force) { 51926 if (!arguments.length) { 51927 return -(element.scrollTop + offsetTop); 51928 } 51929 51930 var dif = element.scrollTop - prevTop, 51931 oldOffset = offsetTop; 51932 51933 if ((dif > 2 || dif < -2) && !force) { 51934 prevTop = element.scrollTop; 51935 gsap.killTweensOf(this, { 51936 top: 1, 51937 scrollTop: 1 51938 }); 51939 this.top(-prevTop); 51940 51941 if (vars.onKill) { 51942 vars.onKill(); 51943 } 51944 51945 return; 51946 } 51947 51948 value = -value; 51949 51950 if (value < 0) { 51951 offsetTop = value - 0.5 | 0; 51952 value = 0; 51953 } else if (value > maxTop) { 51954 offsetTop = value - maxTop | 0; 51955 value = maxTop; 51956 } else { 51957 offsetTop = 0; 51958 } 51959 51960 if (offsetTop || oldOffset) { 51961 if (!this._skip) { 51962 style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd; 51963 } 51964 } 51965 51966 element.scrollTop = value | 0; 51967 prevTop = element.scrollTop; 51968 }; 51969 51970 this.maxScrollTop = function () { 51971 return maxTop; 51972 }; 51973 51974 this.maxScrollLeft = function () { 51975 return maxLeft; 51976 }; 51977 51978 this.disable = function () { 51979 node = content.firstChild; 51980 51981 while (node) { 51982 nextNode = node.nextSibling; 51983 element.appendChild(node); 51984 node = nextNode; 51985 } 51986 51987 if (element === content.parentNode) { 51988 element.removeChild(content); 51989 } 51990 }; 51991 51992 this.enable = function () { 51993 node = element.firstChild; 51994 51995 if (node === content) { 51996 return; 51997 } 51998 51999 while (node) { 52000 nextNode = node.nextSibling; 52001 content.appendChild(node); 52002 node = nextNode; 52003 } 52004 52005 element.appendChild(content); 52006 this.calibrate(); 52007 }; 52008 52009 this.calibrate = function (force) { 52010 var widthMatches = element.clientWidth === elementWidth, 52011 cs, 52012 x, 52013 y; 52014 prevTop = element.scrollTop; 52015 prevLeft = element.scrollLeft; 52016 52017 if (widthMatches && element.clientHeight === elementHeight && content.offsetHeight === contentHeight && scrollWidth === element.scrollWidth && scrollHeight === element.scrollHeight && !force) { 52018 return; 52019 } 52020 52021 if (offsetTop || offsetLeft) { 52022 x = this.left(); 52023 y = this.top(); 52024 this.left(-element.scrollLeft); 52025 this.top(-element.scrollTop); 52026 } 52027 52028 cs = _getComputedStyle(element); 52029 52030 if (!widthMatches || force) { 52031 style.display = "block"; 52032 style.width = "auto"; 52033 style.paddingRight = "0px"; 52034 extraPadRight = Math.max(0, element.scrollWidth - element.clientWidth); 52035 52036 if (extraPadRight) { 52037 extraPadRight += parseFloat(cs.paddingLeft) + (_addPaddingBR ? parseFloat(cs.paddingRight) : 0); 52038 } 52039 } 52040 52041 style.display = "inline-block"; 52042 style.position = "relative"; 52043 style.overflow = "visible"; 52044 style.verticalAlign = "top"; 52045 style.boxSizing = "content-box"; 52046 style.width = "100%"; 52047 style.paddingRight = extraPadRight + "px"; 52048 52049 if (_addPaddingBR) { 52050 style.paddingBottom = cs.paddingBottom; 52051 } 52052 52053 elementWidth = element.clientWidth; 52054 elementHeight = element.clientHeight; 52055 scrollWidth = element.scrollWidth; 52056 scrollHeight = element.scrollHeight; 52057 maxLeft = element.scrollWidth - elementWidth; 52058 maxTop = element.scrollHeight - elementHeight; 52059 contentHeight = content.offsetHeight; 52060 style.display = "block"; 52061 52062 if (x || y) { 52063 this.left(x); 52064 this.top(y); 52065 } 52066 }; 52067 52068 this.content = content; 52069 this.element = element; 52070 this._skip = false; 52071 this.enable(); 52072 }, 52073 _initCore = function _initCore(required) { 52074 if (_windowExists() && document.body) { 52075 var nav = window && window.navigator; 52076 _win$1 = window; 52077 _doc$1 = document; 52078 _docElement$1 = _doc$1.documentElement; 52079 _body$1 = _doc$1.body; 52080 _tempDiv = _createElement("div"); 52081 _supportsPointer = !!window.PointerEvent; 52082 _placeholderDiv = _createElement("div"); 52083 _placeholderDiv.style.cssText = "visibility:hidden;height:1px;top:-1px;pointer-events:none;position:relative;clear:both;cursor:grab"; 52084 _defaultCursor = _placeholderDiv.style.cursor === "grab" ? "grab" : "move"; 52085 _isAndroid = nav && nav.userAgent.toLowerCase().indexOf("android") !== -1; 52086 _isTouchDevice = "ontouchstart" in _docElement$1 && "orientation" in _win$1 || nav && (nav.MaxTouchPoints > 0 || nav.msMaxTouchPoints > 0); 52087 52088 _addPaddingBR = function () { 52089 var div = _createElement("div"), 52090 child = _createElement("div"), 52091 childStyle = child.style, 52092 parent = _body$1, 52093 val; 52094 52095 childStyle.display = "inline-block"; 52096 childStyle.position = "relative"; 52097 div.style.cssText = "width:90px;height:40px;padding:10px;overflow:auto;visibility:hidden"; 52098 div.appendChild(child); 52099 parent.appendChild(div); 52100 val = child.offsetHeight + 18 > div.scrollHeight; 52101 parent.removeChild(div); 52102 return val; 52103 }(); 52104 52105 _touchEventLookup = function (types) { 52106 var standard = types.split(","), 52107 converted = ("onpointerdown" in _tempDiv ? "pointerdown,pointermove,pointerup,pointercancel" : "onmspointerdown" in _tempDiv ? "MSPointerDown,MSPointerMove,MSPointerUp,MSPointerCancel" : types).split(","), 52108 obj = {}, 52109 i = 4; 52110 52111 while (--i > -1) { 52112 obj[standard[i]] = converted[i]; 52113 obj[converted[i]] = standard[i]; 52114 } 52115 52116 try { 52117 _docElement$1.addEventListener("test", null, Object.defineProperty({}, "passive", { 52118 get: function get() { 52119 _supportsPassive = 1; 52120 } 52121 })); 52122 } catch (e) {} 52123 52124 return obj; 52125 }("touchstart,touchmove,touchend,touchcancel"); 52126 52127 _addListener(_doc$1, "touchcancel", _emptyFunc); 52128 52129 _addListener(_win$1, "touchmove", _emptyFunc); 52130 52131 _body$1 && _body$1.addEventListener("touchstart", _emptyFunc); 52132 52133 _addListener(_doc$1, "contextmenu", function () { 52134 for (var p in _lookup) { 52135 if (_lookup[p].isPressed) { 52136 _lookup[p].endDrag(); 52137 } 52138 } 52139 }); 52140 52141 gsap = _coreInitted = _getGSAP(); 52142 } 52143 52144 if (gsap) { 52145 InertiaPlugin = gsap.plugins.inertia; 52146 52147 _context = gsap.core.context || function () {}; 52148 52149 _checkPrefix = gsap.utils.checkPrefix; 52150 _transformProp$1 = _checkPrefix(_transformProp$1); 52151 _transformOriginProp$1 = _checkPrefix(_transformOriginProp$1); 52152 _toArray = gsap.utils.toArray; 52153 _getStyleSaver = gsap.core.getStyleSaver; 52154 _supports3D = !!_checkPrefix("perspective"); 52155 } else if (required) { 52156 console.warn("Please gsap.registerPlugin(Draggable)"); 52157 } 52158 }; 52159 52160 var EventDispatcher = function () { 52161 function EventDispatcher(target) { 52162 this._listeners = {}; 52163 this.target = target || this; 52164 } 52165 52166 var _proto = EventDispatcher.prototype; 52167 52168 _proto.addEventListener = function addEventListener(type, callback) { 52169 var list = this._listeners[type] || (this._listeners[type] = []); 52170 52171 if (!~list.indexOf(callback)) { 52172 list.push(callback); 52173 } 52174 }; 52175 52176 _proto.removeEventListener = function removeEventListener(type, callback) { 52177 var list = this._listeners[type], 52178 i = list && list.indexOf(callback); 52179 i >= 0 && list.splice(i, 1); 52180 }; 52181 52182 _proto.dispatchEvent = function dispatchEvent(type) { 52183 var _this = this; 52184 52185 var result; 52186 (this._listeners[type] || []).forEach(function (callback) { 52187 return callback.call(_this, { 52188 type: type, 52189 target: _this.target 52190 }) === false && (result = false); 52191 }); 52192 return result; 52193 }; 52194 52195 return EventDispatcher; 52196 }(); 52197 52198 var Draggable = function (_EventDispatcher) { 52199 _inheritsLoose(Draggable, _EventDispatcher); 52200 52201 function Draggable(target, vars) { 52202 var _this2; 52203 52204 _this2 = _EventDispatcher.call(this) || this; 52205 _coreInitted || _initCore(1); 52206 target = _toArray(target)[0]; 52207 _this2.styles = _getStyleSaver && _getStyleSaver(target, "transform,left,top"); 52208 52209 if (!InertiaPlugin) { 52210 InertiaPlugin = gsap.plugins.inertia; 52211 } 52212 52213 _this2.vars = vars = _copy(vars || {}); 52214 _this2.target = target; 52215 _this2.x = _this2.y = _this2.rotation = 0; 52216 _this2.dragResistance = parseFloat(vars.dragResistance) || 0; 52217 _this2.edgeResistance = isNaN(vars.edgeResistance) ? 1 : parseFloat(vars.edgeResistance) || 0; 52218 _this2.lockAxis = vars.lockAxis; 52219 _this2.autoScroll = vars.autoScroll || 0; 52220 _this2.lockedAxis = null; 52221 _this2.allowEventDefault = !!vars.allowEventDefault; 52222 gsap.getProperty(target, "x"); 52223 52224 var type = (vars.type || "x,y").toLowerCase(), 52225 xyMode = ~type.indexOf("x") || ~type.indexOf("y"), 52226 rotationMode = type.indexOf("rotation") !== -1, 52227 xProp = rotationMode ? "rotation" : xyMode ? "x" : "left", 52228 yProp = xyMode ? "y" : "top", 52229 allowX = !!(~type.indexOf("x") || ~type.indexOf("left") || type === "scroll"), 52230 allowY = !!(~type.indexOf("y") || ~type.indexOf("top") || type === "scroll"), 52231 minimumMovement = vars.minimumMovement || 2, 52232 self = _assertThisInitialized(_this2), 52233 triggers = _toArray(vars.trigger || vars.handle || target), 52234 killProps = {}, 52235 dragEndTime = 0, 52236 checkAutoScrollBounds = false, 52237 autoScrollMarginTop = vars.autoScrollMarginTop || 40, 52238 autoScrollMarginRight = vars.autoScrollMarginRight || 40, 52239 autoScrollMarginBottom = vars.autoScrollMarginBottom || 40, 52240 autoScrollMarginLeft = vars.autoScrollMarginLeft || 40, 52241 isClickable = vars.clickableTest || _isClickable, 52242 clickTime = 0, 52243 gsCache = target._gsap || gsap.core.getCache(target), 52244 isFixed = _isFixed$1(target), 52245 getPropAsNum = function getPropAsNum(property, unit) { 52246 return parseFloat(gsCache.get(target, property, unit)); 52247 }, 52248 ownerDoc = target.ownerDocument || _doc$1, 52249 enabled, 52250 scrollProxy, 52251 startPointerX, 52252 startPointerY, 52253 startElementX, 52254 startElementY, 52255 hasBounds, 52256 hasDragCallback, 52257 hasMoveCallback, 52258 maxX, 52259 minX, 52260 maxY, 52261 minY, 52262 touch, 52263 touchID, 52264 rotationOrigin, 52265 dirty, 52266 old, 52267 snapX, 52268 snapY, 52269 snapXY, 52270 isClicking, 52271 touchEventTarget, 52272 matrix, 52273 interrupted, 52274 allowNativeTouchScrolling, 52275 touchDragAxis, 52276 isDispatching, 52277 clickDispatch, 52278 trustedClickDispatch, 52279 isPreventingDefault, 52280 innerMatrix, 52281 dragged, 52282 onContextMenu = function onContextMenu(e) { 52283 _preventDefault(e); 52284 52285 e.stopImmediatePropagation && e.stopImmediatePropagation(); 52286 return false; 52287 }, 52288 render = function render(suppressEvents) { 52289 if (self.autoScroll && self.isDragging && (checkAutoScrollBounds || dirty)) { 52290 var e = target, 52291 autoScrollFactor = self.autoScroll * 15, 52292 parent, 52293 isRoot, 52294 rect, 52295 pointerX, 52296 pointerY, 52297 changeX, 52298 changeY, 52299 gap; 52300 checkAutoScrollBounds = false; 52301 _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop; 52302 _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft; 52303 pointerX = self.pointerX - _windowProxy.scrollLeft; 52304 pointerY = self.pointerY - _windowProxy.scrollTop; 52305 52306 while (e && !isRoot) { 52307 isRoot = _isRoot(e.parentNode); 52308 parent = isRoot ? _windowProxy : e.parentNode; 52309 rect = isRoot ? { 52310 bottom: Math.max(_docElement$1.clientHeight, _win$1.innerHeight || 0), 52311 right: Math.max(_docElement$1.clientWidth, _win$1.innerWidth || 0), 52312 left: 0, 52313 top: 0 52314 } : parent.getBoundingClientRect(); 52315 changeX = changeY = 0; 52316 52317 if (allowY) { 52318 gap = parent._gsMaxScrollY - parent.scrollTop; 52319 52320 if (gap < 0) { 52321 changeY = gap; 52322 } else if (pointerY > rect.bottom - autoScrollMarginBottom && gap) { 52323 checkAutoScrollBounds = true; 52324 changeY = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.bottom - pointerY) / autoScrollMarginBottom) | 0); 52325 } else if (pointerY < rect.top + autoScrollMarginTop && parent.scrollTop) { 52326 checkAutoScrollBounds = true; 52327 changeY = -Math.min(parent.scrollTop, autoScrollFactor * (1 - Math.max(0, pointerY - rect.top) / autoScrollMarginTop) | 0); 52328 } 52329 52330 if (changeY) { 52331 parent.scrollTop += changeY; 52332 } 52333 } 52334 52335 if (allowX) { 52336 gap = parent._gsMaxScrollX - parent.scrollLeft; 52337 52338 if (gap < 0) { 52339 changeX = gap; 52340 } else if (pointerX > rect.right - autoScrollMarginRight && gap) { 52341 checkAutoScrollBounds = true; 52342 changeX = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.right - pointerX) / autoScrollMarginRight) | 0); 52343 } else if (pointerX < rect.left + autoScrollMarginLeft && parent.scrollLeft) { 52344 checkAutoScrollBounds = true; 52345 changeX = -Math.min(parent.scrollLeft, autoScrollFactor * (1 - Math.max(0, pointerX - rect.left) / autoScrollMarginLeft) | 0); 52346 } 52347 52348 if (changeX) { 52349 parent.scrollLeft += changeX; 52350 } 52351 } 52352 52353 if (isRoot && (changeX || changeY)) { 52354 _win$1.scrollTo(parent.scrollLeft, parent.scrollTop); 52355 52356 setPointerPosition(self.pointerX + changeX, self.pointerY + changeY); 52357 } 52358 52359 e = parent; 52360 } 52361 } 52362 52363 if (dirty) { 52364 var x = self.x, 52365 y = self.y; 52366 52367 if (rotationMode) { 52368 self.deltaX = x - parseFloat(gsCache.rotation); 52369 self.rotation = x; 52370 gsCache.rotation = x + "deg"; 52371 gsCache.renderTransform(1, gsCache); 52372 } else { 52373 if (scrollProxy) { 52374 if (allowY) { 52375 self.deltaY = y - scrollProxy.top(); 52376 scrollProxy.top(y); 52377 } 52378 52379 if (allowX) { 52380 self.deltaX = x - scrollProxy.left(); 52381 scrollProxy.left(x); 52382 } 52383 } else if (xyMode) { 52384 if (allowY) { 52385 self.deltaY = y - parseFloat(gsCache.y); 52386 gsCache.y = y + "px"; 52387 } 52388 52389 if (allowX) { 52390 self.deltaX = x - parseFloat(gsCache.x); 52391 gsCache.x = x + "px"; 52392 } 52393 52394 gsCache.renderTransform(1, gsCache); 52395 } else { 52396 if (allowY) { 52397 self.deltaY = y - parseFloat(target.style.top || 0); 52398 target.style.top = y + "px"; 52399 } 52400 52401 if (allowX) { 52402 self.deltaX = x - parseFloat(target.style.left || 0); 52403 target.style.left = x + "px"; 52404 } 52405 } 52406 } 52407 52408 if (hasDragCallback && !suppressEvents && !isDispatching) { 52409 isDispatching = true; 52410 52411 if (_dispatchEvent(self, "drag", "onDrag") === false) { 52412 if (allowX) { 52413 self.x -= self.deltaX; 52414 } 52415 52416 if (allowY) { 52417 self.y -= self.deltaY; 52418 } 52419 52420 render(true); 52421 } 52422 52423 isDispatching = false; 52424 } 52425 } 52426 52427 dirty = false; 52428 }, 52429 syncXY = function syncXY(skipOnUpdate, skipSnap) { 52430 var x = self.x, 52431 y = self.y, 52432 snappedValue, 52433 cs; 52434 52435 if (!target._gsap) { 52436 gsCache = gsap.core.getCache(target); 52437 } 52438 52439 gsCache.uncache && gsap.getProperty(target, "x"); 52440 52441 if (xyMode) { 52442 self.x = parseFloat(gsCache.x); 52443 self.y = parseFloat(gsCache.y); 52444 } else if (rotationMode) { 52445 self.x = self.rotation =
52445parseFloat(gsCache.rotation
vendor: 18,327 bytes, lines 52445-52995
52445); 52446 } else if (scrollProxy) { 52447 self.y = scrollProxy.top(); 52448 self.x = scrollProxy.left(); 52449 } else { 52450 self.y = parseFloat(target.style.top || (cs = _getComputedStyle(target)) && cs.top) || 0; 52451 self.x = parseFloat(target.style.left || (cs || {}).left) || 0; 52452 } 52453 52454 if ((snapX || snapY || snapXY) && !skipSnap && (self.isDragging || self.isThrowing)) { 52455 if (snapXY) { 52456 _temp1.x = self.x; 52457 _temp1.y = self.y; 52458 snappedValue = snapXY(_temp1); 52459 52460 if (snappedValue.x !== self.x) { 52461 self.x = snappedValue.x; 52462 dirty = true; 52463 } 52464 52465 if (snappedValue.y !== self.y) { 52466 self.y = snappedValue.y; 52467 dirty = true; 52468 } 52469 } 52470 52471 if (snapX) { 52472 snappedValue = snapX(self.x); 52473 52474 if (snappedValue !== self.x) { 52475 self.x = snappedValue; 52476 52477 if (rotationMode) { 52478 self.rotation = snappedValue; 52479 } 52480 52481 dirty = true; 52482 } 52483 } 52484 52485 if (snapY) { 52486 snappedValue = snapY(self.y); 52487 52488 if (snappedValue !== self.y) { 52489 self.y = snappedValue; 52490 } 52491 52492 dirty = true; 52493 } 52494 } 52495 52496 dirty && render(true); 52497 52498 if (!skipOnUpdate) { 52499 self.deltaX = self.x - x; 52500 self.deltaY = self.y - y; 52501 52502 _dispatchEvent(self, "throwupdate", "onThrowUpdate"); 52503 } 52504 }, 52505 buildSnapFunc = function buildSnapFunc(snap, min, max, factor) { 52506 if (min == null) { 52507 min = -_bigNum; 52508 } 52509 52510 if (max == null) { 52511 max = _bigNum; 52512 } 52513 52514 if (_isFunction(snap)) { 52515 return function (n) { 52516 var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance; 52517 return snap.call(self, (n > max ? max + (n - max) * edgeTolerance : n < min ? min + (n - min) * edgeTolerance : n) * factor) * factor; 52518 }; 52519 } 52520 52521 if (_isArray(snap)) { 52522 return function (n) { 52523 var i = snap.length, 52524 closest = 0, 52525 absDif = _bigNum, 52526 val, 52527 dif; 52528 52529 while (--i > -1) { 52530 val = snap[i]; 52531 dif = val - n; 52532 52533 if (dif < 0) { 52534 dif = -dif; 52535 } 52536 52537 if (dif < absDif && val >= min && val <= max) { 52538 closest = i; 52539 absDif = dif; 52540 } 52541 } 52542 52543 return snap[closest]; 52544 }; 52545 } 52546 52547 return isNaN(snap) ? function (n) { 52548 return n; 52549 } : function () { 52550 return snap * factor; 52551 }; 52552 }, 52553 buildPointSnapFunc = function buildPointSnapFunc(snap, minX, maxX, minY, maxY, radius, factor) { 52554 radius = radius && radius < _bigNum ? radius * radius : _bigNum; 52555 52556 if (_isFunction(snap)) { 52557 return function (point) { 52558 var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance, 52559 x = point.x, 52560 y = point.y, 52561 result, 52562 dx, 52563 dy; 52564 point.x = x = x > maxX ? maxX + (x - maxX) * edgeTolerance : x < minX ? minX + (x - minX) * edgeTolerance : x; 52565 point.y = y = y > maxY ? maxY + (y - maxY) * edgeTolerance : y < minY ? minY + (y - minY) * edgeTolerance : y; 52566 result = snap.call(self, point); 52567 52568 if (result !== point) { 52569 point.x = result.x; 52570 point.y = result.y; 52571 } 52572 52573 if (factor !== 1) { 52574 point.x *= factor; 52575 point.y *= factor; 52576 } 52577 52578 if (radius < _bigNum) { 52579 dx = point.x - x; 52580 dy = point.y - y; 52581 52582 if (dx * dx + dy * dy > radius) { 52583 point.x = x; 52584 point.y = y; 52585 } 52586 } 52587 52588 return point; 52589 }; 52590 } 52591 52592 if (_isArray(snap)) { 52593 return function (p) { 52594 var i = snap.length, 52595 closest = 0, 52596 minDist = _bigNum, 52597 x, 52598 y, 52599 point, 52600 dist; 52601 52602 while (--i > -1) { 52603 point = snap[i]; 52604 x = point.x - p.x; 52605 y = point.y - p.y; 52606 dist = x * x + y * y; 52607 52608 if (dist < minDist) { 52609 closest = i; 52610 minDist = dist; 52611 } 52612 } 52613 52614 return minDist <= radius ? snap[closest] : p; 52615 }; 52616 } 52617 52618 return function (n) { 52619 return n; 52620 }; 52621 }, 52622 calculateBounds = function calculateBounds() { 52623 var bounds, targetBounds, snap, snapIsRaw; 52624 hasBounds = false; 52625 52626 if (scrollProxy) { 52627 scrollProxy.calibrate(); 52628 self.minX = minX = -scrollProxy.maxScrollLeft(); 52629 self.minY = minY = -scrollProxy.maxScrollTop(); 52630 self.maxX = maxX = self.maxY = maxY = 0; 52631 hasBounds = true; 52632 } else if (!!vars.bounds) { 52633 bounds = _getBounds(vars.bounds, target.parentNode); 52634 52635 if (rotationMode) { 52636 self.minX = minX = bounds.left; 52637 self.maxX = maxX = bounds.left + bounds.width; 52638 self.minY = minY = self.maxY = maxY = 0; 52639 } else if (!_isUndefined(vars.bounds.maxX) || !_isUndefined(vars.bounds.maxY)) { 52640 bounds = vars.bounds; 52641 self.minX = minX = bounds.minX; 52642 self.minY = minY = bounds.minY; 52643 self.maxX = maxX = bounds.maxX; 52644 self.maxY = maxY = bounds.maxY; 52645 } else { 52646 targetBounds = _getBounds(target, target.parentNode); 52647 self.minX = minX = Math.round(getPropAsNum(xProp, "px") + bounds.left - targetBounds.left); 52648 self.minY = minY = Math.round(getPropAsNum(yProp, "px") + bounds.top - targetBounds.top); 52649 self.maxX = maxX = Math.round(minX + (bounds.width - targetBounds.width)); 52650 self.maxY = maxY = Math.round(minY + (bounds.height - targetBounds.height)); 52651 } 52652 52653 if (minX > maxX) { 52654 self.minX = maxX; 52655 self.maxX = maxX = minX; 52656 minX = self.minX; 52657 } 52658 52659 if (minY > maxY) { 52660 self.minY = maxY; 52661 self.maxY = maxY = minY; 52662 minY = self.minY; 52663 } 52664 52665 if (rotationMode) { 52666 self.minRotation = minX; 52667 self.maxRotation = maxX; 52668 } 52669 52670 hasBounds = true; 52671 } 52672 52673 if (vars.liveSnap) { 52674 snap = vars.liveSnap === true ? vars.snap || {} : vars.liveSnap; 52675 snapIsRaw = _isArray(snap) || _isFunction(snap); 52676 52677 if (rotationMode) { 52678 snapX = buildSnapFunc(snapIsRaw ? snap : snap.rotation, minX, maxX, 1); 52679 snapY = null; 52680 } else { 52681 if (snap.points) { 52682 snapXY = buildPointSnapFunc(snapIsRaw ? snap : snap.points, minX, maxX, minY, maxY, snap.radius, scrollProxy ? -1 : 1); 52683 } else { 52684 if (allowX) { 52685 snapX = buildSnapFunc(snapIsRaw ? snap : snap.x || snap.left || snap.scrollLeft, minX, maxX, scrollProxy ? -1 : 1); 52686 } 52687 52688 if (allowY) { 52689 snapY = buildSnapFunc(snapIsRaw ? snap : snap.y || snap.top || snap.scrollTop, minY, maxY, scrollProxy ? -1 : 1); 52690 } 52691 } 52692 } 52693 } 52694 }, 52695 onThrowComplete = function onThrowComplete() { 52696 self.isThrowing = false; 52697 52698 _dispatchEvent(self, "throwcomplete", "onThrowComplete"); 52699 }, 52700 onThrowInterrupt = function onThrowInterrupt() { 52701 self.isThrowing = false; 52702 }, 52703 animate = function animate(inertia, forceZeroVelocity) { 52704 var snap, snapIsRaw, tween, overshootTolerance; 52705 52706 if (inertia && InertiaPlugin) { 52707 if (inertia === true) { 52708 snap = vars.snap || vars.liveSnap || {}; 52709 snapIsRaw = _isArray(snap) || _isFunction(snap); 52710 inertia = { 52711 resistance: (vars.throwResistance || vars.resistance || 1000) / (rotationMode ? 10 : 1) 52712 }; 52713 52714 if (rotationMode) { 52715 inertia.rotation = _parseInertia(self, snapIsRaw ? snap : snap.rotation, maxX, minX, 1, forceZeroVelocity); 52716 } else { 52717 if (allowX) { 52718 inertia[xProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.x || snap.left, maxX, minX, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "x"); 52719 } 52720 52721 if (allowY) { 52722 inertia[yProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.y || snap.top, maxY, minY, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "y"); 52723 } 52724 52725 if (snap.points || _isArray(snap) && _isObject(snap[0])) { 52726 inertia.linkedProps = xProp + "," + yProp; 52727 inertia.radius = snap.radius; 52728 } 52729 } 52730 } 52731 52732 self.isThrowing = true; 52733 overshootTolerance = !isNaN(vars.overshootTolerance) ? vars.overshootTolerance : vars.edgeResistance === 1 ? 0 : 1 - self.edgeResistance + 0.2; 52734 52735 if (!inertia.duration) { 52736 inertia.duration = { 52737 max: Math.max(vars.minDuration || 0, "maxDuration" in vars ? vars.maxDuration : 2), 52738 min: !isNaN(vars.minDuration) ? vars.minDuration : overshootTolerance === 0 || _isObject(inertia) && inertia.resistance > 1000 ? 0 : 0.5, 52739 overshoot: overshootTolerance 52740 }; 52741 } 52742 52743 self.tween = tween = gsap.to(scrollProxy || target, { 52744 inertia: inertia, 52745 data: "_draggable", 52746 inherit: false, 52747 onComplete: onThrowComplete, 52748 onInterrupt: onThrowInterrupt, 52749 onUpdate: vars.fastMode ? _dispatchEvent : syncXY, 52750 onUpdateParams: vars.fastMode ? [self, "onthrowupdate", "onThrowUpdate"] : snap && snap.radius ? [false, true] : [] 52751 }); 52752 52753 if (!vars.fastMode) { 52754 if (scrollProxy) { 52755 scrollProxy._skip = true; 52756 } 52757 52758 tween.render(1e9, true, true); 52759 syncXY(true, true); 52760 self.endX = self.x; 52761 self.endY = self.y; 52762 52763 if (rotationMode) { 52764 self.endRotation = self.x; 52765 } 52766 52767 tween.play(0); 52768 syncXY(true, true); 52769 52770 if (scrollProxy) { 52771 scrollProxy._skip = false; 52772 } 52773 } 52774 } else if (hasBounds) { 52775 self.applyBounds(); 52776 } 52777 }, 52778 updateMatrix = function updateMatrix(shiftStart) { 52779 var start = matrix, 52780 p; 52781 matrix = getGlobalMatrix(target.parentNode, true); 52782 52783 if (shiftStart && self.isPressed && !matrix.equals(start || new Matrix2D())) { 52784 p = start.inverse().apply({ 52785 x: startPointerX, 52786 y: startPointerY 52787 }); 52788 matrix.apply(p, p); 52789 startPointerX = p.x; 52790 startPointerY = p.y; 52791 } 52792 52793 if (matrix.equals(_identityMatrix$1)) { 52794 matrix = null; 52795 } 52796 }, 52797 recordStartPositions = function recordStartPositions() { 52798 var edgeTolerance = 1 - self.edgeResistance, 52799 offsetX = isFixed ? _getDocScrollLeft$1(ownerDoc) : 0, 52800 offsetY = isFixed ? _getDocScrollTop$1(ownerDoc) : 0, 52801 parsedOrigin, 52802 x, 52803 y; 52804 52805 if (xyMode) { 52806 gsCache.x = getPropAsNum(xProp, "px") + "px"; 52807 gsCache.y = getPropAsNum(yProp, "px") + "px"; 52808 gsCache.renderTransform(); 52809 } 52810 52811 updateMatrix(false); 52812 _point1.x = self.pointerX - offsetX; 52813 _point1.y = self.pointerY - offsetY; 52814 matrix && matrix.apply(_point1, _point1); 52815 startPointerX = _point1.x; 52816 startPointerY = _point1.y; 52817 52818 if (dirty) { 52819 setPointerPosition(self.pointerX, self.pointerY); 52820 render(true); 52821 } 52822 52823 innerMatrix = getGlobalMatrix(target); 52824 52825 if (scrollProxy) { 52826 calculateBounds(); 52827 startElementY = scrollProxy.top(); 52828 startElementX = scrollProxy.left(); 52829 } else { 52830 if (isTweening()) { 52831 syncXY(true, true); 52832 calculateBounds(); 52833 } else { 52834 self.applyBounds(); 52835 } 52836 52837 if (rotationMode) { 52838 parsedOrigin = target.ownerSVGElement ? [gsCache.xOrigin - target.getBBox().x, gsCache.yOrigin - target.getBBox().y] : (_getComputedStyle(target)[_transformOriginProp$1] || "0 0").split(" "); 52839 rotationOrigin = self.rotationOrigin = getGlobalMatrix(target).apply({ 52840 x: parseFloat(parsedOrigin[0]) || 0, 52841 y: parseFloat(parsedOrigin[1]) || 0 52842 }); 52843 syncXY(true, true); 52844 x = self.pointerX - rotationOrigin.x - offsetX; 52845 y = rotationOrigin.y - self.pointerY + offsetY; 52846 startElementX = self.x; 52847 startElementY = self.y = Math.atan2(y, x) * _RAD2DEG; 52848 } else { 52849 startElementY = getPropAsNum(yProp, "px"); 52850 startElementX = getPropAsNum(xProp, "px"); 52851 } 52852 } 52853 52854 if (hasBounds && edgeTolerance) { 52855 if (startElementX > maxX) { 52856 startElementX = maxX + (startElementX - maxX) / edgeTolerance; 52857 } else if (startElementX < minX) { 52858 startElementX = minX - (minX - startElementX) / edgeTolerance; 52859 } 52860 52861 if (!rotationMode) { 52862 if (startElementY > maxY) { 52863 startElementY = maxY + (startElementY - maxY) / edgeTolerance; 52864 } else if (startElementY < minY) { 52865 startElementY = minY - (minY - startElementY) / edgeTolerance; 52866 } 52867 } 52868 } 52869 52870 self.startX = startElementX = _round(startElementX); 52871 self.startY = startElementY = _round(startElementY); 52872 }, 52873 isTweening = function isTweening() { 52874 return self.tween && self.tween.isActive(); 52875 }, 52876 removePlaceholder = function removePlaceholder() { 52877 if (_placeholderDiv.parentNode && !isTweening() && !self.isDragging) { 52878 _placeholderDiv.parentNode.removeChild(_placeholderDiv); 52879 } 52880 }, 52881 onPress = function onPress(e, force) { 52882 var i; 52883 52884 if (!enabled || self.isPressed || !e || (e.type === "mousedown" || e.type === "pointerdown") && !force && _getTime() - clickTime < 30 && _touchEventLookup[self.pointerEvent.type]) { 52885 isPreventingDefault && e && enabled && _preventDefault(e); 52886 return; 52887 } 52888 52889 interrupted = isTweening(); 52890 dragged = false; 52891 self.pointerEvent = e; 52892 52893 if (_touchEventLookup[e.type]) { 52894 touchEventTarget = ~e.type.indexOf("touch") ? e.currentTarget || e.target : ownerDoc; 52895 52896 _addListener(touchEventTarget, "touchend", onRelease); 52897 52898 _addListener(touchEventTarget, "touchmove", onMove); 52899 52900 _addListener(touchEventTarget, "touchcancel", onRelease); 52901 52902 _addListener(ownerDoc, "touchstart", _onMultiTouchDocument); 52903 } else { 52904 touchEventTarget = null; 52905 52906 _addListener(ownerDoc, "mousemove", onMove); 52907 } 52908 52909 touchDragAxis = null; 52910 52911 if (!_supportsPointer || !touchEventTarget) { 52912 _addListener(ownerDoc, "mouseup", onRelease); 52913 52914 e && e.target && _addListener(e.target, "mouseup", onRelease); 52915 } 52916 52917 isClicking = isClickable.call(self, e.target) && vars.dragClickables === false && !force; 52918 52919 if (isClicking) { 52920 _addListener(e.target, "change", onRelease); 52921 52922 _dispatchEvent(self, "pressInit", "onPressInit"); 52923 52924 _dispatchEvent(self, "press", "onPress"); 52925 52926 _setSelectable(triggers, true); 52927 52928 isPreventingDefault = false; 52929 return; 52930 } 52931 52932 allowNativeTouchScrolling = !touchEventTarget || allowX === allowY || self.vars.allowNativeTouchScrolling === false || self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2) ? false : allowX ? "y" : "x"; 52933 isPreventingDefault = !allowNativeTouchScrolling && !self.allowEventDefault; 52934 52935 if (isPreventingDefault) { 52936 _preventDefault(e); 52937 52938 _addListener(_win$1, "touchforcechange", _preventDefault); 52939 } 52940 52941 if (e.changedTouches) { 52942 e = touch = e.changedTouches[0]; 52943 touchID = e.identifier; 52944 } else if (e.pointerId) { 52945 touchID = e.pointerId; 52946 } else { 52947 touch = touchID = null; 52948 } 52949 52950 _dragCount++; 52951 52952 _addToRenderQueue(render); 52953 52954 startPointerY = self.pointerY = e.pageY; 52955 startPointerX = self.pointerX = e.pageX; 52956 52957 _dispatchEvent(self, "pressInit", "onPressInit"); 52958 52959 if (allowNativeTouchScrolling || self.autoScroll) { 52960 _recordMaxScrolls(target.parentNode); 52961 } 52962 52963 if (target.parentNode && self.autoScroll && !scrollProxy && !rotationMode && target.parentNode._gsMaxScrollX && !_placeholderDiv.parentNode && !target.getBBox) { 52964 _placeholderDiv.style.width = target.parentNode.scrollWidth + "px"; 52965 target.parentNode.appendChild(_placeholderDiv); 52966 } 52967 52968 recordStartPositions(); 52969 self.tween && self.tween.kill(); 52970 self.isThrowing = false; 52971 gsap.killTweensOf(scrollProxy || target, killProps, true); 52972 scrollProxy && gsap.killTweensOf(target, { 52973 scrollTo: 1 52974 }, true); 52975 self.tween = self.lockedAxis = null; 52976 52977 if (vars.zIndexBoost || !rotationMode && !scrollProxy && vars.zIndexBoost !== false) { 52978 target.style.zIndex = Draggable.zIndex++; 52979 } 52980 52981 self.isPressed = true; 52982 hasDragCallback = !!(vars.onDrag || self._listeners.drag); 52983 hasMoveCallback = !!(vars.onMove || self._listeners.move); 52984 52985 if (vars.cursor !== false || vars.activeCursor) { 52986 i = triggers.length; 52987 52988 while (--i > -1) { 52989 gsap.set(triggers[i], { 52990 cursor: vars.activeCursor || vars.cursor || (_defaultCursor === "grab" ? "grabbing" : _defaultCursor) 52991 }); 52992 } 52993 } 52994 52995 _dispatchEvent(self, "press", "onPress");
vendor: 2,447 bytes, lines 52996-53063
52996 }, 52997 onMove = function onMove(e) { 52998 var originalEvent = e, 52999 touches, 53000 pointerX, 53001 pointerY, 53002 i, 53003 dx, 53004 dy; 53005 53006 if (!enabled || _isMultiTouching || !self.isPressed || !e) { 53007 isPreventingDefault && e && enabled && _preventDefault(e); 53008 return; 53009 } 53010 53011 self.pointerEvent = e; 53012 touches = e.changedTouches; 53013 53014 if (touches) { 53015 e = touches[0]; 53016 53017 if (e !== touch && e.identifier !== touchID) { 53018 i = touches.length; 53019 53020 while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {} 53021 53022 if (i < 0) { 53023 return; 53024 } 53025 } 53026 } else if (e.pointerId && touchID && e.pointerId !== touchID) { 53027 return; 53028 } 53029 53030 if (touchEventTarget && allowNativeTouchScrolling && !touchDragAxis) { 53031 _point1.x = e.pageX - (isFixed ? _getDocScrollLeft$1(ownerDoc) : 0); 53032 _point1.y = e.pageY - (isFixed ? _getDocScrollTop$1(ownerDoc) : 0); 53033 matrix && matrix.apply(_point1, _point1); 53034 pointerX = _point1.x; 53035 pointerY = _point1.y; 53036 dx = Math.abs(pointerX - startPointerX); 53037 dy = Math.abs(pointerY - startPointerY); 53038 53039 if (dx !== dy && (dx > minimumMovement || dy > minimumMovement) || _isAndroid && allowNativeTouchScrolling === touchDragAxis) { 53040 touchDragAxis = dx > dy && allowX ? "x" : "y"; 53041 53042 if (allowNativeTouchScrolling && touchDragAxis !== allowNativeTouchScrolling) { 53043 _addListener(_win$1, "touchforcechange", _preventDefault); 53044 } 53045 53046 if (self.vars.lockAxisOnTouchScroll !== false && allowX && allowY) { 53047 self.lockedAxis = touchDragAxis === "x" ? "y" : "x"; 53048 _isFunction(self.vars.onLockAxis) && self.vars.onLockAxis.call(self, originalEvent); 53049 } 53050 53051 if (_isAndroid && allowNativeTouchScrolling === touchDragAxis) { 53052 onRelease(originalEvent); 53053 return; 53054 } 53055 } 53056 } 53057 53058 if (!self.allowEventDefault && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling !== touchDragAxis) && originalEvent.cancelable !== false) { 53059 _preventDefault(originalEvent); 53060 53061 isPreventingDefault = true; 53062 } else if (isPreventingDefault) { 53063 isPreventingDefault = false;
vendor: 3,917 bytes, lines 53064-53192
53064 } 53065 53066 if (self.autoScroll) { 53067 checkAutoScrollBounds = true; 53068 } 53069 53070 setPointerPosition(e.pageX, e.pageY, hasMoveCallback); 53071 }, 53072 setPointerPosition = function setPointerPosition(pointerX, pointerY, invokeOnMove) { 53073 var dragTolerance = 1 - self.dragResistance, 53074 edgeTolerance = 1 - self.edgeResistance, 53075 prevPointerX = self.pointerX, 53076 prevPointerY = self.pointerY, 53077 prevStartElementY = startElementY, 53078 prevX = self.x, 53079 prevY = self.y, 53080 prevEndX = self.endX, 53081 prevEndY = self.endY, 53082 prevEndRotation = self.endRotation, 53083 prevDirty = dirty, 53084 xChange, 53085 yChange, 53086 x, 53087 y, 53088 dif, 53089 temp; 53090 self.pointerX = pointerX; 53091 self.pointerY = pointerY; 53092 53093 if (isFixed) { 53094 pointerX -= _getDocScrollLeft$1(ownerDoc); 53095 pointerY -= _getDocScrollTop$1(ownerDoc); 53096 } 53097 53098 if (rotationMode) { 53099 y = Math.atan2(rotationOrigin.y - pointerY, pointerX - rotationOrigin.x) * _RAD2DEG; 53100 dif = self.y - y; 53101 53102 if (dif > 180) { 53103 startElementY -= 360; 53104 self.y = y; 53105 } else if (dif < -180) { 53106 startElementY += 360; 53107 self.y = y; 53108 } 53109 53110 if (self.x !== startElementX || Math.abs(startElementY - y) > minimumMovement) { 53111 self.y = y; 53112 x = startElementX + (startElementY - y) * dragTolerance; 53113 } else { 53114 x = startElementX; 53115 } 53116 } else { 53117 if (matrix) { 53118 temp = pointerX * matrix.a + pointerY * matrix.c + matrix.e; 53119 pointerY = pointerX * matrix.b + pointerY * matrix.d + matrix.f; 53120 pointerX = temp; 53121 } 53122 53123 yChange = pointerY - startPointerY; 53124 xChange = pointerX - startPointerX; 53125 53126 if (yChange < minimumMovement && yChange > -minimumMovement) { 53127 yChange = 0; 53128 } 53129 53130 if (xChange < minimumMovement && xChange > -minimumMovement) { 53131 xChange = 0; 53132 } 53133 53134 if ((self.lockAxis || self.lockedAxis) && (xChange || yChange)) { 53135 temp = self.lockedAxis; 53136 53137 if (!temp) { 53138 self.lockedAxis = temp = allowX && Math.abs(xChange) > Math.abs(yChange) ? "y" : allowY ? "x" : null; 53139 53140 if (temp && _isFunction(self.vars.onLockAxis)) { 53141 self.vars.onLockAxis.call(self, self.pointerEvent); 53142 } 53143 } 53144 53145 if (temp === "y") { 53146 yChange = 0; 53147 } else if (temp === "x") { 53148 xChange = 0; 53149 } 53150 } 53151 53152 x = _round(startElementX + xChange * dragTolerance); 53153 y = _round(startElementY + yChange * dragTolerance); 53154 } 53155 53156 if ((snapX || snapY || snapXY) && (self.x !== x || self.y !== y && !rotationMode)) { 53157 if (snapXY) { 53158 _temp1.x = x; 53159 _temp1.y = y; 53160 temp = snapXY(_temp1); 53161 x = _round(temp.x); 53162 y = _round(temp.y); 53163 } 53164 53165 if (snapX) { 53166 x = _round(snapX(x)); 53167 } 53168 53169 if (snapY) { 53170 y = _round(snapY(y)); 53171 } 53172 } 53173 53174 if (hasBounds) { 53175 if (x > maxX) { 53176 x = maxX + Math.round((x - maxX) * edgeTolerance); 53177 } else if (x < minX) { 53178 x = minX + Math.round((x - minX) * edgeTolerance); 53179 } 53180 53181 if (!rotationMode) { 53182 if (y > maxY) { 53183 y = Math.round(maxY + (y - maxY) * edgeTolerance); 53184 } else if (y < minY) { 53185 y = Math.round(minY + (y - minY) * edgeTolerance); 53186 } 53187 } 53188 } 53189 53190 if (self.x !== x || self.y !== y && !rotationMode) { 53191 if (rotationMode) { 53192 self.endRotation = self.x = self.endX = x
vendor: 13,666 bytes, lines 53192-53599
53192; 53193 dirty = true; 53194 } else { 53195 if (allowY) { 53196 self.y = self.endY = y; 53197 dirty = true; 53198 } 53199 53200 if (allowX) { 53201 self.x = self.endX = x; 53202 dirty = true; 53203 } 53204 } 53205 53206 if (!invokeOnMove || _dispatchEvent(self, "move", "onMove") !== false) { 53207 if (!self.isDragging && self.isPressed) { 53208 self.isDragging = dragged = true; 53209 53210 _dispatchEvent(self, "dragstart", "onDragStart"); 53211 } 53212 } else { 53213 self.pointerX = prevPointerX; 53214 self.pointerY = prevPointerY; 53215 startElementY = prevStartElementY; 53216 self.x = prevX; 53217 self.y = prevY; 53218 self.endX = prevEndX; 53219 self.endY = prevEndY; 53220 self.endRotation = prevEndRotation; 53221 dirty = prevDirty; 53222 } 53223 } 53224 }, 53225 onRelease = function onRelease(e, force) { 53226 if (!enabled || !self.isPressed || e && touchID != null && !force && (e.pointerId && e.pointerId !== touchID && e.target !== target || e.changedTouches && !_hasTouchID(e.changedTouches, touchID))) { 53227 isPreventingDefault && e && enabled && _preventDefault(e); 53228 return; 53229 } 53230 53231 self.isPressed = false; 53232 var originalEvent = e, 53233 wasDragging = self.isDragging, 53234 isContextMenuRelease = self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2), 53235 placeholderDelayedCall = gsap.delayedCall(0.001, removePlaceholder), 53236 touches, 53237 i, 53238 syntheticEvent, 53239 eventTarget, 53240 syntheticClick; 53241 53242 if (touchEventTarget) { 53243 _removeListener(touchEventTarget, "touchend", onRelease); 53244 53245 _removeListener(touchEventTarget, "touchmove", onMove); 53246 53247 _removeListener(touchEventTarget, "touchcancel", onRelease); 53248 53249 _removeListener(ownerDoc, "touchstart", _onMultiTouchDocument); 53250 } else { 53251 _removeListener(ownerDoc, "mousemove", onMove); 53252 } 53253 53254 _removeListener(_win$1, "touchforcechange", _preventDefault); 53255 53256 if (!_supportsPointer || !touchEventTarget) { 53257 _removeListener(ownerDoc, "mouseup", onRelease); 53258 53259 e && e.target && _removeListener(e.target, "mouseup", onRelease); 53260 } 53261 53262 dirty = false; 53263 53264 if (wasDragging) { 53265 dragEndTime = _lastDragTime = _getTime(); 53266 self.isDragging = false; 53267 } 53268 53269 _removeFromRenderQueue(render); 53270 53271 if (isClicking && !isContextMenuRelease) { 53272 if (e) { 53273 _removeListener(e.target, "change", onRelease); 53274 53275 self.pointerEvent = originalEvent; 53276 } 53277 53278 _setSelectable(triggers, false); 53279 53280 _dispatchEvent(self, "release", "onRelease"); 53281 53282 _dispatchEvent(self, "click", "onClick"); 53283 53284 isClicking = false; 53285 return; 53286 } 53287 53288 i = triggers.length; 53289 53290 while (--i > -1) { 53291 _setStyle(triggers[i], "cursor", vars.cursor || (vars.cursor !== false ? _defaultCursor : null)); 53292 } 53293 53294 _dragCount--; 53295 53296 if (e) { 53297 touches = e.changedTouches; 53298 53299 if (touches) { 53300 e = touches[0]; 53301 53302 if (e !== touch && e.identifier !== touchID) { 53303 i = touches.length; 53304 53305 while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {} 53306 53307 if (i < 0 && !force) { 53308 return; 53309 } 53310 } 53311 } 53312 53313 self.pointerEvent = originalEvent; 53314 self.pointerX = e.pageX; 53315 self.pointerY = e.pageY; 53316 } 53317 53318 if (isContextMenuRelease && originalEvent) { 53319 _preventDefault(originalEvent); 53320 53321 isPreventingDefault = true; 53322 53323 _dispatchEvent(self, "release", "onRelease"); 53324 } else if (originalEvent && !wasDragging) { 53325 isPreventingDefault = false; 53326 53327 if (interrupted && (vars.snap || vars.bounds)) { 53328 animate(vars.inertia || vars.throwProps); 53329 } 53330 53331 _dispatchEvent(self, "release", "onRelease"); 53332 53333 if ((!_isAndroid || originalEvent.type !== "touchmove") && originalEvent.type.indexOf("cancel") === -1) { 53334 _dispatchEvent(self, "click", "onClick"); 53335 53336 if (_getTime() - clickTime < 300) { 53337 _dispatchEvent(self, "doubleclick", "onDoubleClick"); 53338 } 53339 53340 eventTarget = originalEvent.target || target; 53341 clickTime = _getTime(); 53342 53343 syntheticClick = function syntheticClick() { 53344 if (clickTime !== clickDispatch && self.enabled() && !self.isPressed && !originalEvent.defaultPrevented) { 53345 if (eventTarget.click) { 53346 eventTarget.click(); 53347 } else if (ownerDoc.createEvent) { 53348 syntheticEvent = ownerDoc.createEvent("MouseEvents"); 53349 syntheticEvent.initMouseEvent("click", true, true, _win$1, 1, self.pointerEvent.screenX, self.pointerEvent.screenY, self.pointerX, self.pointerY, false, false, false, false, 0, null); 53350 eventTarget.dispatchEvent(syntheticEvent); 53351 } 53352 } 53353 }; 53354 53355 if (!_isAndroid && !originalEvent.defaultPrevented) { 53356 gsap.delayedCall(0.05, syntheticClick); 53357 } 53358 } 53359 } else { 53360 animate(vars.inertia || vars.throwProps); 53361 53362 if (!self.allowEventDefault && originalEvent && (vars.dragClickables !== false || !isClickable.call(self, originalEvent.target)) && wasDragging && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling === touchDragAxis) && originalEvent.cancelable !== false) { 53363 isPreventingDefault = true; 53364 53365 _preventDefault(originalEvent); 53366 } else { 53367 isPreventingDefault = false; 53368 } 53369 53370 _dispatchEvent(self, "release", "onRelease"); 53371 } 53372 53373 isTweening() && placeholderDelayedCall.duration(self.tween.duration()); 53374 wasDragging && _dispatchEvent(self, "dragend", "onDragEnd"); 53375 return true; 53376 }, 53377 updateScroll = function updateScroll(e) { 53378 if (e && self.isDragging && !scrollProxy) { 53379 var parent = e.target || target.parentNode, 53380 deltaX = parent.scrollLeft - parent._gsScrollX, 53381 deltaY = parent.scrollTop - parent._gsScrollY; 53382 53383 if (deltaX || deltaY) { 53384 if (matrix) { 53385 startPointerX -= deltaX * matrix.a + deltaY * matrix.c; 53386 startPointerY -= deltaY * matrix.d + deltaX * matrix.b; 53387 } else { 53388 startPointerX -= deltaX; 53389 startPointerY -= deltaY; 53390 } 53391 53392 parent._gsScrollX += deltaX; 53393 parent._gsScrollY += deltaY; 53394 setPointerPosition(self.pointerX, self.pointerY); 53395 } 53396 } 53397 }, 53398 onClick = function onClick(e) { 53399 var time = _getTime(), 53400 recentlyClicked = time - clickTime < 100, 53401 recentlyDragged = time - dragEndTime < 50, 53402 alreadyDispatched = recentlyClicked && clickDispatch === clickTime, 53403 defaultPrevented = self.pointerEvent && self.pointerEvent.defaultPrevented, 53404 alreadyDispatchedTrusted = recentlyClicked && trustedClickDispatch === clickTime, 53405 trusted = e.isTrusted || e.isTrusted == null && recentlyClicked && alreadyDispatched; 53406 53407 if ((alreadyDispatched || recentlyDragged && self.vars.suppressClickOnDrag !== false) && e.stopImmediatePropagation) { 53408 e.stopImmediatePropagation(); 53409 } 53410 53411 if (recentlyClicked && !(self.pointerEvent && self.pointerEvent.defaultPrevented) && (!alreadyDispatched || trusted && !alreadyDispatchedTrusted)) { 53412 if (trusted && alreadyDispatched) { 53413 trustedClickDispatch = clickTime; 53414 } 53415 53416 clickDispatch = clickTime; 53417 return; 53418 } 53419 53420 if (self.isPressed || recentlyDragged || recentlyClicked) { 53421 if (!trusted || !e.detail || !recentlyClicked || defaultPrevented) { 53422 _preventDefault(e); 53423 } 53424 } 53425 53426 if (!recentlyClicked && !recentlyDragged && !dragged) { 53427 e && e.target && (self.pointerEvent = e); 53428 53429 _dispatchEvent(self, "click", "onClick"); 53430 } 53431 }, 53432 localizePoint = function localizePoint(p) { 53433 return matrix ? { 53434 x: p.x * matrix.a + p.y * matrix.c + matrix.e, 53435 y: p.x * matrix.b + p.y * matrix.d + matrix.f 53436 } : { 53437 x: p.x, 53438 y: p.y 53439 }; 53440 }; 53441 53442 old = Draggable.get(target); 53443 old && old.kill(); 53444 53445 _this2.startDrag = function (event, align) { 53446 var r1, r2, p1, p2; 53447 onPress(event || self.pointerEvent, true); 53448 53449 if (align && !self.hitTest(event || self.pointerEvent)) { 53450 r1 = _parseRect(event || self.pointerEvent); 53451 r2 = _parseRect(target); 53452 p1 = localizePoint({ 53453 x: r1.left + r1.width / 2, 53454 y: r1.top + r1.height / 2 53455 }); 53456 p2 = localizePoint({ 53457 x: r2.left + r2.width / 2, 53458 y: r2.top + r2.height / 2 53459 }); 53460 startPointerX -= p1.x - p2.x; 53461 startPointerY -= p1.y - p2.y; 53462 } 53463 53464 if (!self.isDragging) { 53465 self.isDragging = dragged = true; 53466 53467 _dispatchEvent(self, "dragstart", "onDragStart"); 53468 } 53469 }; 53470 53471 _this2.drag = onMove; 53472 53473 _this2.endDrag = function (e) { 53474 return onRelease(e || self.pointerEvent, true); 53475 }; 53476 53477 _this2.timeSinceDrag = function () { 53478 return self.isDragging ? 0 : (_getTime() - dragEndTime) / 1000; 53479 }; 53480 53481 _this2.timeSinceClick = function () { 53482 return (_getTime() - clickTime) / 1000; 53483 }; 53484 53485 _this2.hitTest = function (target, threshold) { 53486 return Draggable.hitTest(self.target, target, threshold); 53487 }; 53488 53489 _this2.getDirection = function (from, diagonalThreshold) { 53490 var mode = from === "velocity" && InertiaPlugin ? from : _isObject(from) && !rotationMode ? "element" : "start", 53491 xChange, 53492 yChange, 53493 ratio, 53494 direction, 53495 r1, 53496 r2; 53497 53498 if (mode === "element") { 53499 r1 = _parseRect(self.target); 53500 r2 = _parseRect(from); 53501 } 53502 53503 xChange = mode === "start" ? self.x - startElementX : mode === "velocity" ? InertiaPlugin.getVelocity(target, xProp) : r1.left + r1.width / 2 - (r2.left + r2.width / 2); 53504 53505 if (rotationMode) { 53506 return xChange < 0 ? "counter-clockwise" : "clockwise"; 53507 } else { 53508 diagonalThreshold = diagonalThreshold || 2; 53509 yChange = mode === "start" ? self.y - startElementY : mode === "velocity" ? InertiaPlugin.getVelocity(target, yProp) : r1.top + r1.height / 2 - (r2.top + r2.height / 2); 53510 ratio = Math.abs(xChange / yChange); 53511 direction = ratio < 1 / diagonalThreshold ? "" : xChange < 0 ? "left" : "right"; 53512 53513 if (ratio < diagonalThreshold) { 53514 if (direction !== "") { 53515 direction += "-"; 53516 } 53517 53518 direction += yChange < 0 ? "up" : "down"; 53519 } 53520 } 53521 53522 return direction; 53523 }; 53524 53525 _this2.applyBounds = function (newBounds, sticky) { 53526 var x, y, forceZeroVelocity, e, parent, isRoot; 53527 53528 if (newBounds && vars.bounds !== newBounds) { 53529 vars.bounds = newBounds; 53530 return self.update(true, sticky); 53531 } 53532 53533 syncXY(true); 53534 calculateBounds(); 53535 53536 if (hasBounds && !isTweening()) { 53537 x = self.x; 53538 y = self.y; 53539 53540 if (x > maxX) { 53541 x = maxX; 53542 } else if (x < minX) { 53543 x = minX; 53544 } 53545 53546 if (y > maxY) { 53547 y = maxY; 53548 } else if (y < minY) { 53549 y = minY; 53550 } 53551 53552 if (self.x !== x || self.y !== y) { 53553 forceZeroVelocity = true; 53554 self.x = self.endX = x; 53555 53556 if (rotationMode) { 53557 self.endRotation = x; 53558 } else { 53559 self.y = self.endY = y; 53560 } 53561 53562 dirty = true; 53563 render(true); 53564 53565 if (self.autoScroll && !self.isDragging) { 53566 _recordMaxScrolls(target.parentNode); 53567 53568 e = target; 53569 _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop; 53570 _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft; 53571 53572 while (e && !isRoot) { 53573 isRoot = _isRoot(e.parentNode); 53574 parent = isRoot ? _windowProxy : e.parentNode; 53575 53576 if (allowY && parent.scrollTop > parent._gsMaxScrollY) { 53577 parent.scrollTop = parent._gsMaxScrollY; 53578 } 53579 53580 if (allowX && parent.scrollLeft > parent._gsMaxScrollX) { 53581 parent.scrollLeft = parent._gsMaxScrollX; 53582 } 53583 53584 e = parent; 53585 } 53586 } 53587 } 53588 53589 if (self.isThrowing && (forceZeroVelocity || self.endX > maxX || self.endX < minX || self.endY > maxY || self.endY < minY)) { 53590 animate(vars.inertia || vars.throwProps, forceZeroVelocity); 53591 } 53592 } 53593 53594 return self; 53595 }; 53596 53597 _this2.update = function (applyBounds, sticky, ignoreExternalChanges) { 53598 if (sticky && self.isPressed) { 53599
vendor: 3,070 bytes, lines 53599-53700
53599var m = getGlobalMatrix(target), 53600 p = innerMatrix.apply({ 53601 x: self.x - startElementX, 53602 y: self.y - startElementY 53603 }), 53604 m2 = getGlobalMatrix(target.parentNode, true); 53605 m2.apply({ 53606 x: m.e - p.x, 53607 y: m.f - p.y 53608 }, p); 53609 self.x -= p.x - m2.e; 53610 self.y -= p.y - m2.f; 53611 render(true); 53612 recordStartPositions(); 53613 } 53614 53615 var x = self.x, 53616 y = self.y; 53617 updateMatrix(!sticky); 53618 53619 if (applyBounds) { 53620 self.applyBounds(); 53621 } else { 53622 dirty && ignoreExternalChanges && render(true); 53623 syncXY(true); 53624 } 53625 53626 if (sticky) { 53627 setPointerPosition(self.pointerX, self.pointerY); 53628 dirty && render(true); 53629 } 53630 53631 if (self.isPressed && !sticky && (allowX && Math.abs(x - self.x) > 0.01 || allowY && Math.abs(y - self.y) > 0.01 && !rotationMode)) { 53632 recordStartPositions(); 53633 } 53634 53635 if (self.autoScroll) { 53636 _recordMaxScrolls(target.parentNode, self.isDragging); 53637 53638 checkAutoScrollBounds = self.isDragging; 53639 render(true); 53640 53641 _removeScrollListener(target, updateScroll); 53642 53643 _addScrollListener(target, updateScroll); 53644 } 53645 53646 return self; 53647 }; 53648 53649 _this2.enable = function (type) { 53650 var setVars = { 53651 lazy: true 53652 }, 53653 id, 53654 i, 53655 trigger; 53656 53657 if (vars.cursor !== false) { 53658 setVars.cursor = vars.cursor || _defaultCursor; 53659 } 53660 53661 if (gsap.utils.checkPrefix("touchCallout")) { 53662 setVars.touchCallout = "none"; 53663 } 53664 53665 if (type !== "soft") { 53666 _setTouchActionForAllDescendants(triggers, allowX === allowY ? "none" : vars.allowNativeTouchScrolling && target.scrollHeight === target.clientHeight === (target.scrollWidth === target.clientHeight) || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x"); 53667 53668 i = triggers.length; 53669 53670 while (--i > -1) { 53671 trigger = triggers[i]; 53672 _supportsPointer || _addListener(trigger, "mousedown", onPress); 53673 53674 _addListener(trigger, "touchstart", onPress); 53675 53676 _addListener(trigger, "click", onClick, true); 53677 53678 gsap.set(trigger, setVars); 53679 53680 if (trigger.getBBox && trigger.ownerSVGElement && allowX !== allowY) { 53681 gsap.set(trigger.ownerSVGElement, { 53682 touchAction: vars.allowNativeTouchScrolling || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x" 53683 }); 53684 } 53685 53686 vars.allowContextMenu || _addListener(trigger, "contextmenu", onContextMenu); 53687 } 53688 53689 _setSelectable(triggers, false); 53690 } 53691 53692 _addScrollListener(target, updateScroll); 53693 53694 enabled = true; 53695 53696 if (InertiaPlugin && type !== "soft") { 53697 InertiaPlugin.track(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left"); 53698 } 53699 53700 target._gsDragID = id =
vendor: 5,466 bytes, lines 53700-53906
53700 "d" + _lookupCount++; 53701 _lookup[id] = self; 53702 53703 if (scrollProxy) { 53704 scrollProxy.enable(); 53705 scrollProxy.element._gsDragID = id; 53706 } 53707 53708 (vars.bounds || rotationMode) && recordStartPositions(); 53709 vars.bounds && self.applyBounds(); 53710 return self; 53711 }; 53712 53713 _this2.disable = function (type) { 53714 var dragging = self.isDragging, 53715 i = triggers.length, 53716 trigger; 53717 53718 while (--i > -1) { 53719 _setStyle(triggers[i], "cursor", null); 53720 } 53721 53722 if (type !== "soft") { 53723 _setTouchActionForAllDescendants(triggers, null); 53724 53725 i = triggers.length; 53726 53727 while (--i > -1) { 53728 trigger = triggers[i]; 53729 53730 _setStyle(trigger, "touchCallout", null); 53731 53732 _removeListener(trigger, "mousedown", onPress); 53733 53734 _removeListener(trigger, "touchstart", onPress); 53735 53736 _removeListener(trigger, "click", onClick, true); 53737 53738 _removeListener(trigger, "contextmenu", onContextMenu); 53739 } 53740 53741 _setSelectable(triggers, true); 53742 53743 if (touchEventTarget) { 53744 _removeListener(touchEventTarget, "touchcancel", onRelease); 53745 53746 _removeListener(touchEventTarget, "touchend", onRelease); 53747 53748 _removeListener(touchEventTarget, "touchmove", onMove); 53749 } 53750 53751 _removeListener(ownerDoc, "mouseup", onRelease); 53752 53753 _removeListener(ownerDoc, "mousemove", onMove); 53754 } 53755 53756 _removeScrollListener(target, updateScroll); 53757 53758 enabled = false; 53759 53760 if (InertiaPlugin && type !== "soft") { 53761 InertiaPlugin.untrack(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left"); 53762 self.tween && self.tween.kill(); 53763 } 53764 53765 scrollProxy && scrollProxy.disable(); 53766 53767 _removeFromRenderQueue(render); 53768 53769 self.isDragging = self.isPressed = isClicking = false; 53770 dragging && _dispatchEvent(self, "dragend", "onDragEnd"); 53771 return self; 53772 }; 53773 53774 _this2.enabled = function (value, type) { 53775 return arguments.length ? value ? self.enable(type) : self.disable(type) : enabled; 53776 }; 53777 53778 _this2.kill = function () { 53779 self.isThrowing = false; 53780 self.tween && self.tween.kill(); 53781 self.disable(); 53782 gsap.set(triggers, { 53783 clearProps: "userSelect" 53784 }); 53785 delete _lookup[target._gsDragID]; 53786 return self; 53787 }; 53788 53789 _this2.revert = function () { 53790 this.kill(); 53791 this.styles && this.styles.revert(); 53792 }; 53793 53794 if (~type.indexOf("scroll")) { 53795 scrollProxy = _this2.scrollProxy = new ScrollProxy(target, _extend({ 53796 onKill: function onKill() { 53797 self.isPressed && onRelease(null); 53798 } 53799 }, vars)); 53800 target.style.overflowY = allowY && !_isTouchDevice ? "auto" : "hidden"; 53801 target.style.overflowX = allowX && !_isTouchDevice ? "auto" : "hidden"; 53802 target = scrollProxy.content; 53803 } 53804 53805 if (rotationMode) { 53806 killProps.rotation = 1; 53807 } else { 53808 if (allowX) { 53809 killProps[xProp] = 1; 53810 } 53811 53812 if (allowY) { 53813 killProps[yProp] = 1; 53814 } 53815 } 53816 53817 gsCache.force3D = "force3D" in vars ? vars.force3D : true; 53818 53819 _context(_assertThisInitialized(_this2)); 53820 53821 _this2.enable(); 53822 53823 return _this2; 53824 } 53825 53826 Draggable.register = function register(core) { 53827 gsap = core; 53828 53829 _initCore(); 53830 }; 53831 53832 Draggable.create = function create(targets, vars) { 53833 _coreInitted || _initCore(true); 53834 return _toArray(targets).map(function (target) { 53835 return new Draggable(target, vars); 53836 }); 53837 }; 53838 53839 Draggable.get = function get(target) { 53840 return _lookup[(_toArray(target)[0] || {})._gsDragID]; 53841 }; 53842 53843 Draggable.timeSinceDrag = function timeSinceDrag() { 53844 return (_getTime() - _lastDragTime) / 1000; 53845 }; 53846 53847 Draggable.hitTest = function hitTest(obj1, obj2, threshold) { 53848 if (obj1 === obj2) { 53849 return false; 53850 } 53851 53852 var r1 = _parseRect(obj1), 53853 r2 = _parseRect(obj2), 53854 top = r1.top, 53855 left = r1.left, 53856 right = r1.right, 53857 bottom = r1.bottom, 53858 width = r1.width, 53859 height = r1.height, 53860 isOutside = r2.left > right || r2.right < left || r2.top > bottom || r2.bottom < top, 53861 overlap, 53862 area, 53863 isRatio; 53864 53865 if (isOutside || !threshold) { 53866 return !isOutside; 53867 } 53868 53869 isRatio = (threshold + "").indexOf("%") !== -1; 53870 threshold = parseFloat(threshold) || 0; 53871 overlap = { 53872 left: Math.max(left, r2.left), 53873 top: Math.max(top, r2.top) 53874 }; 53875 overlap.width = Math.min(right, r2.right) - overlap.left; 53876 overlap.height = Math.min(bottom, r2.bottom) - overlap.top; 53877 53878 if (overlap.width < 0 || overlap.height < 0) { 53879 return false; 53880 } 53881 53882 if (isRatio) { 53883 threshold *= 0.01; 53884 area = overlap.width * overlap.height; 53885 return area >= width * height * threshold || area >= r2.width * r2.height * threshold; 53886 } 53887 53888 return overlap.width > threshold && overlap.height > threshold; 53889 }; 53890 53891 return Draggable; 53892 }(EventDispatcher); 53893 53894 _setDefaults(Draggable.prototype, { 53895 pointerX: 0, 53896 pointerY: 0, 53897 startX: 0, 53898 startY: 0, 53899 deltaX: 0, 53900 deltaY: 0, 53901 isDragging: false, 53902 isPressed: false 53903 }); 53904 53905 Draggable.zIndex = 1000; 53906 Draggable.version = "3.1
vendor: 15,817 bytes, lines 53906-54449
539062.5"; 53907 _getGSAP() && gsap.registerPlugin(Draggable); 53908 53909 exports.Draggable = Draggable; 53910 exports.default = Draggable; 53911 53912 if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;} 53913 53914}))); 53915/* ======================================================================== 53916 * Bootstrap: collapse.js v3.1.1 53917 * http://getbootstrap.com/javascript/#collapse 53918 * ======================================================================== 53919 * Copyright 2011-2014 Twitter, Inc. 53920 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 53921 * ======================================================================== */ 53922 53923 53924+function ($) { 53925 'use strict'; 53926 53927 // COLLAPSE PUBLIC CLASS DEFINITION 53928 // ================================ 53929 53930 var Collapse = function (element, options) { 53931 this.$element = $(element) 53932 this.options = $.extend({}, Collapse.DEFAULTS, options) 53933 this.transitioning = null 53934 53935 if (this.options.parent) this.$parent = $(this.options.parent) 53936 if (this.options.toggle) this.toggle() 53937 } 53938 53939 Collapse.DEFAULTS = { 53940 toggle: true 53941 } 53942 53943 Collapse.prototype.dimension = function () { 53944 var hasWidth = this.$element.hasClass('width') 53945 return hasWidth ? 'width' : 'height' 53946 } 53947 53948 Collapse.prototype.show = function () { 53949 if (this.transitioning || this.$element.hasClass('in')) return 53950 53951 var startEvent = $.Event('show.bs.collapse') 53952 this.$element.trigger(startEvent) 53953 if (startEvent.isDefaultPrevented()) return 53954 53955 var actives = this.$parent && this.$parent.find('> .panel > .in') 53956 53957 if (actives && actives.length) { 53958 var hasData = actives.data('bs.collapse') 53959 if (hasData && hasData.transitioning) return 53960 //START UNCODE EDIT 53961 var parentNoToggle = this.$parent.data('no-toggle') 53962 if (!parentNoToggle) { 53963 actives.collapse('hide') 53964 } 53965 //END UNCODE EDIT 53966 hasData || actives.data('bs.collapse', null) 53967 } 53968 53969 var dimension = this.dimension() 53970 53971 this.$element 53972 .removeClass('collapse') 53973 .addClass('collapsing')[dimension](0) 53974 53975 this.transitioning = 1 53976 53977 var complete = function (e) { 53978 if (e && e.target != this.$element[0]) return 53979 this.$element 53980 .removeClass('collapsing') 53981 .addClass('collapse in')[dimension]('auto') 53982 this.transitioning = 0 53983 this.$element.trigger('shown.bs.collapse') 53984 } 53985 53986 if (!$.support.transition) return complete.call(this) 53987 53988 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 53989 53990 this.$element 53991 .one($.support.transition.end, $.proxy(complete, this)) 53992 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 53993 } 53994 53995 Collapse.prototype.hide = function () { 53996 if (this.transitioning || !this.$element.hasClass('in')) return 53997 53998 var startEvent = $.Event('hide.bs.collapse') 53999 this.$element.trigger(startEvent) 54000 if (startEvent.isDefaultPrevented()) return 54001 54002 var dimension = this.dimension() 54003 54004 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 54005 54006 this.$element 54007 .addClass('collapsing') 54008 .removeClass('collapse') 54009 .removeClass('in') 54010 54011 this.transitioning = 1 54012 54013 var complete = function (e) { 54014 if (e && e.target != this.$element[0]) return 54015 this.transitioning = 0 54016 this.$element 54017 .trigger('hidden.bs.collapse') 54018 .removeClass('collapsing') 54019 .addClass('collapse') 54020 } 54021 54022 if (!$.support.transition) return complete.call(this) 54023 54024 this.$element 54025 [dimension](0) 54026 .one($.support.transition.end, $.proxy(complete, this)) 54027 .emulateTransitionEnd(350) 54028 } 54029 54030 Collapse.prototype.toggle = function () { 54031 this[this.$element.hasClass('in') ? 'hide' : 'show']() 54032 } 54033 54034 54035 // COLLAPSE PLUGIN DEFINITION 54036 // ========================== 54037 54038 var old = $.fn.collapse 54039 54040 $.fn.collapse = function (option) { 54041 return this.each(function () { 54042 var $this = $(this) 54043 var data = $this.data('bs.collapse') 54044 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 54045 54046 if (!data && options.toggle && option == 'show') option = !option 54047 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 54048 if (typeof option == 'string') data[option]() 54049 }) 54050 } 54051 54052 $.fn.collapse.Constructor = Collapse 54053 54054 54055 // COLLAPSE NO CONFLICT 54056 // ==================== 54057 54058 $.fn.collapse.noConflict = function () { 54059 $.fn.collapse = old 54060 return this 54061 } 54062 54063 54064 // COLLAPSE DATA-API 54065 // ================= 54066 54067 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 54068 var $this = $(this), href 54069 var target = $this.attr('data-target') 54070 || e.preventDefault() 54071 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 54072 //Edited by Uncode to replace ID in panel [START] 54073 var _target = href.replace(/^#/, ""); 54074 if ( $('[data-id="' + _target + '"]').length ) { 54075 var $target = $('[data-id="' + _target + '"]') 54076 } else { 54077 var $target = $(target) 54078 } 54079 //Edited by Uncode to replace ID in panel [END] 54080 var data = $target.data('bs.collapse') 54081 var option = data ? 'toggle' : $this.data() 54082 var parent = $this.attr('data-parent') 54083 var $parent = parent && $(parent) 54084 54085 if (!data || !data.transitioning) { 54086 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 54087 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 54088 } 54089 54090 $target.collapse(option) 54091 }) 54092 54093}(jQuery); 54094 54095/* ======================================================================== 54096 * Bootstrap: tab.js v3.1.1 54097 * http://getbootstrap.com/javascript/#tabs 54098 * ======================================================================== 54099 * Copyright 2011-2014 Twitter, Inc. 54100 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 54101 * ======================================================================== */ 54102 54103 54104+function ($) { 54105 'use strict'; 54106 54107 // TAB CLASS DEFINITION 54108 // ==================== 54109 54110 var Tab = function (element) { 54111 this.element = $(element) 54112 } 54113 54114 Tab.prototype.show = function () { 54115 var $this = this.element 54116 var $ul = $this.closest('ul:not(.dropdown-menu)') 54117 var selector = $this.data('target') 54118 54119 if (!selector) { 54120 selector = $this.attr('href') 54121 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 54122 } 54123 54124 if ($this.parent('li').hasClass('active')) return 54125 54126 var previous = $ul.find('.active:last a')[0] 54127 var e = $.Event('show.bs.tab', { 54128 relatedTarget: previous 54129 }) 54130 54131 $this.trigger(e) 54132 54133 if (e.isDefaultPrevented()) return 54134 54135 //Edited by Uncode to replace ID in panel [START] 54136 var _target = selector.replace(/^#/, ""); 54137 if ( $('[data-id="' + _target + '"]').length ) 54138 var $target = $('[data-id="' + _target + '"]') 54139 else 54140 var $target = $(selector) 54141 //Edited by Uncode to replace ID in panel [END] 54142 54143 this.activate($this.parent('li'), $ul) 54144 this.activate($target, $target.parent(), function () { 54145 $this.trigger({ 54146 type: 'shown.bs.tab', 54147 relatedTarget: previous 54148 }) 54149 }) 54150 } 54151 54152 Tab.prototype.activate = function (element, container, callback) { 54153 var $active = container.find('> .active').add(container.find('> .active > .active')) 54154 var transition = callback 54155 && $.support.transition 54156 && $active.hasClass('fade') 54157 54158 function next() { 54159 $active 54160 .removeClass('active') 54161 .find('> .dropdown-menu > .active') 54162 .removeClass('active') 54163 54164 $active 54165 .find('.tab-excerpt').slideUp(); 54166 54167 element.addClass('active') 54168 $('.tab-excerpt', element).slideDown(); 54169 54170 //if (transition) { 54171 element[0].offsetWidth // reflow for transition 54172 element.add($active).addClass('in') 54173 /*} else { 54174 element.removeClass('fade') 54175 }*/ 54176 54177 if (element.parents('.dropdown-menu').length) { 54178 element.closest('li.dropdown').addClass('active') 54179 } 54180 54181 if ( ! element.is('li') ) { 54182 element.closest('.tab-content').find('> .active').not(element).removeClass('active'); 54183 } 54184 54185 callback && callback() 54186 } 54187 54188 transition ? 54189 $active 54190 .one($.support.transition.end, next) 54191 .emulateTransitionEnd(150) : 54192 next() 54193 54194 $active.removeClass('in') 54195 } 54196 54197 54198 // TAB PLUGIN DEFINITION 54199 // ===================== 54200 54201 var old = $.fn.tab 54202 54203 $.fn.tab = function ( option ) { 54204 return this.each(function () { 54205 var $this = $(this) 54206 var data = $this.data('bs.tab') 54207 54208 if (!data) $this.data('bs.tab', (data = new Tab(this))) 54209 if (typeof option == 'string') data[option]() 54210 }) 54211 } 54212 54213 $.fn.tab.Constructor = Tab 54214 54215 54216 // TAB NO CONFLICT 54217 // =============== 54218 54219 $.fn.tab.noConflict = function () { 54220 $.fn.tab = old 54221 return this 54222 } 54223 54224 54225 // TAB DATA-API 54226 // ============ 54227 54228 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 54229 e.preventDefault() 54230 $(this).tab('show') 54231 }) 54232 54233}(jQuery); 54234 54235/* ======================================================================== 54236 * Bootstrap: tooltip.js v3.1.1 54237 * http://getbootstrap.com/javascript/#tooltip 54238 * Inspired by the original jQuery.tipsy by Jason Frame 54239 * ======================================================================== 54240 * Copyright 2011-2014 Twitter, Inc. 54241 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 54242 * ======================================================================== */ 54243 54244 54245+function ($) { 54246 'use strict'; 54247 54248 // TOOLTIP PUBLIC CLASS DEFINITION 54249 // =============================== 54250 54251 var Tooltip = function (element, options) { 54252 this.type = 54253 this.options = 54254 this.enabled = 54255 this.timeout = 54256 this.hoverState = 54257 this.$element = null 54258 54259 this.init('tooltip', element, options) 54260 } 54261 54262 Tooltip.DEFAULTS = { 54263 animation: true, 54264 placement: 'top', 54265 selector: false, 54266 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 54267 trigger: 'hover focus', 54268 title: '', 54269 delay: 0, 54270 html: false, 54271 container: false, 54272 viewport: { 54273 selector: 'body', 54274 padding: 0 54275 } 54276 } 54277 54278 Tooltip.prototype.init = function (type, element, options) { 54279 this.enabled = true 54280 this.type = type 54281 this.$element = $(element) 54282 this.options = this.getOptions(options) 54283 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 54284 54285 var triggers = this.options.trigger.split(' ') 54286 54287 for (var i = triggers.length; i--;) { 54288 var trigger = triggers[i] 54289 54290 if (trigger == 'click') { 54291 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 54292 } else if (trigger != 'manual') { 54293 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 54294 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 54295 54296 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 54297 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 54298 } 54299 } 54300 54301 this.options.selector ? 54302 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 54303 this.fixTitle() 54304 } 54305 54306 Tooltip.prototype.getDefaults = function () { 54307 return Tooltip.DEFAULTS 54308 } 54309 54310 Tooltip.prototype.getOptions = function (options) { 54311 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 54312 54313 if (options.delay && typeof options.delay == 'number') { 54314 options.delay = { 54315 show: options.delay, 54316 hide: options.delay 54317 } 54318 } 54319 54320 return options 54321 } 54322 54323 Tooltip.prototype.getDelegateOptions = function () { 54324 var options = {} 54325 var defaults = this.getDefaults() 54326 54327 this._options && $.each(this._options, function (key, value) { 54328 if (defaults[key] != value) options[key] = value 54329 }) 54330 54331 return options 54332 } 54333 54334 Tooltip.prototype.enter = function (obj) { 54335 var self = obj instanceof this.constructor ? 54336 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 54337 54338 clearTimeout(self.timeout) 54339 54340 self.hoverState = 'in' 54341 54342 if (!self.options.delay || !self.options.delay.show) return self.show() 54343 54344 self.timeout = setTimeout(function () { 54345 if (self.hoverState == 'in') self.show() 54346 }, self.options.delay.show) 54347 } 54348 54349 Tooltip.prototype.leave = function (obj) { 54350 var self = obj instanceof this.constructor ? 54351 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 54352 54353 clearTimeout(self.timeout) 54354 54355 self.hoverState = 'out' 54356 54357 if (!self.options.delay || !self.options.delay.hide) return self.hide() 54358 54359 self.timeout = setTimeout(function () { 54360 if (self.hoverState == 'out') self.hide() 54361 }, self.options.delay.hide) 54362 } 54363 54364 Tooltip.prototype.show = function () { 54365 var e = $.Event('show.bs.' + this.type) 54366 54367 if (this.hasContent() && this.enabled) { 54368 this.$element.trigger(e) 54369 54370 if (e.isDefaultPrevented()) return 54371 var that = this; 54372 54373 var $tip = this.tip() 54374 54375 this.setContent() 54376 54377 if (this.options.animation) $tip.addClass('fade') 54378 54379 var placement = typeof this.options.placement == 'function' ? 54380 this.options.placement.call(this, $tip[0], this.$element[0]) : 54381 this.options.placement 54382 54383 var autoToken = /\s?auto?\s?/i 54384 var autoPlace = autoToken.test(placement) 54385 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 54386 54387 $tip 54388 .detach() 54389 .css({ top: 0, left: 0, display: 'block' }) 54390 .addClass(placement) 54391 54392 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 54393 54394 var pos = this.getPosition() 54395 var actualWidth = $tip[0].offsetWidth 54396 var actualHeight = $tip[0].offsetHeight 54397 54398 if (autoPlace) { 54399 var orgPlacement = placement 54400 var $parent = this.$element.parent() 54401 var parentDim = this.getPosition($parent) 54402 54403 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 54404 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 54405 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 54406 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 54407 placement 54408 54409 $tip 54410 .removeClass(orgPlacement) 54411 .addClass(placement) 54412 } 54413 54414 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 54415 54416 this.applyPlacement(calculatedOffset, placement) 54417 this.hoverState = null 54418 54419 var complete = function() { 54420 that.$element.trigger('shown.bs.' + that.type) 54421 } 54422 54423 $.support.transition && this.$tip.hasClass('fade') ? 54424 $tip 54425 .one($.support.transition.end, complete) 54426 .emulateTransitionEnd(150) : 54427 complete() 54428 } 54429 } 54430 54431 Tooltip.prototype.applyPlacement = function (offset, placement) { 54432 var $tip = this.tip() 54433 var width = $tip[0].offsetWidth 54434 var height = $tip[0].offsetHeight 54435 54436 // manually read margins because getBoundingClientRect includes difference 54437 var marginTop = parseInt($tip.css('margin-top'), 10) 54438 var marginLeft = parseInt($tip.css('margin-left'), 10) 54439 54440 // we must check for NaN for ie 8/9 54441 if (isNaN(marginTop)) marginTop = 0 54442 if (isNaN(marginLeft)) marginLeft = 0 54443 54444 offset.top = offset.top + marginTop 54445 offset.left = offset.left + marginLeft 54446 54447 // $.fn.offset doesn't round pixel values 54448 // so we use setOffset directly with our own function B-0 54449 $.offset.setOffset($tip[
544490], $.extend({ 54450 using: function (props) { 54451 $tip.css({ 54452 top: Math.round(props.top), 54453 left: Math.round(props.left) 54454 }) 54455 } 54456 }, offset), 0) 54457 54458 $tip.addClass('in') 54459 54460 // check to see if placing tip in new offset caused the tip to resize itself 54461 var actualWidth = $tip[0].offsetWidth 54462 var actualHeight = $tip[0].offsetHeight 54463 54464 if (placement == 'top' && actualHeight != height) { 54465 offset.top = offset.top + height - actualHeight 54466 } 54467 54468 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 54469 54470 if (delta.left) offset.left += delta.left 54471 else offset.top += delta.top 54472 54473 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 54474 var arrowPosition = delta.left ? 'left' : 'top' 54475 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 54476 54477 $tip.offset(offset) 54478 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 54479 } 54480 54481 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 54482 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 54483 } 54484 54485 Tooltip.prototype.setContent = function () { 54486 var $tip = this.tip() 54487 var title = this.getTitle() 54488 54489 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 54490 $tip.removeClass('fade in top bottom left right') 54491 } 54492 54493 Tooltip.prototype.hide = function () { 54494 var that = this 54495 var $tip = this.tip() 54496 var e = $.Event('hide.bs.' + this.type) 54497 54498 function complete() { 54499 if (that.hoverState != 'in') $tip.detach() 54500 that.$element.trigger('hidden.bs.' + that.type) 54501 } 54502 54503 this.$element.trigger(e) 54504 54505 if (e.isDefaultPrevented()) return 54506 54507 $tip.removeClass('in') 54508 54509 $.support.transition && this.$tip.hasClass('fade') ? 54510 $tip 54511 .one($.support.transition.end, complete) 54512 .emulateTransitionEnd(150) : 54513 complete() 54514 54515 this.hoverState = null 54516 54517 return this 54518 } 54519 54520 Tooltip.prototype.fixTitle = function () { 54521 var $e = this.$element 54522 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 54523 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 54524 } 54525 } 54526 54527 Tooltip.prototype.hasContent = function () { 54528 return this.getTitle() 54529 } 54530 54531 Tooltip.prototype.getPosition = function ($element) { 54532 $element = $element || this.$element 54533 var el = $element[0] 54534 var isBody = el.tagName == 'BODY' 54535 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 54536 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 54537 width: isBody ? $(window).width() : $element.outerWidth(), 54538 height: isBody ? $(window).height() : $element.outerHeight() 54539 }, isBody ? {top: 0, left: 0} : $element.offset()) 54540 } 54541 54542 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 54543 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 54544 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 54545 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 54546 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 54547 54548 } 54549 54550 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 54551 var delta = { top: 0, left: 0 } 54552 if (!this.$viewport) return delta 54553 54554 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 54555 var viewportDimensions = this.getPosition(this.$viewport) 54556 54557 if (/right|left/.test(placement)) { 54558 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 54559 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 54560 if (topEdgeOffset < viewportDimensions.top) { // top overflow 54561 delta.top = viewportDimensions.top - topEdgeOffset 54562 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 54563 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
54563EdgeOffset 54564 } 54565 } else { 54566 var leftEdgeOffset = pos.left - viewportPadding 54567 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 54568 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 54569 delta.left = viewportDimensions.left - leftEdgeOffset 54570 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 54571 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 54572 } 54573 } 54574 54575 return delta 54576 } 54577 54578 Tooltip.prototype.getTitle = function () { 54579 var title 54580 var $e = this.$element 54581 var o = this.options 54582 54583 title = $e.attr('data-original-title') 54584 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 54585 54586 return title 54587 } 54588 54589 Tooltip.prototype.tip = function () { 54590 return this.$tip = this.$tip || $(this.options.template) 54591 } 54592 54593 Tooltip.prototype.arrow = function () { 54594 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 54595 } 54596 54597 Tooltip.prototype.validate = function () { 54598 if (!this.$element[0].parentNode) { 54599 this.hide() 54600 this.$element = null 54601 this.options = null 54602 } 54603 } 54604 54605 Tooltip.prototype.enable = function () { 54606 this.enabled = true 54607 } 54608 54609 Tooltip.prototype.disable = function () { 54610 this.enabled = false 54611 } 54612 54613 Tooltip.prototype.toggleEnabled = function () { 54614 this.enabled = !this.enabled 54615 } 54616 54617 Tooltip.prototype.toggle = function (e) { 54618 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 54619 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 54620 } 54621 54622 Tooltip.prototype.destroy = function () { 54623 clearTimeout(this.timeout) 54624 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 54625 } 54626 54627 54628 // TOOLTIP PLUGIN DEFINITION 54629 // ========================= 54630 54631 var old = $.fn.tooltip 54632 54633 $.fn.tooltip = function (option) { 54634 return this.each(function () { 54635 var $this = $(this) 54636 var data = $this.data('bs.tooltip') 54637 var options = typeof option == 'object' && option 54638 54639 if (!data && option == 'destroy') return 54640 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 54641 if (typeof option == 'string') data[option]() 54642 }) 54643 } 54644 54645 $.fn.tooltip.Constructor = Tooltip 54646 54647 54648 // TOOLTIP NO CONFLICT 54649 // =================== 54650 54651 $.fn.tooltip.noConflict = function () { 54652 $.fn.tooltip = old 54653 return this 54654 } 54655 54656}(jQuery); 54657 54658/* ======================================================================== 54659 * Bootstrap: transition.js v3.1.1 54660 * http://getbootstrap.com/javascript/#transitions 54661 * ======================================================================== 54662 * Copyright 2011-2014 Twitter, Inc. 54663 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 54664 * ======================================================================== */ 54665 54666 54667+function ($) { 54668 'use strict'; 54669 54670 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 54671 // ============================================================ 54672 54673 function transitionEnd() { 54674 var el = document.createElement('bootstrap') 54675 54676 var transEndEventNames = { 54677 WebkitTransition : 'webkitTransitionEnd', 54678 MozTransition : 'transitionend', 54679 OTransition : 'oTransitionEnd otransitionend', 54680 transition : 'transitionend' 54681 } 54682 54683 for (var name in transEndEventNames) { 54684 if (el.style[name] !== undefined) { 54685 return { end: transEndEventNames[name] } 54686 } 54687 } 54688 54689 return false // explicit for ie8 ( ._.) 54690 } 54691 54692 // http://blog.alexmaccaw.com/css-transitions 54693 $.fn.emulateTransitionEnd = function (duration) { 54694 var called = false, $el = this 54695 $(this).one($.support.transition.end, function () { called = true }) 54696 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 54697 setTimeout(callback, duration) 54698 return this 54699 } 54700 54701 $(function () { 54702 $.support.transition = transitionEnd() 54703 }) 54704 54705}(jQuery); 54706 54707 54708// ------------------------------------------ 54709// Rellax.js 54710// Buttery smooth parallax library 54711// Copyright (c) 2016 Moe Amaya (@moeamaya) 54712// MIT license 54713// 54714// Thanks to Paraxify.js and Jaime Cabllero 54715// for parallax concepts 54716// ------------------------------------------ 54717 54718(function (root, factory) { 54719 if (typeof define === 'function' && define.amd) { 54720 // AMD. Register as an anonymous module. 54721 define([], factory); 54722 } else if (typeof module === 'object' && module.exports) { 54723 // Node. Does not work with strict CommonJS, but 54724 // only CommonJS-like environments that support module.exports, 54725 // like Node. 54726 module.exports = factory(); 54727 } else { 54728 // Browser globals (root is window) 54729 root.Rellax = factory(); 54730 } 54731}(typeof window !== "undefined" ? window : global, function () { 54732 var Rellax = function(el, options){ 54733 "use strict"; 54734 54735 var self = Object.create(Rellax.prototype); 54736 54737 var posY = 0; 54738 var screenY = 0; 54739 var posX = 0; 54740 var screenX = 0; 54741 var blocks = []; 54742 var pause = true; 54743 54744 // check what requestAnimationFrame to use, and if 54745 // it's not supported, use the onscroll event 54746 var loop = window.requestAnimationFrame || 54747 window.webkitRequestAnimationFrame || 54748 window.mozRequestAnimationFrame || 54749 window.msRequestAnimationFrame || 54750 window.oRequestAnimationFrame || 54751 function(callback){ return setTimeout(callback, 1000 / 60); }; 54752 54753 // store the id for later use 54754 var loopId = null; 54755 54756 // Test via a getter in the options object to see if the passive property is accessed 54757 var supportsPassive = false;
vendor: 10,724 bytes, lines 54758-55059
54758 try { 54759 var opts = Object.defineProperty({}, 'passive', { 54760 get: function() { 54761 supportsPassive = true; 54762 } 54763 }); 54764 window.addEventListener("testPassive", null, opts); 54765 window.removeEventListener("testPassive", null, opts); 54766 } catch (e) {} 54767 54768 // check what cancelAnimation method to use 54769 var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout; 54770 54771 // check which transform property to use 54772 var transformProp = window.transformProp || (function(){ 54773 var testEl = document.createElement('div'); 54774 if (testEl.style.transform === null) { 54775 var vendors = ['Webkit', 'Moz', 'ms']; 54776 for (var vendor in vendors) { 54777 if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) { 54778 return vendors[vendor] + 'Transform'; 54779 } 54780 } 54781 } 54782 return 'transform'; 54783 })(); 54784 54785 // Default Settings 54786 self.options = { 54787 speed: -2, 54788 verticalSpeed: null, 54789 horizontalSpeed: null, 54790 breakpoints: [576, 768, 1201], 54791 center: false, 54792 wrapper: null, 54793 relativeToWrapper: false, 54794 round: true, 54795 vertical: true, 54796 horizontal: false, 54797 verticalScrollAxis: "y", 54798 horizontalScrollAxis: "x", 54799 callback: function() {}, 54800 }; 54801 54802 // User defined options (might have more in the future) 54803 if (options){ 54804 Object.keys(options).forEach(function(key){ 54805 self.options[key] = options[key]; 54806 }); 54807 } 54808 54809 function validateCustomBreakpoints () { 54810 if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) { 54811 var isAscending = true; 54812 var isNumerical = true; 54813 var lastVal; 54814 self.options.breakpoints.forEach(function (i) { 54815 if (typeof i !== 'number') isNumerical = false; 54816 if (lastVal !== null) { 54817 if (i < lastVal) isAscending = false; 54818 } 54819 lastVal = i; 54820 }); 54821 if (isAscending && isNumerical) return; 54822 } 54823 // revert defaults if set incorrectly 54824 self.options.breakpoints = [576, 768, 1201]; 54825 console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted"); 54826 } 54827 54828 if (options && options.breakpoints) { 54829 validateCustomBreakpoints(); 54830 } 54831 54832 // By default, rellax class 54833 if (!el) { 54834 el = '.rellax'; 54835 } 54836 54837 // check if el is a className or a node 54838 var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el]; 54839 54840 // Now query selector 54841 if (elements.length > 0) { 54842 self.elems = elements; 54843 } 54844 54845 // The elements don't exist 54846 else { 54847 console.warn("Rellax: The elements you're trying to select don't exist."); 54848 return; 54849 } 54850 54851 // Has a wrapper and it exists 54852 if (self.options.wrapper) { 54853 if (!self.options.wrapper.nodeType) { 54854 var wrapper = document.querySelector(self.options.wrapper); 54855 54856 if (wrapper) { 54857 self.options.wrapper = wrapper; 54858 } else { 54859 console.warn("Rellax: The wrapper you're trying to use doesn't exist."); 54860 return; 54861 } 54862 } 54863 } 54864 54865 // set a placeholder for the current breakpoint 54866 var currentBreakpoint; 54867 54868 // helper to determine current breakpoint 54869 var getCurrentBreakpoint = function (w) { 54870 var bp = self.options.breakpoints; 54871 if (w < bp[0]) return 'xs'; 54872 if (w >= bp[0] && w < bp[1]) return 'sm'; 54873 if (w >= bp[1] && w < bp[2]) return 'md'; 54874 return 'lg'; 54875 }; 54876 54877 // Get and cache initial position of all elements 54878 var cacheBlocks = function() { 54879 for (var i = 0; i < self.elems.length; i++){ 54880 var block = createBlock(self.elems[i]); 54881 blocks.push(block); 54882 } 54883 }; 54884 54885 54886 // Let's kick this script off 54887 // Build array for cached element values 54888 var init = function() { 54889 for (var i = 0; i < blocks.length; i++){ 54890 self.elems[i].style.cssText = blocks[i].style; 54891 } 54892 54893 blocks = []; 54894 54895 screenY = window.innerHeight; 54896 screenX = window.innerWidth; 54897 currentBreakpoint = getCurrentBreakpoint(screenX); 54898 54899 setPosition(); 54900 54901 cacheBlocks(); 54902 54903 animate(); 54904 54905 // If paused, unpause and set listener for window resizing events 54906 if (pause) { 54907 window.addEventListener('resize', init); 54908 pause = false; 54909 // Start the loop 54910 update(); 54911 } 54912 }; 54913 54914 // We want to cache the parallax blocks' 54915 // values: base, top, height, speed 54916 // el: is dom object, return: el cache values 54917 var createBlock = function(el) { 54918 var dataPercentage = el.getAttribute( 'data-rellax-percentage' ); 54919 var dataSpeed = el.getAttribute( 'data-rellax-speed' ); 54920 var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' ); 54921 var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' ); 54922 var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' ); 54923 var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' ); 54924 var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed'); 54925 var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed'); 54926 var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis'); 54927 var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis'); 54928 var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0; 54929 var dataMin = el.getAttribute( 'data-rellax-min' ); 54930 var dataMax = el.getAttribute( 'data-rellax-max' ); 54931 var dataMinX = el.getAttribute('data-rellax-min-x'); 54932 var dataMaxX = el.getAttribute('data-rellax-max-x'); 54933 var dataMinY = el.getAttribute('data-rellax-min-y'); 54934 var dataMaxY = el.getAttribute('data-rellax-max-y'); 54935 var mapBreakpoints; 54936 var breakpoints = true; 54937 54938 if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) { 54939 breakpoints = false; 54940 } else { 54941 mapBreakpoints = { 54942 'xs': dataXsSpeed, 54943 'sm': dataMobileSpeed, 54944 'md': dataTabletSpeed, 54945 'lg': dataDesktopSpeed 54946 }; 54947 } 54948 54949 // initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser) 54950 // ensures elements are positioned based on HTML layout. 54951 // 54952 // If the element has the percentage attribute, the posY and posX needs to be 54953 // the current scroll position's value, so that the elements are still positioned based on HTML layout 54954 var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 54955 // If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll. 54956 if (self.options.relativeToWrapper) { 54957 var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 54958 wrapperPosY = scrollPosY - self.options.wrapper.offsetTop; 54959 } 54960 var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0; 54961 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; 54962 54963 var blockTop = posY + el.getBoundingClientRect().top; 54964 var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight; 54965 54966 var blockLeft = posX + el.getBoundingClientRect().left; 54967 var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth; 54968 54969 // apparently parallax equation everyone uses 54970 var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY); 54971 var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX); 54972 if(self.options.center){ percentageX = 0.5; percentageY = 0.5; } 54973 54974 // Optional individual block speed as data attr, otherwise global speed 54975 var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed); 54976 var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed; 54977 var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed; 54978 54979 // Optional individual block movement axis direction as data attr, otherwise global movement direction 54980 var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis; 54981 var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis; 54982 54983 var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed); 54984 54985 // ~~Store non-translate3d transforms~~ 54986 // Store inline styles and extract transforms 54987 var style = el.style.cssText; 54988 var transform = ''; 54989 54990 // Check if there's an inline styled transform 54991 var searchResult = /transform\s*:/i.exec(style); 54992 if (searchResult) { 54993 // Get the index of the transform 54994 var index = searchResult.index; 54995 54996 // Trim the style to the transform point and get the following semi-colon index 54997 var trimmedStyle = style.slice(index); 54998 var delimiter = trimmedStyle.indexOf(';'); 54999 55000 // Remove "transform" string and save the attribute 55001 if (delimiter) { 55002 transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,''); 55003 } else { 55004 transform = " " + trimmedStyle.slice(11).replace(/\s/g,''); 55005 } 55006 } 55007 55008 return { 55009 baseX: bases.x, 55010 baseY: bases.y, 55011 top: blockTop, 55012 left: blockLeft, 55013 height: blockHeight, 55014 width: blockWidth, 55015 speed: speed, 55016 verticalSpeed: verticalSpeed, 55017 horizontalSpeed: horizontalSpeed, 55018 verticalScrollAxis: verticalScrollAxis, 55019 horizontalScrollAxis: horizontalScrollAxis, 55020 style: style, 55021 transform: transform, 55022 zindex: dataZindex, 55023 min: dataMin, 55024 max: dataMax, 55025 minX: dataMinX, 55026 maxX: dataMaxX, 55027 minY: dataMinY, 55028 maxY: dataMaxY 55029 }; 55030 }; 55031 55032 // set scroll position (posY, posX) 55033 // side effect method is not ideal, but okay for now 55034 // returns true if the scroll changed, false if nothing happened 55035 var setPosition = function() { 55036 var oldY = posY; 55037 var oldX = posX; 55038 55039 posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 55040 posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset; 55041 // If option relativeToWrapper is true, use relative wrapper value instead. 55042 if (self.options.relativeToWrapper) { 55043 var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 55044 posY = scrollPosY - self.options.wrapper.offsetTop; 55045 } 55046 55047 55048 if (oldY != posY && self.options.vertical) { 55049 // scroll changed, return true 55050 return true; 55051 } 55052 55053 if (oldX != posX && self.options.horizontal) { 55054 // scroll changed, return true 55055 return true; 55056 } 55057 55058 // scroll did not change 55059 return false;
55060 }; 55061 55062 // Ahh a pure function, gets new transform value 55063 // based on scrollPosition and speed 55064 // Allow for decimal pixel values 55065 var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) { 55066 var result = {}; 55067 var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX))); 55068 var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY))); 55069 55070 result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100; 55071 result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100; 55072 55073 return result; 55074 }; 55075 55076 // Remove event listeners and loop again 55077 var deferredUpdate = function() { 55078 window.removeEventListener('resize', deferredUpdate); 55079 window.removeEventListener('orientationchange', deferredUpdate); 55080 (self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate); 55081 (self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate); 55082 55083 // loop again 55084 loopId = loop(update); 55085 }; 55086 55087 // Loop 55088 var update = function() { 55089 if (setPosition() && pause === false) { 55090 animate(); 55091 55092 // loop again 55093 loopId = loop(update); 55094 } else { 55095 loopId = null; 55096 55097 // Don't animate until we get a position updating event 55098 window.addEventListener('resize', deferredUpdate); 55099 window.addEventListener('orientationchange', deferredUpdate); 55100 (self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false); 55101 (self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false); 55102 } 55103 }; 55104 55105 // Transform3d on parallax element 55106 var animate = function() { 55107 var positions; 55108 for (var i = 0; i < self.elems.length; i++){ 55109 // Determine relevant movement directions 55110 var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase(); 55111 var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase(); 55112 var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0; 55113 var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0; 55114 var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0; 55115 var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0; 55116 55117 var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY)); 55118 var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX)); 55119 55120 // Subtracting initialize value, so element stays in same spot as HTML 55121 positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed); 55122 var positionY = positions.y - blocks[i].baseY; 55123 var positionX = positions.x - blocks[i].baseX; 55124 55125 // The next two "if" blocks go like this: 55126 // Check if a limit is defined (first "min", then "max"); 55127 // Check if we need to change the Y or the X 55128 // (Currently working only if just one of the axes is enabled) 55129 // Then, check if the new position is inside the allowed limit 55130 // If so, use new position. If not, set position to limit. 55131 55132 // Check if a min limit is defined 55133 if (blocks[i].min !== null) { 55134 if (self.options.vertical && !self.options.horizontal) { 55135 positionY = positionY <= blocks[i].min ? blocks[i].min : positionY; 55136 } 55137 if (self.options.horizontal && !self.options.vertical) { 55138 positionX = positionX <= blocks[i].min ? blocks[i].min : positionX; 55139 } 55140 } 55141 55142 // Check if directional min limits are defined 55143 if (blocks[i].minY != null) { 55144 positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY; 55145 } 55146 if (blocks[i].minX != null) { 55147 positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX; 55148 } 55149 55150 // Check if a max limit is defined 55151 if (blocks[i].max !== null) { 55152 if (self.options.vertical && !self.options.horizontal) { 55153 positionY = positionY >= blocks[i].max ? blocks[i].max : positionY; 55154 } 55155 if (self.options.horizontal && !self.options.vertical) { 55156 positionX = positionX >= blocks[i].max ? blocks[i].max : positionX; 55157 } 55158 } 55159 55160 // Check if directional max limits are defined 55161 if (blocks[i].maxY != null) { 55162 positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY; 55163 } 55164 if (blocks[i].maxX != null) { 55165 positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX; 55166 } 55167 55168 var zindex = blocks[i].zindex; 55169 55170 // Move that element 55171 // (Set the new translation and append initial inline transforms.) 55172 var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform; 55173 self.elems[i].style[transformProp] = translate; 55174 } 55175 self.options.callback(positions); 55176 }; 55177 55178 self.destroy = function() { 55179 for (var i = 0; i < self.elems.length; i++){ 55180 self.elems[i].style.cssText = blocks[i].style; 55181 } 55182 55183 // Remove resize event listener if not pause, and pause 55184 if (!pause) { 55185 window.removeEventListener('resize', init); 55186 pause = true; 55187 } 55188 55189 // Clear the animation loop to prevent possible memory leak 55190 clearLoop(loopId); 55191 loopId = null; 55192 }; 55193 55194 // Init 55195 init(); 55196 55197 // Allow to recalculate the initial values whenever we want 55198 self.refresh = init; 55199 55200 return self; 55201 }; 55202 return Rellax; 55203})); 55204 55205/* 55206 * OKVideo by OKFocus v2.3.2 55207 * http://okfoc.us 55208 * 55209 * Copyright 2014, OKFocus 55210 * Licensed under the MIT license. 55211 * 55212 */ 55213var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array(); 55214// youtube player ready 55215function onYouTubeIframeAPIReady() { 55216 YTplayers = new Array(); 55217 jQuery('.uncode-video-container.video').each(function() { 55218 var playerY; 55219 if (jQuery(this).attr('data-provider') == 'youtube') { 55220 var id = jQuery(this).attr('data-id'), 55221 start = jQuery(this).attr('data-start'), 55222 end = jQuery(this).attr('data-end'); 55223 start = typeof start && start !== null ? start : 0; 55224 end = typeof end && end !== null ? end : 0; 55225 options = jQuery(window).data('okoptions-' + id); 55226 if ( typeof options === 'undefined' ) { 55227 return true; 55228 } 55229 options.time = jQuery(this).attr('data-t'); 55230 playerY = new YT.Player('okplayer-' + id, { 55231 videoId: options.video ? options.video.id : null, 55232 playerVars: { 55233 'autohide': 1, 55234 'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay, 55235 'disablekb': 1, 55236 'cc_load_policy': options.captions, 55237 'controls': 0, 55238 'enablejsapi': 1, 55239 'fs': 0, 55240 'modestbranding': 1, 55241 'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname), 55242 'iv_load_policy': options.annotations, 55243 'loop': options.loop, 55244 'showinfo': 0, 55245 'rel': 0, 55246 'wmode': 'opaque', 55247 'hd': options.hd, 55248 'mute': 1, 55249 'start': start, 55250 'end': end 55251 }, 55252 events: { 55253 'onReady': OKEvents.yt.ready, 55254 'onStateChange': OKEvents.yt.onStateChange, 55255 'onError': OKEvents.yt.error 55256 } 55257 }); 55258 YTplayers[id] = playerY; 55259 playerY.videoId = id; 55260 } 55261 55262 }); 55263} 55264// vimeo player ready 55265function vimeoPlayerReady(id) { 55266 options = jQuery(window).data('okoptions-' + id); 55267 if ( typeof options === 'undefined' ) { 55268 return true; 55269 }
55270 var jIframe = options.jobject, 55271 iframe = jIframe[0]; 55272 55273 jIframe.attr('src', jIframe.data('src')); 55274 var playerV = new Vimeo.Player(iframe); 55275 // hide player until Vimeo hides controls... 55276 playerV.on('loaded', function(e) { 55277 OKEvents.v.onReady(iframe); 55278 var carouselContainer = jQuery(iframe).closest('.owl-carousel'); 55279 if (carouselContainer.length) { 55280 UNCODE.owlPlayVideo(carouselContainer); 55281 } 55282 // "Do not try to add listeners or call functions before receiving this event." 55283 if (OKEvents.utils.isMobile()) { 55284 // mobile devices cannot listen for play event 55285 OKEvents.v.onPlay(playerV); 55286 } else { 55287 playerV.on('play', function(){ 55288 OKEvents.v.onPlay(playerV); 55289 jQuery(window).trigger('okevents.v.play', [playerV]); 55290 }); 55291 playerV.on('pause', function(){ 55292 OKEvents.v.onPause; 55293 jQuery(window).trigger('okevents.v.pause', [playerV]); 55294 }); 55295 playerV.on('ended', function(){ 55296 OKEvents.v.onFinish 55297 jQuery(window).trigger('okevents.v.ended', [playerV]); 55298 }); 55299 } 55300 if (options.time != null) { 55301 var optsTimeStr = (options.time).replace('t=', ''), 55302 timeV = ''; 55303 55304 if ( /[a-zA-Z]/g.test(optsTimeStr) ) { 55305 var timeArr = optsTimeStr.split(/([^\d.-])/); 55306 for ( var i = 0; i < timeArr.length; i++ ) { 55307 if ( timeArr[i] === 'h' ) { 55308 timeV += parseFloat(timeArr[i-1]) * 3600; 55309 } else if ( timeArr[i] === 'm' ) { 55310 timeV += parseFloat(timeArr[i-1]) * 60; 55311 } else if ( timeArr[i] === 's' ) { 55312 timeV += parseFloat(timeArr[i-1]); 55313 } 55314 } 55315 } else { 55316 timeV = optsTimeStr; 55317 } 55318 55319 playerV.setCurrentTime(timeV); 55320 } 55321 55322 playerV.setVolume(0); 55323 playerV.play(); 55324 jQuery(iframe).css({ 55325 visibility: 'visible', 55326 opacity: 1 55327 }); 55328 jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 55329 jQuery(iframe).closest('#page-header').addClass('video-started'); 55330 jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 55331 55332 jQuery(window).trigger('okevents.v.loaded', [playerV]); 55333 }); 55334} 55335OKEvents = { 55336 yt: { 55337 ready: function(event) { 55338 var id = event.target.videoId, 55339 $video = jQuery('#okplayer-' + id), 55340 options = jQuery(window).data('okoptions-' + id); 55341 if ( typeof options === 'undefined' ) { 55342 return true; 55343 } 55344 youtubePlayers[id] = event.target; 55345 event.target.setVolume(options.volume); 55346 if (options.autoplay === 1) { 55347 if (options.playlist.list) { 55348 player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality); 55349 } else { 55350 var inCarousel = $video.closest('.owl-item'); 55351 if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) { 55352 if (options.time != null) { 55353 event.target.seekTo(parseInt(options.time)); 55354 } 55355 event.target.playVideo(); 55356 } else { 55357 event.target.pauseVideo(); 55358 } 55359 } 55360 } 55361 OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target); 55362 55363 $video.closest('[data-provider]').on('uncode-resume', function(){ 55364 if (options.time != null) { 55365 event.target.seekTo(parseInt(options.time)).playVideo(); 55366 } else { 55367 event.target.seekTo(0).playVideo(); 55368 } 55369 }); 55370 55371 $video.closest('[data-provider]').on('uncode-pause', function(){ 55372 if (options.time != null) { 55373 event.target.seekTo(parseInt(options.time)).pauseVideo(); 55374 } else { 55375 event.target.seekTo(0).pauseVideo(); 55376 } 55377 }); 55378 jQuery(window).trigger('okevents.y.loaded', [event]); 55379 }, 55380 onStateChange: function(event) { 55381 var id = event.target.videoId, 55382 $video = jQuery('#okplayer-' + id), 55383 options = jQuery(window).data('okoptions-' + id); 55384 if ( typeof options === 'undefined' || typeof event.target.setVolume === 'undefined' ) { 55385 return true; 55386 } 55387 youtubePlayers[id] = event.target; 55388 event.target.setVolume(options.volume); 55389 var $fluid = $video.closest('.fluid-object'), 55390 $tmb = $video.closest('.tmb'), 55391 setTime; 55392 switch (event.data) { 55393 case -1: 55394 OKEvents.utils.isFunction(options.unstarted) && options.unstarted(); 55395 break; 55396 case 0: 55397 OKEvents.utils.isFunction(options.onFinished) && options.onFinished(); 55398 options.loop && event.target.playVideo(); 55399 break; 55400 case 1: 55401 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 55402 setTimeout(function() { 55403 UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)'); 55404 jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 55405 jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started'); 55406 jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 55407 }, 300); 55408 break; 55409 case 2: 55410 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 55411 break; 55412 case 3: 55413 OKEvents.utils.isFunction(options.buffering) && options.buffering(); 55414 break; 55415 case 5: 55416 OKEvents.utils.isFunction(options.cued) && options.cued(); 55417 break; 55418 default:
55419 throw "OKVideo: received invalid data from YT player."; 55420 } 55421 55422 jQuery(window).trigger('okevents.y.change', [event]); 55423 }, 55424 error: function(event) { 55425 throw event; 55426 } 55427 }, 55428 v: { 55429 onReady: function(target) { 55430 if ( typeof options === 'undefined' ) { 55431 return true; 55432 } 55433 OKEvents.utils.isFunction(options.onReady) && options.onReady(target); 55434 }, 55435 onPlay: function(player) { 55436 if ( typeof options === 'undefined' ) { 55437 return true; 55438 } 55439 if (!OKEvents.utils.isMobile()) player.setVolume(options.volume); 55440 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 55441 jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 55442 jQuery(player.element).closest('#page-header').addClass('video-started'); 55443 jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 55444 }, 55445 onPause: function() { 55446 if ( typeof options === 'undefined' ) { 55447 return true; 55448 } 55449 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 55450 }, 55451 onFinish: function() { 55452 if ( typeof options === 'undefined' ) { 55453 return true; 55454 } 55455 OKEvents.utils.isFunction(options.onFinish) && options.onFinish(); 55456 } 55457 }, 55458 utils: { 55459 isFunction: function(func) { 55460 if (typeof func === 'function') { 55461 return true; 55462 } else { 55463 return false; 55464 } 55465 }, 55466 isMobile: function() { 55467 if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) { 55468 return true; 55469 } else { 55470 return false; 55471 } 55472 } 55473 } 55474}; 55475/** 55476 * vivus - JavaScript library to make drawing animation on SVG 55477 * @version v0.4.4 55478 * @link https://github.com/maxwellito/vivus 55479 * @license MIT 55480 */ 55481 55482'use strict'; 55483 55484(function () { 55485 55486 'use strict'; 55487 55488/** 55489 * Pathformer 55490 * Beta version 55491 * 55492 * Take any SVG version 1.1 and transform 55493 * child elements to 'path' elements 55494 * 55495 * This code is purely forked from 55496 * https://github.com/Waest/SVGPathConverter 55497 */ 55498 55499/** 55500 * Class constructor 55501 * 55502 * @param {DOM|String} element Dom element of the SVG or id of it 55503 */ 55504function Pathformer(element) { 55505 // Test params 55506 if (typeof element === 'undefined') { 55507 throw new Error('Pathformer [constructor]: "element" parameter is required'); 55508 } 55509 55510 // Set the element 55511 if (element.constructor === String) { 55512 element = document.getElementById(element); 55513 if (!element) { 55514 throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID'); 55515 } 55516 } 55517 if (element instanceof window.SVGElement || 55518 element instanceof window.SVGGElement || 55519 /^svg$/i.test(element.nodeName)) { 55520 this.el = element; 55521 } else { 55522 throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement'); 55523 } 55524 55525 // Start 55526 this.scan(element); 55527} 55528 55529/** 55530 * List of tags which can be transformed 55531 * to path elements 55532 * 55533 * @type {Array} 55534 */ 55535Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect']; 55536 55537/** 55538 * List of attribute names which contain 55539 * data. This array list them to check if 55540 * they contain bad values, like percentage. 55541 * 55542 * @type {Array} 55543 */ 55544Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 55544-56342
55544y1', 'y2']; 55545 55546/** 55547 * Finds the elements compatible for transform 55548 * and apply the liked method 55549 * 55550 * @param {object} options Object from the constructor 55551 */ 55552Pathformer.prototype.scan = function (svg) { 55553 var fn, element, pathData, pathDom, 55554 elements = svg.querySelectorAll(this.TYPES.join(',')); 55555 55556 for (var i = 0; i < elements.length; i++) { 55557 element = elements[i]; 55558 fn = this[element.tagName.toLowerCase() + 'ToPath']; 55559 pathData = fn(this.parseAttr(element.attributes)); 55560 pathDom = this.pathMaker(element, pathData); 55561 element.parentNode.replaceChild(pathDom, element); 55562 } 55563}; 55564 55565 55566/** 55567 * Read `line` element to extract and transform 55568 * data, to make it ready for a `path` object. 55569 * 55570 * @param {DOMelement} element Line element to transform 55571 * @return {object} Data for a `path` element 55572 */ 55573Pathformer.prototype.lineToPath = function (element) { 55574 var newElement = {}, 55575 x1 = element.x1 || 0, 55576 y1 = element.y1 || 0, 55577 x2 = element.x2 || 0, 55578 y2 = element.y2 || 0; 55579 55580 newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2; 55581 return newElement; 55582}; 55583 55584/** 55585 * Read `rect` element to extract and transform 55586 * data, to make it ready for a `path` object. 55587 * The radius-border is not taken in charge yet. 55588 * (your help is more than welcomed) 55589 * 55590 * @param {DOMelement} element Rect element to transform 55591 * @return {object} Data for a `path` element 55592 */ 55593Pathformer.prototype.rectToPath = function (element) { 55594 var newElement = {}, 55595 x = parseFloat(element.x) || 0, 55596 y = parseFloat(element.y) || 0, 55597 width = parseFloat(element.width) || 0, 55598 height = parseFloat(element.height) || 0; 55599 55600 if (element.rx || element.ry) { 55601 var rx = parseInt(element.rx, 10) || -1, 55602 ry = parseInt(element.ry, 10) || -1; 55603 rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2); 55604 ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2); 55605 55606 newElement.d = 'M ' + (x + rx) + ',' + y + ' ' + 55607 'L ' + (x + width - rx) + ',' + y + ' ' + 55608 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' + 55609 'L ' + (x + width) + ',' + (y + height - ry) + ' ' + 55610 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' + 55611 'L ' + (x + rx) + ',' + (y + height) + ' ' + 55612 'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' + 55613 'L ' + x + ',' + (y + ry) + ' ' + 55614 'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y; 55615 } 55616 else { 55617 newElement.d = 'M' + x + ' ' + y + ' ' + 55618 'L' + (x + width) + ' ' + y + ' ' + 55619 'L' + (x + width) + ' ' + (y + height) + ' ' + 55620 'L' + x + ' ' + (y + height) + ' Z'; 55621 } 55622 return newElement; 55623}; 55624 55625/** 55626 * Read `polyline` element to extract and transform 55627 * data, to make it ready for a `path` object. 55628 * 55629 * @param {DOMelement} element Polyline element to transform 55630 * @return {object} Data for a `path` element 55631 */ 55632Pathformer.prototype.polylineToPath = function (element) { 55633 var newElement = {}, 55634 points = element.points.trim().split(' '), 55635 i, path; 55636 55637 // Reformatting if points are defined without commas 55638 if (element.points.indexOf(',') === -1) { 55639 var formattedPoints = []; 55640 for (i = 0; i < points.length; i+=2) { 55641 formattedPoints.push(points[i] + ',' + points[i+1]); 55642 } 55643 points = formattedPoints; 55644 } 55645 55646 // Generate the path.d value 55647 path = 'M' + points[0]; 55648 for(i = 1; i < points.length; i++) { 55649 if (points[i].indexOf(',') !== -1) { 55650 path += 'L' + points[i]; 55651 } 55652 } 55653 newElement.d = path; 55654 return newElement; 55655}; 55656 55657/** 55658 * Read `polygon` element to extract and transform 55659 * data, to make it ready for a `path` object. 55660 * This method rely on polylineToPath, because the 55661 * logic is similar. The path created is just closed, 55662 * so it needs an 'Z' at the end. 55663 * 55664 * @param {DOMelement} element Polygon element to transform 55665 * @return {object} Data for a `path` element 55666 */ 55667Pathformer.prototype.polygonToPath = function (element) { 55668 var newElement = Pathformer.prototype.polylineToPath(element); 55669 55670 newElement.d += 'Z'; 55671 return newElement; 55672}; 55673 55674/** 55675 * Read `ellipse` element to extract and transform 55676 * data, to make it ready for a `path` object. 55677 * 55678 * @param {DOMelement} element ellipse element to transform 55679 * @return {object} Data for a `path` element 55680 */ 55681Pathformer.prototype.ellipseToPath = function (element) { 55682 var newElement = {}, 55683 rx = parseFloat(element.rx) || 0, 55684 ry = parseFloat(element.ry) || 0, 55685 cx = parseFloat(element.cx) || 0, 55686 cy = parseFloat(element.cy) || 0, 55687 startX = cx - rx, 55688 startY = cy, 55689 endX = parseFloat(cx) + parseFloat(rx), 55690 endY = cy; 55691 55692 newElement.d = 'M' + startX + ',' + startY + 55693 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY + 55694 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY; 55695 return newElement; 55696}; 55697 55698/** 55699 * Read `circle` element to extract and transform 55700 * data, to make it ready for a `path` object. 55701 * 55702 * @param {DOMelement} element Circle element to transform 55703 * @return {object} Data for a `path` element 55704 */ 55705Pathformer.prototype.circleToPath = function (element) { 55706 var newElement = {}, 55707 r = parseFloat(element.r) || 0, 55708 cx = parseFloat(element.cx) || 0, 55709 cy = parseFloat(element.cy) || 0, 55710 startX = cx - r, 55711 startY = cy, 55712 endX = parseFloat(cx) + parseFloat(r), 55713 endY = cy; 55714 55715 newElement.d = 'M' + startX + ',' + startY + 55716 'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY + 55717 'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY; 55718 return newElement; 55719}; 55720 55721/** 55722 * Create `path` elements form original element 55723 * and prepared objects 55724 * 55725 * @param {DOMelement} element Original element to transform 55726 * @param {object} pathData Path data (from `toPath` methods) 55727 * @return {DOMelement} Path element 55728 */ 55729Pathformer.prototype.pathMaker = function (element, pathData) { 55730 var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path'); 55731 for(i = 0; i < element.attributes.length; i++) { 55732 attr = element.attributes[i]; 55733 if (this.ATTR_WATCH.indexOf(attr.name) === -1) { 55734 pathTag.setAttribute(attr.name, attr.value); 55735 } 55736 } 55737 for(i in pathData) { 55738 pathTag.setAttribute(i, pathData[i]); 55739 } 55740 return pathTag; 55741}; 55742 55743/** 55744 * Parse attributes of a DOM element to 55745 * get an object of attribute => value 55746 * 55747 * @param {NamedNodeMap} attributes Attributes object from DOM element to parse 55748 * @return {object} Object of attributes 55749 */ 55750Pathformer.prototype.parseAttr = function (element) { 55751 var attr, output = {}; 55752 for (var i = 0; i < element.length; i++) { 55753 attr = element[i]; 55754 // Check if no data attribute contains '%', or the transformation is impossible 55755 if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) { 55756 throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.'); 55757 } 55758 output[attr.name] = attr.value; 55759 } 55760 return output; 55761}; 55762 55763 'use strict'; 55764 55765var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt; 55766 55767/** 55768 * Vivus 55769 * Beta version 55770 * 55771 * Take any SVG and make the animation 55772 * to give give the impression of live drawing 55773 * 55774 * This in more than just inspired from codrops 55775 * At that point, it's a pure fork. 55776 */ 55777 55778/** 55779 * Class constructor 55780 * option structure 55781 * type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed) 55782 * duration: <int> (in frames) 55783 * start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport) 55784 * delay: <int> (delay between the drawing of first and last path) 55785 * dashGap <integer> whitespace extra margin between dashes 55786 * pathTimingFunction <function> timing animation function for each path element of the SVG 55787 * animTimingFunction <function> timing animation function for the complete SVG 55788 * forceRender <boolean> force the browser to re-render all updated path items 55789 * selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original 55790 * 55791 * The attribute 'type' is by default on 'delayed'. 55792 * - 'delayed' 55793 * all paths are draw at the same time but with a 55794 * little delay between them before start 55795 * - 'sync' 55796 * all path are start and finish at the same time 55797 * - 'oneByOne' 55798 * only one path is draw at the time 55799 * the end of the first one will trigger the draw 55800 * of the next one 55801 * 55802 * All these values can be overwritten individually 55803 * for each path item in the SVG 55804 * The value of frames will always take the advantage of 55805 * the duration value. 55806 * If you fail somewhere, an error will be thrown. 55807 * Good luck. 55808 * 55809 * @constructor 55810 * @this {Vivus} 55811 * @param {DOM|String} element Dom element of the SVG or id of it 55812 * @param {Object} options Options about the animation 55813 * @param {Function} callback Callback for the end of the animation 55814 */ 55815function Vivus (element, options, callback) { 55816 55817 setupEnv(); 55818 55819 // Setup 55820 this.isReady = false; 55821 this.setElement(element, options); 55822 this.setOptions(options); 55823 this.setCallback(callback); 55824 55825 if (this.isReady) { 55826 this.init(); 55827 } 55828} 55829 55830/** 55831 * Timing functions 55832 ************************************** 55833 * 55834 * Default functions to help developers. 55835 * It always take a number as parameter (between 0 to 1) then 55836 * return a number (between 0 and 1) 55837 */ 55838Vivus.LINEAR = function (x) {return x;}; 55839Vivus.EASE = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;}; 55840Vivus.EASE_OUT = function (x) {return 1 - Math.pow(1-x, 3);}; 55841Vivus.EASE_IN = function (x) {return Math.pow(x, 3);}; 55842Vivus.EASE_OUT_BOUNCE = function (x) { 55843 var base = -Math.cos(x * (0.5 * Math.PI)) + 1, 55844 rate = Math.pow(base,1.5), 55845 rateR = Math.pow(1 - x, 2), 55846 progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1; 55847 return (1- rateR) + (progress * rateR); 55848}; 55849 55850 55851/** 55852 * Setters 55853 ************************************** 55854 */ 55855 55856/** 55857 * Check and set the element in the instance 55858 * The method will not return anything, but will throw an 55859 * error if the parameter is invalid 55860 * 55861 * @param {DOM|String} element SVG Dom element or id of it 55862 */ 55863Vivus.prototype.setElement = function (element, options) { 55864 var onLoad, self; 55865 55866 // Basic check 55867 if (typeof element === 'undefined') { 55868 throw new Error('Vivus [constructor]: "element" parameter is required'); 55869 } 55870 55871 // Set the element 55872 if (element.constructor === String) { 55873 element = document.getElementById(element); 55874 if (!element) { 55875 throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID'); 55876 } 55877 } 55878 this.parentEl = element; 55879 55880 // Load the SVG with XMLHttpRequest and extract the SVG 55881 if (options && options.file) { 55882 var self = this; 55883 onLoad = function (e) { 55884 var domSandbox = document.createElement('div'); 55885 domSandbox.innerHTML = this.responseText; 55886 55887 var svgTag = domSandbox.querySelector('svg'); 55888 if (!svgTag) { 55889 throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file); 55890 } 55891 55892 self.el = svgTag 55893 self.el.setAttribute('width', '100%'); 55894 self.el.setAttribute('height', '100%'); 55895 self.parentEl.appendChild(self.el) 55896 self.isReady = true; 55897 self.init(); 55898 self = null; 55899 } 55900 55901 var oReq = new window.XMLHttpRequest(); 55902 oReq.addEventListener('load', onLoad); 55903 oReq.open('GET', options.file); 55904 oReq.send(); 55905 return; 55906 } 55907 55908 switch (element.constructor) { 55909 case window.SVGSVGElement: 55910 case window.SVGElement: 55911 case window.SVGGElement: 55912 this.el = element; 55913 this.isReady = true; 55914 break; 55915 55916 case window.HTMLObjectElement: 55917 self = this; 55918 onLoad = function (e) { 55919 if (self.isReady) { 55920 return; 55921 } 55922 self.el = element.contentDocument && element.contentDocument.querySelector('svg'); 55923 if (!self.el && e) { 55924 throw new Error('Vivus [constructor]: object loaded does not contain any SVG'); 55925 } 55926 else if (self.el) { 55927 if (element.getAttribute('built-by-vivus')) { 55928 self.parentEl.insertBefore(self.el, element); 55929 self.parentEl.removeChild(element); 55930 self.el.setAttribute('width', '100%'); 55931 self.el.setAttribute('height', '100%'); 55932 } 55933 self.isReady = true; 55934 self.init(); 55935 self = null; 55936 } 55937 }; 55938 55939 if (!onLoad()) { 55940 element.addEventListener('load', onLoad); 55941 } 55942 break; 55943 55944 default: 55945 throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)'); 55946 } 55947}; 55948 55949/** 55950 * Set up user option to the instance 55951 * The method will not return anything, but will throw an 55952 * error if the parameter is invalid 55953 * 55954 * @param {object} options Object from the constructor 55955 */ 55956Vivus.prototype.setOptions = function (options) { 55957 var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync']; 55958 var allowedStarts = ['inViewport', 'manual', 'autostart']; 55959 55960 // Basic check 55961 if (options !== undefined && options.constructor !== Object) { 55962 throw new Error('Vivus [constructor]: "options" parameter must be an object'); 55963 } 55964 else { 55965 options = options || {}; 55966 } 55967 55968 // Set the animation type 55969 if (options.type && allowedTypes.indexOf(options.type) === -1) { 55970 throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`'); 55971 } 55972 else { 55973 this.type = options.type || allowedTypes[0]; 55974 } 55975 55976 // Set the start type 55977 if (options.start && allowedStarts.indexOf(options.start) === -1) { 55978 throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option'); 55979 } 55980 else { 55981 this.start = options.start || allowedStarts[0]; 55982 } 55983 55984 this.isIE = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 ); 55985 this.duration = parsePositiveInt(options.duration, 120); 55986 this.delay = parsePositiveInt(options.delay, null); 55987 //Uncode addition 55988 this.delayStart = parsePositiveInt(options.delayStart, null); 55989 //#END 55990 this.dashGap = parsePositiveInt(options.dashGap, 1); 55991 this.forceRender = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE; 55992 this.reverseStack = !!options.reverseStack; 55993 this.selfDestroy = !!options.selfDestroy; 55994 this.onReady = options.onReady; 55995 this.map = []; 55996 this.frameLength = this.currentFrame = this.delayUnit = this.speed = this.handle = null; 55997 55998 this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false; 55999 56000 this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR; 56001 this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR; 56002 56003 if (this.delay >= this.duration) { 56004 throw new Error('Vivus [constructor]: delay must be shorter than duration'); 56005 } 56006}; 56007 56008/** 56009 * Set up callback to the instance 56010 * The method will not return enything, but will throw an 56011 * error if the parameter is invalid 56012 * 56013 * @param {Function} callback Callback for the animation end 56014 */ 56015Vivus.prototype.setCallback = function (callback) { 56016 // Basic check 56017 if (!!callback && callback.constructor !== Function) { 56018 throw new Error('Vivus [constructor]: "callback" parameter must be a function'); 56019 } 56020 this.callback = callback || function () {}; 56021}; 56022 56023 56024/** 56025 * Core 56026 ************************************** 56027 */ 56028 56029/** 56030 * Map the svg, path by path. 56031 * The method return nothing, it just fill the 56032 * `map` array. Each item in this array represent 56033 * a path element from the SVG, with informations for 56034 * the animation. 56035 * 56036 * ``` 56037 * [ 56038 * { 56039 * el: <DOMobj> the path element 56040 * length: <number> length of the path line 56041 * startAt: <number> time start of the path animation (in frames) 56042 * duration: <number> path animation duration (in frames) 56043 * }, 56044 * ... 56045 * ] 56046 * ``` 56047 * 56048 */ 56049Vivus.prototype.mapping = function () { 56050 var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint; 56051 timePoint = totalLength = lengthMeter = 0; 56052 paths = this.el.querySelectorAll('path'); 56053 56054 for (i = 0; i < paths.length; i++) { 56055 path = paths[i]; 56056 if (this.isInvisible(path)) { 56057 continue; 56058 } 56059 pathObj = { 56060 el: path, 56061 length: Math.ceil(path.getTotalLength()) 56062 }; 56063 // Test if the path length is correct 56064 if (isNaN(pathObj.length)) { 56065 if (window.console && console.warn) { 56066 console.warn('Vivus [mapping]: cannot retrieve a path element length', path); 56067 } 56068 continue; 56069 } 56070 this.map.push(pathObj); 56071 path.style.strokeDasharray = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2); 56072 path.style.strokeDashoffset = pathObj.length + this.dashGap; 56073 pathObj.length += this.dashGap; 56074 totalLength += pathObj.length; 56075 56076 this.renderPath(i); 56077 } 56078 56079 totalLength = totalLength === 0 ? 1 : totalLength; 56080 this.delay = this.delay === null ? this.duration / 3 : this.delay; 56081 this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1); 56082 56083 // Reverse stack if asked 56084 if (this.reverseStack) { 56085 this.map.reverse(); 56086 } 56087 56088 for (i = 0; i < this.map.length; i++) { 56089 pathObj = this.map[i]; 56090 56091 switch (this.type) { 56092 case 'delayed': 56093 pathObj.startAt = this.delayUnit * i; 56094 pathObj.duration = this.duration - this.delay; 56095 break; 56096 56097 case 'oneByOne': 56098 pathObj.startAt = lengthMeter / totalLength * this.duration; 56099 pathObj.duration = pathObj.length / totalLength * this.duration; 56100 break; 56101 56102 case 'sync': 56103 case 'async': 56104 case 'nsync': 56105 pathObj.startAt = 0; 56106 pathObj.duration = this.duration; 56107 break; 56108 56109 case 'scenario-sync': 56110 path = pathObj.el; 56111 pAttrs = this.parseAttr(path); 56112 pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0); 56113 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 56114 timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration; 56115 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 56116 break; 56117 56118 case 'scenario': 56119 path = pathObj.el; 56120 pAttrs = this.parseAttr(path); 56121 pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0; 56122 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 56123 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 56124 break; 56125 } 56126 lengthMeter += pathObj.length; 56127 this.frameLength = this.frameLength || this.duration; 56128 } 56129}; 56130 56131/** 56132 * Interval method to draw the SVG from current 56133 * position of the animation. It update the value of 56134 * `currentFrame` and re-trace the SVG. 56135 * 56136 * It use this.handle to store the requestAnimationFrame 56137 * and clear it one the animation is stopped. So this 56138 * attribute can be used to know if the animation is 56139 * playing. 56140 * 56141 * Once the animation at the end, this method will 56142 * trigger the Vivus callback. 56143 * 56144 */ 56145Vivus.prototype.drawer = function () { 56146 var self = this; 56147 this.currentFrame += this.speed; 56148 56149 if (this.currentFrame <= 0) { 56150 this.stop(); 56151 this.reset(); 56152 } else if (this.currentFrame >= this.frameLength) { 56153 this.stop(); 56154 this.currentFrame = this.frameLength; 56155 this.trace(); 56156 if (this.selfDestroy) { 56157 this.destroy(); 56158 } 56159 } else { 56160 this.trace(); 56161 this.handle = requestAnimFrame(function () { 56162 self.drawer(); 56163 }); 56164 return; 56165 } 56166 56167 this.callback(this); 56168 if (this.instanceCallback) { 56169 this.instanceCallback(this); 56170 this.instanceCallback = null; 56171 } 56172}; 56173 56174/** 56175 * Draw the SVG at the current instant from the 56176 * `currentFrame` value. Here is where most of the magic is. 56177 * The trick is to use the `strokeDashoffset` style property. 56178 * 56179 * For optimisation reasons, a new property called `progress` 56180 * is added in each item of `map`. This one contain the current 56181 * progress of the path element. Only if the new value is different 56182 * the new value will be applied to the DOM element. This 56183 * method save a lot of resources to re-render the SVG. And could 56184 * be improved if the animation couldn't be played forward. 56185 * 56186 */ 56187Vivus.prototype.trace = function () { 56188 var i, progress, path, currentFrame; 56189 currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength; 56190 for (i = 0; i < this.map.length; i++) { 56191 path = this.map[i]; 56192 progress = (currentFrame - path.startAt) / path.duration; 56193 progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress))); 56194 if (path.progress !== progress) { 56195 path.progress = progress; 56196 path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress)); 56197 this.renderPath(i); 56198 } 56199 } 56200}; 56201 56202/** 56203 * Method forcing the browser to re-render a path element 56204 * from it's index in the map. Depending on the `forceRender` 56205 * value. 56206 * The trick is to replace the path element by it's clone. 56207 * This practice is not recommended because it's asking more 56208 * ressources, too much DOM manupulation.. 56209 * but it's the only way to let the magic happen on IE. 56210 * By default, this fallback is only applied on IE. 56211 * 56212 * @param {Number} index Path index 56213 */ 56214Vivus.prototype.renderPath = function (index) { 56215 if (this.forceRender && this.map && this.map[index]) { 56216 var pathObj = this.map[index], 56217 newPath = pathObj.el.cloneNode(true); 56218 pathObj.el.parentNode.replaceChild(newPath, pathObj.el); 56219 pathObj.el = newPath; 56220 } 56221}; 56222 56223/** 56224 * When the SVG object is loaded and ready, 56225 * this method will continue the initialisation. 56226 * 56227 * This this mainly due to the case of passing an 56228 * object tag in the constructor. It will wait 56229 * the end of the loading to initialise. 56230 * 56231 */ 56232Vivus.prototype.init = function () { 56233 // Set object variables 56234 this.frameLength = 0; 56235 this.currentFrame = 0; 56236 this.map = []; 56237 56238 // Start 56239 new Pathformer(this.el); 56240 this.mapping(); 56241 this.starter(); 56242 56243 if (this.onReady) { 56244 this.onReady(this); 56245 } 56246}; 56247 56248/** 56249 * Trigger to start of the animation. 56250 * Depending on the `start` value, a different script 56251 * will be applied. 56252 * 56253 * If the `start` value is not valid, an error will be thrown. 56254 * Even if technically, this is impossible. 56255 * 56256 */ 56257Vivus.prototype.starter = function () { 56258 switch (this.start) { 56259 case 'manual': 56260 return; 56261 56262 case 'autostart': 56263 this.play(); 56264 break; 56265 56266 case 'inViewport': 56267 var self = this, 56268 listener = function () { 56269 if (self.isInViewport(self.parentEl, 1)) { 56270 self.play(); 56271 window.removeEventListener('scroll', listener); 56272 //Uncode addition 56273 window.removeEventListener('fp-slide-changed', listener); 56274 window.removeEventListener('fp-slide-scroll', listener); 56275 //#END 56276 } 56277 }; 56278 window.addEventListener('scroll', listener); 56279 //Uncode addition 56280 window.addEventListener('fp-slide-changed', listener); 56281 window.addEventListener('fp-slide-scroll', listener); 56282 //#END 56283 listener(); 56284 break; 56285 } 56286}; 56287 56288 56289/** 56290 * Controls 56291 ************************************** 56292 */ 56293 56294/** 56295 * Get the current status of the animation between 56296 * three different states: 'start', 'progress', 'end'. 56297 * @return {string} Instance status 56298 */ 56299Vivus.prototype.getStatus = function () { 56300 return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress'; 56301}; 56302 56303/** 56304 * Reset the instance to the initial state : undraw 56305 * Be careful, it just reset the animation, if you're 56306 * playing the animation, this won't stop it. But just 56307 * make it start from start. 56308 * 56309 */ 56310Vivus.prototype.reset = function () { 56311 return this.setFrameProgress(0); 56312}; 56313 56314/** 56315 * Set the instance to the final state : drawn 56316 * Be careful, it just set the animation, if you're 56317 * playing the animation on rewind, this won't stop it. 56318 * But just make it start from the end. 56319 * 56320 */ 56321Vivus.prototype.finish = function () { 56322 return this.setFrameProgress(1); 56323}; 56324 56325/** 56326 * Set the level of progress of the drawing. 56327 * 56328 * @param {number} progress Level of progress to set 56329 */ 56330Vivus.prototype.setFrameProgress = function (progress) { 56331 progress = Math.min(1, Math.max(0, progress)); 56332 this.currentFrame = Math.round(this.frameLength * progress); 56333 this.trace(); 56334 return this; 56335}; 56336 56337/** 56338 * Play the animation at the desired speed. 56339 * Speed must be a valid number (no zero). 56340 * By default, the speed value is 1. 56341 * But a negative value is accepted to go forward. 56342 *
56343 * And works with float too. 56344 * But don't forget we are in JavaScript, se be nice 56345 * with him and give him a 1/2^x value. 56346 * 56347 * @param {number} speed Animation speed [optional] 56348 */ 56349Vivus.prototype.play = function (speed, callback) { 56350 this.instanceCallback = null; 56351 56352 if (speed && typeof speed === 'function') { 56353 this.instanceCallback = speed; // first parameter is actually the callback function 56354 speed = null; 56355 } 56356 else if (speed && typeof speed !== 'number') { 56357 throw new Error('Vivus [play]: invalid speed'); 56358 } 56359 // if the first parameter wasn't the callback, check if the seconds was 56360 if (callback && typeof(callback) === 'function' && !this.instanceCallback) { 56361 this.instanceCallback = callback; 56362 } 56363 56364 56365 this.speed = speed || 1; 56366 //Uncode addition 56367 if (!this.handle) { 56368 var $this = this, 56369 delay = (this.delayStart != null) ? this.delayStart : 0; 56370 setTimeout(function() { 56371 $this.drawer(); 56372 }, delay); 56373 } 56374 //#END 56375 return this; 56376}; 56377 56378/** 56379 * Stop the current animation, if on progress. 56380 * Should not trigger any error. 56381 * 56382 */ 56383Vivus.prototype.stop = function () { 56384 if (this.handle) { 56385 cancelAnimFrame(this.handle); 56386 this.handle = null; 56387 } 56388 return this; 56389}; 56390 56391/** 56392 * Destroy the instance. 56393 * Remove all bad styling attributes on all 56394 * path tags 56395 * 56396 */ 56397Vivus.prototype.destroy = function () { 56398 this.stop(); 56399 var i, path; 56400 for (i = 0; i < this.map.length; i++) { 56401 path = this.map[i]; 56402 path.el.style.strokeDashoffset = null; 56403 path.el.style.strokeDasharray = null; 56404 this.renderPath(i); 56405 } 56406}; 56407 56408 56409/** 56410 * Utils methods 56411 * include methods from Codrops 56412 ************************************** 56413 */ 56414 56415/** 56416 * Method to best guess if a path should added into 56417 * the animation or not. 56418 * 56419 * 1. Use the `data-vivus-ignore` attribute if set 56420 * 2. Check if the instance must ignore invisible paths 56421 * 3. Check if the path is visible 56422 * 56423 * For now the visibility checking is unstable. 56424 * It will be used for a beta phase. 56425 * 56426 * Other improvments are planned. Like detecting 56427 * is the path got a stroke or a valid opacity. 56428 */ 56429Vivus.prototype.isInvisible = function (el) { 56430 var rect, 56431 ignoreAttr = el.getAttribute('data-ignore'); 56432 56433 if (ignoreAttr !== null) { 56434 return ignoreAttr !== 'false'; 56435 } 56436 56437 if (this.ignoreInvisible) { 56438 rect = el.getBoundingClientRect(); 56439 return !rect.width && !rect.height; 56440 } 56441 else { 56442 return false; 56443 } 56444}; 56445 56446/** 56447 * Parse attributes of a DOM element to 56448 * get an object of {attributeName => attributeValue} 56449 * 56450 * @param {object} element DOM element to parse 56451 * @return {object} Object of attributes 56452 */ 56453Vivus.prototype.parseAttr = function (element) { 56454 var attr, output = {}; 56455 if (element && element.attributes) { 56456 for (var i = 0; i < element.attributes.length; i++) { 56457 attr = element.attributes[i]; 56458 output[attr.name] = attr.value; 56459 } 56460 } 56461 return output; 56462}; 56463 56464/** 56465 * Reply if an element is in the page viewport 56466 * 56467 * @param {object} el Element to observe 56468 * @param {number} h Percentage of height 56469 * @return {boolean} 56470 */ 56471Vivus.prototype.isInViewport = function (el, h) { 56472 var scrolled = this.scrollY(), 56473 viewed = scrolled + this.getViewportH(), 56474 elBCR = el.getBoundingClientRect(), 56475 elHeight = elBCR.height, 56476 elTop = scrolled + elBCR.top, 56477 elBottom = elTop + elHeight; 56478 56479 // if 0, the element is considered in the viewport as soon as it enters. 56480 // if 1, the element is considered in the viewport only when it's fully inside 56481 // value in percentage (1 >= h >= 0) 56482 h = h || 0; 56483 56484 return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled; 56485}; 56486 56487 56488/** 56489 * Get the viewport height in pixels 56490 * 56491 * @return {integer} Viewport height 56492 */ 56493Vivus.prototype.getViewportH = function () { 56494 var client = this.docElem.clientHeight, 56495 inner = window.innerHeight; 56496 56497 if (client < inner) { 56498 return inner; 56499 } 56500 else { 56501 return client; 56502 } 56503}; 56504 56505/** 56506 * Get the page Y offset 56507 * 56508 * @return {integer} Page Y offset 56509 */ 56510Vivus.prototype.scrollY = function () { 56511 return window.pageYOffset || this.docElem.scrollTop; 56512}; 56513 56514setupEnv = function () { 56515 56516 if (Vivus.prototype.docElem) { 56517 return; 56518 } 56519 56520 /** 56521 * Alias for document element 56522 * 56523 * @type {DOMelement} 56524 */ 56525 Vivus.prototype.docElem = window.document.documentElement; 56526 56527 /** 56528 * Alias for `requestAnimationFrame` or 56529 * `setTimeout` function for deprecated browsers. 56530 * 56531 */ 56532 requestAnimFrame = (function () { 56533 return ( 56534 window.requestAnimationFrame || 56535 window.webkitRequestAnimationFrame || 56536 window.mozRequestAnimationFrame || 56537 window.oRequestAnimationFrame || 56538 window.msRequestAnimationFrame || 56539 function(/* function */ callback){ 56540 return window.setTimeout(callback, 1000 / 60); 56541 } 56542 ); 56543 })(); 56544 56545 /** 56546 * Alias for `cancelAnimationFrame` or 56547 * `cancelTimeout` function for deprecated browsers. 56548 * 56549 */ 56550 cancelAnimFrame = (function () { 56551 return ( 56552 window.cancelAnimationFrame || 56553 window.webkitCancelAnimationFrame || 56554 window.mozCancelAnimationFrame || 56555 window.oCancelAnimationFrame || 56556 window.msCancelAnimationFrame || 56557 function(id){ 56558 return window.clearTimeout(id); 56559 } 56560 ); 56561 })(); 56562}; 56563 56564/** 56565 * Parse string to integer. 56566 * If the number is not positive or null 56567 * the method will return the default value 56568 * or 0 if undefined 56569 * 56570 * @param {string} value String to parse 56571 * @param {*}
56571 defaultValue Value to return if the result parsed is invalid 56572 * @return {number} 56573 * 56574 */ 56575parsePositiveInt = function (value, defaultValue) { 56576 var output = parseInt(value, 10); 56577 return (output >= 0) ? output : defaultValue; 56578}; 56579 56580 56581 if (typeof define === 'function' && define.amd) { 56582 // AMD. Register as an anonymous module. 56583 define([], function() { 56584 return Vivus; 56585 }); 56586 } else if (typeof exports === 'object') { 56587 // Node. Does not work with strict CommonJS, but 56588 // only CommonJS-like environments that support module.exports, 56589 // like Node. 56590 module.exports = Vivus; 56591 } else { 56592 // Browser globals 56593 window.Vivus = Vivus; 56594 } 56595 56596}()); 56597 56598//Noise.js 56599!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)}
56599var 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.