vendor: 4,719 bytes, lines 1-147
1/* ---------------------------------------------------------- 2 * Plugins 3 * ---------------------------------------------------------- */ 4 5(function (global, factory) { 6 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 7 typeof define === 'function' && define.amd ? define(['exports'], factory) : 8 (global = global || self, factory(global.window = global.window || {})); 9}(this, (function (exports) { 'use strict'; 10 11 function _inheritsLoose(subClass, superClass) { 12 subClass.prototype = Object.create(superClass.prototype); 13 subClass.prototype.constructor = subClass; 14 subClass.__proto__ = superClass; 15 } 16 17 function _assertThisInitialized(self) { 18 if (self === void 0) { 19 throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 20 } 21 22 return self; 23 } 24 25 /*! 26 * GSAP 3.6.1 27 * https://greensock.com 28 * 29 * @license Copyright 2008-2021, GreenSock. All rights reserved. 30 * Subject to the terms at https://greensock.com/standard-license or for 31 * Club GreenSock members, the agreement issued with that membership. 32 * @author: Jack Doyle, [email protected] 33 */ 34 var _config = { 35 autoSleep: 120, 36 force3D: "auto", 37 nullTargetWarn: 1, 38 units: { 39 lineHeight: "" 40 } 41 }, 42 _defaults = { 43 duration: .5, 44 overwrite: false, 45 delay: 0 46 }, 47 _suppressOverwrites, 48 _bigNum = 1e8, 49 _tinyNum = 1 / _bigNum, 50 _2PI = Math.PI * 2, 51 _HALF_PI = _2PI / 4, 52 _gsID = 0, 53 _sqrt = Math.sqrt, 54 _cos = Math.cos, 55 _sin = Math.sin, 56 _isString = function _isString(value) { 57 return typeof value === "string"; 58 }, 59 _isFunction = function _isFunction(value) { 60 return typeof value === "function"; 61 }, 62 _isNumber = function _isNumber(value) { 63 return typeof value === "number"; 64 }, 65 _isUndefined = function _isUndefined(value) { 66 return typeof value === "undefined"; 67 }, 68 _isObject = function _isObject(value) { 69 return typeof value === "object"; 70 }, 71 _isNotFalse = function _isNotFalse(value) { 72 return value !== false; 73 }, 74 _windowExists = function _windowExists() { 75 return typeof window !== "undefined"; 76 }, 77 _isFuncOrString = function _isFuncOrString(value) { 78 return _isFunction(value) || _isString(value); 79 }, 80 _isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView || function () {}, 81 _isArray = Array.isArray, 82 _strictNumExp = /(?:-?\.?\d|\.)+/gi, 83 _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/g, 84 _numWithUnitExp = /[-+=.]*\d+[.e-]*\d*[a-z%]*/g, 85 _complexStringNumExp = /[-+=.]*\d+\.?\d*(?:e-|e\+)?\d*/gi, 86 _relExp = /[+-]=-?[.\d]+/, 87 _delimitedValueExp = /[#\-+.]*\b[a-z\d-=+%.]+/gi, 88 _unitExp = /[\d.+\-=]+(?:e[-+]\d*)*/i, 89 _globalTimeline, 90 _win, 91 _coreInitted, 92 _doc, 93 _globals = {}, 94 _installScope = {}, 95 _coreReady, 96 _install = function _install(scope) { 97 return (_installScope = _merge(scope, _globals)) && gsap; 98 }, 99 _missingPlugin = function _missingPlugin(property, value) { 100 return console.warn("Invalid property", property, "set to", value, "Missing plugin? gsap.registerPlugin()"); 101 }, 102 _warn = function _warn(message, suppress) { 103 return !suppress && console.warn(message); 104 }, 105 _addGlobal = function _addGlobal(name, obj) { 106 return name && (_globals[name] = obj) && _installScope && (_installScope[name] = obj) || _globals; 107 }, 108 _emptyFunc = function _emptyFunc() { 109 return 0; 110 }, 111 _reservedProps = {}, 112 _lazyTweens = [], 113 _lazyLookup = {}, 114 _lastRenderedFrame, 115 _plugins = {}, 116 _effects = {}, 117 _nextGCFrame = 30, 118 _harnessPlugins = [], 119 _callbackNames = "", 120 _harness = function _harness(targets) { 121 var target = targets[0], 122 harnessPlugin, 123 i; 124 _isObject(target) || _isFunction(target) || (targets = [targets]); 125 126 if (!(harnessPlugin = (target._gsap || {}).harness)) { 127 i = _harnessPlugins.length; 128 129 while (i-- && !_harnessPlugins[i].targetTest(target)) {} 130 131 harnessPlugin = _harnessPlugins[i]; 132 } 133 134 i = targets.length; 135 136 while (i--) { 137 targets[i] && (targets[i]._gsap || (targets[i]._gsap = new GSCache(targets[i], harnessPlugin))) || targets.splice(i, 1); 138 } 139 140 return targets; 141 }, 142 _getCache = function _getCache(target) { 143 return target._gsap || _harness(toArray(target))[0]._gsap; 144 }, 145 _getProperty = function _getProperty(target, property, v) { 146 return (v = target[property]) && _isFunction(v) ? target[property]() : _isUndefined(v) && target.getAttribute && target.getAttribute(property) || v; 147 },
vendor: 7,717 bytes, lines 148-411
148 _forEachName = function _forEachName(names, func) { 149 return (names = names.split(",")).forEach(func) || names; 150 }, 151 _round = function _round(value) { 152 return Math.round(value * 100000) / 100000 || 0; 153 }, 154 _arrayContainsAny = function _arrayContainsAny(toSearch, toFind) { 155 var l = toFind.length, 156 i = 0; 157 158 for (; toSearch.indexOf(toFind[i]) < 0 && ++i < l;) {} 159 160 return i < l; 161 }, 162 _parseVars = function _parseVars(params, type, parent) { 163 var isLegacy = _isNumber(params[1]), 164 varsIndex = (isLegacy ? 2 : 1) + (type < 2 ? 0 : 1), 165 vars = params[varsIndex], 166 irVars; 167 168 isLegacy && (vars.duration = params[1]); 169 vars.parent = parent; 170 171 if (type) { 172 irVars = vars; 173 174 while (parent && !("immediateRender" in irVars)) { 175 irVars = parent.vars.defaults || {}; 176 parent = _isNotFalse(parent.vars.inherit) && parent.parent; 177 } 178 179 vars.immediateRender = _isNotFalse(irVars.immediateRender); 180 type < 2 ? vars.runBackwards = 1 : vars.startAt = params[varsIndex - 1]; 181 } 182 183 return vars; 184 }, 185 _lazyRender = function _lazyRender() { 186 var l = _lazyTweens.length, 187 a = _lazyTweens.slice(0), 188 i, 189 tween; 190 191 _lazyLookup = {}; 192 _lazyTweens.length = 0; 193 194 for (i = 0; i < l; i++) { 195 tween = a[i]; 196 tween && tween._lazy && (tween.render(tween._lazy[0], tween._lazy[1], true)._lazy = 0); 197 } 198 }, 199 _lazySafeRender = function _lazySafeRender(animation, time, suppressEvents, force) { 200 _lazyTweens.length && _lazyRender(); 201 animation.render(time, suppressEvents, force); 202 _lazyTweens.length && _lazyRender(); 203 }, 204 _numericIfPossible = function _numericIfPossible(value) { 205 var n = parseFloat(value); 206 return (n || n === 0) && (value + "").match(_delimitedValueExp).length < 2 ? n : _isString(value) ? value.trim() : value; 207 }, 208 _passThrough = function _passThrough(p) { 209 return p; 210 }, 211 _setDefaults = function _setDefaults(obj, defaults) { 212 for (var p in defaults) { 213 p in obj || (obj[p] = defaults[p]); 214 } 215 216 return obj; 217 }, 218 _setKeyframeDefaults = function _setKeyframeDefaults(obj, defaults) { 219 for (var p in defaults) { 220 p in obj || p === "duration" || p === "ease" || (obj[p] = defaults[p]); 221 } 222 }, 223 _merge = function _merge(base, toMerge) { 224 for (var p in toMerge) { 225 base[p] = toMerge[p]; 226 } 227 228 return base; 229 }, 230 _mergeDeep = function _mergeDeep(base, toMerge) { 231 for (var p in toMerge) { 232 p !== "__proto__" && p !== "constructor" && p !== "prototype" && (base[p] = _isObject(toMerge[p]) ? _mergeDeep(base[p] || (base[p] = {}), toMerge[p]) : toMerge[p]); 233 } 234 235 return base; 236 }, 237 _copyExcluding = function _copyExcluding(obj, excluding) { 238 var copy = {}, 239 p; 240 241 for (p in obj) { 242 p in excluding || (copy[p] = obj[p]); 243 } 244 245 return copy; 246 }, 247 _inheritDefaults = function _inheritDefaults(vars) { 248 var parent = vars.parent || _globalTimeline, 249 func = vars.keyframes ? _setKeyframeDefaults : _setDefaults; 250 251 if (_isNotFalse(vars.inherit)) { 252 while (parent) { 253 func(vars, parent.vars.defaults); 254 parent = parent.parent || parent._dp; 255 } 256 } 257 258 return vars; 259 }, 260 _arraysMatch = function _arraysMatch(a1, a2) { 261 var i = a1.length, 262 match = i === a2.length; 263 264 while (match && i-- && a1[i] === a2[i]) {} 265 266 return i < 0; 267 }, 268 _addLinkedListItem = function _addLinkedListItem(parent, child, firstProp, lastProp, sortBy) { 269 if (firstProp === void 0) { 270 firstProp = "_first"; 271 } 272 273 if (lastProp === void 0) { 274 lastProp = "_last"; 275 } 276 277 var prev = parent[lastProp], 278 t; 279 280 if (sortBy) { 281 t = child[sortBy]; 282 283 while (prev && prev[sortBy] > t) { 284 prev = prev._prev; 285 } 286 } 287 288 if (prev) { 289 child._next = prev._next; 290 prev._next = child; 291 } else { 292 child._next = parent[firstProp]; 293 parent[firstProp] = child; 294 } 295 296 if (child._next) { 297 child._next._prev = child; 298 } else { 299 parent[lastProp] = child; 300 } 301 302 child._prev = prev; 303 child.parent = child._dp = parent; 304 return child; 305 }, 306 _removeLinkedListItem = function _removeLinkedListItem(parent, child, firstProp, lastProp) { 307 if (firstProp === void 0) { 308 firstProp = "_first"; 309 } 310 311 if (lastProp === void 0) { 312 lastProp = "_last"; 313 } 314 315 var prev = child._prev, 316 next = child._next; 317 318 if (prev) { 319 prev._next = next; 320 } else if (parent[firstProp] === child) { 321 parent[firstProp] = next; 322 } 323 324 if (next) { 325 next._prev = prev; 326 } else if (parent[lastProp] === child) { 327 parent[lastProp] = prev; 328 } 329 330 child._next = child._prev = child.parent = null; 331 }, 332 _removeFromParent = function _removeFromParent(child, onlyIfParentHasAutoRemove) { 333 child.parent && (!onlyIfParentHasAutoRemove || child.parent.autoRemoveChildren) && child.parent.remove(child); 334 child._act = 0; 335 }, 336 _uncache = function _uncache(animation, child) { 337 if (animation && (!child || child._end > animation._dur || child._start < 0)) { 338 var a = animation; 339 340 while (a) { 341 a._dirty = 1; 342 a = a.parent; 343 } 344 } 345 346 return animation; 347 }, 348 _recacheAncestors = function _recacheAncestors(animation) { 349 var parent = animation.parent; 350 351 while (parent && parent.parent) { 352 parent._dirty = 1; 353 parent.totalDuration(); 354 parent = parent.parent; 355 } 356 357 return animation; 358 }, 359 _hasNoPausedAncestors = function _hasNoPausedAncestors(animation) { 360 return !animation || animation._ts && _hasNoPausedAncestors(animation.parent); 361 }, 362 _elapsedCycleDuration = function _elapsedCycleDuration(animation) { 363 return animation._repeat ? _animationCycle(animation._tTime, animation = animation.duration() + animation._rDelay) * animation : 0; 364 }, 365 _animationCycle = function _animationCycle(tTime, cycleDuration) { 366 var whole = Math.floor(tTime /= cycleDuration); 367 return tTime && whole === tTime ? whole - 1 : whole; 368 }, 369 _parentToChildTotalTime = function _parentToChildTotalTime(parentTime, child) { 370 return (parentTime - child._start) * child._ts + (child._ts >= 0 ? 0 : child._dirty ? child.totalDuration() : child._tDur); 371 }, 372 _setEnd = function _setEnd(animation) { 373 return animation._end = _round(animation._start + (animation._tDur / Math.abs(animation._ts || animation._rts || _tinyNum) || 0)); 374 }, 375 _alignPlayhead = function _alignPlayhead(animation, totalTime) { 376 var parent = animation._dp; 377 378 if (parent && parent.smoothChildTiming && animation._ts) { 379 animation._start = _round(parent._time - (animation._ts > 0 ? totalTime / animation._ts : ((animation._dirty ? animation.totalDuration() : animation._tDur) - totalTime) / -animation._ts)); 380 381 _setEnd(animation); 382 383 parent._dirty || _uncache(parent, animation); 384 } 385 386 return animation; 387 }, 388 _postAddChecks = function _postAddChecks(timeline, child) { 389 var t; 390 391 if (child._time || child._initted && !child._dur) { 392 t = _parentToChildTotalTime(timeline.rawTime(), child); 393 394 if (!child._dur || _clamp(0, child.totalDuration(), t) - child._tTime > _tinyNum) { 395 child.render(t, true); 396 } 397 } 398 399 if (_uncache(timeline, child)._dp && timeline._initted && timeline._time >= timeline._dur && timeline._ts) { 400 if (timeline._dur < timeline.duration()) { 401 t = timeline; 402 403 while (t._dp) { 404 t.rawTime() >= 0 && t.totalTime(t._tTime); 405 t = t._dp; 406 } 407 } 408 409 timeline._zTime = -_tinyNum; 410 } 411 },
412 _addToTimeline = function _addToTimeline(timeline, child, position, skipChecks) { 413 child.parent && _removeFromParent(child); 414 child._start = _round(position + child._delay); 415 child._end = _round(child._start + (child.totalDuration() / Math.abs(child.timeScale()) || 0)); 416 417 _addLinkedListItem(timeline, child, "_first", "_last", timeline._sort ? "_start" : 0); 418 419 timeline._recent = child; 420 skipChecks || _postAddChecks(timeline, child); 421 return timeline; 422 }, 423 _scrollTrigger = function _scrollTrigger(animation, trigger) { 424 return (_globals.ScrollTrigger || _missingPlugin("scrollTrigger", trigger)) && _globals.ScrollTrigger.create(trigger, animation); 425 }, 426 _attemptInitTween = function _attemptInitTween(tween, totalTime, force, suppressEvents) { 427 _initTween(tween, totalTime); 428 429 if (!tween._initted) { 430 return 1; 431 } 432 433 if (!force && tween._pt && (tween._dur && tween.vars.lazy !== false || !tween._dur && tween.vars.lazy) && _lastRenderedFrame !== _ticker.frame) { 434 _lazyTweens.push(tween); 435 436 tween._lazy = [totalTime, suppressEvents]; 437 return 1; 438 } 439 }, 440 _parentPlayheadIsBeforeStart = function _parentPlayheadIsBeforeStart(_ref) { 441 var parent = _ref.parent; 442 return parent && parent._ts && parent._initted && !parent._lock && (parent.rawTime() < 0 || _parentPlayheadIsBeforeStart(parent)); 443 }, 444 _renderZeroDurationTween = function _renderZeroDurationTween(tween, totalTime, suppressEvents, force) { 445 var prevRatio = tween.ratio, 446 ratio = totalTime < 0 || !totalTime && (!tween._start && _parentPlayheadIsBeforeStart(tween) || (tween._ts < 0 || tween._dp._ts < 0) && tween.data !== "isFromStart" && tween.data !== "isStart") ? 0 : 1, 447 repeatDelay = tween._rDelay, 448 tTime = 0, 449 pt, 450 iteration, 451 prevIteration; 452 453 if (repeatDelay && tween._repeat) { 454 tTime = _clamp(0, tween._tDur, totalTime); 455 iteration = _animationCycle(tTime, repeatDelay); 456 prevIteration = _animationCycle(tween._tTime, repeatDelay); 457 tween._yoyo && iteration & 1 && (ratio = 1 - ratio); 458 459 if (iteration !== prevIteration) { 460 prevRatio = 1 - ratio; 461 tween.vars.repeatRefresh && tween._initted && tween.invalidate(); 462 } 463 } 464 465 if (ratio !== prevRatio || force || tween._zTime === _tinyNum || !totalTime && tween._zTime) { 466 if (!tween._initted && _attemptInitTween(tween, totalTime, force, suppressEvents)) { 467 return; 468 } 469 470 prevIteration = tween._zTime; 471 tween._zTime = totalTime || (suppressEvents ? _tinyNum : 0); 472 suppressEvents || (suppressEvents = totalTime && !prevIteration); 473 tween.ratio = ratio; 474 tween._from && (ratio = 1 - ratio); 475 tween._time = 0; 476 tween._tTime = tTime; 477 pt = tween._pt; 478 479 while (pt) { 480 pt.r(ratio, pt.d); 481 pt = pt._next; 482 } 483 484 tween._startAt && totalTime < 0 && tween._startAt.render(totalTime, true, true);
vendor: 9,020 bytes, lines 485-753
485 tween._onUpdate && !suppressEvents && _callback(tween, "onUpdate"); 486 tTime && tween._repeat && !suppressEvents && tween.parent && _callback(tween, "onRepeat"); 487 488 if ((totalTime >= tween._tDur || totalTime < 0) && tween.ratio === ratio) { 489 ratio && _removeFromParent(tween, 1); 490 491 if (!suppressEvents) { 492 _callback(tween, ratio ? "onComplete" : "onReverseComplete", true); 493 494 tween._prom && tween._prom(); 495 } 496 } 497 } else if (!tween._zTime) { 498 tween._zTime = totalTime; 499 } 500 }, 501 _findNextPauseTween = function _findNextPauseTween(animation, prevTime, time) { 502 var child; 503 504 if (time > prevTime) { 505 child = animation._first; 506 507 while (child && child._start <= time) { 508 if (!child._dur && child.data === "isPause" && child._start > prevTime) { 509 return child; 510 } 511 512 child = child._next; 513 } 514 } else { 515 child = animation._last; 516 517 while (child && child._start >= time) { 518 if (!child._dur && child.data === "isPause" && child._start < prevTime) { 519 return child; 520 } 521 522 child = child._prev; 523 } 524 } 525 }, 526 _setDuration = function _setDuration(animation, duration, skipUncache, leavePlayhead) { 527 var repeat = animation._repeat, 528 dur = _round(duration) || 0, 529 totalProgress = animation._tTime / animation._tDur; 530 totalProgress && !leavePlayhead && (animation._time *= dur / animation._dur); 531 animation._dur = dur; 532 animation._tDur = !repeat ? dur : repeat < 0 ? 1e10 : _round(dur * (repeat + 1) + animation._rDelay * repeat); 533 totalProgress && !leavePlayhead ? _alignPlayhead(animation, animation._tTime = animation._tDur * totalProgress) : animation.parent && _setEnd(animation); 534 skipUncache || _uncache(animation.parent, animation); 535 return animation; 536 }, 537 _onUpdateTotalDuration = function _onUpdateTotalDuration(animation) { 538 return animation instanceof Timeline ? _uncache(animation) : _setDuration(animation, animation._dur); 539 }, 540 _zeroPosition = { 541 _start: 0, 542 endTime: _emptyFunc 543 }, 544 _parsePosition = function _parsePosition(animation, position) { 545 var labels = animation.labels, 546 recent = animation._recent || _zeroPosition, 547 clippedDuration = animation.duration() >= _bigNum ? recent.endTime(false) : animation._dur, 548 i, 549 offset; 550 551 if (_isString(position) && (isNaN(position) || position in labels)) { 552 i = position.charAt(0); 553 554 if (i === "<" || i === ">") { 555 return (i === "<" ? recent._start : recent.endTime(recent._repeat >= 0)) + (parseFloat(position.substr(1)) || 0); 556 } 557 558 i = position.indexOf("="); 559 560 if (i < 0) { 561 position in labels || (labels[position] = clippedDuration); 562 return labels[position]; 563 } 564 565 offset = +(position.charAt(i - 1) + position.substr(i + 1)); 566 return i > 1 ? _parsePosition(animation, position.substr(0, i - 1)) + offset : clippedDuration + offset; 567 } 568 569 return position == null ? clippedDuration : +position; 570 }, 571 _conditionalReturn = function _conditionalReturn(value, func) { 572 return value || value === 0 ? func(value) : func; 573 }, 574 _clamp = function _clamp(min, max, value) { 575 return value < min ? min : value > max ? max : value; 576 }, 577 getUnit = function getUnit(value) { 578 if (typeof value !== "string") { 579 return ""; 580 } 581 582 var v = _unitExp.exec(value); 583 584 return v ? value.substr(v.index + v[0].length) : ""; 585 }, 586 clamp = function clamp(min, max, value) { 587 return _conditionalReturn(value, function (v) { 588 return _clamp(min, max, v); 589 }); 590 }, 591 _slice = [].slice, 592 _isArrayLike = function _isArrayLike(value, nonEmpty) { 593 return value && _isObject(value) && "length" in value && (!nonEmpty && !value.length || value.length - 1 in value && _isObject(value[0])) && !value.nodeType && value !== _win; 594 }, 595 _flatten = function _flatten(ar, leaveStrings, accumulator) { 596 if (accumulator === void 0) { 597 accumulator = []; 598 } 599 600 return ar.forEach(function (value) { 601 var _accumulator; 602 603 return _isString(value) && !leaveStrings || _isArrayLike(value, 1) ? (_accumulator = accumulator).push.apply(_accumulator, toArray(value)) : accumulator.push(value); 604 }) || accumulator; 605 }, 606 toArray = function toArray(value, leaveStrings) { 607 return _isString(value) && !leaveStrings && (_coreInitted || !_wake()) ? _slice.call(_doc.querySelectorAll(value), 0) : _isArray(value) ? _flatten(value, leaveStrings) : _isArrayLike(value) ? _slice.call(value, 0) : value ? [value] : []; 608 }, 609 shuffle = function shuffle(a) { 610 return a.sort(function () { 611 return .5 - Math.random(); 612 }); 613 }, 614 distribute = function distribute(v) { 615 if (_isFunction(v)) { 616 return v; 617 } 618 619 var vars = _isObject(v) ? v : { 620 each: v 621 }, 622 ease = _parseEase(vars.ease), 623 from = vars.from || 0, 624 base = parseFloat(vars.base) || 0, 625 cache = {}, 626 isDecimal = from > 0 && from < 1, 627 ratios = isNaN(from) || isDecimal, 628 axis = vars.axis, 629 ratioX = from, 630 ratioY = from; 631 632 if (_isString(from)) { 633 ratioX = ratioY = { 634 center: .5, 635 edges: .5, 636 end: 1 637 }[from] || 0; 638 } else if (!isDecimal && ratios) { 639 ratioX = from[0]; 640 ratioY = from[1]; 641 } 642 643 return function (i, target, a) { 644 var l = (a || vars).length, 645 distances = cache[l], 646 originX, 647 originY, 648 x, 649 y, 650 d, 651 j, 652 max, 653 min, 654 wrapAt; 655 656 if (!distances) { 657 wrapAt = vars.grid === "auto" ? 0 : (vars.grid || [1, _bigNum])[1]; 658 659 if (!wrapAt) { 660 max = -_bigNum; 661 662 while (max < (max = a[wrapAt++].getBoundingClientRect().left) && wrapAt < l) {} 663 664 wrapAt--; 665 } 666 667 distances = cache[l] = []; 668 originX = ratios ? Math.min(wrapAt, l) * ratioX - .5 : from % wrapAt; 669 originY = ratios ? l * ratioY / wrapAt - .5 : from / wrapAt | 0; 670 max = 0; 671 min = _bigNum; 672 673 for (j = 0; j < l; j++) { 674 x = j % wrapAt - originX; 675 y = originY - (j / wrapAt | 0); 676 distances[j] = d = !axis ? _sqrt(x * x + y * y) : Math.abs(axis === "y" ? y : x); 677 d > max && (max = d); 678 d < min && (min = d); 679 } 680 681 from === "random" && shuffle(distances); 682 distances.max = max - min; 683 distances.min = min; 684 distances.v = l = (parseFloat(vars.amount) || parseFloat(vars.each) * (wrapAt > l ? l - 1 : !axis ? Math.max(wrapAt, l / wrapAt) : axis === "y" ? l / wrapAt : wrapAt) || 0) * (from === "edges" ? -1 : 1); 685 distances.b = l < 0 ? base - l : base; 686 distances.u = getUnit(vars.amount || vars.each) || 0; 687 ease = ease && l < 0 ? _invertEase(ease) : ease; 688 } 689 690 l = (distances[i] - distances.min) / distances.max || 0; 691 return _round(distances.b + (ease ? ease(l) : l) * distances.v) + distances.u; 692 }; 693 }, 694 _roundModifier = function _roundModifier(v) { 695 var p = v < 1 ? Math.pow(10, (v + "").length - 2) : 1; 696 return function (raw) { 697 var n = Math.round(parseFloat(raw) / v) * v * p; 698 return (n - n % 1) / p + (_isNumber(raw) ? 0 : getUnit(raw)); 699 }; 700 }, 701 snap = function snap(snapTo, value) { 702 var isArray = _isArray(snapTo), 703 radius, 704 is2D; 705 706 if (!isArray && _isObject(snapTo)) { 707 radius = isArray = snapTo.radius || _bigNum; 708 709 if (snapTo.values) { 710 snapTo = toArray(snapTo.values); 711 712 if (is2D = !_isNumber(snapTo[0])) { 713 radius *= radius; 714 } 715 } else { 716 snapTo = _roundModifier(snapTo.increment); 717 } 718 } 719 720 return _conditionalReturn(value, !isArray ? _roundModifier(snapTo) : _isFunction(snapTo) ? function (raw) { 721 is2D = snapTo(raw); 722 return Math.abs(is2D - raw) <= radius ? is2D : raw; 723 } : function (raw) { 724 var x = parseFloat(is2D ? raw.x : raw), 725 y = parseFloat(is2D ? raw.y : 0), 726 min = _bigNum, 727 closest = 0, 728 i = snapTo.length, 729 dx, 730 dy; 731 732 while (i--) { 733 if (is2D) { 734 dx = snapTo[i].x - x; 735 dy = snapTo[i].y - y; 736 dx = dx * dx + dy * dy; 737 } else { 738 dx = Math.abs(snapTo[i] - x); 739 } 740 741 if (dx < min) { 742 min = dx; 743 closest = i; 744 } 745 } 746 747 closest = !radius || min <= radius ? snapTo[closest] : raw; 748 return is2D || closest === raw || _isNumber(raw) ? closest : closest + getUnit(raw); 749 }); 750 }, 751 random = function random(min, max, roundingIncrement, returnFunction) { 752 return _conditionalReturn(_isArray(min) ? !max : roundingIncrement === true ? !!(roundingIncrement = 0) : !returnFunction, function () { 753 return _isArray(min) ? min[~~(Math.random() * min.length)] : (roundingIncrement = roundingIncrement || 1e
vendor: 4,723 bytes, lines 753-909
753-5) && (returnFunction = roundingIncrement < 1 ? Math.pow(10, (roundingIncrement + "").length - 2) : 1) && Math.floor(Math.round((min - roundingIncrement / 2 + Math.random() * (max - min + roundingIncrement * .99)) / roundingIncrement) * roundingIncrement * returnFunction) / returnFunction; 754 }); 755 }, 756 pipe = function pipe() { 757 for (var _len = arguments.length, functions = new Array(_len), _key = 0; _key < _len; _key++) { 758 functions[_key] = arguments[_key]; 759 } 760 761 return function (value) { 762 return functions.reduce(function (v, f) { 763 return f(v); 764 }, value); 765 }; 766 }, 767 unitize = function unitize(func, unit) { 768 return function (value) { 769 return func(parseFloat(value)) + (unit || getUnit(value)); 770 }; 771 }, 772 normalize = function normalize(min, max, value) { 773 return mapRange(min, max, 0, 1, value); 774 }, 775 _wrapArray = function _wrapArray(a, wrapper, value) { 776 return _conditionalReturn(value, function (index) { 777 return a[~~wrapper(index)]; 778 }); 779 }, 780 wrap = function wrap(min, max, value) { 781 var range = max - min; 782 return _isArray(min) ? _wrapArray(min, wrap(0, min.length), max) : _conditionalReturn(value, function (value) { 783 return (range + (value - min) % range) % range + min; 784 }); 785 }, 786 wrapYoyo = function wrapYoyo(min, max, value) { 787 var range = max - min, 788 total = range * 2; 789 return _isArray(min) ? _wrapArray(min, wrapYoyo(0, min.length - 1), max) : _conditionalReturn(value, function (value) { 790 value = (total + (value - min) % total) % total || 0; 791 return min + (value > range ? total - value : value); 792 }); 793 }, 794 _replaceRandom = function _replaceRandom(value) { 795 var prev = 0, 796 s = "", 797 i, 798 nums, 799 end, 800 isArray; 801 802 while (~(i = value.indexOf("random(", prev))) { 803 end = value.indexOf(")", i); 804 isArray = value.charAt(i + 7) === "["; 805 nums = value.substr(i + 7, end - i - 7).match(isArray ? _delimitedValueExp : _strictNumExp); 806 s += value.substr(prev, i - prev) + random(isArray ? nums : +nums[0], isArray ? 0 : +nums[1], +nums[2] || 1e-5); 807 prev = end + 1; 808 } 809 810 return s + value.substr(prev, value.length - prev); 811 }, 812 mapRange = function mapRange(inMin, inMax, outMin, outMax, value) { 813 var inRange = inMax - inMin, 814 outRange = outMax - outMin; 815 return _conditionalReturn(value, function (value) { 816 return outMin + ((value - inMin) / inRange * outRange || 0); 817 }); 818 }, 819 interpolate = function interpolate(start, end, progress, mutate) { 820 var func = isNaN(start + end) ? 0 : function (p) { 821 return (1 - p) * start + p * end; 822 }; 823 824 if (!func) { 825 var isString = _isString(start), 826 master = {}, 827 p, 828 i, 829 interpolators, 830 l, 831 il; 832 833 progress === true && (mutate = 1) && (progress = null); 834 835 if (isString) { 836 start = { 837 p: start 838 }; 839 end = { 840 p: end 841 }; 842 } else if (_isArray(start) && !_isArray(end)) { 843 interpolators = []; 844 l = start.length; 845 il = l - 2; 846 847 for (i = 1; i < l; i++) { 848 interpolators.push(interpolate(start[i - 1], start[i])); 849 } 850 851 l--; 852 853 func = function func(p) { 854 p *= l; 855 var i = Math.min(il, ~~p); 856 return interpolators[i](p - i); 857 }; 858 859 progress = end; 860 } else if (!mutate) { 861 start = _merge(_isArray(start) ? [] : {}, start); 862 } 863 864 if (!interpolators) { 865 for (p in end) { 866 _addPropTween.call(master, start, p, "get", end[p]); 867 } 868 869 func = function func(p) { 870 return _renderPropTweens(p, master) || (isString ? start.p : start); 871 }; 872 } 873 } 874 875 return _conditionalReturn(progress, func); 876 }, 877 _getLabelInDirection = function _getLabelInDirection(timeline, fromTime, backward) { 878 var labels = timeline.labels, 879 min = _bigNum, 880 p, 881 distance, 882 label; 883 884 for (p in labels) { 885 distance = labels[p] - fromTime; 886 887 if (distance < 0 === !!backward && distance && min > (distance = Math.abs(distance))) { 888 label = p; 889 min = distance; 890 } 891 } 892 893 return label; 894 }, 895 _callback = function _callback(animation, type, executeLazyFirst) { 896 var v = animation.vars, 897 callback = v[type], 898 params, 899 scope; 900 901 if (!callback) { 902 return; 903 } 904 905 params = v[type + "Params"]; 906 scope = v.callbackScope || animation; 907 executeLazyFirst && _lazyTweens.length && _lazyRender(); 908 return params ? callback.apply(scope, params) : callback.call(scope); 909 },
vendor: 11,709 bytes, lines 910-1323
910 _interrupt = function _interrupt(animation) { 911 _removeFromParent(animation); 912 913 animation.scrollTrigger && animation.scrollTrigger.kill(false); 914 animation.progress() < 1 && _callback(animation, "onInterrupt"); 915 return animation; 916 }, 917 _quickTween, 918 _createPlugin = function _createPlugin(config) { 919 config = !config.name && config["default"] || config; 920 921 var name = config.name, 922 isFunc = _isFunction(config), 923 Plugin = name && !isFunc && config.init ? function () { 924 this._props = []; 925 } : config, 926 instanceDefaults = { 927 init: _emptyFunc, 928 render: _renderPropTweens, 929 add: _addPropTween, 930 kill: _killPropTweensOf, 931 modifier: _addPluginModifier, 932 rawVars: 0 933 }, 934 statics = { 935 targetTest: 0, 936 get: 0, 937 getSetter: _getSetter, 938 aliases: {}, 939 register: 0 940 }; 941 942 _wake(); 943 944 if (config !== Plugin) { 945 if (_plugins[name]) { 946 return; 947 } 948 949 _setDefaults(Plugin, _setDefaults(_copyExcluding(config, instanceDefaults), statics)); 950 951 _merge(Plugin.prototype, _merge(instanceDefaults, _copyExcluding(config, statics))); 952 953 _plugins[Plugin.prop = name] = Plugin; 954 955 if (config.targetTest) { 956 _harnessPlugins.push(Plugin); 957 958 _reservedProps[name] = 1; 959 } 960 961 name = (name === "css" ? "CSS" : name.charAt(0).toUpperCase() + name.substr(1)) + "Plugin"; 962 } 963 964 _addGlobal(name, Plugin); 965 966 config.register && config.register(gsap, Plugin, PropTween); 967 }, 968 _255 = 255, 969 _colorLookup = { 970 aqua: [0, _255, _255], 971 lime: [0, _255, 0], 972 silver: [192, 192, 192], 973 black: [0, 0, 0], 974 maroon: [128, 0, 0], 975 teal: [0, 128, 128], 976 blue: [0, 0, _255], 977 navy: [0, 0, 128], 978 white: [_255, _255, _255], 979 olive: [128, 128, 0], 980 yellow: [_255, _255, 0], 981 orange: [_255, 165, 0], 982 gray: [128, 128, 128], 983 purple: [128, 0, 128], 984 green: [0, 128, 0], 985 red: [_255, 0, 0], 986 pink: [_255, 192, 203], 987 cyan: [0, _255, _255], 988 transparent: [_255, _255, _255, 0] 989 }, 990 _hue = function _hue(h, m1, m2) { 991 h = h < 0 ? h + 1 : h > 1 ? h - 1 : h; 992 return (h * 6 < 1 ? m1 + (m2 - m1) * h * 6 : h < .5 ? m2 : h * 3 < 2 ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * _255 + .5 | 0; 993 }, 994 splitColor = function splitColor(v, toHSL, forceAlpha) { 995 var a = !v ? _colorLookup.black : _isNumber(v) ? [v >> 16, v >> 8 & _255, v & _255] : 0, 996 r, 997 g, 998 b, 999 h, 1000 s, 1001 l, 1002 max, 1003 min, 1004 d, 1005 wasHSL; 1006 1007 if (!a) { 1008 if (v.substr(-1) === ",") { 1009 v = v.substr(0, v.length - 1); 1010 } 1011 1012 if (_colorLookup[v]) { 1013 a = _colorLookup[v]; 1014 } else if (v.charAt(0) === "#") { 1015 if (v.length < 6) { 1016 r = v.charAt(1); 1017 g = v.charAt(2); 1018 b = v.charAt(3); 1019 v = "#" + r + r + g + g + b + b + (v.length === 5 ? v.charAt(4) + v.charAt(4) : ""); 1020 } 1021 1022 if (v.length === 9) { 1023 a = parseInt(v.substr(1, 6), 16); 1024 return [a >> 16, a >> 8 & _255, a & _255, parseInt(v.substr(7), 16) / 255]; 1025 } 1026 1027 v = parseInt(v.substr(1), 16); 1028 a = [v >> 16, v >> 8 & _255, v & _255]; 1029 } else if (v.substr(0, 3) === "hsl") { 1030 a = wasHSL = v.match(_strictNumExp); 1031 1032 if (!toHSL) { 1033 h = +a[0] % 360 / 360; 1034 s = +a[1] / 100; 1035 l = +a[2] / 100; 1036 g = l <= .5 ? l * (s + 1) : l + s - l * s; 1037 r = l * 2 - g; 1038 a.length > 3 && (a[3] *= 1); 1039 a[0] = _hue(h + 1 / 3, r, g); 1040 a[1] = _hue(h, r, g); 1041 a[2] = _hue(h - 1 / 3, r, g); 1042 } else if (~v.indexOf("=")) { 1043 a = v.match(_numExp); 1044 forceAlpha && a.length < 4 && (a[3] = 1); 1045 return a; 1046 } 1047 } else { 1048 a = v.match(_strictNumExp) || _colorLookup.transparent; 1049 } 1050 1051 a = a.map(Number); 1052 } 1053 1054 if (toHSL && !wasHSL) { 1055 r = a[0] / _255; 1056 g = a[1] / _255; 1057 b = a[2] / _255; 1058 max = Math.max(r, g, b); 1059 min = Math.min(r, g, b); 1060 l = (max + min) / 2; 1061 1062 if (max === min) { 1063 h = s = 0; 1064 } else { 1065 d = max - min; 1066 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 1067 h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4; 1068 h *= 60; 1069 } 1070 1071 a[0] = ~~(h + .5); 1072 a[1] = ~~(s * 100 + .5); 1073 a[2] = ~~(l * 100 + .5); 1074 } 1075 1076 forceAlpha && a.length < 4 && (a[3] = 1); 1077 return a; 1078 }, 1079 _colorOrderData = function _colorOrderData(v) { 1080 var values = [], 1081 c = [], 1082 i = -1; 1083 v.split(_colorExp).forEach(function (v) { 1084 var a = v.match(_numWithUnitExp) || []; 1085 values.push.apply(values, a); 1086 c.push(i += a.length + 1); 1087 }); 1088 values.c = c; 1089 return values; 1090 }, 1091 _formatColors = function _formatColors(s, toHSL, orderMatchData) { 1092 var result = "", 1093 colors = (s + result).match(_colorExp), 1094 type = toHSL ? "hsla(" : "rgba(", 1095 i = 0, 1096 c, 1097 shell, 1098 d, 1099 l; 1100 1101 if (!colors) { 1102 return s; 1103 } 1104 1105 colors = colors.map(function (color) { 1106 return (color = splitColor(color, toHSL, 1)) && type + (toHSL ? color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : color.join(",")) + ")"; 1107 }); 1108 1109 if (orderMatchData) { 1110 d = _colorOrderData(s); 1111 c = orderMatchData.c; 1112 1113 if (c.join(result) !== d.c.join(result)) { 1114 shell = s.replace(_colorExp, "1").split(_numWithUnitExp); 1115 l = shell.length - 1; 1116 1117 for (; i < l; i++) { 1118 result += shell[i] + (~c.indexOf(i) ? colors.shift() || type + "0,0,0,0)" : (d.length ? d : colors.length ? colors : orderMatchData).shift()); 1119 } 1120 } 1121 } 1122 1123 if (!shell) { 1124 shell = s.split(_colorExp); 1125 l = shell.length - 1; 1126 1127 for (; i < l; i++) { 1128 result += shell[i] + colors[i]; 1129 } 1130 } 1131 1132 return result + shell[l]; 1133 }, 1134 _colorExp = function () { 1135 var s = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3,4}){1,2}\\b", 1136 p; 1137 1138 for (p in _colorLookup) { 1139 s += "|" + p + "\\b"; 1140 } 1141 1142 return new RegExp(s + ")", "gi"); 1143 }(), 1144 _hslExp = /hsl[a]?\(/, 1145 _colorStringFilter = function _colorStringFilter(a) { 1146 var combined = a.join(" "), 1147 toHSL; 1148 _colorExp.lastIndex = 0; 1149 1150 if (_colorExp.test(combined)) { 1151 toHSL = _hslExp.test(combined); 1152 a[1] = _formatColors(a[1], toHSL); 1153 a[0] = _formatColors(a[0], toHSL, _colorOrderData(a[1])); 1154 return true; 1155 } 1156 }, 1157 _tickerActive, 1158 _ticker = function () { 1159 var _getTime = Date.now, 1160 _lagThreshold = 500, 1161 _adjustedLag = 33, 1162 _startTime = _getTime(), 1163 _lastUpdate = _startTime, 1164 _gap = 1000 / 240, 1165 _nextTime = _gap, 1166 _listeners = [], 1167 _id, 1168 _req, 1169 _raf, 1170 _self, 1171 _delta, 1172 _i, 1173 _tick = function _tick(v) { 1174 var elapsed = _getTime() - _lastUpdate, 1175 manual = v === true, 1176 overlap, 1177 dispatch, 1178 time, 1179 frame; 1180 1181 elapsed > _lagThreshold && (_startTime += elapsed - _adjustedLag); 1182 _lastUpdate += elapsed; 1183 time = _lastUpdate - _startTime; 1184 overlap = time - _nextTime; 1185 1186 if (overlap > 0 || manual) { 1187 frame = ++_self.frame; 1188 _delta = time - _self.time * 1000; 1189 _self.time = time = time / 1000; 1190 _nextTime += overlap + (overlap >= _gap ? 4 : _gap - overlap); 1191 dispatch = 1; 1192 } 1193 1194 manual || (_id = _req(_tick)); 1195 1196 if (dispatch) { 1197 for (_i = 0; _i < _listeners.length; _i++) { 1198 _listeners[_i](time, _delta, frame, v); 1199 } 1200 } 1201 }; 1202 1203 _self = { 1204 time: 0, 1205 frame: 0, 1206 tick: function tick() { 1207 _tick(true); 1208 }, 1209 deltaRatio: function deltaRatio(fps) { 1210 return _delta / (1000 / (fps || 60)); 1211 }, 1212 wake: function wake() { 1213 if (_coreReady) { 1214 if (!_coreInitted && _windowExists()) { 1215 _win = _coreInitted = window; 1216 _doc = _win.document || {}; 1217 _globals.gsap = gsap; 1218 (_win.gsapVersions || (_win.gsapVersions = [])).push(gsap.version); 1219 1220 _install(_installScope || _win.GreenSockGlobals || !_win.gsap && _win || {}); 1221 1222 _raf = _win.requestAnimationFrame; 1223 } 1224 1225 _id && _self.sleep(); 1226 1227 _req = _raf || function (f) { 1228 return setTimeout(f, _nextTime - _self.time * 1000 + 1 | 0); 1229 }; 1230 1231 _tickerActive = 1; 1232 1233 _tick(2); 1234 } 1235 }, 1236 sleep: function sleep() { 1237 (_raf ? _win.cancelAnimationFrame : clearTimeout)(_id); 1238 _tickerActive = 0; 1239 _req = _emptyFunc; 1240 }, 1241 lagSmoothing: function lagSmoothing(threshold, adjustedLag) { 1242 _lagThreshold = threshold || 1 / _tinyNum; 1243 _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0); 1244 }, 1245 fps: function fps(_fps) { 1246 _gap = 1000 / (_fps || 240); 1247 _nextTime = _self.time * 1000 + _gap; 1248 }, 1249 add: function add(callback) { 1250 _listeners.indexOf(callback) < 0 && _listeners.push(callback); 1251 1252 _wake(); 1253 }, 1254 remove: function remove(callback) { 1255 var i; 1256 ~(i = _listeners.indexOf(callback)) && _listeners.splice(i, 1) && _i >= i && _i--; 1257 }, 1258 _listeners: _listeners 1259 }; 1260 return _self; 1261 }(), 1262 _wake = function _wake() { 1263 return !_tickerActive && _ticker.wake(); 1264 }, 1265 _easeMap = {}, 1266 _customEaseExp = /^[\d.\-M][\d.\-,\s]/, 1267 _quotesExp = /["']/g, 1268 _parseObjectInString = function _parseObjectInString(value) { 1269 var obj = {}, 1270 split = value.substr(1, value.length - 3).split(":"), 1271 key = split[0], 1272 i = 1, 1273 l = split.length, 1274 index, 1275 val, 1276 parsedVal; 1277 1278 for (; i < l; i++) { 1279 val = split[i]; 1280 index = i !== l - 1 ? val.lastIndexOf(",") : val.length; 1281 parsedVal = val.substr(0, index); 1282 obj[key] = isNaN(parsedVal) ? parsedVal.replace(_quotesExp, "").trim() : +parsedVal; 1283 key = val.substr(index + 1).trim(); 1284 } 1285 1286 return obj; 1287 }, 1288 _valueInParentheses = function _valueInParentheses(value) { 1289 var open = value.indexOf("(") + 1, 1290 close = value.indexOf(")"), 1291 nested = value.indexOf("(", open); 1292 return value.substring(open, ~nested && nested < close ? value.indexOf(")", close + 1) : close); 1293 }, 1294 _configEaseFromString = function _configEaseFromString(name) { 1295 var split = (name + "").split("("), 1296 ease = _easeMap[split[0]]; 1297 return ease && split.length > 1 && ease.config ? ease.config.apply(null, ~name.indexOf("{") ? [_parseObjectInString(split[1])] : _valueInParentheses(name).split(",").map(_numericIfPossible)) : _easeMap._CE && _customEaseExp.test(name) ? _easeMap._CE("", name) : ease; 1298 }, 1299 _invertEase = function _invertEase(ease) { 1300 return function (p) { 1301 return 1 - ease(1 - p); 1302 }; 1303 }, 1304 _propagateYoyoEase = function _propagateYoyoEase(timeline, isYoyo) { 1305 var child = timeline._first, 1306 ease; 1307 1308 while (child) { 1309 if (child instanceof Timeline) { 1310 _propagateYoyoEase(child, isYoyo); 1311 } else if (child.vars.yoyoEase && (!child._yoyo || !child._repeat) && child._yoyo !== isYoyo) { 1312 if (child.timeline) { 1313 _propagateYoyoEase(child.timeline, isYoyo); 1314 } else { 1315 ease = child._ease; 1316 child._ease = child._yEase; 1317 child._yEase = ease; 1318 child._yoyo = isYoyo; 1319 } 1320 } 1321 1322 child = child._next; 1323 }
vendor: 3,445 bytes, lines 1323-1434
1323 1324 }, 1325 _parseEase = function _parseEase(ease, defaultEase) { 1326 return !ease ? defaultEase : (_isFunction(ease) ? ease : _easeMap[ease] || _configEaseFromString(ease)) || defaultEase; 1327 }, 1328 _insertEase = function _insertEase(names, easeIn, easeOut, easeInOut) { 1329 if (easeOut === void 0) { 1330 easeOut = function easeOut(p) { 1331 return 1 - easeIn(1 - p); 1332 }; 1333 } 1334 1335 if (easeInOut === void 0) { 1336 easeInOut = function easeInOut(p) { 1337 return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2; 1338 }; 1339 } 1340 1341 var ease = { 1342 easeIn: easeIn, 1343 easeOut: easeOut, 1344 easeInOut: easeInOut 1345 }, 1346 lowercaseName; 1347 1348 _forEachName(names, function (name) { 1349 _easeMap[name] = _globals[name] = ease; 1350 _easeMap[lowercaseName = name.toLowerCase()] = easeOut; 1351 1352 for (var p in ease) { 1353 _easeMap[lowercaseName + (p === "easeIn" ? ".in" : p === "easeOut" ? ".out" : ".inOut")] = _easeMap[name + "." + p] = ease[p]; 1354 } 1355 }); 1356 1357 return ease; 1358 }, 1359 _easeInOutFromOut = function _easeInOutFromOut(easeOut) { 1360 return function (p) { 1361 return p < .5 ? (1 - easeOut(1 - p * 2)) / 2 : .5 + easeOut((p - .5) * 2) / 2; 1362 }; 1363 }, 1364 _configElastic = function _configElastic(type, amplitude, period) { 1365 var p1 = amplitude >= 1 ? amplitude : 1, 1366 p2 = (period || (type ? .3 : .45)) / (amplitude < 1 ? amplitude : 1), 1367 p3 = p2 / _2PI * (Math.asin(1 / p1) || 0), 1368 easeOut = function easeOut(p) { 1369 return p === 1 ? 1 : p1 * Math.pow(2, -10 * p) * _sin((p - p3) * p2) + 1; 1370 }, 1371 ease = type === "out" ? easeOut : type === "in" ? function (p) { 1372 return 1 - easeOut(1 - p); 1373 } : _easeInOutFromOut(easeOut); 1374 1375 p2 = _2PI / p2; 1376 1377 ease.config = function (amplitude, period) { 1378 return _configElastic(type, amplitude, period); 1379 }; 1380 1381 return ease; 1382 }, 1383 _configBack = function _configBack(type, overshoot) { 1384 if (overshoot === void 0) { 1385 overshoot = 1.70158; 1386 } 1387 1388 var easeOut = function easeOut(p) { 1389 return p ? --p * p * ((overshoot + 1) * p + overshoot) + 1 : 0; 1390 }, 1391 ease = type === "out" ? easeOut : type === "in" ? function (p) { 1392 return 1 - easeOut(1 - p); 1393 } : _easeInOutFromOut(easeOut); 1394 1395 ease.config = function (overshoot) { 1396 return _configBack(type, overshoot); 1397 }; 1398 1399 return ease; 1400 }; 1401 1402 _forEachName("Linear,Quad,Cubic,Quart,Quint,Strong", function (name, i) { 1403 var power = i < 5 ? i + 1 : i; 1404 1405 _insertEase(name + ",Power" + (power - 1), i ? function (p) { 1406 return Math.pow(p, power); 1407 } : function (p) { 1408 return p; 1409 }, function (p) { 1410 return 1 - Math.pow(1 - p, power); 1411 }, function (p) { 1412 return p < .5 ? Math.pow(p * 2, power) / 2 : 1 - Math.pow((1 - p) * 2, power) / 2; 1413 }); 1414 }); 1415 1416 _easeMap.Linear.easeNone = _easeMap.none = _easeMap.Linear.easeIn; 1417 1418 _insertEase("Elastic", _configElastic("in"), _configElastic("out"), _configElastic()); 1419 1420 (function (n, c) { 1421 var n1 = 1 / c, 1422 n2 = 2 * n1, 1423 n3 = 2.5 * n1, 1424 easeOut = function easeOut(p) { 1425 return p < n1 ? n * p * p : p < n2 ? n * Math.pow(p - 1.5 / c, 2) + .75 : p < n3 ? n * (p -= 2.25 / c) * p + .9375 : n * Math.pow(p - 2.625 / c, 2) + .984375; 1426 }; 1427 1428 _insertEase("Bounce", function (p) { 1429 return 1 - easeOut(1 - p); 1430 }, easeOut); 1431 })(7.5625, 2.75); 1432 1433 _insertEase("Expo", function (p) { 1434 return
vendor: 6,382 bytes, lines 1434-1617
1434p ? Math.pow(2, 10 * (p - 1)) : 0; 1435 }); 1436 1437 _insertEase("Circ", function (p) { 1438 return -(_sqrt(1 - p * p) - 1); 1439 }); 1440 1441 _insertEase("Sine", function (p) { 1442 return p === 1 ? 1 : -_cos(p * _HALF_PI) + 1; 1443 }); 1444 1445 _insertEase("Back", _configBack("in"), _configBack("out"), _configBack()); 1446 1447 _easeMap.SteppedEase = _easeMap.steps = _globals.SteppedEase = { 1448 config: function config(steps, immediateStart) { 1449 if (steps === void 0) { 1450 steps = 1; 1451 } 1452 1453 var p1 = 1 / steps, 1454 p2 = steps + (immediateStart ? 0 : 1), 1455 p3 = immediateStart ? 1 : 0, 1456 max = 1 - _tinyNum; 1457 return function (p) { 1458 return ((p2 * _clamp(0, max, p) | 0) + p3) * p1; 1459 }; 1460 } 1461 }; 1462 _defaults.ease = _easeMap["quad.out"]; 1463 1464 _forEachName("onComplete,onUpdate,onStart,onRepeat,onReverseComplete,onInterrupt", function (name) { 1465 return _callbackNames += name + "," + name + "Params,"; 1466 }); 1467 1468 var GSCache = function GSCache(target, harness) { 1469 this.id = _gsID++; 1470 target._gsap = this; 1471 this.target = target; 1472 this.harness = harness; 1473 this.get = harness ? harness.get : _getProperty; 1474 this.set = harness ? harness.getSetter : _getSetter; 1475 }; 1476 var Animation = function () { 1477 function Animation(vars, time) { 1478 var parent = vars.parent || _globalTimeline; 1479 this.vars = vars; 1480 this._delay = +vars.delay || 0; 1481 1482 if (this._repeat = vars.repeat === Infinity ? -2 : vars.repeat || 0) { 1483 this._rDelay = vars.repeatDelay || 0; 1484 this._yoyo = !!vars.yoyo || !!vars.yoyoEase; 1485 } 1486 1487 this._ts = 1; 1488 1489 _setDuration(this, +vars.duration, 1, 1); 1490 1491 this.data = vars.data; 1492 _tickerActive || _ticker.wake(); 1493 parent && _addToTimeline(parent, this, time || time === 0 ? time : parent._time, 1); 1494 vars.reversed && this.reverse(); 1495 vars.paused && this.paused(true); 1496 } 1497 1498 var _proto = Animation.prototype; 1499 1500 _proto.delay = function delay(value) { 1501 if (value || value === 0) { 1502 this.parent && this.parent.smoothChildTiming && this.startTime(this._start + value - this._delay); 1503 this._delay = value; 1504 return this; 1505 } 1506 1507 return this._delay; 1508 }; 1509 1510 _proto.duration = function duration(value) { 1511 return arguments.length ? this.totalDuration(this._repeat > 0 ? value + (value + this._rDelay) * this._repeat : value) : this.totalDuration() && this._dur; 1512 }; 1513 1514 _proto.totalDuration = function totalDuration(value) { 1515 if (!arguments.length) { 1516 return this._tDur; 1517 } 1518 1519 this._dirty = 0; 1520 return _setDuration(this, this._repeat < 0 ? value : (value - this._repeat * this._rDelay) / (this._repeat + 1)); 1521 }; 1522 1523 _proto.totalTime = function totalTime(_totalTime, suppressEvents) { 1524 _wake(); 1525 1526 if (!arguments.length) { 1527 return this._tTime; 1528 } 1529 1530 var parent = this._dp; 1531 1532 if (parent && parent.smoothChildTiming && this._ts) { 1533 _alignPlayhead(this, _totalTime); 1534 1535 !parent._dp || parent.parent || _postAddChecks(parent, this); 1536 1537 while (parent.parent) { 1538 if (parent.parent._time !== parent._start + (parent._ts >= 0 ? parent._tTime / parent._ts : (parent.totalDuration() - parent._tTime) / -parent._ts)) { 1539 parent.totalTime(parent._tTime, true); 1540 } 1541 1542 parent = parent.parent; 1543 } 1544 1545 if (!this.parent && this._dp.autoRemoveChildren && (this._ts > 0 && _totalTime < this._tDur || this._ts < 0 && _totalTime > 0 || !this._tDur && !_totalTime)) { 1546 _addToTimeline(this._dp, this, this._start - this._delay); 1547 } 1548 } 1549 1550 if (this._tTime !== _totalTime || !this._dur && !suppressEvents || this._initted && Math.abs(this._zTime) === _tinyNum || !_totalTime && !this._initted && (this.add || this._ptLookup)) { 1551 this._ts || (this._pTime = _totalTime); 1552 1553 _lazySafeRender(this, _totalTime, suppressEvents); 1554 } 1555 1556 return this; 1557 }; 1558 1559 _proto.time = function time(value, suppressEvents) { 1560 return arguments.length ? this.totalTime(Math.min(this.totalDuration(), value + _elapsedCycleDuration(this)) % this._dur || (value ? this._dur : 0), suppressEvents) : this._time; 1561 }; 1562 1563 _proto.totalProgress = function totalProgress(value, suppressEvents) { 1564 return arguments.length ? this.totalTime(this.totalDuration() * value, suppressEvents) : this.totalDuration() ? Math.min(1, this._tTime / this._tDur) : this.ratio; 1565 }; 1566 1567 _proto.progress = function progress(value, suppressEvents) { 1568 return arguments.length ? this.totalTime(this.duration() * (this._yoyo && !(this.iteration() & 1) ? 1 - value : value) + _elapsedCycleDuration(this), suppressEvents) : this.duration() ? Math.min(1, this._time / this._dur) : this.ratio; 1569 }; 1570 1571 _proto.iteration = function iteration(value, suppressEvents) { 1572 var cycleDuration = this.duration() + this._rDelay; 1573 1574 return arguments.length ? this.totalTime(this._time + (value - 1) * cycleDuration, suppressEvents) : this._repeat ? _animationCycle(this._tTime, cycleDuration) + 1 : 1; 1575 }; 1576 1577 _proto.timeScale = function timeScale(value) { 1578 if (!arguments.length) { 1579 return this._rts === -_tinyNum ? 0 : this._rts; 1580 } 1581 1582 if (this._rts === value) { 1583 return this; 1584 } 1585 1586 var tTime = this.parent && this._ts ? _parentToChildTotalTime(this.parent._time, this) : this._tTime; 1587 this._rts = +value || 0; 1588 this._ts = this._ps || value === -_tinyNum ? 0 : this._rts; 1589 return _recacheAncestors(this.totalTime(_clamp(-this._delay, this._tDur, tTime), true)); 1590 }; 1591 1592 _proto.paused = function paused(value) { 1593 if (!arguments.length) { 1594 return this._ps; 1595 } 1596 1597 if (this._ps !== value) { 1598 this._ps = value; 1599 1600 if (value) { 1601 this._pTime = this._tTime || Math.max(-this._delay, this.rawTime()); 1602 this._ts = this._act = 0; 1603 } else { 1604 _wake(); 1605 1606 this._ts = this._rts; 1607 this.totalTime(this.parent && !this.parent.smoothChildTiming ? this.rawTime() : this._tTime || this._pTime, this.progress() === 1 && (this._tTime -= _tinyNum) && Math.abs(this._zTime) !== _tinyNum); 1608 } 1609 } 1610 1611 return this; 1612 }; 1613 1614 _proto.startTime = function startTime(value) { 1615 if (arguments.length) { 1616 this._start = value; 1617 var parent = this.parent || this._dp;
vendor: 2,817 bytes, lines 1618-1708
1618 parent && (parent._sort || !this.parent) && _addToTimeline(parent, this, value - this._delay); 1619 return this; 1620 } 1621 1622 return this._start; 1623 }; 1624 1625 _proto.endTime = function endTime(includeRepeats) { 1626 return this._start + (_isNotFalse(includeRepeats) ? this.totalDuration() : this.duration()) / Math.abs(this._ts); 1627 }; 1628 1629 _proto.rawTime = function rawTime(wrapRepeats) { 1630 var parent = this.parent || this._dp; 1631 return !parent ? this._tTime : wrapRepeats && (!this._ts || this._repeat && this._time && this.totalProgress() < 1) ? this._tTime % (this._dur + this._rDelay) : !this._ts ? this._tTime : _parentToChildTotalTime(parent.rawTime(wrapRepeats), this); 1632 }; 1633 1634 _proto.globalTime = function globalTime(rawTime) { 1635 var animation = this, 1636 time = arguments.length ? rawTime : animation.rawTime(); 1637 1638 while (animation) { 1639 time = animation._start + time / (animation._ts || 1); 1640 animation = animation._dp; 1641 } 1642 1643 return time; 1644 }; 1645 1646 _proto.repeat = function repeat(value) { 1647 if (arguments.length) { 1648 this._repeat = value === Infinity ? -2 : value; 1649 return _onUpdateTotalDuration(this); 1650 } 1651 1652 return this._repeat === -2 ? Infinity : this._repeat; 1653 }; 1654 1655 _proto.repeatDelay = function repeatDelay(value) { 1656 if (arguments.length) { 1657 this._rDelay = value; 1658 return _onUpdateTotalDuration(this); 1659 } 1660 1661 return this._rDelay; 1662 }; 1663 1664 _proto.yoyo = function yoyo(value) { 1665 if (arguments.length) { 1666 this._yoyo = value; 1667 return this; 1668 } 1669 1670 return this._yoyo; 1671 }; 1672 1673 _proto.seek = function seek(position, suppressEvents) { 1674 return this.totalTime(_parsePosition(this, position), _isNotFalse(suppressEvents)); 1675 }; 1676 1677 _proto.restart = function restart(includeDelay, suppressEvents) { 1678 return this.play().totalTime(includeDelay ? -this._delay : 0, _isNotFalse(suppressEvents)); 1679 }; 1680 1681 _proto.play = function play(from, suppressEvents) { 1682 from != null && this.seek(from, suppressEvents); 1683 return this.reversed(false).paused(false); 1684 }; 1685 1686 _proto.reverse = function reverse(from, suppressEvents) { 1687 from != null && this.seek(from || this.totalDuration(), suppressEvents); 1688 return this.reversed(true).paused(false); 1689 }; 1690 1691 _proto.pause = function pause(atTime, suppressEvents) { 1692 atTime != null && this.seek(atTime, suppressEvents); 1693 return this.paused(true); 1694 }; 1695 1696 _proto.resume = function resume() { 1697 return this.paused(false); 1698 }; 1699 1700 _proto.reversed = function reversed(value) { 1701 if (arguments.length) { 1702 !!value !== this.reversed() && this.timeScale(-this._rts || (value ? -_tinyNum : 0)); 1703 return this; 1704 } 1705 1706 return this._rts < 0; 1707 }; 1708
vendor: 8,594 bytes, lines 1709-1972
1709 _proto.invalidate = function invalidate() { 1710 this._initted = this._act = 0; 1711 this._zTime = -_tinyNum; 1712 return this; 1713 }; 1714 1715 _proto.isActive = function isActive() { 1716 var parent = this.parent || this._dp, 1717 start = this._start, 1718 rawTime; 1719 return !!(!parent || this._ts && this._initted && parent.isActive() && (rawTime = parent.rawTime(true)) >= start && rawTime < this.endTime(true) - _tinyNum); 1720 }; 1721 1722 _proto.eventCallback = function eventCallback(type, callback, params) { 1723 var vars = this.vars; 1724 1725 if (arguments.length > 1) { 1726 if (!callback) { 1727 delete vars[type]; 1728 } else { 1729 vars[type] = callback; 1730 params && (vars[type + "Params"] = params); 1731 type === "onUpdate" && (this._onUpdate = callback); 1732 } 1733 1734 return this; 1735 } 1736 1737 return vars[type]; 1738 }; 1739 1740 _proto.then = function then(onFulfilled) { 1741 var self = this; 1742 return new Promise(function (resolve) { 1743 var f = _isFunction(onFulfilled) ? onFulfilled : _passThrough, 1744 _resolve = function _resolve() { 1745 var _then = self.then; 1746 self.then = null; 1747 _isFunction(f) && (f = f(self)) && (f.then || f === self) && (self.then = _then); 1748 resolve(f); 1749 self.then = _then; 1750 }; 1751 1752 if (self._initted && self.totalProgress() === 1 && self._ts >= 0 || !self._tTime && self._ts < 0) { 1753 _resolve(); 1754 } else { 1755 self._prom = _resolve; 1756 } 1757 }); 1758 }; 1759 1760 _proto.kill = function kill() { 1761 _interrupt(this); 1762 }; 1763 1764 return Animation; 1765 }(); 1766 1767 _setDefaults(Animation.prototype, { 1768 _time: 0, 1769 _start: 0, 1770 _end: 0, 1771 _tTime: 0, 1772 _tDur: 0, 1773 _dirty: 0, 1774 _repeat: 0, 1775 _yoyo: false, 1776 parent: null, 1777 _initted: false, 1778 _rDelay: 0, 1779 _ts: 1, 1780 _dp: 0, 1781 ratio: 0, 1782 _zTime: -_tinyNum, 1783 _prom: 0, 1784 _ps: false, 1785 _rts: 1 1786 }); 1787 1788 var Timeline = function (_Animation) { 1789 _inheritsLoose(Timeline, _Animation); 1790 1791 function Timeline(vars, time) { 1792 var _this; 1793 1794 if (vars === void 0) { 1795 vars = {}; 1796 } 1797 1798 _this = _Animation.call(this, vars, time) || this; 1799 _this.labels = {}; 1800 _this.smoothChildTiming = !!vars.smoothChildTiming; 1801 _this.autoRemoveChildren = !!vars.autoRemoveChildren; 1802 _this._sort = _isNotFalse(vars.sortChildren); 1803 _this.parent && _postAddChecks(_this.parent, _assertThisInitialized(_this)); 1804 vars.scrollTrigger && _scrollTrigger(_assertThisInitialized(_this), vars.scrollTrigger); 1805 return _this; 1806 } 1807 1808 var _proto2 = Timeline.prototype; 1809 1810 _proto2.to = function to(targets, vars, position) { 1811 new Tween(targets, _parseVars(arguments, 0, this), _parsePosition(this, _isNumber(vars) ? arguments[3] : position)); 1812 return this; 1813 }; 1814 1815 _proto2.from = function from(targets, vars, position) { 1816 new Tween(targets, _parseVars(arguments, 1, this), _parsePosition(this, _isNumber(vars) ? arguments[3] : position)); 1817 return this; 1818 }; 1819 1820 _proto2.fromTo = function fromTo(targets, fromVars, toVars, position) { 1821 new Tween(targets, _parseVars(arguments, 2, this), _parsePosition(this, _isNumber(fromVars) ? arguments[4] : position)); 1822 return this; 1823 }; 1824 1825 _proto2.set = function set(targets, vars, position) { 1826 vars.duration = 0; 1827 vars.parent = this; 1828 _inheritDefaults(vars).repeatDelay || (vars.repeat = 0); 1829 vars.immediateRender = !!vars.immediateRender; 1830 new Tween(targets, vars, _parsePosition(this, position), 1); 1831 return this; 1832 }; 1833 1834 _proto2.call = function call(callback, params, position) { 1835 return _addToTimeline(this, Tween.delayedCall(0, callback, params), _parsePosition(this, position)); 1836 }; 1837 1838 _proto2.staggerTo = function staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) { 1839 vars.duration = duration; 1840 vars.stagger = vars.stagger || stagger; 1841 vars.onComplete = onCompleteAll; 1842 vars.onCompleteParams = onCompleteAllParams; 1843 vars.parent = this; 1844 new Tween(targets, vars, _parsePosition(this, position)); 1845 return this; 1846 }; 1847 1848 _proto2.staggerFrom = function staggerFrom(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) { 1849 vars.runBackwards = 1; 1850 _inheritDefaults(vars).immediateRender = _isNotFalse(vars.immediateRender); 1851 return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams); 1852 }; 1853 1854 _proto2.staggerFromTo = function staggerFromTo(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams) { 1855 toVars.startAt = fromVars; 1856 _inheritDefaults(toVars).immediateRender = _isNotFalse(toVars.immediateRender); 1857 return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams); 1858 }; 1859 1860 _proto2.render = function render(totalTime, suppressEvents, force) { 1861 var prevTime = this._time, 1862 tDur = this._dirty ? this.totalDuration() : this._tDur, 1863 dur = this._dur, 1864 tTime = this !== _globalTimeline && totalTime > tDur - _tinyNum && totalTime >= 0 ? tDur : totalTime < _tinyNum ? 0 : totalTime, 1865 crossingStart = this._zTime < 0 !== totalTime < 0 && (this._initted || !dur), 1866 time, 1867 child, 1868 next, 1869 iteration, 1870 cycleDuration, 1871 prevPaused, 1872 pauseTween, 1873 timeScale, 1874 prevStart, 1875 prevIteration, 1876 yoyo, 1877 isYoyo; 1878 1879 if (tTime !== this._tTime || force || crossingStart) { 1880 if (prevTime !== this._time && dur) { 1881 tTime += this._time - prevTime; 1882 totalTime += this._time - prevTime; 1883 } 1884 1885 time = tTime; 1886 prevStart = this._start; 1887 timeScale = this._ts; 1888 prevPaused = !timeScale; 1889 1890 if (crossingStart) { 1891 dur || (prevTime = this._zTime); 1892 (totalTime || !suppressEvents) && (this._zTime = totalTime); 1893 } 1894 1895 if (this._repeat) { 1896 yoyo = this._yoyo; 1897 cycleDuration = dur + this._rDelay; 1898 1899 if (this._repeat < -1 && totalTime < 0) { 1900 return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force); 1901 } 1902 1903 time = _round(tTime % cycleDuration); 1904 1905 if (tTime === tDur) { 1906 iteration = this._repeat; 1907 time = dur; 1908 } else { 1909 iteration = ~~(tTime / cycleDuration); 1910 1911 if (iteration && iteration === tTime / cycleDuration) { 1912 time = dur; 1913 iteration--; 1914 } 1915 1916 time > dur && (time = dur); 1917 } 1918 1919 prevIteration = _animationCycle(this._tTime, cycleDuration); 1920 !prevTime && this._tTime && prevIteration !== iteration && (prevIteration = iteration); 1921 1922 if (yoyo && iteration & 1) { 1923 time = dur - time; 1924 isYoyo = 1; 1925 } 1926 1927 if (iteration !== prevIteration && !this._lock) { 1928 var rewinding = yoyo && prevIteration & 1, 1929 doesWrap = rewinding === (yoyo && iteration & 1); 1930 iteration < prevIteration && (rewinding = !rewinding); 1931 prevTime = rewinding ? 0 : dur; 1932 this._lock = 1; 1933 this.render(prevTime || (isYoyo ? 0 : _round(iteration * cycleDuration)), suppressEvents, !dur)._lock = 0; 1934 !suppressEvents && this.parent && _callback(this, "onRepeat"); 1935 this.vars.repeatRefresh && !isYoyo && (this.invalidate()._lock = 1); 1936 1937 if (prevTime && prevTime !== this._time || prevPaused !== !this._ts || this.vars.onRepeat && !this.parent && !this._act) { 1938 return this; 1939 } 1940 1941 dur = this._dur; 1942 tDur = this._tDur; 1943 1944 if (doesWrap) { 1945 this._lock = 2; 1946 prevTime = rewinding ? dur : -0.0001; 1947 this.render(prevTime, true); 1948 } 1949 1950 this._lock = 0; 1951 1952 if (!this._ts && !prevPaused) { 1953 return this; 1954 } 1955 1956 _propagateYoyoEase(this, isYoyo); 1957 } 1958 } 1959 1960 if (this._hasPause && !this._forcing && this._lock < 2) { 1961 pauseTween = _findNextPauseTween(this, _round(prevTime), _round(time)); 1962 1963 if (pauseTween) { 1964 tTime -= time - (time = pauseTween._start); 1965 } 1966 } 1967 1968 this._tTime = tTime; 1969 this._time = time; 1970 this._act = !timeScale; 1971 1972 if (!this._initted) {
vendor: 22,800 bytes, lines 1973-2719
1973 this._onUpdate = this.vars.onUpdate; 1974 this._initted = 1; 1975 this._zTime = totalTime; 1976 prevTime = 0; 1977 } 1978 1979 !prevTime && time && !suppressEvents && _callback(this, "onStart"); 1980 1981 if (time >= prevTime && totalTime >= 0) { 1982 child = this._first; 1983 1984 while (child) { 1985 next = child._next; 1986 1987 if ((child._act || time >= child._start) && child._ts && pauseTween !== child) { 1988 if (child.parent !== this) { 1989 return this.render(totalTime, suppressEvents, force); 1990 } 1991 1992 child.render(child._ts > 0 ? (time - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (time - child._start) * child._ts, suppressEvents, force); 1993 1994 if (time !== this._time || !this._ts && !prevPaused) { 1995 pauseTween = 0; 1996 next && (tTime += this._zTime = -_tinyNum); 1997 break; 1998 } 1999 } 2000 2001 child = next; 2002 } 2003 } else { 2004 child = this._last; 2005 var adjustedTime = totalTime < 0 ? totalTime : time; 2006 2007 while (child) { 2008 next = child._prev; 2009 2010 if ((child._act || adjustedTime <= child._end) && child._ts && pauseTween !== child) { 2011 if (child.parent !== this) { 2012 return this.render(totalTime, suppressEvents, force); 2013 } 2014 2015 child.render(child._ts > 0 ? (adjustedTime - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (adjustedTime - child._start) * child._ts, suppressEvents, force); 2016 2017 if (time !== this._time || !this._ts && !prevPaused) { 2018 pauseTween = 0; 2019 next && (tTime += this._zTime = adjustedTime ? -_tinyNum : _tinyNum); 2020 break; 2021 } 2022 } 2023 2024 child = next; 2025 } 2026 } 2027 2028 if (pauseTween && !suppressEvents) { 2029 this.pause(); 2030 pauseTween.render(time >= prevTime ? 0 : -_tinyNum)._zTime = time >= prevTime ? 1 : -1; 2031 2032 if (this._ts) { 2033 this._start = prevStart; 2034 2035 _setEnd(this); 2036 2037 return this.render(totalTime, suppressEvents, force); 2038 } 2039 } 2040 2041 this._onUpdate && !suppressEvents && _callback(this, "onUpdate", true); 2042 if (tTime === tDur && tDur >= this.totalDuration() || !tTime && prevTime) if (prevStart === this._start || Math.abs(timeScale) !== Math.abs(this._ts)) if (!this._lock) { 2043 (totalTime || !dur) && (tTime === tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1); 2044 2045 if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime)) { 2046 _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true); 2047 2048 this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom(); 2049 } 2050 } 2051 } 2052 2053 return this; 2054 }; 2055 2056 _proto2.add = function add(child, position) { 2057 var _this2 = this; 2058 2059 _isNumber(position) || (position = _parsePosition(this, position)); 2060 2061 if (!(child instanceof Animation)) { 2062 if (_isArray(child)) { 2063 child.forEach(function (obj) { 2064 return _this2.add(obj, position); 2065 }); 2066 return this; 2067 } 2068 2069 if (_isString(child)) { 2070 return this.addLabel(child, position); 2071 } 2072 2073 if (_isFunction(child)) { 2074 child = Tween.delayedCall(0, child); 2075 } else { 2076 return this; 2077 } 2078 } 2079 2080 return this !== child ? _addToTimeline(this, child, position) : this; 2081 }; 2082 2083 _proto2.getChildren = function getChildren(nested, tweens, timelines, ignoreBeforeTime) { 2084 if (nested === void 0) { 2085 nested = true; 2086 } 2087 2088 if (tweens === void 0) { 2089 tweens = true; 2090 } 2091 2092 if (timelines === void 0) { 2093 timelines = true; 2094 } 2095 2096 if (ignoreBeforeTime === void 0) { 2097 ignoreBeforeTime = -_bigNum; 2098 } 2099 2100 var a = [], 2101 child = this._first; 2102 2103 while (child) { 2104 if (child._start >= ignoreBeforeTime) { 2105 if (child instanceof Tween) { 2106 tweens && a.push(child); 2107 } else { 2108 timelines && a.push(child); 2109 nested && a.push.apply(a, child.getChildren(true, tweens, timelines)); 2110 } 2111 } 2112 2113 child = child._next; 2114 } 2115 2116 return a; 2117 }; 2118 2119 _proto2.getById = function getById(id) { 2120 var animations = this.getChildren(1, 1, 1), 2121 i = animations.length; 2122 2123 while (i--) { 2124 if (animations[i].vars.id === id) { 2125 return animations[i]; 2126 } 2127 } 2128 }; 2129 2130 _proto2.remove = function remove(child) { 2131 if (_isString(child)) { 2132 return this.removeLabel(child); 2133 } 2134 2135 if (_isFunction(child)) { 2136 return this.killTweensOf(child); 2137 } 2138 2139 _removeLinkedListItem(this, child); 2140 2141 if (child === this._recent) { 2142 this._recent = this._last; 2143 } 2144 2145 return _uncache(this); 2146 }; 2147 2148 _proto2.totalTime = function totalTime(_totalTime2, suppressEvents) { 2149 if (!arguments.length) { 2150 return this._tTime; 2151 } 2152 2153 this._forcing = 1; 2154 2155 if (!this._dp && this._ts) { 2156 this._start = _round(_ticker.time - (this._ts > 0 ? _totalTime2 / this._ts : (this.totalDuration() - _totalTime2) / -this._ts)); 2157 } 2158 2159 _Animation.prototype.totalTime.call(this, _totalTime2, suppressEvents); 2160 2161 this._forcing = 0; 2162 return this; 2163 }; 2164 2165 _proto2.addLabel = function addLabel(label, position) { 2166 this.labels[label] = _parsePosition(this, position); 2167 return this; 2168 }; 2169 2170 _proto2.removeLabel = function removeLabel(label) { 2171 delete this.labels[label]; 2172 return this; 2173 }; 2174 2175 _proto2.addPause = function addPause(position, callback, params) { 2176 var t = Tween.delayedCall(0, callback || _emptyFunc, params); 2177 t.data = "isPause"; 2178 this._hasPause = 1; 2179 return _addToTimeline(this, t, _parsePosition(this, position)); 2180 }; 2181 2182 _proto2.removePause = function removePause(position) { 2183 var child = this._first; 2184 position = _parsePosition(this, position); 2185 2186 while (child) { 2187 if (child._start === position && child.data === "isPause") { 2188 _removeFromParent(child); 2189 } 2190 2191 child = child._next; 2192 } 2193 }; 2194 2195 _proto2.killTweensOf = function killTweensOf(targets, props, onlyActive) { 2196 var tweens = this.getTweensOf(targets, onlyActive), 2197 i = tweens.length; 2198 2199 while (i--) { 2200 _overwritingTween !== tweens[i] && tweens[i].kill(targets, props); 2201 } 2202 2203 return this; 2204 }; 2205 2206 _proto2.getTweensOf = function getTweensOf(targets, onlyActive) { 2207 var a = [], 2208 parsedTargets = toArray(targets), 2209 child = this._first, 2210 isGlobalTime = _isNumber(onlyActive), 2211 children; 2212 2213 while (child) { 2214 if (child instanceof Tween) { 2215 if (_arrayContainsAny(child._targets, parsedTargets) && (isGlobalTime ? (!_overwritingTween || child._initted && child._ts) && child.globalTime(0) <= onlyActive && child.globalTime(child.totalDuration()) > onlyActive : !onlyActive || child.isActive())) { 2216 a.push(child); 2217 } 2218 } else if ((children = child.getTweensOf(parsedTargets, onlyActive)).length) { 2219 a.push.apply(a, children); 2220 } 2221 2222 child = child._next; 2223 } 2224 2225 return a; 2226 }; 2227 2228 _proto2.tweenTo = function tweenTo(position, vars) { 2229 vars = vars || {}; 2230 2231 var tl = this, 2232 endTime = _parsePosition(tl, position), 2233 _vars = vars, 2234 startAt = _vars.startAt, 2235 _onStart = _vars.onStart, 2236 onStartParams = _vars.onStartParams, 2237 immediateRender = _vars.immediateRender, 2238 tween = Tween.to(tl, _setDefaults({ 2239 ease: vars.ease || "none", 2240 lazy: false, 2241 immediateRender: false, 2242 time: endTime, 2243 overwrite: "auto", 2244 duration: vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()) || _tinyNum, 2245 onStart: function onStart() { 2246 tl.pause(); 2247 var duration = vars.duration || Math.abs((endTime - tl._time) / tl.timeScale()); 2248 tween._dur !== duration && _setDuration(tween, duration, 0, 1).render(tween._time, true, true); 2249 _onStart && _onStart.apply(tween, onStartParams || []); 2250 } 2251 }, vars)); 2252 2253 return immediateRender ? tween.render(0) : tween; 2254 }; 2255 2256 _proto2.tweenFromTo = function tweenFromTo(fromPosition, toPosition, vars) { 2257 return this.tweenTo(toPosition, _setDefaults({ 2258 startAt: { 2259 time: _parsePosition(this, fromPosition) 2260 } 2261 }, vars)); 2262 }; 2263 2264 _proto2.recent = function recent() { 2265 return this._recent; 2266 }; 2267 2268 _proto2.nextLabel = function nextLabel(afterTime) { 2269 if (afterTime === void 0) { 2270 afterTime = this._time; 2271 } 2272 2273 return _getLabelInDirection(this, _parsePosition(this, afterTime)); 2274 }; 2275 2276 _proto2.previousLabel = function previousLabel(beforeTime) { 2277 if (beforeTime === void 0) { 2278 beforeTime = this._time; 2279 } 2280 2281 return _getLabelInDirection(this, _parsePosition(this, beforeTime), 1); 2282 }; 2283 2284 _proto2.currentLabel = function currentLabel(value) { 2285 return arguments.length ? this.seek(value, true) : this.previousLabel(this._time + _tinyNum); 2286 }; 2287 2288 _proto2.shiftChildren = function shiftChildren(amount, adjustLabels, ignoreBeforeTime) { 2289 if (ignoreBeforeTime === void 0) { 2290 ignoreBeforeTime = 0; 2291 } 2292 2293 var child = this._first, 2294 labels = this.labels, 2295 p; 2296 2297 while (child) { 2298 if (child._start >= ignoreBeforeTime) { 2299 child._start += amount; 2300 child._end += amount; 2301 } 2302 2303 child = child._next; 2304 } 2305 2306 if (adjustLabels) { 2307 for (p in labels) { 2308 if (labels[p] >= ignoreBeforeTime) { 2309 labels[p] += amount; 2310 } 2311 } 2312 } 2313 2314 return _uncache(this); 2315 }; 2316 2317 _proto2.invalidate = function invalidate() { 2318 var child = this._first; 2319 this._lock = 0; 2320 2321 while (child) { 2322 child.invalidate(); 2323 child = child._next; 2324 } 2325 2326 return _Animation.prototype.invalidate.call(this); 2327 }; 2328 2329 _proto2.clear = function clear(includeLabels) { 2330 if (includeLabels === void 0) { 2331 includeLabels = true; 2332 } 2333 2334 var child = this._first, 2335 next; 2336 2337 while (child) { 2338 next = child._next; 2339 this.remove(child); 2340 child = next; 2341 } 2342 2343 this._dp && (this._time = this._tTime = this._pTime = 0); 2344 includeLabels && (this.labels = {}); 2345 return _uncache(this); 2346 }; 2347 2348 _proto2.totalDuration = function totalDuration(value) { 2349 var max = 0, 2350 self = this, 2351 child = self._last, 2352 prevStart = _bigNum, 2353 prev, 2354 start, 2355 parent; 2356 2357 if (arguments.length) { 2358 return self.timeScale((self._repeat < 0 ? self.duration() : self.totalDuration()) / (self.reversed() ? -value : value)); 2359 } 2360 2361 if (self._dirty) { 2362 parent = self.parent; 2363 2364 while (child) { 2365 prev = child._prev; 2366 child._dirty && child.totalDuration(); 2367 start = child._start; 2368 2369 if (start > prevStart && self._sort && child._ts && !self._lock) { 2370 self._lock = 1; 2371 _addToTimeline(self, child, start - child._delay, 1)._lock = 0; 2372 } else { 2373 prevStart = start; 2374 } 2375 2376 if (start < 0 && child._ts) { 2377 max -= start; 2378 2379 if (!parent && !self._dp || parent && parent.smoothChildTiming) { 2380 self._start += start / self._ts; 2381 self._time -= start; 2382 self._tTime -= start; 2383 } 2384 2385 self.shiftChildren(-start, false, -1e999); 2386 prevStart = 0; 2387 } 2388 2389 child._end > max && child._ts && (max = child._end); 2390 child = prev; 2391 } 2392 2393 _setDuration(self, self === _globalTimeline && self._time > max ? self._time : max, 1, 1); 2394 2395 self._dirty = 0; 2396 } 2397 2398 return self._tDur; 2399 }; 2400 2401 Timeline.updateRoot = function updateRoot(time) { 2402 if (_globalTimeline._ts) { 2403 _lazySafeRender(_globalTimeline, _parentToChildTotalTime(time, _globalTimeline)); 2404 2405 _lastRenderedFrame = _ticker.frame; 2406 } 2407 2408 if (_ticker.frame >= _nextGCFrame) { 2409 _nextGCFrame += _config.autoSleep || 120; 2410 var child = _globalTimeline._first; 2411 if (!child || !child._ts) if (_config.autoSleep && _ticker._listeners.length < 2) { 2412 while (child && !child._ts) { 2413 child = child._next; 2414 } 2415 2416 child || _ticker.sleep(); 2417 } 2418 } 2419 }; 2420 2421 return Timeline; 2422 }(Animation); 2423 2424 _setDefaults(Timeline.prototype, { 2425 _lock: 0, 2426 _hasPause: 0, 2427 _forcing: 0 2428 }); 2429 2430 var _addComplexStringPropTween = function _addComplexStringPropTween(target, prop, start, end, setter, stringFilter, funcParam) { 2431 var pt = new PropTween(this._pt, target, prop, 0, 1, _renderComplexString, null, setter), 2432 index = 0, 2433 matchIndex = 0, 2434 result, 2435 startNums, 2436 color, 2437 endNum, 2438 chunk, 2439 startNum, 2440 hasRandom, 2441 a; 2442 pt.b = start; 2443 pt.e = end; 2444 start += ""; 2445 end += ""; 2446 2447 if (hasRandom = ~end.indexOf("random(")) { 2448 end = _replaceRandom(end); 2449 } 2450 2451 if (stringFilter) { 2452 a = [start, end]; 2453 stringFilter(a, target, prop); 2454 start = a[0]; 2455 end = a[1]; 2456 } 2457 2458 startNums = start.match(_complexStringNumExp) || []; 2459 2460 while (result = _complexStringNumExp.exec(end)) { 2461 endNum = result[0]; 2462 chunk = end.substring(index, result.index); 2463 2464 if (color) { 2465 color = (color + 1) % 5; 2466 } else if (chunk.substr(-5) === "rgba(") { 2467 color = 1; 2468 } 2469 2470 if (endNum !== startNums[matchIndex++]) { 2471 startNum = parseFloat(startNums[matchIndex - 1]) || 0; 2472 pt._pt = { 2473 _next: pt._pt, 2474 p: chunk || matchIndex === 1 ? chunk : ",", 2475 s: startNum, 2476 c: endNum.charAt(1) === "=" ? parseFloat(endNum.substr(2)) * (endNum.charAt(0) === "-" ? -1 : 1) : parseFloat(endNum) - startNum, 2477 m: color && color < 4 ? Math.round : 0 2478 }; 2479 index = _complexStringNumExp.lastIndex; 2480 } 2481 } 2482 2483 pt.c = index < end.length ? end.substring(index, end.length) : ""; 2484 pt.fp = funcParam; 2485 2486 if (_relExp.test(end) || hasRandom) { 2487 pt.e = 0; 2488 } 2489 2490 this._pt = pt; 2491 return pt; 2492 }, 2493 _addPropTween = function _addPropTween(target, prop, start, end, index, targets, modifier, stringFilter, funcParam) { 2494 _isFunction(end) && (end = end(index || 0, target, targets)); 2495 var currentValue = target[prop], 2496 parsedStart = start !== "get" ? start : !_isFunction(currentValue) ? currentValue : funcParam ? target[prop.indexOf("set") || !_isFunction(target["get" + prop.substr(3)]) ? prop : "get" + prop.substr(3)](funcParam) : target[prop](), 2497 setter = !_isFunction(currentValue) ? _setterPlain : funcParam ? _setterFuncWithParam : _setterFunc, 2498 pt; 2499 2500 if (_isString(end)) { 2501 if (~end.indexOf("random(")) { 2502 end = _replaceRandom(end); 2503 } 2504 2505 if (end.charAt(1) === "=") { 2506 end = parseFloat(parsedStart) + parseFloat(end.substr(2)) * (end.charAt(0) === "-" ? -1 : 1) + (getUnit(parsedStart) || 0); 2507 } 2508 } 2509 2510 if (parsedStart !== end) { 2511 if (!isNaN(parsedStart * end)) { 2512 pt = new PropTween(this._pt, target, prop, +parsedStart || 0, end - (parsedStart || 0), typeof currentValue === "boolean" ? _renderBoolean : _renderPlain, 0, setter); 2513 funcParam && (pt.fp = funcParam); 2514 modifier && pt.modifier(modifier, this, target); 2515 return this._pt = pt; 2516 } 2517 2518 !currentValue && !(prop in target) && _missingPlugin(prop, end); 2519 return _addComplexStringPropTween.call(this, target, prop, parsedStart, end, setter, stringFilter || _config.stringFilter, funcParam); 2520 } 2521 }, 2522 _processVars = function _processVars(vars, index, target, targets, tween) { 2523 _isFunction(vars) && (vars = _parseFuncOrString(vars, tween, index, target, targets)); 2524 2525 if (!_isObject(vars) || vars.style && vars.nodeType || _isArray(vars) || _isTypedArray(vars)) { 2526 return _isString(vars) ? _parseFuncOrString(vars, tween, index, target, targets) : vars; 2527 } 2528 2529 var copy = {}, 2530 p; 2531 2532 for (p in vars) { 2533 copy[p] = _parseFuncOrString(vars[p], tween, index, target, targets); 2534 } 2535 2536 return copy; 2537 }, 2538 _checkPlugin = function _checkPlugin(property, vars, tween, index, target, targets) { 2539 var plugin, pt, ptLookup, i; 2540 2541 if (_plugins[property] && (plugin = new _plugins[property]()).init(target, plugin.rawVars ? vars[property] : _processVars(vars[property], index, target, targets, tween), tween, index, targets) !== false) { 2542 tween._pt = pt = new PropTween(tween._pt, target, property, 0, 1, plugin.render, plugin, 0, plugin.priority); 2543 2544 if (tween !== _quickTween) { 2545 ptLookup = tween._ptLookup[tween._targets.indexOf(target)]; 2546 i = plugin._props.length; 2547 2548 while (i--) { 2549 ptLookup[plugin._props[i]] = pt; 2550 } 2551 } 2552 } 2553 2554 return plugin; 2555 }, 2556 _overwritingTween, 2557 _initTween = function _initTween(tween, time) { 2558 var vars = tween.vars, 2559 ease = vars.ease, 2560 startAt = vars.startAt, 2561 immediateRender = vars.immediateRender, 2562 lazy = vars.lazy, 2563 onUpdate = vars.onUpdate, 2564 onUpdateParams = vars.onUpdateParams, 2565 callbackScope = vars.callbackScope, 2566 runBackwards = vars.runBackwards, 2567 yoyoEase = vars.yoyoEase, 2568 keyframes = vars.keyframes, 2569 autoRevert = vars.autoRevert, 2570 dur = tween._dur, 2571 prevStartAt = tween._startAt, 2572 targets = tween._targets, 2573 parent = tween.parent, 2574 fullTargets = parent && parent.data === "nested" ? parent.parent._targets : targets, 2575 autoOverwrite = tween._overwrite === "auto" && !_suppressOverwrites, 2576 tl = tween.timeline, 2577 cleanVars, 2578 i, 2579 p, 2580 pt, 2581 target, 2582 hasPriority, 2583 gsData, 2584 harness, 2585 plugin, 2586 ptLookup, 2587 index, 2588 harnessVars, 2589 overwritten; 2590 tl && (!keyframes || !ease) && (ease = "none"); 2591 tween._ease = _parseEase(ease, _defaults.ease); 2592 tween._yEase = yoyoEase ? _invertEase(_parseEase(yoyoEase === true ? ease : yoyoEase, _defaults.ease)) : 0; 2593 2594 if (yoyoEase && tween._yoyo && !tween._repeat) { 2595 yoyoEase = tween._yEase; 2596 tween._yEase = tween._ease; 2597 tween._ease = yoyoEase; 2598 } 2599 2600 if (!tl) { 2601 harness = targets[0] ? _getCache(targets[0]).harness : 0; 2602 harnessVars = harness && vars[harness.prop]; 2603 cleanVars = _copyExcluding(vars, _reservedProps); 2604 prevStartAt && prevStartAt.render(-1, true).kill(); 2605 2606 if (startAt) { 2607 _removeFromParent(tween._startAt = Tween.set(targets, _setDefaults({ 2608 data: "isStart", 2609 overwrite: false, 2610 parent: parent, 2611 immediateRender: true, 2612 lazy: _isNotFalse(lazy), 2613 startAt: null, 2614 delay: 0, 2615 onUpdate: onUpdate, 2616 onUpdateParams: onUpdateParams, 2617 callbackScope: callbackScope, 2618 stagger: 0 2619 }, startAt))); 2620 2621 if (immediateRender) { 2622 if (time > 0) { 2623 autoRevert || (tween._startAt = 0); 2624 } else if (dur && !(time < 0 && prevStartAt)) { 2625 time && (tween._zTime = time); 2626 return; 2627 } 2628 } else if (autoRevert === false) { 2629 tween._startAt = 0; 2630 } 2631 } else if (runBackwards && dur) { 2632 if (prevStartAt) { 2633 !autoRevert && (tween._startAt = 0); 2634 } else { 2635 time && (immediateRender = false); 2636 p = _setDefaults({ 2637 overwrite: false, 2638 data: "isFromStart", 2639 lazy: immediateRender && _isNotFalse(lazy), 2640 immediateRender: immediateRender, 2641 stagger: 0, 2642 parent: parent 2643 }, cleanVars); 2644 harnessVars && (p[harness.prop] = harnessVars); 2645 2646 _removeFromParent(tween._startAt = Tween.set(targets, p)); 2647 2648 if (!immediateRender) { 2649 _initTween(tween._startAt, _tinyNum); 2650 } else if (!time) { 2651 return; 2652 } 2653 } 2654 } 2655 2656 tween._pt = 0; 2657 lazy = dur && _isNotFalse(lazy) || lazy && !dur; 2658 2659 for (i = 0; i < targets.length; i++) { 2660 target = targets[i]; 2661 gsData = target._gsap || _harness(targets)[i]._gsap; 2662 tween._ptLookup[i] = ptLookup = {}; 2663 _lazyLookup[gsData.id] && _lazyTweens.length && _lazyRender(); 2664 index = fullTargets === targets ? i : fullTargets.indexOf(target); 2665 2666 if (harness && (plugin = new harness()).init(target, harnessVars || cleanVars, tween, index, fullTargets) !== false) { 2667 tween._pt = pt = new PropTween(tween._pt, target, plugin.name, 0, 1, plugin.render, plugin, 0, plugin.priority); 2668 2669 plugin._props.forEach(function (name) { 2670 ptLookup[name] = pt; 2671 }); 2672 2673 plugin.priority && (hasPriority = 1); 2674 } 2675 2676 if (!harness || harnessVars) { 2677 for (p in cleanVars) { 2678 if (_plugins[p] && (plugin = _checkPlugin(p, cleanVars, tween, index, target, fullTargets))) { 2679 plugin.priority && (hasPriority = 1); 2680 } else { 2681 ptLookup[p] = pt = _addPropTween.call(tween, target, p, "get", cleanVars[p], index, fullTargets, 0, vars.stringFilter); 2682 } 2683 } 2684 } 2685 2686 tween._op && tween._op[i] && tween.kill(target, tween._op[i]); 2687 2688 if (autoOverwrite && tween._pt) { 2689 _overwritingTween = tween; 2690 2691 _globalTimeline.killTweensOf(target, ptLookup, tween.globalTime(0)); 2692 2693 overwritten = !tween.parent; 2694 _overwritingTween = 0; 2695 } 2696 2697 tween._pt && lazy && (_lazyLookup[gsData.id] = 1); 2698 } 2699 2700 hasPriority && _sortPropTweensByPriority(tween); 2701 tween._onInit && tween._onInit(tween); 2702 } 2703 2704 tween._from = !tl && !!vars.runBackwards; 2705 tween._onUpdate = onUpdate; 2706 tween._initted = (!tween._op || tween._pt) && !overwritten; 2707 }, 2708 _addAliasesToVars = function _addAliasesToVars(targets, vars) { 2709 var harness = targets[0] ? _getCache(targets[0]).harness : 0, 2710 propertyAliases = harness && harness.aliases, 2711 copy, 2712 p, 2713 i, 2714 aliases; 2715 2716 if (!propertyAliases) { 2717 return vars; 2718 } 2719
2720 copy = _merge({}, vars); 2721 2722 for (p in propertyAliases) { 2723 if (p in copy) { 2724 aliases = propertyAliases[p].split(","); 2725 i = aliases.length; 2726 2727 while (i--) { 2728 copy[aliases[i]] = copy[p]; 2729 } 2730 } 2731 } 2732 2733 return copy; 2734 }, 2735 _parseFuncOrString = function _parseFuncOrString(value, tween, i, target, targets) { 2736 return _isFunction(value) ? value.call(tween, i, target, targets) : _isString(value) && ~value.indexOf("random(") ? _replaceRandom(value) : value; 2737 }, 2738 _staggerTweenProps = _callbackNames + "repeat,repeatDelay,yoyo,repeatRefresh,yoyoEase", 2739 _staggerPropsToSkip = (_staggerTweenProps + ",id,stagger,delay,duration,paused,scrollTrigger").split(","); 2740 2741 var Tween = function (_Animation2) { 2742 _inheritsLoose(Tween, _Animation2); 2743 2744 function Tween(targets, vars, time, skipInherit) { 2745 var _this3; 2746 2747 if (typeof vars === "number") { 2748 time.duration = vars; 2749 vars = time; 2750 time = null; 2751 } 2752 2753 _this3 = _Animation2.call(this, skipInherit ? vars : _inheritDefaults(vars), time) || this; 2754 var _this3$vars = _this3.vars, 2755 duration = _this3$vars.duration, 2756 delay = _this3$vars.delay, 2757 immediateRender = _this3$vars.immediateRender, 2758 stagger = _this3$vars.stagger, 2759 overwrite = _this3$vars.overwrite, 2760 keyframes = _this3$vars.keyframes, 2761 defaults = _this3$vars.defaults, 2762 scrollTrigger = _this3$vars.scrollTrigger, 2763 yoyoEase = _this3$vars.yoyoEase, 2764 parent = _this3.parent, 2765 parsedTargets = (_isArray(targets) || _isTypedArray(targets) ? _isNumber(targets[0]) : "length" in vars) ? [targets] : toArray(targets), 2766 tl, 2767 i, 2768 copy, 2769 l, 2770 p, 2771 curTarget, 2772 staggerFunc, 2773 staggerVarsToMerge; 2774 _this3._targets = parsedTargets.length ? _harness(parsedTargets) : _warn("GSAP target " + targets + " not found. https://greensock.com", !_config.nullTargetWarn) || []; 2775 _this3._ptLookup = []; 2776 _this3._overwrite = overwrite; 2777 2778 if (keyframes || stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) { 2779 vars = _this3.vars; 2780 tl = _this3.timeline = new Timeline({ 2781 data: "nested", 2782 defaults: defaults || {} 2783 }); 2784 tl.kill(); 2785 tl.parent = tl._dp = _assertThisInitialized(_this3); 2786 tl._start = 0; 2787 2788 if (keyframes) { 2789 _setDefaults(tl.vars.defaults, { 2790 ease: "none" 2791 }); 2792 2793 keyframes.forEach(function (frame) { 2794 return tl.to(parsedTargets, frame, ">"); 2795 }); 2796 } else { 2797 l = parsedTargets.length; 2798 staggerFunc = stagger ? distribute(stagger) : _emptyFunc; 2799 2800 if (_isObject(stagger)) { 2801 for (p in stagger) { 2802 if (~_staggerTweenProps.indexOf(p)) { 2803 staggerVarsToMerge || (staggerVarsToMerge = {}); 2804 staggerVarsToMerge[p] = stagger[p]; 2805 } 2806 } 2807 } 2808 2809 for (i = 0; i < l; i++) { 2810 copy = {}; 2811 2812 for (p in vars) { 2813 if (_staggerPropsToSkip.indexOf(p) < 0) { 2814 copy[p] = vars[p]; 2815 } 2816 } 2817 2818 copy.stagger = 0; 2819 yoyoEase && (copy.yoyoEase = yoyoEase); 2820 staggerVarsToMerge && _merge(copy, staggerVarsToMerge); 2821 curTarget = parsedTargets[i]; 2822 copy.duration = +_parseFuncOrString(duration, _assertThisInitialized(_this3), i, curTarget, parsedTargets); 2823 copy.delay = (+_parseFuncOrString(delay, _assertThisInitialized(_this3), i, curTarget, parsedTargets) || 0) - _this3._delay; 2824 2825 if (!stagger && l === 1 && copy.delay) { 2826 _this3._delay = delay = copy.delay; 2827 _this3._start += delay; 2828 copy.delay = 0; 2829 } 2830 2831 tl.to(curTarget, copy, staggerFunc(i, curTarget, parsedTargets)); 2832 } 2833 2834 tl.duration() ? duration = delay = 0 : _this3.timeline = 0; 2835 } 2836 2837 duration || _this3.duration(duration = tl.duration()); 2838 } else { 2839 _this3.timeline = 0; 2840 } 2841 2842 if (overwrite === true && !_suppressOverwrites) { 2843 _overwritingTween = _assertThisInitialized(_this3); 2844 2845 _globalTimeline.killTweensOf(parsedTargets); 2846 2847 _overwritingTween = 0; 2848 } 2849 2850 parent && _postAddChecks(parent, _assertThisInitialized(_this3)); 2851 2852 if (immediateRender || !duration && !keyframes && _this3._start === _round(parent._time) && _isNotFalse(immediateRender) && _hasNoPausedAncestors(_assertThisInitialized(_this3)) && parent.data !== "nested") { 2853 _this3._tTime = -_tinyNum; 2854 2855 _this3.render(Math.max(0, -delay)); 2856 } 2857 2858 scrollTrigger && _scrollTrigger(_assertThisInitialized(_this3), scrollTrigger); 2859 return _this3; 2860 } 2861 2862 var _proto3 = Tween.prototype; 2863 2864 _proto3.render = function render(totalTime, suppressEvents, force) { 2865 var prevTime = this._time, 2866 tDur = this._tDur, 2867 dur = this._dur, 2868 tTime = totalTime > tDur - _tinyNum && totalTime >= 0 ? tDur : totalTime < _tinyNum ? 0 : totalTime, 2869 time, 2870 pt, 2871 iteration, 2872 cycleDuration, 2873 prevIteration, 2874 isYoyo, 2875 ratio, 2876 timeline, 2877 yoyoEase; 2878 2879 if (!dur) { 2880 _renderZeroDurationTween(this, totalTime, suppressEvents, force); 2881 } else if (tTime !== this._tTime || !totalTime || force || !this._initted && this._tTime || this._startAt && this._zTime < 0 !== totalTime < 0) { 2882 time = tTime; 2883 timeline = this.timeline; 2884 2885 if (this._repeat) { 2886 cycleDuration = dur + this._rDelay; 2887 2888 if (this._repeat < -1 && totalTime < 0) { 2889 return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force); 2890 } 2891 2892 time = _round(tTime % cycleDuration); 2893 2894 if (tTime === tDur) { 2895 iteration = this._repeat; 2896 time = dur; 2897 } else { 2898 iteration = ~~(tTime / cycleDuration); 2899 2900 if (iteration && iteration === tTime / cycleDuration) { 2901 time = dur; 2902 iteration--; 2903 } 2904 2905 time > dur && (time = dur); 2906 } 2907 2908 isYoyo = this._yoyo && iteration & 1; 2909 2910 if (isYoyo) { 2911 yoyoEase = this._yEase; 2912 time = dur - time; 2913 } 2914 2915 prevIteration = _animationCycle(this._tTime, cycleDuration); 2916 2917 if (time === prevTime && !force && this._initted) { 2918 return this; 2919 } 2920 2921 if (iteration !== prevIteration) { 2922 timeline && this._yEase && _propagateYoyoEase(timeline, isYoyo); 2923 2924 if (this.vars.repeatRefresh && !isYoyo && !this._lock) { 2925 this._lock = force = 1; 2926 this.render(_round(cycleDuration * iteration), true).invalidate()._lock = 0; 2927 } 2928 } 2929 } 2930 2931 if (!this._initted) { 2932 if (_attemptInitTween(this, totalTime < 0 ? totalTime : time, force, suppressEvents)) { 2933 this._tTime = 0; 2934 return this; 2935 } 2936 2937 if (dur !== this._dur) { 2938 return this.render(totalTime, suppressEvents, force); 2939 } 2940 } 2941 2942 this._tTime = tTime; 2943 this._time = time; 2944 2945 if (!this._act && this._ts) { 2946 this._act = 1; 2947 this._lazy = 0; 2948 } 2949 2950 this.ratio = ratio = (yoyoEase || this._ease)(time / dur); 2951 2952 if (this._from) { 2953 this.ratio = ratio = 1 - ratio; 2954 } 2955
2956 time && !prevTime && !suppressEvents && _callback(this, "onStart"); 2957 pt = this._pt; 2958 2959 while (pt) { 2960 pt.r(ratio, pt.d); 2961 pt = pt._next; 2962 } 2963 2964 timeline && timeline.render(totalTime < 0 ? totalTime : !time && isYoyo ? -_tinyNum : timeline._dur * ratio, suppressEvents, force) || this._startAt && (this._zTime = totalTime); 2965 2966 if (this._onUpdate && !suppressEvents) { 2967 totalTime < 0 && this._startAt && this._startAt.render(totalTime, true, force); 2968 2969 _callback(this, "onUpdate"); 2970 } 2971 2972 this._repeat && iteration !== prevIteration && this.vars.onRepeat && !suppressEvents && this.parent && _callback(this, "onRepeat"); 2973 2974 if ((tTime === this._tDur || !tTime) && this._tTime === tTime) { 2975 totalTime < 0 && this._startAt && !this._onUpdate && this._startAt.render(totalTime, true, true); 2976 (totalTime || !dur) && (tTime === this._tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1); 2977 2978 if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime)) { 2979 _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true); 2980 2981 this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom(); 2982 } 2983 } 2984 } 2985 2986 return this; 2987 }; 2988 2989 _proto3.targets = function targets() { 2990 return this._targets; 2991 }; 2992
vendor: 32,418 bytes, lines 2993-4050
2993 _proto3.invalidate = function invalidate() { 2994 this._pt = this._op = this._startAt = this._onUpdate = this._lazy = this.ratio = 0; 2995 this._ptLookup = []; 2996 this.timeline && this.timeline.invalidate(); 2997 return _Animation2.prototype.invalidate.call(this); 2998 }; 2999 3000 _proto3.kill = function kill(targets, vars) { 3001 if (vars === void 0) { 3002 vars = "all"; 3003 } 3004 3005 if (!targets && (!vars || vars === "all")) { 3006 this._lazy = this._pt = 0; 3007 return this.parent ? _interrupt(this) : this; 3008 } 3009 3010 if (this.timeline) { 3011 var tDur = this.timeline.totalDuration(); 3012 this.timeline.killTweensOf(targets, vars, _overwritingTween && _overwritingTween.vars.overwrite !== true)._first || _interrupt(this); 3013 this.parent && tDur !== this.timeline.totalDuration() && _setDuration(this, this._dur * this.timeline._tDur / tDur, 0, 1); 3014 return this; 3015 } 3016 3017 var parsedTargets = this._targets, 3018 killingTargets = targets ? toArray(targets) : parsedTargets, 3019 propTweenLookup = this._ptLookup, 3020 firstPT = this._pt, 3021 overwrittenProps, 3022 curLookup, 3023 curOverwriteProps, 3024 props, 3025 p, 3026 pt, 3027 i; 3028 3029 if ((!vars || vars === "all") && _arraysMatch(parsedTargets, killingTargets)) { 3030 vars === "all" && (this._pt = 0); 3031 return _interrupt(this); 3032 } 3033 3034 overwrittenProps = this._op = this._op || []; 3035 3036 if (vars !== "all") { 3037 if (_isString(vars)) { 3038 p = {}; 3039 3040 _forEachName(vars, function (name) { 3041 return p[name] = 1; 3042 }); 3043 3044 vars = p; 3045 } 3046 3047 vars = _addAliasesToVars(parsedTargets, vars); 3048 } 3049 3050 i = parsedTargets.length; 3051 3052 while (i--) { 3053 if (~killingTargets.indexOf(parsedTargets[i])) { 3054 curLookup = propTweenLookup[i]; 3055 3056 if (vars === "all") { 3057 overwrittenProps[i] = vars; 3058 props = curLookup; 3059 curOverwriteProps = {}; 3060 } else { 3061 curOverwriteProps = overwrittenProps[i] = overwrittenProps[i] || {}; 3062 props = vars; 3063 } 3064 3065 for (p in props) { 3066 pt = curLookup && curLookup[p]; 3067 3068 if (pt) { 3069 if (!("kill" in pt.d) || pt.d.kill(p) === true) { 3070 _removeLinkedListItem(this, pt, "_pt"); 3071 } 3072 3073 delete curLookup[p]; 3074 } 3075 3076 if (curOverwriteProps !== "all") { 3077 curOverwriteProps[p] = 1; 3078 } 3079 } 3080 } 3081 } 3082 3083 this._initted && !this._pt && firstPT && _interrupt(this); 3084 return this; 3085 }; 3086 3087 Tween.to = function to(targets, vars) { 3088 return new Tween(targets, vars, arguments[2]); 3089 }; 3090 3091 Tween.from = function from(targets, vars) { 3092 return new Tween(targets, _parseVars(arguments, 1)); 3093 }; 3094 3095 Tween.delayedCall = function delayedCall(delay, callback, params, scope) { 3096 return new Tween(callback, 0, { 3097 immediateRender: false, 3098 lazy: false, 3099 overwrite: false, 3100 delay: delay, 3101 onComplete: callback, 3102 onReverseComplete: callback, 3103 onCompleteParams: params, 3104 onReverseCompleteParams: params, 3105 callbackScope: scope 3106 }); 3107 }; 3108 3109 Tween.fromTo = function fromTo(targets, fromVars, toVars) { 3110 return new Tween(targets, _parseVars(arguments, 2)); 3111 }; 3112 3113 Tween.set = function set(targets, vars) { 3114 vars.duration = 0; 3115 vars.repeatDelay || (vars.repeat = 0); 3116 return new Tween(targets, vars); 3117 }; 3118 3119 Tween.killTweensOf = function killTweensOf(targets, props, onlyActive) { 3120 return _globalTimeline.killTweensOf(targets, props, onlyActive); 3121 }; 3122 3123 return Tween; 3124 }(Animation); 3125 3126 _setDefaults(Tween.prototype, { 3127 _targets: [], 3128 _lazy: 0, 3129 _startAt: 0, 3130 _op: 0, 3131 _onInit: 0 3132 }); 3133 3134 _forEachName("staggerTo,staggerFrom,staggerFromTo", function (name) { 3135 Tween[name] = function () { 3136 var tl = new Timeline(), 3137 params = _slice.call(arguments, 0); 3138 3139 params.splice(name === "staggerFromTo" ? 5 : 4, 0, 0); 3140 return tl[name].apply(tl, params); 3141 }; 3142 }); 3143 3144 var _setterPlain = function _setterPlain(target, property, value) { 3145 return target[property] = value; 3146 }, 3147 _setterFunc = function _setterFunc(target, property, value) { 3148 return target[property](value); 3149 }, 3150 _setterFuncWithParam = function _setterFuncWithParam(target, property, value, data) { 3151 return target[property](data.fp, value); 3152 }, 3153 _setterAttribute = function _setterAttribute(target, property, value) { 3154 return target.setAttribute(property, value); 3155 }, 3156 _getSetter = function _getSetter(target, property) { 3157 return _isFunction(target[property]) ? _setterFunc : _isUndefined(target[property]) && target.setAttribute ? _setterAttribute : _setterPlain; 3158 }, 3159 _renderPlain = function _renderPlain(ratio, data) { 3160 return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000, data); 3161 }, 3162 _renderBoolean = function _renderBoolean(ratio, data) { 3163 return data.set(data.t, data.p, !!(data.s + data.c * ratio), data); 3164 }, 3165 _renderComplexString = function _renderComplexString(ratio, data) { 3166 var pt = data._pt, 3167 s = ""; 3168 3169 if (!ratio && data.b) { 3170 s = data.b; 3171 } else if (ratio === 1 && data.e) { 3172 s = data.e; 3173 } else { 3174 while (pt) { 3175 s = pt.p + (pt.m ? pt.m(pt.s + pt.c * ratio) : Math.round((pt.s + pt.c * ratio) * 10000) / 10000) + s; 3176 pt = pt._next; 3177 } 3178 3179 s += data.c; 3180 } 3181 3182 data.set(data.t, data.p, s, data); 3183 }, 3184 _renderPropTweens = function _renderPropTweens(ratio, data) { 3185 var pt = data._pt; 3186 3187 while (pt) { 3188 pt.r(ratio, pt.d); 3189 pt = pt._next; 3190 } 3191 }, 3192 _addPluginModifier = function _addPluginModifier(modifier, tween, target, property) { 3193 var pt = this._pt, 3194 next; 3195 3196 while (pt) { 3197 next = pt._next; 3198 pt.p === property && pt.modifier(modifier, tween, target); 3199 pt = next; 3200 } 3201 }, 3202 _killPropTweensOf = function _killPropTweensOf(property) { 3203 var pt = this._pt, 3204 hasNonDependentRemaining, 3205 next; 3206 3207 while (pt) { 3208 next = pt._next; 3209 3210 if (pt.p === property && !pt.op || pt.op === property) { 3211 _removeLinkedListItem(this, pt, "_pt"); 3212 } else if (!pt.dep) { 3213 hasNonDependentRemaining = 1; 3214 } 3215 3216 pt = next; 3217 } 3218 3219 return !hasNonDependentRemaining; 3220 }, 3221 _setterWithModifier = function _setterWithModifier(target, property, value, data) { 3222 data.mSet(target, property, data.m.call(data.tween, value, data.mt), data); 3223 }, 3224 _sortPropTweensByPriority = function _sortPropTweensByPriority(parent) { 3225 var pt = parent._pt, 3226 next, 3227 pt2, 3228 first, 3229 last; 3230 3231 while (pt) { 3232 next = pt._next; 3233 pt2 = first; 3234 3235 while (pt2 && pt2.pr > pt.pr) { 3236 pt2 = pt2._next; 3237 } 3238 3239 if (pt._prev = pt2 ? pt2._prev : last) { 3240 pt._prev._next = pt; 3241 } else { 3242 first = pt; 3243 } 3244 3245 if (pt._next = pt2) { 3246 pt2._prev = pt; 3247 } else { 3248 last = pt; 3249 } 3250 3251 pt = next; 3252 } 3253 3254 parent._pt = first; 3255 }; 3256 3257 var PropTween = function () { 3258 function PropTween(next, target, prop, start, change, renderer, data, setter, priority) { 3259 this.t = target; 3260 this.s = start; 3261 this.c = change; 3262 this.p = prop; 3263 this.r = renderer || _renderPlain; 3264 this.d = data || this; 3265 this.set = setter || _setterPlain; 3266 this.pr = priority || 0; 3267 this._next = next; 3268 3269 if (next) { 3270 next._prev = this; 3271 } 3272 } 3273 3274 var _proto4 = PropTween.prototype; 3275 3276 _proto4.modifier = function modifier(func, tween, target) { 3277 this.mSet = this.mSet || this.set; 3278 this.set = _setterWithModifier; 3279 this.m = func; 3280 this.mt = target; 3281 this.tween = tween; 3282 }; 3283 3284 return PropTween; 3285 }(); 3286 3287 _forEachName(_callbackNames + "parent,duration,ease,delay,overwrite,runBackwards,startAt,yoyo,immediateRender,repeat,repeatDelay,data,paused,reversed,lazy,callbackScope,stringFilter,id,yoyoEase,stagger,inherit,repeatRefresh,keyframes,autoRevert,scrollTrigger", function (name) { 3288 return _reservedProps[name] = 1; 3289 }); 3290 3291 _globals.TweenMax = _globals.TweenLite = Tween; 3292 _globals.TimelineLite = _globals.TimelineMax = Timeline; 3293 _globalTimeline = new Timeline({ 3294 sortChildren: false, 3295 defaults: _defaults, 3296 autoRemoveChildren: true, 3297 id: "root", 3298 smoothChildTiming: true 3299 }); 3300 _config.stringFilter = _colorStringFilter; 3301 var _gsap = { 3302 registerPlugin: function registerPlugin() { 3303 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 3304 args[_key2] = arguments[_key2]; 3305 } 3306 3307 args.forEach(function (config) { 3308 return _createPlugin(config); 3309 }); 3310 }, 3311 timeline: function timeline(vars) { 3312 return new Timeline(vars); 3313 }, 3314 getTweensOf: function getTweensOf(targets, onlyActive) { 3315 return _globalTimeline.getTweensOf(targets, onlyActive); 3316 }, 3317 getProperty: function getProperty(target, property, unit, uncache) { 3318 _isString(target) && (target = toArray(target)[0]); 3319 3320 var getter = _getCache(target || {}).get, 3321 format = unit ? _passThrough : _numericIfPossible; 3322 3323 unit === "native" && (unit = ""); 3324 return !target ? target : !property ? function (property, unit, uncache) { 3325 return format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache)); 3326 } : format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache)); 3327 }, 3328 quickSetter: function quickSetter(target, property, unit) { 3329 target = toArray(target); 3330 3331 if (target.length > 1) { 3332 var setters = target.map(function (t) { 3333 return gsap.quickSetter(t, property, unit); 3334 }), 3335 l = setters.length; 3336 return function (value) { 3337 var i = l; 3338 3339 while (i--) { 3340 setters[i](value); 3341 } 3342 }; 3343 } 3344 3345 target = target[0] || {}; 3346 3347 var Plugin = _plugins[property], 3348 cache = _getCache(target), 3349 p = cache.harness && (cache.harness.aliases || {})[property] || property, 3350 setter = Plugin ? function (value) { 3351 var p = new Plugin(); 3352 _quickTween._pt = 0; 3353 p.init(target, unit ? value + unit : value, _quickTween, 0, [target]); 3354 p.render(1, p); 3355 _quickTween._pt && _renderPropTweens(1, _quickTween); 3356 } : cache.set(target, p); 3357 3358 return Plugin ? setter : function (value) { 3359 return setter(target, p, unit ? value + unit : value, cache, 1); 3360 }; 3361 }, 3362 isTweening: function isTweening(targets) { 3363 return _globalTimeline.getTweensOf(targets, true).length > 0; 3364 }, 3365 defaults: function defaults(value) { 3366 value && value.ease && (value.ease = _parseEase(value.ease, _defaults.ease)); 3367 return _mergeDeep(_defaults, value || {}); 3368 }, 3369 config: function config(value) { 3370 return _mergeDeep(_config, value || {}); 3371 }, 3372 registerEffect: function registerEffect(_ref2) { 3373 var name = _ref2.name, 3374 effect = _ref2.effect, 3375 plugins = _ref2.plugins, 3376 defaults = _ref2.defaults, 3377 extendTimeline = _ref2.extendTimeline; 3378 (plugins || "").split(",").forEach(function (pluginName) { 3379 return pluginName && !_plugins[pluginName] && !_globals[pluginName] && _warn(name + " effect requires " + pluginName + " plugin."); 3380 }); 3381 3382 _effects[name] = function (targets, vars, tl) { 3383 return effect(toArray(targets), _setDefaults(vars || {}, defaults), tl); 3384 }; 3385 3386 if (extendTimeline) { 3387 Timeline.prototype[name] = function (targets, vars, position) { 3388 return this.add(_effects[name](targets, _isObject(vars) ? vars : (position = vars) && {}, this), position); 3389 }; 3390 } 3391 }, 3392 registerEase: function registerEase(name, ease) { 3393 _easeMap[name] = _parseEase(ease); 3394 }, 3395 parseEase: function parseEase(ease, defaultEase) { 3396 return arguments.length ? _parseEase(ease, defaultEase) : _easeMap; 3397 }, 3398 getById: function getById(id) { 3399 return _globalTimeline.getById(id); 3400 }, 3401 exportRoot: function exportRoot(vars, includeDelayedCalls) { 3402 if (vars === void 0) { 3403 vars = {}; 3404 } 3405 3406 var tl = new Timeline(vars), 3407 child, 3408 next; 3409 tl.smoothChildTiming = _isNotFalse(vars.smoothChildTiming); 3410 3411 _globalTimeline.remove(tl); 3412 3413 tl._dp = 0; 3414 tl._time = tl._tTime = _globalTimeline._time; 3415 child = _globalTimeline._first; 3416 3417 while (child) { 3418 next = child._next; 3419 3420 if (includeDelayedCalls || !(!child._dur && child instanceof Tween && child.vars.onComplete === child._targets[0])) { 3421 _addToTimeline(tl, child, child._start - child._delay); 3422 } 3423 3424 child = next; 3425 } 3426 3427 _addToTimeline(_globalTimeline, tl, 0); 3428 3429 return tl; 3430 }, 3431 utils: { 3432 wrap: wrap, 3433 wrapYoyo: wrapYoyo, 3434 distribute: distribute, 3435 random: random, 3436 snap: snap, 3437 normalize: normalize, 3438 getUnit: getUnit, 3439 clamp: clamp, 3440 splitColor: splitColor, 3441 toArray: toArray, 3442 mapRange: mapRange, 3443 pipe: pipe, 3444 unitize: unitize, 3445 interpolate: interpolate, 3446 shuffle: shuffle 3447 }, 3448 install: _install, 3449 effects: _effects, 3450 ticker: _ticker, 3451 updateRoot: Timeline.updateRoot, 3452 plugins: _plugins, 3453 globalTimeline: _globalTimeline, 3454 core: { 3455 PropTween: PropTween, 3456 globals: _addGlobal, 3457 Tween: Tween, 3458 Timeline: Timeline, 3459 Animation: Animation, 3460 getCache: _getCache, 3461 _removeLinkedListItem: _removeLinkedListItem, 3462 suppressOverwrites: function suppressOverwrites(value) { 3463 return _suppressOverwrites = value; 3464 } 3465 } 3466 }; 3467 3468 _forEachName("to,from,fromTo,delayedCall,set,killTweensOf", function (name) { 3469 return _gsap[name] = Tween[name]; 3470 }); 3471 3472 _ticker.add(Timeline.updateRoot); 3473 3474 _quickTween = _gsap.to({}, { 3475 duration: 0 3476 }); 3477 3478 var _getPluginPropTween = function _getPluginPropTween(plugin, prop) { 3479 var pt = plugin._pt; 3480 3481 while (pt && pt.p !== prop && pt.op !== prop && pt.fp !== prop) { 3482 pt = pt._next; 3483 } 3484 3485 return pt; 3486 }, 3487 _addModifiers = function _addModifiers(tween, modifiers) { 3488 var targets = tween._targets, 3489 p, 3490 i, 3491 pt; 3492 3493 for (p in modifiers) { 3494 i = targets.length; 3495 3496 while (i--) { 3497 pt = tween._ptLookup[i][p]; 3498 3499 if (pt && (pt = pt.d)) { 3500 if (pt._pt) { 3501 pt = _getPluginPropTween(pt, p); 3502 } 3503 3504 pt && pt.modifier && pt.modifier(modifiers[p], tween, targets[i], p); 3505 } 3506 } 3507 } 3508 }, 3509 _buildModifierPlugin = function _buildModifierPlugin(name, modifier) { 3510 return { 3511 name: name, 3512 rawVars: 1, 3513 init: function init(target, vars, tween) { 3514 tween._onInit = function (tween) { 3515 var temp, p; 3516 3517 if (_isString(vars)) { 3518 temp = {}; 3519 3520 _forEachName(vars, function (name) { 3521 return temp[name] = 1; 3522 }); 3523 3524 vars = temp; 3525 } 3526 3527 if (modifier) { 3528 temp = {}; 3529 3530 for (p in vars) { 3531 temp[p] = modifier(vars[p]); 3532 } 3533 3534 vars = temp; 3535 } 3536 3537 _addModifiers(tween, vars); 3538 }; 3539 } 3540 }; 3541 }; 3542 3543 var gsap = _gsap.registerPlugin({ 3544 name: "attr", 3545 init: function init(target, vars, tween, index, targets) { 3546 var p, pt; 3547 3548 for (p in vars) { 3549 pt = this.add(target, "setAttribute", (target.getAttribute(p) || 0) + "", vars[p], index, targets, 0, 0, p); 3550 pt && (pt.op = p); 3551 3552 this._props.push(p); 3553 } 3554 } 3555 }, { 3556 name: "endArray", 3557 init: function init(target, value) { 3558 var i = value.length; 3559 3560 while (i--) { 3561 this.add(target, i, target[i] || 0, value[i]); 3562 } 3563 } 3564 }, _buildModifierPlugin("roundProps", _roundModifier), _buildModifierPlugin("modifiers"), _buildModifierPlugin("snap", snap)) || _gsap; 3565 Tween.version = Timeline.version = gsap.version = "3.6.1"; 3566 _coreReady = 1; 3567 3568 if (_windowExists()) { 3569 _wake(); 3570 } 3571 3572 var Power0 = _easeMap.Power0, 3573 Power1 = _easeMap.Power1, 3574 Power2 = _easeMap.Power2, 3575 Power3 = _easeMap.Power3, 3576 Power4 = _easeMap.Power4, 3577 Linear = _easeMap.Linear, 3578 Quad = _easeMap.Quad, 3579 Cubic = _easeMap.Cubic, 3580 Quart = _easeMap.Quart, 3581 Quint = _easeMap.Quint, 3582 Strong = _easeMap.Strong, 3583 Elastic = _easeMap.Elastic, 3584 Back = _easeMap.Back, 3585 SteppedEase = _easeMap.SteppedEase, 3586 Bounce = _easeMap.Bounce, 3587 Sine = _easeMap.Sine, 3588 Expo = _easeMap.Expo, 3589 Circ = _easeMap.Circ; 3590 3591 var _win$1, 3592 _doc$1, 3593 _docElement, 3594 _pluginInitted, 3595 _tempDiv, 3596 _tempDivStyler, 3597 _recentSetterPlugin, 3598 _windowExists$1 = function _windowExists() { 3599 return typeof window !== "undefined"; 3600 }, 3601 _transformProps = {}, 3602 _RAD2DEG = 180 / Math.PI, 3603 _DEG2RAD = Math.PI / 180, 3604 _atan2 = Math.atan2, 3605 _bigNum$1 = 1e8, 3606 _capsExp = /([A-Z])/g, 3607 _horizontalExp = /(?:left|right|width|margin|padding|x)/i, 3608 _complexExp = /[\s,\(]\S/, 3609 _propertyAliases = { 3610 autoAlpha: "opacity,visibility", 3611 scale: "scaleX,scaleY", 3612 alpha: "opacity" 3613 }, 3614 _renderCSSProp = function _renderCSSProp(ratio, data) { 3615 return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); 3616 }, 3617 _renderPropWithEnd = function _renderPropWithEnd(ratio, data) { 3618 return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); 3619 }, 3620 _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) { 3621 return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data); 3622 }, 3623 _renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) { 3624 var value = data.s + data.c * ratio; 3625 data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data); 3626 }, 3627 _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) { 3628 return data.set(data.t, data.p, ratio ? data.e : data.b, data); 3629 }, 3630 _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) { 3631 return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data); 3632 }, 3633 _setterCSSStyle = function _setterCSSStyle(target, property, value) { 3634 return target.style[property] = value; 3635 }, 3636 _setterCSSProp = function _setterCSSProp(target, property, value) { 3637 return target.style.setProperty(property, value); 3638 }, 3639 _setterTransform = function _setterTransform(target, property, value) { 3640 return target._gsap[property] = value; 3641 }, 3642 _setterScale = function _setterScale(target, property, value) { 3643 return target._gsap.scaleX = target._gsap.scaleY = value; 3644 }, 3645 _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) { 3646 var cache = target._gsap; 3647 cache.scaleX = cache.scaleY = value; 3648 cache.renderTransform(ratio, cache); 3649 }, 3650 _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) { 3651 var cache = target._gsap; 3652 cache[property] = value; 3653 cache.renderTransform(ratio, cache); 3654 }, 3655 _transformProp = "transform", 3656 _transformOriginProp = _transformProp + "Origin", 3657 _supports3D, 3658 _createElement = function _createElement(type, ns) { 3659 var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type); 3660 return e.style ? e : _doc$1.createElement(type); 3661 }, 3662 _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) { 3663 var cs = getComputedStyle(target); 3664 return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || ""; 3665 }, 3666 _prefixes = "O,Moz,ms,Ms,Webkit".split(","), 3667 _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) { 3668 var e = element || _tempDiv, 3669 s = e.style, 3670 i = 5; 3671 3672 if (property in s && !preferPrefix) { 3673 return property; 3674 } 3675 3676 property = property.charAt(0).toUpperCase() + property.substr(1); 3677 3678 while (i-- && !(_prefixes[i] + property in s)) {} 3679 3680 return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property; 3681 }, 3682 _initCore = function _initCore() { 3683 if (_windowExists$1() && window.document) { 3684 _win$1 = window; 3685 _doc$1 = _win$1.document; 3686 _docElement = _doc$1.documentElement; 3687 _tempDiv = _createElement("div") || { 3688 style: {} 3689 }; 3690 _tempDivStyler = _createElement("div"); 3691 _transformProp = _checkPropPrefix(_transformProp); 3692 _transformOriginProp = _transformProp + "Origin"; 3693 _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0"; 3694 _supports3D = !!_checkPropPrefix("perspective"); 3695 _pluginInitted = 1; 3696 } 3697 }, 3698 _getBBoxHack = function _getBBoxHack(swapIfPossible) { 3699 var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"), 3700 oldParent = this.parentNode, 3701 oldSibling = this.nextSibling, 3702 oldCSS = this.style.cssText, 3703 bbox; 3704 3705 _docElement.appendChild(svg); 3706 3707 svg.appendChild(this); 3708 this.style.display = "block"; 3709 3710 if (swapIfPossible) { 3711 try { 3712 bbox = this.getBBox(); 3713 this._gsapBBox = this.getBBox; 3714 this.getBBox = _getBBoxHack; 3715 } catch (e) {} 3716 } else if (this._gsapBBox) { 3717 bbox = this._gsapBBox(); 3718 } 3719 3720 if (oldParent) { 3721 if (oldSibling) { 3722 oldParent.insertBefore(this, oldSibling); 3723 } else { 3724 oldParent.appendChild(this); 3725 } 3726 } 3727 3728 _docElement.removeChild(svg); 3729 3730 this.style.cssText = oldCSS; 3731 return bbox; 3732 }, 3733 _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) { 3734 var i = attributesArray.length; 3735 3736 while (i--) { 3737 if (target.hasAttribute(attributesArray[i])) { 3738 return target.getAttribute(attributesArray[i]); 3739 } 3740 } 3741 }, 3742 _getBBox = function _getBBox(target) { 3743 var bounds; 3744 3745 try { 3746 bounds = target.getBBox(); 3747 } catch (error) { 3748 bounds = _getBBoxHack.call(target, true); 3749 } 3750 3751 bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true)); 3752 return bounds && !bounds.width && !bounds.x && !bounds.y ? { 3753 x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0, 3754 y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0, 3755 width: 0, 3756 height: 0 3757 } : bounds; 3758 }, 3759 _isSVG = function _isSVG(e) { 3760 return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e)); 3761 }, 3762 _removeProperty = function _removeProperty(target, property) { 3763 if (property) { 3764 var style = target.style; 3765 3766 if (property in _transformProps && property !== _transformOriginProp) { 3767 property = _transformProp; 3768 } 3769 3770 if (style.removeProperty) { 3771 if (property.substr(0, 2) === "ms" || property.substr(0, 6) === "webkit") { 3772 property = "-" + property; 3773 } 3774 3775 style.removeProperty(property.replace(_capsExp, "-$1").toLowerCase()); 3776 } else { 3777 style.removeAttribute(property); 3778 } 3779 } 3780 }, 3781 _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) { 3782 var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue); 3783 plugin._pt = pt; 3784 pt.b = beginning; 3785 pt.e = end; 3786 3787 plugin._props.push(property); 3788 3789 return pt; 3790 }, 3791 _nonConvertibleUnits = { 3792 deg: 1, 3793 rad: 1, 3794 turn: 1 3795 }, 3796 _convertToUnit = function _convertToUnit(target, property, value, unit) { 3797 var curValue = parseFloat(value) || 0, 3798 curUnit = (value + "").trim().substr((curValue + "").length) || "px", 3799 style = _tempDiv.style, 3800 horizontal = _horizontalExp.test(property), 3801 isRootSVG = target.tagName.toLowerCase() === "svg", 3802 measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"), 3803 amount = 100, 3804 toPixels = unit === "px", 3805 toPercent = unit === "%", 3806 px, 3807 parent, 3808 cache, 3809 isSVG; 3810 3811 if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) { 3812 return curValue; 3813 } 3814 3815 curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px")); 3816 isSVG = target.getCTM && _isSVG(target); 3817 3818 if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) { 3819 px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty]; 3820 return _round(toPercent ? curValue / px * amount : curValue / 100 * px); 3821 } 3822 3823 style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit); 3824 parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode; 3825 3826 if (isSVG) { 3827 parent = (target.ownerSVGElement || {}).parentNode; 3828 } 3829 3830 if (!parent || parent === _doc$1 || !parent.appendChild) { 3831 parent = _doc$1.body; 3832 } 3833 3834 cache = parent._gsap; 3835 3836 if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time) { 3837 return _round(curValue / cache.width * amount); 3838 } else { 3839 (toPercent || curUnit === "%") && (style.position = _getComputedProperty(target, "position")); 3840 parent === target && (style.position = "static"); 3841 parent.appendChild(_tempDiv); 3842 px = _tempDiv[measureProperty]; 3843 parent.removeChild(_tempDiv); 3844 style.position = "absolute"; 3845 3846 if (horizontal && toPercent) { 3847 cache = _getCache(parent); 3848 cache.time = _ticker.time; 3849 cache.width = parent[measureProperty]; 3850 } 3851 } 3852 3853 return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0); 3854 }, 3855 _get = function _get(target, property, unit, uncache) { 3856 var value; 3857 _pluginInitted || _initCore(); 3858 3859 if (property in _propertyAliases && property !== "transform") { 3860 property = _propertyAliases[property]; 3861 3862 if (~property.indexOf(",")) { 3863 property = property.split(",")[0]; 3864 } 3865 } 3866 3867 if (_transformProps[property] && property !== "transform") { 3868 value = _parseTransform(target, uncache); 3869 value = property !== "transformOrigin" ? value[property] : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px"; 3870 } else { 3871 value = target.style[property]; 3872 3873 if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) { 3874 value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0); 3875 } 3876 } 3877 3878 return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value; 3879 }, 3880 _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) { 3881 if (!start || start === "none") { 3882 var p = _checkPropPrefix(prop, target, 1), 3883 s = p && _getComputedProperty(target, p, 1); 3884 3885 if (s && s !== start) { 3886 prop = p; 3887 start = s; 3888 } else if (prop === "borderColor") { 3889 start = _getComputedProperty(target, "borderTopColor"); 3890 } 3891 } 3892 3893 var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString), 3894 index = 0, 3895 matchIndex = 0, 3896 a, 3897 result, 3898 startValues, 3899 startNum, 3900 color, 3901 startValue, 3902 endValue, 3903 endNum, 3904 chunk, 3905 endUnit, 3906 startUnit, 3907 relative, 3908 endValues; 3909 pt.b = start; 3910 pt.e = end; 3911 start += ""; 3912 end += ""; 3913 3914 if (end === "auto") { 3915 target.style[prop] = end; 3916 end = _getComputedProperty(target, prop) || end; 3917 target.style[prop] = start; 3918 } 3919 3920 a = [start, end]; 3921 3922 _colorStringFilter(a); 3923 3924 start = a[0]; 3925 end = a[1]; 3926 startValues = start.match(_numWithUnitExp) || []; 3927 endValues = end.match(_numWithUnitExp) || []; 3928 3929 if (endValues.length) { 3930 while (result = _numWithUnitExp.exec(end)) { 3931 endValue = result[0]; 3932 chunk = end.substring(index, result.index); 3933 3934 if (color) { 3935 color = (color + 1) % 5; 3936 } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") { 3937 color = 1; 3938 } 3939 3940 if (endValue !== (startValue = startValues[matchIndex++] || "")) { 3941 startNum = parseFloat(startValue) || 0; 3942 startUnit = startValue.substr((startNum + "").length); 3943 relative = endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0; 3944 3945 if (relative) { 3946 endValue = endValue.substr(2); 3947 } 3948 3949 endNum = parseFloat(endValue); 3950 endUnit = endValue.substr((endNum + "").length); 3951 index = _numWithUnitExp.lastIndex - endUnit.length; 3952 3953 if (!endUnit) { 3954 endUnit = endUnit || _config.units[prop] || startUnit; 3955 3956 if (index === end.length) { 3957 end += endUnit; 3958 pt.e += endUnit; 3959 } 3960 } 3961 3962 if (startUnit !== endUnit) { 3963 startNum = _convertToUnit(target, prop, startValue, endUnit) || 0; 3964 } 3965 3966 pt._pt = { 3967 _next: pt._pt, 3968 p: chunk || matchIndex === 1 ? chunk : ",", 3969 s: startNum, 3970 c: relative ? relative * endNum : endNum - startNum, 3971 m: color && color < 4 || prop === "zIndex" ? Math.round : 0 3972 }; 3973 } 3974 } 3975 3976 pt.c = index < end.length ? end.substring(index, end.length) : ""; 3977 } else { 3978 pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue; 3979 } 3980 3981 _relExp.test(end) && (pt.e = 0); 3982 this._pt = pt; 3983 return pt; 3984 }, 3985 _keywordToPercent = { 3986 top: "0%", 3987 bottom: "100%", 3988 left: "0%", 3989 right: "100%", 3990 center: "50%" 3991 }, 3992 _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) { 3993 var split = value.split(" "), 3994 x = split[0], 3995 y = split[1] || "50%"; 3996 3997 if (x === "top" || x === "bottom" || y === "left" || y === "right") { 3998 value = x; 3999 x = y; 4000 y = value; 4001 } 4002 4003 split[0] = _keywordToPercent[x] || x; 4004 split[1] = _keywordToPercent[y] || y; 4005 return split.join(" "); 4006 }, 4007 _renderClearProps = function _renderClearProps(ratio, data) { 4008 if (data.tween && data.tween._time === data.tween._dur) { 4009 var target = data.t, 4010 style = target.style, 4011 props = data.u, 4012 cache = target._gsap, 4013 prop, 4014 clearTransforms, 4015 i; 4016 4017 if (props === "all" || props === true) { 4018 style.cssText = ""; 4019 clearTransforms = 1; 4020 } else { 4021 props = props.split(","); 4022 i = props.length; 4023 4024 while (--i > -1) { 4025 prop = props[i]; 4026 4027 if (_transformProps[prop]) { 4028 clearTransforms = 1; 4029 prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp; 4030 } 4031 4032 _removeProperty(target, prop); 4033 } 4034 } 4035 4036 if (clearTransforms) { 4037 _removeProperty(target, _transformProp); 4038 4039 if (cache) { 4040 cache.svg && target.removeAttribute("transform"); 4041 4042 _parseTransform(target, 1); 4043 4044 cache.uncache = 1; 4045 } 4046 } 4047 } 4048 }, 4049 _specialProps = { 4050 clearProps: function clearProps(plugin, target, property, endValue, tween) {
vendor: 3,001 bytes, lines 4051-4131
4051 if (tween.data !== "isFromStart") { 4052 var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps); 4053 pt.u = endValue; 4054 pt.pr = -10; 4055 pt.tween = tween; 4056 4057 plugin._props.push(property); 4058 4059 return 1; 4060 } 4061 } 4062 }, 4063 _identity2DMatrix = [1, 0, 0, 1, 0, 0], 4064 _rotationalProperties = {}, 4065 _isNullTransform = function _isNullTransform(value) { 4066 return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value; 4067 }, 4068 _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) { 4069 var matrixString = _getComputedProperty(target, _transformProp); 4070 4071 return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round); 4072 }, 4073 _getMatrix = function _getMatrix(target, force2D) { 4074 var cache = target._gsap || _getCache(target), 4075 style = target.style, 4076 matrix = _getComputedTransformMatrixAsArray(target), 4077 parent, 4078 nextSibling, 4079 temp, 4080 addedToDOM; 4081 4082 if (cache.svg && target.getAttribute("transform")) { 4083 temp = target.transform.baseVal.consolidate().matrix; 4084 matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f]; 4085 return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix; 4086 } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) { 4087 temp = style.display; 4088 style.display = "block"; 4089 parent = target.parentNode; 4090 4091 if (!parent || !target.offsetParent) { 4092 addedToDOM = 1; 4093 nextSibling = target.nextSibling; 4094 4095 _docElement.appendChild(target); 4096 } 4097 4098 matrix = _getComputedTransformMatrixAsArray(target); 4099 temp ? style.display = temp : _removeProperty(target, "display"); 4100 4101 if (addedToDOM) { 4102 nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target); 4103 } 4104 } 4105 4106 return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix; 4107 }, 4108 _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) { 4109 var cache = target._gsap, 4110 matrix = matrixArray || _getMatrix(target, true), 4111 xOriginOld = cache.xOrigin || 0, 4112 yOriginOld = cache.yOrigin || 0, 4113 xOffsetOld = cache.xOffset || 0, 4114 yOffsetOld = cache.yOffset || 0, 4115 a = matrix[0], 4116 b = matrix[1], 4117 c = matrix[2], 4118 d = matrix[3], 4119 tx = matrix[4], 4120 ty = matrix[5], 4121 originSplit = origin.split(" "), 4122 xOrigin = parseFloat(originSplit[0]) || 0, 4123 yOrigin = parseFloat(originSplit[1]) || 0, 4124 bounds, 4125 determinant, 4126 x, 4127 y; 4128 4129 if (!originIsAbsolute) { 4130 bounds = _getBBox(target); 4131 xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * boun
vendor: 6,518 bytes, lines 4131-4339
4131ds.width : xOrigin); 4132 yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin); 4133 } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) { 4134 x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant; 4135 y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant; 4136 xOrigin = x; 4137 yOrigin = y; 4138 } 4139 4140 if (smooth || smooth !== false && cache.smooth) { 4141 tx = xOrigin - xOriginOld; 4142 ty = yOrigin - yOriginOld; 4143 cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx; 4144 cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty; 4145 } else { 4146 cache.xOffset = cache.yOffset = 0; 4147 } 4148 4149 cache.xOrigin = xOrigin; 4150 cache.yOrigin = yOrigin; 4151 cache.smooth = !!smooth; 4152 cache.origin = origin; 4153 cache.originIsAbsolute = !!originIsAbsolute; 4154 target.style[_transformOriginProp] = "0px 0px"; 4155 4156 if (pluginToAddPropTweensTo) { 4157 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin); 4158 4159 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin); 4160 4161 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset); 4162 4163 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset); 4164 } 4165 4166 target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin); 4167 }, 4168 _parseTransform = function _parseTransform(target, uncache) { 4169 var cache = target._gsap || new GSCache(target); 4170 4171 if ("x" in cache && !uncache && !cache.uncache) { 4172 return cache; 4173 } 4174 4175 var style = target.style, 4176 invertedScaleX = cache.scaleX < 0, 4177 px = "px", 4178 deg = "deg", 4179 origin = _getComputedProperty(target, _transformOriginProp) || "0", 4180 x, 4181 y, 4182 z, 4183 scaleX, 4184 scaleY, 4185 rotation, 4186 rotationX, 4187 rotationY, 4188 skewX, 4189 skewY, 4190 perspective, 4191 xOrigin, 4192 yOrigin, 4193 matrix, 4194 angle, 4195 cos, 4196 sin, 4197 a, 4198 b, 4199 c, 4200 d, 4201 a12, 4202 a22, 4203 t1, 4204 t2, 4205 t3, 4206 a13, 4207 a23, 4208 a33, 4209 a42, 4210 a43, 4211 a32; 4212 x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0; 4213 scaleX = scaleY = 1; 4214 cache.svg = !!(target.getCTM && _isSVG(target)); 4215 matrix = _getMatrix(target, cache.svg); 4216 4217 if (cache.svg) { 4218 t1 = !cache.uncache && !uncache && target.getAttribute("data-svg-origin"); 4219 4220 _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix); 4221 } 4222 4223 xOrigin = cache.xOrigin || 0; 4224 yOrigin = cache.yOrigin || 0; 4225 4226 if (matrix !== _identity2DMatrix) { 4227 a = matrix[0]; 4228 b = matrix[1]; 4229 c = matrix[2]; 4230 d = matrix[3]; 4231 x = a12 = matrix[4]; 4232 y = a22 = matrix[5]; 4233 4234 if (matrix.length === 6) { 4235 scaleX = Math.sqrt(a * a + b * b); 4236 scaleY = Math.sqrt(d * d + c * c); 4237 rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0; 4238 skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0; 4239 skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD))); 4240 4241 if (cache.svg) { 4242 x -= xOrigin - (xOrigin * a + yOrigin * c); 4243 y -= yOrigin - (xOrigin * b + yOrigin * d); 4244 } 4245 } else { 4246 a32 = matrix[6]; 4247 a42 = matrix[7]; 4248 a13 = matrix[8]; 4249 a23 = matrix[9]; 4250 a33 = matrix[10]; 4251 a43 = matrix[11]; 4252 x = matrix[12]; 4253 y = matrix[13]; 4254 z = matrix[14]; 4255 angle = _atan2(a32, a33); 4256 rotationX = angle * _RAD2DEG; 4257 4258 if (angle) { 4259 cos = Math.cos(-angle); 4260 sin = Math.sin(-angle); 4261 t1 = a12 * cos + a13 * sin; 4262 t2 = a22 * cos + a23 * sin; 4263 t3 = a32 * cos + a33 * sin; 4264 a13 = a12 * -sin + a13 * cos; 4265 a23 = a22 * -sin + a23 * cos; 4266 a33 = a32 * -sin + a33 * cos; 4267 a43 = a42 * -sin + a43 * cos; 4268 a12 = t1; 4269 a22 = t2; 4270 a32 = t3; 4271 } 4272 4273 angle = _atan2(-c, a33); 4274 rotationY = angle * _RAD2DEG; 4275 4276 if (angle) { 4277 cos = Math.cos(-angle); 4278 sin = Math.sin(-angle); 4279 t1 = a * cos - a13 * sin; 4280 t2 = b * cos - a23 * sin; 4281 t3 = c * cos - a33 * sin; 4282 a43 = d * sin + a43 * cos; 4283 a = t1; 4284 b = t2; 4285 c = t3; 4286 } 4287 4288 angle = _atan2(b, a); 4289 rotation = angle * _RAD2DEG; 4290 4291 if (angle) { 4292 cos = Math.cos(angle); 4293 sin = Math.sin(angle); 4294 t1 = a * cos + b * sin; 4295 t2 = a12 * cos + a22 * sin; 4296 b = b * cos - a * sin; 4297 a22 = a22 * cos - a12 * sin; 4298 a = t1; 4299 a12 = t2; 4300 } 4301 4302 if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) { 4303 rotationX = rotation = 0; 4304 rotationY = 180 - rotationY; 4305 } 4306 4307 scaleX = _round(Math.sqrt(a * a + b * b + c * c)); 4308 scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32)); 4309 angle = _atan2(a12, a22); 4310 skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0; 4311 perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0; 4312 } 4313 4314 if (cache.svg) { 4315 t1 = target.getAttribute("transform"); 4316 cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp)); 4317 t1 && target.setAttribute("transform", t1); 4318 } 4319 } 4320 4321 if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) { 4322 if (invertedScaleX) { 4323 scaleX *= -1; 4324 skewX += rotation <= 0 ? 180 : -180; 4325 rotation += rotation <= 0 ? 180 : -180; 4326 } else { 4327 scaleY *= -1; 4328 skewX += skewX <= 0 ? 180 : -180; 4329 } 4330 } 4331 4332 cache.x = x - ((cache.xPercent = x && (cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px; 4333 cache.y = y - ((cache.yPercent = y && (cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px; 4334 cache.z = z + px; 4335 cache.scaleX = _round(scaleX); 4336 cache.scaleY = _round(scaleY); 4337 cache.rotation = _round(rotation) + deg; 4338 cache.rotationX = _round(rotationX) + deg; 4339 cache.rotationY = _round(rotationY) + deg;
vendor: 4,199 bytes, lines 4340-4467
4340 cache.skewX = skewX + deg; 4341 cache.skewY = skewY + deg; 4342 cache.transformPerspective = perspective + px; 4343 4344 if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || 0) { 4345 style[_transformOriginProp] = _firstTwoOnly(origin); 4346 } 4347 4348 cache.xOffset = cache.yOffset = 0; 4349 cache.force3D = _config.force3D; 4350 cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms; 4351 cache.uncache = 0; 4352 return cache; 4353 }, 4354 _firstTwoOnly = function _firstTwoOnly(value) { 4355 return (value = value.split(" "))[0] + " " + value[1]; 4356 }, 4357 _addPxTranslate = function _addPxTranslate(target, start, value) { 4358 var unit = getUnit(start); 4359 return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit; 4360 }, 4361 _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) { 4362 cache.z = "0px"; 4363 cache.rotationY = cache.rotationX = "0deg"; 4364 cache.force3D = 0; 4365 4366 _renderCSSTransforms(ratio, cache); 4367 }, 4368 _zeroDeg = "0deg", 4369 _zeroPx = "0px", 4370 _endParenthesis = ") ", 4371 _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) { 4372 var _ref = cache || this, 4373 xPercent = _ref.xPercent, 4374 yPercent = _ref.yPercent, 4375 x = _ref.x, 4376 y = _ref.y, 4377 z = _ref.z, 4378 rotation = _ref.rotation, 4379 rotationY = _ref.rotationY, 4380 rotationX = _ref.rotationX, 4381 skewX = _ref.skewX, 4382 skewY = _ref.skewY, 4383 scaleX = _ref.scaleX, 4384 scaleY = _ref.scaleY, 4385 transformPerspective = _ref.transformPerspective, 4386 force3D = _ref.force3D, 4387 target = _ref.target, 4388 zOrigin = _ref.zOrigin, 4389 transforms = "", 4390 use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true; 4391 4392 if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) { 4393 var angle = parseFloat(rotationY) * _DEG2RAD, 4394 a13 = Math.sin(angle), 4395 a33 = Math.cos(angle), 4396 cos; 4397 4398 angle = parseFloat(rotationX) * _DEG2RAD; 4399 cos = Math.cos(angle); 4400 x = _addPxTranslate(target, x, a13 * cos * -zOrigin); 4401 y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin); 4402 z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin); 4403 } 4404 4405 if (transformPerspective !== _zeroPx) { 4406 transforms += "perspective(" + transformPerspective + _endParenthesis; 4407 } 4408 4409 if (xPercent || yPercent) { 4410 transforms += "translate(" + xPercent + "%, " + yPercent + "%) "; 4411 } 4412 4413 if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) { 4414 transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis; 4415 } 4416 4417 if (rotation !== _zeroDeg) { 4418 transforms += "rotate(" + rotation + _endParenthesis; 4419 } 4420 4421 if (rotationY !== _zeroDeg) { 4422 transforms += "rotateY(" + rotationY + _endParenthesis; 4423 } 4424 4425 if (rotationX !== _zeroDeg) { 4426 transforms += "rotateX(" + rotationX + _endParenthesis; 4427 } 4428 4429 if (skewX !== _zeroDeg || skewY !== _zeroDeg) { 4430 transforms += "skew(" + skewX + ", " + skewY + _endParenthesis; 4431 } 4432 4433 if (scaleX !== 1 || scaleY !== 1) { 4434 transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis; 4435 } 4436 4437 target.style[_transformProp] = transforms || "translate(0, 0)"; 4438 }, 4439 _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) { 4440 var _ref2 = cache || this, 4441 xPercent = _ref2.xPercent, 4442 yPercent = _ref2.yPercent, 4443 x = _ref2.x, 4444 y = _ref2.y, 4445 rotation = _ref2.rotation, 4446 skewX = _ref2.skewX, 4447 skewY = _ref2.skewY, 4448 scaleX = _ref2.scaleX, 4449 scaleY = _ref2.scaleY, 4450 target = _ref2.target, 4451 xOrigin = _ref2.xOrigin, 4452 yOrigin = _ref2.yOrigin, 4453 xOffset = _ref2.xOffset, 4454 yOffset = _ref2.yOffset, 4455 forceCSS = _ref2.forceCSS, 4456 tx = parseFloat(x), 4457 ty = parseFloat(y), 4458 a11, 4459 a21, 4460 a12, 4461 a22, 4462 temp; 4463 4464 rotation = parseFloat(rotation); 4465 skewX = parseFloat(skewX); 4466 skewY = parseFloat(skewY); 4467
vendor: 4,432 bytes, lines 4468-4616
4468 if (skewY) { 4469 skewY = parseFloat(skewY); 4470 skewX += skewY; 4471 rotation += skewY; 4472 } 4473 4474 if (rotation || skewX) { 4475 rotation *= _DEG2RAD; 4476 skewX *= _DEG2RAD; 4477 a11 = Math.cos(rotation) * scaleX; 4478 a21 = Math.sin(rotation) * scaleX; 4479 a12 = Math.sin(rotation - skewX) * -scaleY; 4480 a22 = Math.cos(rotation - skewX) * scaleY; 4481 4482 if (skewX) { 4483 skewY *= _DEG2RAD; 4484 temp = Math.tan(skewX - skewY); 4485 temp = Math.sqrt(1 + temp * temp); 4486 a12 *= temp; 4487 a22 *= temp; 4488 4489 if (skewY) { 4490 temp = Math.tan(skewY); 4491 temp = Math.sqrt(1 + temp * temp); 4492 a11 *= temp; 4493 a21 *= temp; 4494 } 4495 } 4496 4497 a11 = _round(a11); 4498 a21 = _round(a21); 4499 a12 = _round(a12); 4500 a22 = _round(a22); 4501 } else { 4502 a11 = scaleX; 4503 a22 = scaleY; 4504 a21 = a12 = 0; 4505 } 4506 4507 if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) { 4508 tx = _convertToUnit(target, "x", x, "px"); 4509 ty = _convertToUnit(target, "y", y, "px"); 4510 } 4511 4512 if (xOrigin || yOrigin || xOffset || yOffset) { 4513 tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset); 4514 ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset); 4515 } 4516 4517 if (xPercent || yPercent) { 4518 temp = target.getBBox(); 4519 tx = _round(tx + xPercent / 100 * temp.width); 4520 ty = _round(ty + yPercent / 100 * temp.height); 4521 } 4522 4523 temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")"; 4524 target.setAttribute("transform", temp); 4525 forceCSS && (target.style[_transformProp] = temp); 4526 }, 4527 _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue, relative) { 4528 var cap = 360, 4529 isString = _isString(endValue), 4530 endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1), 4531 change = relative ? endNum * relative : endNum - startNum, 4532 finalValue = startNum + change + "deg", 4533 direction, 4534 pt; 4535 4536 if (isString) { 4537 direction = endValue.split("_")[1]; 4538 4539 if (direction === "short") { 4540 change %= cap; 4541 4542 if (change !== change % (cap / 2)) { 4543 change += change < 0 ? cap : -cap; 4544 } 4545 } 4546 4547 if (direction === "cw" && change < 0) { 4548 change = (change + cap * _bigNum$1) % cap - ~~(change / cap) * cap; 4549 } else if (direction === "ccw" && change > 0) { 4550 change = (change - cap * _bigNum$1) % cap - ~~(change / cap) * cap; 4551 } 4552 } 4553 4554 plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd); 4555 pt.e = finalValue; 4556 pt.u = "deg"; 4557 4558 plugin._props.push(property); 4559 4560 return pt; 4561 }, 4562 _assign = function _assign(target, source) { 4563 for (var p in source) { 4564 target[p] = source[p]; 4565 } 4566 4567 return target; 4568 }, 4569 _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) { 4570 var startCache = _assign({}, target._gsap), 4571 exclude = "perspective,force3D,transformOrigin,svgOrigin", 4572 style = target.style, 4573 endCache, 4574 p, 4575 startValue, 4576 endValue, 4577 startNum, 4578 endNum, 4579 startUnit, 4580 endUnit; 4581 4582 if (startCache.svg) { 4583 startValue = target.getAttribute("transform"); 4584 target.setAttribute("transform", ""); 4585 style[_transformProp] = transforms; 4586 endCache = _parseTransform(target, 1); 4587 4588 _removeProperty(target, _transformProp); 4589 4590 target.setAttribute("transform", startValue); 4591 } else { 4592 startValue = getComputedStyle(target)[_transformProp]; 4593 style[_transformProp] = transforms; 4594 endCache = _parseTransform(target, 1); 4595 style[_transformProp] = startValue; 4596 } 4597 4598 for (p in _transformProps) { 4599 startValue = startCache[p]; 4600 endValue = endCache[p]; 4601 4602 if (startValue !== endValue && exclude.indexOf(p) < 0) { 4603 startUnit = getUnit(startValue); 4604 endUnit = getUnit(endValue); 4605 startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue); 4606 endNum = parseFloat(endValue); 4607 plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp); 4608 plugin._pt.u = endUnit || 0; 4609 4610 plugin._props.push(p); 4611 } 4612 } 4613 4614 _assign(endCache, startCache); 4615 }; 4616
vendor: 4,076 bytes, lines 4617-4738
4617 _forEachName("padding,margin,Width,Radius", function (name, index) { 4618 var t = "Top", 4619 r = "Right", 4620 b = "Bottom", 4621 l = "Left", 4622 props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) { 4623 return index < 2 ? name + side : "border" + side + name; 4624 }); 4625 4626 _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) { 4627 var a, vars; 4628 4629 if (arguments.length < 4) { 4630 a = props.map(function (prop) { 4631 return _get(plugin, prop, property); 4632 }); 4633 vars = a.join(" "); 4634 return vars.split(a[0]).length === 5 ? a[0] : vars; 4635 } 4636 4637 a = (endValue + "").split(" "); 4638 vars = {}; 4639 props.forEach(function (prop, i) { 4640 return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0]; 4641 }); 4642 plugin.init(target, vars, tween); 4643 }; 4644 }); 4645 4646 var CSSPlugin = { 4647 name: "css", 4648 register: _initCore, 4649 targetTest: function targetTest(target) { 4650 return target.style && target.nodeType; 4651 }, 4652 init: function init(target, vars, tween, index, targets) { 4653 var props = this._props, 4654 style = target.style, 4655 startAt = tween.vars.startAt, 4656 startValue, 4657 endValue, 4658 endNum, 4659 startNum, 4660 type, 4661 specialProp, 4662 p, 4663 startUnit, 4664 endUnit, 4665 relative, 4666 isTransformRelated, 4667 transformPropTween, 4668 cache, 4669 smooth, 4670 hasPriority; 4671 _pluginInitted || _initCore(); 4672 4673 for (p in vars) { 4674 if (p === "autoRound") { 4675 continue; 4676 } 4677 4678 endValue = vars[p]; 4679 4680 if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) { 4681 continue; 4682 } 4683 4684 type = typeof endValue; 4685 specialProp = _specialProps[p]; 4686 4687 if (type === "function") { 4688 endValue = endValue.call(tween, index, target, targets); 4689 type = typeof endValue; 4690 } 4691 4692 if (type === "string" && ~endValue.indexOf("random(")) { 4693 endValue = _replaceRandom(endValue); 4694 } 4695 4696 if (specialProp) { 4697 specialProp(this, target, p, endValue, tween) && (hasPriority = 1); 4698 } else if (p.substr(0, 2) === "--") { 4699 startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim(); 4700 endValue += ""; 4701 _colorExp.lastIndex = 0; 4702 4703 if (!_colorExp.test(startValue)) { 4704 startUnit = getUnit(startValue); 4705 endUnit = getUnit(endValue); 4706 } 4707 4708 endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit); 4709 this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p); 4710 } else if (type !== "undefined") { 4711 if (startAt && p in startAt) { 4712 startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p]; 4713 p in _config.units && !getUnit(startValue) && (startValue += _config.units[p]); 4714 (startValue + "").charAt(1) === "=" && (startValue = _get(target, p)); 4715 } else { 4716 startValue = _get(target, p); 4717 } 4718 4719 startNum = parseFloat(startValue); 4720 relative = type === "string" && endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0; 4721 relative && (endValue = endValue.substr(2)); 4722 endNum = parseFloat(endValue); 4723 4724 if (p in _propertyAliases) { 4725 if (p === "autoAlpha") { 4726 if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) { 4727 startNum = 0; 4728 } 4729 4730 _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum); 4731 } 4732 4733 if (p !== "scale" && p !== "transform") { 4734 p = _propertyAliases[p]; 4735 ~p.indexOf(",") && (p = p.split(",")[0]); 4736 } 4737 } 4738
vendor: 4,279 bytes, lines 4739-4832
4739 isTransformRelated = p in _transformProps; 4740 4741 if (isTransformRelated) { 4742 if (!transformPropTween) { 4743 cache = target._gsap; 4744 cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform); 4745 smooth = vars.smoothOrigin !== false && cache.smooth; 4746 transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1); 4747 transformPropTween.dep = 1; 4748 } 4749 4750 if (p === "scale") { 4751 this._pt = new PropTween(this._pt, cache, "scaleY", cache.scaleY, relative ? relative * endNum : endNum - cache.scaleY); 4752 props.push("scaleY", p); 4753 p += "X"; 4754 } else if (p === "transformOrigin") { 4755 endValue = _convertKeywordsToPercentages(endValue); 4756 4757 if (cache.svg) { 4758 _applySVGOrigin(target, endValue, 0, smooth, 0, this); 4759 } else { 4760 endUnit = parseFloat(endValue.split(" ")[2]) || 0; 4761 endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit); 4762 4763 _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue)); 4764 } 4765 4766 continue; 4767 } else if (p === "svgOrigin") { 4768 _applySVGOrigin(target, endValue, 1, smooth, 0, this); 4769 4770 continue; 4771 } else if (p in _rotationalProperties) { 4772 _addRotationalPropTween(this, cache, p, startNum, endValue, relative); 4773 4774 continue; 4775 } else if (p === "smoothOrigin") { 4776 _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue); 4777 4778 continue; 4779 } else if (p === "force3D") { 4780 cache[p] = endValue; 4781 continue; 4782 } else if (p === "transform") { 4783 _addRawTransformPTs(this, endValue, target); 4784 4785 continue; 4786 } 4787 } else if (!(p in style)) { 4788 p = _checkPropPrefix(p) || p; 4789 } 4790 4791 if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) { 4792 startUnit = (startValue + "").substr((startNum + "").length); 4793 endNum || (endNum = 0); 4794 endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit); 4795 startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit)); 4796 this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, relative ? relative * endNum : endNum - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp); 4797 this._pt.u = endUnit || 0; 4798 4799 if (startUnit !== endUnit) { 4800 this._pt.b = startValue; 4801 this._pt.r = _renderCSSPropWithBeginning; 4802 } 4803 } else if (!(p in style)) { 4804 if (p in target) { 4805 this.add(target, p, target[p], endValue, index, targets); 4806 } else { 4807 _missingPlugin(p, endValue); 4808 4809 continue; 4810 } 4811 } else { 4812 _tweenComplexCSSString.call(this, target, p, startValue, endValue); 4813 } 4814 4815 props.push(p); 4816 } 4817 } 4818 4819 hasPriority && _sortPropTweensByPriority(this); 4820 }, 4821 get: _get, 4822 aliases: _propertyAliases, 4823 getSetter: function getSetter(target, property, plugin) { 4824 var p = _propertyAliases[property]; 4825 p && p.indexOf(",") < 0 && (property = p); 4826 return property in _transformProps && property !== _transformOriginProp && (target._gsap.x || _get(target, "x")) ? plugin && _recentSetterPlugin === plugin ? property === "scale" ? _setterScale : _setterTransform : (_recentSetterPlugin = plugin || {}) && (property === "scale" ? _setterScaleWithRender : _setterTransformWithRender) : target.style && !_isUndefined(target.style[property]) ? _setterCSSStyle : ~property.indexOf("-") ? _setterCSSProp : _getSetter(target, property); 4827 }, 4828 core: { 4829 _removeProperty: _removeProperty, 4830 _getMatrix: _getMatrix 4831 } 4832 };
4833 gsap.utils.checkPrefix = _checkPropPrefix; 4834 4835 (function (positionAndScale, rotation, others, aliases) { 4836 var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) { 4837 _transformProps[name] = 1; 4838 }); 4839 4840 _forEachName(rotation, function (name) { 4841 _config.units[name] = "deg"; 4842 _rotationalProperties[name] = 1; 4843 }); 4844 4845 _propertyAliases[all[13]] = positionAndScale + "," + rotation; 4846 4847 _forEachName(aliases, function (name) { 4848 var split = name.split(":"); 4849 _propertyAliases[split[1]] = all[split[0]]; 4850 }); 4851 })("x,y,z,scale,scaleX,scaleY,xPercent,yPercent", "rotation,rotationX,rotationY,skewX,skewY", "transform,transformOrigin,svgOrigin,force3D,smoothOrigin,transformPerspective", "0:translateX,1:translateY,2:translateZ,8:rotate,8:rotationZ,8:rotateZ,9:rotateX,10:rotateY"); 4852 4853 _forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) { 4854 _config.units[name] = "px"; 4855 }); 4856 4857 gsap.registerPlugin(CSSPlugin); 4858 4859 var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap, 4860 TweenMaxWithCSS = gsapWithCSS.core.Tween; 4861 4862 exports.Back = Back; 4863 exports.Bounce = Bounce; 4864 exports.CSSPlugin = CSSPlugin; 4865 exports.Circ = Circ; 4866 exports.Cubic = Cubic; 4867 exports.Elastic = Elastic; 4868 exports.Expo = Expo; 4869 exports.Linear = Linear; 4870 exports.Power0 = Power0; 4871 exports.Power1 = Power1; 4872 exports.Power2 = Power2; 4873 exports.Power3 = Power3; 4874 exports.Power4 = Power4; 4875 exports.Quad = Quad; 4876 exports.Quart = Quart; 4877 exports.Quint = Quint; 4878 exports.Sine = Sine; 4879 exports.SteppedEase = SteppedEase; 4880 exports.Strong = Strong; 4881 exports.TimelineLite = Timeline; 4882 exports.TimelineMax = Timeline; 4883 exports.TweenLite = Tween; 4884 exports.TweenMax = TweenMaxWithCSS; 4885 exports.default = gsapWithCSS; 4886 exports.gsap = gsapWithCSS; 4887 4888 if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;} 4889 4890}))); 4891 4892(function(window, $) { 4893 'use strict'; 4894 var counter = 0, 4895 $headCache = $('head'), 4896 oldBigText = window.BigText, 4897 oldjQueryMethod = $.fn.bigtext, 4898 BigText = { 4899 DEBUG_MODE: false, 4900 DEFAULT_MIN_FONT_SIZE_PX: null, 4901 DEFAULT_MAX_FONT_SIZE_PX: 528, 4902 GLOBAL_STYLE_ID: 'bigtext-style', 4903 STYLE_ID: 'bigtext-id', 4904 LINE_CLASS_PREFIX: 'bigtext-line', 4905 EXEMPT_CLASS: 'bigtext-exempt', 4906 noConflict: function(restore) 4907 { 4908 if(restore) { 4909 $.fn.bigtext = oldjQueryMethod; 4910 window.BigText = oldBigText; 4911 } 4912 return BigText; 4913 }, 4914 supports: { 4915 wholeNumberFontSizeOnly: (function() { 4916 if( !( 'getComputedStyle' in window ) ) { 4917 return true; 4918 } 4919 var test = $('<div/>').css({ 4920 position: 'absolute', 4921 'font-size': '14.1px' 4922 }).insertBefore( $('script').eq(0) ), 4923 computedStyle = window.getComputedStyle( test[0], null ); 4924 4925 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 4926 test.remove(); 4927 return ret; 4928 })() 4929 }, 4930 init: function() { 4931 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 4932 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 4933 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 4934 } 4935 }, 4936 bindResize: function(eventName, resizeFunction) { 4937 var timeoutId; 4938 $(window).unbind(eventName).bind(eventName, function() { 4939 if( timeoutId ) { 4940 clearTimeout( timeoutId ); 4941 } 4942 timeoutId = setTimeout( resizeFunction, 300 ); 4943 }); 4944 }, 4945 getStyleId: function(id) 4946 { 4947 return BigText.STYLE_ID + '-' + id; 4948 }, 4949 generateStyleTag: function(id, css) 4950 { 4951 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 4952 }, 4953 clearCss: function(id) 4954 { 4955 var styleId = BigText.getStyleId(id); 4956 $('#' + styleId).remove(); 4957 }, 4958 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 4959 { 4960 var css = []; 4961 4962 BigText.clearCss(id); 4963 4964 for(var j=0, k=linesFontSizes.length; j<k; j++) { 4965 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 4966 (minFontSizes[j] ? ' white-space: normal;' : '') + 4967 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 4968 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 4969 '}'); 4970 } 4971 4972 return BigText.generateStyleTag(BigText.getStyleId(id), css); 4973 }, 4974 jQueryMethod: function(options) 4975 {
4976 BigText.init(); 4977 4978 options = $.extend({ 4979 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 4980 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 4981 childSelector: '', 4982 resize: true 4983 }, options || {}); 4984 4985 this.each(function() 4986 { 4987 var $t = $(this).addClass('bigtext'), 4988 maxWidth = $t.width(), 4989 id = $t.attr('id'), 4990 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 4991 4992 if(!id) { 4993 id = 'bigtext-id' + (counter++); 4994 $t.attr('id', id); 4995 } 4996 4997 if(options.resize) { 4998 BigText.bindResize('resize.bigtext-event-' + id, function() 4999 { 5000 // TODO only call this if the width has changed. 5001 BigText.jQueryMethod.call($('#' + id), options); 5002 }); 5003 } 5004 5005 BigText.clearCss(id); 5006 5007 $children.addClass(function(lineNumber, className) 5008 { 5009 // remove existing line classes. 5010 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 5011 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 5012 }); 5013 5014 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 5015 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 5016 }); 5017 5018 return this.trigger('bigtext:complete'); 5019 } 5020 }; 5021 5022 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 5023 { 5024 var width; 5025 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 5026 $line.css(property, size + units); 5027 5028 width = $line.width(); 5029 5030 if(width >= maxWidth) { 5031 5032 $line.css(property, ''); 5033 5034 if(width === maxWidth) { 5035 return { 5036 match: 'exact', 5037 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 5038 }; 5039 } 5040 5041 // Since this is an estimate, we calculate how far over the width we went with the new value. 5042 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 5043 // Otherwise, we revert to the underestimate. 5044 var under = maxWidth - previousWidth, 5045 over = width - maxWidth; 5046 5047 return { 5048 match: 'estimate', 5049 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 5050 }; 5051 } 5052 5053 return width; 5054 } 5055 5056 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 5057 { 5058 var $c = $t.clone(true) 5059 .addClass('bigtext-cloned') 5060 .css({ 5061 fontFamily: $t.css('font-family'), 5062 textTransform: $t.css('text-transform'), 5063 wordSpacing: $t.css('word-spacing'), 5064 letterSpacing: $t.css('letter-spacing'), 5065 position: 'absolute', 5066 left: BigText.DEBUG_MODE ? 0 : -9999, 5067 top: BigText.DEBUG_MODE ? 0 : -9999 5068 }) 5069 .appendTo(document.body); 5070 5071 // font-size isn't the only thing we can modify, we can also mess with: 5072 // word-spacing and letter-spacing. WebKit does not respect subpixel 5073 // letter-spacing, word-spacing, or font-size. 5074 // TODO try -webkit-transform: scale() as a workaround. 5075 var fontSizes = [], 5076 wordSpacings = [], 5077 minFontSizes = [], 5078 ratios = []; 5079 5080 $children.css('float', 'left').each(function() { 5081 var $line = $(this), 5082 // TODO replace 8, 4 with a proportional size to the calculated font-size. 5083 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 5084 lineMax, 5085 newFontSize; 5086 5087 if($line.hasClass(BigText.EXEMPT_CLASS)) { 5088 fontSizes.push(null); 5089 ratios.push(null); 5090 minFontSizes.push(false); 5091 return; 5092 } 5093 5094 // TODO we can cache this ratio? 5095 var autoGuessSubtraction = 32, // font size in px 5096 currentFontSize = parseFloat($line.css('font-size')), 5097 ratio = ( $line.width() / currentFontSize ).toFixed(6); 5098 5099 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 5100 5101 outer: for(var m=0, n=intervals.length; m<n; m++) { 5102 inner: for(var j=1, k=10; j<=k; j++) { 5103 if(newFontSize + j*intervals[m] > maxFontSize) { 5104 newFontSize = maxFontSize; 5105 break outer; 5106 } 5107 5108 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 5109 if(typeof lineMax !== 'number') { 5110 newFontSize = lineMax.size; 5111 5112 if(lineMax.match === 'exact') { 5113 break outer; 5114 } 5115 break inner; 5116 } 5117 } 5118 } 5119 5120 ratios.push(maxWidth / newFontSize); 5121 5122 if(newFontSize > maxFontSize) { 5123 fontSizes.push(maxFontSize); 5124 minFontSizes.push(false); 5125 } else if(!!minFontSize && newFontSize < minFontSize) { 5126 fontSizes.push(minFontSize); 5127 minFontSizes.push(true); 5128 } else { 5129 fontSizes.push(newFontSize); 5130 minFontSizes.push(false); 5131 } 5132 }).each(function(lineNumber) { 5133 var $line = $(this), 5134 wordSpacing = 0, 5135 interval = 1, 5136 maxWordSpacing; 5137 5138 if($line.hasClass(BigText.EXEMPT_CLASS)) { 5139 wordSpacings.push(null); 5140 return; 5141 } 5142 5143 // must re-use font-size, even though it was removed above. 5144 $line.css('font-size', fontSizes[lineNumber] + 'px'); 5145 5146 for(var m=1, n=3; m<n; m+=interval) { 5147 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 5148 if(typeof maxWordSpacing !== 'number') { 5149 wordSpacing = maxWordSpacing.size; 5150 break; 5151 } 5152 } 5153 5154 $line.css('font-size', ''); 5155 wordSpacings.push(wordSpacing); 5156 }).removeAttr('style'); 5157 5158 if( !BigText.DEBUG_MODE ) { 5159 $c.remove(); 5160 } else { 5161 $c.css({ 5162 'background-color': 'rgba(255,255,255,.4)' 5163 }); 5164 } 5165 5166 return { 5167 fontSizes: fontSizes, 5168 wordSpacings: wordSpacings, 5169 ratios: ratios, 5170 minFontSizes: minFontSizes 5171 }; 5172 } 5173 5174 $.fn.bigtext = BigText.jQueryMethod; 5175 window.BigText = BigText; 5176 5177})(this, jQuery);
vendor: 16,093 bytes, lines 5178-5835
5178/*! 5179 * Isotope PACKAGED v3.0.6 5180 * 5181 * Licensed GPLv3 for open source use 5182 * or Isotope Commercial License for commercial use 5183 * 5184 * https://isotope.metafizzy.co 5185 * Copyright 2010-2018 Metafizzy 5186 */ 5187 5188/** 5189 * Bridget makes jQuery widgets 5190 * v2.0.1 5191 * MIT license 5192 */ 5193 5194/* jshint browser: true, strict: true, undef: true, unused: true */ 5195 5196( function( window, factory ) { 5197 // universal module definition 5198 /*jshint strict: false */ /* globals define, module, require */ 5199 if ( typeof define == 'function' && define.amd ) { 5200 // AMD 5201 define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) { 5202 return factory( window, jQuery ); 5203 }); 5204 } else if ( typeof module == 'object' && module.exports ) { 5205 // CommonJS 5206 module.exports = factory( 5207 window, 5208 require('jquery') 5209 ); 5210 } else { 5211 // browser global 5212 window.jQueryBridget = factory( 5213 window, 5214 window.jQuery 5215 ); 5216 } 5217 5218}( window, function factory( window, jQuery ) { 5219'use strict'; 5220 5221// ----- utils ----- // 5222 5223var arraySlice = Array.prototype.slice; 5224 5225// helper function for logging errors 5226// $.error breaks jQuery chaining 5227var console = window.console; 5228var logError = typeof console == 'undefined' ? function() {} : 5229 function( message ) { 5230 console.error( message ); 5231 }; 5232 5233// ----- jQueryBridget ----- // 5234 5235function jQueryBridget( namespace, PluginClass, $ ) { 5236 $ = $ || jQuery || window.jQuery; 5237 if ( !$ ) { 5238 return; 5239 } 5240 5241 // add option method -> $().plugin('option', {...}) 5242 if ( !PluginClass.prototype.option ) { 5243 // option setter 5244 PluginClass.prototype.option = function( opts ) { 5245 // bail out if not an object 5246 if ( !$.isPlainObject( opts ) ){ 5247 return; 5248 } 5249 this.options = $.extend( true, this.options, opts ); 5250 }; 5251 } 5252 5253 // make jQuery plugin 5254 $.fn[ namespace ] = function( arg0 /*, arg1 */ ) { 5255 if ( typeof arg0 == 'string' ) { 5256 // method call $().plugin( 'methodName', { options } ) 5257 // shift arguments by 1 5258 var args = arraySlice.call( arguments, 1 ); 5259 return methodCall( this, arg0, args ); 5260 } 5261 // just $().plugin({ options }) 5262 plainCall( this, arg0 ); 5263 return this; 5264 }; 5265 5266 // $().plugin('methodName') 5267 function methodCall( $elems, methodName, args ) { 5268 var returnValue; 5269 var pluginMethodStr = '$().' + namespace + '("' + methodName + '")'; 5270 5271 $elems.each( function( i, elem ) { 5272 // get instance 5273 var instance = $.data( elem, namespace ); 5274 if ( !instance ) { 5275 logError( namespace + ' not initialized. Cannot call methods, i.e. ' + 5276 pluginMethodStr ); 5277 return; 5278 } 5279 5280 var method = instance[ methodName ]; 5281 if ( !method || methodName.charAt(0) == '_' ) { 5282 logError( pluginMethodStr + ' is not a valid method' ); 5283 return; 5284 } 5285 5286 // apply method, get return value 5287 var value = method.apply( instance, args ); 5288 // set return value if value is returned, use only first value 5289 returnValue = returnValue === undefined ? value : returnValue; 5290 }); 5291 5292 return returnValue !== undefined ? returnValue : $elems; 5293 } 5294 5295 function plainCall( $elems, options ) { 5296 $elems.each( function( i, elem ) { 5297 var instance = $.data( elem, namespace ); 5298 if ( instance ) { 5299 // set options & init 5300 instance.option( options ); 5301 instance._init(); 5302 } else { 5303 // initialize new instance 5304 instance = new PluginClass( elem, options ); 5305 $.data( elem, namespace, instance ); 5306 } 5307 }); 5308 } 5309 5310 updateJQuery( $ ); 5311 5312} 5313 5314// ----- updateJQuery ----- // 5315 5316// set $.bridget for v1 backwards compatibility 5317function updateJQuery( $ ) { 5318 if ( !$ || ( $ && $.bridget ) ) { 5319 return; 5320 } 5321 $.bridget = jQueryBridget; 5322} 5323 5324updateJQuery( jQuery || window.jQuery ); 5325 5326// ----- ----- // 5327 5328return jQueryBridget; 5329 5330})); 5331 5332/** 5333 * EvEmitter v1.1.0 5334 * Lil' event emitter 5335 * MIT License 5336 */ 5337 5338/* jshint unused: true, undef: true, strict: true */ 5339 5340( function( global, factory ) { 5341 // universal module definition 5342 /* jshint strict: false */ /* globals define, module, window */ 5343 if ( typeof define == 'function' && define.amd ) { 5344 // AMD - RequireJS 5345 define( 'ev-emitter/ev-emitter',factory ); 5346 } else if ( typeof module == 'object' && module.exports ) { 5347 // CommonJS - Browserify, Webpack 5348 module.exports = factory(); 5349 } else { 5350 // Browser globals 5351 global.EvEmitter = factory(); 5352 } 5353 5354}( typeof window != 'undefined' ? window : this, function() { 5355 5356 5357 5358function EvEmitter() {} 5359 5360var proto = EvEmitter.prototype; 5361 5362proto.on = function( eventName, listener ) { 5363 if ( !eventName || !listener ) { 5364 return; 5365 } 5366 // set events hash 5367 var events = this._events = this._events || {}; 5368 // set listeners array 5369 var listeners = events[ eventName ] = events[ eventName ] || []; 5370 // only add once 5371 if ( listeners.indexOf( listener ) == -1 ) { 5372 listeners.push( listener ); 5373 } 5374 5375 return this; 5376}; 5377 5378proto.once = function( eventName, listener ) { 5379 if ( !eventName || !listener ) { 5380 return; 5381 } 5382 // add event 5383 this.on( eventName, listener ); 5384 // set once flag 5385 // set onceEvents hash 5386 var onceEvents = this._onceEvents = this._onceEvents || {}; 5387 // set onceListeners object 5388 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 5389 // set flag 5390 onceListeners[ listener ] = true; 5391 5392 return this; 5393}; 5394 5395proto.off = function( eventName, listener ) { 5396 var listeners = this._events && this._events[ eventName ]; 5397 if ( !listeners || !listeners.length ) { 5398 return; 5399 } 5400 var index = listeners.indexOf( listener ); 5401 if ( index != -1 ) { 5402 listeners.splice( index, 1 ); 5403 } 5404 5405 return this; 5406}; 5407 5408proto.emitEvent = function( eventName, args ) { 5409 var listeners = this._events && this._events[ eventName ]; 5410 if ( !listeners || !listeners.length ) { 5411 return; 5412 } 5413 // copy over to avoid interference if .off() in listener 5414 listeners = listeners.slice(0); 5415 args = args || []; 5416 // once stuff 5417 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 5418 5419 for ( var i=0; i < listeners.length; i++ ) { 5420 var listener = listeners[i] 5421 var isOnce = onceListeners && onceListeners[ listener ]; 5422 if ( isOnce ) { 5423 // remove listener 5424 // remove before trigger to prevent recursion 5425 this.off( eventName, listener ); 5426 // unset once flag 5427 delete onceListeners[ listener ]; 5428 } 5429 // trigger listener 5430 listener.apply( this, args ); 5431 } 5432 5433 return this; 5434}; 5435 5436proto.allOff = function() { 5437 delete this._events; 5438 delete this._onceEvents; 5439}; 5440 5441return EvEmitter; 5442 5443})); 5444 5445/*! 5446 * getSize v2.0.3 5447 * measure size of elements 5448 * MIT license 5449 */ 5450 5451/* jshint browser: true, strict: true, undef: true, unused: true */ 5452/* globals console: false */ 5453 5454( function( window, factory ) { 5455 /* jshint strict: false */ /* globals define, module */ 5456 if ( typeof define == 'function' && define.amd ) { 5457 // AMD 5458 define( 'get-size/get-size',factory ); 5459 } else if ( typeof module == 'object' && module.exports ) { 5460 // CommonJS 5461 module.exports = factory(); 5462 } else { 5463 // browser global 5464 window.getSize = factory(); 5465 } 5466 5467})( window, function factory() { 5468'use strict'; 5469 5470// -------------------------- helpers -------------------------- // 5471 5472// get a number from a string, not a percentage 5473function getStyleSize( value ) { 5474 var num = parseFloat( value ); 5475 // not a percent like '100%', and a number 5476 var isValid = value.indexOf('%') == -1 && !isNaN( num ); 5477 return isValid && num; 5478} 5479 5480function noop() {} 5481 5482var logError = typeof console == 'undefined' ? noop : 5483 function( message ) { 5484 console.error( message ); 5485 }; 5486 5487// -------------------------- measurements -------------------------- // 5488 5489var measurements = [ 5490 'paddingLeft', 5491 'paddingRight', 5492 'paddingTop', 5493 'paddingBottom', 5494 'marginLeft', 5495 'marginRight', 5496 'marginTop', 5497 'marginBottom', 5498 'borderLeftWidth', 5499 'borderRightWidth', 5500 'borderTopWidth', 5501 'borderBottomWidth' 5502]; 5503 5504var measurementsLength = measurements.length; 5505 5506function getZeroSize() { 5507 var size = { 5508 width: 0, 5509 height: 0, 5510 innerWidth: 0, 5511 innerHeight: 0, 5512 outerWidth: 0, 5513 outerHeight: 0 5514 }; 5515 for ( var i=0; i < measurementsLength; i++ ) { 5516 var measurement = measurements[i]; 5517 size[ measurement ] = 0; 5518 } 5519 return size; 5520} 5521 5522// -------------------------- getStyle -------------------------- // 5523 5524/** 5525 * getStyle, get style of element, check for Firefox bug 5526 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 5527 */ 5528function getStyle( elem ) { 5529 var style = getComputedStyle( elem ); 5530 if ( !style ) { 5531 logError( 'Style returned ' + style + 5532 '. Are you running this code in a hidden iframe on Firefox? ' + 5533 'See https://bit.ly/getsizebug1' ); 5534 } 5535 return style; 5536} 5537 5538// -------------------------- setup -------------------------- // 5539 5540var isSetup = false; 5541 5542var isBoxSizeOuter; 5543 5544/** 5545 * setup 5546 * check isBoxSizerOuter 5547 * do on first getSize() rather than on page load for Firefox bug 5548 */ 5549function setup() { 5550 // setup once 5551 if ( isSetup ) { 5552 return; 5553 } 5554 isSetup = true; 5555 5556 // -------------------------- box sizing -------------------------- // 5557 5558 /** 5559 * Chrome & Safari measure the outer-width on style.width on border-box elems 5560 * IE11 & Firefox<29 measures the inner-width 5561 */ 5562 var div = document.createElement('div'); 5563 div.style.width = '200px'; 5564 div.style.padding = '1px 2px 3px 4px'; 5565 div.style.borderStyle = 'solid'; 5566 div.style.borderWidth = '1px 2px 3px 4px'; 5567 div.style.boxSizing = 'border-box'; 5568 5569 var body = document.body || document.documentElement; 5570 body.appendChild( div ); 5571 var style = getStyle( div ); 5572 // round value for browser zoom. desandro/masonry#928 5573 isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200; 5574 getSize.isBoxSizeOuter = isBoxSizeOuter; 5575 5576 body.removeChild( div ); 5577} 5578 5579// -------------------------- getSize -------------------------- // 5580 5581function getSize( elem ) { 5582 setup(); 5583 5584 // use querySeletor if elem is string 5585 if ( typeof elem == 'string' ) { 5586 elem = document.querySelector( elem ); 5587 } 5588 5589 // do not proceed on non-objects 5590 if ( !elem || typeof elem != 'object' || !elem.nodeType ) { 5591 return; 5592 } 5593 5594 var style = getStyle( elem ); 5595 5596 // if hidden, everything is 0 5597 if ( style.display == 'none' ) { 5598 return getZeroSize(); 5599 } 5600 5601 var size = {}; 5602 size.width = elem.offsetWidth; 5603 size.height = elem.offsetHeight; 5604 5605 var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; 5606 5607 // get all measurements 5608 for ( var i=0; i < measurementsLength; i++ ) { 5609 var measurement = measurements[i]; 5610 var value = style[ measurement ]; 5611 var num = parseFloat( value ); 5612 // any 'auto', 'medium' value will be 0 5613 size[ measurement ] = !isNaN( num ) ? num : 0; 5614 } 5615 5616 var paddingWidth = size.paddingLeft + size.paddingRight; 5617 var paddingHeight = size.paddingTop + size.paddingBottom; 5618 var marginWidth = size.marginLeft + size.marginRight; 5619 var marginHeight = size.marginTop + size.marginBottom; 5620 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 5621 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 5622 5623 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 5624 5625 // overwrite width and height if we can get it from style 5626 var styleWidth = getStyleSize( style.width ); 5627 if ( styleWidth !== false ) { 5628 size.width = styleWidth + 5629 // add padding and border unless it's already including it 5630 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 5631 } 5632 5633 var styleHeight = getStyleSize( style.height ); 5634 if ( styleHeight !== false ) { 5635 size.height = styleHeight + 5636 // add padding and border unless it's already including it 5637 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 5638 } 5639 5640 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 5641 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 5642 5643 size.outerWidth = size.width + marginWidth; 5644 size.outerHeight = size.height + marginHeight; 5645 5646 return size; 5647} 5648 5649return getSize; 5650 5651}); 5652 5653/** 5654 * matchesSelector v2.0.2 5655 * matchesSelector( element, '.selector' ) 5656 * MIT license 5657 */ 5658 5659/*jshint browser: true, strict: true, undef: true, unused: true */ 5660 5661( function( window, factory ) { 5662 /*global define: false, module: false */ 5663 'use strict'; 5664 // universal module definition 5665 if ( typeof define == 'function' && define.amd ) { 5666 // AMD 5667 define( 'desandro-matches-selector/matches-selector',factory ); 5668 } else if ( typeof module == 'object' && module.exports ) { 5669 // CommonJS 5670 module.exports = factory(); 5671 } else { 5672 // browser global 5673 window.matchesSelector = factory(); 5674 } 5675 5676}( window, function factory() { 5677 'use strict'; 5678 5679 var matchesMethod = ( function() { 5680 var ElemProto = window.Element.prototype; 5681 // check for the standard method name first 5682 if ( ElemProto.matches ) { 5683 return 'matches'; 5684 } 5685 // check un-prefixed 5686 if ( ElemProto.matchesSelector ) { 5687 return 'matchesSelector'; 5688 } 5689 // check vendor prefixes 5690 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 5691 5692 for ( var i=0; i < prefixes.length; i++ ) { 5693 var prefix = prefixes[i]; 5694 var method = prefix + 'MatchesSelector'; 5695 if ( ElemProto[ method ] ) { 5696 return method; 5697 } 5698 } 5699 })(); 5700 5701 return function matchesSelector( elem, selector ) { 5702 return elem[ matchesMethod ]( selector ); 5703 }; 5704 5705})); 5706 5707/** 5708 * Fizzy UI utils v2.0.7 5709 * MIT license 5710 */ 5711 5712/*jshint browser: true, undef: true, unused: true, strict: true */ 5713 5714( function( window, factory ) { 5715 // universal module definition 5716 /*jshint strict: false */ /*globals define, module, require */ 5717 5718 if ( typeof define == 'function' && define.amd ) { 5719 // AMD 5720 define( 'fizzy-ui-utils/utils',[ 5721 'desandro-matches-selector/matches-selector' 5722 ], function( matchesSelector ) { 5723 return factory( window, matchesSelector ); 5724 }); 5725 } else if ( typeof module == 'object' && module.exports ) { 5726 // CommonJS 5727 module.exports = factory( 5728 window, 5729 require('desandro-matches-selector') 5730 ); 5731 } else { 5732 // browser global 5733 window.fizzyUIUtils = factory( 5734 window, 5735 window.matchesSelector 5736 ); 5737 } 5738 5739}( window, function factory( window, matchesSelector ) { 5740 5741 5742 5743var utils = {}; 5744 5745// ----- extend ----- // 5746 5747// extends objects 5748utils.extend = function( a, b ) { 5749 for ( var prop in b ) { 5750 a[ prop ] = b[ prop ]; 5751 } 5752 return a; 5753}; 5754 5755// ----- modulo ----- // 5756 5757utils.modulo = function( num, div ) { 5758 return ( ( num % div ) + div ) % div; 5759}; 5760 5761// ----- makeArray ----- // 5762 5763var arraySlice = Array.prototype.slice; 5764 5765// turn element or nodeList into an array 5766utils.makeArray = function( obj ) { 5767 if ( Array.isArray( obj ) ) { 5768 // use object if already an array 5769 return obj; 5770 } 5771 // return empty array if undefined or null. #6 5772 if ( obj === null || obj === undefined ) { 5773 return []; 5774 } 5775 5776 var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; 5777 if ( isArrayLike ) { 5778 // convert nodeList to array 5779 return arraySlice.call( obj ); 5780 } 5781 5782 // array of single index 5783 return [ obj ]; 5784}; 5785 5786// ----- removeFrom ----- // 5787 5788utils.removeFrom = function( ary, obj ) { 5789 var index = ary.indexOf( obj ); 5790 if ( index != -1 ) { 5791 ary.splice( index, 1 ); 5792 } 5793}; 5794 5795// ----- getParent ----- // 5796 5797utils.getParent = function( elem, selector ) { 5798 while ( elem.parentNode && elem != document.body ) { 5799 elem = elem.parentNode; 5800 if ( matchesSelector( elem, selector ) ) { 5801 return elem; 5802 } 5803 } 5804}; 5805 5806// ----- getQueryElement ----- // 5807 5808// use element as selector string 5809utils.getQueryElement = function( elem ) { 5810 if ( typeof elem == 'string' ) { 5811 return document.querySelector( elem ); 5812 } 5813 return elem; 5814}; 5815 5816// ----- handleEvent ----- // 5817 5818// enable .ontype to trigger from .addEventListener( elem, 'type' ) 5819utils.handleEvent = function( event ) { 5820 var method = 'on' + event.type; 5821 if ( this[ method ] ) { 5822 this[ method ]( event ); 5823 } 5824}; 5825 5826// ----- filterFindElements ----- // 5827 5828utils.filterFindElements = function( elems, selector ) { 5829 // make array of elems 5830 elems = utils.makeArray( elems ); 5831 var ffElems = []; 5832 5833 elems.forEach( function( elem ) { 5834 // check that elem is an actual element 5835
5835// START UNCODE EDIT 5836 // if ( !( elem instanceof HTMLElement ) ) { 5837 if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) { 5838 // END UNCODE EDIT
vendor: 75,264 bytes, lines 5838-8743
5838 5839 return; 5840 } 5841 // add elem if no selector 5842 if ( !selector ) { 5843 ffElems.push( elem ); 5844 return; 5845 } 5846 // filter & find items if we have a selector 5847 // filter 5848 if ( matchesSelector( elem, selector ) ) { 5849 ffElems.push( elem ); 5850 } 5851 // find children 5852 var childElems = elem.querySelectorAll( selector ); 5853 // concat childElems to filterFound array 5854 for ( var i=0; i < childElems.length; i++ ) { 5855 ffElems.push( childElems[i] ); 5856 } 5857 }); 5858 5859 return ffElems; 5860}; 5861 5862// ----- debounceMethod ----- // 5863 5864utils.debounceMethod = function( _class, methodName, threshold ) { 5865 threshold = threshold || 100; 5866 // original method 5867 var method = _class.prototype[ methodName ]; 5868 var timeoutName = methodName + 'Timeout'; 5869 5870 _class.prototype[ methodName ] = function() { 5871 var timeout = this[ timeoutName ]; 5872 clearTimeout( timeout ); 5873 5874 var args = arguments; 5875 var _this = this; 5876 this[ timeoutName ] = setTimeout( function() { 5877 method.apply( _this, args ); 5878 delete _this[ timeoutName ]; 5879 }, threshold ); 5880 }; 5881}; 5882 5883// ----- docReady ----- // 5884 5885utils.docReady = function( callback ) { 5886 var readyState = document.readyState; 5887 if ( readyState == 'complete' || readyState == 'interactive' ) { 5888 // do async to allow for other scripts to run. metafizzy/flickity#441 5889 setTimeout( callback ); 5890 } else { 5891 document.addEventListener( 'DOMContentLoaded', callback ); 5892 } 5893}; 5894 5895// ----- htmlInit ----- // 5896 5897// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 5898utils.toDashed = function( str ) { 5899 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 5900 return $1 + '-' + $2; 5901 }).toLowerCase(); 5902}; 5903 5904var console = window.console; 5905/** 5906 * allow user to initialize classes via [data-namespace] or .js-namespace class 5907 * htmlInit( Widget, 'widgetName' ) 5908 * options are parsed from data-namespace-options 5909 */ 5910utils.htmlInit = function( WidgetClass, namespace ) { 5911 utils.docReady( function() { 5912 var dashedNamespace = utils.toDashed( namespace ); 5913 var dataAttr = 'data-' + dashedNamespace; 5914 var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); 5915 var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); 5916 var elems = utils.makeArray( dataAttrElems ) 5917 .concat( utils.makeArray( jsDashElems ) ); 5918 var dataOptionsAttr = dataAttr + '-options'; 5919 var jQuery = window.jQuery; 5920 5921 elems.forEach( function( elem ) { 5922 var attr = elem.getAttribute( dataAttr ) || 5923 elem.getAttribute( dataOptionsAttr ); 5924 var options; 5925 try { 5926 options = attr && JSON.parse( attr ); 5927 } catch ( error ) { 5928 // log error, do not initialize 5929 if ( console ) { 5930 console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + 5931 ': ' + error ); 5932 } 5933 return; 5934 } 5935 // initialize 5936 var instance = new WidgetClass( elem, options ); 5937 // make available via $().data('namespace') 5938 if ( jQuery ) { 5939 jQuery.data( elem, namespace, instance ); 5940 } 5941 }); 5942 5943 }); 5944}; 5945 5946// ----- ----- // 5947 5948return utils; 5949 5950})); 5951 5952/** 5953 * Outlayer Item 5954 */ 5955 5956( function( window, factory ) { 5957 // universal module definition 5958 /* jshint strict: false */ /* globals define, module, require */ 5959 if ( typeof define == 'function' && define.amd ) { 5960 // AMD - RequireJS 5961 define( 'outlayer/item',[ 5962 'ev-emitter/ev-emitter', 5963 'get-size/get-size' 5964 ], 5965 factory 5966 ); 5967 } else if ( typeof module == 'object' && module.exports ) { 5968 // CommonJS - Browserify, Webpack 5969 module.exports = factory( 5970 require('ev-emitter'), 5971 require('get-size') 5972 ); 5973 } else { 5974 // browser global 5975 window.Outlayer = {}; 5976 window.Outlayer.Item = factory( 5977 window.EvEmitter, 5978 window.getSize 5979 ); 5980 } 5981 5982}( window, function factory( EvEmitter, getSize ) { 5983'use strict'; 5984 5985// ----- helpers ----- // 5986 5987function isEmptyObj( obj ) { 5988 for ( var prop in obj ) { 5989 return false; 5990 } 5991 prop = null; 5992 return true; 5993} 5994 5995// -------------------------- CSS3 support -------------------------- // 5996 5997 5998var docElemStyle = document.documentElement.style; 5999 6000var transitionProperty = typeof docElemStyle.transition == 'string' ? 6001 'transition' : 'WebkitTransition'; 6002var transformProperty = typeof docElemStyle.transform == 'string' ? 6003 'transform' : 'WebkitTransform'; 6004 6005var transitionEndEvent = { 6006 WebkitTransition: 'webkitTransitionEnd', 6007 transition: 'transitionend' 6008}[ transitionProperty ]; 6009 6010// cache all vendor properties that could have vendor prefix 6011var vendorProperties = { 6012 transform: transformProperty, 6013 transition: transitionProperty, 6014 transitionDuration: transitionProperty + 'Duration', 6015 transitionProperty: transitionProperty + 'Property', 6016 transitionDelay: transitionProperty + 'Delay' 6017}; 6018 6019// -------------------------- Item -------------------------- // 6020 6021function Item( element, layout ) { 6022 if ( !element ) { 6023 return; 6024 } 6025 6026 this.element = element; 6027 // parent layout class, i.e. Masonry, Isotope, or Packery 6028 this.layout = layout; 6029 this.position = { 6030 x: 0, 6031 y: 0 6032 }; 6033 6034 this._create(); 6035} 6036 6037// inherit EvEmitter 6038var proto = Item.prototype = Object.create( EvEmitter.prototype ); 6039proto.constructor = Item; 6040 6041proto._create = function() { 6042 // transition objects 6043 this._transn = { 6044 ingProperties: {}, 6045 clean: {}, 6046 onEnd: {} 6047 }; 6048 6049 this.css({ 6050 position: 'absolute' 6051 }); 6052}; 6053 6054// trigger specified handler for event type 6055proto.handleEvent = function( event ) { 6056 var method = 'on' + event.type; 6057 if ( this[ method ] ) { 6058 this[ method ]( event ); 6059 } 6060}; 6061 6062proto.getSize = function() { 6063 this.size = getSize( this.element ); 6064}; 6065 6066/** 6067 * apply CSS styles to element 6068 * @param {Object} style 6069 */ 6070proto.css = function( style ) { 6071 var elemStyle = this.element.style; 6072 6073 for ( var prop in style ) { 6074 // use vendor property if available 6075 var supportedProp = vendorProperties[ prop ] || prop; 6076 elemStyle[ supportedProp ] = style[ prop ]; 6077 } 6078}; 6079 6080 // measure position, and sets it 6081proto.getPosition = function() { 6082 var style = getComputedStyle( this.element ); 6083 var isOriginLeft = this.layout._getOption('originLeft'); 6084 var isOriginTop = this.layout._getOption('originTop'); 6085 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 6086 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 6087 var x = parseFloat( xValue ); 6088 var y = parseFloat( yValue ); 6089 // convert percent to pixels 6090 var layoutSize = this.layout.size; 6091 if ( xValue.indexOf('%') != -1 ) { 6092 x = ( x / 100 ) * layoutSize.width; 6093 } 6094 if ( yValue.indexOf('%') != -1 ) { 6095 y = ( y / 100 ) * layoutSize.height; 6096 } 6097 // clean up 'auto' or other non-integer values 6098 x = isNaN( x ) ? 0 : x; 6099 y = isNaN( y ) ? 0 : y; 6100 // remove padding from measurement 6101 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 6102 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 6103 6104 this.position.x = x; 6105 this.position.y = y; 6106}; 6107 6108// set settled position, apply padding 6109proto.layoutPosition = function() { 6110 var layoutSize = this.layout.size; 6111 var style = {}; 6112 var isOriginLeft = this.layout._getOption('originLeft'); 6113 var isOriginTop = this.layout._getOption('originTop'); 6114 6115 // x 6116 var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; 6117 var xProperty = isOriginLeft ? 'left' : 'right'; 6118 var xResetProperty = isOriginLeft ? 'right' : 'left'; 6119 6120 var x = this.position.x + layoutSize[ xPadding ]; 6121 // set in percentage or pixels 6122 style[ xProperty ] = this.getXValue( x ); 6123 // reset other property 6124 style[ xResetProperty ] = ''; 6125 6126 // y 6127 var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; 6128 var yProperty = isOriginTop ? 'top' : 'bottom'; 6129 var yResetProperty = isOriginTop ? 'bottom' : 'top'; 6130 6131 var y = this.position.y + layoutSize[ yPadding ]; 6132 // set in percentage or pixels 6133 style[ yProperty ] = this.getYValue( y ); 6134 // reset other property 6135 style[ yResetProperty ] = ''; 6136 6137 this.css( style ); 6138 this.emitEvent( 'layout', [ this ] ); 6139}; 6140 6141proto.getXValue = function( x ) { 6142 var isHorizontal = this.layout._getOption('horizontal'); 6143 return this.layout.options.percentPosition && !isHorizontal ? 6144 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 6145}; 6146 6147proto.getYValue = function( y ) { 6148 var isHorizontal = this.layout._getOption('horizontal'); 6149 return this.layout.options.percentPosition && isHorizontal ? 6150 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 6151}; 6152 6153proto._transitionTo = function( x, y ) { 6154 this.getPosition(); 6155 // get current x & y from top/left 6156 var curX = this.position.x; 6157 var curY = this.position.y; 6158 6159 var didNotMove = x == this.position.x && y == this.position.y; 6160 6161 // save end position 6162 this.setPosition( x, y ); 6163 6164 // if did not move and not transitioning, just go to layout 6165 if ( didNotMove && !this.isTransitioning ) { 6166 this.layoutPosition(); 6167 return; 6168 } 6169 6170 var transX = x - curX; 6171 var transY = y - curY; 6172 var transitionStyle = {}; 6173 transitionStyle.transform = this.getTranslate( transX, transY ); 6174 6175 this.transition({ 6176 to: transitionStyle, 6177 onTransitionEnd: { 6178 transform: this.layoutPosition 6179 }, 6180 isCleaning: true 6181 }); 6182}; 6183 6184proto.getTranslate = function( x, y ) { 6185 // flip cooridinates if origin on right or bottom 6186 var isOriginLeft = this.layout._getOption('originLeft'); 6187 var isOriginTop = this.layout._getOption('originTop'); 6188 x = isOriginLeft ? x : -x; 6189 y = isOriginTop ? y : -y; 6190 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 6191}; 6192 6193// non transition + transform support 6194proto.goTo = function( x, y ) { 6195 this.setPosition( x, y ); 6196 this.layoutPosition(); 6197}; 6198 6199proto.moveTo = proto._transitionTo; 6200 6201proto.setPosition = function( x, y ) { 6202 this.position.x = parseFloat( x ); 6203 this.position.y = parseFloat( y ); 6204}; 6205 6206// ----- transition ----- // 6207 6208/** 6209 * @param {Object} style - CSS 6210 * @param {Function} onTransitionEnd 6211 */ 6212 6213// non transition, just trigger callback 6214proto._nonTransition = function( args ) { 6215 this.css( args.to ); 6216 if ( args.isCleaning ) { 6217 this._removeStyles( args.to ); 6218 } 6219 for ( var prop in args.onTransitionEnd ) { 6220 args.onTransitionEnd[ prop ].call( this ); 6221 } 6222}; 6223 6224/** 6225 * proper transition 6226 * @param {Object} args - arguments 6227 * @param {Object} to - style to transition to 6228 * @param {Object} from - style to start transition from 6229 * @param {Boolean} isCleaning - removes transition styles after transition 6230 * @param {Function} onTransitionEnd - callback 6231 */ 6232proto.transition = function( args ) { 6233 // redirect to nonTransition if no transition duration 6234 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 6235 this._nonTransition( args ); 6236 return; 6237 } 6238 6239 var _transition = this._transn; 6240 // keep track of onTransitionEnd callback by css property 6241 for ( var prop in args.onTransitionEnd ) { 6242 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 6243 } 6244 // keep track of properties that are transitioning 6245 for ( prop in args.to ) { 6246 _transition.ingProperties[ prop ] = true; 6247 // keep track of properties to clean up when transition is done 6248 if ( args.isCleaning ) { 6249 _transition.clean[ prop ] = true; 6250 } 6251 } 6252 6253 // set from styles 6254 if ( args.from ) { 6255 this.css( args.from ); 6256 // force redraw. http://blog.alexmaccaw.com/css-transitions 6257 var h = this.element.offsetHeight; 6258 // hack for JSHint to hush about unused var 6259 h = null; 6260 } 6261 // enable transition 6262 this.enableTransition( args.to ); 6263 // set styles that are transitioning 6264 this.css( args.to ); 6265 6266 this.isTransitioning = true; 6267 6268}; 6269 6270// dash before all cap letters, including first for 6271// WebkitTransform => -webkit-transform 6272function toDashedAll( str ) { 6273 return str.replace( /([A-Z])/g, function( $1 ) { 6274 return '-' + $1.toLowerCase(); 6275 }); 6276} 6277 6278var transitionProps = 'opacity,' + toDashedAll( transformProperty ); 6279 6280proto.enableTransition = function(/* style */) { 6281 // HACK changing transitionProperty during a transition 6282 // will cause transition to jump 6283 if ( this.isTransitioning ) { 6284 return; 6285 } 6286 6287 // make `transition: foo, bar, baz` from style object 6288 // HACK un-comment this when enableTransition can work 6289 // while a transition is happening 6290 // var transitionValues = []; 6291 // for ( var prop in style ) { 6292 // // dash-ify camelCased properties like WebkitTransition 6293 // prop = vendorProperties[ prop ] || prop; 6294 // transitionValues.push( toDashedAll( prop ) ); 6295 // } 6296 // munge number to millisecond, to match stagger 6297 var duration = this.layout.options.transitionDuration; 6298 duration = typeof duration == 'number' ? duration + 'ms' : duration; 6299 // enable transition styles 6300 this.css({ 6301 transitionProperty: transitionProps, 6302 transitionDuration: duration, 6303 transitionDelay: this.staggerDelay || 0 6304 }); 6305 // listen for transition end event 6306 this.element.addEventListener( transitionEndEvent, this, false ); 6307}; 6308 6309// ----- events ----- // 6310 6311proto.onwebkitTransitionEnd = function( event ) { 6312 this.ontransitionend( event ); 6313}; 6314 6315proto.onotransitionend = function( event ) { 6316 this.ontransitionend( event ); 6317}; 6318 6319// properties that I munge to make my life easier 6320var dashedVendorProperties = { 6321 '-webkit-transform': 'transform' 6322}; 6323 6324proto.ontransitionend = function( event ) { 6325 // disregard bubbled events from children 6326 if ( event.target !== this.element ) { 6327 return; 6328 } 6329 var _transition = this._transn; 6330 // get property name of transitioned property, convert to prefix-free 6331 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 6332 6333 // remove property that has completed transitioning 6334 delete _transition.ingProperties[ propertyName ]; 6335 // check if any properties are still transitioning 6336 if ( isEmptyObj( _transition.ingProperties ) ) { 6337 // all properties have completed transitioning 6338 this.disableTransition(); 6339 } 6340 // clean style 6341 if ( propertyName in _transition.clean ) { 6342 // clean up style 6343 this.element.style[ event.propertyName ] = ''; 6344 delete _transition.clean[ propertyName ]; 6345 } 6346 // trigger onTransitionEnd callback 6347 if ( propertyName in _transition.onEnd ) { 6348 var onTransitionEnd = _transition.onEnd[ propertyName ]; 6349 onTransitionEnd.call( this ); 6350 delete _transition.onEnd[ propertyName ]; 6351 } 6352 6353 this.emitEvent( 'transitionEnd', [ this ] ); 6354}; 6355 6356proto.disableTransition = function() { 6357 this.removeTransitionStyles(); 6358 this.element.removeEventListener( transitionEndEvent, this, false ); 6359 this.isTransitioning = false; 6360}; 6361 6362/** 6363 * removes style property from element 6364 * @param {Object} style 6365**/ 6366proto._removeStyles = function( style ) { 6367 // clean up transition styles 6368 var cleanStyle = {}; 6369 for ( var prop in style ) { 6370 cleanStyle[ prop ] = ''; 6371 } 6372 this.css( cleanStyle ); 6373}; 6374 6375var cleanTransitionStyle = { 6376 transitionProperty: '', 6377 transitionDuration: '', 6378 transitionDelay: '' 6379}; 6380 6381proto.removeTransitionStyles = function() { 6382 // remove transition 6383 this.css( cleanTransitionStyle ); 6384}; 6385 6386// ----- stagger ----- // 6387 6388proto.stagger = function( delay ) { 6389 delay = isNaN( delay ) ? 0 : delay; 6390 this.staggerDelay = delay + 'ms'; 6391}; 6392 6393// ----- show/hide/remove ----- // 6394 6395// remove element from DOM 6396proto.removeElem = function() { 6397 this.element.parentNode.removeChild( this.element ); 6398 // remove display: none 6399 this.css({ display: '' }); 6400 this.emitEvent( 'remove', [ this ] ); 6401}; 6402 6403proto.remove = function() { 6404 // just remove element if no transition support or no transition 6405 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 6406 this.removeElem(); 6407 return; 6408 } 6409 6410 // start transition 6411 this.once( 'transitionEnd', function() { 6412 this.removeElem(); 6413 }); 6414 this.hide(); 6415}; 6416 6417proto.reveal = function() { 6418 delete this.isHidden; 6419 // remove display: none 6420 this.css({ display: '' }); 6421 6422 var options = this.layout.options; 6423 6424 var onTransitionEnd = {}; 6425 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 6426 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 6427 6428 this.transition({ 6429 from: options.hiddenStyle, 6430 to: options.visibleStyle, 6431 isCleaning: true, 6432 onTransitionEnd: onTransitionEnd 6433 }); 6434}; 6435 6436proto.onRevealTransitionEnd = function() { 6437 // check if still visible 6438 // during transition, item may have been hidden 6439 if ( !this.isHidden ) { 6440 this.emitEvent('reveal'); 6441 } 6442}; 6443 6444/** 6445 * get style property use for hide/reveal transition end 6446 * @param {String} styleProperty - hiddenStyle/visibleStyle 6447 * @returns {String} 6448 */ 6449proto.getHideRevealTransitionEndProperty = function( styleProperty ) { 6450 var optionStyle = this.layout.options[ styleProperty ]; 6451 // use opacity 6452 if ( optionStyle.opacity ) { 6453 return 'opacity'; 6454 } 6455 // get first property 6456 for ( var prop in optionStyle ) { 6457 return prop; 6458 } 6459}; 6460 6461proto.hide = function() { 6462 // set flag 6463 this.isHidden = true; 6464 // remove display: none 6465 this.css({ display: '' }); 6466 6467 var options = this.layout.options; 6468 6469 var onTransitionEnd = {}; 6470 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 6471 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 6472 6473 this.transition({ 6474 from: options.visibleStyle, 6475 to: options.hiddenStyle, 6476 // keep hidden stuff hidden 6477 isCleaning: true, 6478 onTransitionEnd: onTransitionEnd 6479 }); 6480}; 6481 6482proto.onHideTransitionEnd = function() { 6483 // check if still hidden 6484 // during transition, item may have been un-hidden 6485 if ( this.isHidden ) { 6486 this.css({ display: 'none' }); 6487 this.emitEvent('hide'); 6488 } 6489}; 6490 6491proto.destroy = function() { 6492 this.css({ 6493 position: '', 6494 left: '', 6495 right: '', 6496 top: '', 6497 bottom: '', 6498 transition: '', 6499 transform: '' 6500 }); 6501}; 6502 6503return Item; 6504 6505})); 6506 6507/*! 6508 * Outlayer v2.1.1 6509 * the brains and guts of a layout library 6510 * MIT license 6511 */ 6512 6513( function( window, factory ) { 6514 'use strict'; 6515 // universal module definition 6516 /* jshint strict: false */ /* globals define, module, require */ 6517 if ( typeof define == 'function' && define.amd ) { 6518 // AMD - RequireJS 6519 define( 'outlayer/outlayer',[ 6520 'ev-emitter/ev-emitter', 6521 'get-size/get-size', 6522 'fizzy-ui-utils/utils', 6523 './item' 6524 ], 6525 function( EvEmitter, getSize, utils, Item ) { 6526 return factory( window, EvEmitter, getSize, utils, Item); 6527 } 6528 ); 6529 } else if ( typeof module == 'object' && module.exports ) { 6530 // CommonJS - Browserify, Webpack 6531 module.exports = factory( 6532 window, 6533 require('ev-emitter'), 6534 require('get-size'), 6535 require('fizzy-ui-utils'), 6536 require('./item') 6537 ); 6538 } else { 6539 // browser global 6540 window.Outlayer = factory( 6541 window, 6542 window.EvEmitter, 6543 window.getSize, 6544 window.fizzyUIUtils, 6545 window.Outlayer.Item 6546 ); 6547 } 6548 6549}( window, function factory( window, EvEmitter, getSize, utils, Item ) { 6550'use strict'; 6551 6552// ----- vars ----- // 6553 6554var console = window.console; 6555var jQuery = window.jQuery; 6556var noop = function() {}; 6557 6558// -------------------------- Outlayer -------------------------- // 6559 6560// globally unique identifiers 6561var GUID = 0; 6562// internal store of all Outlayer intances 6563var instances = {}; 6564 6565 6566/** 6567 * @param {Element, String} element 6568 * @param {Object} options 6569 * @constructor 6570 */ 6571function Outlayer( element, options ) { 6572 var queryElement = utils.getQueryElement( element ); 6573 if ( !queryElement ) { 6574 if ( console ) { 6575 console.error( 'Bad element for ' + this.constructor.namespace + 6576 ': ' + ( queryElement || element ) ); 6577 } 6578 return; 6579 } 6580 this.element = queryElement; 6581 // add jQuery 6582 if ( jQuery ) { 6583 this.$element = jQuery( this.element ); 6584 } 6585 6586 // options 6587 this.options = utils.extend( {}, this.constructor.defaults ); 6588 this.option( options ); 6589 6590 // add id for Outlayer.getFromElement 6591 var id = ++GUID; 6592 this.element.outlayerGUID = id; // expando 6593 instances[ id ] = this; // associate via id 6594 6595 // kick it off 6596 this._create(); 6597 6598 var isInitLayout = this._getOption('initLayout'); 6599 if ( isInitLayout ) { 6600 this.layout(); 6601 } 6602} 6603 6604// settings are for internal use only 6605Outlayer.namespace = 'outlayer'; 6606Outlayer.Item = Item; 6607 6608// default options 6609Outlayer.defaults = { 6610 containerStyle: { 6611 position: 'relative' 6612 }, 6613 initLayout: true, 6614 originLeft: true, 6615 originTop: true, 6616 resize: true, 6617 resizeContainer: true, 6618 // item options 6619 transitionDuration: '0.4s', 6620 hiddenStyle: { 6621 opacity: 0, 6622 transform: 'scale(0.001)' 6623 }, 6624 visibleStyle: { 6625 opacity: 1, 6626 transform: 'scale(1)' 6627 } 6628}; 6629 6630var proto = Outlayer.prototype; 6631// inherit EvEmitter 6632utils.extend( proto, EvEmitter.prototype ); 6633 6634/** 6635 * set options 6636 * @param {Object} opts 6637 */ 6638proto.option = function( opts ) { 6639 utils.extend( this.options, opts ); 6640}; 6641 6642/** 6643 * get backwards compatible option value, check old name 6644 */ 6645proto._getOption = function( option ) { 6646 var oldOption = this.constructor.compatOptions[ option ]; 6647 return oldOption && this.options[ oldOption ] !== undefined ? 6648 this.options[ oldOption ] : this.options[ option ]; 6649}; 6650 6651Outlayer.compatOptions = { 6652 // currentName: oldName 6653 initLayout: 'isInitLayout', 6654 horizontal: 'isHorizontal', 6655 layoutInstant: 'isLayoutInstant', 6656 originLeft: 'isOriginLeft', 6657 originTop: 'isOriginTop', 6658 resize: 'isResizeBound', 6659 resizeContainer: 'isResizingContainer' 6660}; 6661 6662proto._create = function() { 6663 // get items from children 6664 this.reloadItems(); 6665 // elements that affect layout, but are not laid out 6666 this.stamps = []; 6667 this.stamp( this.options.stamp ); 6668 // set container style 6669 utils.extend( this.element.style, this.options.containerStyle ); 6670 6671 // bind resize method 6672 var canBindResize = this._getOption('resize'); 6673 if ( canBindResize ) { 6674 this.bindResize(); 6675 } 6676}; 6677 6678// goes through all children again and gets bricks in proper order 6679proto.reloadItems = function() { 6680 // collection of item elements 6681 this.items = this._itemize( this.element.children ); 6682}; 6683 6684 6685/** 6686 * turn elements into Outlayer.Items to be used in layout 6687 * @param {Array or NodeList or HTMLElement} elems 6688 * @returns {Array} items - collection of new Outlayer Items 6689 */ 6690proto._itemize = function( elems ) { 6691 6692 var itemElems = this._filterFindItemElements( elems ); 6693 var Item = this.constructor.Item; 6694 6695 // create new Outlayer Items for collection 6696 var items = []; 6697 for ( var i=0; i < itemElems.length; i++ ) { 6698 var elem = itemElems[i]; 6699 var item = new Item( elem, this ); 6700 items.push( item ); 6701 } 6702 6703 return items; 6704}; 6705 6706/** 6707 * get item elements to be used in layout 6708 * @param {Array or NodeList or HTMLElement} elems 6709 * @returns {Array} items - item elements 6710 */ 6711proto._filterFindItemElements = function( elems ) { 6712 return utils.filterFindElements( elems, this.options.itemSelector ); 6713}; 6714 6715/** 6716 * getter method for getting item elements 6717 * @returns {Array} elems - collection of item elements 6718 */ 6719proto.getItemElements = function() { 6720 return this.items.map( function( item ) { 6721 return item.element; 6722 }); 6723}; 6724 6725// ----- init & layout ----- // 6726 6727/** 6728 * lays out all items 6729 */ 6730proto.layout = function() { 6731 this._resetLayout(); 6732 this._manageStamps(); 6733 6734 // don't animate first layout 6735 var layoutInstant = this._getOption('layoutInstant'); 6736 var isInstant = layoutInstant !== undefined ? 6737 layoutInstant : !this._isLayoutInited; 6738 this.layoutItems( this.items, isInstant ); 6739 6740 // flag for initalized 6741 this._isLayoutInited = true; 6742}; 6743 6744// _init is alias for layout 6745proto._init = proto.layout; 6746 6747/** 6748 * logic before any new layout 6749 */ 6750proto._resetLayout = function() { 6751 this.getSize(); 6752}; 6753 6754 6755proto.getSize = function() { 6756 this.size = getSize( this.element ); 6757}; 6758 6759/** 6760 * get measurement from option, for columnWidth, rowHeight, gutter 6761 * if option is String -> get element from selector string, & get size of element 6762 * if option is Element -> get size of element 6763 * else use option as a number 6764 * 6765 * @param {String} measurement 6766 * @param {String} size - width or height 6767 * @private 6768 */ 6769proto._getMeasurement = function( measurement, size ) { 6770 var option = this.options[ measurement ]; 6771 var elem; 6772 if ( !option ) { 6773 // default to 0 6774 this[ measurement ] = 0; 6775 } else { 6776 // use option as an element 6777 if ( typeof option == 'string' ) { 6778 elem = this.element.querySelector( option ); 6779 } else if ( option instanceof HTMLElement ) { 6780 elem = option; 6781 } 6782 // use size of element, if element 6783 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 6784 } 6785}; 6786 6787/** 6788 * layout a collection of item elements 6789 * @api public 6790 */ 6791proto.layoutItems = function( items, isInstant ) { 6792 items = this._getItemsForLayout( items ); 6793 6794 this._layoutItems( items, isInstant ); 6795 6796 this._postLayout(); 6797}; 6798 6799/** 6800 * get the items to be laid out 6801 * you may want to skip over some items 6802 * @param {Array} items 6803 * @returns {Array} items 6804 */ 6805proto._getItemsForLayout = function( items ) { 6806 return items.filter( function( item ) { 6807 return !item.isIgnored; 6808 }); 6809}; 6810 6811/** 6812 * layout items 6813 * @param {Array} items 6814 * @param {Boolean} isInstant 6815 */ 6816proto._layoutItems = function( items, isInstant ) { 6817 this._emitCompleteOnItems( 'layout', items ); 6818 6819 if ( !items || !items.length ) { 6820 // no items, emit event with empty array 6821 return; 6822 } 6823 6824 var queue = []; 6825 6826 items.forEach( function( item ) { 6827 // get x/y object from method 6828 var position = this._getItemLayoutPosition( item ); 6829 // enqueue 6830 position.item = item; 6831 position.isInstant = isInstant || item.isLayoutInstant; 6832 queue.push( position ); 6833 }, this ); 6834 6835 this._processLayoutQueue( queue ); 6836}; 6837 6838/** 6839 * get item layout position 6840 * @param {Outlayer.Item} item 6841 * @returns {Object} x and y position 6842 */ 6843proto._getItemLayoutPosition = function( /* item */ ) { 6844 return { 6845 x: 0, 6846 y: 0 6847 }; 6848}; 6849 6850/** 6851 * iterate over array and position each item 6852 * Reason being - separating this logic prevents 'layout invalidation' 6853 * thx @paul_irish 6854 * @param {Array} queue 6855 */ 6856proto._processLayoutQueue = function( queue ) { 6857 this.updateStagger(); 6858 queue.forEach( function( obj, i ) { 6859 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); 6860 }, this ); 6861}; 6862 6863// set stagger from option in milliseconds number 6864proto.updateStagger = function() { 6865 var stagger = this.options.stagger; 6866 if ( stagger === null || stagger === undefined ) { 6867 this.stagger = 0; 6868 return; 6869 } 6870 this.stagger = getMilliseconds( stagger ); 6871 return this.stagger; 6872}; 6873 6874/** 6875 * Sets position of item in DOM 6876 * @param {Outlayer.Item} item 6877 * @param {Number} x - horizontal position 6878 * @param {Number} y - vertical position 6879 * @param {Boolean} isInstant - disables transitions 6880 */ 6881proto._positionItem = function( item, x, y, isInstant, i ) { 6882 if ( isInstant ) { 6883 // if not transition, just set CSS 6884 item.goTo( x, y ); 6885 } else { 6886 item.stagger( i * this.stagger ); 6887 item.moveTo( x, y ); 6888 } 6889}; 6890 6891/** 6892 * Any logic you want to do after each layout, 6893 * i.e. size the container 6894 */ 6895proto._postLayout = function() { 6896 this.resizeContainer(); 6897}; 6898 6899proto.resizeContainer = function() { 6900 var isResizingContainer = this._getOption('resizeContainer'); 6901 if ( !isResizingContainer ) { 6902 return; 6903 } 6904 var size = this._getContainerSize(); 6905 if ( size ) { 6906 this._setContainerMeasure( size.width, true ); 6907 this._setContainerMeasure( size.height, false ); 6908 } 6909}; 6910 6911/** 6912 * Sets width or height of container if returned 6913 * @returns {Object} size 6914 * @param {Number} width 6915 * @param {Number} height 6916 */ 6917proto._getContainerSize = noop; 6918 6919/** 6920 * @param {Number} measure - size of width or height 6921 * @param {Boolean} isWidth 6922 */ 6923proto._setContainerMeasure = function( measure, isWidth ) { 6924 if ( measure === undefined ) { 6925 return; 6926 } 6927 6928 var elemSize = this.size; 6929 // add padding and border width if border box 6930 if ( elemSize.isBorderBox ) { 6931 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 6932 elemSize.borderLeftWidth + elemSize.borderRightWidth : 6933 elemSize.paddingBottom + elemSize.paddingTop + 6934 elemSize.borderTopWidth + elemSize.borderBottomWidth; 6935 } 6936 6937 measure = Math.max( measure, 0 ); 6938 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 6939}; 6940 6941/** 6942 * emit eventComplete on a collection of items events 6943 * @param {String} eventName 6944 * @param {Array} items - Outlayer.Items 6945 */ 6946proto._emitCompleteOnItems = function( eventName, items ) { 6947 var _this = this; 6948 function onComplete() { 6949 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 6950 } 6951 6952 var count = items.length; 6953 if ( !items || !count ) { 6954 onComplete(); 6955 return; 6956 } 6957 6958 var doneCount = 0; 6959 function tick() { 6960 doneCount++; 6961 if ( doneCount == count ) { 6962 onComplete(); 6963 } 6964 } 6965 6966 // bind callback 6967 items.forEach( function( item ) { 6968 item.once( eventName, tick ); 6969 }); 6970}; 6971 6972/** 6973 * emits events via EvEmitter and jQuery events 6974 * @param {String} type - name of event 6975 * @param {Event} event - original event 6976 * @param {Array} args - extra arguments 6977 */ 6978proto.dispatchEvent = function( type, event, args ) { 6979 // add original event to arguments 6980 var emitArgs = event ? [ event ].concat( args ) : args; 6981 this.emitEvent( type, emitArgs ); 6982 6983 if ( jQuery ) { 6984 // set this.$element 6985 this.$element = this.$element || jQuery( this.element ); 6986 if ( event ) { 6987 // create jQuery event 6988 var $event = jQuery.Event( event ); 6989 $event.type = type; 6990 this.$element.trigger( $event, args ); 6991 } else { 6992 // just trigger with type if no event available 6993 this.$element.trigger( type, args ); 6994 } 6995 } 6996}; 6997 6998// -------------------------- ignore & stamps -------------------------- // 6999 7000 7001/** 7002 * keep item in collection, but do not lay it out 7003 * ignored items do not get skipped in layout 7004 * @param {Element} elem 7005 */ 7006proto.ignore = function( elem ) { 7007 var item = this.getItem( elem ); 7008 if ( item ) { 7009 item.isIgnored = true; 7010 } 7011}; 7012 7013/** 7014 * return item to layout collection 7015 * @param {Element} elem 7016 */ 7017proto.unignore = function( elem ) { 7018 var item = this.getItem( elem ); 7019 if ( item ) { 7020 delete item.isIgnored; 7021 } 7022}; 7023 7024/** 7025 * adds elements to stamps 7026 * @param {NodeList, Array, Element, or String} elems 7027 */ 7028proto.stamp = function( elems ) { 7029 elems = this._find( elems ); 7030 if ( !elems ) { 7031 return; 7032 } 7033 7034 this.stamps = this.stamps.concat( elems ); 7035 // ignore 7036 elems.forEach( this.ignore, this ); 7037}; 7038 7039/** 7040 * removes elements to stamps 7041 * @param {NodeList, Array, or Element} elems 7042 */ 7043proto.unstamp = function( elems ) { 7044 elems = this._find( elems ); 7045 if ( !elems ){ 7046 return; 7047 } 7048 7049 elems.forEach( function( elem ) { 7050 // filter out removed stamp elements 7051 utils.removeFrom( this.stamps, elem ); 7052 this.unignore( elem ); 7053 }, this ); 7054}; 7055 7056/** 7057 * finds child elements 7058 * @param {NodeList, Array, Element, or String} elems 7059 * @returns {Array} elems 7060 */ 7061proto._find = function( elems ) { 7062 if ( !elems ) { 7063 return; 7064 } 7065 // if string, use argument as selector string 7066 if ( typeof elems == 'string' ) { 7067 elems = this.element.querySelectorAll( elems ); 7068 } 7069 elems = utils.makeArray( elems ); 7070 return elems; 7071}; 7072 7073proto._manageStamps = function() { 7074 if ( !this.stamps || !this.stamps.length ) { 7075 return; 7076 } 7077 7078 this._getBoundingRect(); 7079 7080 this.stamps.forEach( this._manageStamp, this ); 7081}; 7082 7083// update boundingLeft / Top 7084proto._getBoundingRect = function() { 7085 // get bounding rect for container element 7086 var boundingRect = this.element.getBoundingClientRect(); 7087 var size = this.size; 7088 this._boundingRect = { 7089 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 7090 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 7091 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 7092 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 7093 }; 7094}; 7095 7096/** 7097 * @param {Element} stamp 7098**/ 7099proto._manageStamp = noop; 7100 7101/** 7102 * get x/y position of element relative to container element 7103 * @param {Element} elem 7104 * @returns {Object} offset - has left, top, right, bottom 7105 */ 7106proto._getElementOffset = function( elem ) { 7107 var boundingRect = elem.getBoundingClientRect(); 7108 var thisRect = this._boundingRect; 7109 var size = getSize( elem ); 7110 var offset = { 7111 left: boundingRect.left - thisRect.left - size.marginLeft, 7112 top: boundingRect.top - thisRect.top - size.marginTop, 7113 right: thisRect.right - boundingRect.right - size.marginRight, 7114 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 7115 }; 7116 return offset; 7117}; 7118 7119// -------------------------- resize -------------------------- // 7120 7121// enable event handlers for listeners 7122// i.e. resize -> onresize 7123proto.handleEvent = utils.handleEvent; 7124 7125/** 7126 * Bind layout to window resizing 7127 */ 7128proto.bindResize = function() { 7129 window.addEventListener( 'resize', this ); 7130 this.isResizeBound = true; 7131}; 7132 7133/** 7134 * Unbind layout to window resizing 7135 */ 7136proto.unbindResize = function() { 7137 window.removeEventListener( 'resize', this ); 7138 this.isResizeBound = false; 7139}; 7140 7141proto.onresize = function() { 7142 this.resize(); 7143}; 7144 7145utils.debounceMethod( Outlayer, 'onresize', 100 ); 7146 7147proto.resize = function() { 7148 // don't trigger if size did not change 7149 // or if resize was unbound. See #9 7150 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 7151 return; 7152 } 7153 7154 this.layout(); 7155}; 7156 7157/** 7158 * check if layout is needed post layout 7159 * @returns Boolean 7160 */ 7161proto.needsResizeLayout = function() { 7162 var size = getSize( this.element ); 7163 // check that this.size and size are there 7164 // IE8 triggers resize on body size change, so they might not be 7165 var hasSizes = this.size && size; 7166 return hasSizes && size.innerWidth !== this.size.innerWidth; 7167}; 7168 7169// -------------------------- methods -------------------------- // 7170 7171/** 7172 * add items to Outlayer instance 7173 * @param {Array or NodeList or Element} elems 7174 * @returns {Array} items - Outlayer.Items 7175**/ 7176proto.addItems = function( elems ) { 7177 var items = this._itemize( elems ); 7178 // add items to collection 7179 if ( items.length ) { 7180 this.items = this.items.concat( items ); 7181 } 7182 return items; 7183}; 7184 7185/** 7186 * Layout newly-appended item elements 7187 * @param {Array or NodeList or Element} elems 7188 */ 7189proto.appended = function( elems ) { 7190 var items = this.addItems( elems ); 7191 if ( !items.length ) { 7192 return; 7193 } 7194 // layout and reveal just the new items 7195 this.layoutItems( items, true ); 7196 this.reveal( items ); 7197}; 7198 7199/** 7200 * Layout prepended elements 7201 * @param {Array or NodeList or Element} elems 7202 */ 7203proto.prepended = function( elems ) { 7204 var items = this._itemize( elems ); 7205 if ( !items.length ) { 7206 return; 7207 } 7208 // add items to beginning of collection 7209 var previousItems = this.items.slice(0); 7210 this.items = items.concat( previousItems ); 7211 // start new layout 7212 this._resetLayout(); 7213 this._manageStamps(); 7214 // layout new stuff without transition 7215 this.layoutItems( items, true ); 7216 this.reveal( items ); 7217 // layout previous items 7218 this.layoutItems( previousItems ); 7219}; 7220 7221/** 7222 * reveal a collection of items 7223 * @param {Array of Outlayer.Items} items 7224 */ 7225proto.reveal = function( items ) { 7226 this._emitCompleteOnItems( 'reveal', items ); 7227 if ( !items || !items.length ) { 7228 return; 7229 } 7230 var stagger = this.updateStagger(); 7231 items.forEach( function( item, i ) { 7232 item.stagger( i * stagger ); 7233 item.reveal(); 7234 }); 7235}; 7236 7237/** 7238 * hide a collection of items 7239 * @param {Array of Outlayer.Items} items 7240 */ 7241proto.hide = function( items ) { 7242 this._emitCompleteOnItems( 'hide', items ); 7243 if ( !items || !items.length ) { 7244 return; 7245 } 7246 var stagger = this.updateStagger(); 7247 items.forEach( function( item, i ) { 7248 item.stagger( i * stagger ); 7249 item.hide(); 7250 }); 7251}; 7252 7253/** 7254 * reveal item elements 7255 * @param {Array}, {Element}, {NodeList} items 7256 */ 7257proto.revealItemElements = function( elems ) { 7258 var items = this.getItems( elems ); 7259 this.reveal( items ); 7260}; 7261 7262/** 7263 * hide item elements 7264 * @param {Array}, {Element}, {NodeList} items 7265 */ 7266proto.hideItemElements = function( elems ) { 7267 var items = this.getItems( elems ); 7268 this.hide( items ); 7269}; 7270 7271/** 7272 * get Outlayer.Item, given an Element 7273 * @param {Element} elem 7274 * @param {Function} callback 7275 * @returns {Outlayer.Item} item 7276 */ 7277proto.getItem = function( elem ) { 7278 // loop through items to get the one that matches 7279 for ( var i=0; i < this.items.length; i++ ) { 7280 var item = this.items[i]; 7281 if ( item.element == elem ) { 7282 // return item 7283 return item; 7284 } 7285 } 7286}; 7287 7288/** 7289 * get collection of Outlayer.Items, given Elements 7290 * @param {Array} elems 7291 * @returns {Array} items - Outlayer.Items 7292 */ 7293proto.getItems = function( elems ) { 7294 elems = utils.makeArray( elems ); 7295 var items = []; 7296 elems.forEach( function( elem ) { 7297 var item = this.getItem( elem ); 7298 if ( item ) { 7299 items.push( item ); 7300 } 7301 }, this ); 7302 7303 return items; 7304}; 7305 7306/** 7307 * remove element(s) from instance and DOM 7308 * @param {Array or NodeList or Element} elems 7309 */ 7310proto.remove = function( elems ) { 7311 var removeItems = this.getItems( elems ); 7312 7313 this._emitCompleteOnItems( 'remove', removeItems ); 7314 7315 // bail if no items to remove 7316 if ( !removeItems || !removeItems.length ) { 7317 return; 7318 } 7319 7320 removeItems.forEach( function( item ) { 7321 item.remove(); 7322 // remove item from collection 7323 utils.removeFrom( this.items, item ); 7324 }, this ); 7325}; 7326 7327// ----- destroy ----- // 7328 7329// remove and disable Outlayer instance 7330proto.destroy = function() { 7331 // clean up dynamic styles 7332 var style = this.element.style; 7333 style.height = ''; 7334 style.position = ''; 7335 style.width = ''; 7336 // destroy items 7337 this.items.forEach( function( item ) { 7338 item.destroy(); 7339 }); 7340 7341 this.unbindResize(); 7342 7343 var id = this.element.outlayerGUID; 7344 delete instances[ id ]; // remove reference to instance by id 7345 delete this.element.outlayerGUID; 7346 // remove data for jQuery 7347 if ( jQuery ) { 7348 jQuery.removeData( this.element, this.constructor.namespace ); 7349 } 7350 7351}; 7352 7353// -------------------------- data -------------------------- // 7354 7355/** 7356 * get Outlayer instance from element 7357 * @param {Element} elem 7358 * @returns {Outlayer} 7359 */ 7360Outlayer.data = function( elem ) { 7361 elem = utils.getQueryElement( elem ); 7362 var id = elem && elem.outlayerGUID; 7363 return id && instances[ id ]; 7364}; 7365 7366 7367// -------------------------- create Outlayer class -------------------------- // 7368 7369/** 7370 * create a layout class 7371 * @param {String} namespace 7372 */ 7373Outlayer.create = function( namespace, options ) { 7374 // sub-class Outlayer 7375 var Layout = subclass( Outlayer ); 7376 // apply new options and compatOptions 7377 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 7378 utils.extend( Layout.defaults, options ); 7379 Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); 7380 7381 Layout.namespace = namespace; 7382 7383 Layout.data = Outlayer.data; 7384 7385 // sub-class Item 7386 Layout.Item = subclass( Item ); 7387 7388 // -------------------------- declarative -------------------------- // 7389 7390 utils.htmlInit( Layout, namespace ); 7391 7392 // -------------------------- jQuery bridge -------------------------- // 7393 7394 // make into jQuery plugin 7395 if ( jQuery && jQuery.bridget ) { 7396 jQuery.bridget( namespace, Layout ); 7397 } 7398 7399 return Layout; 7400}; 7401 7402function subclass( Parent ) { 7403 function SubClass() { 7404 Parent.apply( this, arguments ); 7405 } 7406 7407 SubClass.prototype = Object.create( Parent.prototype ); 7408 SubClass.prototype.constructor = SubClass; 7409 7410 return SubClass; 7411} 7412 7413// ----- helpers ----- // 7414 7415// how many milliseconds are in each unit 7416var msUnits = { 7417 ms: 1, 7418 s: 1000 7419}; 7420 7421// munge time-like parameter into millisecond number 7422// '0.4s' -> 40 7423function getMilliseconds( time ) { 7424 if ( typeof time == 'number' ) { 7425 return time; 7426 } 7427 var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); 7428 var num = matches && matches[1]; 7429 var unit = matches && matches[2]; 7430 if ( !num.length ) { 7431 return 0; 7432 } 7433 num = parseFloat( num ); 7434 var mult = msUnits[ unit ] || 1; 7435 return num * mult; 7436} 7437 7438// ----- fin ----- // 7439 7440// back in global 7441Outlayer.Item = Item; 7442 7443return Outlayer; 7444 7445})); 7446 7447/** 7448 * Isotope Item 7449**/ 7450 7451( function( window, factory ) { 7452 // universal module definition 7453 /* jshint strict: false */ /*globals define, module, require */ 7454 if ( typeof define == 'function' && define.amd ) { 7455 // AMD 7456 define( 'isotope-layout/js/item',[ 7457 'outlayer/outlayer' 7458 ], 7459 factory ); 7460 } else if ( typeof module == 'object' && module.exports ) { 7461 // CommonJS 7462 module.exports = factory( 7463 require('outlayer') 7464 ); 7465 } else { 7466 // browser global 7467 window.Isotope = window.Isotope || {}; 7468 window.Isotope.Item = factory( 7469 window.Outlayer 7470 ); 7471 } 7472 7473}( window, function factory( Outlayer ) { 7474'use strict'; 7475 7476// -------------------------- Item -------------------------- // 7477 7478// sub-class Outlayer Item 7479function Item() { 7480 Outlayer.Item.apply( this, arguments ); 7481} 7482 7483var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 7484 7485var _create = proto._create; 7486proto._create = function() { 7487 // assign id, used for original-order sorting 7488 this.id = this.layout.itemGUID++; 7489 _create.call( this ); 7490 this.sortData = {}; 7491}; 7492 7493proto.updateSortData = function() { 7494 if ( this.isIgnored ) { 7495 return; 7496 } 7497 // default sorters 7498 this.sortData.id = this.id; 7499 // for backward compatibility 7500 this.sortData['original-order'] = this.id; 7501 this.sortData.random = Math.random(); 7502 // go thru getSortData obj and apply the sorters 7503 var getSortData = this.layout.options.getSortData; 7504 var sorters = this.layout._sorters; 7505 for ( var key in getSortData ) { 7506 var sorter = sorters[ key ]; 7507 this.sortData[ key ] = sorter( this.element, this ); 7508 } 7509}; 7510 7511var _destroy = proto.destroy; 7512proto.destroy = function() { 7513 // call super 7514 _destroy.apply( this, arguments ); 7515 // reset display, #741 7516 this.css({ 7517 display: '' 7518 }); 7519}; 7520 7521return Item; 7522 7523})); 7524 7525/** 7526 * Isotope LayoutMode 7527 */ 7528 7529( function( window, factory ) { 7530 // universal module definition 7531 /* jshint strict: false */ /*globals define, module, require */ 7532 if ( typeof define == 'function' && define.amd ) { 7533 // AMD 7534 define( 'isotope-layout/js/layout-mode',[ 7535 'get-size/get-size', 7536 'outlayer/outlayer' 7537 ], 7538 factory ); 7539 } else if ( typeof module == 'object' && module.exports ) { 7540 // CommonJS 7541 module.exports = factory( 7542 require('get-size'), 7543 require('outlayer') 7544 ); 7545 } else { 7546 // browser global 7547 window.Isotope = window.Isotope || {}; 7548 window.Isotope.LayoutMode = factory( 7549 window.getSize, 7550 window.Outlayer 7551 ); 7552 } 7553 7554}( window, function factory( getSize, Outlayer ) { 7555 'use strict'; 7556 7557 // layout mode class 7558 function LayoutMode( isotope ) { 7559 this.isotope = isotope; 7560 // link properties 7561 if ( isotope ) { 7562 this.options = isotope.options[ this.namespace ]; 7563 this.element = isotope.element; 7564 this.items = isotope.filteredItems; 7565 this.size = isotope.size; 7566 } 7567 } 7568 7569 var proto = LayoutMode.prototype; 7570 7571 /** 7572 * some methods should just defer to default Outlayer method 7573 * and reference the Isotope instance as `this` 7574 **/ 7575 var facadeMethods = [ 7576 '_resetLayout', 7577 '_getItemLayoutPosition', 7578 '_manageStamp', 7579 '_getContainerSize', 7580 '_getElementOffset', 7581 'needsResizeLayout', 7582 '_getOption' 7583 ]; 7584 7585 facadeMethods.forEach( function( methodName ) { 7586 proto[ methodName ] = function() { 7587 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 7588 }; 7589 }); 7590 7591 // ----- ----- // 7592 7593 // for horizontal layout modes, check vertical size 7594 proto.needsVerticalResizeLayout = function() { 7595 // don't trigger if size did not change 7596 var size = getSize( this.isotope.element ); 7597 // check that this.size and size are there 7598 // IE8 triggers resize on body size change, so they might not be 7599 var hasSizes = this.isotope.size && size; 7600 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 7601 }; 7602 7603 // ----- measurements ----- // 7604 7605 proto._getMeasurement = function() { 7606 this.isotope._getMeasurement.apply( this, arguments ); 7607 }; 7608 7609 proto.getColumnWidth = function() { 7610 this.getSegmentSize( 'column', 'Width' ); 7611 }; 7612 7613 proto.getRowHeight = function() { 7614 this.getSegmentSize( 'row', 'Height' ); 7615 }; 7616 7617 /** 7618 * get columnWidth or rowHeight 7619 * segment: 'column' or 'row' 7620 * size 'Width' or 'Height' 7621 **/ 7622 proto.getSegmentSize = function( segment, size ) { 7623 var segmentName = segment + size; 7624 var outerSize = 'outer' + size; 7625 // columnWidth / outerWidth // rowHeight / outerHeight 7626 this._getMeasurement( segmentName, outerSize ); 7627 // got rowHeight or columnWidth, we can chill 7628 if ( this[ segmentName ] ) { 7629 return; 7630 } 7631 // fall back to item of first element 7632 var firstItemSize = this.getFirstItemSize(); 7633 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 7634 // or size of container 7635 this.isotope.size[ 'inner' + size ]; 7636 }; 7637 7638 proto.getFirstItemSize = function() { 7639 var firstItem = this.isotope.filteredItems[0]; 7640 return firstItem && firstItem.element && getSize( firstItem.element ); 7641 }; 7642 7643 // ----- methods that should reference isotope ----- // 7644 7645 proto.layout = function() { 7646 this.isotope.layout.apply( this.isotope, arguments ); 7647 }; 7648 7649 proto.getSize = function() { 7650 this.isotope.getSize(); 7651 this.size = this.isotope.size; 7652 }; 7653 7654 // -------------------------- create -------------------------- // 7655 7656 LayoutMode.modes = {}; 7657 7658 LayoutMode.create = function( namespace, options ) { 7659 7660 function Mode() { 7661 LayoutMode.apply( this, arguments ); 7662 } 7663 7664 Mode.prototype = Object.create( proto ); 7665 Mode.prototype.constructor = Mode; 7666 7667 // default options 7668 if ( options ) { 7669 Mode.options = options; 7670 } 7671 7672 Mode.prototype.namespace = namespace; 7673 // register in Isotope 7674 LayoutMode.modes[ namespace ] = Mode; 7675 7676 return Mode; 7677 }; 7678 7679 return LayoutMode; 7680 7681})); 7682 7683/*! 7684 * Masonry v4.2.1 7685 * Cascading grid layout library 7686 * https://masonry.desandro.com 7687 * MIT License 7688 * by David DeSandro 7689 */ 7690 7691( function( window, factory ) { 7692 // universal module definition 7693 /* jshint strict: false */ /*globals define, module, require */ 7694 if ( typeof define == 'function' && define.amd ) { 7695 // AMD 7696 define( 'masonry-layout/masonry',[ 7697 'outlayer/outlayer', 7698 'get-size/get-size' 7699 ], 7700 factory ); 7701 } else if ( typeof module == 'object' && module.exports ) { 7702 // CommonJS 7703 module.exports = factory( 7704 require('outlayer'), 7705 require('get-size') 7706 ); 7707 } else { 7708 // browser global 7709 window.Masonry = factory( 7710 window.Outlayer, 7711 window.getSize 7712 ); 7713 } 7714 7715}( window, function factory( Outlayer, getSize ) { 7716 7717 7718 7719// -------------------------- masonryDefinition -------------------------- // 7720 7721 // create an Outlayer layout class 7722 var Masonry = Outlayer.create('masonry'); 7723 // isFitWidth -> fitWidth 7724 Masonry.compatOptions.fitWidth = 'isFitWidth'; 7725 7726 var proto = Masonry.prototype; 7727 7728 proto._resetLayout = function() { 7729 this.getSize(); 7730 this._getMeasurement( 'columnWidth', 'outerWidth' ); 7731 this._getMeasurement( 'gutter', 'outerWidth' ); 7732 this.measureColumns(); 7733 7734 // reset column Y 7735 this.colYs = []; 7736 for ( var i=0; i < this.cols; i++ ) { 7737 this.colYs.push( 0 ); 7738 } 7739 7740 this.maxY = 0; 7741 this.horizontalColIndex = 0; 7742 }; 7743 7744 proto.measureColumns = function() { 7745 this.getContainerWidth(); 7746 // if columnWidth is 0, default to outerWidth of first item 7747 if ( !this.columnWidth ) { 7748 var firstItem = this.items[0]; 7749 var firstItemElem = firstItem && firstItem.element; 7750 // columnWidth fall back to item of first element 7751 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 7752 // if first elem has no width, default to size of container 7753 this.containerWidth; 7754 } 7755 7756 var columnWidth = this.columnWidth += this.gutter; 7757 7758 // calculate columns 7759 var containerWidth = this.containerWidth + this.gutter; 7760 var cols = containerWidth / columnWidth; 7761 // fix rounding errors, typically with gutters 7762 var excess = columnWidth - containerWidth % columnWidth; 7763 // if overshoot is less than a pixel, round up, otherwise floor it 7764 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 7765 cols = Math[ mathMethod ]( cols ); 7766 this.cols = Math.max( cols, 1 ); 7767 }; 7768 7769 proto.getContainerWidth = function() { 7770 // container is parent if fit width 7771 var isFitWidth = this._getOption('fitWidth'); 7772 var container = isFitWidth ? this.element.parentNode : this.element; 7773 // check that this.size and size are there 7774 // IE8 triggers resize on body size change, so they might not be 7775 var size = getSize( container ); 7776 this.containerWidth = size && size.innerWidth; 7777 }; 7778 7779 proto._getItemLayoutPosition = function( item ) { 7780 item.getSize(); 7781 // how many columns does this brick span 7782 var remainder = item.size.outerWidth % this.columnWidth; 7783 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 7784 // round if off by 1 pixel, otherwise use ceil 7785 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 7786 colSpan = Math.min( colSpan, this.cols ); 7787 // use horizontal or top column position 7788 var colPosMethod = this.options.horizontalOrder ? 7789 '_getHorizontalColPosition' : '_getTopColPosition'; 7790 var colPosition = this[ colPosMethod ]( colSpan, item ); 7791 // position the brick 7792 var position = { 7793 x: this.columnWidth * colPosition.col, 7794 y: colPosition.y 7795 }; 7796 // apply setHeight to necessary columns 7797 var setHeight = colPosition.y + item.size.outerHeight; 7798 var setMax = colSpan + colPosition.col; 7799 for ( var i = colPosition.col; i < setMax; i++ ) { 7800 this.colYs[i] = setHeight; 7801 } 7802 7803 return position; 7804 }; 7805 7806 proto._getTopColPosition = function( colSpan ) { 7807 var colGroup = this._getTopColGroup( colSpan ); 7808 // get the minimum Y value from the columns 7809 var minimumY = Math.min.apply( Math, colGroup ); 7810 7811 return { 7812 col: colGroup.indexOf( minimumY ), 7813 y: minimumY, 7814 }; 7815 }; 7816 7817 /** 7818 * @param {Number} colSpan - number of columns the element spans 7819 * @returns {Array} colGroup 7820 */ 7821 proto._getTopColGroup = function( colSpan ) { 7822 if ( colSpan < 2 ) { 7823 // if brick spans only one column, use all the column Ys 7824 return this.colYs; 7825 } 7826 7827 var colGroup = []; 7828 // how many different places could this brick fit horizontally 7829 var groupCount = this.cols + 1 - colSpan; 7830 // for each group potential horizontal position 7831 for ( var i = 0; i < groupCount; i++ ) { 7832 colGroup[i] = this._getColGroupY( i, colSpan ); 7833 } 7834 return colGroup; 7835 }; 7836 7837 proto._getColGroupY = function( col, colSpan ) { 7838 if ( colSpan < 2 ) { 7839 return this.colYs[ col ]; 7840 } 7841 // make an array of colY values for that one group 7842 var groupColYs = this.colYs.slice( col, col + colSpan ); 7843 // and get the max value of the array 7844 return Math.max.apply( Math, groupColYs ); 7845 }; 7846 7847 // get column position based on horizontal index. #873 7848 proto._getHorizontalColPosition = function( colSpan, item ) { 7849 var col = this.horizontalColIndex % this.cols; 7850 var isOver = colSpan > 1 && col + colSpan > this.cols; 7851 // shift to next row if item can't fit on current row 7852 col = isOver ? 0 : col; 7853 // don't let zero-size items take up space 7854 var hasSize = item.size.outerWidth && item.size.outerHeight; 7855 this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex; 7856 7857 return { 7858 col: col, 7859 y: this._getColGroupY( col, colSpan ), 7860 }; 7861 }; 7862 7863 proto._manageStamp = function( stamp ) { 7864 var stampSize = getSize( stamp ); 7865 var offset = this._getElementOffset( stamp ); 7866 // get the columns that this stamp affects 7867 var isOriginLeft = this._getOption('originLeft'); 7868 var firstX = isOriginLeft ? offset.left : offset.right; 7869 var lastX = firstX + stampSize.outerWidth; 7870 var firstCol = Math.floor( firstX / this.columnWidth ); 7871 firstCol = Math.max( 0, firstCol ); 7872 var lastCol = Math.floor( lastX / this.columnWidth ); 7873 // lastCol should not go over if multiple of columnWidth #425 7874 lastCol -= lastX % this.columnWidth ? 0 : 1; 7875 lastCol = Math.min( this.cols - 1, lastCol ); 7876 // set colYs to bottom of the stamp 7877 7878 var isOriginTop = this._getOption('originTop'); 7879 var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + 7880 stampSize.outerHeight; 7881 for ( var i = firstCol; i <= lastCol; i++ ) { 7882 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 7883 } 7884 }; 7885 7886 proto._getContainerSize = function() { 7887 this.maxY = Math.max.apply( Math, this.colYs ); 7888 var size = { 7889 height: this.maxY 7890 }; 7891 7892 if ( this._getOption('fitWidth') ) { 7893 size.width = this._getContainerFitWidth(); 7894 } 7895 7896 return size; 7897 }; 7898 7899 proto._getContainerFitWidth = function() { 7900 var unusedCols = 0; 7901 // count unused columns 7902 var i = this.cols; 7903 while ( --i ) { 7904 if ( this.colYs[i] !== 0 ) { 7905 break; 7906 } 7907 unusedCols++; 7908 } 7909 // fit container to columns that have been used 7910 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 7911 }; 7912 7913 proto.needsResizeLayout = function() { 7914 var previousWidth = this.containerWidth; 7915 this.getContainerWidth(); 7916 return previousWidth != this.containerWidth; 7917 }; 7918 7919 return Masonry; 7920 7921})); 7922 7923/*! 7924 * Masonry layout mode 7925 * sub-classes Masonry 7926 * https://masonry.desandro.com 7927 */ 7928 7929( function( window, factory ) { 7930 // universal module definition 7931 /* jshint strict: false */ /*globals define, module, require */ 7932 if ( typeof define == 'function' && define.amd ) { 7933 // AMD 7934 define( 'isotope-layout/js/layout-modes/masonry',[ 7935 '../layout-mode', 7936 'masonry-layout/masonry' 7937 ], 7938 factory ); 7939 } else if ( typeof module == 'object' && module.exports ) { 7940 // CommonJS 7941 module.exports = factory( 7942 require('../layout-mode'), 7943 require('masonry-layout') 7944 ); 7945 } else { 7946 // browser global 7947 factory( 7948 window.Isotope.LayoutMode, 7949 window.Masonry 7950 ); 7951 } 7952 7953}( window, function factory( LayoutMode, Masonry ) { 7954'use strict'; 7955 7956// -------------------------- masonryDefinition -------------------------- // 7957 7958 // create an Outlayer layout class 7959 var MasonryMode = LayoutMode.create('masonry'); 7960 7961 var proto = MasonryMode.prototype; 7962 7963 var keepModeMethods = { 7964 _getElementOffset: true, 7965 layout: true, 7966 _getMeasurement: true 7967 }; 7968 7969 // inherit Masonry prototype 7970 for ( var method in Masonry.prototype ) { 7971 // do not inherit mode methods 7972 if ( !keepModeMethods[ method ] ) { 7973 proto[ method ] = Masonry.prototype[ method ]; 7974 } 7975 } 7976 7977 var measureColumns = proto.measureColumns; 7978 proto.measureColumns = function() { 7979 // set items, used if measuring first item 7980 this.items = this.isotope.filteredItems; 7981 measureColumns.call( this ); 7982 }; 7983 7984 // point to mode options for fitWidth 7985 var _getOption = proto._getOption; 7986 proto._getOption = function( option ) { 7987 if ( option == 'fitWidth' ) { 7988 return this.options.isFitWidth !== undefined ? 7989 this.options.isFitWidth : this.options.fitWidth; 7990 } 7991 return _getOption.apply( this.isotope, arguments ); 7992 }; 7993 7994 return MasonryMode; 7995 7996})); 7997 7998/** 7999 * fitRows layout mode 8000 */ 8001 8002( function( window, factory ) { 8003 // universal module definition 8004 /* jshint strict: false */ /*globals define, module, require */ 8005 if ( typeof define == 'function' && define.amd ) { 8006 // AMD 8007 define( 'isotope-layout/js/layout-modes/fit-rows',[ 8008 '../layout-mode' 8009 ], 8010 factory ); 8011 } else if ( typeof exports == 'object' ) { 8012 // CommonJS 8013 module.exports = factory( 8014 require('../layout-mode') 8015 ); 8016 } else { 8017 // browser global 8018 factory( 8019 window.Isotope.LayoutMode 8020 ); 8021 } 8022 8023}( window, function factory( LayoutMode ) { 8024'use strict'; 8025 8026var FitRows = LayoutMode.create('fitRows'); 8027 8028var proto = FitRows.prototype; 8029 8030proto._resetLayout = function() { 8031 this.x = 0; 8032 this.y = 0; 8033 this.maxY = 0; 8034 this._getMeasurement( 'gutter', 'outerWidth' ); 8035}; 8036 8037proto._getItemLayoutPosition = function( item ) { 8038 item.getSize(); 8039 8040 var itemWidth = item.size.outerWidth + this.gutter; 8041 // if this element cannot fit in the current row 8042 var containerWidth = this.isotope.size.innerWidth + this.gutter; 8043 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 8044 this.x = 0; 8045 this.y = this.maxY; 8046 } 8047 8048 var position = { 8049 x: this.x, 8050 y: this.y 8051 }; 8052 8053 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 8054 this.x += itemWidth; 8055 8056 return position; 8057}; 8058 8059proto._getContainerSize = function() { 8060 return { height: this.maxY }; 8061}; 8062 8063return FitRows; 8064 8065})); 8066 8067/** 8068 * vertical layout mode 8069 */ 8070 8071( function( window, factory ) { 8072 // universal module definition 8073 /* jshint strict: false */ /*globals define, module, require */ 8074 if ( typeof define == 'function' && define.amd ) { 8075 // AMD 8076 define( 'isotope-layout/js/layout-modes/vertical',[ 8077 '../layout-mode' 8078 ], 8079 factory ); 8080 } else if ( typeof module == 'object' && module.exports ) { 8081 // CommonJS 8082 module.exports = factory( 8083 require('../layout-mode') 8084 ); 8085 } else { 8086 // browser global 8087 factory( 8088 window.Isotope.LayoutMode 8089 ); 8090 } 8091 8092}( window, function factory( LayoutMode ) { 8093'use strict'; 8094 8095var Vertical = LayoutMode.create( 'vertical', { 8096 horizontalAlignment: 0 8097}); 8098 8099var proto = Vertical.prototype; 8100 8101proto._resetLayout = function() { 8102 this.y = 0; 8103}; 8104 8105proto._getItemLayoutPosition = function( item ) { 8106 item.getSize(); 8107 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 8108 this.options.horizontalAlignment; 8109 var y = this.y; 8110 this.y += item.size.outerHeight; 8111 return { x: x, y: y }; 8112}; 8113 8114proto._getContainerSize = function() { 8115 return { height: this.y }; 8116}; 8117 8118return Vertical; 8119 8120})); 8121 8122/*! 8123 * Isotope v3.0.6 8124 * 8125 * Licensed GPLv3 for open source use 8126 * or Isotope Commercial License for commercial use 8127 * 8128 * https://isotope.metafizzy.co 8129 * Copyright 2010-2018 Metafizzy 8130 */ 8131 8132( function( window, factory ) { 8133 // universal module definition 8134 /* jshint strict: false */ /*globals define, module, require */ 8135 if ( typeof define == 'function' && define.amd ) { 8136 // AMD 8137 define( [ 8138 'outlayer/outlayer', 8139 'get-size/get-size', 8140 'desandro-matches-selector/matches-selector', 8141 'fizzy-ui-utils/utils', 8142 'isotope-layout/js/item', 8143 'isotope-layout/js/layout-mode', 8144 // include default layout modes 8145 'isotope-layout/js/layout-modes/masonry', 8146 'isotope-layout/js/layout-modes/fit-rows', 8147 'isotope-layout/js/layout-modes/vertical' 8148 ], 8149 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 8150 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 8151 }); 8152 } else if ( typeof module == 'object' && module.exports ) { 8153 // CommonJS 8154 module.exports = factory( 8155 window, 8156 require('outlayer'), 8157 require('get-size'), 8158 require('desandro-matches-selector'), 8159 require('fizzy-ui-utils'), 8160 require('isotope-layout/js/item'), 8161 require('isotope-layout/js/layout-mode'), 8162 // include default layout modes 8163 require('isotope-layout/js/layout-modes/masonry'), 8164 require('isotope-layout/js/layout-modes/fit-rows'), 8165 require('isotope-layout/js/layout-modes/vertical') 8166 ); 8167 } else { 8168 // browser global 8169 window.Isotope = factory( 8170 window, 8171 window.Outlayer, 8172 window.getSize, 8173 window.matchesSelector, 8174 window.fizzyUIUtils, 8175 window.Isotope.Item, 8176 window.Isotope.LayoutMode 8177 ); 8178 } 8179 8180}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 8181 Item, LayoutMode ) { 8182 8183 8184 8185// -------------------------- vars -------------------------- // 8186 8187var jQuery = window.jQuery; 8188 8189// -------------------------- helpers -------------------------- // 8190 8191var trim = String.prototype.trim ? 8192 function( str ) { 8193 return str.trim(); 8194 } : 8195 function( str ) { 8196 return str.replace( /^\s+|\s+$/g, '' ); 8197 }; 8198 8199// -------------------------- isotopeDefinition -------------------------- // 8200 8201 // create an Outlayer layout class 8202 var Isotope = Outlayer.create( 'isotope', { 8203 layoutMode: 'masonry', 8204 isJQueryFiltering: true, 8205 sortAscending: true 8206 }); 8207 8208 Isotope.Item = Item; 8209 Isotope.LayoutMode = LayoutMode; 8210 8211 var proto = Isotope.prototype; 8212 8213 proto._create = function() { 8214 this.itemGUID = 0; 8215 // functions that sort items 8216 this._sorters = {}; 8217 this._getSorters(); 8218 // call super 8219 Outlayer.prototype._create.call( this ); 8220 8221 // create layout modes 8222 this.modes = {}; 8223 // start filteredItems with all items 8224 this.filteredItems = this.items; 8225 // keep of track of sortBys 8226 this.sortHistory = [ 'original-order' ]; 8227 // create from registered layout modes 8228 for ( var name in LayoutMode.modes ) { 8229 this._initLayoutMode( name ); 8230 } 8231 }; 8232 8233 proto.reloadItems = function() { 8234 // reset item ID counter 8235 this.itemGUID = 0; 8236 // call super 8237 Outlayer.prototype.reloadItems.call( this ); 8238 }; 8239 8240 proto._itemize = function() { 8241 var items = Outlayer.prototype._itemize.apply( this, arguments ); 8242 // assign ID for original-order 8243 for ( var i=0; i < items.length; i++ ) { 8244 var item = items[i]; 8245 item.id = this.itemGUID++; 8246 } 8247 this._updateItemsSortData( items ); 8248 return items; 8249 }; 8250 8251 8252 // -------------------------- layout -------------------------- // 8253 8254 proto._initLayoutMode = function( name ) { 8255 var Mode = LayoutMode.modes[ name ]; 8256 // set mode options 8257 // HACK extend initial options, back-fill in default options 8258 var initialOpts = this.options[ name ] || {}; 8259 this.options[ name ] = Mode.options ? 8260 utils.extend( Mode.options, initialOpts ) : initialOpts; 8261 // init layout mode instance 8262 this.modes[ name ] = new Mode( this ); 8263 }; 8264 8265 8266 proto.layout = function() { 8267 // if first time doing layout, do all magic 8268 if ( !this._isLayoutInited && this._getOption('initLayout') ) { 8269 this.arrange(); 8270 return; 8271 } 8272 this._layout(); 8273 }; 8274 8275 // private method to be used in layout() & magic() 8276 proto._layout = function() { 8277 // don't animate first layout 8278 var isInstant = this._getIsInstant(); 8279 // layout flow 8280 this._resetLayout(); 8281 this._manageStamps(); 8282 this.layoutItems( this.filteredItems, isInstant ); 8283 8284 // flag for initalized 8285 this._isLayoutInited = true; 8286 }; 8287 8288 // filter + sort + layout 8289 proto.arrange = function( opts ) { 8290 // set any options pass 8291 this.option( opts ); 8292 this._getIsInstant(); 8293 // filter, sort, and layout 8294 8295 // filter 8296 var filtered = this._filter( this.items ); 8297 this.filteredItems = filtered.matches; 8298 8299 this._bindArrangeComplete(); 8300 8301 if ( this._isInstant ) { 8302 this._noTransition( this._hideReveal, [ filtered ] ); 8303 } else { 8304 this._hideReveal( filtered ); 8305 } 8306 8307 this._sort(); 8308 this._layout(); 8309 }; 8310 // alias to _init for main plugin method 8311 proto._init = proto.arrange; 8312 8313 proto._hideReveal = function( filtered ) { 8314 this.reveal( filtered.needReveal ); 8315 this.hide( filtered.needHide ); 8316 }; 8317 8318 // HACK 8319 // Don't animate/transition first layout 8320 // Or don't animate/transition other layouts 8321 proto._getIsInstant = function() { 8322 var isLayoutInstant = this._getOption('layoutInstant'); 8323 var isInstant = isLayoutInstant !== undefined ? isLayoutInstant : 8324 !this._isLayoutInited; 8325 this._isInstant = isInstant; 8326 return isInstant; 8327 }; 8328 8329 // listen for layoutComplete, hideComplete and revealComplete 8330 // to trigger arrangeComplete 8331 proto._bindArrangeComplete = function() { 8332 // listen for 3 events to trigger arrangeComplete 8333 var isLayoutComplete, isHideComplete, isRevealComplete; 8334 var _this = this; 8335 function arrangeParallelCallback() { 8336 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 8337 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 8338 } 8339 } 8340 this.once( 'layoutComplete', function() { 8341 isLayoutComplete = true; 8342 arrangeParallelCallback(); 8343 }); 8344 this.once( 'hideComplete', function() { 8345 isHideComplete = true; 8346 arrangeParallelCallback(); 8347 }); 8348 this.once( 'revealComplete', function() { 8349 isRevealComplete = true; 8350 arrangeParallelCallback(); 8351 }); 8352 }; 8353 8354 // -------------------------- filter -------------------------- // 8355 8356 proto._filter = function( items ) { 8357 var filter = this.options.filter; 8358 filter = filter || '*'; 8359 var matches = []; 8360 var hiddenMatched = []; 8361 var visibleUnmatched = []; 8362 8363 var test = this._getFilterTest( filter ); 8364 8365 // test each item 8366 for ( var i=0; i < items.length; i++ ) { 8367 var item = items[i]; 8368 if ( item.isIgnored ) { 8369 continue; 8370 } 8371 // add item to either matched or unmatched group 8372 var isMatched = test( item ); 8373 // item.isFilterMatched = isMatched; 8374 // add to matches if its a match 8375 if ( isMatched ) { 8376 matches.push( item ); 8377 } 8378 // add to additional group if item needs to be hidden or revealed 8379 if ( isMatched && item.isHidden ) { 8380 hiddenMatched.push( item ); 8381 } else if ( !isMatched && !item.isHidden ) { 8382 visibleUnmatched.push( item ); 8383 } 8384 } 8385 8386 // return collections of items to be manipulated 8387 return { 8388 matches: matches, 8389 needReveal: hiddenMatched, 8390 needHide: visibleUnmatched 8391 }; 8392 }; 8393 8394 // get a jQuery, function, or a matchesSelector test given the filter 8395 proto._getFilterTest = function( filter ) { 8396 if ( jQuery && this.options.isJQueryFiltering ) { 8397 // use jQuery 8398 return function( item ) { 8399 return jQuery( item.element ).is( filter ); 8400 }; 8401 } 8402 if ( typeof filter == 'function' ) { 8403 // use filter as function 8404 return function( item ) { 8405 return filter( item.element ); 8406 }; 8407 } 8408 // default, use filter as selector string 8409 return function( item ) { 8410 return matchesSelector( item.element, filter ); 8411 }; 8412 }; 8413 8414 // -------------------------- sorting -------------------------- // 8415 8416 /** 8417 * @params {Array} elems 8418 * @public 8419 */ 8420 proto.updateSortData = function( elems ) { 8421 // get items 8422 var items; 8423 if ( elems ) { 8424 elems = utils.makeArray( elems ); 8425 items = this.getItems( elems ); 8426 } else { 8427 // update all items if no elems provided 8428 items = this.items; 8429 } 8430 8431 this._getSorters(); 8432 this._updateItemsSortData( items ); 8433 }; 8434 8435 proto._getSorters = function() { 8436 var getSortData = this.options.getSortData; 8437 for ( var key in getSortData ) { 8438 var sorter = getSortData[ key ]; 8439 this._sorters[ key ] = mungeSorter( sorter ); 8440 } 8441 }; 8442 8443 /** 8444 * @params {Array} items - of Isotope.Items 8445 * @private 8446 */ 8447 proto._updateItemsSortData = function( items ) { 8448 // do not update if no items 8449 var len = items && items.length; 8450 8451 for ( var i=0; len && i < len; i++ ) { 8452 var item = items[i]; 8453 item.updateSortData(); 8454 } 8455 }; 8456 8457 // ----- munge sorter ----- // 8458 8459 // encapsulate this, as we just need mungeSorter 8460 // other functions in here are just for munging 8461 var mungeSorter = ( function() { 8462 // add a magic layer to sorters for convienent shorthands 8463 // `.foo-bar` will use the text of .foo-bar querySelector 8464 // `[foo-bar]` will use attribute 8465 // you can also add parser 8466 // `.foo-bar parseInt` will parse that as a number 8467 function mungeSorter( sorter ) { 8468 // if not a string, return function or whatever it is 8469 if ( typeof sorter != 'string' ) { 8470 return sorter; 8471 } 8472 // parse the sorter string 8473 var args = trim( sorter ).split(' '); 8474 var query = args[0]; 8475 // check if query looks like [an-attribute] 8476 var attrMatch = query.match( /^\[(.+)\]$/ ); 8477 var attr = attrMatch && attrMatch[1]; 8478 var getValue = getValueGetter( attr, query ); 8479 // use second argument as a parser 8480 var parser = Isotope.sortDataParsers[ args[1] ]; 8481 // parse the value, if there was a parser 8482 sorter = parser ? function( elem ) { 8483 return elem && parser( getValue( elem ) ); 8484 } : 8485 // otherwise just return value 8486 function( elem ) { 8487 return elem && getValue( elem ); 8488 }; 8489 8490 return sorter; 8491 } 8492 8493 // get an attribute getter, or get text of the querySelector 8494 function getValueGetter( attr, query ) { 8495 // if query looks like [foo-bar], get attribute 8496 if ( attr ) { 8497 return function getAttribute( elem ) { 8498 return elem.getAttribute( attr ); 8499 }; 8500 } 8501 8502 // otherwise, assume its a querySelector, and get its text 8503 return function getChildText( elem ) { 8504 var child = elem.querySelector( query ); 8505 return child && child.textContent; 8506 }; 8507 } 8508 8509 return mungeSorter; 8510 })(); 8511 8512 // parsers used in getSortData shortcut strings 8513 Isotope.sortDataParsers = { 8514 'parseInt': function( val ) { 8515 return parseInt( val, 10 ); 8516 }, 8517 'parseFloat': function( val ) { 8518 return parseFloat( val ); 8519 } 8520 }; 8521 8522 // ----- sort method ----- // 8523 8524 // sort filteredItem order 8525 proto._sort = function() { 8526 if ( !this.options.sortBy ) { 8527 return; 8528 } 8529 // keep track of sortBy History 8530 var sortBys = utils.makeArray( this.options.sortBy ); 8531 if ( !this._getIsSameSortBy( sortBys ) ) { 8532 // concat all sortBy and sortHistory, add to front, oldest goes in last 8533 this.sortHistory = sortBys.concat( this.sortHistory ); 8534 } 8535 // sort magic 8536 var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending ); 8537 this.filteredItems.sort( itemSorter ); 8538 }; 8539 8540 // check if sortBys is same as start of sortHistory 8541 proto._getIsSameSortBy = function( sortBys ) { 8542 for ( var i=0; i < sortBys.length; i++ ) { 8543 if ( sortBys[i] != this.sortHistory[i] ) { 8544 return false; 8545 } 8546 } 8547 return true; 8548 }; 8549 8550 // returns a function used for sorting 8551 function getItemSorter( sortBys, sortAsc ) { 8552 return function sorter( itemA, itemB ) { 8553 // cycle through all sortKeys 8554 for ( var i = 0; i < sortBys.length; i++ ) { 8555 var sortBy = sortBys[i]; 8556 var a = itemA.sortData[ sortBy ]; 8557 var b = itemB.sortData[ sortBy ]; 8558 if ( a > b || a < b ) { 8559 // if sortAsc is an object, use the value given the sortBy key 8560 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 8561 var direction = isAscending ? 1 : -1; 8562 return ( a > b ? 1 : -1 ) * direction; 8563 } 8564 } 8565 return 0; 8566 }; 8567 } 8568 8569 // -------------------------- methods -------------------------- // 8570 8571 // get layout mode 8572 proto._mode = function() { 8573 var layoutMode = this.options.layoutMode; 8574 var mode = this.modes[ layoutMode ]; 8575 if ( !mode ) { 8576 // TODO console.error 8577 throw new Error( 'No layout mode: ' + layoutMode ); 8578 } 8579 // HACK sync mode's options 8580 // any options set after init for layout mode need to be synced 8581 mode.options = this.options[ layoutMode ]; 8582 return mode; 8583 }; 8584 8585 proto._resetLayout = function() { 8586 // trigger original reset layout 8587 Outlayer.prototype._resetLayout.call( this ); 8588 this._mode()._resetLayout(); 8589 }; 8590 8591 proto._getItemLayoutPosition = function( item ) { 8592 return this._mode()._getItemLayoutPosition( item ); 8593 }; 8594 8595 proto._manageStamp = function( stamp ) { 8596 this._mode()._manageStamp( stamp ); 8597 }; 8598 8599 proto._getContainerSize = function() { 8600 return this._mode()._getContainerSize(); 8601 }; 8602 8603 proto.needsResizeLayout = function() { 8604 return this._mode().needsResizeLayout(); 8605 }; 8606 8607 // -------------------------- adding & removing -------------------------- // 8608 8609 // HEADS UP overwrites default Outlayer appended 8610 proto.appended = function( elems ) { 8611 var items = this.addItems( elems ); 8612 if ( !items.length ) { 8613 return; 8614 } 8615 // filter, layout, reveal new items 8616 var filteredItems = this._filterRevealAdded( items ); 8617 // add to filteredItems 8618 this.filteredItems = this.filteredItems.concat( filteredItems ); 8619 }; 8620 8621 // HEADS UP overwrites default Outlayer prepended 8622 proto.prepended = function( elems ) { 8623 var items = this._itemize( elems ); 8624 if ( !items.length ) { 8625 return; 8626 } 8627 // start new layout 8628 this._resetLayout(); 8629 this._manageStamps(); 8630 // filter, layout, reveal new items 8631 var filteredItems = this._filterRevealAdded( items ); 8632 // layout previous items 8633 this.layoutItems( this.filteredItems ); 8634 // add to items and filteredItems 8635 this.filteredItems = filteredItems.concat( this.filteredItems ); 8636 this.items = items.concat( this.items ); 8637 }; 8638 8639 proto._filterRevealAdded = function( items ) { 8640 var filtered = this._filter( items ); 8641 this.hide( filtered.needHide ); 8642 // reveal all new items 8643 this.reveal( filtered.matches ); 8644 // layout new items, no transition 8645 this.layoutItems( filtered.matches, true ); 8646 return filtered.matches; 8647 }; 8648 8649 /** 8650 * Filter, sort, and layout newly-appended item elements 8651 * @param {Array or NodeList or Element} elems 8652 */ 8653 proto.insert = function( elems ) { 8654 var items = this.addItems( elems ); 8655 if ( !items.length ) { 8656 return; 8657 } 8658 // append item elements 8659 var i, item; 8660 var len = items.length; 8661 for ( i=0; i < len; i++ ) { 8662 item = items[i]; 8663 this.element.appendChild( item.element ); 8664 } 8665 // filter new stuff 8666 var filteredInsertItems = this._filter( items ).matches; 8667 // set flag 8668 for ( i=0; i < len; i++ ) { 8669 items[i].isLayoutInstant = true; 8670 } 8671 this.arrange(); 8672 // reset flag 8673 for ( i=0; i < len; i++ ) { 8674 delete items[i].isLayoutInstant; 8675 } 8676 this.reveal( filteredInsertItems ); 8677 }; 8678 8679 var _remove = proto.remove; 8680 proto.remove = function( elems ) { 8681 elems = utils.makeArray( elems ); 8682 var removeItems = this.getItems( elems ); 8683 // do regular thing 8684 _remove.call( this, elems ); 8685 // bail if no items to remove 8686 var len = removeItems && removeItems.length; 8687 // remove elems from filteredItems 8688 for ( var i=0; len && i < len; i++ ) { 8689 var item = removeItems[i]; 8690 // remove item from collection 8691 utils.removeFrom( this.filteredItems, item ); 8692 } 8693 }; 8694 8695 proto.shuffle = function() { 8696 // update random sortData 8697 for ( var i=0; i < this.items.length; i++ ) { 8698 var item = this.items[i]; 8699 item.sortData.random = Math.random(); 8700 } 8701 this.options.sortBy = 'random'; 8702 this._sort(); 8703 this._layout(); 8704 }; 8705 8706 /** 8707 * trigger fn without transition 8708 * kind of hacky to have this in the first place 8709 * @param {Function} fn 8710 * @param {Array} args 8711 * @returns ret 8712 * @private 8713 */ 8714 proto._noTransition = function( fn, args ) { 8715 // save transitionDuration before disabling 8716 var transitionDuration = this.options.transitionDuration; 8717 // disable transition 8718 this.options.transitionDuration = 0; 8719 // do it 8720 var returnValue = fn.apply( this, args ); 8721 // re-enable transition for reveal 8722 this.options.transitionDuration = transitionDuration; 8723 return returnValue; 8724 }; 8725 8726 // ----- helper methods ----- // 8727 8728 /** 8729 * getter method for getting filtered item elements 8730 * @returns {Array} elems - collection of item elements 8731 */ 8732 proto.getFilteredItemElements = function() { 8733 return this.filteredItems.map( function( item ) { 8734 return item.element; 8735 }); 8736 }; 8737 8738 // ----- ----- // 8739 8740 return Isotope; 8741 8742})); 8743
8744/*! 8745 * Packery layout mode PACKAGED v2.0.1 8746 * sub-classes Packery 8747 */ 8748 8749/** 8750 * Rect 8751 * low-level utility class for basic geometry 8752 */ 8753 8754( function( window, factory ) { 8755 // universal module definition 8756 /* jshint strict: false */ /* globals define, module */ 8757 if ( typeof define == 'function' && define.amd ) { 8758 // AMD 8759 define( 'packery/js/rect',factory ); 8760 } else if ( typeof module == 'object' && module.exports ) { 8761 // CommonJS 8762 module.exports = factory(); 8763 } else { 8764 // browser global 8765 window.Packery = window.Packery || {}; 8766 window.Packery.Rect = factory(); 8767 } 8768 8769}( window, function factory() { 8770 8771 8772// -------------------------- Rect -------------------------- // 8773 8774function Rect( props ) { 8775 // extend properties from defaults 8776 for ( var prop in Rect.defaults ) { 8777 this[ prop ] = Rect.defaults[ prop ]; 8778 } 8779 8780 for ( prop in props ) { 8781 this[ prop ] = props[ prop ]; 8782 } 8783 8784} 8785 8786Rect.defaults = { 8787 x: 0, 8788 y: 0, 8789 width: 0, 8790 height: 0 8791}; 8792 8793var proto = Rect.prototype; 8794 8795/** 8796 * Determines whether or not this rectangle wholly encloses another rectangle or point. 8797 * @param {Rect} rect 8798 * @returns {Boolean} 8799**/ 8800proto.contains = function( rect ) { 8801 // points don't have width or height 8802 var otherWidth = rect.width || 0; 8803 var otherHeight = rect.height || 0; 8804 return this.x <= rect.x && 8805 this.y <= rect.y && 8806 this.x + this.width >= rect.x + otherWidth && 8807 this.y + this.height >= rect.y + otherHeight; 8808}; 8809 8810/** 8811 * Determines whether or not the rectangle intersects with another. 8812 * @param {Rect} rect 8813 * @returns {Boolean} 8814**/ 8815proto.overlaps = function( rect ) { 8816 var thisRight = this.x + this.width; 8817 var thisBottom = this.y + this.height; 8818 var rectRight = rect.x + rect.width; 8819 var rectBottom = rect.y + rect.height; 8820 8821 // http://stackoverflow.com/a/306332 8822 return this.x < rectRight && 8823 thisRight > rect.x && 8824 this.y < rectBottom && 8825 thisBottom > rect.y; 8826}; 8827 8828/** 8829 * @param {Rect} rect - the overlapping rect 8830 * @returns {Array} freeRects - rects representing the area around the rect 8831**/ 8832proto.getMaximalFreeRects = function( rect ) { 8833 8834 // if no intersection, return false 8835 if ( !this.overlaps( rect ) ) { 8836 return false; 8837 } 8838 8839 var freeRects = []; 8840 var freeRect; 8841 8842 var thisRight = this.x + this.width; 8843 var thisBottom = this.y + this.height; 8844 var rectRight = rect.x + rect.width; 8845 var rectBottom = rect.y + rect.height; 8846 8847 // top 8848 if ( this.y < rect.y ) { 8849 freeRect = new Rect({ 8850 x: this.x, 8851 y: this.y, 8852 width: this.width, 8853 height: rect.y - this.y 8854 }); 8855 freeRects.push( freeRect ); 8856 } 8857 8858 // right 8859 if ( thisRight > rectRight ) { 8860 freeRect = new Rect({ 8861 x: rectRight, 8862 y: this.y, 8863 width: thisRight - rectRight, 8864 height: this.height 8865 }); 8866 freeRects.push( freeRect ); 8867 } 8868 8869 // bottom 8870 if ( thisBottom > rectBottom ) { 8871 freeRect = new Rect({ 8872 x: this.x, 8873 y: rectBottom, 8874 width: this.width, 8875 height: thisBottom - rectBottom 8876 }); 8877 freeRects.push( freeRect ); 8878 } 8879 8880 // left 8881 if ( this.x < rect.x ) { 8882 freeRect = new Rect({ 8883 x: this.x, 8884 y: this.y, 8885 width: rect.x - this.x, 8886 height: this.height 8887 }); 8888 freeRects.push( freeRect ); 8889 } 8890 8891 return freeRects; 8892}; 8893 8894proto.canFit = function( rect ) { 8895 return this.width >= rect.width && this.height >= rect.height; 8896}; 8897 8898return Rect; 8899 8900})); 8901 8902/** 8903 * Packer 8904 * bin-packing algorithm 8905 */ 8906 8907( function( window, factory ) { 8908 // universal module definition 8909 /* jshint strict: false */ /* globals define, module, require */ 8910 if ( typeof define == 'function' && define.amd ) { 8911 // AMD 8912 define( 'packery/js/packer',[ './rect' ], factory ); 8913 } else if ( typeof module == 'object' && module.exports ) { 8914 // CommonJS 8915 module.exports = factory( 8916 require('./rect') 8917 ); 8918 } else { 8919 // browser global 8920 var Packery = window.Packery = window.Packery || {}; 8921 Packery.Packer = factory( Packery.Rect ); 8922 } 8923 8924}( window, function factory( Rect ) { 8925 8926 8927// -------------------------- Packer -------------------------- // 8928 8929/** 8930 * @param {Number} width 8931 * @param {Number} height 8932 * @param {String} sortDirection 8933 * topLeft for vertical, leftTop for horizontal 8934 */ 8935function Packer( width, height, sortDirection ) { 8936 this.width = width || 0; 8937 this.height = height || 0; 8938 this.sortDirection = sortDirection || 'downwardLeftToRight'; 8939 8940 this.reset(); 8941} 8942 8943var proto = Packer.prototype; 8944 8945proto.reset = function() { 8946 this.spaces = []; 8947 8948 var initialSpace = new Rect({ 8949 x: 0, 8950 y: 0, 8951 width: this.width, 8952 height: this.height 8953 }); 8954 8955 this.spaces.push( initialSpace ); 8956 // set sorter 8957 this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight; 8958}; 8959 8960// change x and y of rect to fit with in Packer's available space
8960s 8961proto.pack = function( rect ) { 8962 for ( var i=0; i < this.spaces.length; i++ ) { 8963 var space = this.spaces[i]; 8964 if ( space.canFit( rect ) ) { 8965 this.placeInSpace( rect, space ); 8966 break; 8967 } 8968 } 8969}; 8970 8971proto.columnPack = function( rect ) { 8972 for ( var i=0; i < this.spaces.length; i++ ) { 8973 var space = this.spaces[i]; 8974 var canFitInSpaceColumn = space.x <= rect.x && 8975 space.x + space.width >= rect.x + rect.width && 8976 space.height >= rect.height - 0.01; // fudge number for rounding error 8977 if ( canFitInSpaceColumn ) { 8978 rect.y = space.y; 8979 this.placed( rect ); 8980 break; 8981 } 8982 } 8983}; 8984 8985proto.rowPack = function( rect ) { 8986 for ( var i=0; i < this.spaces.length; i++ ) { 8987 var space = this.spaces[i]; 8988 var canFitInSpaceRow = space.y <= rect.y && 8989 space.y + space.height >= rect.y + rect.height && 8990 space.width >= rect.width - 0.01; // fudge number for rounding error 8991 if ( canFitInSpaceRow ) { 8992 rect.x = space.x; 8993 this.placed( rect ); 8994 break; 8995 } 8996 } 8997}; 8998 8999proto.placeInSpace = function( rect, space ) { 9000 // place rect in space 9001 rect.x = space.x; 9002 rect.y = space.y; 9003 9004 this.placed( rect ); 9005}; 9006 9007// update spaces with placed rect 9008proto.placed = function( rect ) { 9009 // update spaces 9010 var revisedSpaces = []; 9011 for ( var i=0; i < this.spaces.length; i++ ) { 9012 var space = this.spaces[i]; 9013 var newSpaces = space.getMaximalFreeRects( rect ); 9014 // add either the original space or the new spaces to the revised spaces 9015 if ( newSpaces ) { 9016 revisedSpaces.push.apply( revisedSpaces, newSpaces ); 9017 } else { 9018 revisedSpaces.push( space ); 9019 } 9020 } 9021 9022 this.spaces = revisedSpaces; 9023 9024 this.mergeSortSpaces(); 9025}; 9026 9027proto.mergeSortSpaces = function() { 9028 // remove redundant spaces 9029 Packer.mergeRects( this.spaces ); 9030 this.spaces.sort( this.sorter ); 9031}; 9032 9033// add a space back 9034proto.addSpace = function( rect ) { 9035 this.spaces.push( rect ); 9036 this.mergeSortSpaces(); 9037}; 9038 9039// -------------------------- utility functions -------------------------- // 9040 9041/** 9042 * Remove redundant rectangle from array of rectangles 9043 * @param {Array} rects: an array of Rects 9044 * @returns {Array} rects: an array of Rects 9045**/ 9046Packer.mergeRects = function( rects ) { 9047 var i = 0; 9048 var rect = rects[i]; 9049 9050 rectLoop: 9051 while ( rect ) { 9052 var j = 0; 9053 var compareRect = rects[ i + j ]; 9054 9055 while ( compareRect ) { 9056 if ( compareRect == rect ) { 9057 j++; // next 9058 } else if ( compareRect.contains( rect ) ) { 9059 // remove rect 9060 rects.splice( i, 1 ); 9061 rect = rects[i]; // set next rect 9062 continue rectLoop; // bail on compareLoop 9063 } else if ( rect.contains( compareRect ) ) { 9064 // remove compareRect 9065 rects.splice( i + j, 1 ); 9066 } else { 9067 j++; 9068 } 9069 compareRect = rects[ i + j ]; // set next compareRect 9070 } 9071 i++; 9072 rect = rects[i]; 9073 } 9074 9075 return rects; 9076}; 9077 9078 9079// -------------------------- sorters -------------------------- // 9080 9081// functions for sorting rects in order 9082var sorters = { 9083 // top down, then left to right 9084 downwardLeftToRight: function( a, b ) { 9085 return a.y - b.y || a.x - b.x; 9086 }, 9087 // left to right, then top down 9088 rightwardTopToBottom: function( a, b ) { 9089 return a.x - b.x || a.y - b.y; 9090 } 9091}; 9092 9093 9094// -------------------------- -------------------------- // 9095 9096return Packer; 9097 9098})); 9099 9100/** 9101 * Packery Item Element 9102**/ 9103 9104( function( window, factory ) { 9105 // universal module definition 9106 /* jshint strict: false */ /* globals define, module, require */ 9107 if ( typeof define == 'function' && define.amd ) { 9108 // AMD 9109 define( 'packery/js/item',[ 9110 'outlayer/outlayer', 9111 './rect' 9112 ], 9113 factory ); 9114 } else if ( typeof module == 'object' && module.exports ) { 9115 // CommonJS 9116 module.exports = factory( 9117 require('outlayer'), 9118 require('./rect') 9119 ); 9120 } else { 9121 // browser global 9122 window.Packery.Item = factory( 9123 window.Outlayer, 9124 window.Packery.Rect 9125 ); 9126 } 9127 9128}( window, function factory( Outlayer, Rect ) { 9129 9130 9131// -------------------------- Item -------------------------- // 9132 9133var docElemStyle = document.documentElement.style; 9134 9135var transformProperty = typeof docElemStyle.transform == 'string' ? 9136 'transform' : 'WebkitTransform'; 9137 9138// sub-class Item 9139var Item = function PackeryItem() { 9140 Outlayer.Item.apply( this, arguments ); 9141}; 9142 9143var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 9144 9145var __create = proto._create; 9146proto._create = function() { 9147 // call default _create logic 9148 __create.call( this ); 9149 this.rect = new Rect(); 9150}; 9151 9152var _moveTo = proto.moveTo; 9153proto.moveTo = function( x, y ) {
9154 // don't shift 1px while dragging 9155 var dx = Math.abs( this.position.x - x ); 9156 var dy = Math.abs( this.position.y - y ); 9157 9158 var canHackGoTo = this.layout.dragItemCount && !this.isPlacing && 9159 !this.isTransitioning && dx < 1 && dy < 1; 9160 if ( canHackGoTo ) { 9161 this.goTo( x, y ); 9162 return; 9163 } 9164 _moveTo.apply( this, arguments ); 9165}; 9166 9167// -------------------------- placing -------------------------- // 9168 9169proto.enablePlacing = function() { 9170 this.removeTransitionStyles(); 9171 // remove transform property from transition 9172 if ( this.isTransitioning && transformProperty ) { 9173 this.element.style[ transformProperty ] = 'none'; 9174 } 9175 this.isTransitioning = false; 9176 this.getSize(); 9177 this.layout._setRectSize( this.element, this.rect ); 9178 this.isPlacing = true; 9179}; 9180 9181proto.disablePlacing = function() { 9182 this.isPlacing = false; 9183}; 9184 9185// ----- ----- // 9186 9187// remove element from DOM 9188proto.removeElem = function() { 9189 this.element.parentNode.removeChild( this.element ); 9190 // add space back to packer 9191 this.layout.packer.addSpace( this.rect ); 9192 this.emitEvent( 'remove', [ this ] ); 9193}; 9194 9195// ----- dropPlaceholder ----- // 9196 9197proto.showDropPlaceholder = function() { 9198 var dropPlaceholder = this.dropPlaceholder; 9199 if ( !dropPlaceholder ) { 9200 // create dropPlaceholder 9201 dropPlaceholder = this.dropPlaceholder = document.createElement('div'); 9202 dropPlaceholder.className = 'packery-drop-placeholder'; 9203 dropPlaceholder.style.position = 'absolute'; 9204 } 9205 9206 dropPlaceholder.style.width = this.size.width + 'px'; 9207 dropPlaceholder.style.height = this.size.height + 'px'; 9208 this.positionDropPlaceholder(); 9209 this.layout.element.appendChild( dropPlaceholder ); 9210}; 9211 9212proto.positionDropPlaceholder = function() { 9213 this.dropPlaceholder.style[ transformProperty ] = 'translate(' + 9214 this.rect.x + 'px, ' + this.rect.y + 'px)'; 9215}; 9216 9217proto.hideDropPlaceholder = function() { 9218 this.layout.element.removeChild( this.dropPlaceholder ); 9219}; 9220 9221// ----- ----- // 9222 9223return Item; 9224 9225})); 9226 9227/*! 9228 * Packery v2.0.0 9229 * Gapless, draggable grid layouts 9230 * 9231 * Licensed GPLv3 for open source use 9232 * or Packery Commercial License for commercial use 9233 * 9234 * http://packery.metafizzy.co 9235 * Copyright 2016 Metafizzy 9236 */ 9237 9238( function( window, factory ) { 9239 // universal module definition 9240 /* jshint strict: false */ /* globals define, module, require */ 9241 if ( typeof define == 'function' && define.amd ) { 9242 // AMD 9243 define( 'packery/js/packery',[ 9244 'get-size/get-size', 9245 'outlayer/outlayer', 9246 './rect', 9247 './packer', 9248 './item' 9249 ], 9250 factory ); 9251 } else if ( typeof module == 'object' && module.exports ) { 9252 // CommonJS 9253 module.exports = factory( 9254 require('get-size'), 9255 require('outlayer'), 9256 require('./rect'), 9257 require('./packer'), 9258 require('./item') 9259 ); 9260 } else { 9261 // browser global 9262 window.Packery = factory( 9263 window.getSize, 9264 window.Outlayer, 9265 window.Packery.Rect, 9266 window.Packery.Packer, 9267 window.Packery.Item 9268 ); 9269 } 9270 9271}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) { 9272 9273 9274// ----- Rect ----- // 9275 9276// allow for pixel rounding errors IE8-IE11 & Firefox; #227 9277Rect.prototype.canFit = function( rect ) { 9278 return this.width >= rect.width - 1 && this.height >= rect.height - 1; 9279}; 9280 9281// -------------------------- Packery -------------------------- // 9282 9283// create an Outlayer layout class 9284var Packery = Outlayer.create('packery'); 9285Packery.Item = Item; 9286 9287var proto = Packery.prototype; 9288 9289proto._create = function() { 9290 // call super 9291 Outlayer.prototype._create.call( this ); 9292 9293 // initial properties 9294 this.packer = new Packer(); 9295 // packer for drop targets 9296 this.shiftPacker = new Packer(); 9297 this.isEnabled = true; 9298 9299 this.dragItemCount = 0; 9300 9301 // create drag handlers 9302 var _this = this; 9303 this.handleDraggabilly = { 9304 dragStart: function() { 9305 _this.itemDragStart( this.element ); 9306 }, 9307 dragMove: function() { 9308 _this.itemDragMove( this.element, this.position.x, this.position.y ); 9309 }, 9310 dragEnd: function() { 9311 _this.itemDragEnd( this.element ); 9312 } 9313 }; 9314 9315 this.handleUIDraggable = { 9316 start: function handleUIDraggableStart( event, ui ) { 9317 // HTML5 may trigger dragstart, dismiss HTML5 dragging 9318 if ( !ui ) { 9319 return; 9320 } 9321 _this.itemDragStart( event.currentTarget ); 9322 }, 9323 drag: function handleUIDraggableDrag( event, ui ) { 9324 if ( !ui ) { 9325 return; 9326 } 9327 _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top ); 9328 }, 9329 stop: function handleUIDraggableStop( event, ui ) { 9330 if ( !ui ) { 9331 return; 9332 } 9333 _this.itemDragEnd( event.currentTarget ); 9334 } 9335 }; 9336 9337}; 9338 9339 9340// ----- init & layout ----- // 9341 9342/** 9343 * logic before any new layout 9344 */ 9345proto._resetLayout = function() {
9346 this.getSize(); 9347 9348 this._getMeasurements(); 9349 9350 // reset packer 9351 var width, height, sortDirection; 9352 // packer settings, if horizontal or vertical 9353 if ( this._getOption('horizontal') ) { 9354 width = Infinity; 9355 height = this.size.innerHeight + this.gutter; 9356 sortDirection = 'rightwardTopToBottom'; 9357 } else { 9358 width = this.size.innerWidth + this.gutter; 9359 height = Infinity; 9360 sortDirection = 'downwardLeftToRight'; 9361 } 9362 9363 this.packer.width = this.shiftPacker.width = width; 9364 this.packer.height = this.shiftPacker.height = height; 9365 this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection; 9366 9367 this.packer.reset(); 9368 9369 // layout 9370 this.maxY = 0; 9371 this.maxX = 0; 9372}; 9373 9374/** 9375 * update columnWidth, rowHeight, & gutter 9376 * @private 9377 */ 9378proto._getMeasurements = function() { 9379 this._getMeasurement( 'columnWidth', 'width' ); 9380 this._getMeasurement( 'rowHeight', 'height' ); 9381 this._getMeasurement( 'gutter', 'width' ); 9382}; 9383 9384proto._getItemLayoutPosition = function( item ) { 9385 this._setRectSize( item.element, item.rect ); 9386 if ( this.isShifting || this.dragItemCount > 0 ) { 9387 var packMethod = this._getPackMethod(); 9388 this.packer[ packMethod ]( item.rect ); 9389 } else { 9390 this.packer.pack( item.rect ); 9391 } 9392 9393 this._setMaxXY( item.rect ); 9394 return item.rect; 9395}; 9396 9397proto.shiftLayout = function() { 9398 this.isShifting = true; 9399 this.layout(); 9400 delete this.isShifting; 9401}; 9402 9403proto._getPackMethod = function() { 9404 return this._getOption('horizontal') ? 'rowPack' : 'columnPack'; 9405}; 9406 9407 9408/** 9409 * set max X and Y value, for size of container 9410 * @param {Packery.Rect} rect 9411 * @private 9412 */ 9413proto._setMaxXY = function( rect ) { 9414 this.maxX = Math.max( rect.x + rect.width, this.maxX ); 9415 this.maxY = Math.max( rect.y + rect.height, this.maxY ); 9416}; 9417 9418/** 9419 * set the width and height of a rect, applying columnWidth and rowHeight 9420 * @param {Element} elem 9421 * @param {Packery.Rect} rect 9422 */ 9423proto._setRectSize = function( elem, rect ) { 9424 var size = getSize( elem ); 9425 var w = size.outerWidth; 9426 var h = size.outerHeight; 9427 // size for columnWidth and rowHeight, if available 9428 // only check if size is non-zero, #177 9429 if ( w || h ) { 9430 w = this._applyGridGutter( w, this.columnWidth ); 9431 h = this._applyGridGutter( h, this.rowHeight ); 9432 } 9433 // rect must fit in packer 9434 rect.width = Math.min( w, this.packer.width ); 9435 rect.height = Math.min( h, this.packer.height ); 9436}; 9437 9438/** 9439 * fits item to columnWidth/rowHeight and adds gutter 9440 * @param {Number} measurement - item width or height 9441 * @param {Number} gridSize - columnWidth or rowHeight 9442 * @returns measurement 9443 */ 9444proto._applyGridGutter = function( measurement, gridSize ) { 9445 // just add gutter if no gridSize 9446 if ( !gridSize ) { 9447 return measurement + this.gutter; 9448 } 9449 gridSize += this.gutter; 9450 // fit item to columnWidth/rowHeight 9451 var remainder = measurement % gridSize; 9452 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 9453 measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize; 9454 return measurement; 9455}; 9456 9457proto._getContainerSize = function() { 9458 if ( this._getOption('horizontal') ) { 9459 return { 9460 width: this.maxX - this.gutter 9461 }; 9462 } else { 9463 return { 9464 height: this.maxY - this.gutter 9465 }; 9466 } 9467}; 9468 9469 9470// -------------------------- stamp -------------------------- // 9471 9472/** 9473 * makes space for element 9474 * @param {Element} elem 9475 */ 9476proto._manageStamp = function( elem ) { 9477 9478 var item = this.getItem( elem ); 9479 var rect; 9480 if ( item && item.isPlacing ) { 9481 rect = item.rect; 9482 } else { 9483 var offset = this._getElementOffset( elem ); 9484 rect = new Rect({ 9485 x: this._getOption('originLeft') ? offset.left : offset.right, 9486 y: this._getOption('originTop') ? offset.top : offset.bottom 9487 }); 9488 } 9489 9490 this._setRectSize( elem, rect ); 9491 // save its space in the packer 9492 this.packer.placed( rect ); 9493 this._setMaxXY( rect ); 9494}; 9495 9496// -------------------------- methods -------------------------- // 9497 9498function verticalSorter( a, b ) { 9499 return a.position.y - b.position.y || a.position.x - b.position.x; 9500} 9501 9502function horizontalSorter( a, b ) { 9503 return a.position.x - b.position.x || a.position.y - b.position.y; 9504} 9505
9506proto.sortItemsByPosition = function() { 9507 var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter; 9508 this.items.sort( sorter ); 9509}; 9510 9511/** 9512 * Fit item element in its current position 9513 * Packery will position elements around it 9514 * useful for expanding elements 9515 * 9516 * @param {Element} elem 9517 * @param {Number} x - horizontal destination position, optional 9518 * @param {Number} y - vertical destination position, optional 9519 */ 9520proto.fit = function( elem, x, y ) { 9521 var item = this.getItem( elem ); 9522 if ( !item ) { 9523 return; 9524 } 9525 9526 // stamp item to get it out of layout 9527 this.stamp( item.element ); 9528 // set placing flag 9529 item.enablePlacing(); 9530 this.updateShiftTargets( item ); 9531 // fall back to current position for fitting 9532 x = x === undefined ? item.rect.x: x; 9533 y = y === undefined ? item.rect.y: y; 9534 // position it best at its destination 9535 this.shift( item, x, y ); 9536 this._bindFitEvents( item ); 9537 item.moveTo( item.rect.x, item.rect.y ); 9538 // layout everything else 9539 this.shiftLayout(); 9540 // return back to regularly scheduled programming 9541 this.unstamp( item.element ); 9542 this.sortItemsByPosition(); 9543 item.disablePlacing(); 9544}; 9545 9546/** 9547 * emit event when item is fit and other items are laid out 9548 * @param {Packery.Item} item 9549 * @private 9550 */ 9551proto._bindFitEvents = function( item ) { 9552 var _this = this; 9553 var ticks = 0; 9554 function onLayout() { 9555 ticks++; 9556 if ( ticks != 2 ) { 9557 return; 9558 } 9559 _this.dispatchEvent( 'fitComplete', null, [ item ] ); 9560 } 9561 // when item is laid out 9562 item.once( 'layout', onLayout ); 9563 // when all items are laid out 9564 this.once( 'layoutComplete', onLayout ); 9565}; 9566 9567// -------------------------- resize -------------------------- // 9568 9569// debounced, layout on resize 9570proto.resize = function() { 9571 // don't trigger if size did not change 9572 // or if resize was unbound. See #285, outlayer#9 9573 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 9574 return; 9575 } 9576 9577 if ( this.options.shiftPercentResize ) { 9578 this.resizeShiftPercentLayout(); 9579 } else { 9580 this.layout(); 9581 } 9582}; 9583 9584/** 9585 * check if layout is needed post layout 9586 * @returns Boolean 9587 */ 9588proto.needsResizeLayout = function() { 9589 var size = getSize( this.element ); 9590 var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth'; 9591 return size[ innerSize ] != this.size[ innerSize ]; 9592}; 9593 9594proto.resizeShiftPercentLayout = function() { 9595 var items = this._getItemsForLayout( this.items ); 9596 9597 var isHorizontal = this._getOption('horizontal'); 9598 var coord = isHorizontal ? 'y' : 'x'; 9599 var measure = isHorizontal ? 'height' : 'width'; 9600 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 9601 var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth'; 9602 9603 // proportional re-align items 9604 var previousSegment = this[ segmentName ]; 9605 previousSegment = previousSegment && previousSegment + this.gutter; 9606 9607 if ( previousSegment ) { 9608 this._getMeasurements(); 9609 var currentSegment = this[ segmentName ] + this.gutter; 9610 items.forEach( function( item ) { 9611 var seg = Math.round( item.rect[ coord ] / previousSegment ); 9612 item.rect[ coord ] = seg * currentSegment; 9613 }); 9614 } else { 9615 var currentSize = getSize( this.element )[ innerSize ] + this.gutter; 9616 var previousSize = this.packer[ measure ]; 9617 items.forEach( function( item ) { 9618 item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize; 9619 }); 9620 } 9621 9622 this.shiftLayout(); 9623}; 9624 9625// -------------------------- drag -------------------------- // 9626 9627/** 9628 * handle an item drag start event 9629 * @param {Element} elem 9630 */ 9631proto.itemDragStart = function( elem ) { 9632 if ( !this.isEnabled ) { 9633 return; 9634 } 9635 this.stamp( elem ); 9636 // this.ignore( elem ); 9637 var item = this.getItem( elem ); 9638 if ( !item ) { 9639 return; 9640 } 9641 9642 item.enablePlacing(); 9643 item.showDropPlaceholder(); 9644 this.dragItemCount++; 9645 this.updateShiftTargets( item ); 9646}; 9647 9648proto.updateShiftTargets = function( dropItem ) { 9649 this.shiftPacker.reset(); 9650 9651 // pack stamps 9652 this._getBoundingRect(); 9653 var isOriginLeft = this._getOption('originLeft'); 9654 var isOriginTop = this._getOption('originTop'); 9655 this.stamps.forEach( function( stamp ) { 9656 // ignore dragged item 9657 var item = this.getItem( stamp ); 9658 if ( item && item.isPlacing ) { 9659 return; 9660 } 9661 var offset = this._getElementOffset( stamp ); 9662 var rect = new Rect({ 9663 x: isOriginLeft ? offset.left : offset.right, 9664 y: isOriginTop ? offset.top : offset.bottom 9665 }); 9666 this._setRectSize( stamp, rect ); 9667 // save its space in the packer 9668 this.shiftPacker.placed( rect ); 9669 }, this ); 9670 9671 // reset shiftTargets 9672 var isHorizontal = this._getOption('horizontal'); 9673 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 9674 var measure = isHorizontal ? 'height' : 'width'; 9675 9676 this.shiftTargetKeys = []; 9677 this.shiftTargets = []; 9678 var boundsSize; 9679 var segment = this[ segmentName ]; 9680 segment = segment && segment + this.gutter; 9681 9682 if ( segment ) { 9683 var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment ); 9684 var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment ); 9685 boundsSize = ( segs - segmentSpan ) * segment; 9686 // add targets on top 9687 for ( var i=0; i < segs; i++ ) { 9688 this._addShiftTarget( i * segment, 0, boundsSize ); 9689 } 9690 } else { 9691 boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ]; 9692 this._addShiftTarget( 0, 0, boundsSize ); 9693 } 9694 9695 // pack each item to measure where shiftTargets are 9696 var items = this._getItemsForLayout( this.items ); 9697 var packMethod = this._getPackMethod();
9698 items.forEach( function( item ) { 9699 var rect = item.rect; 9700 this._setRectSize( item.element, rect ); 9701 this.shiftPacker[ packMethod ]( rect ); 9702 9703 // add top left corner 9704 this._addShiftTarget( rect.x, rect.y, boundsSize ); 9705 // add bottom left / top right corner 9706 var cornerX = isHorizontal ? rect.x + rect.width : rect.x; 9707 var cornerY = isHorizontal ? rect.y : rect.y + rect.height; 9708 this._addShiftTarget( cornerX, cornerY, boundsSize ); 9709 9710 if ( segment ) { 9711 // add targets for each column on bottom / row on right 9712 var segSpan = Math.round( rect[ measure ] / segment ); 9713 for ( var i=1; i < segSpan; i++ ) { 9714 var segX = isHorizontal ? cornerX : rect.x + segment * i; 9715 var segY = isHorizontal ? rect.y + segment * i : cornerY; 9716 this._addShiftTarget( segX, segY, boundsSize ); 9717 } 9718 } 9719 }, this ); 9720 9721}; 9722 9723proto._addShiftTarget = function( x, y, boundsSize ) { 9724 var checkCoord = this._getOption('horizontal') ? y : x; 9725 if ( checkCoord !== 0 && checkCoord > boundsSize ) { 9726 return; 9727 } 9728 // create string for a key, easier to keep track of what targets 9729 var key = x + ',' + y; 9730 var hasKey = this.shiftTargetKeys.indexOf( key ) != -1; 9731 if ( hasKey ) { 9732 return; 9733 } 9734 this.shiftTargetKeys.push( key ); 9735 this.shiftTargets.push({ x: x, y: y }); 9736}; 9737 9738// -------------------------- drop -------------------------- // 9739 9740proto.shift = function( item, x, y ) { 9741 var shiftPosition; 9742 var minDistance = Infinity; 9743 var position = { x: x, y: y }; 9744 this.shiftTargets.forEach( function( target ) { 9745 var distance = getDistance( target, position ); 9746 if ( distance < minDistance ) { 9747 shiftPosition = target; 9748 minDistance = distance; 9749 } 9750 }); 9751 item.rect.x = shiftPosition.x; 9752 item.rect.y = shiftPosition.y; 9753}; 9754 9755function getDistance( a, b ) { 9756 var dx = b.x - a.x; 9757 var dy = b.y - a.y; 9758 return Math.sqrt( dx * dx + dy * dy ); 9759} 9760 9761// -------------------------- drag move -------------------------- // 9762 9763var DRAG_THROTTLE_TIME = 120; 9764 9765/** 9766 * handle an item drag move event 9767 * @param {Element} elem 9768 * @param {Number} x - horizontal change in position 9769 * @param {Number} y - vertical change in position 9770 */ 9771proto.itemDragMove = function( elem, x, y ) { 9772 var item = this.isEnabled && this.getItem( elem ); 9773 if ( !item ) { 9774 return; 9775 } 9776 9777 x -= this.size.paddingLeft; 9778 y -= this.size.paddingTop; 9779 9780 var _this = this; 9781 function onDrag() { 9782 _this.shift( item, x, y ); 9783 item.positionDropPlaceholder(); 9784 _this.layout(); 9785 } 9786 9787 // throttle 9788 var now = new Date(); 9789 if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) { 9790 clearTimeout( this.dragTimeout ); 9791 this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME ); 9792 } else { 9793 onDrag(); 9794 this._itemDragTime = now; 9795 } 9796}; 9797 9798// -------------------------- drag end -------------------------- // 9799 9800/** 9801 * handle an item drag end event 9802 * @param {Element} elem 9803 */ 9804proto.itemDragEnd = function( elem ) { 9805 var item = this.isEnabled && this.getItem( elem ); 9806 if ( !item ) { 9807 return; 9808 } 9809 9810 clearTimeout( this.dragTimeout ); 9811 item.element.classList.add('is-positioning-post-drag'); 9812 9813 var completeCount = 0; 9814 var _this = this; 9815 function onDragEndLayoutComplete() { 9816 completeCount++; 9817 if ( completeCount != 2 ) { 9818 return; 9819 } 9820 // reset drag item 9821 item.element.classList.remove('is-positioning-post-drag'); 9822 item.hideDropPlaceholder(); 9823 _this.dispatchEvent( 'dragItemPositioned', null, [ item ] ); 9824 } 9825 9826 item.once( 'layout', onDragEndLayoutComplete ); 9827 this.once( 'layoutComplete', onDragEndLayoutComplete ); 9828 item.moveTo( item.rect.x, item.rect.y ); 9829 this.layout(); 9830 this.dragItemCount = Math.max( 0, this.dragItemCount - 1 ); 9831 this.sortItemsByPosition(); 9832 item.disablePlacing(); 9833 this.unstamp( item.element ); 9834}; 9835 9836/** 9837 * binds Draggabilly events 9838 * @param {Draggabilly} draggie 9839 */ 9840proto.bindDraggabillyEvents = function( draggie ) { 9841 this._bindDraggabillyEvents( draggie, 'on' ); 9842}; 9843 9844proto.unbindDraggabillyEvents = function( draggie ) { 9845 this._bindDraggabillyEvents( draggie, 'off' ); 9846}; 9847 9848proto._bindDraggabillyEvents = function( draggie, method ) { 9849 var handlers = this.handleDraggabilly; 9850 draggie[ method ]( 'dragStart', handlers.dragStart ); 9851 draggie[ method ]( 'dragMove', handlers.dragMove ); 9852 draggie[ method ]( 'dragEnd', handlers.dragEnd ); 9853}; 9854 9855/** 9856 * binds jQuery UI Draggable events 9857 * @param {jQuery} $elems 9858 */ 9859proto.bindUIDraggableEvents = function( $elems ) { 9860 this._bindUIDraggableEvents( $elems, 'on' ); 9861}; 9862 9863proto.unbindUIDraggableEvents = function( $elems ) { 9864 this._bindUIDraggableEvents( $elems, 'off' ); 9865}; 9866 9867proto._bindUIDraggableEvents = function( $elems, method ) { 9868 var handlers = this.handleUIDraggable; 9869 $elems 9870 [ method ]( 'dragstart', handlers.start ) 9871 [ method ]( 'drag', handlers.drag ) 9872 [ method ]( 'dragstop', handlers.stop ); 9873}; 9874 9875// ----- destroy ----- // 9876 9877var _destroy = proto.destroy; 9878proto.destroy = function() { 9879 _destroy.apply( this, arguments ); 9880 // disable flag; prevent drag events from triggering. #72 9881 this.isEnabled = false;
9882}; 9883 9884// ----- ----- // 9885 9886Packery.Rect = Rect; 9887Packery.Packer = Packer; 9888 9889return Packery; 9890 9891})); 9892 9893/*! 9894 * Packery layout mode v2.0.1 9895 * sub-classes Packery 9896 */ 9897 9898/*jshint browser: true, strict: true, undef: true, unused: true */ 9899 9900( function( window, factory ) { 9901 9902 // universal module definition 9903 if ( typeof define == 'function' && define.amd ) { 9904 // AMD 9905 define( [ 9906 'isotope-layout/js/layout-mode', 9907 'packery/js/packery' 9908 ], 9909 factory ); 9910 } else if ( typeof module == 'object' && module.exports ) { 9911 // CommonJS 9912 module.exports = factory( 9913 require('isotope-layout/js/layout-mode'), 9914 require('packery') 9915 ); 9916 } else { 9917 // browser global 9918 factory( 9919 window.Isotope.LayoutMode, 9920 window.Packery 9921 ); 9922 } 9923 9924}( window, function factor( LayoutMode, Packery ) { 9925 9926 9927 // create an Outlayer layout class 9928 var PackeryMode = LayoutMode.create('packery'); 9929 var proto = PackeryMode.prototype; 9930 9931 var keepModeMethods = { 9932 _getElementOffset: true, 9933 _getMeasurement: true 9934 }; 9935 9936 // inherit Packery prototype 9937 for ( var method in Packery.prototype ) { 9938 // do not inherit mode methods 9939 if ( !keepModeMethods[ method ] ) { 9940 proto[ method ] = Packery.prototype[ method ]; 9941 } 9942 } 9943 9944 // set packer in _resetLayout 9945 var _resetLayout = proto._resetLayout; 9946 proto._resetLayout = function() { 9947 this.packer = this.packer || new Packery.Packer(); 9948 this.shiftPacker = this.shiftPacker || new Packery.Packer(); 9949 _resetLayout.apply( this, arguments ); 9950 }; 9951 9952 var _getItemLayoutPosition = proto._getItemLayoutPosition; 9953 proto._getItemLayoutPosition = function( item ) { 9954 // set packery rect 9955 item.rect = item.rect || new Packery.Rect(); 9956 return _getItemLayoutPosition.call( this, item ); 9957 }; 9958 9959 // needsResizeLayout for vertical or horizontal 9960 var _needsResizeLayout = proto.needsResizeLayout; 9961 proto.needsResizeLayout = function() { 9962 if ( this._getOption('horizontal') ) { 9963 return this.needsVerticalResizeLayout(); 9964 } else { 9965 return _needsResizeLayout.call( this ); 9966 } 9967 }; 9968 9969 // point to mode options for horizontal 9970 var _getOption = proto._getOption; 9971 proto._getOption = function( option ) { 9972 if ( option == 'horizontal' ) { 9973 return this.options.isHorizontal !== undefined ? 9974 this.options.isHorizontal : this.options.horizontal; 9975 } 9976 return _getOption.apply( this.isotope, arguments ); 9977 }; 9978 9979 return PackeryMode; 9980 9981})); 9982 9983/*! 9984 * cellsByRows layout mode for Isotope 9985 * v1.1.3 9986 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 9987 */ 9988 9989/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 9990 9991( function( window, factory ) { 9992 // universal module definition 9993 /* jshint strict: false */ /*globals define, module, require */ 9994 if ( typeof define === 'function' && define.amd ) { 9995 // AMD 9996 define( [ 9997 'isotope/js/layout-mode' 9998 ], 9999 factory ); 10000 } else if ( typeof exports === 'object' ) { 10001 // CommonJS 10002 module.exports = factory( 10003 require('isotope-layout/js/layout-mode') 10004 ); 10005 } else { 10006 // browser global 10007 factory( 10008 window.Isotope.LayoutMode 10009 ); 10010 } 10011 10012}( window, function factory( LayoutMode ) { 10013 'use strict'; 10014 10015 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 10016 var proto = CellsByRow.prototype; 10017 10018 proto._resetLayout = function() { 10019 // reset properties 10020 this.itemIndex = 0; 10021 // measurements 10022 this.getColumnWidth(); 10023 this.getRowHeight(); 10024 // set cols 10025 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 10026 this.cols = Math.max( this.cols, 1 ); 10027 }; 10028 10029 proto._getItemLayoutPosition = function( item ) { 10030 item.getSize(); 10031 var col = this.itemIndex % this.cols; 10032 var row = Math.floor( this.itemIndex / this.cols ); 10033 // center item within cell 10034 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 10035 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 10036 this.itemIndex++; 10037 return { x: x, y: y }; 10038 }; 10039 10040 proto._getContainerSize = function() { 10041 return { 10042 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 10043 }; 10044 }; 10045 10046 return CellsByRow; 10047 10048})); 10049/*global jQuery: true */ 10050 10051/*! 10052 -------------------------------- 10053 Infinite Scroll 10054 -------------------------------- 10055 + https://github.com/paulirish/infinite-scroll 10056 + version 2.1.0 10057 + Copyright 2011/12 Paul Irish & Luke Shumard 10058 + Licensed under the MIT license 10059 10060 + Documentation: http://infinite-scroll.com/ 10061*/ 10062 10063// Uses AMD or browser globals to create a jQuery plugin. 10064(function (factory) { 10065 if (typeof define === 'function' && define.amd) { 10066 // AMD. Register as an anonymous module. 10067 define(['jquery'], factory); 10068 } else { 10069 // Browser globals 10070 factory(jQuery); 10071 } 10072}(function ($, undefined) { 10073 'use strict'; 10074
10075 $.infinitescroll = function infscr(options, callback, element) { 10076 this.element = $(element); 10077 10078 // Flag the object in the event of a failed creation 10079 if (!this._create(options, callback)) { 10080 this.failed = true; 10081 } 10082 }; 10083 10084 $.infinitescroll.defaults = { 10085 loading: { 10086 finished: undefined, 10087 finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>", 10088 img: 'data:image/gif;base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oXHlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSH
10088MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2G
10088iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7', 10089 msg: null, 10090 msgText: '<em>Loading the next set of posts...</em>', 10091 selector: null, 10092 speed: 'fast', 10093 start: undefined 10094 }, 10095 state: { 10096 isDuringAjax: false, 10097 isInvalidPage: false,
10098 isDestroyed: false, 10099 isDone: false, // For when it goes all the way through the archive. 10100 isPaused: false, 10101 isBeyondMaxPage: false, 10102 currPage: 1 10103 }, 10104 debug: false, 10105 behavior: undefined, 10106 binder: $(window), // used to cache the selector 10107 nextSelector: 'div.navigation a:first', 10108 navSelector: 'div.navigation', 10109 contentSelector: null, // rename to pageFragment 10110 extraScrollPx: 150, 10111 itemSelector: 'div.post', 10112 animate: false, 10113 pathParse: undefined, 10114 dataType: 'html', 10115 appendCallback: true, 10116 bufferPx: 40, 10117 errorCallback: function () { }, 10118 infid: 0, //Instance ID 10119 pixelsFromNavToBottom: undefined, 10120 path: undefined, // Either parts of a URL as an array (e.g. ["/page/", "/"] or a function that takes in the page number and returns a URL 10121 prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted 10122 maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work) 10123 }; 10124 10125 $.infinitescroll.prototype = { 10126 10127 /* 10128 ---------------------------- 10129 Private methods 10130 ---------------------------- 10131 */ 10132 10133 // Bind or unbind from scroll 10134 _binding: function infscr_binding(binding) { 10135 10136 var instance = this, 10137 opts = instance.options; 10138 10139 opts.v = '2.0b2.120520'; 10140 10141 // if behavior is defined and this function is extended, call that instead of default 10142 if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) { 10143 this['_binding_'+opts.behavior].call(this); 10144 return; 10145 } 10146 10147 if (binding !== 'bind' && binding !== 'unbind') { 10148 this._debug('Binding value ' + binding + ' not valid'); 10149 return false; 10150 } 10151 10152 if (binding === 'unbind') { 10153 (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid); 10154 } else { 10155 (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () { 10156 instance.scroll(); 10157 }); 10158 } 10159 10160 this._debug('Binding', binding); 10161 }, 10162 10163 // Fundamental aspects of the plugin are initialized 10164 _create: function infscr_create(options, callback) { 10165 10166 // Add custom options to defaults 10167 var opts = $.extend(true, {}, $.infinitescroll.defaults, options); 10168 this.options = opts; 10169 var $window = $(window); 10170 var instance = this; 10171 10172 // Validate selectors 10173 if (!instance._validate(options)) { 10174 return false; 10175 } 10176 10177 // Validate page fragment path 10178 var path = $(opts.nextSelector).attr('href'); 10179 if (!path) { 10180 this._debug('Navigation selector not found'); 10181 return false; 10182 } 10183 10184 // Set the path to be a relative URL from root. 10185 opts.path = opts.path || this._determinepath(path); 10186 10187 // contentSelector is 'page fragment' option for .load() / .ajax() calls 10188 opts.contentSelector = opts.contentSelector || this.element; 10189 10190 // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector 10191 opts.loading.selector = opts.loading.selector || opts.contentSelector; 10192 10193 // Define loading.msg 10194 opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>'); 10195 10196 // Preload loading.img 10197 (new Image()).src = opts.loading.img; 10198 10199 // distance from nav links to bottom 10200 // computed as: height of the document + top offset of container - top offset of nav link 10201 if(opts.pixelsFromNavToBottom === undefined) { 10202 opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top; 10203 this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom); 10204 } 10205 10206 var self = this; 10207 10208 // determine loading.start actions 10209 opts.loading.start = opts.loading.start || function() { 10210 $(opts.navSelector).hide(); 10211 opts.loading.msg 10212 .appendTo(opts.loading.selector) 10213 .show(opts.loading.speed, $.proxy(function() { 10214 this.beginAjax(opts); 10215 }, self)); 10216 }; 10217 10218 // determine loading.finished actions 10219 opts.loading.finished = opts.loading.finished || function() { 10220 if (!opts.state.isBeyondMaxPage) 10221 opts.loading.msg.fadeOut(opts.loading.speed); 10222 }; 10223 10224 // callback loading 10225 opts.callback = function(instance, data, url) { 10226 if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) { 10227 instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url); 10228 } 10229 10230 if (callback) { 10231 callback.call($(opts.contentSelector)[0], data, opts, url); 10232 } 10233 10234 if (opts.prefill) { 10235 $window.bind('resize.infinite-scroll', instance._prefill); 10236 } 10237 }; 10238 10239 if (options.debug) { 10240 // Tell IE9 to use its built-in console 10241 if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') { 10242 ['log','info','warn','error','assert','dir','clear','profile','profileEnd'] 10243 .forEach(function (method) { 10244 console[method] = this.call(console[method], console); 10245 }, Function.prototype.bind); 10246 } 10247 } 10248 10249 this._setup(); 10250 10251 // Setups the prefill method for use 10252 if (opts.prefill) { 10253 this._prefill(); 10254 } 10255 10256 // Return true to indicate successful creation 10257 return true; 10258 }, 10259 10260 _prefill: function infscr_prefill() { 10261 var instance = this; 10262 var $window = $(window); 10263 10264 function needsPrefill() { 10265 return ( $(instance.options.contentSelector).height() <= $window.height() ); 10266 } 10267 10268 this._prefill = function() { 10269 if (needsPrefill()) { 10270 instance.scroll(); 10271 } 10272 10273 $window.bind('resize.infinite-scroll', function() { 10274 if (needsPrefill()) { 10275 $window.unbind('resize.infinite-scroll'); 10276 instance.scroll(); 10277 } 10278 }); 10279 }; 10280 10281 // Call self after setting up the new function 10282 this._prefill(); 10283 }, 10284 10285 // Console log wrapper 10286 _debug: function infscr_debug() { 10287 if (true !== this.options.debug) { 10288 return; 10289 } 10290 10291 if (typeof console !== 'undefined' && typeof console.log === 'function') { 10292 // Modern browsers 10293 // Single argument, which is a string 10294 if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') { 10295 console.log( (Array.prototype.slice.call(arguments)).toString() ); 10296 } else { 10297 console.log( Array.prototype.slice.call(arguments) ); 10298 } 10299 } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') { 10300 // IE8 10301 Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments)); 10302 } 10303 }, 10304 10305 // find the number to increment in the path.
10306 _determinepath: function infscr_determinepath(path) { 10307 10308 var opts = this.options; 10309 10310 // if behavior is defined and this function is extended, call that instead of default 10311 if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) { 10312 return this['_determinepath_'+opts.behavior].call(this,path); 10313 } 10314 10315 if (!!opts.pathParse) { 10316 10317 this._debug('pathParse manual'); 10318 return opts.pathParse(path, this.options.state.currPage+1); 10319 10320 } else if (path.match(/^(.*?)\b2\b(.*?$)/)) { 10321 path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 10322 10323 // if there is any 2 in the url at all. 10324 } else if (path.match(/^(.*?)2(.*?$)/)) { 10325 10326 // page= is used in django: 10327 // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127 10328 if (path.match(/^(.*?page=)2(\/.*|$)/)) { 10329 path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 10330 return path; 10331 } 10332 10333 path = path.match(/^(.*?)2(.*?$)/).slice(1); 10334 10335 } else { 10336 10337 // page= is used in drupal too but second page is page=1 not page=2: 10338 // thx Jerod Fritz, vladikoff 10339 if (path.match(/^(.*?page=)1(\/.*|$)/)) { 10340 path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 10341 return path; 10342 } else { 10343 this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com."); 10344 // Get rid of isInvalidPage to allow permalink to state 10345 opts.state.isInvalidPage = true; //prevent it from running on this page. 10346 } 10347 } 10348 this._debug('determinePath', path); 10349 return path; 10350 10351 }, 10352 10353 // Custom error 10354 _error: function infscr_error(xhr) { 10355 10356 var opts = this.options; 10357 10358 // if behavior is defined and this function is extended, call that instead of default 10359 if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) { 10360 this['_error_'+opts.behavior].call(this,xhr); 10361 return; 10362 } 10363 10364 if (xhr !== 'destroy' && xhr !== 'end') { 10365 xhr = 'unknown'; 10366 } 10367 10368 this._debug('Error', xhr); 10369 10370 if (xhr === 'end' || opts.state.isBeyondMaxPage) { 10371 this._showdonemsg(); 10372 } 10373 10374 opts.state.isDone = true; 10375 opts.state.currPage = 1; // if you need to go back to this instance 10376 opts.state.isPaused = false; 10377 opts.state.isBeyondMaxPage = false; 10378 this._binding('unbind'); 10379 10380 }, 10381 10382 // Load Callback 10383 _loadcallback: function infscr_loadcallback(box, data, url) { 10384 var opts = this.options, 10385 callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK 10386 result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append', 10387 frag; 10388 10389 // if behavior is defined and this function is extended, call that instead of default 10390 if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) { 10391 this['_loadcallback_'+opts.behavior].call(this,box,data); 10392 return; 10393 } 10394 10395 switch (result) { 10396 case 'done': 10397 this._showdonemsg(); 10398 return false; 10399 10400 case 'no-append': 10401 if (opts.dataType === 'html') { 10402 data = '<div>' + data + '</div>'; 10403 data = $(data).find(opts.itemSelector); 10404 } 10405 10406 // if it didn't return anything 10407 if (data.length === 0) { 10408 return this._error('end'); 10409 } 10410 10411 break; 10412 10413 case 'append': 10414 var children = box.children(); 10415 // if it didn't return anything 10416 if (children.length === 0) { 10417 return this._error('end'); 10418 } 10419 10420 // use a documentFragment because it works when content is going into a table or UL 10421 frag = document.createDocumentFragment(); 10422 while (box[0].firstChild) { 10423 frag.appendChild(box[0].firstChild); 10424 } 10425 10426 this._debug('contentSelector', $(opts.contentSelector)[0]); 10427 $(opts.contentSelector)[0].appendChild(frag); 10428 // previously, we would pass in the new DOM element as context for the callback 10429 // however we're now using a documentfragment, which doesn't have parents or children, 10430 // so the context is the contentContainer guy, and we pass in an array 10431 // of the elements collected as the first argument. 10432 10433 data = children.get(); 10434 break; 10435 } 10436 10437 // loadingEnd function 10438 opts.loading.finished.call($(opts.contentSelector)[0],opts); 10439 10440 // smooth scroll to ease in the new content 10441 if (opts.animate) { 10442 var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px'; 10443 $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; }); 10444 } 10445 10446 if (!opts.animate) { 10447 // once the call is done, we can allow it again. 10448 opts.state.isDuringAjax = false;
10449 } 10450 10451 callback(this, data, url); 10452 10453 if (opts.prefill) { 10454 this._prefill(); 10455 } 10456 }, 10457 10458 _nearbottom: function infscr_nearbottom() { 10459 10460 var opts = this.options, 10461 pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height(); 10462 10463 // if behavior is defined and this function is extended, call that instead of default 10464 if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) { 10465 return this['_nearbottom_'+opts.behavior].call(this); 10466 } 10467 10468 this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom); 10469 10470 // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom.... 10471 return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom); 10472 10473 }, 10474 10475 // Pause / temporarily disable plugin from firing 10476 _pausing: function infscr_pausing(pause) { 10477 10478 var opts = this.options; 10479 10480 // if behavior is defined and this function is extended, call that instead of default 10481 if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) { 10482 this['_pausing_'+opts.behavior].call(this,pause); 10483 return; 10484 } 10485 10486 // If pause is not 'pause' or 'resume', toggle it's value 10487 if (pause !== 'pause' && pause !== 'resume' && pause !== null) { 10488 this._debug('Invalid argument. Toggling pause value instead'); 10489 } 10490 10491 pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle'; 10492 10493 switch (pause) { 10494 case 'pause': 10495 opts.state.isPaused = true; 10496 break; 10497 10498 case 'resume': 10499 opts.state.isPaused = false; 10500 break; 10501 10502 case 'toggle': 10503 opts.state.isPaused = !opts.state.isPaused; 10504 break; 10505 } 10506 10507 this._debug('Paused', opts.state.isPaused); 10508 return false; 10509 10510 }, 10511 10512 // Behavior is determined 10513 // If the behavior option is undefined, it will set to default and bind to scroll 10514 _setup: function infscr_setup() { 10515 10516 var opts = this.options; 10517 10518 // if behavior is defined and this function is extended, call that instead of default 10519 if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) { 10520 this['_setup_'+opts.behavior].call(this); 10521 return; 10522 } 10523 10524 this._binding('bind'); 10525 10526 return false; 10527 10528 }, 10529 10530 // Show done message 10531 _showdonemsg: function infscr_showdonemsg() { 10532 10533 var opts = this.options; 10534 10535 // if behavior is defined and this function is extended, call that instead of default 10536 if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) { 10537 this['_showdonemsg_'+opts.behavior].call(this); 10538 return; 10539 } 10540 10541 opts.loading.msg 10542 .find('img') 10543 .hide() 10544 .parent() 10545 .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () { 10546 $(this).parent().fadeOut(opts.loading.speed); 10547 }); 10548 10549 // user provided callback when done 10550 opts.errorCallback.call($(opts.contentSelector)[0],'done'); 10551 }, 10552 10553 // grab each selector option and see if any fail 10554 _validate: function infscr_validate(opts) { 10555 for (var key in opts) { 10556 if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) { 10557 this._debug('Your ' + key + ' found no elements.'); 10558 return false; 10559 } 10560 } 10561 10562 return true; 10563 }, 10564 10565 /* 10566 ---------------------------- 10567 Public methods 10568 ---------------------------- 10569 */ 10570 10571 // Bind to scroll 10572 bind: function infscr_bind() { 10573 this._binding('bind'); 10574 }, 10575 10576 // Destroy current instance of plugin 10577 destroy: function infscr_destroy() { 10578 this.options.state.isDestroyed = true; 10579 this.options.loading.finished(); 10580 return this._error('destroy'); 10581 }, 10582 10583 // Set pause value to false 10584 pause: function infscr_pause() { 10585 this._pausing('pause'); 10586 }, 10587 10588 // Set pause value to false 10589 resume: function infscr_resume() { 10590 this._pausing('resume'); 10591 }, 10592 10593 beginAjax: function infscr_ajax(opts) { 10594 var instance = this, 10595 path = opts.path, 10596 box, desturl, method, condition; 10597 10598 // increment the URL bit. e.g. /page/3/ 10599 opts.state.currPage++; 10600 10601 // Manually control maximum page 10602 if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){ 10603 opts.state.isBeyondMaxPage = true; 10604 this.destroy(); 10605 return; 10606 } 10607 10608 // if we're dealing with a table we can't use DIVs 10609 box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>'); 10610 10611 desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage); 10612 instance._debug('heading into ajax', desturl); 10613 10614 method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback'; 10615 if (opts.appendCallback && opts.dataType === 'html') { 10616 method += '+callback'; 10617 } 10618 10619 switch (method) { 10620 case 'html+callback': 10621 instance._debug('Using HTML via .load() method'); 10622 box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) { 10623 instance._loadcallback(box, responseText, desturl); 10624 }); 10625 10626 break; 10627 10628 case 'html': 10629 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 10630 $.ajax({ 10631 // params 10632 url: desturl, 10633 dataType: opts.dataType, 10634 complete: function infscr_ajax_callback(jqXHR, textStatus) { 10635 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 10636 if (condition) { 10637 instance._loadcallback(box, jqXHR.responseText, desturl); 10638 } else { 10639 instance._error('end'); 10640 } 10641 } 10642 }); 10643 10644 break; 10645 case 'json': 10646 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 10647 $.ajax({ 10648 dataType: 'json', 10649 type: 'GET', 10650 url: desturl, 10651 success: function (data, textStatus, jqXHR) { 10652 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 10653 if (opts.appendCallback) { 10654 // if appendCallback is true, you must defined template in options. 10655 // note that data passed into _loadcallback is already an html (after processed in opts.template(data)). 10656 if (opts.template !== undefined) { 10657 var theData = opts.template(data); 10658 box.append(theData); 10659 if (condition) { 10660 instance._loadcallback(box, theData); 10661 } else { 10662 instance._error('end'); 10663 } 10664 } else { 10665 instance._debug('template must be defined.'); 10666 instance._error('end'); 10667 } 10668 } else { 10669 // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback. 10670 if (condition) { 10671 instance._loadcallback(box, data, desturl); 10672 } else { 10673 instance._error('end'); 10674 } 10675 } 10676 }, 10677 error: function() { 10678 instance._debug('JSON ajax request failed.'); 10679 instance._error('end'); 10680 } 10681 }); 10682 10683 break; 10684 } 10685 }, 10686 10687 // Retrieve next set of content items 10688 retrieve: function infscr_retrieve(pageNum) { 10689 pageNum = pageNum || null; 10690 10691 var instance = this, 10692 opts = instance.options; 10693 10694 // if behavior is defined and this function is extended, call that instead of default 10695 if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) { 10696 this['retrieve_'+opts.behavior].call(this,pageNum); 10697 return; 10698 } 10699 10700 // for manual triggers, if destroyed, get out of here 10701 if (opts.state.isDestroyed) { 10702 this._debug('Instance is destroyed'); 10703 return false;
10704 } 10705 10706 // we dont want to fire the ajax multiple times 10707 opts.state.isDuringAjax = true; 10708 10709 opts.loading.start.call($(opts.contentSelector)[0],opts); 10710 }, 10711 10712 // Check to see next page is needed 10713 scroll: function infscr_scroll() { 10714 10715 var opts = this.options, 10716 state = opts.state; 10717 10718 // if behavior is defined and this function is extended, call that instead of default 10719 if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) { 10720 this['scroll_'+opts.behavior].call(this); 10721 return; 10722 } 10723 10724 if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) { 10725 return; 10726 } 10727 10728 if (!this._nearbottom()) { 10729 return; 10730 } 10731 10732 this.retrieve(); 10733 10734 }, 10735 10736 // Toggle pause value 10737 toggle: function infscr_toggle() { 10738 this._pausing(); 10739 }, 10740 10741 // Unbind from scroll 10742 unbind: function infscr_unbind() { 10743 this._binding('unbind'); 10744 }, 10745 10746 // update options 10747 update: function infscr_options(key) { 10748 if ($.isPlainObject(key)) { 10749 this.options = $.extend(true,this.options,key); 10750 } 10751 } 10752 }; 10753 10754 10755 /* 10756 ---------------------------- 10757 Infinite Scroll function 10758 ---------------------------- 10759 10760 Borrowed logic from the following... 10761 10762 jQuery UI 10763 - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js 10764 10765 jCarousel 10766 - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js 10767 10768 Masonry 10769 - https://github.com/desandro/masonry/blob/master/jquery.masonry.js 10770 10771*/ 10772 10773 $.fn.infinitescroll = function infscr_init(options, callback) { 10774 10775 10776 var thisCall = typeof options; 10777 10778 switch (thisCall) { 10779 10780 // method 10781 case 'string': 10782 var args = Array.prototype.slice.call(arguments, 1); 10783 10784 this.each(function () { 10785 var instance = $.data(this, 'infinitescroll'); 10786 10787 if (!instance) { 10788 // not setup yet 10789 // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup'); 10790 return false; 10791 } 10792 10793 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') { 10794 // return $.error('No such method ' + options + ' for Infinite Scroll'); 10795 return false; 10796 } 10797 10798 // no errors! 10799 instance[options].apply(instance, args); 10800 }); 10801 10802 break; 10803 10804 // creation 10805 case 'object': 10806 10807 this.each(function () { 10808 10809 var instance = $.data(this, 'infinitescroll'); 10810 10811 if (instance) { 10812 10813 // update options of current instance 10814 instance.update(options); 10815 10816 } else { 10817 10818 // initialize new instance 10819 instance = new $.infinitescroll(options, callback, this); 10820 10821 // don't attach if instantiation failed 10822 if (!instance.failed) { 10823 $.data(this, 'infinitescroll', instance); 10824 } 10825 10826 } 10827 10828 }); 10829 10830 break; 10831 10832 } 10833 10834 return this; 10835 }; 10836 10837 10838 10839 /* 10840 * smartscroll: debounced scroll event for jQuery * 10841 * https://github.com/lukeshumard/smartscroll 10842 * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js * 10843 * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. * 10844 */ 10845 10846 var event = $.event, 10847 scrollTimeout; 10848 10849 event.special.smartscroll = { 10850 setup: function () { 10851 $(this).bind('scroll', event.special.smartscroll.handler); 10852 }, 10853 teardown: function () { 10854 $(this).unbind('scroll', event.special.smartscroll.handler); 10855 }, 10856 handler: function (event, execAsap) { 10857 // Save the context 10858 var context = this, 10859 args = arguments; 10860 10861 // set correct event type 10862 event.type = 'smartscroll'; 10863 10864 if (scrollTimeout) { clearTimeout(scrollTimeout); } 10865 scrollTimeout = setTimeout(function () { 10866 $(context).trigger('smartscroll', args); 10867 }, execAsap === 'execAsap' ? 0 : 100); 10868 } 10869 }; 10870 10871 $.fn.smartscroll = function (fn) {
10872 return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']); 10873 }; 10874 10875})); 10876 10877/*! 10878Waypoints - 4.0.1 10879Copyright © 2011-2016 Caleb Troughton 10880Licensed under the MIT license. 10881https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 10882*/ 10883(function() { 10884 'use strict' 10885 10886 var keyCounter = 0 10887 var allWaypoints = {} 10888 10889 /* http://imakewebthings.com/waypoints/api/waypoint */ 10890 function Waypoint(options) { 10891 if (!options) { 10892 throw new Error('No options passed to Waypoint constructor') 10893 } 10894 if (!options.element) { 10895 throw new Error('No element option passed to Waypoint constructor') 10896 } 10897 if (!options.handler) { 10898 throw new Error('No handler option passed to Waypoint constructor') 10899 } 10900 10901 this.key = 'waypoint-' + keyCounter 10902 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 10903 this.element = this.options.element 10904 this.adapter = new Waypoint.Adapter(this.element) 10905 this.callback = options.handler 10906 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 10907 this.enabled = this.options.enabled 10908 this.triggerPoint = null 10909 this.group = Waypoint.Group.findOrCreate({ 10910 name: this.options.group, 10911 axis: this.axis 10912 }) 10913 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 10914 10915 if (Waypoint.offsetAliases[this.options.offset]) { 10916 this.options.offset = Waypoint.offsetAliases[this.options.offset] 10917 } 10918 this.group.add(this) 10919 this.context.add(this) 10920 allWaypoints[this.key] = this 10921 keyCounter += 1 10922 } 10923 10924 /* Private */ 10925 Waypoint.prototype.queueTrigger = function(direction) { 10926 this.group.queueTrigger(this, direction) 10927 } 10928 10929 /* Private */ 10930 Waypoint.prototype.trigger = function(args) { 10931 if (!this.enabled) { 10932 return 10933 } 10934 if (this.callback) { 10935 this.callback.apply(this, args) 10936 } 10937 } 10938 10939 /* Public */ 10940 /* http://imakewebthings.com/waypoints/api/destroy */ 10941 Waypoint.prototype.destroy = function() { 10942 this.context.remove(this) 10943 this.group.remove(this) 10944 delete allWaypoints[this.key] 10945 } 10946 10947 /* Public */ 10948 /* http://imakewebthings.com/waypoints/api/disable */ 10949 Waypoint.prototype.disable = function() { 10950 this.enabled = false 10951 return this 10952 } 10953 10954 /* Public */ 10955 /* http://imakewebthings.com/waypoints/api/enable */ 10956 Waypoint.prototype.enable = function() { 10957 this.context.refresh() 10958 this.enabled = true 10959 return this 10960 } 10961 10962 /* Public */ 10963 /* http://imakewebthings.com/waypoints/api/next */ 10964 Waypoint.prototype.next = function() { 10965 return this.group.next(this) 10966 } 10967 10968 /* Public */ 10969 /* http://imakewebthings.com/waypoints/api/previous */ 10970 Waypoint.prototype.previous = function() { 10971 return this.group.previous(this) 10972 } 10973 10974 /* Private */ 10975 Waypoint.invokeAll = function(method) { 10976 var allWaypointsArray = []
10977 for (var waypointKey in allWaypoints) { 10978 allWaypointsArray.push(allWaypoints[waypointKey]) 10979 } 10980 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 10981 allWaypointsArray[i][method]() 10982 } 10983 } 10984 10985 /* Public */ 10986 /* http://imakewebthings.com/waypoints/api/destroy-all */ 10987 Waypoint.destroyAll = function() { 10988 Waypoint.invokeAll('destroy') 10989 } 10990 10991 /* Public */ 10992 /* http://imakewebthings.com/waypoints/api/disable-all */ 10993 Waypoint.disableAll = function() { 10994 Waypoint.invokeAll('disable') 10995 } 10996 10997 /* Public */ 10998 /* http://imakewebthings.com/waypoints/api/enable-all */ 10999 Waypoint.enableAll = function() { 11000 Waypoint.Context.refreshAll() 11001 for (var waypointKey in allWaypoints) { 11002 allWaypoints[waypointKey].enabled = true 11003 } 11004 return this 11005 } 11006 11007 /* Public */ 11008 /* http://imakewebthings.com/waypoints/api/refresh-all */ 11009 Waypoint.refreshAll = function() { 11010 Waypoint.Context.refreshAll() 11011 } 11012 11013 /* Public */ 11014 /* http://imakewebthings.com/waypoints/api/viewport-height */ 11015 Waypoint.viewportHeight = function() { 11016 return window.innerHeight || document.documentElement.clientHeight 11017 } 11018 11019 /* Public */ 11020 /* http://imakewebthings.com/waypoints/api/viewport-width */ 11021 Waypoint.viewportWidth = function() { 11022 return document.documentElement.clientWidth 11023 } 11024 11025 Waypoint.adapters = [] 11026 11027 Waypoint.defaults = { 11028 context: window, 11029 continuous: true, 11030 enabled: true, 11031 group: 'default', 11032 horizontal: false, 11033 offset: 0 11034 } 11035 11036 Waypoint.offsetAliases = { 11037 'bottom-in-view': function() { 11038 return this.context.innerHeight() - this.adapter.outerHeight() 11039 }, 11040 'right-in-view': function() { 11041 return this.context.innerWidth() - this.adapter.outerWidth() 11042 } 11043 } 11044 11045 window.Waypoint = Waypoint 11046}()) 11047;(function() { 11048 'use strict' 11049 11050 function requestAnimationFrameShim(callback) { 11051 window.setTimeout(callback, 1000 / 60) 11052 } 11053 11054 var keyCounter = 0 11055 var contexts = {} 11056 var Waypoint = window.Waypoint 11057 var oldWindowLoad = window.onload 11058 11059 /* http://imakewebthings.com/waypoints/api/context */ 11060 function Context(element) { 11061 this.element = element 11062 this.Adapter = Waypoint.Adapter 11063 this.adapter = new this.Adapter(element) 11064 this.key = 'waypoint-context-' + keyCounter 11065 this.didScroll = false 11066 this.didResize = false 11067 this.oldScroll = { 11068 x: this.adapter.scrollLeft(), 11069 y: this.adapter.scrollTop() 11070 } 11071 this.waypoints = { 11072 vertical: {}, 11073 horizontal: {} 11074 } 11075 11076 element.waypointContextKey = this.key 11077 contexts[element.waypointContextKey] = this 11078 keyCounter += 1 11079 if (!Waypoint.windowContext) { 11080 Waypoint.windowContext = true 11081 Waypoint.windowContext = new Context(window) 11082 } 11083 11084 this.createThrottledScrollHandler() 11085 this.createThrottledResizeHandler() 11086 } 11087 11088 /* Private */ 11089 Context.prototype.add = function(waypoint) { 11090 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 11091 this.waypoints[axis][waypoint.key] = waypoint 11092 this.refresh() 11093 } 11094 11095 /* Private */ 11096 Context.prototype.checkEmpty = function() { 11097 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 11098 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 11099 var isWindow = this.element == this.element.window 11100 if (horizontalEmpty && verticalEmpty && !isWindow) { 11101 this.adapter.off('.waypoints') 11102 delete contexts[this.key] 11103 } 11104 } 11105 11106 /* Private */ 11107 Context.prototype.createThrottledResizeHandler = function() { 11108 var self = this 11109 11110 function resizeHandler() { 11111 self.handleResize() 11112 self.didResize = false 11113 } 11114 11115 this.adapter.on('resize.waypoints', function() { 11116 if (!self.didResize) { 11117 self.didResize = true 11118 Waypoint.requestAnimationFrame(resizeHandler) 11119 } 11120 }) 11121 } 11122 11123 /* Private */ 11124 Context.prototype.createThrottledScrollHandler = function() { 11125 var self = this 11126 function scrollHandler() { 11127 self.handleScroll() 11128 self.didScroll = false 11129 } 11130 11131 this.adapter.on('scroll.waypoints', function() { 11132 if (!self.didScroll || Waypoint.isTouch) { 11133 self.didScroll = true 11134 Waypoint.requestAnimationFrame(scrollHandler) 11135 } 11136 }) 11137 } 11138 11139 /* Private */ 11140 Context.prototype.handleResize = function() { 11141 Waypoint.Context.refreshAll() 11142 } 11143 11144 /* Private */ 11145 Context.prototype.handleScroll = function() { 11146 var triggeredGroups = {} 11147 var axes = { 11148 horizontal: { 11149 newScroll: this.adapter.scrollLeft(), 11150 oldScroll: this.oldScroll.x, 11151 forward: 'right', 11152 backward: 'left' 11153 }, 11154 vertical: { 11155 newScroll: this.adapter.scrollTop(), 11156 oldScroll: this.oldScroll.y, 11157 forward: 'down', 11158 backward: 'up' 11159 } 11160 } 11161 11162 for (var axisKey in axes) { 11163 var axis = axes[axisKey] 11164 var isForward = axis.newScroll > axis.oldScroll 11165 var direction = isForward ? axis.forward : axis.backward 11166
11167 for (var waypointKey in this.waypoints[axisKey]) { 11168 var waypoint = this.waypoints[axisKey][waypointKey] 11169 if (waypoint.triggerPoint === null) { 11170 continue 11171 } 11172 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 11173 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 11174 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 11175 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 11176 if (crossedForward || crossedBackward) { 11177 waypoint.queueTrigger(direction) 11178 triggeredGroups[waypoint.group.id] = waypoint.group 11179 } 11180 } 11181 } 11182 11183 for (var groupKey in triggeredGroups) { 11184 triggeredGroups[groupKey].flushTriggers() 11185 } 11186 11187 this.oldScroll = { 11188 x: axes.horizontal.newScroll, 11189 y: axes.vertical.newScroll 11190 } 11191 } 11192 11193 /* Private */ 11194 Context.prototype.innerHeight = function() { 11195 /*eslint-disable eqeqeq */ 11196 if (this.element == this.element.window) { 11197 return Waypoint.viewportHeight() 11198 } 11199 /*eslint-enable eqeqeq */ 11200 return this.adapter.innerHeight() 11201 } 11202 11203 /* Private */ 11204 Context.prototype.remove = function(waypoint) { 11205 delete this.waypoints[waypoint.axis][waypoint.key] 11206 this.checkEmpty() 11207 } 11208 11209 /* Private */ 11210 Context.prototype.innerWidth = function() { 11211 /*eslint-disable eqeqeq */ 11212 if (this.element == this.element.window) { 11213 return Waypoint.viewportWidth() 11214 } 11215 /*eslint-enable eqeqeq */ 11216 return this.adapter.innerWidth() 11217 } 11218 11219 /* Public */ 11220 /* http://imakewebthings.com/waypoints/api/context-destroy */ 11221 Context.prototype.destroy = function() { 11222 var allWaypoints = [] 11223 for (var axis in this.waypoints) {
11224 for (var waypointKey in this.waypoints[axis]) { 11225 allWaypoints.push(this.waypoints[axis][waypointKey]) 11226 } 11227 } 11228 for (var i = 0, end = allWaypoints.length; i < end; i++) { 11229 allWaypoints[i].destroy() 11230 } 11231 } 11232 11233 /* Public */ 11234 /* http://imakewebthings.com/waypoints/api/context-refresh */ 11235 Context.prototype.refresh = function() { 11236 /*eslint-disable eqeqeq */ 11237 var isWindow = this.element == this.element.window 11238 /*eslint-enable eqeqeq */ 11239 var contextOffset = isWindow ? undefined : this.adapter.offset() 11240 var triggeredGroups = {} 11241 var axes 11242 11243 this.handleScroll() 11244 axes = { 11245 horizontal: { 11246 contextOffset: isWindow ? 0 : contextOffset.left, 11247 contextScroll: isWindow ? 0 : this.oldScroll.x, 11248 contextDimension: this.innerWidth(), 11249 oldScroll: this.oldScroll.x, 11250 forward: 'right', 11251 backward: 'left', 11252 offsetProp: 'left' 11253 }, 11254 vertical: { 11255 contextOffset: isWindow ? 0 : contextOffset.top, 11256 contextScroll: isWindow ? 0 : this.oldScroll.y, 11257 contextDimension: this.innerHeight(), 11258 oldScroll: this.oldScroll.y, 11259 forward: 'down', 11260 backward: 'up', 11261 offsetProp: 'top' 11262 } 11263 } 11264 11265 for (var axisKey in axes) { 11266 var axis = axes[axisKey]
11267 for (var waypointKey in this.waypoints[axisKey]) { 11268 var waypoint = this.waypoints[axisKey][waypointKey] 11269 var adjustment = waypoint.options.offset 11270 var oldTriggerPoint = waypoint.triggerPoint 11271 var elementOffset = 0 11272 var freshWaypoint = oldTriggerPoint == null 11273 var contextModifier, wasBeforeScroll, nowAfterScroll 11274 var triggeredBackward, triggeredForward 11275 11276 if (waypoint.element !== waypoint.element.window) { 11277 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 11278 } 11279 11280 if (typeof adjustment === 'function') { 11281 adjustment = adjustment.apply(waypoint) 11282 } 11283 else if (typeof adjustment === 'string') { 11284 adjustment = parseFloat(adjustment) 11285 if (waypoint.options.offset.indexOf('%') > - 1) { 11286 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 11287 } 11288 } 11289 11290 contextModifier = axis.contextScroll - axis.contextOffset 11291 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 11292 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 11293 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 11294 triggeredBackward = wasBeforeScroll && nowAfterScroll 11295 triggeredForward = !wasBeforeScroll && !nowAfterScroll 11296 11297 if (!freshWaypoint && triggeredBackward) { 11298 waypoint.queueTrigger(axis.backward) 11299 triggeredGroups[waypoint.group.id] = waypoint.group 11300 } 11301 else if (!freshWaypoint && triggeredForward) { 11302 waypoint.queueTrigger(axis.forward) 11303 triggeredGroups[waypoint.group.id] = waypoint.group 11304 } 11305 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 11306 waypoint.queueTrigger(axis.forward) 11307 triggeredGroups[waypoint.group.id] = waypoint.group 11308 } 11309 } 11310 } 11311 11312 Waypoint.requestAnimationFrame(function() { 11313 for (var groupKey in triggeredGroups) { 11314 triggeredGroups[groupKey].flushTriggers() 11315 } 11316 }) 11317 11318 return this 11319 } 11320 11321 /* Private */ 11322 Context.findOrCreateByElement = function(element) { 11323 return Context.findByElement(element) || new Context(element) 11324 } 11325 11326 /* Private */ 11327 Context.refreshAll = function() { 11328 for (var contextId in contexts) { 11329 contexts[contextId].refresh() 11330 } 11331 } 11332 11333 /* Public */ 11334 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 11335 Context.findByElement = function(element) { 11336 return contexts[element.waypointContextKey] 11337 } 11338 11339 window.onload = function() { 11340 if (oldWindowLoad) { 11341 oldWindowLoad() 11342 } 11343 Context.refreshAll() 11344 } 11345 11346 11347 Waypoint.requestAnimationFrame = function(callback) { 11348 var requestFn = window.requestAnimationFrame || 11349 window.mozRequestAnimationFrame || 11350 window.webkitRequestAnimationFrame || 11351 requestAnimationFrameShim 11352 requestFn.call(window, callback) 11353 } 11354 Waypoint.Context = Context 11355}()) 11356;(function() { 11357 'use strict' 11358 11359 function byTriggerPoint(a, b) { 11360 return a.triggerPoint - b.triggerPoint 11361 } 11362 11363 function byReverseTriggerPoint(a, b) { 11364 return b.triggerPoint - a.triggerPoint 11365 } 11366 11367 var groups = { 11368 vertical: {}, 11369 horizontal: {} 11370 } 11371 var Waypoint = window.Waypoint 11372 11373 /* http://imakewebthings.com/waypoints/api/group */ 11374 function Group(options) { 11375 this.name = options.name 11376 this.axis = options.axis 11377 this.id = this.name + '-' + this.axis 11378 this.waypoints = [] 11379 this.clearTriggerQueues() 11380 groups[this.axis][this.name] = this 11381 } 11382 11383 /* Private */ 11384 Group.prototype.add = function(waypoint) { 11385 this.waypoints.push(waypoint) 11386 } 11387 11388 /* Private */ 11389 Group.prototype.clearTriggerQueues = function() { 11390 this.triggerQueues = { 11391 up: [], 11392 down: [], 11393 left: [], 11394 right: [] 11395 } 11396 } 11397 11398 /* Private */ 11399 Group.prototype.flushTriggers = function() { 11400 for (var direction in this.triggerQueues) { 11401 var waypoints = this.triggerQueues[direction] 11402 var reverse = direction === 'up' || direction === 'left' 11403 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 11404 for (var i = 0, end = waypoints.length; i < end; i += 1) { 11405 var waypoint = waypoints[i] 11406 if (waypoint.options.continuous || i === waypoints.length - 1) { 11407 waypoint.trigger([direction]) 11408 } 11409 } 11410 } 11411 this.clearTriggerQueues() 11412 } 11413 11414 /* Private */ 11415 Group.prototype.next = function(waypoint) { 11416 this.waypoints.sort(byTriggerPoint) 11417 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 11418 var isLast = index === this.waypoints.length - 1 11419 return isLast ? null : this.waypoints[index + 1] 11420 } 11421 11422 /* Private */ 11423 Group.prototype.previous = function(waypoint) { 11424 this.waypoints.sort(byTriggerPoint) 11425 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 11426 return index ? this.waypoints[index - 1] : null 11427 } 11428 11429 /* Private */ 11430 Group.prototype.queueTrigger = function(waypoint, direction) { 11431 this.triggerQueues[direction].push(waypoint) 11432 } 11433 11434 /* Private */ 11435 Group.prototype.remove = function(waypoint) { 11436 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 11437 if (index > -1) { 11438 this.waypoints.splice(index, 1) 11439 } 11440 } 11441 11442 /* Public */ 11443 /* http://imakewebthings.com/waypoints/api/first */ 11444 Group.prototype.first = function() { 11445 return this.waypoints[0] 11446 } 11447 11448 /* Public */ 11449 /* http://imakewebthings.com/waypoints/api/last */ 11450 Group.prototype.last = function() { 11451 return this.waypoints[this.waypoints.length - 1] 11452 } 11453 11454 /* Private */ 11455 Group.findOrCreate = function(options) { 11456 return groups[options.axis][options.name] || new Group(options) 11457 } 11458 11459 Waypoint.Group = Group 11460}()) 11461;(function() { 11462 'use strict' 11463 11464 var $ = window.jQuery 11465 var Waypoint = window.Waypoint 11466 11467 function JQueryAdapter(element) { 11468 this.$element = $(element) 11469 } 11470 11471 $.each([
11472 'innerHeight', 11473 'innerWidth', 11474 'off', 11475 'offset', 11476 'on', 11477 'outerHeight', 11478 'outerWidth', 11479 'scrollLeft', 11480 'scrollTop' 11481 ], function(i, method) { 11482 JQueryAdapter.prototype[method] = function() { 11483 var args = Array.prototype.slice.call(arguments) 11484 return this.$element[method].apply(this.$element, args) 11485 } 11486 }) 11487 11488 $.each([ 11489 'extend', 11490 'inArray', 11491 'isEmptyObject' 11492 ], function(i, method) { 11493 JQueryAdapter[method] = $[method] 11494 }) 11495 11496 Waypoint.adapters.push({ 11497 name: 'jquery', 11498 Adapter: JQueryAdapter 11499 }) 11500 Waypoint.Adapter = JQueryAdapter 11501}()) 11502;(function() { 11503 'use strict' 11504 11505 var Waypoint = window.Waypoint 11506 11507 function createExtension(framework) { 11508 return function() { 11509 var waypoints = [] 11510 var overrides = arguments[0] 11511 11512 if (framework.isFunction(arguments[0])) { 11513 overrides = framework.extend({}, arguments[1]) 11514 overrides.handler = arguments[0] 11515 } 11516 11517 this.each(function() { 11518 var options = framework.extend({}, overrides, { 11519 element: this 11520 }) 11521 if (typeof options.context === 'string') { 11522 options.context = framework(this).closest(options.context)[0] 11523 } 11524 waypoints.push(new Waypoint(options)) 11525 }) 11526 11527 return waypoints 11528 } 11529 } 11530 11531 if (window.jQuery) { 11532 window.jQuery.fn.waypoint = createExtension(window.jQuery) 11533 } 11534 if (window.Zepto) { 11535 window.Zepto.fn.waypoint = createExtension(window.Zepto) 11536 } 11537}()) 11538; 11539/*! 11540Waypoints Inview Shortcut - 4.0.1 11541Copyright © 2011-2016 Caleb Troughton 11542Licensed under the MIT license. 11543https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 11544*/ 11545(function() { 11546 'use strict' 11547 11548 function noop() {} 11549 11550 var Waypoint = window.Waypoint 11551 11552 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 11553 function Inview(options) { 11554 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 11555 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 11556 this.waypoints = [] 11557 this.element = this.options.element 11558 this.createWaypoints() 11559 } 11560 11561 /* Private */ 11562 Inview.prototype.createWaypoints = function() { 11563 var configs = { 11564 vertical: [{ 11565 down: 'enter', 11566 up: 'exited', 11567 offset: '100%' 11568 }, { 11569 down: 'entered', 11570 up: 'exit', 11571 offset: 'bottom-in-view' 11572 }, { 11573 down: 'exit', 11574 up: 'entered', 11575 offset: 0 11576 }, { 11577 down: 'exited', 11578 up: 'enter', 11579 offset: function() { 11580 return -this.adapter.outerHeight() 11581 } 11582 }], 11583 horizontal: [{ 11584 right: 'enter', 11585 left: 'exited', 11586 offset: '100%' 11587 }, { 11588 right: 'entered', 11589 left: 'exit', 11590 offset: 'right-in-view' 11591 }, { 11592 right: 'exit', 11593 left: 'entered', 11594 offset: 0 11595 }, { 11596 right: 'exited', 11597 left: 'enter', 11598 offset: function() { 11599 return -this.adapter.outerWidth() 11600 } 11601 }] 11602 } 11603 11604 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 11605 var config = configs[this.axis][i] 11606 this.createWaypoint(config) 11607 } 11608 } 11609 11610 /* Private */ 11611 Inview.prototype.createWaypoint = function(config) { 11612 var self = this 11613 this.waypoints.push(new Waypoint({ 11614 context: this.options.context, 11615 element: this.options.element, 11616 enabled: this.options.enabled, 11617 handler: (function(config) { 11618 return function(direction) { 11619 self.options[config[direction]].call(self, direction) 11620 } 11621 }(config)), 11622 offset: config.offset, 11623 horizontal: this.options.horizontal 11624 })) 11625 } 11626 11627 /* Public */ 11628 Inview.prototype.destroy = function() { 11629 for (var i = 0, end = this.waypoints.length; i < end; i++) { 11630 this.waypoints[i].destroy() 11631 } 11632 this.waypoints = [] 11633 } 11634 11635 Inview.prototype.disable = function() { 11636 for (var i = 0, end = this.waypoints.length; i < end; i++) { 11637 this.waypoints[i].disable() 11638 } 11639 } 11640 11641 Inview.prototype.enable = function() { 11642 for (var i = 0, end = this.waypoints.length; i < end; i++) { 11643 this.waypoints[i].enable() 11644 } 11645 } 11646 11647 Inview.defaults = { 11648 context: window, 11649 enabled: true, 11650 enter: noop, 11651 entered: noop,
11652 exit: noop, 11653 exited: noop 11654 } 11655 11656 Waypoint.Inview = Inview 11657}()) 11658; 11659 11660/* 11661 * SmartMenus jQuery v0.9.6 11662 * http://www.smartmenus.org/ 11663 * 11664 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 11665 * http://vadikom.com/ 11666 * 11667 * Released under the MIT license: 11668 * http://www.opensource.org/licenses/MIT 11669 */ 11670 11671(function($) { 11672 11673 var menuTrees = [], 11674 IE = !!window.createPopup, // we need to detect it, unfortunately 11675 IElt9 = IE && !document.defaultView, 11676 IElt8 = IE && !document.querySelector, 11677 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 11678 mouse = false, // optimize for touch by default - we will detect for mouse input 11679 mouseDetectionEnabled = false; 11680 11681 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 11682 function initMouseDetection(disable) { 11683 if (!mouseDetectionEnabled && !disable) { 11684 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 11685 // in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events) 11686 var firstTime = true, 11687 lastMove = null; 11688 $(document).bind({ 11689 'mousemove.smartmenus_mouse': function(e) { 11690 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 11691 if (lastMove) { 11692 var deltaX = Math.abs(lastMove.x - thisMove.x), 11693 deltaY = Math.abs(lastMove.y - thisMove.y); 11694 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 11695 mouse = true; 11696 // if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes 11697 if (firstTime) { 11698 var $a = $(e.target).closest('a'); 11699 if ($a.is('a')) { 11700 $.each(menuTrees, function() { 11701 if ($.contains(this.$root[0], $a[0])) { 11702 this.itemEnter({ currentTarget: $a[0] }); 11703 return false; 11704 } 11705 }); 11706 } 11707 firstTime = false; 11708 } 11709 } 11710 } 11711 lastMove = thisMove; 11712 }, 11713 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 11714 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 11715 mouse = false; 11716 } 11717 } 11718 }); 11719 mouseDetectionEnabled = true; 11720 } else if (mouseDetectionEnabled && disable) { 11721 $(document).unbind('.smartmenus_mouse'); 11722 mouseDetectionEnabled = false; 11723 } 11724 }; 11725 11726 $.SmartMenus = function(elm, options) { 11727 this.$root = $(elm); 11728 this.opts = options; 11729 this.rootId = ''; // internal 11730 this.$subArrow = null; 11731 this.subMenus = []; // all sub menus in the tree (UL elms) in no particular order (only real - e.g. UL's in mega sub menus won't be counted) 11732 this.activatedItems = []; // stores last activated A's for each level 11733 this.visibleSubMenus = []; // stores visible sub menus UL's 11734 this.showTimeout = 0; 11735 this.hideTimeout = 0; 11736 this.scrollTimeout = 0; 11737 this.clickActivated = false; 11738 this.zIndexInc = 0; 11739 this.$firstLink = null; // we'll use these for some tests 11740 this.$firstSub = null; // at runtime so we'll cache them 11741 this.disabled = false; 11742 this.$disableOverlay = null; 11743 this.init(); 11744 }; 11745 11746 $.extend($.SmartMenus, { 11747 hideAll: function() { 11748 $.each(menuTrees, function() { 11749 this.menuHideAll(); 11750 }); 11751 }, 11752 destroy: function() { 11753 while (menuTrees.length) { 11754 menuTrees[0].destroy(); 11755 } 11756 initMouseDetection(true); 11757 }, 11758 prototype: { 11759 init: function(refresh) { 11760 var self = this; 11761 11762 if (!refresh) { 11763 menuTrees.push(this); 11764 11765 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 11766 11767 if (this.$root.hasClass('sm-rtl')) { 11768 this.opts.rightToLeftSubMenus = true; 11769 } 11770 11771 // init root (main menu) 11772 this.$root 11773 .data('smartmenus', this) 11774 .attr('data-smartmenus-id', this.rootId) 11775 .dataSM('level', 1) 11776 .bind({ 11777 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
11778 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 11779 }) 11780 .delegate('a, div.logo-container', { 11781 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 11782 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 11783 'mousedown.smartmenus': $.proxy(this.itemDown, this), 11784 'focus.smartmenus': $.proxy(this.itemFocus, this), 11785 'blur.smartmenus': $.proxy(this.itemBlur, this), 11786 'click.smartmenus': $.proxy(this.itemClick, this), 11787 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 11788 }); 11789 11790 var eNamespace = '.smartmenus' + this.rootId; 11791 // hide menus on tap or click outside the root UL 11792 if (this.opts.hideOnClick) { 11793 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 11794 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 11795 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 11796 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 11797 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 11798 } 11799 // hide sub menus on resize 11800 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 11801 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 11802 11803 if (this.opts.subIndicators) { 11804 this.$subArrow = $('<span/>').addClass('sub-arrow'); 11805 if (this.opts.subIndicatorsText) { 11806 this.$subArrow.html(this.opts.subIndicatorsText); 11807 } 11808 } 11809 11810 // make sure mouse detection is enabled 11811 initMouseDetection(); 11812 } 11813 11814 // init sub menus 11815 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 11816 11817 this.$firstLink = this.$root.find('a').eq(0); 11818 11819 // find current item 11820 if (this.opts.markCurrentItem) { 11821 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 11822 reHash = /#.*/, 11823 locHref = window.location.href.replace(reDefaultDoc, ''), 11824 locHrefNoHash = locHref.replace(reHash, ''); 11825 this.$root.find('a').each(function() { 11826 var href = this.href.replace(reDefaultDoc, ''), 11827 $this = $(this); 11828 if (href == locHref || href == locHrefNoHash) { 11829 $this.addClass('current'); 11830 if (self.opts.markCurrentTree) { 11831 $this.parents('li').each(function() { 11832 var $this = $(this); 11833 if ($this.dataSM('sub')) { 11834 $this.children('a').addClass('current'); 11835 } 11836 }); 11837 } 11838 } 11839 }); 11840 } 11841 }, 11842 destroy: function() { 11843 this.menuHideAll(); 11844 this.$root 11845 .removeData('smartmenus') 11846 .removeAttr('data-smartmenus-id') 11847 .removeDataSM('level') 11848 .unbind('.smartmenus') 11849 .undelegate('.smartmenus'); 11850 var eNamespace = '.smartmenus' + this.rootId; 11851 $(document).unbind(eNamespace); 11852 $(window).unbind(eNamespace); 11853 if (this.opts.subIndicators) { 11854 this.$subArrow = null; 11855 } 11856 var self = this; 11857 $.each(this.subMenus, function() { 11858 if (this.hasClass('mega-menu')) { 11859 this.find('ul').removeDataSM('in-mega'); 11860 } 11861 if (this.dataSM('shown-before')) { 11862 if (IElt8) { 11863 this.children().css({ styleFloat: '', width: '' }); 11864 } 11865 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 11866 if (!IE6) { 11867 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 11868 } else { 11869 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 11870 } 11871 } 11872 if (this.dataSM('scroll-arrows')) { 11873 this.dataSM('scroll-arrows').remove(); 11874 } 11875 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 11876 } 11877 if (self.opts.subIndicators) { 11878 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 11879 } 11880 this.removeDataSM('shown-before') 11881 .removeDataSM('ie-shim') 11882 .removeDataSM('scroll-arrows') 11883 .removeDataSM('parent-a') 11884 .removeDataSM('level') 11885 .removeDataSM('beforefirstshowfired') 11886 .parent().removeDataSM('sub'); 11887 }); 11888 if (this.opts.markCurrentItem) { 11889 this.$root.find('a.current').removeClass('current'); 11890 } 11891 this.$root = null; 11892 this.$firstLink = null; 11893 this.$firstSub = null; 11894 if (this.$disableOverlay) { 11895 this.$disableOverlay.remove(); 11896 this.$disableOverlay = null; 11897 } 11898 menuTrees.splice($.inArray(this, menuTrees), 1); 11899 }, 11900 disable: function(noOverlay) { 11901 if (!this.disabled) { 11902 this.menuHideAll(); 11903 // display overlay over the menu to prevent interaction 11904 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 11905 var pos = this.$root.offset(); 11906 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 11907 position: 'absolute', 11908 top: pos.top, 11909 left: pos.left, 11910 width: this.$root.outerWidth(), 11911 height: this.$root.outerHeight(),
11912 zIndex: this.getStartZIndex() + 1, 11913 opacity: 0 11914 }).appendTo(document.body); 11915 } 11916 this.disabled = true; 11917 } 11918 }, 11919 docClick: function(e) { 11920 // hide on any click outside the menu or on a menu link 11921 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 11922 this.menuHideAll($(e.target)); 11923 } 11924 }, 11925 docTouchEnd: function(e) { 11926 if (!this.lastTouch) { 11927 return; 11928 } 11929 if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) { 11930 if (this.hideTimeout) { 11931 clearTimeout(this.hideTimeout); 11932 this.hideTimeout = 0; 11933 } 11934 // hide with a delay to prevent triggering accidental unwanted click on some page element 11935 var self = this; 11936 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 11937 } 11938 this.lastTouch = null; 11939 }, 11940 docTouchMove: function(e) { 11941 if (!this.lastTouch) { 11942 return; 11943 } 11944 var touchPoint = e.originalEvent.touches[0]; 11945 this.lastTouch.x2 = touchPoint.pageX; 11946 this.lastTouch.y2 = touchPoint.pageY; 11947 }, 11948 docTouchStart: function(e) { 11949 var touchPoint = e.originalEvent.touches[0]; 11950 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 11951 }, 11952 enable: function() { 11953 if (this.disabled) { 11954 if (this.$disableOverlay) { 11955 this.$disableOverlay.remove(); 11956 this.$disableOverlay = null; 11957 } 11958 this.disabled = false; 11959 } 11960 }, 11961 getHeight: function($elm) { 11962 return this.getOffset($elm, true); 11963 }, 11964 // returns precise width/height float values in IE9+, FF4+, recent WebKit 11965 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 11966 getOffset: function($elm, height) { 11967 var old; 11968 if ($elm.css('display') == 'none') { 11969 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 11970 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 11971 } 11972 var defaultView = $elm[0].ownerDocument.defaultView, 11973 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 11974 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 11975 if (val) { 11976 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 11977 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 11978 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 11979 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 11980 } else { 11981 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 11982 } 11983 if (old) { 11984 $elm.hide().css(old); 11985 } 11986 return val; 11987 }, 11988 getWidth: function($elm) { 11989 return this.getOffset($elm); 11990 }, 11991 getStartZIndex: function() { 11992 var zIndex = parseInt(this.$root.css('z-index')); 11993 return !isNaN(zIndex) ? zIndex : 1; 11994 }, 11995 handleEvents: function() { 11996 return !this.disabled && this.isCSSOn(); 11997 }, 11998 handleItemEvents: function($a) { 11999 return this.handleEvents() && !this.isLinkInMegaMenu($a); 12000 }, 12001 isCollapsible: function() { 12002 return this.$firstSub.css('position') == 'static'; 12003 }, 12004 isCSSOn: function() { 12005 return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'flex' || this.$firstLink.css('display') == 'inline-flex' || this.$firstLink.css('display') == 'table-cell' || this.$firstLink.css('display') == 'inline'; 12006 }, 12007 isFixed: function() { 12008 return this.$root.css('position') == 'fixed'; 12009 }, 12010 isLinkInMegaMenu: function($a) { 12011 return !$a.parent().parent().dataSM('level'); 12012 }, 12013 isTouchMode: function() { 12014 return !mouse || this.isCollapsible(); 12015 }, 12016 itemActivate: function($a) { 12017 var $li = $a.parent(), 12018 $ul = $li.parent(), 12019 level = $ul.dataSM('level'); 12020 // if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first 12021 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 12022 var self = this; 12023 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 12024 self.itemActivate($(this).dataSM('parent-a')); 12025 }); 12026 } 12027 // hide any visible deeper level sub menus 12028 if (this.visibleSubMenus.length > level) { 12029 for (var i = this.visibleSubMenus.length - 1, l = !this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level; i > l; i--) { 12030 this.menuHide(this.visibleSubMenus[i]); 12031 } 12032 } 12033 // save new active item and sub menu for this level 12034 this.activatedItems[level - 1] = $a; 12035 this.visibleSubMenus[level - 1] = $ul; 12036 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 12037 return; 12038 } 12039 // show the sub menu if this item has one 12040 var $sub = $li.dataSM('sub'); 12041 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 12042 this.menuShow($sub); 12043 } 12044 }, 12045 itemBlur: function(e) { 12046 var $a = $(e.currentTarget); 12047 if (!this.handleItemEvents($a)) { 12048 return; 12049 } 12050 this.$root.triggerHandler('blur.smapi', $a[0]); 12051 }, 12052 itemClick: function(e) { 12053 var $a = $(e.currentTarget); 12054 12055 if (!this.handleItemEvents($a)) { 12056 return; 12057 } 12058 $a.removeDataSM('mousedown'); 12059 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 12060 return false;
12061 } 12062 var $sub = $a.parent().dataSM('sub'); 12063 if (this.isTouchMode()) { 12064 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 12065 if ($a.dataSM('href')) { 12066 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 12067 } 12068 // if the sub is not visible 12069 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 12070 // try to activate the item and show the sub 12071 this.itemActivate($a); 12072 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 12073 // if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded 12074 if ($sub.is(':visible')) { 12075 return false; 12076 } 12077 } 12078 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 12079 this.clickActivated = true; 12080 this.menuShow($sub); 12081 return false; 12082 } 12083 if ($a.hasClass('disabled')) { 12084 return false; 12085 } 12086 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 12087 return false; 12088 } 12089 }, 12090 itemDown: function(e) { 12091 var $a = $(e.currentTarget); 12092 if (!this.handleItemEvents($a)) { 12093 return; 12094 } 12095 $a.dataSM('mousedown', true); 12096 }, 12097 itemEnter: function(e) { 12098 var $a = $(e.currentTarget); 12099 if (!this.handleItemEvents($a)) { 12100 return; 12101 } 12102 if (!this.isTouchMode()) { 12103 if (this.showTimeout) { 12104 clearTimeout(this.showTimeout); 12105 this.showTimeout = 0; 12106 } 12107 var self = this; 12108 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 12109 } 12110 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 12111 }, 12112 itemFocus: function(e) { 12113 var $a = $(e.currentTarget); 12114 if (!this.handleItemEvents($a)) { 12115 return; 12116 } 12117 // fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus 12118 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 12119 this.itemActivate($a); 12120 } 12121 this.$root.triggerHandler('focus.smapi', $a[0]); 12122 }, 12123 itemLeave: function(e) { 12124 var $a = $(e.currentTarget); 12125 if (!this.handleItemEvents($a)) { 12126 return; 12127 } 12128 if (!this.isTouchMode()) { 12129 if ($a[0].blur) { 12130 $a[0].blur(); 12131 } 12132 if (this.showTimeout) { 12133 clearTimeout(this.showTimeout); 12134 this.showTimeout = 0; 12135 } 12136 } 12137 $a.removeDataSM('mousedown'); 12138 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 12139 }, 12140 itemTouchEnd: function(e) { 12141 var $a = $(e.currentTarget); 12142 if (!this.handleItemEvents($a)) { 12143 return; 12144 } 12145 // prevent the address bar on iPhone from sliding down when expanding a sub menu 12146 var $sub = $a.parent().dataSM('sub'); 12147 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 12148 $a.dataSM('href', $a.attr('href')); 12149 $a.attr('href', '#'); 12150 } 12151 }, 12152 menuFixLayout: function($ul) { 12153 // fixes a menu that is being shown for the first time 12154 if (!$ul.dataSM('shown-before')) { 12155 $ul.hide().dataSM('shown-before', true); 12156 // fix the layout of the items in IE<8 12157 if (IElt8) { 12158 $ul.children().css({ styleFloat: 'left', width: '100%' }); 12159 } 12160 } 12161 }, 12162 menuHide: function($sub) { 12163 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 12164 return; 12165 } 12166 $sub.stop(true, true); 12167 if ($sub.is(':visible')) { 12168 var complete = function() { 12169 // unset z-index 12170 if (IElt9) { 12171 $sub.parent().css('z-index', ''); 12172 } else { 12173 $sub.css('z-index', ''); 12174 } 12175 }; 12176 // if sub is collapsible (mobile view) 12177 if (this.isCollapsible()) { 12178 if (this.opts.collapsibleHideFunction) { 12179 this.opts.collapsibleHideFunction.call(this, $sub, complete); 12180 } else { 12181 $sub.hide(this.opts.collapsibleHideDuration, complete); 12182 } 12183 } else { 12184 if (this.opts.hideFunction) { 12185 this.opts.hideFunction.call(this, $sub, complete); 12186 } else { 12187 $sub.hide(this.opts.hideDuration, complete); 12188 } 12189 } 12190 // remove IE iframe shim 12191 if ($sub.dataSM('ie-shim')) { 12192 $sub.dataSM('ie-shim').remove(); 12193 } 12194 // deactivate scrolling if it is activated for this sub 12195 if ($sub.dataSM('scroll')) { 12196 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 12197 } 12198 // unhighlight parent item 12199 $sub.dataSM('parent-a').removeClass('highlighted'); 12200 var level = $sub.dataSM('level'); 12201 this.activatedItems.splice(level - 1, 1); 12202 this.visibleSubMenus.splice(level - 1, 1); 12203 this.$root.triggerHandler('hide.smapi', $sub[0]); 12204 } 12205 }, 12206 menuHideAll: function($item) { 12207 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 12208 var $win = $(window), 12209 winW = $win.width(); 12210 if ( $('body').hasClass('vmenu') && winW >= 560 ) { 12211 return; 12212 } 12213 if (this.showTimeout) { 12214 clearTimeout(this.showTimeout); 12215 this.showTimeout = 0; 12216 } 12217 // hide all subs 12218 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 12219 this.menuHide(this.visibleSubMenus[i]); 12220 } 12221 // hide root if it's popup 12222 if (this.opts.isPopup) { 12223 this.$root.stop(true, true); 12224 if (this.$root.is(':visible')) { 12225 if (this.opts.hideFunction) { 12226 this.opts.hideFunction.call(this, this.$root); 12227 } else { 12228 this.$root.hide(this.opts.hideDuration); 12229 } 12230 // remove IE iframe shim 12231 if (this.$root.dataSM('ie-shim')) { 12232 this.$root.dataSM('ie-shim').remove(); 12233 } 12234 } 12235 } 12236 this.activatedItems = []; 12237 this.visibleSubMenus = []; 12238 this.clickActivated = false;
12239 // reset z-index increment 12240 this.zIndexInc = 0; 12241 }, 12242 menuIframeShim: function($ul) { 12243 // create iframe shim for the menu 12244 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 12245 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 12246 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 12247 ); 12248 } 12249 }, 12250 menuInit: function($ul) { 12251 if (!$ul.dataSM('in-mega')) { 12252 this.subMenus.push($ul); 12253 // mark UL's in mega drop downs (if any) so we can neglect them 12254 if ($ul.hasClass('mega-menu')) { 12255 $ul.find('ul').dataSM('in-mega', true); 12256 } 12257 // get level (much faster than, for example, using parentsUntil) 12258 var level = 2, 12259 par = $ul[0]; 12260 while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) { 12261 level++; 12262 } 12263 // cache stuff 12264 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 12265 .dataSM('level', level) 12266 .parent().dataSM('sub', $ul); 12267 // add sub indicator to parent item 12268 if (this.opts.subIndicators) { 12269 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 12270 } 12271 } 12272 }, 12273 menuPosition: function($sub) { 12274 var fixIE = $('html.ie').length; 12275 // if (fixIE) { 12276 // var $rowParent = $($sub).closest('.main-menu-container'); 12277 // $rowParent.height($rowParent.height()); 12278 // } 12279 var $a = $sub.dataSM('parent-a'), 12280 $li = $sub.parent(), 12281 $ul = $sub.parent().parent(), 12282 // $container = $ul.closest('.row-menu-inner').length ? ( $('body').hasClass('megamenu-side-to-side') ? ( $('body').hasClass('boxed-width') ? $ul.closest('.row-menu') : $(window) ) : $ul.closest('.row-menu-inner') ) : $ul.closest('.uncol'), 12283 $container = $ul.closest('.row-menu-inner').length ? ( $('body').hasClass('megamenu-side-to-side') ? $ul.closest('.row-menu') : $ul.closest('.row-menu-inner') ) : $ul.closest('.uncol'), 12284 level = $sub.dataSM('level'), 12285 subW = this.getWidth($sub), 12286 subH = this.getHeight($sub), 12287 itemOffset = $a.offset(), 12288 itemX = itemOffset.left, 12289 itemY = itemOffset.top, 12290 itemW = this.getWidth($a), 12291 itemH = this.getHeight($a), 12292 $win = $(window), 12293 winX = $win.scrollLeft(), 12294 winY = $win.scrollTop(), 12295 winW = $win.width(), 12296 winH = $win.height(), 12297 containerW = $container.width(), 12298 containerOffsetX = containerW + ((winW - containerW) / 2), 12299 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 12300 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 12301 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 12302 x, y, leftPos; 12303 12304 if (horizontalParent) { 12305 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 12306 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 12307 } else { 12308 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX; 12309 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 12310 } 12311 if (this.opts.keepInViewport && !this.isCollapsible()) { 12312 if (this.isFixed()) { 12313 itemX -= winX; 12314 itemY -= winY; 12315 winX = winY = 0; 12316 } 12317 var absX = itemX + x, 12318 absY = itemY + y; 12319 if (this.opts.rightToLeftSubMenus && absX < winX) { 12320 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 12321 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 12322 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 12323 } 12324 if (!horizontalParent) { 12325 if (subH < winH && absY + subH > winY + winH) { 12326 y += winY + winH - subH - absY; 12327 } else if (subH >= winH || absY < winY) { 12328 y += winY - absY; 12329 } 12330 } 12331 // do we need scrolling? 12332 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 12333 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 12334 var self = this; 12335 if (!$sub.dataSM('scroll-arrows')) { 12336 $sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]) 12337 .bind({ 12338 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 12339 mouseleave: function(e) { 12340 self.menuScrollStop($sub); 12341 self.menuScrollOut($sub, e); 12342 }, 12343 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 12344 }) 12345 .insertAfter($sub) 12346 ); 12347 } 12348 // bind events to show/hide arrows on hover and save scrolling data for this sub 12349 var vportY = winY - (itemY + itemH); 12350 $sub.dataSM('scroll', { 12351 vportY: vportY, 12352 subH: subH, 12353 winH: winH, 12354 step: 1 12355 }) 12356 .bind({ 12357 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 12358 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 12359 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 12360 }) 12361 .dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: this.getWidth($sub) - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: this.get
12361StartZIndex() + this.zIndexInc }) 12362 .eq(0).css('margin-top', vportY).end() 12363 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 12364 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 12365 } 12366 } 12367 if ( !$sub.closest('.menu-accordion').length ) { 12368 var rightPos = 'auto'; 12369 if ( $sub.parents('.isotope-filters').length ) { 12370 if ( $sub.parents('.text-right').eq(0).length ) { 12371 leftPos = '0px'; 12372 rightPos = 'auto'; 12373 } else { 12374 leftPos = 'auto'; 12375 rightPos = '0px'; 12376 } 12377 x = 0; 12378 } else { 12379 if ( $sub.hasClass('mega-menu-inner') ) { 12380 $sub.css({ width: containerW}); 12381 leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left)); 12382 if ( ! $('body').hasClass('megamenu-side-to-side') ) { 12383 leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft')); 12384 } 12385 x = 0; 12386 } else { 12387 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 12388 x = (level > 2 && x >= 0) ? x + 1 : x - 1; 12389 } 12390 } 12391 } 12392 12393 // $sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, right: rightPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-borders').length ? 1 : 0) }); 12394 $sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, right: rightPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-borders').length && !$sub.closest('.menu-borders.needs-after').length ? 1 : 0) }); 12395 // IE iframe shim 12396 this.menuIframeShim($sub); 12397 if ($sub.dataSM('ie-shim')) { 12398 $sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) }); 12399 } 12400 }, 12401 menuScroll: function($sub, up, wheel) { 12402 var y = parseFloat($sub.css('margin-top')), 12403 scroll = $sub.dataSM('scroll'), 12404 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 12405 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 12406 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 12407 y = parseFloat($sub.css('margin-top')); 12408 // show opposite arrow if appropriate 12409 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 12410 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 12411 } 12412 // accelerate when not using mousewheel to scroll 12413 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 12414 $sub.dataSM('scroll').step += 0.5; 12415 } 12416 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 12417 if (Math.abs(y - end) < 1) { 12418 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 12419 $sub.dataSM('scroll').step = 1; 12420 } else if (!wheel) { 12421 var self = this; 12422 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 12423 } 12424 }, 12425 menuScrollMousewheel: function($sub, e) { 12426 var $closestSub = $(e.target).closest('ul'); 12427 while ($closestSub.dataSM('in-mega')) { 12428 $closestSub = $closestSub.parent().closest('ul'); 12429 } 12430 if ($closestSub[0] == $sub[0]) { 12431 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 12432 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 12433 this.menuScroll($sub, up, true); 12434 } 12435 } 12436 e.preventDefault(); 12437 }, 12438 menuScrollOut: function($sub, e) { 12439 var reClass = /^scroll-(up|down)/, 12440 $closestSub = $(e.relatedTarget).closest('ul'); 12441 while ($closestSub.dataSM('in-mega')) { 12442 $closestSub = $closestSub.parent().closest('ul'); 12443 } 12444 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 12445 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 12446 } 12447 }, 12448 menuScrollOver: function($sub, e) { 12449 var reClass = /^scroll-(up|down)/, 12450 $closestSub = $(e.target).closest('ul'); 12451 while ($closestSub.dataSM('in-mega')) { 12452 $closestSub = $closestSub.parent().closest('ul'); 12453 } 12454 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 12455 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 12456 } 12457 }, 12458 menuScrollStop: function($sub) { 12459 if (this.scrollTimeout) { 12460 clearTimeout(this.scrollTimeout); 12461 this.scrollTimeout = 0; 12462 $sub.dataSM('scroll').step = 1; 12463 } 12464 }, 12465 menuShow: function($sub) { 12466 if (!$sub.dataSM('beforefirstshowfired')) { 12467 $sub.dataSM('beforefirstshowfired', true); 12468 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 12469 return; 12470 } 12471 } 12472 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 12473 return; 12474 } 12475 this.menuFixLayout($sub); 12476 $sub.stop(true, true); 12477 if (!$sub.is(':visible')) { 12478 $sub.css({ 12479 'visibility': 'visible', 12480 'pointer-events': 'auto', 12481 }); 12482 // set z-index - for IE < 9 set it to the parent LI
12483 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 12484 if (IElt9) { 12485 $sub.parent().css('z-index', zIndex); 12486 } else { 12487 $sub.css('z-index', zIndex); 12488 } 12489 // highlight parent item 12490 if (this.opts.keepHighlighted || this.isCollapsible()) { 12491 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 12492 $sub.dataSM('parent-a').addClass('highlighted'); 12493 } 12494 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 12495 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 12496 if (!IElt8) { 12497 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 12498 if (this.opts.subMenusMinWidth) { 12499 $sub.css('min-width', this.opts.subMenusMinWidth); 12500 } 12501 if (this.opts.subMenusMaxWidth) { 12502 var noMaxWidth = this.getWidth($sub); 12503 if ( ! $sub.hasClass('mega-menu-inner') ) { 12504 $sub.css('max-width', this.opts.subMenusMaxWidth); 12505 } 12506 if (noMaxWidth > this.getWidth($sub)) { 12507 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 12508 } 12509 } 12510 // IE6,7 12511 } else { 12512 $sub.children().css('styleFloat', 'none'); 12513 if (IE6) { 12514 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 12515 .children().children('a').css('white-space', 'nowrap'); 12516 } else { // IE7 12517 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 12518 if (this.opts.subMenusMinWidth) { 12519 $sub.css('min-width', this.opts.subMenusMinWidth); 12520 } 12521 } 12522 if (this.opts.subMenusMaxWidth) { 12523 var noMaxWidth = $sub.width(); 12524 if (IE6) { 12525 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 12526 if (noMaxWidth > maxWidth) { 12527 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 12528 } else { 12529 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 12530 } 12531 } else { // IE7 12532 if ( ! $sub.hasClass('mega-menu-inner') ) { 12533 $sub.css('max-width', this.opts.subMenusMaxWidth); 12534 } 12535 if (noMaxWidth > $sub.width()) { 12536 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 12537 } else { 12538 $sub.width(noMaxWidth); 12539 } 12540 } 12541 } else { 12542 $sub.width($sub.width()); 12543 } 12544 $sub.children().css('styleFloat', 'left'); 12545 } 12546 } 12547 this.menuPosition($sub); 12548 // insert IE iframe shim 12549 if ($sub.dataSM('ie-shim')) { 12550 $sub.dataSM('ie-shim').insertBefore($sub); 12551 } 12552 var complete = function() { 12553 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 12554 $sub.css('overflow', ''); 12555 }; 12556 // if sub is collapsible (mobile view) 12557 if (this.isCollapsible()) { 12558 if (this.opts.collapsibleShowFunction) { 12559 this.opts.collapsibleShowFunction.call(this, $sub, complete); 12560 } else { 12561 $sub.show(this.opts.collapsibleShowDuration, complete); 12562 } 12563 } else { 12564 if (this.opts.showFunction) { 12565 this.opts.showFunction.call(this, $sub, complete); 12566 } else { 12567 $sub.show(this.opts.showDuration, complete); 12568 } 12569 } 12570 // save new sub menu for this level 12571 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 12572 this.$root.triggerHandler('show.smapi', $sub[0]); 12573 } 12574 }, 12575 popupHide: function(noHideTimeout) { 12576 if (this.hideTimeout) { 12577 clearTimeout(this.hideTimeout); 12578 this.hideTimeout = 0; 12579 } 12580 var self = this; 12581 this.hideTimeout = setTimeout(function() { 12582 self.menuHideAll(); 12583 }, noHideTimeout ? 1 : this.opts.hideTimeout); 12584 }, 12585 popupShow: function(left, top) { 12586 if (!this.opts.isPopup) { 12587 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 12588 return; 12589 } 12590 if (this.hideTimeout) { 12591 clearTimeout(this.hideTimeout); 12592 this.hideTimeout = 0; 12593 } 12594 this.menuFixLayout(this.$root); 12595 this.$root.stop(true, true); 12596 if (!this.$root.is(':visible')) { 12597 this.$root.css({ left: left, top: top }); 12598 // IE iframe shim 12599 this.menuIframeShim(this.$root); 12600 if (this.$root.dataSM('ie-shim')) { 12601 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
12601: left, top: top }).insertBefore(this.$root); 12602 } 12603 // show menu 12604 if (this.opts.showFunction) { 12605 this.opts.showFunction.call(this, this.$root); 12606 } else { 12607 this.$root.show(this.opts.showDuration); 12608 } 12609 this.visibleSubMenus[0] = this.$root; 12610 } 12611 }, 12612 refresh: function() { 12613 this.menuHideAll(); 12614 this.$root.find('ul').each(function() { 12615 var $this = $(this); 12616 if ($this.dataSM('scroll-arrows')) { 12617 $this.dataSM('scroll-arrows').remove(); 12618 } 12619 }) 12620 .removeDataSM('in-mega') 12621 .removeDataSM('shown-before') 12622 .removeDataSM('ie-shim') 12623 .removeDataSM('scroll-arrows') 12624 .removeDataSM('parent-a') 12625 .removeDataSM('level') 12626 .removeDataSM('beforefirstshowfired'); 12627 this.$root.find('a.has-submenu').removeClass('has-submenu') 12628 .parent().removeDataSM('sub'); 12629 if (this.opts.subIndicators) { 12630 this.$root.find('span.sub-arrow').remove(); 12631 } 12632 if (this.opts.markCurrentItem) { 12633 this.$root.find('a.current').removeClass('current'); 12634 } 12635 this.subMenus = []; 12636 this.init(true); 12637 }, 12638 rootOut: function(e) { 12639 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 12640 return; 12641 } 12642 if (this.hideTimeout) { 12643 clearTimeout(this.hideTimeout); 12644 this.hideTimeout = 0; 12645 } 12646 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 12647 var self = this; 12648 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 12649 } 12650 }, 12651 rootOver: function(e) { 12652 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 12653 return; 12654 } 12655 if (this.hideTimeout) { 12656 clearTimeout(this.hideTimeout); 12657 this.hideTimeout = 0; 12658 } 12659 }, 12660 winResize: function(e) { 12661 if (!this.handleEvents()) { 12662 // we still need to resize the disable overlay if it's visible 12663 if (this.$disableOverlay) { 12664 var pos = this.$root.offset(); 12665 this.$disableOverlay.css({ 12666 top: pos.top, 12667 left: pos.left, 12668 width: this.$root.outerWidth(), 12669 height: this.$root.outerHeight() 12670 }); 12671 } 12672 return; 12673 } 12674 // hide sub menus on resize - on mobile do it only on orientation change 12675 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 12676 if (this.activatedItems.length) { 12677 this.activatedItems[this.activatedItems.length - 1][0].blur(); 12678 } 12679 this.menuHideAll(); 12680 } 12681 } 12682 } 12683 }); 12684 12685 $.fn.dataSM = function(key, val) { 12686 if (val) { 12687 return this.data(key + '_smartmenus', val); 12688 } 12689 return this.data(key + '_smartmenus'); 12690 } 12691 12692 $.fn.removeDataSM = function(key) { 12693 return this.removeData(key + '_smartmenus'); 12694 } 12695 12696 $.fn.smartmenus = function(options) { 12697 if (typeof options == 'string') { 12698 var args = arguments, 12699 method = options; 12700 Array.prototype.shift.call(args); 12701 return this.each(function() { 12702 var smartmenus = $(this).data('smartmenus'); 12703 if (smartmenus && smartmenus[method]) { 12704 smartmenus[method].apply(smartmenus, args); 12705 } 12706 }); 12707 } 12708 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 12709 return this.each(function() { 12710 new $.SmartMenus(this, opts); 12711 }); 12712 } 12713 12714 // default settings 12715 $.fn.smartmenus.defaults = { 12716 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 12717 mainMenuSubOffsetX: 0, // pixels offset from default position
12718 mainMenuSubOffsetY: 0, // pixels offset from default position 12719 subMenusSubOffsetX: 0, // pixels offset from default position 12720 subMenusSubOffsetY: 0, // pixels offset from default position 12721 subMenusMinWidth: false, //'10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 12722 subMenusMaxWidth: false, //'20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 12723 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 12724 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 12725 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 12726 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 12727 scrollInterval: 30, // interval between each scrolling step 12728 scrollAccelerate: true, // accelerate scrolling or use a fixed step 12729 showTimeout: 250, // timeout before showing the sub menus 12730 hideTimeout: 500, // timeout before hiding the sub menus 12731 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 12732 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 12733 // don't forget to call complete() at the end of whatever you do 12734 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 12735 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 12736 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 12737 // don't forget to call complete() at the end of whatever you do 12738 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 12739 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 12740 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 12741 // (i.e. when mobile styles are used to make the sub menus collapsible) 12742 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 12743 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 12744 // (i.e. when mobile styles are used to make the sub menus collapsible) 12745 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 12746 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 12747 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 12748 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 12749 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 12750 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 12751 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 12752 bottomToTopSubMenus: false, // bottom to top display of the sub menus 12753 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 12754 }; 12755 12756})(jQuery); 12757 12758/* 12759 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/ 12760 * Open source under the BSD License. 12761 * Copyright © 2008 George McGinley Smith 12762 * All rights reserved. 12763 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE 12764*/ 12765 12766/* globals jQuery, define, module, require */ 12767(function (factory) { 12768 if (typeof define === "function" && define.amd) { 12769 define(['jquery'], function ($) { 12770 return factory($); 12771 }); 12772 } else if (typeof module === "object" && typeof module.exports === "object") { 12773 module.exports = factory(require('jquery')); 12774 } else { 12775 factory(jQuery); 12776 } 12777})(function($){ 12778 12779 // Preserve the original jQuery "swing" easing as "jswing" 12780 if (typeof $.easing !== 'undefined') { 12781 $.easing['jswing'] = $.easing['swing']; 12782 } 12783 12784 var pow = Math.pow, 12785 sqrt = Math.sqrt, 12786 sin = Math.sin, 12787 cos = Math.cos, 12788 PI = Math.PI,
12789 c1 = 1.70158, 12790 c2 = c1 * 1.525, 12791 c3 = c1 + 1, 12792 c4 = ( 2 * PI ) / 3, 12793 c5 = ( 2 * PI ) / 4.5; 12794 12795 // x is the fraction of animation progress, in the range 0..1 12796 function bounceOut(x) { 12797 var n1 = 7.5625, 12798 d1 = 2.75; 12799 if ( x < 1/d1 ) { 12800 return n1*x*x; 12801 } else if ( x < 2/d1 ) { 12802 return n1*(x-=(1.5/d1))*x + .75; 12803 } else if ( x < 2.5/d1 ) { 12804 return n1*(x-=(2.25/d1))*x + .9375; 12805 } else { 12806 return n1*(x-=(2.625/d1))*x + .984375; 12807 } 12808 } 12809 12810 $.extend( $.easing, { 12811 def: 'easeOutQuad', 12812 swing: function (x) { 12813 return $.easing[$.easing.def](x); 12814 }, 12815 easeInQuad: function (x) { 12816 return x * x; 12817 }, 12818 easeOutQuad: function (x) { 12819 return 1 - ( 1 - x ) * ( 1 - x ); 12820 }, 12821 easeInOutQuad: function (x) { 12822 return x < 0.5 ? 12823 2 * x * x : 12824 1 - pow( -2 * x + 2, 2 ) / 2; 12825 }, 12826 easeInCubic: function (x) { 12827 return x * x * x; 12828 }, 12829 easeOutCubic: function (x) { 12830 return 1 - pow( 1 - x, 3 ); 12831 }, 12832 easeInOutCubic: function (x) { 12833 return x < 0.5 ? 12834 4 * x * x * x : 12835 1 - pow( -2 * x + 2, 3 ) / 2; 12836 }, 12837 easeInQuart: function (x) { 12838 return x * x * x * x; 12839 }, 12840 easeOutQuart: function (x) { 12841 return 1 - pow( 1 - x, 4 ); 12842 }, 12843 easeInOutQuart: function (x) { 12844 return x < 0.5 ? 12845 8 * x * x * x * x : 12846 1 - pow( -2 * x + 2, 4 ) / 2; 12847 }, 12848 easeInQuint: function (x) { 12849 return x * x * x * x * x; 12850 }, 12851 easeOutQuint: function (x) { 12852 return 1 - pow( 1 - x, 5 ); 12853 }, 12854 easeInOutQuint: function (x) { 12855 return x < 0.5 ? 12856 16 * x * x * x * x * x : 12857 1 - pow( -2 * x + 2, 5 ) / 2; 12858 }, 12859 easeInSine: function (x) { 12860 return 1 - cos( x * PI/2 ); 12861 }, 12862 easeOutSine: function (x) { 12863 return sin( x * PI/2 ); 12864 }, 12865 easeInOutSine: function (x) { 12866 return -( cos( PI * x ) - 1 ) / 2; 12867 }, 12868 easeInExpo: function (x) { 12869 return x === 0 ? 0 : pow( 2, 10 * x - 10 ); 12870 }, 12871 easeOutExpo: function (x) { 12872 return x === 1 ? 1 : 1 - pow( 2, -10 * x ); 12873 }, 12874 easeInOutExpo: function (x) { 12875 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 12876 pow( 2, 20 * x - 10 ) / 2 : 12877 ( 2 - pow( 2, -20 * x + 10 ) ) / 2; 12878 }, 12879 easeInCirc: function (x) { 12880 return 1 - sqrt( 1 - pow( x, 2 ) ); 12881 }, 12882 easeOutCirc: function (x) { 12883 return sqrt( 1 - pow( x - 1, 2 ) ); 12884 }, 12885 easeInOutCirc: function (x) { 12886 return x < 0.5 ? 12887 ( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 : 12888 ( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2; 12889 }, 12890 easeInElastic: function (x) { 12891 return x === 0 ? 0 : x === 1 ? 1 : 12892 -pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 ); 12893 }, 12894 easeOutElastic: function (x) { 12895 return x === 0 ? 0 : x === 1 ? 1 : 12896 pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1; 12897 }, 12898 easeInOutElastic: function (x) { 12899 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 12900 -( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 : 12901 pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1; 12902 }, 12903 easeInBack: function (x) { 12904 return c3 * x * x * x - c1 * x * x; 12905 }, 12906 easeOutBack: function (x) { 12907 return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 ); 12908 }, 12909 easeInOutBack: function (x) { 12910 return x < 0.5 ? 12911 ( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 : 12912 ( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2; 12913 }, 12914 easeInBounce: function (x) { 12915 return 1 - bounceOut( 1 - x ); 12916 }, 12917 easeOutBounce: bounceOut, 12918 easeInOutBounce: function (x) { 12919 return x < 0.5 ? 12920 ( 1 - bounceOut( 1 - 2 * x ) ) / 2 : 12921 ( 1 + bounceOut( 2 * x - 1 ) ) / 2; 12922 } 12923 }); 12924 return $; 12925}); 12926 12927/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 12928 * Licensed under the MIT License (LICENSE.txt). 12929 * 12930 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 12931 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 12932 * Thanks to: Seamus Leahy for adding deltaX and deltaY 12933 * 12934 * Version: 3.0.6 12935 * 12936 * Requires: 1.2.2+ 12937 */ 12938(function($) { 12939 var types = ['DOMMouseScroll', 'mousewheel']; 12940 if ($.event.fixHooks) { 12941 for (var i = types.length; i;) { 12942 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 12943 } 12944 } 12945 $.event.special.mousewheel = { 12946 setup: function() { 12947 if (this.addEventListener) { 12948 for (var i = types.length; i;) { 12949 this.addEventListener(types[--i], handler, false); 12950 } 12951 } else { 12952 this.onmousewheel = handler; 12953 } 12954 }, 12955 teardown: function() { 12956 if (this.removeEventListener) { 12957 for (var i = types.length; i;) { 12958 this.removeEventListener(types[--i], handler, false); 12959 } 12960 } else { 12961 this.onmousewheel = null; 12962 } 12963 } 12964 }; 12965 $.fn.extend({ 12966 mousewheel: function(fn) { 12967 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 12968 }, 12969 unmousewheel: function(fn) { 12970 return this.unbind("mousewheel", fn); 12971 } 12972 }); 12973 12974 function handler(event) { 12975 var orgEvent = event || window.event, 12976 args = [].slice.call(arguments, 1), 12977 delta = 0, 12978 returnValue = true, 12979 deltaX = 0, 12980 deltaY = 0; 12981 event = $.event.fix(orgEvent); 12982 event.type = "mousewheel"; 12983 // Old school scrollwheel delta 12984 if (orgEvent.wheelDelta) { 12985 delta = orgEvent.wheelDelta / 120; 12986 } 12987 if (orgEvent.detail) { 12988 delta = -orgEvent.detail / 3; 12989 } 12990 // New school multidimensional scroll (touchpads) deltas 12991 deltaY = delta; 12992 // Gecko 12993 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 12994 deltaY = 0; 12995 deltaX = -1 * delta; 12996 } 12997 // Webkit 12998 if (orgEvent.wheelDeltaY !== undefined) { 12999 deltaY = orgEvent.wheelDeltaY / 120; 13000 } 13001 if (orgEvent.wheelDeltaX !== undefined) { 13002 deltaX = -1 * orgEvent.wheelDeltaX / 120; 13003 } 13004 // Add event and delta to the front of the arguments 13005 args.unshift(event, delta, deltaX, deltaY); 13006 return ($.event.dispatch || $.event.handle).apply(this, args); 13007 } 13008})(jQuery); 13009/** 13010 * jQuery iLightBox - Revolutionary Lightbox Plugin 13011 * http://www.ilightbox.net/ 13012 * 13013 * @version: 2.2.4 - October 14, 2017 13014 * 13015 * @author: iProDev (Hemn Chawroka) 13016 * http://www.iprodev.com/ 13017 * 13018 */ 13019(function($, window, undefined) { 13020 13021 var extensions = { 13022 flash: ['swf'], 13023 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'], 13024 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 13025 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 13026 }, 13027 13028 // Global DOM elements 13029 $win = $(window), 13030 $doc = $(document), 13031
13032 // Support indicators 13033 browser, 13034 transform, 13035 gpuAcceleration, 13036 fullScreenApi = '', 13037 userAgent = navigator.userAgent || navigator.vendor || window.opera, 13038 supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1), 13039 ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1, 13040 isMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4)), 13041 13042 // Events 13043 clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox", 13044 touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 13045 touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 13046 touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 13047 13048 // Math shorthands 13049 abs = Math.abs, 13050 sqrt = Math.sqrt, 13051 round = Math.round, 13052 max = Math.max, 13053 min = Math.min, 13054 floor = Math.floor, 13055 random = Math.random, 13056 13057 pluginspages = { 13058 quicktime: 'http://www.apple.com/quicktime/download', 13059 flash: 'http://www.adobe.com/go/getflash' 13060 }, 13061 13062 iLightBox = function(el, options, items, instant) { 13063 var iL = this; 13064 13065 iL.options = options, 13066 iL.selector = options.selector || el, 13067 iL.context = document, 13068 iL.instant = instant; 13069 13070 if (items.length < 1) iL.attachItems(); 13071 else iL.items = items; 13072 13073 iL.vars = { 13074 total: iL.items.length, 13075 start: 0, 13076 current: null, 13077 next: null, 13078 prev: null, 13079 BODY: $('body'), 13080 loadRequests: 0, 13081 overlay: $('<div class="ilightbox-overlay"></div>'), 13082 loader: $('<div class="ilightbox-loader"><div></div></div>'), 13083 toolbar: $('<div class="ilightbox-toolbar"></div>'), 13084 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 13085 title: $('<div class="ilightbox-title"></div>'), 13086 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 13087 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 13088 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 13089 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 13090 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 13091 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 13092 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 13093 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 13094 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 13095 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13096 thumbnails: $('<div class="ilightbox-thumbnails" ondragstart="return false;"><div class="ilightbox-thumbnails-container"><a class="ilightbox-thumbnails-dragger"></a><div class="ilightbox-thumbnails-grid"></div></div></div>'), 13097 thumbs: false, 13098 nextLock: false, 13099 prevLock: false, 13100 hashLock: false, 13101 isMobile: false, 13102 mobileMaxWidth: 980, 13103 isInFullScreen: false, 13104 isSwipe: false, 13105 mouseID: 0, 13106 cycleID: 0, 13107 isPaused: 0, 13108 captionHeight: 39, 13109 }; 13110 13111 // Hideable elements with mousemove event 13112 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 13113 13114 iL.normalizeItems(); 13115 13116 //Check necessary plugins 13117 iL.availPlugins(); 13118 13119 //Set startFrom 13120 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 13121 13122 //If randomStart 13123 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 13124 iL.vars.start = iL.options.startFrom; 13125 13126 if (instant) iL.instantCall(); 13127 else iL.patchItemsEvents(); 13128 13129 if (iL.options.linkId) { 13130 iL.hashChangeHandler(); 13131 $win.iLightBoxHashChange(function() { 13132 iL.hashChangeHandler(); 13133 }); 13134 } 13135 13136 if (supportTouch) { 13137 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 13138 replace = "itap"; 13139 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 13140 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 13141 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 13142 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 13143 } 13144 13145 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 13146 $.extend(iL.options.styles, { 13147 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 13148 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 13149 nextOpacity: 0, 13150 prevOpacity: 0 13151 }); 13152 } 13153 }; 13154 13155 //iLightBox helpers 13156 iLightBox.prototype = { 13157 showLoader: function() { 13158 var iL = this; 13159 iL.vars.loadRequests += 1; 13160 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 13161 //top: '-30px' 13162 opacity: '1' 13163 }, iL.options.show.speed, 'easeOutCirc'); 13164 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 13165 //left: '-30px' 13166 opacity: '1' 13167 }, iL.options.show.speed, 'easeOutCirc'); 13168 }, 13169 13170 hideLoader: function() { 13171 var iL = this; 13172 iL.vars.loadRequests -= 1; 13173 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 13174 if (iL.options.path.toLowerCase() == "horizontal") { 13175 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 13176 //top: '-192px' 13177 opacity: '0' 13178 }, iL.options.show.speed, 'easeInCirc'); 13179 } else { 13180 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 13181 //left: '-192px' 13182 opacity: '0' 13183 }, iL.options.show.speed, 'easeInCirc'); 13184 } 13185 }, 13186 13187 createUI: function() { 13188 var iL = this; 13189 13190 iL.ui = { 13191 currentElement: iL.vars.holder, 13192 nextElement: iL.vars.nextPhoto, 13193 prevElement: iL.vars.prevPhoto, 13194 currentItem: iL.vars.current, 13195 nextItem: iL.vars.next, 13196 prevItem: iL.vars.prev, 13197 hide: function() { 13198 iL.closeAction(); 13199 }, 13200 refresh: function() { 13201 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 13202 }, 13203 fullscreen: function() { 13204 iL.fullScreenAction(); 13205 } 13206 }; 13207 }, 13208 13209 attachItems: function() { 13210 var iL = this, 13211 itemsObject = new Array(), 13212 items = new Array(); 13213 13214 $(iL.selector, iL.context).each(function() { 13215 var t = $(this), 13216 URL = t.attr(iL.options.attr) || null, 13217 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 13218 caption = t.data('caption'), 13219 title = t.data('title'), 13220 type = t.data('type') || getTypeByExtension(URL), 13221 clone = t.data('lbox-clone') || false; 13222 13223 //Uncode addition ##START## 13224 if (type === false) { 13225 return; 13226 } 13227 //Uncode addition ##END## 13228 13229 if (t.data('lbox-clone') != undefined) return; 13230 13231 //Uncode addition ##START## 13232 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 13233 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 13234 URL_i, 13235 URLS_LENGHT = ALBUM_URLS.length; 13236 13237 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 13238 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 13239 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 13240 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 13241 items.push({ 13242 URL: ALBUM_URLS[URL_i].url, 13243 caption: ALBUM_URLS[URL_i].caption, 13244 title: ALBUM_URLS[URL_i].title, 13245 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 13246 options: item_opts, 13247 clone: clone 13248 }); 13249 var newT = t; 13250 newT.attr('href',ALBUM_URLS[URL_i].url); 13251 if (!iL.instant) itemsObject.push(newT); 13252 } 13253 } 13254 } else { 13255 //Uncode addition ##END## 13256 items.push({ 13257 URL: URL, 13258 caption: caption, 13259 title: title, 13260 type: type, 13261 options: options, 13262 clone: clone 13263 }); 13264 } 13265 13266 13267 if (iL.vars != undefined) iL.vars.total = items.length; 13268 13269 if (!iL.instant) itemsObject.push(t); 13270 }); 13271 13272 iL.items = items, 13273 iL.itemsObject = itemsObject; 13274 13275 }, 13276 13277 normalizeItems: function() { 13278 var iL = this, 13279 newItems = new Array(); 13280 13281 $.each(iL.items, function(key, val) { 13282 13283 if (typeof val == "string") val = { 13284 url: val 13285 }; 13286 13287 var URL = val.url || val.URL || null, 13288 options = val.options || {}, 13289 caption = val.caption || null, 13290 title = val.title || null, 13291 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 13292 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 13293 13294 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
13295 options.videoType = options.videoType || null, 13296 options.skin = options.skin || iL.options.skin, 13297 options.width = options.width || null, 13298 options.height = options.height || null, 13299 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 13300 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 13301 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 13302 13303 if (type == "video") { 13304 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 13305 13306 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 13307 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 13308 options.html5video.preload = options.html5video.preload || "metadata"; 13309 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 13310 //UNCODE addition 13311 options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false; 13312 } 13313 13314 if (!options.width || !options.height) { 13315 if (type == "video") options.width = 1280, options.height = 720; 13316 else if (type == "iframe") options.width = '100%', options.height = '90%'; 13317 else if (type == "flash") options.width = 1280, options.height = 720; 13318 } 13319 13320 delete val.url; 13321 val.index = key; 13322 val.URL = URL; 13323 val.caption = caption; 13324 val.title = title; 13325 val.type = type; 13326 val.options = options; 13327 val.ext = ext; 13328 13329 newItems.push(val); 13330 }); 13331 13332 iL.items = newItems; 13333 }, 13334 13335 instantCall: function() { 13336 var iL = this, 13337 key = iL.vars.start; 13338 13339 iL.vars.current = key; 13340 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 13341 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 13342 13343 iL.addContents(); 13344 iL.patchEvents(); 13345 }, 13346 13347 addContents: function() { 13348 var iL = this, 13349 vars = iL.vars, 13350 opts = iL.options, 13351 viewport = getViewport(), 13352 path = opts.path.toLowerCase(), 13353 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 13354 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 13355 }), 13356 needRecognition = recognizingItems.length > 0; 13357 13358 if (opts.mobileOptimizer && !opts.innerToolbar) 13359 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 13360 13361 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 13362 13363 if (opts.linkId) 13364 vars.overlay[0].setAttribute('linkid', opts.linkId); 13365 13366 //Add Toolbar Buttons 13367 if (opts.controls.toolbar) { 13368 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 13369 if (opts.controls.fullscreen) 13370 vars.toolbar.append(vars.fullScreenButton); 13371 if (opts.controls.slideshow) 13372 vars.toolbar.append(vars.innerPlayButton); 13373 if (vars.total > 1) 13374 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 13375 } 13376 13377 //Append elements to body 13378 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 13379 13380 if (!opts.innerToolbar) 13381 vars.BODY.append(vars.toolbar); 13382 if (opts.controls.arrows) 13383 vars.BODY.append(vars.nextButton).append(vars.prevButton); 13384 13385 if (opts.controls.thumbnail && vars.total > 1) { 13386 vars.BODY.append(vars.thumbnails); 13387 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 13388 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 13389 vars.thumbs = true; 13390 } 13391 13392 //Configure loader and arrows 13393 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 13394 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 13395 } : { 13396 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 13397 }; 13398 vars.loader.addClass(opts.skin).css(loaderCss); 13399 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 13400 if (path == "horizontal") 13401 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 13402 13403 // Configure arrow buttons 13404 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 13405 13406 if (!opts.infinite) { 13407 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 13408 13409 if (vars.current == 0) 13410 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 13411 if (vars.current >= vars.total - 1) 13412 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 13413 } 13414 13415 if (opts.show.effect) { 13416 vars.overlay.stop().fadeIn(opts.show.speed); 13417 vars.toolbar.stop().fadeIn(opts.show.speed); 13418 } else { 13419 vars.overlay.show(); 13420 vars.toolbar.show(); 13421 } 13422 13423 var length = recognizingItems.length; 13424 if (needRecognition) { 13425 iL.showLoader(); 13426 13427 $.each(recognizingItems, function(key, val) { 13428 var resultFnc = function(result) { 13429 var key = -1, 13430 filter = iL.items.filter(function(e, i, arr) { 13431 if (e.URL == result.url) 13432 key = i; 13433 13434 return e.URL == result.url; 13435 }), 13436 self = iL.items[key]; 13437 13438 if (result) 13439 $.extend(true, self, { 13440 URL: result.source, 13441 type: result.type, 13442 recognized: true, 13443 options: { 13444 html5video: result.html5video, 13445 width: (result.type == "image") ? 0 : (result.width || self.width), 13446 height: (result.type == "image") ? 0 : (result.height || self.height), 13447 thumbnail: self.options.thumbnail || result.thumbnail 13448 } 13449 }); 13450 13451 length--; 13452 13453 if (length == 0) { 13454 iL.hideLoader(); 13455 13456 vars.dontGenerateThumbs = false;
13457 iL.generateThumbnails(); 13458 13459 if (opts.show.effect) 13460 setTimeout(function() { 13461 iL.generateBoxes(); 13462 }, opts.show.speed); 13463 else 13464 iL.generateBoxes(); 13465 } 13466 }; 13467 13468 iL.ogpRecognition(this, resultFnc); 13469 }); 13470 } 13471 else { 13472 if (opts.show.effect) 13473 setTimeout(function() { 13474 iL.generateBoxes(); 13475 }, opts.show.speed); 13476 else 13477 iL.generateBoxes(); 13478 } 13479 13480 iL.createUI(); 13481 13482 window.iLightBox = { 13483 close: function() { 13484 iL.closeAction(); 13485 }, 13486 fullscreen: function() { 13487 iL.fullScreenAction(); 13488 }, 13489 moveNext: function() { 13490 iL.moveTo('next'); 13491 }, 13492 movePrev: function() { 13493 iL.moveTo('prev'); 13494 }, 13495 goTo: function(index) { 13496 iL.goTo(index); 13497 }, 13498 refresh: function() { 13499 iL.refresh(); 13500 }, 13501 reposition: function() { 13502 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 13503 }, 13504 setOption: function(options) { 13505 iL.setOption(options); 13506 }, 13507 destroy: function() { 13508 iL.closeAction(); 13509 iL.dispatchItemsEvents(); 13510 } 13511 }; 13512 13513 if (opts.linkId) { 13514 vars.hashLock = true; 13515 window.location.hash = opts.linkId + '/' + vars.current; 13516 setTimeout(function() { 13517 vars.hashLock = false; 13518 }, 55); 13519 } 13520 13521 if (!opts.slideshow.startPaused) { 13522 iL.resume(); 13523 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 13524 } 13525 13526 //Trigger the onOpen callback 13527 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 13528 }, 13529 13530 loadContent: function(obj, opt, speed) { 13531 var iL = this, 13532 holder, item; 13533 13534 iL.createUI(); 13535 13536 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 13537 13538 if (opt == 'current') { 13539 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 13540 else iL.vars.lockWheel = false; 13541 13542 if (!obj.options.swipe) iL.vars.lockSwipe = true; 13543 else iL.vars.lockSwipe = false; 13544 } 13545 13546 switch (opt) { 13547 case 'current': 13548 holder = iL.vars.holder, item = iL.vars.current; 13549 break; 13550 case 'next': 13551 holder = iL.vars.nextPhoto, item = iL.vars.next; 13552 break; 13553 case 'prev': 13554 holder = iL.vars.prevPhoto, item = iL.vars.prev; 13555 break; 13556 } 13557 13558 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 13559 $('div.ilightbox-inner-toolbar', holder).remove(); 13560 13561 if (obj.title || iL.options.innerToolbar) { 13562 var innerToolbar = iL.vars.innerToolbar.clone(); 13563 if (obj.title && iL.options.show.title) { 13564 var title = iL.vars.title.clone(); 13565 title.empty().html(obj.title); 13566 innerToolbar.append(title); 13567 } 13568 if (iL.options.innerToolbar) { 13569 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 13570 } 13571 holder.prepend(innerToolbar); 13572 } 13573 13574 //console.warn('loadContent', arguments); 13575 13576 iL.loadSwitcher(obj, holder, item, opt); 13577 }, 13578 13579 loadSwitcher: function(obj, holder, item, opt) { 13580 var iL = this, 13581 opts = iL.options, 13582 api = { 13583 element: holder, 13584 position: item 13585 }; 13586 13587 switch (obj.type) { 13588 case 'image': 13589 //Trigger the onBeforeLoad callback 13590 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13591 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13592 13593 iL.loadImage(obj.URL, function(img) { 13594 //Trigger the onAfterLoad callback 13595 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13596 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13597 13598 var width = (img) ? img.width : 400, 13599 height = (img) ? img.height : 200; 13600 13601 holder.data({ 13602 naturalWidth: width, 13603 naturalHeight: height 13604 }); 13605 13606 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 13607 13608 //Trigger the onRender callback 13609 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13610 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13611 13612 iL.configureHolder(obj, opt, holder); 13613 }); 13614 13615 break; 13616
13617 case 'video': 13618 holder.data({ 13619 naturalWidth: obj.options.width, 13620 naturalHeight: obj.options.height 13621 }); 13622 13623 if (opt === 'current') { 13624 iL.addContent(holder, obj); 13625 13626 //Trigger the onRender callback 13627 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13628 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13629 } else { 13630 $('div.ilightbox-container', holder).empty(); 13631 } 13632 13633 iL.configureHolder(obj, opt, holder); 13634 13635 break; 13636 13637 case 'iframe': 13638 //iL.showLoader(); 13639 holder.data({ 13640 naturalWidth: obj.options.width, 13641 naturalHeight: obj.options.height 13642 }); 13643 13644 iL.configureHolder(obj, opt, holder); 13645 13646 if (opt === 'current') { 13647 var el = iL.addContent(holder, obj); 13648 13649 //Trigger the onRender callback 13650 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13651 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13652 13653 //Trigger the onBeforeLoad callback 13654 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13655 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13656 13657 el.bind('load', function() { 13658 //Trigger the onAfterLoad callback 13659 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13660 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13661 13662 //iL.hideLoader(); 13663 el.unbind('load'); 13664 }); 13665 } else { 13666 $('div.ilightbox-container', holder).empty(); 13667 } 13668 13669 break; 13670 13671 case 'inline': 13672 var el = $(obj.URL), 13673 content = iL.addContent(holder, obj), 13674 images = findImageInElement(holder); 13675 13676 holder.data({ 13677 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 13678 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 13679 }); 13680 content.children().eq(0).show(); 13681 13682 //Trigger the onRender callback 13683 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13684 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13685 13686 //Trigger the onBeforeLoad callback 13687 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13688 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13689 13690 iL.loadImage(images, function() { 13691 //Trigger the onAfterLoad callback 13692 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13693 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13694 13695 iL.configureHolder(obj, opt, holder); 13696 }); 13697 13698 break; 13699 13700 case 'flash': 13701 var el = iL.addContent(holder, obj); 13702 13703 holder.data({ 13704 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 13705 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 13706 }); 13707 13708 //Trigger the onRender callback 13709 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13710 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13711 13712 iL.configureHolder(obj, opt, holder); 13713 13714 break; 13715 13716 case 'ajax': 13717 var ajax = obj.options.ajax || {}; 13718 //Trigger the onBeforeLoad callback 13719 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13720 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13721 13722 iL.showLoader(); 13723 $.ajax({ 13724 url: obj.URL || opts.ajaxSetup.url, 13725 data: ajax.data || null, 13726 dataType: ajax.dataType || "html", 13727 type: ajax.type || opts.ajaxSetup.type, 13728 cache: ajax.cache || opts.ajaxSetup.cache, 13729 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 13730 global: ajax.global || opts.ajaxSetup.global, 13731 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 13732 username: ajax.username || opts.ajaxSetup.username, 13733 password: ajax.password || opts.ajaxSetup.password, 13734 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 13735 complete: ajax.complete || opts.ajaxSetup.complete, 13736 success: function(data, textStatus, jqXHR) { 13737 iL.hideLoader(); 13738 13739 var el = $(data), 13740 container = $('div.ilightbox-container', holder), 13741 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 13742 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 13743 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 13744 'overflow': 'hidden' 13745 } : {}; 13746 13747 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 13748 holder.show().data({
13749 naturalWidth: (elWidth || container.outerWidth()), 13750 naturalHeight: (elHeight || container.outerHeight()) 13751 }).hide(); 13752 13753 //Trigger the onRender callback 13754 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13755 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13756 13757 var images = findImageInElement(holder); 13758 iL.loadImage(images, function() { 13759 //Trigger the onAfterLoad callback 13760 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13761 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13762 13763 iL.configureHolder(obj, opt, holder); 13764 }); 13765 13766 opts.ajaxSetup.success(data, textStatus, jqXHR); 13767 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 13768 }, 13769 error: function(jqXHR, textStatus, errorThrown) { 13770 //Trigger the onAfterLoad callback 13771 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13772 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13773 13774 iL.hideLoader(); 13775 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 13776 iL.configureHolder(obj, opt, holder); 13777 13778 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 13779 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 13780 } 13781 }); 13782 13783 break; 13784 13785 case 'html': 13786 var object = obj.URL, 13787 el 13788 container = $('div.ilightbox-container', holder); 13789 13790 if (object[0].nodeName) el = object.clone(); 13791 else { 13792 var dom = $(object); 13793 if (dom.selector) el = $('<div>' + dom + '</div>'); 13794 else el = dom; 13795 } 13796 13797 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 13798 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 13799 13800 iL.addContent(holder, obj); 13801 13802 el.appendTo(document.documentElement).hide(); 13803 13804 //Trigger the onRender callback 13805 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13806 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13807 13808 var images = findImageInElement(holder); 13809 13810 //Trigger the onBeforeLoad callback 13811 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13812 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13813 13814 iL.loadImage(images, function() { 13815 //Trigger the onAfterLoad callback 13816 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13817 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13818 13819 holder.show().data({ 13820 naturalWidth: (elWidth || container.outerWidth()), 13821 naturalHeight: (elHeight || container.outerHeight()) 13822 }).hide(); 13823 el.remove(); 13824 13825 iL.configureHolder(obj, opt, holder); 13826 }); 13827 13828 break; 13829 } 13830 }, 13831 13832 configureHolder: function(obj, opt, holder) { 13833 var iL = this, 13834 vars = iL.vars, 13835 opts = iL.options; 13836 13837 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 13838 13839 if (opt == "current") 13840 var item = vars.current; 13841 else if (opt == "next") 13842 var opacity = opts.styles.nextOpacity, 13843 item = vars.next; 13844 else 13845 var opacity = opts.styles.prevOpacity, 13846 item = vars.prev; 13847 13848 var api = { 13849 element: holder, 13850 position: item 13851 }; 13852 13853 iL.items[item].options.width = iL.items[item].options.width || 0, 13854 iL.items[item].options.height = iL.items[item].options.height || 0; 13855 13856 if (opt == "current") { 13857 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 13858 holder.css(transform, ''); 13859 if (obj.caption) { 13860 iL.setCaption(obj, holder); 13861 var caption = $('div.ilightbox-caption', holder), 13862 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 13863 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
13863Speed); 13864 } 13865 13866 var social = obj.options.social; 13867 if (social) { 13868 iL.setSocial(social, obj.URL, holder); 13869 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 13870 } 13871 13872 //Generate thumbnails 13873 iL.generateThumbnails(); 13874 13875 //Trigger the onShow callback 13876 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13877 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13878 }); 13879 else { 13880 holder.show(); 13881 13882 //Generate thumbnails 13883 iL.generateThumbnails(); 13884 13885 //Trigger the onShow callback 13886 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13887 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13888 } 13889 } else { 13890 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 13891 if (opt == "next") vars.nextLock = false; 13892 else vars.prevLock = false; 13893 13894 //Generate thumbnails 13895 iL.generateThumbnails(); 13896 13897 //Trigger the onShow callback 13898 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13899 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13900 }); 13901 else { 13902 holder.css({ 13903 opacity: opacity 13904 }).show(); 13905 if (opt == "next") vars.nextLock = false; 13906 else vars.prevLock = false; 13907 13908 //Generate thumbnails 13909 iL.generateThumbnails(); 13910 13911 //Trigger the onShow callback 13912 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13913 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13914 } 13915 } 13916 13917 setTimeout(function() { 13918 iL.repositionPhoto(); 13919 }, 0); 13920 }, 13921 13922 generateBoxes: function() { 13923 var iL = this, 13924 vars = iL.vars, 13925 opts = iL.options; 13926 13927 if (opts.infinite && vars.total >= 3) { 13928 if (vars.current == vars.total - 1) vars.next = 0; 13929 if (vars.current == 0) vars.prev = vars.total - 1; 13930 } else opts.infinite = false; 13931 13932 //UNCODE addition 13933 if ( typeof iL.items[vars.current] == 'undefined' ) 13934 vars.current = 0; 13935 13936 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 13937 13938 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 13939 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 13940 }, 13941 13942 generateThumbnails: function() { 13943 var iL = this, 13944 vars = iL.vars, 13945 opts = iL.options, 13946 timeOut = null; 13947 13948 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 13949 var thumbnails = vars.thumbnails, 13950 container = $('div.ilightbox-thumbnails-container', thumbnails), 13951 grid = $('div.ilightbox-thumbnails-grid', container), 13952 i = 0; 13953 13954 grid.removeAttr('style').empty(); 13955 13956 $.each(iL.items, function(key, val) { 13957 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 13958 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 13959 thumb = val.options.thumbnail, 13960 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 13961 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 13962 13963 thumbnail.css({ 13964 opacity: 0 13965 }).addClass(isActive); 13966 13967 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 13968 icon.addClass('ilightbox-thumbnail-video'); 13969 thumbnail.append(icon); 13970 } else if (val.options.icon) { 13971 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 13972 thumbnail.append(icon); 13973 } 13974 13975 if (thumb) iL.loadImage(thumb, function(img) { 13976 i++; 13977 if (img) thumbnail.data({ 13978 naturalWidth: img.width, 13979 naturalHeight: img.height 13980 }).append('<img src="' + thumb + '" border="0" />'); 13981 else thumbnail.data({ 13982 naturalWidth: opts.thumbnails.maxWidth, 13983 naturalHeight: opts.thumbnails.maxHeight 13984 }); 13985 13986 clearTimeout(timeOut); 13987 timeOut = setTimeout(function() { 13988 iL.positionThumbnails(thumbnails, container, grid); 13989 }, 20); 13990 setTimeout(function() { 13991 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 13992 }, i * 20); 13993 }); 13994 13995 grid.append(thumbnail); 13996 }); 13997 iL.vars.dontGenerateThumbs = true; 13998 } 13999 }, 14000
14001 positionThumbnails: function(thumbnails, container, grid) { 14002 var iL = this, 14003 vars = iL.vars, 14004 opts = iL.options, 14005 viewport = getViewport(), 14006 path = opts.path.toLowerCase(); 14007 14008 if (!thumbnails) thumbnails = vars.thumbnails; 14009 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 14010 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 14011 14012 var thumbs = $('.ilightbox-thumbnail', grid), 14013 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 14014 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 14015 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 14016 gridHeight = (path == 'horizontal') ? heightAvail : 0, 14017 active = $('.ilightbox-active', grid), 14018 gridCss = {}, 14019 css = {}; 14020 14021 if (arguments.length < 3) { 14022 thumbs.css({ 14023 opacity: opts.thumbnails.normalOpacity 14024 }); 14025 active.css({ 14026 opacity: opts.thumbnails.activeOpacity 14027 }); 14028 } 14029 14030 thumbs.each(function(i) { 14031 var t = $(this), 14032 data = t.data(), 14033 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 14034 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 14035 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 14036 14037 t.css({ 14038 width: dims.width, 14039 height: dims.height 14040 }); 14041 if (path == 'horizontal') t.css({ 14042 'float': 'left' 14043 }); 14044 14045 (path == 'horizontal') ? ( 14046 gridWidth += t.outerWidth() 14047 ) : ( 14048 gridHeight += t.outerHeight() 14049 ); 14050 }); 14051 14052 gridCss = { 14053 width: gridWidth, 14054 height: gridHeight 14055 }; 14056 14057 grid.css(gridCss); 14058 14059 gridCss = {}; 14060 14061 var gridOffset = grid.offset(), 14062 activeOffset = (active.length) ? active.offset() : { 14063 top: parseInt(heightAvail / 2), 14064 left: parseInt(widthAvail / 2) 14065 }; 14066 14067 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 14068 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 14069 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 14070 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 14071 14072 (path == 'horizontal') ? ( 14073 gridCss.top = 0, 14074 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 14075 ) : ( 14076 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 14077 gridCss.left = 0 14078 ); 14079 14080 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 14081 else grid.css(gridCss); 14082 }, 14083 14084 loadImage: function(image, callback) { 14085 if (!$.isArray(image)) image = [image]; 14086 14087 var iL = this, 14088 length = image.length; 14089 14090 if (length > 0) { 14091 iL.showLoader(); 14092 $.each(image, function(index, value) { 14093 var img = new Image(); 14094 img.onload = function() { 14095 length -= 1; 14096 if (length == 0) { 14097 iL.hideLoader(); 14098 callback(img); 14099 } 14100 }; 14101 img.onerror = img.onabort = function() { 14102 length -= 1; 14103 if (length == 0) { 14104 iL.hideLoader(); 14105 callback(false); 14106 } 14107 }; 14108 img.src = image[index]; 14109 }); 14110 } else callback(false); 14111 }, 14112 14113 patchItemsEvents: function() { 14114 var iL = this, 14115 vars = iL.vars, 14116 clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL", 14117 vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL"; 14118 14119 if (iL.context && iL.selector) { 14120 var $items = $(iL.selector, iL.context); 14121 14122 $(iL.context).on(clickEvent, iL.selector, function() { 14123 var $this = $(this), 14124 //UNCODE addition 14125 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 14126 if (UNCODE.isMobile) { 14127 var isCarousel = $this.closest('.owl-carousel'); 14128 if (isCarousel.length) { 14129 if (isCarousel.hasClass('owl-translating')) return false; 14130 } 14131 } 14132 14133 vars.current = key; 14134 vars.next = iL.items[key + 1] ? key + 1 : null; 14135 vars.prev = iL.items[key - 1] ? key - 1 : null; 14136 14137 //UNCODE addition 14138 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 14139 return false;
14140 14141 iL.addContents(); 14142 iL.patchEvents(); 14143 14144 return false; 14145 }).on(vEvent, iL.selector, function() { 14146 return false; 14147 }); 14148 } else 14149 $.each(iL.itemsObject, function(key, val) { 14150 val.on(clickEvent, function() { 14151 vars.current = key; 14152 vars.next = iL.items[key + 1] ? key + 1 : null; 14153 vars.prev = iL.items[key - 1] ? key - 1 : null; 14154 14155 iL.addContents(); 14156 iL.patchEvents(); 14157 14158 return false; 14159 }).on(vEvent, function() { 14160 return false; 14161 }); 14162 }); 14163 }, 14164 14165 dispatchItemsEvents: function() { 14166 var iL = this, 14167 vars = iL.vars, 14168 opts = iL.options; 14169 14170 if (iL.context && iL.selector) 14171 $(iL.context).off('.iL', iL.selector); 14172 else 14173 $.each(iL.itemsObject, function(key, val) { 14174 val.off('.iL'); 14175 }); 14176 }, 14177 14178 refresh: function() { 14179 var iL = this; 14180 14181 iL.dispatchItemsEvents(); 14182 iL.attachItems(); 14183 iL.normalizeItems(); 14184 iL.patchItemsEvents(); 14185 }, 14186 14187 patchEvents: function() { 14188 var iL = this, 14189 vars = iL.vars, 14190 opts = iL.options, 14191 path = opts.path.toLowerCase(), 14192 holders = $('.ilightbox-holder'), 14193 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 14194 durationThreshold = 1000, 14195 horizontalDistanceThreshold = 14196 verticalDistanceThreshold = 100, 14197 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 14198 14199 $win.bind('resize.iLightBox', function() { 14200 var viewport = getViewport(); 14201 14202 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 14203 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 14204 14205 iL.repositionPhoto(null); 14206 if (supportTouch) { 14207 clearTimeout(vars.setTime); 14208 vars.setTime = setTimeout(function() { 14209 var scrollTop = getScrollXY().y; 14210 window.scrollTo(0, scrollTop - 30); 14211 window.scrollTo(0, scrollTop + 30); 14212 window.scrollTo(0, scrollTop); 14213 }, 2000); 14214 } 14215 if (vars.thumbs) iL.positionThumbnails(); 14216 }).bind('keydown.iLightBox', function(event) { 14217 if (opts.controls.keyboard) { 14218 switch (event.keyCode) { 14219 case 13: 14220 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 14221 break; 14222 case 27: 14223 if (opts.keyboard.esc) iL.closeAction(); 14224 break; 14225 case 37: 14226 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 14227 break; 14228 case 38: 14229 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 14230 break; 14231 case 39: 14232 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 14233 break; 14234 case 40: 14235 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 14236 break; 14237 } 14238 } 14239 }); 14240 14241 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 14242 iL.doFullscreen(); 14243 }); 14244 14245 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 14246 return arr.lastIndexOf(e) === i; 14247 }), 14248 holderEvents = ""; 14249 14250 $.each(holderEventsArr, function(key, val) { 14251 if (key != 0) holderEvents += ' '; 14252 holderEvents += val; 14253 }); 14254 14255 $doc.on(clickEvent, '.ilightbox-overlay', function() { 14256 if (opts.overlay.blur) iL.closeAction(); 14257 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 14258 iL.moveTo('next'); 14259 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 14260 iL.moveTo('prev'); 14261 }).on(clickEvent, '.ilightbox-thumbnail', function() { 14262 var t = $(this), 14263 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 14264 index = thumbs.index(t); 14265 14266 if (index != vars.current) iL.goTo(index); 14267 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 14268 var caption = $('div.ilightbox-caption', vars.holder), 14269 social = $('div.ilightbox-social', vars.holder), 14270 fadeSpeed = opts.effects.fadeSpeed; 14271 14272 if (vars.nextLock || vars.prevLock) { 14273 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 14274 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 14275 14276 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 14277 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 14278 } else { 14279 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 14280 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 14281 14282 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 14283 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 14284 } 14285 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 14286 if (e.type == 'mouseenter') vars.lockWheel = true; 14287 else vars.lockWheel = false;
14288 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 14289 var t = $(this); 14290 14291 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 14292 else if (t.hasClass('ilightbox-play')) { 14293 iL.resume(); 14294 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 14295 } else if (t.hasClass('ilightbox-pause')) { 14296 iL.pause(); 14297 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 14298 } else iL.closeAction(); 14299 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 14300 // prevent scrolling 14301 e.preventDefault(); 14302 }); 14303 14304 function mouseMoveHandler(e) { 14305 if (!vars.isMobile) { 14306 if (!vars.mouseID) { 14307 vars.hideableElements.show(); 14308 } 14309 14310 vars.mouseID = clearTimeout(vars.mouseID); 14311 14312 if (buttonsArray.indexOf(e.target) === -1) 14313 vars.mouseID = setTimeout(function() { 14314 vars.hideableElements.hide(); 14315 vars.mouseID = clearTimeout(vars.mouseID); 14316 }, 3000); 14317 } 14318 } 14319 14320 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 14321 14322 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 14323 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 14324 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 14325 }); 14326 14327 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'), 14328 delay = false; 14329 14330 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 14331 event.preventDefault(); 14332 if (delay) return; 14333 delay = true; 14334 if (!vars.lockWheel) { 14335 event.preventDefault(); 14336 if (delta < 0) { 14337 iL.moveTo('next'); 14338 } else if (delta > 0) { 14339 iL.moveTo('prev'); 14340 } 14341 } 14342 setTimeout(function(){
14343 delay = false; 14344 }, 2000); 14345 }); 14346 14347 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 14348 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 14349 14350 vars.BODY.addClass('ilightbox-closedhand'); 14351 14352 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 14353 scrollTop = $doc.scrollTop(), 14354 scrollLeft = $doc.scrollLeft(), 14355 offsets = [ 14356 holders.eq(0).offset(), 14357 holders.eq(1).offset(), 14358 holders.eq(2).offset() 14359 ], 14360 offSet = [{ 14361 top: offsets[0].top - scrollTop, 14362 left: offsets[0].left - scrollLeft 14363 }, { 14364 top: offsets[1].top - scrollTop, 14365 left: offsets[1].left - scrollLeft 14366 }, { 14367 top: offsets[2].top - scrollTop, 14368 left: offsets[2].left - scrollLeft 14369 }], 14370 start = { 14371 time: (new Date()).getTime(), 14372 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 14373 }, 14374 stop; 14375 14376 function moveEachHandler(i) { 14377 var t = $(this), 14378 offset = offSet[i], 14379 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 14380 14381 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 14382 } 14383 14384 function moveHandler(event) { 14385 14386 if (!start) return; 14387 14388 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 14389 14390 stop = { 14391 time: (new Date()).getTime(), 14392 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 14393 }; 14394 14395 holders.each(moveEachHandler); 14396 14397 // prevent scrolling 14398 event.preventDefault(); 14399 } 14400 14401 function repositionHolders() { 14402 holders.each(function() { 14403 var t = $(this), 14404 offset = t.data('offset') || { 14405 top: t.offset().top - scrollTop, 14406 left: t.offset().left - scrollLeft 14407 }, 14408 top = offset.top, 14409 left = offset.left; 14410 14411 t.css(transform, gpuAcceleration).stop().animate({ 14412 top: top, 14413 left: left 14414 }, 500, 'easeOutCirc', function() { 14415 t.css(transform, ''); 14416 }); 14417 }); 14418 } 14419 14420 holders.bind(touchMoveEvent, moveHandler); 14421 $doc.one(touchStopEvent, function(event) { 14422 holders.unbind(touchMoveEvent, moveHandler); 14423 14424 vars.BODY.removeClass('ilightbox-closedhand'); 14425 14426 if (start && stop) { 14427 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 14428 if (start.coords[0] > stop.coords[0]) { 14429 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 14430 else { 14431 vars.isSwipe = true; 14432 iL.moveTo('next'); 14433 } 14434 } else { 14435 if (vars.current == 0 && !opts.infinite) repositionHolders(); 14436 else { 14437 vars.isSwipe = true; 14438 iL.moveTo('prev'); 14439 } 14440 } 14441 } else if (path == "vertical" && stop.time - start.time < durationThreshold && abs(start.coords[1] - stop.coords[1]) > horizontalDistanceThreshold && abs(start.coords[0] - stop.coords[0]) < verticalDistanceThreshold) { 14442 if (start.coords[1] > stop.coords[1]) { 14443 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 14444 else { 14445 vars.isSwipe = true; 14446 iL.moveTo('next'); 14447 } 14448 } else { 14449 if (vars.current == 0 && !opts.infinite) repositionHolders(); 14450 else { 14451 vars.isSwipe = true; 14452 iL.moveTo('prev'); 14453 } 14454 } 14455 } else repositionHolders(); 14456 } 14457 start = stop = undefined; 14458 }); 14459 }); 14460 14461 }, 14462 14463 goTo: function(index) { 14464 var iL = this, 14465 vars = iL.vars, 14466 opts = iL.options, 14467 diff = (index - vars.current); 14468 14469 if (opts.infinite) { 14470 if (index == vars.total - 1 && vars.current == 0) diff = -1; 14471 if (vars.current == vars.total - 1 && index == 0) diff = 1; 14472 } 14473 14474 if (diff == 1) iL.moveTo('next'); 14475 else if (diff == -1) iL.moveTo('prev'); 14476 else { 14477 14478 if (vars.nextLock || vars.prevLock) return false; 14479 14480 //Trigger the onBeforeChange callback 14481 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 14482 14483 if (opts.linkId) { 14484 vars.hashLock = true; 14485 window.location.hash = opts.linkId + '/' + index; 14486 } 14487 14488 if (iL.items[index]) { 14489 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 14490 else iL.vars.lockWheel = false;
14491 14492 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 14493 else vars.lockSwipe = false; 14494 } 14495 14496 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 14497 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 14498 }); 14499 14500 vars.current = index; 14501 vars.next = index + 1; 14502 vars.prev = index - 1; 14503 14504 iL.createUI(); 14505 14506 setTimeout(function() { 14507 iL.generateBoxes(); 14508 }, opts.effects.loadedFadeSpeed + 50); 14509 14510 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 14511 iL.positionThumbnails(); 14512 14513 if (opts.linkId) setTimeout(function() { 14514 vars.hashLock = false; 14515 }, 55); 14516 14517 // Configure arrow buttons 14518 if (!opts.infinite) { 14519 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 14520 14521 if (vars.current == 0) { 14522 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 14523 } 14524 if (vars.current >= vars.total - 1) { 14525 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 14526 } 14527 } 14528 14529 // Reset next cycle timeout 14530 iL.resetCycle(); 14531 14532 //Trigger the onAfterChange callback 14533 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 14534 } 14535 }, 14536 14537 moveTo: function(side) { 14538 var iL = this, 14539 vars = iL.vars, 14540 opts = iL.options, 14541 path = opts.path.toLowerCase(), 14542 viewport = getViewport(), 14543 switchSpeed = opts.effects.switchSpeed; 14544 14545 if (vars.nextLock || vars.prevLock) return false; 14546 else { 14547 14548 var item = (side == "next") ? vars.next : vars.prev; 14549 14550 if (opts.linkId) { 14551 vars.hashLock = true; 14552 window.location.hash = opts.linkId + '/' + item; 14553 } 14554 14555 if (side == "next") { 14556 if (!iL.items[item]) return false; 14557 var firstHolder = vars.nextPhoto, 14558 secondHolder = vars.holder, 14559 lastHolder = vars.prevPhoto, 14560 firstClass = 'ilightbox-prev', 14561 secondClass = 'ilightbox-next'; 14562 } else if (side == "prev") { 14563 if (!iL.items[item]) return false; 14564 var firstHolder = vars.prevPhoto, 14565 secondHolder = vars.holder, 14566 lastHolder = vars.nextPhoto, 14567 firstClass = 'ilightbox-next', 14568 secondClass = 'ilightbox-prev'; 14569 } 14570 14571 //Trigger the onBeforeChange callback 14572 if (typeof opts.callback.onBeforeChange == 'function') 14573 opts.callback.onBeforeChange.call(iL, iL.ui); 14574 14575 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 14576 14577 var captionFirst = $('div.ilightbox-caption', secondHolder), 14578 socialFirst = $('div.ilightbox-social', secondHolder); 14579 14580 if (captionFirst.length) 14581 captionFirst.stop().fadeOut(switchSpeed, function() { 14582 $(this).remove(); 14583 }); 14584 if (socialFirst.length) 14585 socialFirst.stop().fadeOut(switchSpeed, function() { 14586 $(this).remove(); 14587 }); 14588 14589 if (iL.items[item].caption) { 14590 iL.setCaption(iL.items[item], firstHolder); 14591 var caption = $('div.ilightbox-caption', firstHolder), 14592 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 14593 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 14594 } 14595 14596 var social = iL.items[item].options.social; 14597 if (social) { 14598 iL.setSocial(social, iL.items[item].URL, firstHolder); 14599 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 14600 } 14601 14602 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 14603 val.removeClass('ilightbox-next ilightbox-prev'); 14604 }); 14605 14606 var firstOffset = firstHolder.data('offset'), 14607 winW = (viewport.width - (opts.styles.pageOffsetX)), 14608 winH = (viewport.height - (opts.styles.pageOffsetY)), 14609 width = firstOffset.newDims.width, 14610 height = firstOffset.newDims.height, 14611 thumbsOffset = firstOffset.thumbsOffset, 14612 diff = firstOffset.diff, 14613 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 14614 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 14615 14616 var secondOffset = secondHolder.data('offset'), 14617 object = secondOffset.object; 14618 14619 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 14620 var objRatio = width / height; 14621 height = height - vars.captionHeight; 14622 width = height * objRatio; 14623 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 14624 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 14625 }*/ 14626 14627 firstHolder.show().css(transform, gpuAcceleration).animate({ 14628 top: top, 14629 left: left, 14630 opacity: 1 14631 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 14632 firstHolder.css(transform, ''); 14633 }); 14634 14635 $('div.ilightbox-container', firstHolder).animate({ 14636 width: width, 14637 height: height 14638 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 14639 14640 diff = secondOffset.diff; 14641 14642 width = secondOffset.newDims.width, 14643 height = secondOffset.newDims.height; 14644 14645 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 14646 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 14647 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 14648 14649 if (side == 'prev') 14650 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 14651 else { 14652 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 14653 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 14654 } 14655 14656 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 14657 var objRatio = width / height; 14658 height = height - vars.captionHeight; 14659 width = height * objRatio; 14660 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 14661 }*/ 14662 14663 $('div.ilightbox-container', secondHolder).animate({ 14664 width: width, 14665 height: height 14666 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 14667 14668 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 14669 top: top, 14670 left: left, 14671 opacity: opts.styles.prevOpacity, 14672 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 14673 secondHolder.css(transform, ''); 14674
14675 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 14676 iL.positionThumbnails(); 14677 14678 if (iL.items[item]) { 14679 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 14680 else vars.lockWheel = false; 14681 14682 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 14683 else vars.lockSwipe = false; 14684 } 14685 14686 vars.isSwipe = false; 14687 14688 // Remove iframe & video from previous slide 14689 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 14690 $('div.ilightbox-container', secondHolder).empty(); 14691 } 14692 14693 if (side == "next") { 14694 vars.nextPhoto = lastHolder, 14695 vars.prevPhoto = secondHolder, 14696 vars.holder = firstHolder; 14697 14698 vars.nextPhoto.hide(); 14699 14700 vars.next = vars.next + 1, 14701 vars.prev = vars.current, 14702 vars.current = vars.current + 1; 14703 14704 if (opts.infinite) { 14705 if (vars.current > vars.total - 1) vars.current = 0; 14706 if (vars.current == vars.total - 1) vars.next = 0; 14707 if (vars.current == 0) vars.prev = vars.total - 1; 14708 } 14709 14710 iL.createUI(); 14711 14712 if (!iL.items[vars.next]) 14713 vars.nextLock = false; 14714 else 14715 iL.loadContent(iL.items[vars.next], 'next'); 14716 } else { 14717 vars.prevPhoto = lastHolder; 14718 vars.nextPhoto = secondHolder; 14719 vars.holder = firstHolder; 14720 14721 vars.prevPhoto.hide(); 14722 14723 vars.next = vars.current; 14724 vars.current = vars.prev; 14725 vars.prev = vars.current - 1; 14726 14727 if (opts.infinite) { 14728 if (vars.current == vars.total - 1) vars.next = 0; 14729 if (vars.current == 0) vars.prev = vars.total - 1; 14730 } 14731 14732 iL.createUI(); 14733 14734 if (!iL.items[vars.prev]) 14735 vars.prevLock = false; 14736 else 14737 iL.loadContent(iL.items[vars.prev], 'prev'); 14738 } 14739 14740 // Add iframe & video content for current slide 14741 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 14742 iL.loadContent(iL.items[vars.current], 'current'); 14743 } 14744 14745 if (opts.linkId) setTimeout(function() { 14746 vars.hashLock = false; 14747 }, 55); 14748 14749 // Configure arrow buttons 14750 if (!opts.infinite) { 14751 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 14752 14753 if (vars.current == 0) 14754 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 14755 if (vars.current >= vars.total - 1) 14756 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 14757 } 14758 14759 iL.repositionPhoto(); 14760 14761 // Reset next cycle timeout 14762 iL.resetCycle(); 14763 14764 //Trigger the onAfterChange callback 14765 if (typeof opts.callback.onAfterChange == 'function') 14766 opts.callback.onAfterChange.call(iL, iL.ui); 14767 }); 14768 14769 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 14770 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 14771 14772 lastHolder.css(transform, gpuAcceleration).animate({ 14773 top: top, 14774 left: left, 14775 opacity: opts.styles.nextOpacity 14776 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 14777 lastHolder.css(transform, ''); 14778 }).addClass(secondClass); 14779 } 14780 }, 14781 14782 setCaption: function(obj, target) { 14783 var iL = this, 14784 caption = $('<div class="ilightbox-caption"></div>'); 14785 14786 if (obj.caption) { 14787 caption.html(obj.caption); 14788 $('div.ilightbox-container', target).append(caption); 14789 } 14790 }, 14791 14792 normalizeSocial: function(obj, url) { 14793 var iL = this, 14794 vars = iL.vars, 14795 opts = iL.options, 14796 baseURL = window.location.href; 14797 14798 $.each(obj, function(key, value) { 14799 if (!value) 14800 return true; 14801 14802 var item = key.toLowerCase(), 14803 source, text; 14804 14805 switch (item) { 14806 case 'facebook': 14807 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 14808 text = "Share on Facebook"; 14809 break; 14810 case 'twitter': 14811 source = "http://twitter.com/home?status={URL}", 14812 text = "Share on Twitter"; 14813 break; 14814 case 'digg': 14815 source = "http://digg.com/submit?phase=2&url={URL}", 14816 text = "Share on Digg"; 14817 break; 14818 case 'reddit': 14819 source = "http://reddit.com/submit?url={URL}", 14820 text = "Share on reddit"; 14821 break; 14822 } 14823 14824 obj[key] = { 14825 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 14826 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 14827 text: value.text || text || "Share on " + key, 14828 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 14829 height: value.height || 360 14830 }; 14831 14832 }); 14833 14834 return obj; 14835 }, 14836 14837 setSocial: function(obj, url, target) { 14838 var iL = this, 14839 socialBar = $('<div class="ilightbox-social"></div>'), 14840 buttons = '<ul>'; 14841 14842 obj = iL.normalizeSocial(obj, url); 14843 14844 $.each(obj, function(key, value) { 14845 var item = key.toLowerCase(), 14846 source = value.source.replace(/\{URL\}/g, encodeURIComponent(value.URL).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+')); 14847 buttons += '<li class="' + key + '"><a href="' + source + '" onclick="javascript:window.open(this.href' + ((value.width <= 0 || value.height <= 0) ? '' : ', \'\', \'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=' + value.height + ',width=' + value.width + ',left=40,top=40\'') + ');return false;" title="' + value.text + '" target="_blank"></a></li>'; 14848 }); 14849 14850 buttons += '</ul>'; 14851 14852 socialBar.html(buttons); 14853 $('div.ilightbox-container', target).append(socialBar); 14854 }, 14855 14856 fullScreenAction: function() { 14857 var iL = this, 14858 vars = iL.vars; 14859 14860 if (fullScreenApi.supportsFullScreen) { 14861 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 14862 else fullScreenApi.requestFullScreen(document.documentElement); 14863 } else { 14864 iL.doFullscreen(); 14865 } 14866 }, 14867 14868 doFullscreen: function() { 14869 var iL = this, 14870 vars = iL.vars, 14871 viewport = getViewport(), 14872 opts = iL.options; 14873 14874 if (opts.fullAlone) { 14875 var currentHolder = vars.holder, 14876 current = iL.items[vars.current], 14877 windowWidth = viewport.width, 14878 windowHeight = viewport.height, 14879 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 14880 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 14881 14882 if (!vars.isInFullScreen) { 14883 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 14884 vars.overlay.css({ 14885 opacity: 1 14886 }); 14887 14888 $.each(hideElements, function(i, element) { 14889 element.hide(); 14890 }); 14891 14892 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 14893 14894 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
14895 naturalWidthOld: currentHolder.data('naturalWidth'), 14896 naturalHeightOld: currentHolder.data('naturalHeight'), 14897 naturalWidth: windowWidth, 14898 naturalHeight: windowHeight 14899 }); 14900 else { 14901 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 14902 newWidth = windowWidth, 14903 newHeight = windowHeight, 14904 width = currentHolder.data('naturalWidth'), 14905 height = currentHolder.data('naturalHeight'); 14906 14907 if (viewport.toLowerCase() == 'fill') { 14908 newHeight = (newWidth / width) * height; 14909 14910 if (newHeight < windowHeight) { 14911 newWidth = (windowHeight / height) * width, 14912 newHeight = windowHeight; 14913 } 14914 } else if (viewport.toLowerCase() == 'fit') { 14915 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 14916 14917 newWidth = dims.width, 14918 newHeight = dims.height; 14919 } else if (viewport.toLowerCase() == 'stretch') { 14920 newWidth = newWidth, 14921 newHeight = newHeight; 14922 } else { 14923 var scale = (width > newWidth || height > newHeight) ? true : false, 14924 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 14925 newWidth = dims.width, 14926 newHeight = dims.height; 14927 } 14928 14929 currentHolder.data({ 14930 naturalWidthOld: currentHolder.data('naturalWidth'), 14931 naturalHeightOld: currentHolder.data('naturalHeight'), 14932 naturalWidth: newWidth, 14933 naturalHeight: newHeight 14934 }); 14935 } 14936 14937 $.each(elements, function(key, val) { 14938 val.addClass('ilightbox-fullscreen'); 14939 }); 14940 14941 //Trigger the onEnterFullScreen callback 14942 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 14943 } else { 14944 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 14945 vars.overlay.css({ 14946 opacity: iL.options.overlay.opacity 14947 }); 14948 14949 $.each(hideElements, function(i, element) { 14950 element.show(); 14951 }); 14952 14953 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 14954 14955 currentHolder.data({ 14956 naturalWidth: currentHolder.data('naturalWidthOld'), 14957 naturalHeight: currentHolder.data('naturalHeightOld'), 14958 naturalWidthOld: null, 14959 naturalHeightOld: null 14960 }); 14961 14962 $.each(elements, function(key, val) { 14963 val.removeClass('ilightbox-fullscreen'); 14964 }); 14965 14966 //Trigger the onExitFullScreen callback 14967 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 14968 } 14969 } else { 14970 if (!vars.isInFullScreen) vars.isInFullScreen = true; 14971 else vars.isInFullScreen = false; 14972 } 14973 iL.repositionPhoto(true); 14974 }, 14975 14976 closeAction: function() { 14977 var iL = this, 14978 vars = iL.vars, 14979 opts = iL.options; 14980 14981 $win.unbind('.iLightBox'); 14982 $doc.off('.iLightBox'); 14983 14984 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 14985 14986 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 14987 14988 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 14989 vars.overlay.remove(); 14990 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 14991 }); 14992 else { 14993 vars.overlay.remove(); 14994 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 14995 } 14996 14997 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 14998 14999 $.each(fadeOuts, function(i, element) { 15000 element.removeAttr('style').remove(); 15001 }); 15002 15003 vars.dontGenerateThumbs = vars.isInFullScreen = false; 15004 15005 window.iLightBox = null; 15006 15007 if (opts.linkId) { 15008 vars.hashLock = true; 15009 removeHash(); 15010 setTimeout(function() { 15011 vars.hashLock = false; 15012 }, 55); 15013 } 15014 15015 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 15016 15017 //Trigger the onHide callback 15018 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 15019 }, 15020 15021 repositionPhoto: function() { 15022 var iL = this, 15023 vars = iL.vars, 15024 opts = iL.options, 15025 path = opts.path.toLowerCase(), 15026 viewport = getViewport(), 15027 winWidth = viewport.width, 15028 winHeight = viewport.height; 15029 15030 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 15031 15032 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 15033 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 15034 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 15035 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 15036 offsetW = (path == 'horizontal') ? parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((width / 10) <= 30) ? 30 : (width / 10))) : parseInt(((width / 10) <= 30) ? 30 : (width / 10)) + thumbsOffsetW, 15037 offsetH = (path == 'horizontal') ? parseInt(((height / 10) <= 30) ? 30 : (height / 10)) + thumbsOffsetH : parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((height / 10) <= 30) ? 30 : (height / 10))); 15038 15039 var elObject = { 15040 type: 'current', 15041 width: width, 15042 height: height, 15043 item: iL.items[vars.current], 15044 offsetW: offsetW, 15045 offsetH: offsetH,
15046 thumbsOffsetW: thumbsOffsetW, 15047 thumbsOffsetH: thumbsOffsetH, 15048 animate: arguments.length, 15049 holder: vars.holder 15050 }; 15051 15052 iL.repositionEl(elObject); 15053 15054 if (iL.items[vars.next]) { 15055 elObject = $.extend(elObject, { 15056 type: 'next', 15057 item: iL.items[vars.next], 15058 offsetX: opts.styles.nextOffsetX, 15059 offsetY: opts.styles.nextOffsetY, 15060 holder: vars.nextPhoto 15061 }); 15062 15063 iL.repositionEl(elObject); 15064 } 15065 15066 if (iL.items[vars.prev]) { 15067 elObject = $.extend(elObject, { 15068 type: 'prev', 15069 item: iL.items[vars.prev], 15070 offsetX: opts.styles.nextOffsetX, 15071 offsetY: opts.styles.prevOffsetY, 15072 holder: vars.prevPhoto 15073 }); 15074 15075 iL.repositionEl(elObject); 15076 } 15077 15078 var loaderCss = (path == "horizontal") ? { 15079 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 15080 } : { 15081 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 15082 }; 15083 vars.loader.css(loaderCss); 15084 }, 15085 15086 repositionEl: function(obj) { 15087 var iL = this, 15088 vars = iL.vars, 15089 opts = iL.options, 15090 path = opts.path.toLowerCase(), 15091 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 15092 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 15093 itemParent = obj.item, 15094 item = obj.item.options, 15095 holder = obj.holder, 15096 offsetX = obj.offsetX || 0, 15097 offsetY = obj.offsetY || 0, 15098 //Uncode change ##START## 15099 toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0, 15100 //Uncode change ##END## 15101 thumbsOffsetW = obj.thumbsOffsetW, 15102 thumbsOffsetH = obj.thumbsOffsetH; 15103 15104 if (obj.type == 'current') { 15105 if (typeof item.width == 'number' && item.width) widthAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? widthAvail : ((item.width > widthAvail) ? widthAvail : item.width); 15106 if (typeof item.height == 'number' && item.height) heightAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? heightAvail : ((item.height > heightAvail) ? heightAvail : item.height); 15107 } else { 15108 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 15109 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 15110 } 15111 15112 15113 //Uncode change ##START## 15114 heightAvail = parseInt(heightAvail - toolbarHeight); 15115 // heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 15116 //Uncode change ##END## 15117 15118 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 15119 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 15120 15121 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 15122 width: width, 15123 height: height 15124 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 15125 newDims = $.extend({}, dims, {}); 15126 15127 if (obj.type == 'prev' || obj.type == 'next') 15128 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 15129 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 15130 else 15131 width = dims.width, 15132 height = dims.height; 15133 15134 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 15135 heightDiff = parseInt((getPixel(holder, 'padding-top') + getPixel(holder, 'padding-bottom') + getPixel(holder, 'border-top-width') + getPixel(holder, 'border-bottom-width') + ($('.ilightbox-inner-toolbar', holder).outerHeight() || 0)) / 2); 15136 15137 switch (obj.type) { 15138 case 'current': 15139 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 15140 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 15141 break; 15142
15143 case 'next': 15144 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 15145 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 15146 break; 15147 15148 case 'prev': 15149 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 15150 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 15151 break; 15152 } 15153 15154 holder.data('offset', { 15155 top: top, 15156 left: left, 15157 newDims: newDims, 15158 diff: { 15159 W: widthDiff, 15160 H: heightDiff 15161 }, 15162 thumbsOffset: { 15163 W: thumbsOffsetW, 15164 H: thumbsOffsetH 15165 }, 15166 object: obj 15167 }); 15168 15169 var opacityMobile; 15170 if ( isMobile ) { 15171 opacityMobile = { 15172 opacity: 1, 15173 top: top, 15174 left: left 15175 }; 15176 } else { 15177 opacityMobile = { 15178 top: top, 15179 left: left 15180 }; 15181 } 15182 15183 if (obj.animate > 0 && opts.effects.reposition) { 15184 holder.css(transform, gpuAcceleration).stop().animate( 15185 opacityMobile, 15186 opts.effects.repositionSpeed, 'easeOutCirc', function() { 15187 holder.css(transform, ''); 15188 }); 15189 $('div.ilightbox-container', holder).stop().animate({ 15190 width: width, 15191 height: height 15192 }, opts.effects.repositionSpeed, 'easeOutCirc'); 15193 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 15194 width: width 15195 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 15196 $(this).css('overflow', 'visible'); 15197 }); 15198 } else { 15199 holder.css(opacityMobile); 15200 $('div.ilightbox-container', holder).css({ 15201 width: width, 15202 height: height 15203 }); 15204 $('div.ilightbox-inner-toolbar', holder).css({ 15205 width: width 15206 }); 15207 } 15208 }, 15209 15210 15211 resume: function(priority) { 15212 var iL = this, 15213 vars = iL.vars, 15214 opts = iL.options; 15215 15216 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 15217 return; 15218 } 15219 15220 vars.isPaused = 0; 15221 15222 if (vars.cycleID) { 15223 vars.cycleID = clearTimeout(vars.cycleID); 15224 } 15225 15226 vars.cycleID = setTimeout(function() { 15227 if (vars.current == vars.total - 1) iL.goTo(0); 15228 else iL.moveTo('next'); 15229 }, opts.slideshow.pauseTime); 15230 }, 15231 15232 pause: function(priority) { 15233 var iL = this, 15234 vars = iL.vars, 15235 opts = iL.options; 15236 15237 if (priority < vars.isPaused) { 15238 return; 15239 } 15240 15241 vars.isPaused = priority || 100; 15242 15243 if (vars.cycleID) { 15244 vars.cycleID = clearTimeout(vars.cycleID); 15245 } 15246 }, 15247 15248 resetCycle: function() { 15249 var iL = this, 15250 vars = iL.vars, 15251 opts = iL.options; 15252 15253 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 15254 iL.resume(); 15255 } 15256 }, 15257 15258 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 15259 var iL = this; 15260 15261 if (!width) factor = height / height_old; 15262 else if (!height) factor = width / width_old; 15263 else factor = min(width / width_old, height / height_old); 15264 15265 if (!thumb) { 15266 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 15267 else if (factor < iL.options.minScale) factor = iL.options.minScale; 15268 } 15269 15270 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 15271 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 15272 15273 return { 15274 width: final_width, 15275 height: final_height, 15276 ratio: factor 15277 }; 15278 }, 15279 15280 setOption: function(options) { 15281 var iL = this; 15282 15283 iL.options = $.extend(true, iL.options, options || {}); 15284 iL.refresh(); 15285 }, 15286 15287 availPlugins: function() { 15288 var iL = this, 15289 testEl = document.createElement("video"); 15290 15291 iL.plugins = { 15292 flash: !isMobile, 15293 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 15294 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 15295 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 15296 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 15297 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 15298 }; 15299 }, 15300 15301 addContent: function(element, obj) { 15302 var iL = this, 15303 el; 15304 15305 switch (obj.type) { 15306 case 'video': 15307 var HTML5 = false, 15308 videoType = obj.videoType, 15309 html5video = obj.options.html5video; 15310 15311 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 15312 obj.ext = 'mp4', 15313 obj.URL = html5video.h264 || obj.URL; 15314 else if (html5video.webm && iL.plugins.html5WebM) 15315 obj.ext = 'webm', 15316 obj.URL = html5video.webm || obj.URL; 15317 else if (html5video.ogg && iL.plugins.html5Vorbis) 15318 obj.ext = 'ogv', 15319 obj.URL = html5video.ogg || obj.URL; 15320 15321 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 15322 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 15323 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 15324 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 15325 15326 if (HTML5) { 15327 el = $('<video />
15327', { 15328 "width": "100%", 15329 "height": "100%", 15330 "preload": html5video.preload, 15331 "autoplay": html5video.autoplay, 15332 "loop": html5video.loop, 15333 "poster": html5video.poster, 15334 "controls": html5video.controls, 15335 "controlslist": "nodownload" 15336 }).append($('<source />', { 15337 "src": obj.URL, 15338 "type": videoType 15339 })); 15340 } else { 15341 if (!iL.plugins.quicktime) el = $('<span />', { 15342 "class": "ilightbox-alert", 15343 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 15344 }); 15345 else { 15346 15347 el = $('<object />', { 15348 "type": "video/quicktime", 15349 "pluginspage": pluginspages.quicktime 15350 }).attr({ 15351 "data": obj.URL, 15352 "width": "100%", 15353 "height": "100%" 15354 }).append($('<param />', { 15355 "name": "src", 15356 "value": obj.URL 15357 })).append($('<param />', { 15358 "name": "autoplay", 15359 "value": "false" 15360 })).append($('<param />', { 15361 "name": "loop", 15362 "value": "false" 15363 })).append($('<param />', { 15364 "name": "scale", 15365 "value": "tofit" 15366 })); 15367 15368 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 15369 } 15370 } 15371 15372 break; 15373 15374 case 'flash': 15375 if (!iL.plugins.flash) el = $('<span />', { 15376 "class": "ilightbox-alert", 15377 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 15378 }); 15379 else { 15380 var flashvars = "", 15381 i = 0; 15382 15383 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 15384 if (i != 0) flashvars += "&"; 15385 flashvars += k + "=" + encodeURIComponent(v); 15386 i++; 15387 }); 15388 else flashvars = null; 15389 15390 el = $('<embed />').attr({ 15391 "type": "application/x-shockwave-flash", 15392 "src": obj.URL, 15393 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 15394 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 15395 "quality": "high", 15396 "bgcolor": "#000000", 15397 "play": "true", 15398 "loop": "true", 15399 "menu": "true", 15400 "wmode": "transparent", 15401 "scale": "showall", 15402 "allowScriptAccess": "always", 15403 "allowFullScreen": "true", 15404 "flashvars": flashvars, 15405 "fullscreen": "yes" 15406 }); 15407 } 15408 15409 break; 15410 15411 case 'iframe': 15412 el = $('<iframe />').attr({ 15413 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 15414 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 15415 src: obj.URL, 15416 frameborder: 0, 15417 'hspace': 0, 15418 'vspace': 0, 15419 'scrolling': supportTouch ? 'auto' : 'scroll', 15420 'webkitAllowFullScreen': '', 15421 'mozallowfullscreen': '', 15422 'allowFullScreen': '' 15423 }); 15424 15425 break; 15426 15427 case 'inline': 15428 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 15429 15430 break; 15431 15432 case 'html': 15433 var object = obj.URL, 15434 el; 15435 15436 if (object[0].nodeName) { 15437 el = $('<div class="ilightbox-wrapper"></div>').html(object); 15438 } else { 15439 var dom = $(obj.URL), 15440 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 15441 el = $('<div class="ilightbox-wrapper"></div>').html(html); 15442 } 15443 15444 break; 15445 } 15446 15447 $('div.ilightbox-container', element).empty().html(el); 15448 15449 // For fixing Chrome about just playing the video for first time 15450 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 15451 var src = el[0].currentSrc + '?' + floor(random() * 30000); 15452 el[0].currentSrc = src; 15453 el[0].src = src; 15454 }); 15455 15456 return el; 15457 }, 15458 15459 ogpRecognition: function(obj, callback) { 15460 var iL = this, 15461 url = obj.URL; 15462 15463 iL.showLoader(); 15464 doAjax(url, function(data) { 15465 iL.hideLoader(); 15466 if (data) { 15467 var object = new Object(); 15468 15469 object.length = false, 15470 object.url = data.url; 15471 15472 if (data.status == 200) { 15473 var result = data.results, 15474 type = result.type, 15475 source = result.source; 15476 15477 object.source = source.src, 15478 object.width = source.width && parseInt(source.width) || 0, 15479 object.height = source.height && parseInt(source.height) || 0, 15480 object.type = type, 15481 object.thumbnail = source.thumbnail || result.images && result.images[0], 15482 object.html5video = result.html5video || {}, 15483 object.length = true; 15484 15485 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 15486 else if (source.type.indexOf("video/") != -1) object.type = "video"; 15487 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 15488 else if (source.type.indexOf("image/") != -1) object.type = "image"; 15489 15490 } else if (typeof data.response != 'undefined') 15491 throw data.response; 15492 15493 callback.call(this, object.length ? object : false); 15494 } 15495 }); 15496 }, 15497 15498 hashChangeHandler: function(url) { 15499 var iL = this, 15500 vars = iL.vars, 15501 opts = iL.options, 15502 URL = url || window.location.href, 15503 hash = parseURI(URL).hash, 15504 split = hash.split('/'), 15505 index = split[1]; 15506 15507 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 15508 15509 if (index) { 15510 var target = split[1] || 0; 15511 if (iL.items[target]) {
15512 var overlay = $('.ilightbox-overlay'); 15513 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 15514 iL.goTo(target); 15515 } else { 15516 iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click'); 15517 //iL.goTo(target); 15518 } 15519 } else { 15520 var overlay = $('.ilightbox-overlay'); 15521 if (overlay.length) iL.closeAction(); 15522 } 15523 } else { 15524 var overlay = $('.ilightbox-overlay'); 15525 if (overlay.length) iL.closeAction(); 15526 } 15527 } 15528 }; 15529 15530 /** 15531 * Parse style to pixels. 15532 * 15533 * @param {Object} $element jQuery object with element. 15534 * @param {Property} property CSS property to get the pixels from. 15535 * 15536 * @return {Int} 15537 */ 15538 function getPixel($element, property) { 15539 return parseInt($element.css(property), 10) || 0; 15540 } 15541 15542 /** 15543 * Make sure that number is within the limits. 15544 * 15545 * @param {Number} number 15546 * @param {Number} min 15547 * @param {Number} max 15548 * 15549 * @return {Number} 15550 */ 15551 function within(number, min, max) { 15552 return number < min ? min : number > max ? max : number; 15553 } 15554 15555 /** 15556 * Get viewport/window size (width and height). 15557 * 15558 * @return {Object} 15559 */ 15560 function getViewport() { 15561 var e = window, 15562 a = 'inner'; 15563 if (!('innerWidth' in window)) { 15564 a = 'client'; 15565 e = document.documentElement || document.body; 15566 } 15567 return { 15568 width: e[a + 'Width'], 15569 height: e[a + 'Height'] 15570 } 15571 } 15572 15573 /** 15574 * Remove hash tag from the URL 15575 * 15576 * @return {Void} 15577 */ 15578 function removeHash() { 15579 var scroll = getScrollXY(); 15580 15581 //UNCODE change 15582 // window.location.hash = ""; 15583 // history.pushState("", document.title, window.location.pathname + window.location.search); 15584 history.replaceState({}, document.title, window.location.pathname + window.location.search); 15585 15586 // Restore the scroll offset, should be flicker free 15587 window.scrollTo(scroll.x, scroll.y); 15588 } 15589 15590 /** 15591 * Do the ajax requests with callback. 15592 * 15593 * @param {String} url 15594 * @param {Function} callback 15595 * 15596 * @return {Void} 15597 */ 15598 function doAjax(url, callback) { 15599 var url = "//ilightbox.net/getSource/jsonp.php?url=" + encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A'); 15600 $.ajax({ 15601 url: url, 15602 dataType: 'jsonp' 15603 }); 15604 15605 iLCallback = function(data) { 15606 callback.call(this, data); 15607 }; 15608 } 15609 15610 /** 15611 * Find image from DOM elements 15612 * 15613 * @param {Element} element 15614 * 15615 * @return {Void} 15616 */ 15617 function findImageInElement(element) { 15618 var elements = $('*', element), 15619 imagesArr = new Array(); 15620 15621 elements.each(function() { 15622 var url = "", 15623 element = this; 15624 15625 if ($(element).css("background-image") != "none") { 15626 url = $(element).css("background-image"); 15627 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 15628 url = $(element).attr("src"); 15629 } 15630 15631 if (url.indexOf("gradient") == -1) { 15632 url = url.replace(/url\(\"/g, ""); 15633 url = url.replace(/url\(/g, ""); 15634 url = url.replace(/\"\)/g, ""); 15635 url = url.replace(/\)/g, ""); 15636 15637 var urls = url.split(","); 15638 15639 for (var i = 0; i < urls.length; i++) { 15640 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 15641 var extra = ""; 15642 if (browser.msie && browser.version < 9) { 15643 extra = "?" + floor(random() * 3000); 15644 } 15645 imagesArr.push(urls[i] + extra); 15646 } 15647 } 15648 } 15649 }); 15650 15651 return imagesArr; 15652 } 15653 15654 /** 15655 * Get file extension. 15656 * 15657 * @param {String} URL 15658 * 15659 * @return {String} 15660 */ 15661 function getExtension(URL) { 15662 if (URL !== null) { 15663 //UNCODE: fix issue to detect media type with query strings 15664 var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL; 15665 ext = ext.split('.').pop().toLowerCase(); 15666 15667 return ext; 15668 } 15669 } 15670 15671 /** 15672 * Get type via extension. 15673 * 15674 * @param {String} URL 15675 * 15676 * @return {String} 15677 */ 15678 function getTypeByExtension(URL) { 15679 var type, 15680 ext = getExtension(URL); 15681 15682 //Uncode addition ##START## 15683 if (URL == undefined) { 15684 return false; 15685 } 15686 //Uncode addition ##END## 15687 15688 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 15689 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 15690 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 15691 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 15692 else type = 'iframe'; 15693 15694 return type; 15695 } 15696 15697 /** 15698 * Return value from percent of a number. 15699 * 15700 * @param {Number} percent 15701 * @param {Number} total 15702 * 15703 * @return {Number} 15704 */ 15705 function percentToValue(percent, total) { 15706 return parseInt((total / 100) * percent); 15707 } 15708 15709 /** 15710 * A JavaScript equivalent of PHP’s parse_url. 15711 * 15712 * @param {String} url The URL to parse. 15713 * 15714 * @return {Mixed} 15715 */ 15716 function parseURI(url) { 15717 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 15718 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 15719 return (m ? { 15720 href: m[0] || '', 15721 protocol: m[1] || '', 15722 authority: m[2] || '', 15723 host: m[3] || '', 15724 hostname: m[4] || '', 15725 port: m[5] || '', 15726 pathname: m[6] || '', 15727 search: m[7] || '', 15728 hash: m[8] || '' 15729 } : null); 15730 } 15731 15732 /** 15733 * Gets the absolute URI. 15734 * 15735 * @param {String} href The relative URL. 15736 * @param {String} base The base URL. 15737 * 15738 * @return {String} The absolute URL. 15739 */ 15740 function absolutizeURI(base, href) { // RFC 3986 15741 var iL = this; 15742 15743 function removeDotSegments(input) { 15744 var output = []; 15745 input.replace(/^(\.\.?(\/|$))+/, '') 15746 .replace(/\/(\.(\/|$))+/g, '/') 15747 .replace(/\/\.\.$/, '/../') 15748 .replace(/\/?[^\/]*/g, function(p) { 15749 if (p === '/..') { 15750 output.pop(); 15751 } else { 15752 output.push(p); 15753 } 15754 }); 15755 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 15756 } 15757 15758 href = parseURI(href || ''); 15759 base = parseURI(base || ''); 15760 15761 return !href || !base ? null : (href.protocol || base.protocol) + 15762 (href.protocol || href.authority ? href.authority : base.authority) + 15763 removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) + 15764 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 15765 href.hash; 15766 } 15767 15768 /** 15769 * A JavaScript equivalent of PHP’s version_compare. 15770 * 15771 * @param {String} v1 15772 * @param {String} v2 15773 * @param {String} operator
15774 * 15775 * @return {Boolean} 15776 */ 15777 function version_compare(v1, v2, operator) { 15778 this.php_js = this.php_js || {}; 15779 this.php_js.ENV = this.php_js.ENV || {}; 15780 var i = 0, 15781 x = 0, 15782 compare = 0, 15783 vm = { 15784 'dev': -6, 15785 'alpha': -5, 15786 'a': -5, 15787 'beta': -4, 15788 'b': -4, 15789 'RC': -3, 15790 'rc': -3, 15791 '#': -2, 15792 'p': 1, 15793 'pl': 1 15794 }, 15795 prepVersion = function(v) { 15796 v = ('' + v).replace(/[_\-+]/g, '.'); 15797 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 15798 return (!v.length ? [-8] : v.split('.')); 15799 }, 15800 numVersion = function(v) { 15801 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 15802 }; 15803 v1 = prepVersion(v1); 15804 v2 = prepVersion(v2); 15805 x = max(v1.length, v2.length); 15806 for (i = 0; i < x; i++) { 15807 if (v1[i] == v2[i]) { 15808 continue; 15809 } 15810 v1[i] = numVersion(v1[i]); 15811 v2[i] = numVersion(v2[i]); 15812 if (v1[i] < v2[i]) { 15813 compare = -1; 15814 break; 15815 } else if (v1[i] > v2[i]) { 15816 compare = 1; 15817 break; 15818 } 15819 } 15820 if (!operator) { 15821 return compare; 15822 } 15823 15824 switch (operator) { 15825 case '>': 15826 case 'gt': 15827 return (compare > 0); 15828 case '>=': 15829 case 'ge': 15830 return (compare >= 0); 15831 case '<=': 15832 case 'le': 15833 return (compare <= 0); 15834 case '==': 15835 case '=': 15836 case 'eq': 15837 return (compare === 0); 15838 case '<>': 15839 case '!=': 15840 case 'ne': 15841 return (compare !== 0); 15842 case '': 15843 case '<': 15844 case 'lt': 15845 return (compare < 0); 15846 default: 15847 return null; 15848 } 15849 } 15850 15851 15852 // Begin the iLightBox plugin 15853 $.fn.iLightBox = function() { 15854 15855 var args = arguments, 15856 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 15857 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 15858 15859 if (!opt) opt = {}; 15860 15861 // Default options. Play carefully. 15862 var options = $.extend(true, { 15863 attr: 'href', 15864 path: 'vertical', 15865 skin: 'dark', 15866 linkId: false, 15867 infinite: false, 15868 startFrom: 0, 15869 randomStart: false, 15870 keepAspectRatio: true, 15871 maxScale: 1, 15872 minScale: .2, 15873 innerToolbar: false, 15874 smartRecognition: false, 15875 mobileOptimizer: true, 15876 fullAlone: true, 15877 fullViewPort: null, 15878 fullStretchTypes: 'flash, video', 15879 overlay: { 15880 blur: true, 15881 opacity: .85 15882 }, 15883 controls: { 15884 arrows: false, 15885 slideshow: false, 15886 toolbar: true, 15887 fullscreen: true, 15888 thumbnail: true, 15889 keyboard: true, 15890 mousewheel: true, 15891 swipe: true 15892 }, 15893 keyboard: { 15894 left: true, // previous 15895 right: true, // next 15896 up: true, // previous 15897 down: true, // next 15898 esc: true, // close 15899 shift_enter: true // fullscreen 15900 }, 15901 show: { 15902 effect: true, 15903 speed: 300, 15904 title: true 15905 }, 15906 hide: { 15907 effect: true, 15908 speed: 300 15909 }, 15910 caption: { 15911 start: true, 15912 show: 'mouseenter', 15913 hide: 'mouseleave' 15914 }, 15915 social: { 15916 start: true, 15917 show: 'mouseenter', 15918 hide: 'mouseleave',
15919 buttons: false 15920 }, 15921 styles: { 15922 pageOffsetX: 0, 15923 pageOffsetY: 0, 15924 nextOffsetX: 45, 15925 nextOffsetY: 0, 15926 nextOpacity: 1, 15927 nextScale: 1, 15928 prevOffsetX: 45, 15929 prevOffsetY: 0, 15930 prevOpacity: 1, 15931 prevScale: 1 15932 }, 15933 thumbnails: { 15934 maxWidth: 120, 15935 maxHeight: 80, 15936 normalOpacity: 1, 15937 activeOpacity: .6 15938 }, 15939 effects: { 15940 reposition: true, 15941 repositionSpeed: 200, 15942 switchSpeed: 500, 15943 loadedFadeSpeed: 180, 15944 fadeSpeed: 200 15945 }, 15946 slideshow: { 15947 pauseTime: 5000, 15948 pauseOnHover: false, 15949 startPaused: true 15950 }, 15951 text: { 15952 close: "Press Esc to close", 15953 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 15954 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 15955 slideShow: "Slideshow", 15956 next: "Next", 15957 previous: "Previous" 15958 }, 15959 errors: { 15960 loadImage: "An error occurred when trying to load photo.", 15961 loadContents: "An error occurred when trying to load contents.", 15962 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 15963 }, 15964 ajaxSetup: { 15965 url: '', 15966 beforeSend: function(jqXHR, settings) {}, 15967 cache: false, 15968 complete: function(jqXHR, textStatus) {}, 15969 crossDomain: false, 15970 error: function(jqXHR, textStatus, errorThrown) {}, 15971 success: function(data, textStatus, jqXHR) {}, 15972 global: true, 15973 ifModified: false, 15974 username: null, 15975 password: null, 15976 type: 'GET' 15977 }, 15978 callback: {} 15979 }, opt); 15980 15981 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 15982 15983 items = $.isArray(items) ? items : new Array(); 15984 15985 if (typeof args[0] == 'string') items[0] = args[0]; 15986 15987 if (version_compare($.fn.jquery, '1.8', '>=')) { 15988 var iLB = new iLightBox($(this), options, items, instant); 15989 return { 15990 close: function() { 15991 iLB.closeAction(); 15992 }, 15993 fullscreen: function() { 15994 iLB.fullScreenAction(); 15995 }, 15996 moveNext: function() { 15997 iLB.moveTo('next'); 15998 }, 15999 movePrev: function() { 16000 iLB.moveTo('prev'); 16001 }, 16002 goTo: function(index) { 16003 iLB.goTo(index); 16004 }, 16005 refresh: function() { 16006 iLB.refresh(); 16007 }, 16008 reposition: function() { 16009 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 16010 }, 16011 setOption: function(options) { 16012 iLB.setOption(options); 16013 }, 16014 destroy: function() { 16015 iLB.closeAction(); 16016 iLB.dispatchItemsEvents(); 16017 } 16018 }; 16019 } else { 16020 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 16021 } 16022 16023 }; 16024 16025 16026 $.iLightBox = function() { 16027 return $.fn.iLightBox(arguments[0], arguments[1]); 16028 }; 16029 16030 function getScrollXY() { 16031 var scrOfX = 0, 16032 scrOfY = 0; 16033 if (typeof(window.pageYOffset) == 'number') { 16034 //Netscape compliant 16035 scrOfY = window.pageYOffset; 16036 scrOfX = window.pageXOffset; 16037 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 16038 //DOM compliant 16039 scrOfY = document.body.scrollTop; 16040 scrOfX = document.body.scrollLeft; 16041 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 16042 //IE6 standards compliant mode 16043 scrOfY = document.documentElement.scrollTop; 16044 scrOfX = document.documentElement.scrollLeft; 16045 } 16046 return { 16047 x: scrOfX, 16048 y: scrOfY 16049 }; 16050 } 16051 16052 (function() { 16053 // add new event shortcuts 16054 $.each(("touchstart touchmove touchend " + 16055 "tap taphold " + 16056 "swipe swipeleft swiperight " + 16057 "scrollstart scrollstop").split(" "), function(i, name) { 16058 16059 $.fn[name] = function(fn) { 16060 return fn ? this.bind(name, fn) : this.trigger(name); 16061 }; 16062 16063 // jQuery < 1.8 16064 // if ($.attrFn) { 16065 // $.attrFn[name] = true; 16066 // } 16067 }); 16068 16069 var tapSettings = { 16070 startEvent: 'touchstart.iTap', 16071 endEvent: 'touchend.iTap' 16072 }; 16073 16074 // tap Event: 16075 $.event.special.itap = { 16076 setup: function() { 16077 16078 var self = this, 16079 $self = $(this), 16080 start, stop; 16081 16082 $self.bind(tapSettings.startEvent, function(event) { 16083 start = getScrollXY(); 16084 16085 $self.one(tapSettings.endEvent, function(event) { 16086 stop = getScrollXY(); 16087 16088 var orgEvent = event || window.event; 16089 event = $.event.fix(orgEvent); 16090 event.type = "itap"; 16091 16092 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 16093 16094 start = stop = undefined; 16095 }); 16096 }); 16097 }, 16098 16099 teardown: function() { 16100 $(this).unbind(tapSettings.startEvent); 16101 } 16102 }; 16103 }()); 16104 16105 16106 //Fullscreen API 16107 (function() { 16108 fullScreenApi = { 16109 supportsFullScreen: false, 16110 isFullScreen: function() { 16111 return false;
16112 }, 16113 requestFullScreen: function() {}, 16114 cancelFullScreen: function() {}, 16115 fullScreenEventName: '', 16116 prefix: '' 16117 }, 16118 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 16119 16120 // check for native support 16121 if (typeof document.cancelFullScreen != 'undefined') { 16122 fullScreenApi.supportsFullScreen = true; 16123 } else { 16124 // check for fullscreen support by vendor prefix 16125 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 16126 fullScreenApi.prefix = browserPrefixes[i]; 16127 16128 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 16129 fullScreenApi.supportsFullScreen = true; 16130 16131 break; 16132 } 16133 } 16134 } 16135 16136 // update methods to do something useful 16137 if (fullScreenApi.supportsFullScreen) { 16138 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 16139 16140 fullScreenApi.isFullScreen = function() { 16141 switch (this.prefix) { 16142 case '': 16143 return document.fullScreen; 16144 case 'webkit': 16145 return document.webkitIsFullScreen; 16146 default: 16147 return document[this.prefix + 'FullScreen']; 16148 } 16149 } 16150 fullScreenApi.requestFullScreen = function(el) { 16151 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 16152 } 16153 fullScreenApi.cancelFullScreen = function(el) { 16154 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 16155 } 16156 } 16157 }()); 16158 16159 // Browser detect 16160 (function() { 16161 function uaMatch(ua) { 16162 ua = ua.toLowerCase(); 16163 16164 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 16165 /(webkit)[ \/]([\w.]+)/.exec(ua) || 16166 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 16167 /(msie) ([\w.]+)/.exec(ua) || 16168 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 16169 16170 return { 16171 browser: match[1] || "", 16172 version: match[2] || "0" 16173 }; 16174 } 16175 16176 var matched = uaMatch(navigator.userAgent); 16177 browser = {}; 16178 16179 if (matched.browser) { 16180 browser[matched.browser] = true; 16181 browser.version = matched.version; 16182 } 16183 16184 // Chrome is Webkit, but Webkit is also Safari. 16185 if (browser.chrome) { 16186 browser.webkit = true; 16187 } else if (browser.webkit) { 16188 browser.safari = true; 16189 } 16190 }()); 16191 16192 // Feature detects 16193 (function() { 16194 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 16195 var el = document.createElement('div'); 16196 16197 function testProp(prop) { 16198 for (var p = 0, pl = prefixes.length; p < pl; p++) { 16199 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 16200 if (el.style[prefixedProp] !== undefined) { 16201 return prefixedProp; 16202 } 16203 } 16204 } 16205 16206 // Global support indicators 16207 transform = testProp('transform') || ''; 16208 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 16209 }()); 16210 16211 16212 /* 16213 PluginDetect v0.7.9 16214 www.pinlady.net/PluginDetect/license/ 16215 [ getVersion onWindowLoaded BetterIE ] 16216 [ Flash QuickTime Shockwave ] 16217 */ 16218 var PluginDetect={version:"0.7.9",name:"PluginDetect",handler:function(c,b,a){return function(){c(b,a)}},openTag:"<",isDefined:function(b){return typeof b!="undefined"},isArray:function(b){return(/array/i).test(Object.prototype.toString.call(b))},isFunc:function(b){return typeof b=="function"},isString:function(b){return typeof b=="string"},isNum:function(b){return typeof b=="number"},isStrNum:function(b){return(typeof b=="string"&&(/\d/).test(b))},getNumRegx:/[\d][\d\.\_,-]*/,splitNumRegx:/[\.\_,-]/g,getNum:function(b,c){var d=this,a=d.isStrNum(b)?(d.isDefined(c)?new RegExp(c):d.getNumRegx).exec(b):null;return a?a[0]:null},compareNums:function(h,f,d){var e=this,c,b,a,g=parseInt;if(e.isStrNum(h)&&e.isStrNum(f)){if(e.isDefined(d)&&d.compareNums){return d.compareNums(h,f)}c=h.split(e.splitNumRegx);b=f.split(e.splitNumRegx);for(a=0;a<min(c.length,b.length);a++){if(g(c[a],10)>g(b[a],10)){return 1}if(g(c[a],10)<g(b[a],10)){return -1}}}return 0},formatNum:function(b,c){var d=this,a,e;if(!d.isStrNum(b)){return null}if(!d.isNum(c)){c=4}c--;e=b.replace(/\s/g,"").split(d.splitNumRegx).concat(["0","0","0","0"]);for(a=0;a<4;a++){if(/^(0+)(.+)$/.test(e[a])){e[a]=RegExp.$2}if(a>c||!(/\d/).test(e[a])){e[a]="0"}}return e.slice(0,4).join(",")},$$hasMimeType:function(a){return function(c){if(!a.isIE&&c){var f,e,b,d=a.isArray(c)?c:(a.isString(c)?[c]:[]);for(b=0;b<d.length;b++){if(a.isString(d[b])&&/[^\s]/.test(d[b])){f=navigator.mimeTypes[d[b]];e=f?f.enabledPlugin:0;if(e&&(e.name||e.description)){return f}}}}return null}},findNavPlugin:function(l,e,c){var j=this,h=new RegExp(l,"i"),d=(!j.isDefined(e)||e)?/\d/:0,k=c?new RegExp(c,"i"):0,a=navigator.plugins,g="",f,b,m;for(f=0;f<a.length;f++){m=a[f].description||g;b=a[f].name||g;if((h.test(m)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))||(h.test(b)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))){if(!k||!(k.test(m)||k.test(b))){return a[f]}}}return null},getMimeEnabledPlugin:function(k,m,c){var e=this,f,b=new RegExp(m,"i"),h="",g=c?new RegExp(c,"i"):0,a,l,d,j=e.isString(k)?[k]:k;for(d=0;d<j.length;
16218d++){if((f=e.hasMimeType(j[d]))&&(f=f.enabledPlugin)){l=f.description||h;a=f.name||h;if(b.test(l)||b.test(a)){if(!g||!(g.test(l)||g.test(a))){return f}}}}return 0},getPluginFileVersion:function(f,b){var h=this,e,d,g,a,c=-1;if(h.OS>2||!f||!f.version||!(e=h.getNum(f.version))){return b}if(!b){return e}e=h.formatNum(e);b=h.formatNum(b);d=b.split(h.splitNumRegx);g=e.split(h.splitNumRegx);for(a=0;a<d.length;a++){if(c>-1&&a>c&&d[a]!="0"){return b}if(g[a]!=d[a]){if(c==-1){c=a}if(d[a]!="0"){return b}}}return e},AXO:window.ActiveXObject,getAXO:function(a){var f=null,d,b=this,c={};try{f=new b.AXO(a)}catch(d){}return f},convertFuncs:function(f){var a,g,d,b=/^[\$][\$]/,c=this;for(a in f){if(b.test(a)){try{g=a.slice(2);if(g.length>0&&!f[g]){f[g]=f[a](f);delete f[a]}}catch(d){}}}},initObj:function(e,b,d){var a,c;if(e){if(e[b[0]]==1||d){for(a=0;a<b.length;a=a+2){e[b[a]]=b[a+1]}}for(a in e){c=e[a];if(c&&c[b[0]]==1){this.initObj(c,b)}}}},initScript:function(){var d=this,a=navigator,h,i=document,l=a.userAgent||"",j=a.vendor||"",b=a.platform||"",k=a.product||"";d.initObj(d,["$",d]);for(h in d.Plugins){if(d.Plugins[h]){d.initObj(d.Plugins[h],["$",d,"$$",d.Plugins[h]],1)}}d.convertFuncs(d);d.OS=100;if(b){var g=["Win",1,"Mac",2,"Linux",3,"FreeBSD",4,"iPhone",21.1,"iPod",21.2,"iPad",21.3,"Win.*CE",22.1,"Win.*Mobile",22.2,"Pocket\\s*PC",22.3,"",100];for(h=g.length-2;h>=0;h=h-2){if(g[h]&&new RegExp(g[h],"i").test(b)){d.OS=g[h+1];break}}};d.head=i.getElementsByTagName("head")[0]||i.getElementsByTagName("body")[0]||i.body||null;d.isIE=new Function("return/*@cc_on!@*/!1")();d.verIE=d.isIE&&(/MSIE\s*(\d+\.?\d*)/i).test(l)?parseFloat(RegExp.$1,10):null;d.verIEfull=null;d.docModeIE=null;if(d.isIE){var f,n,c=document.createElement("div");try{c.style.behavior="url(#default#clientcaps)";d.verIEfull=(c.getComponentVersion("{89820200-ECBD-11CF-8B85-00AA005B4383}","componentid")).replace(/,/g,".")}catch(f){}n=parseFloat(d.verIEfull||"0",10);d.docModeIE=i.documentMode||((/back/i).test(i.compatMode||"")?5:n)||d.verIE;d.verIE=n||d.docModeIE};d.ActiveXEnabled=false;if(d.isIE){var h,m=["Msxml2.XMLHTTP","Msxml2.DOMDocument","Microsoft.XMLDOM","ShockwaveFlash.ShockwaveFlash","TDCCtl.TDCCtl","Shell.UIHelper","Scripting.Dictionary","wmplayer.ocx"];for(h=0;h<m.length;h++){if(d.getAXO(m[h])){d.ActiveXEnabled=true;break}}};d.isGecko=(/Gecko/i).test(k)&&(/Gecko\s*\/\s*\d/i).test(l);
16218d.verGecko=d.isGecko?d.formatNum((/rv\s*\:\s*([\.\,\d]+)/i).test(l)?RegExp.$1:"0.9"):null;d.isChrome=(/Chrome\s*\/\s*(\d[\d\.]*)/i).test(l);d.verChrome=d.isChrome?d.formatNum(RegExp.$1):null;d.isSafari=((/Apple/i).test(j)||(!j&&!d.isChrome))&&(/Safari\s*\/\s*(\d[\d\.]*)/i).test(l);d.verSafari=d.isSafari&&(/Version\s*\/\s*(\d[\d\.]*)/i).test(l)?d.formatNum(RegExp.$1):null;d.isOpera=(/Opera\s*[\/]?\s*(\d+\.?\d*)/i).test(l);d.verOpera=d.isOpera&&((/Version\s*\/\s*(\d+\.?\d*)/i).test(l)||1)?parseFloat(RegExp.$1,10):null;d.addWinEvent("load",d.handler(d.runWLfuncs,d))},init:function(d){var c=this,b,d,a={status:-3,plugin:0};if(!c.isString(d)){return a}if(d.length==1){c.getVersionDelimiter=d;return a}d=d.toLowerCase().replace(/\s/g,"");b=c.Plugins[d];if(!b||!b.getVersion){return a}a.plugin=b;if(!c.isDefined(b.installed)){b.installed=null;b.version=null;b.version0=null;b.getVersionDone=null;b.pluginName=d}c.garbage=false;if(c.isIE&&!c.ActiveXEnabled&&d!=="java"){a.status=-2;return a}a.status=1;return a},fPush:function(b,a){var c=this;if(c.isArray(a)&&(c.isFunc(b)||(c.isArray(b)&&b.length>0&&c.isFunc(b[0])))){a.push(b)}},callArray:function(b){var c=this,a;if(c.isArray(b)){for(a=0;a<b.length;a++){if(b[a]===null){return}c.call(b[a]);b[a]=null}}},call:function(c){var b=this,a=b.isArray(c)?c.length:-1;if(a>0&&b.isFunc(c[0])){c[0](b,a>1?c[1]:0,a>2?c[2]:0,a>3?c[3]:0)}else{if(b.isFunc(c)){c(b)}}},getVersionDelimiter:",",$$getVersion:function(a){return function(g,d,c){var e=a.init(g),f,b,h={};if(e.status<0){return null};f=e.plugin;if(f.getVersionDone!=1){f.getVersion(null,d,c);if(f.getVersionDone===null){f.getVersionDone=1}}a.cleanup();b=(f.version||f.version0);b=b?b.replace(a.splitNumRegx,a.getVersionDelimiter):b;return b}},cleanup:function(){var a=this;if(a.garbage&&a.isDefined(window.CollectGarbage)){window.CollectGarbage()}},isActiveXObject:function(d,b){var f=this,a=false,g,c='<object width="1" height="1" style="display:none" '+d.getCodeBaseVersion(b)+">"+d.HTML+f.openTag+"/object>";if(!f.head){return a}f.head.insertBefore(document.createElement("object"),f.head.firstChild);f.head.firstChild.outerHTML=c;try{f.head.firstChild.classid=d.classID}catch(g){}try{if(f.head.firstChild.object){a=true}}catch(g){}try{if(a&&f.head.firstChild.readyState<4){f.garbage=true}}catch(g){}f.head.removeChild(f.head.firstChild);return a},codebaseSearch:function(f,b){var c=this;if(!c.ActiveXEnabled||!f){return null}if(f.BIfuncs&&f.BIfuncs.length&&f.BIfuncs[f.BIfuncs.length-1]!==null){c.callArray(f.BIfuncs)}var d,o=f.SEARCH,k={};if(c.isStrNum(b)){if(o.match&&o.min&&c.compareNums(b,o.min)<=0){return true}if(o.match&&o.max&&c.compareNums(b,o.max)>=0){return false}d=c.isActiveXObject(f,b);if(d&&(!o.min||c.compareNums(b,o.min)>0)){o.min=b}if(!d&&(!o.max||c.compareNums(b,o.max)<0)){o.max=b}return d};var e=[0,0,0,0],l=[].concat(o.digits),a=o.min?1:0,j,i,h,g,m,n=function(p,r){var q=[].concat(e);q[p]=r;return c.isActiveXObject(f,q.join(","))};if(o.max){g=o.max.split(c.splitNumRegx);for(j=0;j<g.length;j++){g[j]=parseInt(g[j],10)}if(g[0]<l[0]){l[0]=g[0]}}if(o.min){m=o.min.split(c.splitNumRegx);for(j=0;j<m.length;j++){m[j]=parseInt(m[j],10)}if(m[0]>e[0]){e[0]=m[0]}}if(m&&g){for(j=1;j<m.length;j++){if(m[j-1]!=g[j-1]){break}if(g[j]<l[j]){l[j]=g[j]}if(m[j]>e[j]){e[j]=m[j]}}}if(o.max){for(j=1;j<l.length;j++){if(g[j]>0&&l[j]==0&&l[j-1]<o.digits[j-1]){l[j-1]+=1;break}}};for(j=0;j<l.length;j++){h={};for(i=0;i<20;i++){if(l[j]-e[j]<1){break}d=round((l[j]+e[j])/2);if(h["a"+d]){break}h["a"+d]=1;if(n(j,d)){e[j]=d;a=1}else{l[j]=d}}l[j]=e[j];if(!a&&n(j,e[j])){a=1};if(!a){break}};return a?e.join(","):null},addWinEvent:function(d,c){var e=this,a=window,b;if(e.isFunc(c)){if(a.addEventListener){a.addEventListener(d,c,false)}else{if(a.attachEvent){a.attachEvent("on"+d,c)}else{b=a["on"+d];a["on"+d]=e.winHandler(c,b)}}}},winHandler:function(d,c){return function(){d();if(typeof c=="function"){c()}}},WLfuncs0:[],WLfuncs:[],runWLfuncs:function(a){var b={};a.winLoaded=true;a.callArray(a.WLfuncs0);a.callArray(a.WLfuncs);if(a.onDoneEmptyDiv){a.onDoneEmptyDiv()}},winLoaded:false,$$onWindowLoaded:function(a){return function(b){if(a.winLoaded){a.call(b)}else{a.fPush(b,a.WLfuncs)}}},div:null,divID:"plugindetect",divWidth:50,pluginSize:1,emptyDiv:function(){var d=this,b,h,c,a,f,g;if(d.div&&d.div.childNodes){for(b=d.div.childNodes.length-1;b>=0;b--){c=d.div.childNodes[b];if(c&&c.childNodes){for(h=c.childNodes.length-1;h>=0;h--){g=c.childNodes[h];try{c.removeChild(g)}catch(f){}}}if(c){try{d.div.removeChild(c)}catch(f){}}}}if(!d.div){a=document.getElementById(d.divID);if(a){d.div=a}}if(d.div&&d.div.parentNode){try{d.div.parentNode.removeChild(d.div)}catch(f){}d.div=null}},DONEfuncs:[],onDoneEmptyDiv:function(){var c=this,a,b;if(!c.winLoaded){return}if(c.WLfuncs&&c.WLfuncs.length&&c.WLfuncs[c.WLfuncs.length-1]!==null){return}for(a in c){b=c[a];if(b&&b.funcs){if(b.OTF==3){return}if(b.funcs.length&&b.funcs[b.funcs.length-1]!==null){return}}}for(a=0;a<c.DONEfuncs.length;a++){c.callArray(c.DONEfuncs)}
16218c.emptyDiv()},getWidth:function(c){if(c){var a=c.scrollWidth||c.offsetWidth,b=this;if(b.isNum(a)){return a}}return -1},getTagStatus:function(m,g,a,b){var c=this,f,k=m.span,l=c.getWidth(k),h=a.span,j=c.getWidth(h),d=g.span,i=c.getWidth(d);if(!k||!h||!d||!c.getDOMobj(m)){return -2}if(j<i||l<0||j<0||i<0||i<=c.pluginSize||c.pluginSize<1){return 0}if(l>=i){return -1}try{if(l==c.pluginSize&&(!c.isIE||c.getDOMobj(m).readyState==4)){if(!m.winLoaded&&c.winLoaded){return 1}if(m.winLoaded&&c.isNum(b)){if(!c.isNum(m.count)){m.count=b}if(b-m.count>=10){return 1}}}}catch(f){}return 0},getDOMobj:function(g,a){var f,d=this,c=g?g.span:0,b=c&&c.firstChild?1:0;try{if(b&&a){d.div.focus()}}catch(f){}return b?c.firstChild:null},setStyle:function(b,g){var f=b.style,a,d,c=this;if(f&&g){for(a=0;a<g.length;a=a+2){try{f[g[a]]=g[a+1]}catch(d){}}}},insertDivInBody:function(i,g){var f,c=this,h="pd33993399",b=null,d=g?window.top.document:window.document,a=d.getElementsByTagName("body")[0]||d.body;if(!a){try{d.write('<div id="'+h+'">.'+c.openTag+"/div>");b=d.getElementById(h)}catch(f){}}a=d.getElementsByTagName("body")[0]||d.body;if(a){a.insertBefore(i,a.firstChild);if(b){a.removeChild(b)}}},insertHTML:function(f,b,g,a,k){var l,m=document,j=this,p,o=m.createElement("span"),n,i;var c=["outlineStyle","none","borderStyle","none","padding","0px","margin","0px","visibility","visible"];var h="outline-style:none;border-style:none;padding:0px;margin:0px;visibility:visible;";if(!j.isDefined(a)){a=""}if(j.isString(f)&&(/[^\s]/).test(f)){f=f.toLowerCase().replace(/\s/g,"");p=j.openTag+f+' width="'+j.pluginSize+'" height="'+j.pluginSize+'" ';p+='style="'+h+'display:inline;" ';for(n=0;n<b.length;n=n+2){if(/[^\s]/.test(b[n+1])){p+=b[n]+'="'+b[n+1]+'" '}}p+=">";for(n=0;n<g.length;n=n+2){if(/[^\s]/.test(g[n+1])){p+=j.openTag+'param name="'+g[n]+'" value="'+g[n+1]+'" />'}}p+=a+j.openTag+"/"+f+">"}else{p=a}if(!j.div){i=m.getElementById(j.divID);if(i){j.div=i}else{j.div=m.createElement("div");j.div.id=j.divID}j.setStyle(j.div,c.concat(["width",j.divWidth+"px","height",(j.pluginSize+3)+"px","fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","block"]));if(!i){j.setStyle(j.div,["position","absolute","right","0px","top","0px"]);j.insertDivInBody(j.div)}}if(j.div&&j.div.parentNode){j.setStyle(o,c.concat(["fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","inline"]));try{o.innerHTML=p}catch(l){};try{j.div.appendChild(o)}catch(l){};return{span:o,winLoaded:j.winLoaded,tagName:f,outerHTML:p}}return{span:null,winLoaded:j.winLoaded,tagName:"",outerHTML:p}},Plugins:{quicktime:{mimeType:["video/quicktime","application/x-quicktimeplayer","image/x-macpaint","image/x-quicktime"],progID:"QuickTimeCheckObject.QuickTimeCheck.1",progID0:"QuickTime.QuickTime",classID:"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B",minIEver:7,HTML:'<param name="src" value="" /><param name="controller" value="false" />',getCodeBaseVersion:function(a){return'codebase="#version='+a+'"'},SEARCH:{min:0,max:0,match:0,digits:[16,128,128,0]},getVersion:function(c){var f=this,d=f.$,a=null,e=null,b;if(!d.isIE){if(d.hasMimeType(f.mimeType)){e=d.OS!=3?d.findNavPlugin("QuickTime.*Plug-?in",0):null;if(e&&e.name){a=d.getNum(e.name)}}}else{if(d.isStrNum(c)){b=c.split(d.splitNumRegx);if(b.length>3&&parseInt(b[3],10)>0){b[3]="9999"}c=b.join(",")}if(d.isStrNum(c)&&d.verIE>=f.minIEver&&f.canUseIsMin()>0){f.installed=f.isMin(c);f.getVersionDone=0;return}f.getVersionDone=1;if(!a&&d.verIE>=f.minIEver){a=f.CDBASE2VER(d.codebaseSearch(f))}if(!a){e=d.getAXO(f.progID);if(e&&e.QuickTimeVersion){a=e.QuickTimeVersion.toString(16);a=parseInt(a.charAt(0),16)+"."+parseInt(a.charAt(1),16)+"."+parseInt(a.charAt(2),16)}}}f.installed=a?1:(e?0:-1);f.version=d.formatNum(a,3)},cdbaseUpper:["7,60,0,0","0,0,0,0"],cdbaseLower:["7,50,0,0",null],cdbase2ver:[function(c,b){var a=b.split(c.$.splitNumRegx);return[a[0],a[1].charAt(0),a[1].charAt(1),a[2]].join(",")},null],CDBASE2VER:function(f){var e=this,c=e.$,b,a=e.cdbaseUpper,d=e.cdbaseLower;
16218if(f){f=c.formatNum(f);for(b=0;b<a.length;b++){if(a[b]&&c.compareNums(f,a[b])<0&&d[b]&&c.compareNums(f,d[b])>=0&&e.cdbase2ver[b]){return e.cdbase2ver[b](e,f)}}}return f},canUseIsMin:function(){var f=this,d=f.$,b,c=f.canUseIsMin,a=f.cdbaseUpper,e=f.cdbaseLower;if(!c.value){c.value=-1;for(b=0;b<a.length;b++){if(a[b]&&d.codebaseSearch(f,a[b])){c.value=1;break}if(e[b]&&d.codebaseSearch(f,e[b])){c.value=-1;break}}}f.SEARCH.match=c.value==1?1:0;return c.value},isMin:function(c){var b=this,a=b.$;return a.codebaseSearch(b,c)?0.7:-1}},flash:{mimeType:"application/x-shockwave-flash",progID:"ShockwaveFlash.ShockwaveFlash",classID:"clsid:D27CDB6E-AE6D-11CF-96B8-444553540000",getVersion:function(){var b=function(i){if(!i){return null}var e=/[\d][\d\,\.\s]*[rRdD]{0,1}[\d\,]*/.exec(i);return e?e[0].replace(/[rRdD\.]/g,",").replace(/\s/g,""):null};var j=this,g=j.$,k,h,l=null,c=null,a=null,f,m,d;if(!g.isIE){m=g.hasMimeType(j.mimeType);if(m){f=g.getDOMobj(g.insertHTML("object",["type",j.mimeType],[],"",j));try{l=g.getNum(f.GetVariable("$version"))}catch(k){}}if(!l){d=m?m.enabledPlugin:null;if(d&&d.description){l=b(d.description)}if(l){l=g.getPluginFileVersion(d,l)}}}else{for(h=15;h>2;h--){c=g.getAXO(j.progID+"."+h);if(c){a=h.toString();break}}if(!c){c=g.getAXO(j.progID)}if(a=="6"){try{c.AllowScriptAccess="always"}catch(k){return"6,0,21,0"}}try{l=b(c.GetVariable("$version"))}catch(k){}if(!l&&a){l=a}}j.installed=l?1:-1;j.version=g.formatNum(l);return true}},shockwave:{mimeType:"application/x-director",progID:"SWCtl.SWCtl",classID:"clsid:166B1BCA-3F9C-11CF-8075-444553540000",getVersion:function(){var a=null,b=null,g,f,d=this,c=d.$;if(!c.isIE){f=c.findNavPlugin("Shockwave\\s*for\\s*Director");if(f&&f.description&&c.hasMimeType(d.mimeType)){a=c.getNum(f.description)}if(a){a=c.getPluginFileVersion(f,a)}}else{try{b=c.getAXO(d.progID).ShockwaveVersion("")}catch(g){}if(c.isString(b)&&b.length>0){a=c.getNum(b)}else{if(c.getAXO(d.progID+".8")){a="8"}else{if(c.getAXO(d.progID+".7")){a="7"}else{if(c.getAXO(d.progID+".1")){a="6"}}}}}d.installed=a?1:-1;d.version=c.formatNum(a)}},zz:0}};PluginDetect.initScript(); 16219 16220 var gArgCountErr='The "%%" function requires an even number of arguments.\nArguments should be in the form "atttributeName", "attributeValue", ...',gTagAttrs=null,gQTGeneratorVersion=1;function AC_QuickTimeVersion(){return gQTGeneratorVersion}function _QTComplain(a,b){b=b.replace("%%",a);alert(b)}function _QTAddAttribute(a,b,c){var d;d=gTagAttrs[a+b];null==d&&(d=gTagAttrs[b]);return null!=d?(0==b.indexOf(a)&&null==c&&(c=b.substring(a.length)),null==c&&(c=b),c+'="'+d+'" '):""}function _QTAddObjectAttr(a,b){if(0==a.indexOf("emb#"))return"";0==a.indexOf("obj#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("obj#",a,b)}function _QTAddEmbedAttr(a,b){if(0==a.indexOf("obj#"))return"";0==a.indexOf("emb#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("emb#",a,b)}function _QTAddObjectParam(a,b){var c,d="",e=b?" />":">";-1==a.indexOf("emb#")&&(c=gTagAttrs["obj#"+a],null==c&&(c=gTagAttrs[a]),0==a.indexOf("obj#")&&(a=a.substring(4)),null!=c&&(d=' <param name="'+a+'" value="'+c+'"'+e+"\n"));return d}function _QTDeleteTagAttrs(){for(var a=0;a<arguments.length;a++){var b=arguments[a];delete gTagAttrs[b];delete gTagAttrs["emb#"+b];delete gTagAttrs["obj#"+b]}}function _QTGenerate(a,b,c){if(4>c.length||0!=c.length%2)return _QTComplain(a,gArgCountErr),"";gTagAttrs=[];gTagAttrs.src=c[0];gTagAttrs.width=c[1];gTagAttrs.height=c[2];gTagAttrs.classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";gTagAttrs.pluginspage="http://www.apple.com/quicktime/download/";a=c[3];if(null==a||""==a)a="6,0,2,0";gTagAttrs.codebase="http://www.apple.com/qtactivex/qtplugin.cab#version="+a;for(var d,e=4;e<c.length;e+=2)d=c[e].toLowerCase(),a=c[e+1],"name"==d||"id"==d?gTagAttrs.name=a:gTagAttrs[d]=a;c="<object "+_QTAddObjectAttr("classid")+_QTAddObjectAttr("width")+_QTAddObjectAttr("height")+_QTAddObjectAttr("codebase")+_QTAddObjectAttr("name","id")+_QTAddObjectAttr("tabindex")+_QTAddObjectAttr("hspace")+_QTAddObjectAttr("vspace")+_QTAddObjectAttr("border")+_QTAddObjectAttr("align")+_QTAddObjectAttr("class")+_QTAddObjectAttr("title")+_QTAddObjectAttr("accesskey")+_QTAddObjectAttr("noexternaldata")+">\n"+_QTAddObjectParam("src",b);e=" <embed "+_QTAddEmbedAttr("src")+_QTAddEmbedAttr("width")+_QTAddEmbedAttr("height")+_QTAddEmbedAttr("pluginspage")+_QTAddEmbedAttr("name")+_QTAddEmbedAttr("align")+_QTAddEmbedAttr("tabindex");_QTDeleteTagAttrs("src","width","height","pluginspage","classid","codebase","name","tabindex","hspace","vspace","border","align","noexternaldata","class","title","accesskey");for(d in gTagAttrs)a=gTagAttrs[d],null!=a&&(e+=_QTAddEmbedAttr(d),c+=_QTAddObjectParam(d,b));return c+e+"> </embed>\n</object>"}function QT_GenerateOBJECTText(){return _QTGenerate("QT_GenerateOBJECTText",!1,arguments)}; 16221 16222 16223 /* 16224 jQuery hashchange event v1.3 16225 https://github.com/cowboy/jquery-hashchange 16226 Copyright (c) 2010 "Cowboy" Ben Alman 16227 Dual licensed under the MIT and GPL licenses. 16228 */ 16229 (function(){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var k=document,b,f=$.event.special,p=k.documentMode,m="oniLightBoxHashChange"in window&&(void 0===p||7<p);$.fn.iLightBoxHashChange=function(a){return a?this.bind("iLightBoxHashChange",a):this.trigger("iLightBoxHashChange")};$.fn.iLightBoxHashChange.delay=50;f.iLightBoxHashChange=$.extend(f.iLightBoxHashChange,{setup:function(){if(m)return!1;$(b.start)},teardown:function(){if(m)return!1;$(b.stop)}});b=function(){function a(){var c= 16230 e(),d=f(l);c!==l?(n(l=c,d),$(window).trigger("iLightBoxHashChange")):d!==l&&(location.href=location.href.replace(/#.*/,"")+d);g=setTimeout(a,$.fn.iLightBoxHashChange.delay)}var h={},g,l=e(),b=function(c){return c},n=b,f=b;h.start=function(){g||a()};h.stop=function(){g&&clearTimeout(g);g=void 0};browser.msie&&!m&&function(){var c,d;h.start=function(){c||(d=(d=$.fn.iLightBoxHashChange.src)&&d+e(),c=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||n(e());a()}).attr("src",d|| 16231 "javascript:0").insertAfter("body")[0].contentWindow,k.onpropertychange=function(){try{"title"===event.propertyName&&(c.document.title=k.title)}catch(a){}})};h.stop=b;f=function(){return e(c.location.href)};n=function(a,d){var b=c.document,e=$.fn.iLightBoxHashChange.domain;
16231a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 16232 16233 if (!Array.prototype.filter) { 16234 Array.prototype.filter = function(fun /*, thisp */ ) { 16235 "use strict"; 16236 16237 if (this == null) 16238 throw new TypeError(); 16239 16240 var t = Object(this); 16241 var len = t.length >>> 0; 16242 if (typeof fun != "function") 16243 throw new TypeError(); 16244 16245 var res = []; 16246 var thisp = arguments[1]; 16247 for (var i = 0; i < len; i++) { 16248 if (i in t) { 16249 var val = t[i]; // in case fun mutates this 16250 if (fun.call(thisp, val, i, t)) 16251 res.push(val); 16252 } 16253 } 16254 16255 return res; 16256 }; 16257 } 16258 16259 if (!Array.prototype.indexOf) { 16260 Array.prototype.indexOf = function(searchElement, fromIndex) { 16261 var k; 16262 16263 if (this == null) { 16264 throw new TypeError('"this" is null or not defined'); 16265 } 16266 16267 var O = Object(this); 16268 16269 var len = O.length >>> 0; 16270 16271 if (len === 0) { 16272 return -1; 16273 } 16274 16275 var n = +fromIndex || 0; 16276 16277 if (abs(n) === Infinity) { 16278 n = 0; 16279 } 16280 16281 if (n >= len) { 16282 return -1; 16283 } 16284 16285 k = max(n >= 0 ? n : len - abs(n), 0); 16286 16287 while (k < len) { 16288 var kValue; 16289 if (k in O && O[k] === searchElement) { 16290 return k; 16291 } 16292 k++; 16293 } 16294 return -1; 16295 }; 16296 } 16297 16298 if (!Array.prototype.lastIndexOf) { 16299 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 16300 "use strict"; 16301 16302 if (this == null) 16303 throw new TypeError(); 16304 16305 var t = Object(this); 16306 var len = t.length >>> 0; 16307 if (len === 0) 16308 return -1; 16309 16310 var n = len; 16311 if (arguments.length > 1) { 16312 n = Number(arguments[1]); 16313 if (n != n) 16314 n = 0; 16315 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 16316 n = (n > 0 || -1) * floor(abs(n)); 16317 } 16318 16319 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 16320 16321 for (; k >= 0; k--) { 16322 if (k in t && t[k] === searchElement) 16323 return k; 16324 } 16325 return -1; 16326 }; 16327 } 16328})(jQuery, this); 16329 16330/** 16331 * Owl carousel
vendor: 61,882 bytes, lines 16332-18683
16332 * @version 2.0.0-beta.3 16333 * @author Bartosz Wojciechowski 16334 * @license The MIT License (MIT) 16335 * @todo Lazy Load Icon 16336 * @todo prevent animationend bubling 16337 * @todo itemsScaleUp 16338 * @todo Test Zepto 16339 * @todo stagePadding calculate wrong active classes 16340 */ 16341;(function($, window, document, undefined) { 16342 16343 /** 16344 * Creates a carousel. 16345 * @class The Owl Carousel. 16346 * @public 16347 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 16348 * @param {Object} [options] - The options 16349 */ 16350 function Owl(element, options) { 16351 16352 /** 16353 * Current settings for the carousel. 16354 * @public 16355 */ 16356 this.settings = null; 16357 16358 /** 16359 * Current options set by the caller including defaults. 16360 * @public 16361 */ 16362 this.options = $.extend({}, Owl.Defaults, options); 16363 16364 /** 16365 * Plugin element. 16366 * @public 16367 */ 16368 this.$element = $(element); 16369 16370 /** 16371 * Proxied event handlers. 16372 * @protected 16373 */ 16374 this._handlers = {}; 16375 16376 /** 16377 * References to the running plugins of this carousel. 16378 * @protected 16379 */ 16380 this._plugins = {}; 16381 16382 /** 16383 * Currently suppressed events to prevent them from beeing retriggered. 16384 * @protected 16385 */ 16386 this._supress = {}; 16387 16388 /** 16389 * Absolute current position. 16390 * @protected 16391 */ 16392 this._current = null; 16393 16394 /** 16395 * Animation speed in milliseconds. 16396 * @protected 16397 */ 16398 this._speed = null; 16399 16400 /** 16401 * Coordinates of all items in pixel. 16402 * @todo The name of this member is missleading. 16403 * @protected 16404 */ 16405 this._coordinates = []; 16406 16407 /** 16408 * Current breakpoint. 16409 * @todo Real media queries would be nice. 16410 * @protected 16411 */ 16412 this._breakpoint = null; 16413 16414 /** 16415 * Current width of the plugin element. 16416 */ 16417 this._width = null; 16418 16419 /** 16420 * All real items. 16421 * @protected 16422 */ 16423 this._items = []; 16424 16425 /** 16426 * All cloned items. 16427 * @protected 16428 */ 16429 this._clones = []; 16430 16431 /** 16432 * Merge values of all items. 16433 * @todo Maybe this could be part of a plugin. 16434 * @protected 16435 */ 16436 this._mergers = []; 16437 16438 /** 16439 * Widths of all items. 16440 */ 16441 this._widths = []; 16442 16443 /** 16444 * Invalidated parts within the update process. 16445 * @protected 16446 */ 16447 this._invalidated = {}; 16448 16449 /** 16450 * Ordered list of workers for the update process. 16451 * @protected 16452 */ 16453 this._pipe = []; 16454 16455 /** 16456 * Current state information for the drag operation. 16457 * @todo #261 16458 * @protected 16459 */ 16460 this._drag = { 16461 time: null, 16462 target: null, 16463 pointer: null, 16464 stage: { 16465 start: null, 16466 current: null 16467 }, 16468 direction: null 16469 }; 16470 16471 /** 16472 * Current state information and their tags. 16473 * @type {Object} 16474 * @protected 16475 */ 16476 this._states = { 16477 current: {}, 16478 tags: { 16479 'initializing': [ 'busy' ], 16480 'animating': [ 'busy' ], 16481 'dragging': [ 'interacting' ] 16482 } 16483 }; 16484 16485 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 16486 this._handlers[handler] = $.proxy(this[handler], this); 16487 }, this)); 16488 16489 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 16490 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 16491 = new plugin(this); 16492 }, this)); 16493 16494 $.each(Owl.Workers, $.proxy(function(priority, worker) { 16495 this._pipe.push({ 16496 'filter': worker.filter, 16497 'run': $.proxy(worker.run, this) 16498 }); 16499 }, this)); 16500 16501 this.setup(); 16502 this.initialize(); 16503 } 16504 16505 /** 16506 * Default options for the carousel. 16507 * @public 16508 */ 16509 Owl.Defaults = { 16510 items: 3, 16511 loop: false, 16512 center: false, 16513 rewind: false, 16514 16515 mouseDrag: true, 16516 touchDrag: true, 16517 pullDrag: true, 16518 freeDrag: false, 16519 16520 margin: 0, 16521 stagePadding: 0, 16522 16523 merge: false, 16524 mergeFit: true, 16525 autoWidth: false, 16526 16527 startPosition: 0, 16528 rtl: false, 16529 16530 smartSpeed: 250, 16531 fluidSpeed: false, 16532 dragEndSpeed: false, 16533 16534 responsive: {}, 16535 responsiveRefreshRate: 200, 16536 responsiveBaseElement: window, 16537 16538 fallbackEasing: 'swing', 16539 16540 info: false, 16541 16542 nestedItemSelector: false, 16543 itemElement: 'div', 16544 stageElement: 'div', 16545 16546 refreshClass: 'owl-refresh', 16547 loadedClass: 'owl-loaded', 16548 loadingClass: 'owl-loading', 16549 rtlClass: 'owl-rtl', 16550 responsiveClass: 'owl-responsive', 16551 dragClass: 'owl-drag', 16552 itemClass: 'owl-item', 16553 stageClass: 'owl-stage', 16554 stageOuterClass: 'owl-stage-outer', 16555 grabClass: 'owl-grab' 16556 }; 16557 16558 /** 16559 * Enumeration for width. 16560 * @public 16561 * @readonly 16562 * @enum {String} 16563 */ 16564 Owl.Width = { 16565 Default: 'default', 16566 Inner: 'inner', 16567 Outer: 'outer' 16568 }; 16569 16570 /** 16571 * Enumeration for types. 16572 * @public 16573 * @readonly 16574 * @enum {String} 16575 */ 16576 Owl.Type = { 16577 Event: 'event', 16578 State: 'state' 16579 }; 16580 16581 /** 16582 * Contains all registered plugins. 16583 * @public 16584 */ 16585 Owl.Plugins = {}; 16586 16587 /** 16588 * List of workers involved in the update process. 16589 */ 16590 Owl.Workers = [ { 16591 filter: [ 'width', 'settings' ], 16592 run: function() { 16593 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 16594 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 16595 } 16596 }, { 16597 filter: [ 'width', 'items', 'settings' ], 16598 run: function(cache) { 16599 cache.current = this._items && this._items[this.relative(this._current)]; 16600 } 16601 }, { 16602 filter: [ 'items', 'settings' ], 16603 run: function() { 16604 this.$stage.children('.cloned').remove(); 16605 } 16606 }, { 16607 filter: [ 'width', 'items', 'settings' ], 16608 run: function(cache) { 16609 var margin = this.settings.margin || '', 16610 grid = !this.settings.autoWidth, 16611 rtl = this.settings.rtl, 16612 css = { 16613 'width': 'auto', 16614 'margin-left': rtl ? margin : '', 16615 'margin-right': rtl ? '' : margin 16616 }; 16617 16618 !grid && this.$stage.children().css(css); 16619 16620 cache.css = css; 16621 } 16622 }, { 16623 filter: [ 'width', 'items', 'settings' ], 16624 run: function(cache) { 16625 //UNCODE edit to fix Chrome stage padding issue 16626 var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin), 16627 merge = null, 16628 iterator = this._items.length, 16629 grid = !this.settings.autoWidth, 16630 widths = []; 16631 16632 cache.items = { 16633 merge: false, 16634 width: width 16635 }; 16636 16637 while (iterator--) { 16638 merge = this._mergers[iterator]; 16639 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 16640 16641 cache.items.merge = merge > 1 || cache.items.merge; 16642 16643 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 16644 } 16645 16646 this._widths = widths; 16647 } 16648 }, { 16649 filter: [ 'items', 'settings' ], 16650 run: function() { 16651 var clones = [], 16652 items = this._items, 16653 settings = this.settings, 16654 view = Math.max(settings.items * 2, 4), 16655 size = Math.ceil(items.length / 2) * 2, 16656 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 16657 append = '', 16658 prepend = ''; 16659 16660 repeat /= 2; 16661 16662 while (repeat--) { 16663 clones.push(this.normalize(clones.length / 2, true)); 16664 append = append + items[clones[clones.length - 1]][0].outerHTML; 16665 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 16666 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 16667 } 16668 16669 this._clones = clones; 16670 16671 // var appendVideo = $(append).find('.uncode-video-container'); 16672 // if (appendVideo.length) { 16673 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 16674 // } 16675 // var prependVideo = $(prepend).find('.uncode-video-container'); 16676 // if (prependVideo.length) { 16677 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 16678 // } 16679 $(append).addClass('cloned').appendTo(this.$stage); 16680 $(prepend).addClass('cloned').prependTo(this.$stage); 16681 } 16682 }, { 16683 filter: [ 'width', 'items', 'settings' ], 16684 run: function() { 16685 var rtl = this.settings.rtl ? 1 : -1, 16686 size = this._clones.length + this._items.length, 16687 iterator = -1, 16688 previous = 0, 16689 current = 0, 16690 coordinates = []; 16691 16692 while (++iterator < size) { 16693 previous = coordinates[iterator - 1] || 0; 16694 current = this._widths[this.relative(iterator)] + this.settings.margin; 16695 coordinates.push(previous + current * rtl); 16696 } 16697 16698 this._coordinates = coordinates; 16699 } 16700 }, { 16701 filter: [ 'width', 'items', 'settings' ], 16702 run: function() { 16703 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 16704 padding = stagePadding, 16705 coordinates = this._coordinates, 16706 css = { 16707 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 16708 'padding-left': padding || '', 16709 'padding-right': padding || '' 16710 }; 16711 16712 this.$stage.css(css); 16713 } 16714 }, { 16715 filter: [ 'width', 'items', 'settings' ], 16716 run: function(cache) { 16717 var iterator = this._coordinates.length, 16718 grid = !this.settings.autoWidth, 16719 items = this.$stage.children(); 16720 16721 if (grid && cache.items.merge) { 16722 while (iterator--) { 16723 cache.css.width = this._widths[this.relative(iterator)]; 16724 items.eq(iterator).css(cache.css); 16725 } 16726 } else if (grid) { 16727 cache.css.width = cache.items.width; 16728 items.css(cache.css); 16729 } 16730 } 16731 }, { 16732 filter: [ 'items' ], 16733 run: function() { 16734 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 16735 } 16736 }, { 16737 filter: [ 'width', 'items', 'settings' ], 16738 run: function(cache) { 16739 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 16740 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 16741 this.reset(cache.current); 16742 } 16743 }, { 16744 filter: [ 'position' ], 16745 run: function() { 16746 this.animate(this.coordinates(this._current)); 16747 } 16748 }, { 16749 filter: [ 'width', 'position', 'items', 'settings' ], 16750 run: function() { 16751 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 16752 rtl = this.settings.rtl ? 1 : -1, 16753 padding = this.settings.stagePadding * 2, 16754 begin = this.coordinates(this.current()) + padding, 16755 end = begin + this.width() * rtl, 16756 inner, outer, matches = [], i, n; 16757 16758 for (i = 0, n = this._coordinates.length; i < n; i++) { 16759 inner = this._coordinates[i - 1] || 0; 16760 outer = Math.abs(this._coordinates[i]) + padding * rtl; 16761 16762 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 16763 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 16764 matches.push(i); 16765 } 16766 } 16767 16768 this.$stage.children('.active').removeClass('active'); 16769 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 16770 16771 if (this.settings.center) { 16772 this.$stage.children('.center').removeClass('center'); 16773 this.$stage.children().eq(this.current()).addClass('center'); 16774 } 16775 } 16776 } ]; 16777 16778 /** 16779 * Initializes the carousel. 16780 * @protected 16781 */ 16782 Owl.prototype.initialize = function() { 16783 this.enter('initializing'); 16784 this.trigger('initialize'); 16785 16786 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 16787 16788 if (this.settings.autoWidth && !this.is('pre-loading')) { 16789 var imgs, nestedSelector, width; 16790 imgs = this.$element.find('img'); 16791 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 16792 width = this.$element.children(nestedSelector).width(); 16793 16794 if (imgs.length && width <= 0) { 16795 this.preloadAutoWidthImages(imgs); 16796 } 16797 } 16798 16799 this.$element.addClass(this.options.loadingClass); 16800 16801 // create stage 16802 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 16803 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 16804 16805 // append stage 16806 this.$element.append(this.$stage.parent()); 16807 16808 // append content 16809 this.replace(this.$element.children().not(this.$stage.parent())); 16810 16811 // check visibility 16812 if (this.$element.is(':visible')) { 16813 // update view 16814 this.refresh(); 16815 } else { 16816 // invalidate width 16817 this.invalidate('width'); 16818 } 16819 16820 this.$element 16821 .removeClass(this.options.loadingClass) 16822 .addClass(this.options.loadedClass); 16823 16824 // register event handlers 16825 this.registerEventHandlers(); 16826 16827 this.leave('initializing'); 16828 this.trigger('initialized'); 16829 }; 16830 16831 /** 16832 * Setups the current settings. 16833 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 16834 * @todo Support for media queries by using `matchMedia` would be nice. 16835 * @public 16836 */ 16837 Owl.prototype.setup = function() { 16838 var viewport = this.viewport(), 16839 overwrites = this.options.responsive, 16840 match = -1, 16841 settings = null; 16842 16843 if (!overwrites) { 16844 settings = $.extend({}, this.options); 16845 } else { 16846 $.each(overwrites, function(breakpoint) { 16847 if (breakpoint <= viewport && breakpoint > match) { 16848 match = Number(breakpoint); 16849 } 16850 }); 16851 16852 settings = $.extend({}, this.options, overwrites[match]); 16853 delete settings.responsive; 16854 16855 // responsive class 16856 if (settings.responsiveClass) { 16857 this.$element.attr('class', 16858 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 16859 ); 16860 } 16861 } 16862 16863 if (this.settings === null || this._breakpoint !== match) { 16864 this.trigger('change', { property: { name: 'settings', value: settings } }); 16865 this._breakpoint = match; 16866 this.settings = settings; 16867 this.invalidate('settings'); 16868 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 16869 } 16870 }; 16871 16872 /** 16873 * Updates option logic if necessery. 16874 * @protected 16875 */ 16876 Owl.prototype.optionsLogic = function() { 16877 if (this.settings.autoWidth) { 16878 this.settings.stagePadding = false; 16879 this.settings.merge = false; 16880 } 16881 }; 16882 16883 /** 16884 * Prepares an item before add. 16885 * @todo Rename event parameter `content` to `item`. 16886 * @protected 16887 * @returns {jQuery|HTMLElement} - The item container. 16888 */ 16889 Owl.prototype.prepare = function(item, index) { 16890 var event = this.trigger('prepare', { content: item }); 16891 if (!event.data) { 16892 event.data = $('<' + this.settings.itemElement + '/>') 16893 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 16894 } 16895 16896 this.trigger('prepared', { content: event.data }); 16897 16898 return event.data; 16899 }; 16900 16901 /** 16902 * Updates the view. 16903 * @public 16904 */ 16905 Owl.prototype.update = function() { 16906 var i = 0, 16907 n = this._pipe.length, 16908 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 16909 cache = {}; 16910 16911 while (i < n) { 16912 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 16913 this._pipe[i].run(cache); 16914 } 16915 i++; 16916 } 16917 16918 this._invalidated = {}; 16919 16920 !this.is('valid') && this.enter('valid'); 16921 }; 16922 16923 /** 16924 * Gets the width of the view. 16925 * @public 16926 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 16927 * @returns {Number} - The width of the view in pixel. 16928 */ 16929 Owl.prototype.width = function(dimension) { 16930 dimension = dimension || Owl.Width.Default; 16931 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 16932 switch (dimension) { 16933 case Owl.Width.Inner: 16934 case Owl.Width.Outer: 16935 return this._width; 16936 default: 16937 return this._width - stagePadding * 2 + this.settings.margin; 16938 } 16939 }; 16940 16941 /** 16942 * Refreshes the carousel primarily for adaptive purposes. 16943 * @public 16944 */ 16945 Owl.prototype.refresh = function() { 16946 this.enter('refreshing'); 16947 this.trigger('refresh'); 16948 16949 this.setup(); 16950 16951 this.optionsLogic(); 16952 16953 this.$element.addClass(this.options.refreshClass); 16954 16955 this.update(); 16956 16957 this.$element.removeClass(this.options.refreshClass); 16958 16959 this.leave('refreshing'); 16960 this.trigger('refreshed'); 16961 }; 16962 16963 /** 16964 * Checks window `resize` event. 16965 * @protected 16966 */ 16967 Owl.prototype.onThrottledResize = function() { 16968 window.clearTimeout(this.resizeTimer); 16969 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 16970 }; 16971 16972 /** 16973 * Checks window `resize` event. 16974 * @protected 16975 */ 16976 Owl.prototype.onResize = function() { 16977 if (!this._items.length) { 16978 return false; 16979 } 16980 16981 if (this._width === this.$element.width()) { 16982 return false; 16983 } 16984 16985 if (!this.$element.is(':visible')) { 16986 return false; 16987 } 16988 16989 this.enter('resizing'); 16990 16991 if (this.trigger('resize').isDefaultPrevented()) { 16992 this.leave('resizing'); 16993 return false; 16994 } 16995 16996 this.invalidate('width'); 16997 16998 this.refresh(); 16999 17000 this.leave('resizing'); 17001 this.trigger('resized'); 17002 }; 17003 17004 /** 17005 * Registers event handlers. 17006 * @todo Check `msPointerEnabled` 17007 * @todo #261 17008 * @protected 17009 */ 17010 Owl.prototype.registerEventHandlers = function() { 17011 if ($.support.transition) { 17012 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 17013 } 17014 17015 if (this.settings.responsive !== false) { 17016 this.on(window, 'resize', this._handlers.onThrottledResize); 17017 } 17018 17019 if (this.settings.mouseDrag) { 17020 this.$element.addClass(this.options.dragClass); 17021 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 17022 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 17023 } 17024 17025 if (this.settings.touchDrag){ 17026 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 17027 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 17028 } 17029 }; 17030 17031 /** 17032 * Handles `touchstart` and `mousedown` events. 17033 * @todo Horizontal swipe threshold as option 17034 * @todo #261 17035 * @protected 17036 * @param {Event} event - The event arguments. 17037 */ 17038 Owl.prototype.onDragStart = function(event) { 17039 var stage = null; 17040 17041 if (event.which === 3) { 17042 return; 17043 } 17044 17045 if ($.support.transform) { 17046 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 17047 stage = { 17048 x: stage[stage.length === 16 ? 12 : 4], 17049 y: stage[stage.length === 16 ? 13 : 5] 17050 }; 17051 } else { 17052 stage = this.$stage.position(); 17053 stage = { 17054 x: this.settings.rtl ? 17055 stage.left + this.$stage.width() - this.width() + this.settings.margin : 17056 stage.left, 17057 y: stage.top 17058 }; 17059 } 17060 17061 if (this.is('animating')) { 17062 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 17063 this.invalidate('position'); 17064 } 17065 17066 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 17067 17068 this.speed(0); 17069 17070 this._drag.time = new Date().getTime(); 17071 this._drag.target = $(event.target); 17072 this._drag.stage.start = stage; 17073 this._drag.stage.current = stage; 17074 this._drag.pointer = this.pointer(event); 17075 17076 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 17077 17078 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 17079 var delta = this.difference(this._drag.pointer, this.pointer(event)); 17080 17081 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 17082 17083 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 17084 return; 17085 } 17086 17087 event.preventDefault(); 17088 17089 this.enter('dragging'); 17090 this.trigger('drag'); 17091 }, this)); 17092 }; 17093 17094 /** 17095 * Handles the `touchmove` and `mousemove` events. 17096 * @todo #261 17097 * @protected 17098 * @param {Event} event - The event arguments. 17099 */ 17100 Owl.prototype.onDragMove = function(event) { 17101 var minimum = null, 17102 maximum = null, 17103 pull = null, 17104 delta = this.difference(this._drag.pointer, this.pointer(event)), 17105 stage = this.difference(this._drag.stage.start, delta); 17106 17107 if (!this.is('dragging')) { 17108 return; 17109 } 17110 17111 event.preventDefault(); 17112 17113 if (this.settings.loop) { 17114 minimum = this.coordinates(this.minimum()); 17115 maximum = this.coordinates(this.maximum() + 1) - minimum; 17116 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 17117 } else { 17118 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 17119 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 17120 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 17121 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 17122 } 17123 17124 this._drag.stage.current = stage; 17125 17126 this.animate(stage.x); 17127 }; 17128 17129 /** 17130 * Handles the `touchend` and `mouseup` events. 17131 * @todo #261 17132 * @todo Threshold for click event 17133 * @protected 17134 * @param {Event} event - The event arguments. 17135 */ 17136 Owl.prototype.onDragEnd = function(event) { 17137 var delta = this.difference(this._drag.pointer, this.pointer(event)), 17138 stage = this._drag.stage.current, 17139 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 17140 17141 $(document).off('.owl.core'); 17142 17143 this.$element.removeClass(this.options.grabClass); 17144 17145 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 17146 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 17147 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 17148 this.invalidate('position'); 17149 this.update(); 17150 17151 this._drag.direction = direction; 17152 17153 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 17154 this._drag.target.one('click.owl.core', function() { return false; }); 17155 } 17156 } 17157 17158 if (!this.is('dragging')) { 17159 return; 17160 } 17161 17162 this.leave('dragging'); 17163 this.trigger('dragged'); 17164 }; 17165 17166 /** 17167 * Gets absolute position of the closest item for a coordinate. 17168 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 17169 * @protected 17170 * @param {Number} coordinate - The coordinate in pixel. 17171 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 17172 * @return {Number} - The absolute position of the closest item. 17173 */ 17174 Owl.prototype.closest = function(coordinate, direction) { 17175 var position = -1, 17176 pull = 30, 17177 width = this.width(), 17178 coordinates = this.coordinates(); 17179 17180 if (!this.settings.freeDrag) { 17181 // check closest item 17182 $.each(coordinates, $.proxy(function(index, value) { 17183 if (coordinate > value - pull && coordinate < value + pull) { 17184 position = index; 17185 } else if (this.op(coordinate, '<', value) 17186 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 17187 position = direction === 'left' ? index + 1 : index; 17188 } 17189 return position === -1; 17190 }, this)); 17191 } 17192 17193 if (!this.settings.loop) { 17194 // non loop boundries 17195 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 17196 position = coordinate = this.minimum(); 17197 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 17198 position = coordinate = this.maximum(); 17199 } 17200 } 17201 17202 return position; 17203 }; 17204 17205 /** 17206 * Animates the stage. 17207 * @todo #270 17208 * @public 17209 * @param {Number} coordinate - The coordinate in pixels. 17210 */ 17211 Owl.prototype.animate = function(coordinate) { 17212 var animate = this.speed() > 0; 17213 17214 this.is('animating') && this.onTransitionEnd(); 17215 17216 if (animate) { 17217 this.enter('animating'); 17218 this.trigger('translate'); 17219 } 17220 17221 if ($.support.transform3d && $.support.transition) { 17222 this.$stage.css({ 17223 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 17224 transition: (this.speed() / 1000) + 's' 17225 }); 17226 } else if (animate) { 17227 this.$stage.animate({ 17228 left: coordinate + 'px' 17229 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 17230 } else { 17231 this.$stage.css({ 17232 left: coordinate + 'px' 17233 }); 17234 } 17235 }; 17236 17237 /** 17238 * Checks whether the carousel is in a specific state or not. 17239 * @param {String} state - The state to check. 17240 * @returns {Boolean} - The flag which indicates if the carousel is busy. 17241 */ 17242 Owl.prototype.is = function(state) { 17243 return this._states.current[state] && this._states.current[state] > 0; 17244 }; 17245 17246 /** 17247 * Sets the absolute position of the current item. 17248 * @public 17249 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 17250 * @returns {Number} - The absolute position of the current item. 17251 */ 17252 Owl.prototype.current = function(position) { 17253 if (position === undefined) { 17254 return this._current; 17255 } 17256 17257 if (this._items.length === 0) { 17258 return undefined; 17259 } 17260 17261 position = this.normalize(position); 17262 17263 if (this._current !== position) { 17264 var event = this.trigger('change', { property: { name: 'position', value: position } }); 17265 17266 if (event.data !== undefined) { 17267 position = this.normalize(event.data); 17268 } 17269 17270 this._current = position; 17271 17272 this.invalidate('position'); 17273 17274 this.trigger('changed', { property: { name: 'position', value: this._current } }); 17275 } 17276 17277 return this._current; 17278 }; 17279 17280 /** 17281 * Invalidates the given part of the update routine. 17282 * @param {String} [part] - The part to invalidate. 17283 * @returns {Array.<String>} - The invalidated parts. 17284 */ 17285 Owl.prototype.invalidate = function(part) { 17286 if ($.type(part) === 'string') { 17287 this._invalidated[part] = true; 17288 this.is('valid') && this.leave('valid'); 17289 } 17290 return $.map(this._invalidated, function(v, i) { return i }); 17291 }; 17292 17293 /** 17294 * Resets the absolute position of the current item. 17295 * @public 17296 * @param {Number} position - The absolute position of the new item. 17297 */ 17298 Owl.prototype.reset = function(position) { 17299 position = this.normalize(position); 17300 17301 if (position === undefined) { 17302 return; 17303 } 17304 17305 this._speed = 0; 17306 this._current = position; 17307 17308 this.suppress([ 'translate', 'translated' ]); 17309 17310 this.animate(this.coordinates(position)); 17311 17312 this.release([ 'translate', 'translated' ]); 17313 }; 17314 17315 /** 17316 * Normalizes an absolute or a relative position of an item. 17317 * @public 17318 * @param {Number} position - The absolute or relative position to normalize. 17319 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 17320 * @returns {Number} - The normalized position. 17321 */ 17322 Owl.prototype.normalize = function(position, relative) { 17323 var n = this._items.length, 17324 m = relative ? 0 : this._clones.length; 17325 17326 if (!$.isNumeric(position) || n < 1) { 17327 position = undefined; 17328 } else if (position < 0 || position >= n + m) { 17329 position = ((position - m / 2) % n + n) % n + m / 2; 17330 } 17331 17332 return position; 17333 }; 17334 17335 /** 17336 * Converts an absolute position of an item into a relative one. 17337 * @public 17338 * @param {Number} position - The absolute position to convert. 17339 * @returns {Number} - The converted position. 17340 */ 17341 Owl.prototype.relative = function(position) { 17342 position -= this._clones.length / 2; 17343 return this.normalize(position, true); 17344 }; 17345 17346 /** 17347 * Gets the maximum position for the current item. 17348 * @public 17349 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 17350 * @returns {Number} 17351 */ 17352 Owl.prototype.maximum = function(relative) { 17353 var settings = this.settings, 17354 maximum = this._coordinates.length, 17355 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 17356 i = -1, j; 17357 17358 if (settings.loop) { 17359 maximum = this._clones.length / 2 + this._items.length - 1; 17360 } else if (settings.autoWidth || settings.merge) { 17361 // binary search 17362 while (maximum - i > 1) { 17363 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 17364 ? i = j : maximum = j; 17365 } 17366 } else if (settings.center) { 17367 maximum = this._items.length - 1; 17368 } else { 17369 maximum = this._items.length - settings.items; 17370 } 17371 17372 if (relative) { 17373 maximum -= this._clones.length / 2; 17374 } 17375 17376 return Math.max(maximum, 0); 17377 }; 17378 17379 /** 17380 * Gets the minimum position for the current item. 17381 * @public 17382 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 17383 * @returns {Number} 17384 */ 17385 Owl.prototype.minimum = function(relative) { 17386 return relative ? 0 : this._clones.length / 2; 17387 }; 17388 17389 /** 17390 * Gets an item at the specified relative position. 17391 * @public 17392 * @param {Number} [position] - The relative position of the item. 17393 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 17394 */ 17395 Owl.prototype.items = function(position) { 17396 if (position === undefined) { 17397 return this._items.slice(); 17398 } 17399 17400 position = this.normalize(position, true); 17401 return this._items[position]; 17402 }; 17403 17404 /** 17405 * Gets an item at the specified relative position. 17406 * @public 17407 * @param {Number} [position] - The relative position of the item. 17408 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 17409 */ 17410 Owl.prototype.mergers = function(position) { 17411 if (position === undefined) { 17412 return this._mergers.slice(); 17413 } 17414 17415 position = this.normalize(position, true); 17416 return this._mergers[position]; 17417 }; 17418 17419 /** 17420 * Gets the absolute positions of clones for an item. 17421 * @public 17422 * @param {Number} [position] - The relative position of the item. 17423 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 17424 */ 17425 Owl.prototype.clones = function(position) { 17426 var odd = this._clones.length / 2, 17427 even = odd + this._items.length, 17428 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 17429 17430 if (position === undefined) { 17431 return $.map(this._clones, function(v, i) { return map(i) }); 17432 } 17433 17434 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 17435 }; 17436 17437 /** 17438 * Sets the current animation speed. 17439 * @public 17440 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 17441 * @returns {Number} - The current animation speed in milliseconds. 17442 */ 17443 Owl.prototype.speed = function(speed) { 17444 if (speed !== undefined) { 17445 this._speed = speed; 17446 } 17447 17448 return this._speed; 17449 }; 17450 17451 /** 17452 * Gets the coordinate of an item. 17453 * @todo The name of this method is missleanding. 17454 * @public 17455 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 17456 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 17457 */ 17458 Owl.prototype.coordinates = function(position) { 17459 var coordinate = null; 17460 17461 if (position === undefined) { 17462 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 17463 return this.coordinates(index); 17464 }, this)); 17465 } 17466 17467 if (this.settings.center) { 17468 coordinate = this._coordinates[position]; 17469 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 17470 } else { 17471 coordinate = this._coordinates[position - 1] || 0; 17472 } 17473 17474 return coordinate; 17475 }; 17476 17477 /** 17478 * Calculates the speed for a translation. 17479 * @protected 17480 * @param {Number} from - The absolute position of the start item. 17481 * @param {Number} to - The absolute position of the target item. 17482 * @param {Number} [factor=undefined] - The time factor in milliseconds. 17483 * @returns {Number} - The time in milliseconds for the translation. 17484 */ 17485 Owl.prototype.duration = function(from, to, factor) { 17486 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 17487 }; 17488 17489 /** 17490 * Slides to the specified item. 17491 * @public 17492 * @param {Number} position - The position of the item. 17493 * @param {Number} [speed] - The time in milliseconds for the transition. 17494 */ 17495 Owl.prototype.to = function(position, speed) { 17496 var current = this.current(), 17497 revert = null, 17498 distance = position - this.relative(current), 17499 direction = (distance > 0) - (distance < 0), 17500 items = this._items.length, 17501 minimum = this.minimum(), 17502 maximum = this.maximum(); 17503 17504 if (this.settings.loop) { 17505 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 17506 distance += direction * -1 * items; 17507 } 17508 17509 position = current + distance; 17510 revert = ((position - minimum) % items + items) % items + minimum; 17511 17512 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 17513 current = revert - distance; 17514 position = revert; 17515 this.reset(current); 17516 } 17517 } else if (this.settings.rewind) { 17518 maximum += 1; 17519 position = (position % maximum + maximum) % maximum; 17520 } else { 17521 position = Math.max(minimum, Math.min(maximum, position)); 17522 } 17523 17524 this.speed(this.duration(current, position, speed)); 17525 this.current(position); 17526 17527 if (this.$element.is(':visible')) { 17528 this.update(); 17529 } 17530 }; 17531 17532 /** 17533 * Slides to the next item. 17534 * @public 17535 * @param {Number} [speed] - The time in milliseconds for the transition. 17536 */ 17537 Owl.prototype.next = function(speed) { 17538 speed = speed || false; 17539 this.to(this.relative(this.current()) + 1, speed); 17540 }; 17541 17542 /** 17543 * Slides to the previous item. 17544 * @public 17545 * @param {Number} [speed] - The time in milliseconds for the transition. 17546 */ 17547 Owl.prototype.prev = function(speed) { 17548 speed = speed || false; 17549 this.to(this.relative(this.current()) - 1, speed); 17550 }; 17551 17552 /** 17553 * Handles the end of an animation. 17554 * @protected 17555 * @param {Event} event - The event arguments. 17556 */ 17557 Owl.prototype.onTransitionEnd = function(event) { 17558 17559 // if css2 animation then event object is undefined 17560 if (event !== undefined) { 17561 event.stopPropagation(); 17562 17563 // Catch only owl-stage transitionEnd event 17564 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 17565 return false; 17566 } 17567 } 17568 17569 this.leave('animating'); 17570 this.trigger('translated'); 17571 }; 17572 17573 /** 17574 * Gets viewport width. 17575 * @protected 17576 * @return {Number} - The width in pixel. 17577 */ 17578 Owl.prototype.viewport = function() { 17579 var width; 17580 if (this.options.responsiveBaseElement !== window) { 17581 width = $(this.options.responsiveBaseElement).width(); 17582 } else if (window.innerWidth) { 17583 width = window.innerWidth; 17584 } else if (document.documentElement && document.documentElement.clientWidth) { 17585 width = document.documentElement.clientWidth; 17586 } else { 17587 throw 'Can not detect viewport width.'; 17588 } 17589 17590 return width; 17591 }; 17592 17593 /** 17594 * Replaces the current content. 17595 * @public 17596 * @param {HTMLElement|jQuery|String} content - The new content. 17597 */ 17598 Owl.prototype.replace = function(content) { 17599 this.$stage.empty(); 17600 this._items = []; 17601 17602 if (content) { 17603 content = (content instanceof jQuery) ? content : $(content); 17604 } 17605 17606 if (this.settings.nestedItemSelector) { 17607 content = content.find('.' + this.settings.nestedItemSelector); 17608 } 17609 17610 content.filter(function() { 17611 return this.nodeType === 1; 17612 }).each($.proxy(function(index, item) { 17613 item = this.prepare(item, index); 17614 this.$stage.append(item); 17615 this._items.push(item); 17616 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 17617 }, this)); 17618 17619 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 17620 17621 this.invalidate('items'); 17622 }; 17623 17624 /** 17625 * Adds an item. 17626 * @todo Use `item` instead of `content` for the event arguments. 17627 * @public 17628 * @param {HTMLElement|jQuery|String} content - The item content to add. 17629 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 17630 */ 17631 Owl.prototype.add = function(content, position) { 17632 var current = this.relative(this._current); 17633 17634 position = position === undefined ? this._items.length : this.normalize(position, true); 17635 content = content instanceof jQuery ? content : $(content); 17636 17637 this.trigger('add', { content: content, position: position }); 17638 17639 content = this.prepare(content, this._items[current].index()); 17640 17641 if (this._items.length === 0 || position === this._items.length) { 17642 this._items.length === 0 && this.$stage.append(content); 17643 this._items.length !== 0 && this._items[position - 1].after(content); 17644 this._items.push(content); 17645 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 17646 } else { 17647 this._items[position].before(content); 17648 this._items.splice(position, 0, content); 17649 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 17650 } 17651 17652 this._items[current] && this.reset(this._items[current].index()); 17653 17654 this.invalidate('items'); 17655 17656 this.trigger('added', { content: content, position: position }); 17657 }; 17658 17659 /** 17660 * Removes an item by its position. 17661 * @todo Use `item` instead of `content` for the event arguments. 17662 * @public 17663 * @param {Number} position - The relative position of the item to remove. 17664 */ 17665 Owl.prototype.remove = function(position) { 17666 position = this.normalize(position, true); 17667 17668 if (position === undefined) { 17669 return; 17670 } 17671 17672 this.trigger('remove', { content: this._items[position], position: position }); 17673 17674 this._items[position].remove(); 17675 this._items.splice(position, 1); 17676 this._mergers.splice(position, 1); 17677 17678 this.invalidate('items'); 17679 17680 this.trigger('removed', { content: null, position: position }); 17681 }; 17682 17683 /** 17684 * Preloads images with auto width. 17685 * @todo Replace by a more generic approach 17686 * @protected 17687 */ 17688 Owl.prototype.preloadAutoWidthImages = function(images) { 17689 images.each($.proxy(function(i, element) { 17690 this.enter('pre-loading'); 17691 element = $(element); 17692 $(new Image()).one('load', $.proxy(function(e) { 17693 element.attr('src', e.target.src); 17694 element.css('opacity', 1); 17695 this.leave('pre-loading'); 17696 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 17697 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 17698 }, this)); 17699 }; 17700 17701 /** 17702 * Destroys the carousel. 17703 * @public 17704 */ 17705 Owl.prototype.destroy = function() { 17706 17707 this.$element.off('.owl.core'); 17708 this.$stage.off('.owl.core'); 17709 $(document).off('.owl.core'); 17710 17711 if (this.settings.responsive !== false) { 17712 window.clearTimeout(this.resizeTimer); 17713 this.off(window, 'resize', this._handlers.onThrottledResize); 17714 } 17715 17716 for (var i in this._plugins) { 17717 this._plugins[i].destroy(); 17718 } 17719 17720 this.$stage.children('.cloned').remove(); 17721 17722 this.$stage.unwrap(); 17723 this.$stage.children().contents().unwrap(); 17724 this.$stage.children().unwrap(); 17725 17726 this.$element 17727 .removeClass(this.options.refreshClass) 17728 .removeClass(this.options.loadingClass) 17729 .removeClass(this.options.loadedClass) 17730 .removeClass(this.options.rtlClass) 17731 .removeClass(this.options.dragClass) 17732 .removeClass(this.options.grabClass) 17733 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 17734 .removeData('owl.carousel'); 17735 }; 17736 17737 /** 17738 * Operators to calculate right-to-left and left-to-right. 17739 * @protected 17740 * @param {Number} [a] - The left side operand. 17741 * @param {String} [o] - The operator. 17742 * @param {Number} [b] - The right side operand. 17743 */ 17744 Owl.prototype.op = function(a, o, b) { 17745 var rtl = this.settings.rtl; 17746 switch (o) { 17747 case '<': 17748 return rtl ? a > b : a < b; 17749 case '>': 17750 return rtl ? a < b : a > b; 17751 case '>=': 17752 return rtl ? a <= b : a >= b; 17753 case '<=': 17754 return rtl ? a >= b : a <= b; 17755 default: 17756 break; 17757 } 17758 }; 17759 17760 /** 17761 * Attaches to an internal event. 17762 * @protected 17763 * @param {HTMLElement} element - The event source. 17764 * @param {String} event - The event name. 17765 * @param {Function} listener - The event handler to attach. 17766 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 17767 */ 17768 Owl.prototype.on = function(element, event, listener, capture) { 17769 if (element.addEventListener) { 17770 element.addEventListener(event, listener, capture); 17771 } else if (element.attachEvent) { 17772 element.attachEvent('on' + event, listener); 17773 } 17774 }; 17775 17776 /** 17777 * Detaches from an internal event. 17778 * @protected 17779 * @param {HTMLElement} element - The event source. 17780 * @param {String} event - The event name. 17781 * @param {Function} listener - The attached event handler to detach. 17782 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 17783 */ 17784 Owl.prototype.off = function(element, event, listener, capture) { 17785 if (element.removeEventListener) { 17786 element.removeEventListener(event, listener, capture); 17787 } else if (element.detachEvent) { 17788 element.detachEvent('on' + event, listener); 17789 } 17790 }; 17791 17792 /** 17793 * Triggers a public event. 17794 * @todo Remove `status`, `relatedTarget` should be used instead. 17795 * @protected 17796 * @param {String} name - The event name. 17797 * @param {*} [data=null] - The event data. 17798 * @param {String} [namespace=carousel] - The event namespace. 17799 * @param {String} [state] - The state which is associated with the event. 17800 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 17801 * @returns {Event} - The event arguments. 17802 */ 17803 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 17804 var status = { 17805 item: { count: this._items.length, index: this.current() } 17806 }, handler = $.camelCase( 17807 $.grep([ 'on', name, namespace ], function(v) { return v }) 17808 .join('-').toLowerCase() 17809 ), event = $.Event( 17810 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 17811 $.extend({ relatedTarget: this }, status, data) 17812 ); 17813 17814 if (!this._supress[name]) { 17815 $.each(this._plugins, function(name, plugin) { 17816 if (plugin.onTrigger) { 17817 plugin.onTrigger(event); 17818 } 17819 }); 17820 17821 this.register({ type: Owl.Type.Event, name: name }); 17822 this.$element.trigger(event); 17823 17824 if (this.settings && typeof this.settings[handler] === 'function') { 17825 this.settings[handler].call(this, event); 17826 } 17827 } 17828 17829 return event; 17830 }; 17831 17832 /** 17833 * Enters a state. 17834 * @param name - The state name. 17835 */ 17836 Owl.prototype.enter = function(name) { 17837 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 17838 if (this._states.current[name] === undefined) { 17839 this._states.current[name] = 0; 17840 } 17841 17842 this._states.current[name]++; 17843 }, this)); 17844 }; 17845 17846 /** 17847 * Leaves a state. 17848 * @param name - The state name. 17849 */ 17850 Owl.prototype.leave = function(name) { 17851 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 17852 this._states.current[name]--; 17853 }, this)); 17854 }; 17855 17856 /** 17857 * Registers an event or state. 17858 * @public 17859 * @param {Object} object - The event or state to register. 17860 */ 17861 Owl.prototype.register = function(object) { 17862 if (object.type === Owl.Type.Event) { 17863 if (!$.event.special[object.name]) { 17864 $.event.special[object.name] = {}; 17865 } 17866 17867 if (!$.event.special[object.name].owl) { 17868 var _default = $.event.special[object.name]._default; 17869 $.event.special[object.name]._default = function(e) { 17870 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 17871 return _default.apply(this, arguments); 17872 } 17873 return e.namespace && e.namespace.indexOf('owl') > -1; 17874 }; 17875 $.event.special[object.name].owl = true; 17876 } 17877 } else if (object.type === Owl.Type.State) { 17878 if (!this._states.tags[object.name]) { 17879 this._states.tags[object.name] = object.tags; 17880 } else { 17881 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 17882 } 17883 17884 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 17885 return $.inArray(tag, this._states.tags[object.name]) === i; 17886 }, this)); 17887 } 17888 }; 17889 17890 /** 17891 * Suppresses events. 17892 * @protected 17893 * @param {Array.<String>} events - The events to suppress. 17894 */ 17895 Owl.prototype.suppress = function(events) { 17896 $.each(events, $.proxy(function(index, event) { 17897 this._supress[event] = true; 17898 }, this)); 17899 }; 17900 17901 /** 17902 * Releases suppressed events. 17903 * @protected 17904 * @param {Array.<String>} events - The events to release. 17905 */ 17906 Owl.prototype.release = function(events) { 17907 $.each(events, $.proxy(function(index, event) { 17908 delete this._supress[event]; 17909 }, this)); 17910 }; 17911 17912 /** 17913 * Gets unified pointer coordinates from event. 17914 * @todo #261 17915 * @protected 17916 * @param {Event} - The `mousedown` or `touchstart` event. 17917 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 17918 */ 17919 Owl.prototype.pointer = function(event) { 17920 var result = { x: null, y: null }; 17921 17922 event = event.originalEvent || event || window.event; 17923 17924 event = event.touches && event.touches.length ? 17925 event.touches[0] : event.changedTouches && event.changedTouches.length ? 17926 event.changedTouches[0] : event; 17927 17928 if (event.pageX) { 17929 result.x = event.pageX; 17930 result.y = event.pageY; 17931 } else { 17932 result.x = event.clientX; 17933 result.y = event.clientY; 17934 } 17935 17936 return result; 17937 }; 17938 17939 /** 17940 * Gets the difference of two vectors. 17941 * @todo #261 17942 * @protected 17943 * @param {Object} - The first vector. 17944 * @param {Object} - The second vector. 17945 * @returns {Object} - The difference. 17946 */ 17947 Owl.prototype.difference = function(first, second) { 17948 return { 17949 x: first.x - second.x, 17950 y: first.y - second.y 17951 }; 17952 }; 17953 17954 /** 17955 * The jQuery Plugin for the Owl Carousel 17956 * @todo Navigation plugin `next` and `prev` 17957 * @public 17958 */ 17959 $.fn.owlCarousel = function(option) { 17960 var args = Array.prototype.slice.call(arguments, 1); 17961 17962 return this.each(function() { 17963 var $this = $(this), 17964 data = $this.data('owl.carousel'); 17965 17966 if (!data) { 17967 data = new Owl(this, typeof option == 'object' && option); 17968 $this.data('owl.carousel', data); 17969 17970 $.each([ 17971 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 17972 ], function(i, event) { 17973 data.register({ type: Owl.Type.Event, name: event }); 17974 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 17975 if (e.namespace && e.relatedTarget !== this) { 17976 this.suppress([ event ]); 17977 data[event].apply(this, [].slice.call(arguments, 1)); 17978 this.release([ event ]); 17979 } 17980 }, data)); 17981 }); 17982 } 17983 17984 if (typeof option == 'string' && option.charAt(0) !== '_') { 17985 data[option].apply(data, args); 17986 } 17987 }); 17988 }; 17989 17990 /** 17991 * The constructor for the jQuery Plugin 17992 * @public 17993 */ 17994 $.fn.owlCarousel.Constructor = Owl; 17995 17996})(window.Zepto || window.jQuery, window, document); 17997 17998/** 17999 * AutoRefresh Plugin 18000 * @version 2.0.0-beta.3 18001 * @author Artus Kolanowski 18002 * @license The MIT License (MIT) 18003 */ 18004;(function($, window, document, undefined) { 18005 18006 /** 18007 * Creates the auto refresh plugin. 18008 * @class The Auto Refresh Plugin 18009 * @param {Owl} carousel - The Owl Carousel 18010 */ 18011 var AutoRefresh = function(carousel) { 18012 /** 18013 * Reference to the core. 18014 * @protected 18015 * @type {Owl} 18016 */ 18017 this._core = carousel; 18018 18019 /** 18020 * Refresh interval. 18021 * @protected 18022 * @type {number} 18023 */ 18024 this._interval = null; 18025 18026 /** 18027 * Whether the element is currently visible or not. 18028 * @protected 18029 * @type {Boolean} 18030 */ 18031 this._visible = null; 18032 18033 /** 18034 * All event handlers. 18035 * @protected 18036 * @type {Object} 18037 */ 18038 this._handlers = { 18039 'initialized.owl.carousel': $.proxy(function(e) { 18040 if (e.namespace && this._core.settings.autoRefresh) { 18041 this.watch(); 18042 } 18043 }, this) 18044 }; 18045 18046 // set default options 18047 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 18048 18049 // register event handlers 18050 this._core.$element.on(this._handlers); 18051 }; 18052 18053 /** 18054 * Default options. 18055 * @public 18056 */ 18057 AutoRefresh.Defaults = { 18058 autoRefresh: true, 18059 autoRefreshInterval: 500 18060 }; 18061 18062 /** 18063 * Watches the element. 18064 */ 18065 AutoRefresh.prototype.watch = function() { 18066 if (this._interval) { 18067 return; 18068 } 18069 18070 this._visible = this._core.$element.is(':visible'); 18071 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 18072 }; 18073 18074 /** 18075 * Refreshes the element. 18076 */ 18077 AutoRefresh.prototype.refresh = function() { 18078 if (this._core.$element.is(':visible') === this._visible) { 18079 return; 18080 } 18081 18082 this._visible = !this._visible; 18083 18084 this._core.$element.toggleClass('owl-hidden', !this._visible); 18085 18086 this._visible && (this._core.invalidate('width') && this._core.refresh()); 18087 }; 18088 18089 /** 18090 * Destroys the plugin. 18091 */ 18092 AutoRefresh.prototype.destroy = function() { 18093 var handler, property; 18094 18095 window.clearInterval(this._interval); 18096 18097 for (handler in this._handlers) { 18098 this._core.$element.off(handler, this._handlers[handler]); 18099 } 18100 for (property in Object.getOwnPropertyNames(this)) { 18101 typeof this[property] != 'function' && (this[property] = null); 18102 } 18103 }; 18104 18105 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 18106 18107})(window.Zepto || window.jQuery, window, document); 18108 18109/** 18110 * Lazy Plugin 18111 * @version 2.0.0-beta.3 18112 * @author Bartosz Wojciechowski 18113 * @license The MIT License (MIT) 18114 */ 18115;(function($, window, document, undefined) { 18116 18117 /** 18118 * Creates the lazy plugin. 18119 * @class The Lazy Plugin 18120 * @param {Owl} carousel - The Owl Carousel 18121 */ 18122 var Lazy = function(carousel) { 18123 18124 /** 18125 * Reference to the core. 18126 * @protected 18127 * @type {Owl} 18128 */ 18129 this._core = carousel; 18130 18131 /** 18132 * Already loaded items. 18133 * @protected 18134 * @type {Array.<jQuery>} 18135 */ 18136 this._loaded = []; 18137 18138 /** 18139 * Event handlers. 18140 * @protected 18141 * @type {Object} 18142 */ 18143 this._handlers = { 18144 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 18145 if (!e.namespace) { 18146 return; 18147 } 18148 18149 if (!this._core.settings || !this._core.settings.lazyLoad) { 18150 return; 18151 } 18152 18153 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 18154 var settings = this._core.settings, 18155 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 18156 i = ((settings.center && n * -1) || 0), 18157 position = ((e.property && e.property.value) || this._core.current()) + i, 18158 clones = this._core.clones().length, 18159 load = $.proxy(function(i, v) { this.load(v) }, this); 18160 18161 while (i++ < n) { 18162 this.load(clones / 2 + this._core.relative(position)); 18163 clones && $.each(this._core.clones(this._core.relative(position)), load); 18164 position++; 18165 } 18166 } 18167 }, this) 18168 }; 18169 18170 // set the default options 18171 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 18172 18173 // register event handler 18174 this._core.$element.on(this._handlers); 18175 } 18176 18177 /** 18178 * Default options. 18179 * @public 18180 */ 18181 Lazy.Defaults = { 18182 lazyLoad: false 18183 } 18184 18185 /** 18186 * Loads all resources of an item at the specified position. 18187 * @param {Number} position - The absolute position of the item. 18188 * @protected 18189 */ 18190 Lazy.prototype.load = function(position) { 18191 var $item = this._core.$stage.children().eq(position), 18192 $elements = $item && $item.find('.owl-lazy'); 18193 18194 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 18195 return; 18196 } 18197 18198 $elements.each($.proxy(function(index, element) { 18199 var $element = $(element), image, 18200 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 18201 18202 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 18203 18204 if ($element.is('img')) { 18205 $element.one('load.owl.lazy', $.proxy(function() { 18206 $element.css('opacity', 1); 18207 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 18208 }, this)).attr('src', url); 18209 } else { 18210 image = new Image(); 18211 image.onload = $.proxy(function() { 18212 $element.css({ 18213 'background-image': 'url(' + url + ')', 18214 'opacity': '1' 18215 }); 18216 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 18217 }, this); 18218 image.src = url; 18219 } 18220 }, this)); 18221 18222 this._loaded.push($item.get(0)); 18223 } 18224 18225 /** 18226 * Destroys the plugin. 18227 * @public 18228 */ 18229 Lazy.prototype.destroy = function() { 18230 var handler, property; 18231 18232 for (handler in this.handlers) { 18233 this._core.$element.off(handler, this.handlers[handler]); 18234 } 18235 for (property in Object.getOwnPropertyNames(this)) { 18236 typeof this[property] != 'function' && (this[property] = null); 18237 } 18238 }; 18239 18240 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 18241 18242})(window.Zepto || window.jQuery, window, document); 18243 18244/** 18245 * AutoHeight Plugin 18246 * @version 2.0.0-beta.3 18247 * @author Bartosz Wojciechowski 18248 * @license The MIT License (MIT) 18249 */ 18250;(function($, window, document, undefined) { 18251 18252 /** 18253 * Creates the auto height plugin. 18254 * @class The Auto Height Plugin 18255 * @param {Owl} carousel - The Owl Carousel 18256 */ 18257 var AutoHeight = function(carousel) { 18258 /** 18259 * Reference to the core. 18260 * @protected 18261 * @type {Owl} 18262 */ 18263 this._core = carousel; 18264 18265 /** 18266 * All event handlers. 18267 * @protected 18268 * @type {Object} 18269 */ 18270 this._handlers = { 18271 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 18272 if (e.namespace && this._core.settings.autoHeight) { 18273 this.update(); 18274 } 18275 }, this), 18276 'changed.owl.carousel': $.proxy(function(e) { 18277 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 18278 this.update(); 18279 } 18280 }, this), 18281 'loaded.owl.lazy': $.proxy(function(e) { 18282 if (e.namespace && this._core.settings.autoHeight 18283 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 18284 this.update(); 18285 } 18286 }, this) 18287 }; 18288 18289 // set default options 18290 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 18291 18292 // register event handlers 18293 this._core.$element.on(this._handlers); 18294 }; 18295 18296 /** 18297 * Default options. 18298 * @public 18299 */ 18300 AutoHeight.Defaults = { 18301 autoHeight: false, 18302 autoHeightClass: 'owl-height' 18303 }; 18304 18305 /** 18306 * Updates the view. 18307 */ 18308 AutoHeight.prototype.update = function() { 18309 var start = this._core._current, 18310 end = start + this._core.settings.items, 18311 visible = this._core.$stage.children().toArray().slice(start, end); 18312 heights = [], 18313 maxheight = 0; 18314 18315 $.each(visible, function(index, item) { 18316 heights.push($(item).height()); 18317 }); 18318 18319 maxheight = Math.max.apply(null, heights); 18320 18321 this._core.$stage.parent() 18322 .height(maxheight) 18323 .addClass(this._core.settings.autoHeightClass); 18324 }; 18325 18326 AutoHeight.prototype.destroy = function() { 18327 var handler, property; 18328 18329 for (handler in this._handlers) { 18330 this._core.$element.off(handler, this._handlers[handler]); 18331 } 18332 for (property in Object.getOwnPropertyNames(this)) { 18333 typeof this[property] != 'function' && (this[property] = null); 18334 } 18335 }; 18336 18337 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 18338 18339})(window.Zepto || window.jQuery, window, document); 18340 18341/** 18342 * Video Plugin 18343 * @version 2.0.0-beta.3 18344 * @author Bartosz Wojciechowski 18345 * @license The MIT License (MIT) 18346 */ 18347;(function($, window, document, undefined) { 18348 18349 /** 18350 * Creates the video plugin. 18351 * @class The Video Plugin 18352 * @param {Owl} carousel - The Owl Carousel 18353 */ 18354 var Video = function(carousel) { 18355 /** 18356 * Reference to the core. 18357 * @protected 18358 * @type {Owl} 18359 */ 18360 this._core = carousel; 18361 18362 /** 18363 * Cache all video URLs. 18364 * @protected 18365 * @type {Object} 18366 */ 18367 this._videos = {}; 18368 18369 /** 18370 * Current playing item. 18371 * @protected 18372 * @type {jQuery} 18373 */ 18374 this._playing = null; 18375 18376 /** 18377 * All event handlers. 18378 * @todo The cloned content removale is too late 18379 * @protected 18380 * @type {Object} 18381 */ 18382 this._handlers = { 18383 'initialized.owl.carousel': $.proxy(function(e) { 18384 if (e.namespace) { 18385 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 18386 } 18387 }, this), 18388 'resize.owl.carousel': $.proxy(function(e) { 18389 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 18390 e.preventDefault(); 18391 } 18392 }, this), 18393 'refreshed.owl.carousel': $.proxy(function(e) { 18394 if (e.namespace && this._core.is('resizing')) { 18395 this._core.$stage.find('.cloned .owl-video-frame').remove(); 18396 } 18397 }, this), 18398 'changed.owl.carousel': $.proxy(function(e) { 18399 if (e.namespace && e.property.name === 'position' && this._playing) { 18400 this.stop(); 18401 } 18402 }, this), 18403 'prepared.owl.carousel': $.proxy(function(e) { 18404 if (!e.namespace) { 18405 return; 18406 } 18407 18408 var $element = $(e.content).find('.owl-video'); 18409 18410 if ($element.length) { 18411 $element.css('display', 'none'); 18412 this.fetch($element, $(e.content)); 18413 } 18414 }, this) 18415 }; 18416 18417 // set default options 18418 this._core.options = $.extend({}, Video.Defaults, this._core.options); 18419 18420 // register event handlers 18421 this._core.$element.on(this._handlers); 18422 18423 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 18424 this.play(e); 18425 }, this)); 18426 }; 18427 18428 /** 18429 * Default options. 18430 * @public 18431 */ 18432 Video.Defaults = { 18433 video: false, 18434 videoHeight: false, 18435 videoWidth: false 18436 }; 18437 18438 /** 18439 * Gets the video ID and the type (YouTube/Vimeo only). 18440 * @protected 18441 * @param {jQuery} target - The target containing the video data. 18442 * @param {jQuery} item - The item containing the video. 18443 */ 18444 Video.prototype.fetch = function(target, item) { 18445 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 18446 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 18447 width = target.attr('data-width') || this._core.settings.videoWidth, 18448 height = target.attr('data-height') || this._core.settings.videoHeight, 18449 url = target.attr('href'); 18450 18451 if (url) { 18452 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+)?/); 18453 18454 if (id[3].indexOf('youtu') > -1) { 18455 type = 'youtube'; 18456 } else if (id[3].indexOf('vimeo') > -1) { 18457 type = 'vimeo'; 18458 } else { 18459 throw new Error('Video URL not supported.'); 18460 } 18461 id = id[6]; 18462 } else { 18463 throw new Error('Missing video URL.'); 18464 } 18465 18466 this._videos[url] = { 18467 type: type, 18468 id: id, 18469 width: width, 18470 height: height 18471 }; 18472 18473 item.attr('data-video', url); 18474 18475 this.thumbnail(target, this._videos[url]); 18476 }; 18477 18478 /** 18479 * Creates video thumbnail. 18480 * @protected 18481 * @param {jQuery} target - The target containing the video data. 18482 * @param {Object} info - The video info object. 18483 * @see `fetch` 18484 */ 18485 Video.prototype.thumbnail = function(target, video) { 18486 var tnLink, 18487 icon, 18488 path, 18489 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 18490 customTn = target.find('img'), 18491 srcType = 'src', 18492 lazyClass = '', 18493 settings = this._core.settings, 18494 create = function(path) { 18495 icon = '<div class="owl-video-play-icon"></div>'; 18496 18497 if (settings.lazyLoad) { 18498 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 18499 } else { 18500 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 18501 } 18502 target.after(tnLink); 18503 target.after(icon); 18504 }; 18505 18506 // wrap video content into owl-video-wrapper div 18507 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 18508 18509 if (this._core.settings.lazyLoad) { 18510 srcType = 'data-src'; 18511 lazyClass = 'owl-lazy'; 18512 } 18513 18514 // custom thumbnail 18515 if (customTn.length) { 18516 create(customTn.attr(srcType)); 18517 customTn.remove(); 18518 return false; 18519 } 18520 18521 if (video.type === 'youtube') { 18522 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 18523 create(path); 18524 } else if (video.type === 'vimeo') { 18525 $.ajax({ 18526 type: 'GET', 18527 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 18528 jsonp: 'callback', 18529 dataType: 'jsonp', 18530 success: function(data) { 18531 path = data[0].thumbnail_large; 18532 create(path); 18533 } 18534 }); 18535 } 18536 }; 18537 18538 /** 18539 * Stops the current video. 18540 * @public 18541 */ 18542 Video.prototype.stop = function() { 18543 this._core.trigger('stop', null, 'video'); 18544 this._playing.find('.owl-video-frame').remove(); 18545 this._playing.removeClass('owl-video-playing'); 18546 this._playing = null; 18547 this._core.leave('playing'); 18548 this._core.trigger('stopped', null, 'video'); 18549 }; 18550 18551 /** 18552 * Starts the current video. 18553 * @public 18554 * @param {Event} event - The event arguments. 18555 */ 18556 Video.prototype.play = function(event) { 18557 var target = $(event.target), 18558 item = target.closest('.' + this._core.settings.itemClass), 18559 video = this._videos[item.attr('data-video')], 18560 width = video.width || '100%', 18561 height = video.height || this._core.$stage.height(), 18562 html; 18563 18564 if (this._playing) { 18565 return; 18566 } 18567 18568 this._core.enter('playing'); 18569 this._core.trigger('play', null, 'video'); 18570 18571 item = this._core.items(this._core.relative(item.index())); 18572 18573 this._core.reset(item.index()); 18574 18575 if (video.type === 'youtube') { 18576 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 18577 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 18578 } else if (video.type === 'vimeo') { 18579 html = '<iframe src="//player.vimeo.com/video/' + video.id + 18580 '?autoplay=1" width="' + width + '" height="' + height + 18581 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 18582 } 18583 18584 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 18585 18586 this._playing = item.addClass('owl-video-playing'); 18587 }; 18588 18589 /** 18590 * Checks whether an video is currently in full screen mode or not. 18591 * @todo Bad style because looks like a readonly method but changes members. 18592 * @protected 18593 * @returns {Boolean} 18594 */ 18595 Video.prototype.isInFullScreen = function() { 18596 var element = document.fullscreenElement || document.mozFullScreenElement || 18597 document.webkitFullscreenElement; 18598 18599 return element && $(element).parent().hasClass('owl-video-frame'); 18600 }; 18601 18602 /** 18603 * Destroys the plugin. 18604 */ 18605 Video.prototype.destroy = function() { 18606 var handler, property; 18607 18608 this._core.$element.off('click.owl.video'); 18609 18610 for (handler in this._handlers) { 18611 this._core.$element.off(handler, this._handlers[handler]); 18612 } 18613 for (property in Object.getOwnPropertyNames(this)) { 18614 typeof this[property] != 'function' && (this[property] = null); 18615 } 18616 }; 18617 18618 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 18619 18620})(window.Zepto || window.jQuery, window, document); 18621 18622/** 18623 * Animate Plugin 18624 * @version 2.0.0-beta.3 18625 * @author Bartosz Wojciechowski 18626 * @license The MIT License (MIT) 18627 */ 18628;(function($, window, document, undefined) { 18629 18630 /** 18631 * Creates the animate plugin. 18632 * @class The Navigation Plugin 18633 * @param {Owl} scope - The Owl Carousel 18634 */ 18635 var Animate = function(scope) { 18636 this.core = scope; 18637 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 18638 this.swapping = true; 18639 this.previous = undefined; 18640 this.next = undefined; 18641 18642 this.handlers = { 18643 'change.owl.carousel': $.proxy(function(e) { 18644 if (e.namespace && e.property.name == 'position') { 18645 this.previous = this.core.current(); 18646 this.next = e.property.value; 18647 } 18648 }, this), 18649 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 18650 if (e.namespace) { 18651 this.swapping = e.type == 'translated'; 18652 } 18653 }, this), 18654 'translate.owl.carousel': $.proxy(function(e) { 18655 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 18656 this.swap(); 18657 } 18658 }, this) 18659 }; 18660 18661 this.core.$element.on(this.handlers); 18662 }; 18663 18664 /** 18665 * Default options. 18666 * @public 18667 */ 18668 Animate.Defaults = { 18669 animateOut: false, 18670 animateIn: false 18671 }; 18672 18673 /** 18674 * Toggles the animation classes whenever an translations starts. 18675 * @protected 18676 * @returns {Boolean|undefined} 18677 */ 18678 Animate.prototype.swap = function() { 18679 18680 if (this.core.settings.items !== 1) { 18681 return; 18682 } 18683
18684 if (!$.support.animation || !$.support.transition) { 18685 return; 18686 } 18687 18688 this.core.speed(0); 18689 18690 var left, 18691 clear = $.proxy(this.clear, this), 18692 previous = this.core.$stage.children().eq(this.previous), 18693 next = this.core.$stage.children().eq(this.next), 18694 incoming = this.core.settings.animateIn, 18695 outgoing = this.core.settings.animateOut; 18696 18697 if (this.core.current() === this.previous) { 18698 return; 18699 } 18700 18701 if (outgoing) { 18702 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 18703 previous.css( { 'left': left + 'px' } ) 18704 .addClass('animated owl-animated-out') 18705 .addClass(outgoing) 18706 .on($.support.animation.end, clear); 18707 } 18708 18709 if (incoming) { 18710 next.addClass('animated owl-animated-in') 18711 .addClass(incoming) 18712 .on($.support.animation.end, clear); 18713 } 18714 }; 18715 18716 Animate.prototype.clear = function(e) { 18717 if ($(e.target).hasClass('animated')) { 18718 $(e.target).css( { 'left': '' } ) 18719 .removeClass('animated owl-animated-out owl-animated-in') 18720 .removeClass(this.core.settings.animateIn) 18721 .removeClass(this.core.settings.animateOut); 18722 this.core.onTransitionEnd(); 18723 } 18724 }; 18725 18726 /** 18727 * Destroys the plugin. 18728 * @public 18729 */ 18730 Animate.prototype.destroy = function() { 18731 var handler, property; 18732 18733 for (handler in this.handlers) { 18734 this.core.$element.off(handler, this.handlers[handler]); 18735 } 18736 for (property in Object.getOwnPropertyNames(this)) { 18737 typeof this[property] != 'function' && (this[property] = null); 18738 } 18739 }; 18740 18741 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 18742 18743})(window.Zepto || window.jQuery, window, document); 18744 18745/** 18746 * Autoplay Plugin 18747 * @version 2.0.0-beta.3 18748 * @author Bartosz Wojciechowski 18749 * @author Artus Kolanowski 18750 * @license The MIT License (MIT) 18751 */ 18752;(function($, window, document, undefined) { 18753 18754 /** 18755 * Creates the autoplay plugin. 18756 * @class The Autoplay Plugin 18757 * @param {Owl} scope - The Owl Carousel 18758 */ 18759 var Autoplay = function(carousel) { 18760 /** 18761 * Reference to the core. 18762 * @protected 18763 * @type {Owl} 18764 */ 18765 this._core = carousel; 18766 18767 /** 18768 * The autoplay interval. 18769 * @type {Number} 18770 */ 18771 this._interval = null; 18772 18773 /** 18774 * Indicates whenever the autoplay is paused. 18775 * @type {Boolean} 18776 */ 18777 this._paused = false; 18778 18779 /** 18780 * All event handlers. 18781 * @protected 18782 * @type {Object} 18783 */ 18784 this._handlers = { 18785 'changed.owl.carousel': $.proxy(function(e) { 18786 if (e.namespace && e.property.name === 'settings') { 18787 if (this._core.settings.autoplay) { 18788 this.play(); 18789 } else { 18790 this.stop(); 18791 } 18792 } 18793 }, this), 18794 'initialized.owl.carousel': $.proxy(function(e) { 18795 if (e.namespace && this._core.settings.autoplay) { 18796 this.play(); 18797 } 18798 }, this), 18799 'play.owl.autoplay': $.proxy(function(e, t, s) { 18800 if (e.namespace) { 18801 this.play(t, s); 18802 } 18803 }, this), 18804 'stop.owl.autoplay': $.proxy(function(e) { 18805 if (e.namespace) { 18806 this.stop(); 18807 } 18808 }, this), 18809 'mouseover.owl.autoplay': $.proxy(function() { 18810 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 18811 this.pause(); 18812 } 18813 }, this), 18814 'mouseleave.owl.autoplay': $.proxy(function() { 18815 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 18816 this.play(); 18817 } 18818 }, this) 18819 }; 18820 18821 // register event handlers 18822 this._core.$element.on(this._handlers); 18823 18824 // set default options 18825 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 18826 }; 18827 18828 /** 18829 * Default options. 18830 * @public 18831 */ 18832 Autoplay.Defaults = { 18833 autoplay: false, 18834 autoplayTimeout: 5000, 18835 autoplayHoverPause: false, 18836 autoplaySpeed: false 18837 }; 18838 18839 /** 18840 * Starts the autoplay. 18841 * @public 18842 * @param {Number} [timeout] - The interval before the next animation starts. 18843 * @param {Number} [speed] - The animation speed for the animations. 18844 */ 18845 Autoplay.prototype.play = function(timeout, speed) { 18846 this._paused = false; 18847 18848 if (this._core.is('rotating')) { 18849 return; 18850 } 18851 18852 this._core.enter('rotating'); 18853 18854 this._interval = window.setInterval($.proxy(function() { 18855 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 18856 return; 18857 } 18858 this._core.next(speed || this._core.settings.autoplaySpeed); 18859 }, this), timeout || this._core.settings.autoplayTimeout); 18860 }; 18861 18862 /** 18863 * Stops the autoplay. 18864 * @public 18865 */ 18866 Autoplay.prototype.stop = function() { 18867 if (!this._core.is('rotating')) { 18868 return; 18869 } 18870 18871 window.clearInterval(this._interval); 18872 this._core.leave('rotating'); 18873 }; 18874 18875 /** 18876 * Stops the autoplay. 18877 * @public 18878 */ 18879 Autoplay.prototype.pause = function() { 18880 if (!this._core.is('rotating')) { 18881 return; 18882 } 18883 18884 this._paused = true; 18885 }; 18886 18887 /** 18888 * Destroys the plugin. 18889 */ 18890 Autoplay.prototype.destroy = function() { 18891 var handler, property; 18892 18893 this.stop(); 18894 18895 for (handler in this._handlers) { 18896 this._core.$element.off(handler, this._handlers[handler]); 18897 } 18898 for (property in Object.getOwnPropertyNames(this)) { 18899 typeof this[property] != 'function' && (this[property] = null); 18900 } 18901 }; 18902 18903 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 18904 18905})(window.Zepto || window.jQuery, window, document); 18906 18907/** 18908 * Navigation Plugin 18909 * @version 2.0.0-beta.3 18910 * @author Artus Kolanowski 18911 * @license The MIT License (MIT) 18912 */ 18913;(function($, window, document, undefined) { 18914 'use strict'; 18915 18916 /** 18917 * Creates the navigation plugin. 18918 * @class The Navigation Plugin 18919 * @param {Owl} carousel - The Owl Carousel. 18920 */ 18921 var Navigation = function(carousel) { 18922 /** 18923 * Reference to the core. 18924 * @protected 18925 * @type {Owl} 18926 */ 18927 this._core = carousel; 18928 18929 /** 18930 * Indicates whether the plugin is initialized or not. 18931 * @protected 18932 * @type {Boolean} 18933 */ 18934 this._initialized = false;
vendor: 14,104 bytes, lines 18935-19463
18935 18936 /** 18937 * The current paging indexes. 18938 * @protected 18939 * @type {Array} 18940 */ 18941 this._pages = []; 18942 18943 /** 18944 * All DOM elements of the user interface. 18945 * @protected 18946 * @type {Object} 18947 */ 18948 this._controls = {}; 18949 18950 /** 18951 * Markup for an indicator. 18952 * @protected 18953 * @type {Array.<String>} 18954 */ 18955 this._templates = []; 18956 18957 /** 18958 * The carousel element. 18959 * @type {jQuery} 18960 */ 18961 this.$element = this._core.$element; 18962 18963 /** 18964 * Overridden methods of the carousel. 18965 * @protected 18966 * @type {Object} 18967 */ 18968 this._overrides = { 18969 next: this._core.next, 18970 prev: this._core.prev, 18971 to: this._core.to 18972 }; 18973 18974 /** 18975 * All event handlers. 18976 * @protected 18977 * @type {Object} 18978 */ 18979 this._handlers = { 18980 'prepared.owl.carousel': $.proxy(function(e) { 18981 if (e.namespace && this._core.settings.dotsData) { 18982 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 18983 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 18984 } 18985 }, this), 18986 'added.owl.carousel': $.proxy(function(e) { 18987 if (e.namespace && this._core.settings.dotsData) { 18988 this._templates.splice(e.position, 0, this._templates.pop()); 18989 } 18990 }, this), 18991 'remove.owl.carousel': $.proxy(function(e) { 18992 if (e.namespace && this._core.settings.dotsData) { 18993 this._templates.splice(e.position, 1); 18994 } 18995 }, this), 18996 'changed.owl.carousel': $.proxy(function(e) { 18997 if (e.namespace && e.property.name == 'position') { 18998 this.draw(); 18999 } 19000 }, this), 19001 'initialized.owl.carousel': $.proxy(function(e) { 19002 if (e.namespace && !this._initialized) { 19003 this._core.trigger('initialize', null, 'navigation'); 19004 this.initialize(); 19005 this.update(); 19006 this.draw(); 19007 this._initialized = true; 19008 this._core.trigger('initialized', null, 'navigation'); 19009 } 19010 }, this), 19011 'refreshed.owl.carousel': $.proxy(function(e) { 19012 if (e.namespace && this._initialized) { 19013 this._core.trigger('refresh', null, 'navigation'); 19014 this.update(); 19015 this.draw(); 19016 this._core.trigger('refreshed', null, 'navigation'); 19017 } 19018 }, this) 19019 }; 19020 19021 // set default options 19022 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 19023 19024 // register event handlers 19025 this.$element.on(this._handlers); 19026 }; 19027 19028 /** 19029 * Default options. 19030 * @public 19031 * @todo Rename `slideBy` to `navBy` 19032 */ 19033 Navigation.Defaults = { 19034 nav: false, 19035 navText: [ 'prev', 'next' ], 19036 navSpeed: false, 19037 navElement: 'div', 19038 navContainer: false, 19039 navContainerClass: 'owl-nav', 19040 navClass: [ 'owl-prev', 'owl-next' ], 19041 slideBy: 1, 19042 dotClass: 'owl-dot', 19043 dotsClass: 'owl-dots', 19044 dots: true, 19045 dotsEach: false, 19046 dotsData: false, 19047 dotsSpeed: false, 19048 dotsContainer: false 19049 }; 19050 19051 /** 19052 * Initializes the layout of the plugin and extends the carousel. 19053 * @protected 19054 */ 19055 Navigation.prototype.initialize = function() { 19056 var override, 19057 settings = this._core.settings; 19058 19059 // create DOM structure for relative navigation 19060 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 19061 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 19062 19063 this._controls.$previous = $('<' + settings.navElement + '>') 19064 .addClass(settings.navClass[0]) 19065 .html(settings.navText[0]) 19066 .prependTo(this._controls.$relative) 19067 .on('click', $.proxy(function(e) { 19068 this.prev(settings.navSpeed); 19069 }, this)); 19070 this._controls.$next = $('<' + settings.navElement + '>') 19071 .addClass(settings.navClass[1]) 19072 .html(settings.navText[1]) 19073 .appendTo(this._controls.$relative) 19074 .on('click', $.proxy(function(e) { 19075 this.next(settings.navSpeed); 19076 }, this)); 19077 19078 // create DOM structure for absolute navigation 19079 if (!settings.dotsData) { 19080 this._templates = [ $('<div>') 19081 .addClass(settings.dotClass) 19082 .append($('<span>')) 19083 .prop('outerHTML') ]; 19084 } 19085 19086 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 19087 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 19088 19089 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 19090 var index = $(e.target).parent().is(this._controls.$absolute) 19091 ? $(e.target).index() : $(e.target).parent().index(); 19092 19093 e.preventDefault(); 19094 19095 this.to(index, settings.dotsSpeed); 19096 }, this)); 19097 19098 // override public methods of the carousel 19099 for (override in this._overrides) { 19100 this._core[override] = $.proxy(this[override], this); 19101 } 19102 }; 19103 19104 /** 19105 * Destroys the plugin. 19106 * @protected 19107 */ 19108 Navigation.prototype.destroy = function() { 19109 var handler, control, property, override; 19110 19111 for (handler in this._handlers) { 19112 this.$element.off(handler, this._handlers[handler]); 19113 } 19114 for (control in this._controls) { 19115 this._controls[control].remove(); 19116 } 19117 for (override in this.overides) { 19118 this._core[override] = this._overrides[override]; 19119 } 19120 for (property in Object.getOwnPropertyNames(this)) { 19121 typeof this[property] != 'function' && (this[property] = null); 19122 } 19123 }; 19124 19125 /** 19126 * Updates the internal state. 19127 * @protected 19128 */ 19129 Navigation.prototype.update = function() { 19130 var i, j, k, 19131 lower = this._core.clones().length / 2, 19132 upper = lower + this._core.items().length, 19133 maximum = this._core.maximum(true), 19134 settings = this._core.settings, 19135 size = settings.center || settings.autoWidth || settings.dotsData 19136 ? 1 : settings.dotsEach || settings.items; 19137 19138 if (settings.slideBy !== 'page') { 19139 settings.slideBy = Math.min(settings.slideBy, settings.items); 19140 } 19141 19142 if (settings.dots || settings.slideBy == 'page') { 19143 this._pages = []; 19144 19145 for (i = lower, j = 0, k = 0; i < upper; i++) { 19146 if (j >= size || j === 0) { 19147 this._pages.push({ 19148 start: Math.min(maximum, i - lower), 19149 end: i - lower + size - 1 19150 }); 19151 if (Math.min(maximum, i - lower) === maximum) { 19152 break; 19153 } 19154 j = 0, ++k; 19155 } 19156 j += this._core.mergers(this._core.relative(i)); 19157 } 19158 } 19159 }; 19160 19161 /** 19162 * Draws the user interface. 19163 * @todo The option `dotsData` wont work. 19164 * @protected 19165 */ 19166 Navigation.prototype.draw = function() { 19167 var difference, 19168 settings = this._core.settings, 19169 disabled = this._core.items().length <= settings.items, 19170 index = this._core.relative(this._core.current()), 19171 loop = settings.loop || settings.rewind; 19172 19173 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 19174 19175 if (settings.nav) { 19176 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 19177 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 19178 } 19179 19180 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 19181 19182 if (settings.dots) { 19183 difference = this._pages.length - this._controls.$absolute.children().length; 19184 19185 if (settings.dotsData && difference !== 0) { 19186 this._controls.$absolute.html(this._templates.join('')); 19187 } else if (difference > 0) { 19188 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 19189 } else if (difference < 0) { 19190 this._controls.$absolute.children().slice(difference).remove(); 19191 } 19192 19193 this._controls.$absolute.find('.active').removeClass('active'); 19194 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 19195 } 19196 }; 19197 19198 /** 19199 * Extends event data. 19200 * @protected 19201 * @param {Event} event - The event object which gets thrown. 19202 */ 19203 Navigation.prototype.onTrigger = function(event) { 19204 var settings = this._core.settings; 19205 19206 event.page = { 19207 index: $.inArray(this.current(), this._pages), 19208 count: this._pages.length, 19209 size: settings && (settings.center || settings.autoWidth || settings.dotsData 19210 ? 1 : settings.dotsEach || settings.items) 19211 }; 19212 }; 19213 19214 /** 19215 * Gets the current page position of the carousel. 19216 * @protected 19217 * @returns {Number} 19218 */ 19219 Navigation.prototype.current = function() { 19220 var current = this._core.relative(this._core.current()); 19221 return $.grep(this._pages, $.proxy(function(page, index) { 19222 return page.start <= current && page.end >= current; 19223 }, this)).pop(); 19224 }; 19225 19226 /** 19227 * Gets the current succesor/predecessor position. 19228 * @protected 19229 * @returns {Number} 19230 */ 19231 Navigation.prototype.getPosition = function(successor) { 19232 var position, length, 19233 settings = this._core.settings; 19234 19235 if (settings.slideBy == 'page') { 19236 position = $.inArray(this.current(), this._pages); 19237 length = this._pages.length; 19238 successor ? ++position : --position; 19239 position = this._pages[((position % length) + length) % length].start; 19240 } else { 19241 position = this._core.relative(this._core.current()); 19242 length = this._core.items().length; 19243 successor ? position += settings.slideBy : position -= settings.slideBy; 19244 } 19245 19246 return position; 19247 }; 19248 19249 /** 19250 * Slides to the next item or page. 19251 * @public 19252 * @param {Number} [speed=false] - The time in milliseconds for the transition. 19253 */ 19254 Navigation.prototype.next = function(speed) { 19255 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 19256 }; 19257 19258 /** 19259 * Slides to the previous item or page. 19260 * @public 19261 * @param {Number} [speed=false] - The time in milliseconds for the transition. 19262 */ 19263 Navigation.prototype.prev = function(speed) { 19264 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 19265 }; 19266 19267 /** 19268 * Slides to the specified item or page. 19269 * @public 19270 * @param {Number} position - The position of the item or page. 19271 * @param {Number} [speed] - The time in milliseconds for the transition. 19272 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 19273 */ 19274 Navigation.prototype.to = function(position, speed, standard) { 19275 var length; 19276 19277 if (!standard) { 19278 length = this._pages.length; 19279 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 19280 } else { 19281 $.proxy(this._overrides.to, this._core)(position, speed); 19282 } 19283 }; 19284 19285 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 19286 19287})(window.Zepto || window.jQuery, window, document); 19288 19289/** 19290 * Hash Plugin 19291 * @version 2.0.0-beta.3 19292 * @author Artus Kolanowski 19293 * @license The MIT License (MIT) 19294 */ 19295;(function($, window, document, undefined) { 19296 'use strict'; 19297 19298 /** 19299 * Creates the hash plugin. 19300 * @class The Hash Plugin 19301 * @param {Owl} carousel - The Owl Carousel 19302 */ 19303 var Hash = function(carousel) { 19304 /** 19305 * Reference to the core. 19306 * @protected 19307 * @type {Owl} 19308 */ 19309 this._core = carousel; 19310 19311 /** 19312 * Hash index for the items. 19313 * @protected 19314 * @type {Object} 19315 */ 19316 this._hashes = {}; 19317 19318 /** 19319 * The carousel element. 19320 * @type {jQuery} 19321 */ 19322 this.$element = this._core.$element; 19323 19324 /** 19325 * All event handlers. 19326 * @protected 19327 * @type {Object} 19328 */ 19329 this._handlers = { 19330 /*'initialized.owl.carousel': $.proxy(function(e) { 19331 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 19332 $(window).trigger('hashchange.owl.navigation'); 19333 } 19334 }, this),*/ 19335 'prepared.owl.carousel': $.proxy(function(e) { 19336 if (e.namespace) { 19337 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 19338 19339 if (!hash) { 19340 return; 19341 } 19342 19343 this._hashes[hash] = e.content; 19344 } 19345 }, this), 19346 'changed.owl.carousel': $.proxy(function(e) { 19347 if (e.namespace && e.property.name === 'position') { 19348 var current = this._core.items(this._core.relative(this._core.current())), 19349 hash = $.map(this._hashes, function(item, hash) { 19350 return item === current ? hash : null; 19351 }).join(); 19352 19353 if (!hash || window.location.hash.slice(1) === hash) { 19354 return; 19355 } 19356 19357 window.location.hash = hash; 19358 } 19359 }, this) 19360 }; 19361 19362 // set default options 19363 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 19364 19365 // register the event handlers 19366 this.$element.on(this._handlers); 19367 19368 // register event listener for hash navigation 19369 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 19370 var hash = window.location.hash.substring(1), 19371 items = this._core.$stage.children(), 19372 position = this._hashes[hash] && items.index(this._hashes[hash]); 19373 19374 if (position === undefined || position === this._core.current()) { 19375 return; 19376 } 19377 19378 this._core.to(this._core.relative(position), false, true); 19379 }, this));*/ 19380 }; 19381 19382 /** 19383 * Default options. 19384 * @public 19385 */ 19386 Hash.Defaults = { 19387 URLhashListener: false 19388 }; 19389 19390 /** 19391 * Destroys the plugin. 19392 * @public 19393 */ 19394 Hash.prototype.destroy = function() { 19395 var handler, property; 19396 19397 $(window).off('hashchange.owl.navigation'); 19398 19399 for (handler in this._handlers) { 19400 this._core.$element.off(handler, this._handlers[handler]); 19401 } 19402 for (property in Object.getOwnPropertyNames(this)) { 19403 typeof this[property] != 'function' && (this[property] = null); 19404 } 19405 }; 19406 19407 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 19408 19409})(window.Zepto || window.jQuery, window, document); 19410 19411/** 19412 * Support Plugin 19413 * 19414 * @version 2.0.0-beta.3 19415 * @author Vivid Planet Software GmbH 19416 * @author Artus Kolanowski 19417 * @license The MIT License (MIT) 19418 */ 19419;(function($, window, document, undefined) { 19420 19421 var style = $('<support>').get(0).style, 19422 prefixes = 'Webkit Moz O ms'.split(' '), 19423 events = { 19424 transition: { 19425 end: { 19426 WebkitTransition: 'webkitTransitionEnd', 19427 MozTransition: 'transitionend', 19428 OTransition: 'oTransitionEnd', 19429 transition: 'transitionend' 19430 } 19431 }, 19432 animation: { 19433 end: { 19434 WebkitAnimation: 'webkitAnimationEnd', 19435 MozAnimation: 'animationend', 19436 OAnimation: 'oAnimationEnd', 19437 animation: 'animationend' 19438 } 19439 } 19440 }, 19441 tests = { 19442 csstransforms: function() { 19443 return !!test('transform'); 19444 }, 19445 csstransforms3d: function() { 19446 return !!test('perspective'); 19447 }, 19448 csstransitions: function() { 19449 return !!test('transition'); 19450 }, 19451 cssanimations: function() { 19452 return !!test('animation'); 19453 } 19454 }; 19455 19456 function test(property, prefixed) { 19457 var result = false, 19458 upper = property.charAt(0).toUpperCase() + property.slice(1); 19459 19460 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 19461 if (style[property] !== undefined) { 19462 result = prefixed ? property : true; 19463 return false;
19464 } 19465 }); 19466 19467 return result; 19468 } 19469 19470 function prefixed(property) { 19471 return test(property, true); 19472 } 19473 19474 if (tests.csstransitions()) { 19475 /* jshint -W053 */ 19476 $.support.transition = new String(prefixed('transition')) 19477 $.support.transition.end = events.transition.end[ $.support.transition ]; 19478 } 19479 19480 if (tests.cssanimations()) { 19481 /* jshint -W053 */ 19482 $.support.animation = new String(prefixed('animation')) 19483 $.support.animation.end = events.animation.end[ $.support.animation ]; 19484 } 19485 19486 if (tests.csstransforms()) { 19487 /* jshint -W053 */ 19488 $.support.transform = new String(prefixed('transform')); 19489 $.support.transform3d = tests.csstransforms3d(); 19490 } 19491 19492})(window.Zepto || window.jQuery, window, document); 19493 19494(function(window, document, undefined) { 19495 19496 /** 19497 * Find the absolute position of an element 19498 */ 19499 var absPos = function(element) { 19500 var offsetLeft, offsetTop; 19501 offsetLeft = offsetTop = 0; 19502 if (element.offsetParent) { 19503 do { 19504 offsetLeft += element.offsetLeft; 19505 offsetTop += element.offsetTop; 19506 } while (element = element.offsetParent); 19507 } 19508 return [offsetLeft, offsetTop]; 19509 }; 19510 19511 /** 19512 * @constructor Progress Circle class 19513 * @param params.canvas Canvas on which the circles will be drawn. 19514 * @param params.minRadius Inner radius of the innermost circle, in px. 19515 * @param params.arcWidth Width of each circle(to be more accurate, ring). 19516 * @param params.gapWidth Space between each circle. 19517 * @param params.centerX X coordinate of the center of circles. 19518 * @param params.centerY Y coordinate of the center of circles. 19519 * @param params.infoLineBaseAngle Base angle of the info line. 19520 * @param params.infoLineAngleInterval Angles between the info lines. 19521 */ 19522 var ProgressCircle = function(params) { 19523 this.canvas = params.canvas; 19524 this.minRadius = params.minRadius || 15; 19525 this.arcWidth = params.arcWidth || 5; 19526 this.gapWidth = params.gapWidth || 3; 19527 this.centerX = params.centerX || this.canvas.width / 2; 19528 this.centerY = params.centerY || this.canvas.height / 2;
19529 this.infoLineLength = params.infoLineLength || 60; 19530 this.horizLineLength = params.horizLineLength || 10; 19531 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 19532 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 19533 19534 this.context = this.canvas.getContext('2d'); 19535 19536 this.width = this.canvas.width; 19537 this.height = this.canvas.height; 19538 19539 this.circles = []; 19540 this.runningCount = 0; 19541 }; 19542 19543 ProgressCircle.prototype = { 19544 constructor: ProgressCircle, 19545 19546 /** 19547 * @method Adds an progress monitor entry. 19548 * @param params.fillColor Color to fill in the circle. 19549 * @param params.outlineColor Color to outline the circle. 19550 * @param params.progressListener Callback function to fetch the progress. 19551 * @param params.infoListener Callback function to fetch the info. 19552 * @returns this 19553 */ 19554 addEntry: function(params) { 19555 this.circles.push(new Circle({ 19556 canvas: this.canvas, 19557 context: this.context, 19558 centerX: this.centerX, 19559 centerY: this.centerY, 19560 innerRadius: this.minRadius + this.circles.length * 19561 (this.gapWidth + this.arcWidth), 19562 arcWidth: this.arcWidth,
19563 infoLineLength: this.infoLineLength, 19564 horizLineLength: this.horizLineLength, 19565 19566 id: this.circles.length, 19567 fillColor: params.fillColor, 19568 outlineColor: params.outlineColor, 19569 progressListener: params.progressListener, 19570 infoListener: params.infoListener, 19571 infoLineAngle: this.infoLineBaseAngle + 19572 this.circles.length * this.infoLineAngleInterval, 19573 })); 19574 19575 return this; 19576 }, 19577 19578 /** 19579 * @method Starts the monitor and updates with the given interval. 19580 * @param interval Interval between updates, in millisecond. 19581 * @returns this 19582 */ 19583 start: function(interval) { 19584 var self = this; 19585 this.timer = setInterval(function() { 19586 self._update(); 19587 }, interval || 33); 19588 19589 return this; 19590 }, 19591 19592 /** 19593 * @method Stop the animation. 19594 */ 19595 stop: function() { 19596 clearTimeout(this.timer); 19597 }, 19598 19599 /** 19600 * @private 19601 * @method Call update on each circle and redraw them. 19602 * @returns this 19603 */ 19604 _update: function() { 19605 this._clear(); 19606 this.circles.forEach(function(circle, idx, array) { 19607 circle.update(); 19608 }); 19609 19610 return this; 19611 }, 19612 19613 /** 19614 * @private 19615 * @method Clear the canvas. 19616 * @returns this 19617 */ 19618 _clear: function() { 19619 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 19620 19621 return this; 19622 }, 19623 19624 }; 19625 19626 /** 19627 * @private 19628 * @class Individual progress circle. 19629 * @param params.canvas Canvas on which the circle will be drawn. 19630 * @param params.context Context of the canvas. 19631 * @param params.innerRadius Inner radius of the circle, in px. 19632 * @param params.arcWidth Width of each arc(circle). 19633 * @param params.gapWidth Distance between each arc. 19634 * @param params.centerX X coordinate of the center of circles. 19635 * @param params.centerY Y coordinate of the center of circles. 19636 * @param params.fillColor Color to fill in the circle. 19637 * @param params.outlineColor Color to outline the circle. 19638 * @param params.progressListener Callback function to fetch the progress. 19639 * @param params.infoListener Callback function to fetch the info. 19640 * @param params.infoLineAngle Angle of info line. 19641 */ 19642 var Circle = function(params) { 19643 this.id = params.id; 19644 this.canvas = params.canvas; 19645 this.context = params.context; 19646 this.centerX = params.centerX; 19647 this.centerY = params.centerY; 19648 this.arcWidth = params.arcWidth; 19649 this.innerRadius = params.innerRadius || 0; 19650 this.fillColor = params.fillColor || '#fff'; 19651 this.outlineColor = params.outlineColor || this.fillColor; 19652 this.progressListener = params.progressListener;
19653 this.infoLineLength = params.infoLineLength || 250; 19654 this.horizLineLength = params.horizLineLength || 50; 19655 this.infoListener = params.infoListener; 19656 this.infoLineAngle = params.infoLineAngle; 19657 19658 this.outerRadius = this.innerRadius + this.arcWidth; 19659 19660 // If the info listener is not registered, then don't calculate 19661 // the related coordinates 19662 if (!this.infoListener) return; 19663 19664 // calculate the info-line turning points 19665 var angle = this.infoLineAngle, 19666 arcDistance = (this.innerRadius + this.outerRadius) / 2, 19667 19668 sinA = Math.sin(angle), 19669 cosA = Math.cos(angle); 19670 19671 this.infoLineStartX = this.centerX + sinA * arcDistance; 19672 this.infoLineStartY = this.centerY - cosA * arcDistance; 19673 19674 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 19675 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 19676 19677 this.infoLineEndX = this.infoLineMidX + 19678 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 19679 this.infoLineEndY = this.infoLineMidY; 19680 19681 var infoText = document.createElement('div'), 19682 style = infoText.style; 19683 19684 style.color = this.fillColor; 19685 style.position = 'absolute'; 19686 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 19687 // style.top will be calculated in the `drawInfo` method. Since 19688 // user may want to change the size of the font, so the top offset 19689 // must be updated in each loop. 19690 infoText.className = 'ProgressCircleInfo'; // For css styling 19691 infoText.id = 'progress_circle_info_' + this.id; 19692 document.body.appendChild(infoText); 19693 this.infoText = infoText; 19694 }; 19695 19696 Circle.prototype = { 19697 constructor: Circle, 19698 19699 update: function() { 19700 this.progress = this.progressListener(); 19701 this._draw(); 19702 19703 if (this.infoListener) { 19704 this.info = this.infoListener(); 19705 this._drawInfo(); 19706 } 19707 }, 19708 19709 /** 19710 * @private 19711 * @method Draw the circle on the canvas. 19712 * @returns this 19713 */ 19714 _draw: function() { 19715 var ctx = this.context, 19716 19717 ANGLE_OFFSET = -Math.PI / 2, 19718 19719 startAngle = 0 + ANGLE_OFFSET, 19720 endAngle= startAngle + this.progress * Math.PI * 2, 19721 19722 x = this.centerX, 19723 y = this.centerY, 19724 19725 innerRadius = this.innerRadius - this.arcWidth - 1, 19726 outerRadius = this.outerRadius - this.arcWidth - 1; 19727 19728 if ( innerRadius < 0 ) 19729 return; 19730 19731 ctx.fillStyle = this.fillColor; 19732 ctx.strokeStyle = this.outlineColor; 19733 19734 ctx.beginPath(); 19735 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 19736 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 19737 ctx.closePath(); 19738 ctx.stroke(); 19739 ctx.fill(); 19740 19741 return this; 19742 }, 19743 19744 /** 19745 * @private 19746 * @method Draw the info lines and info text. 19747 * @returns this 19748 */ 19749 _drawInfo: function() { 19750 19751 var pointList, lineHeight; 19752 19753 pointList = [ 19754 [this.infoLineStartX, this.infoLineStartY], 19755 [this.infoLineMidX, this.infoLineMidY], 19756 [this.infoLineEndX, this.infoLineEndY], 19757 ]; 19758 this._drawSegments(pointList, false); 19759 19760 this.infoText.innerHTML = this.info; 19761 19762 lineHeight = this.infoText.offsetHeight; 19763 this.infoText.style.top = this.infoLineEndY + 19764 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 19765 19766 return this; 19767 }, 19768 19769 /** 19770 * @private 19771 * @method Helper function to draw the segments 19772 * @param pointList An array of points in the form of [x, y]. 19773 * @param close Whether to connect the first and last point. 19774 */ 19775 _drawSegments: function(pointList, close) { 19776 var ctx = this.context; 19777 19778 ctx.beginPath(); 19779 ctx.moveTo(pointList[0][0], pointList[0][1]); 19780 for (var i = 1; i < pointList.length; ++i) { 19781 ctx.lineTo(pointList[i][0], pointList[i][1]); 19782 } 19783 19784 if (close) { 19785 ctx.closePath(); 19786 } 19787 ctx.stroke(); 19788 }, 19789 }; 19790 19791 window.ProgressCircle = ProgressCircle; 19792 19793})(window, document); 19794 19795 19796 19797 19798/* ========================================================= 19799 * jquery.vc_chart.js v1.0 19800 * ========================================================= 19801 * Copyright 2013 Wpbakery 19802 * 19803 * Jquery chart plugin for the Visual Composer. 19804 * ========================================================= */ 19805(function($){ 19806 /** 19807 * Pie chart animated. 19808 * @param element - DOM element 19809 * @param options - settings object. 19810 * @constructor 19811 */ 19812 var VcChart = function(element, options) { 19813 this.el = element; 19814 this.$el = $(this.el); 19815 var $this = this; 19816 $this.options = $.extend({ 19817 color: 'wpb_button', 19818 units: '', 19819 width: '', 19820 label_selector: '.vc_pie_chart_value', 19821 back_selector: '.vc_pie_chart_back', 19822 responsive: true 19823 }, options); 19824 $this.init(); 19825 }; 19826 VcChart.prototype = { 19827 constructor: VcChart, 19828 _progress_v: 0, 19829 animated: false, 19830 colors: { 19831 'wpb_button': 'rgba(247, 247, 247, 1)', 19832 'btn-primary': 'rgba(0, 136, 204, 1)', 19833 'btn-info': 'rgba(88, 185, 218, 1)', 19834 'btn-success': 'rgba(106, 177, 101, 1)', 19835 'btn-warning': 'rgba(255, 153, 0, 1)', 19836 'btn-danger': 'rgba(255, 103, 91, 1)', 19837 'btn-inverse': 'rgba(85, 85, 85, 1)' 19838 }, 19839 init: function() { 19840 this.setupColor(); 19841 this.value = this.$el.data('pie-value')/100; 19842 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 19843 this.$wrapper = $('.vc_pie_wrapper', this.$el); 19844 this.$label = $(this.options.label_selector, this.$el); 19845 this.$back = $(this.options.back_selector, this.$el); 19846 this.$canvas = this.$el.find('canvas'); 19847 this.arcWidth = this.$el.data('pie-width') * 2; 19848 this.draw(); 19849 this.setWayPoint(); 19850 if(this.options.responsive === true) this.setResponsive(); 19851 if (UNCODE.isMobile) this._progress_v = this.value; 19852 }, 19853 setupColor: function() { 19854 // if(typeof this.colors[this.options.color] !== 'undefined') { 19855 // this.color = this.colors[this.options.color]; 19856 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 19857 // this.color = this.options.color; 19858 // } else { 19859 // this.color = 'rgba(247, 247, 247, 0.2)'; 19860 // } 19861 if(typeof this.options.color !== 'undefined') { 19862 this.color = this.options.color; 19863 } else this.color = 'rgba(247, 247, 247, 0.2)'; 19864 19865 }, 19866 setResponsive: function() { 19867 var that = this; 19868 if (!UNCODE.isMobile) { 19869 $(window).resize(function(){ 19870 if(that.animated === true) that.circle.stop(); 19871 that.draw(true); 19872 }); 19873 } 19874 }, 19875 draw: function(redraw) { 19876 var w = this.$el.addClass('vc_ready').width() * 2, 19877 border_w = this.arcWidth, 19878 radius; 19879 if(!w) w = this.$el.parents(':visible').first().width()-2; 19880 //w = Math.round(w/100*80); 19881 //if (w < 250) w = 250; 19882 radius = w/2; 19883 this.$wrapper.css({"width" : (w / 2) + "px"}); 19884 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 19885 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 19886 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 19887 this.$el.addClass('vc_ready'); 19888 this.circle = new ProgressCircle({ 19889 canvas: this.$canvas.get(0), 19890 minRadius: radius, 19891 arcWidth: border_w 19892 }); 19893 if(redraw === true && this.animated === true) { 19894 this._progress_v = this.value; 19895 this.circle.addEntry({ 19896 fillColor: this.color, 19897 progressListener: $.proxy(this.setProgress, this) 19898 }).start(); 19899 } 19900 }, 19901 setProgress: function() { 19902 if (this._progress_v >= this.value) { 19903 this.circle.stop(); 19904 this.animated = true; 19905 this.$label.html(this.label_value + this.options.units); 19906 return this._progress_v; 19907 } 19908 this._progress_v += 0.01; 19909 if (!isNaN(this.label_value)) { 19910 var label_value = this._progress_v/this.value*this.label_value; 19911 var val = Math.round(label_value) + this.options.units; 19912 this.$label.html(val); 19913 } else this.$label.html(this.label_value + this.options.units); 19914 return this._progress_v; 19915 }, 19916 animate: function() { 19917 if(this.animated !== true) { 19918 this.circle.addEntry({ 19919 fillColor: this.color, 19920 progressListener: $.proxy(this.setProgress, this) 19921 }).start(10); 19922 } 19923 }, 19924 setWayPoint: function() { 19925 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 19926 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 19927 } else { 19928 this.animate(); 19929 } 19930 } 19931 }; 19932 /** 19933 * jQuery plugin 19934 * @param option - object with settings 19935 * @return {*} 19936 */ 19937 $.fn.vcChat = function(option, value) { 19938 return this.each(function () { 19939 var $this = $(this), 19940 data = $this.data('vc_chart'), 19941 options = typeof option === 'object' ? option : { 19942 color: $this.data('pie-color'), 19943 units: $this.data('pie-units') 19944 }; 19945 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 19946 if (typeof option == 'string') data[option](value); 19947 }); 19948 }; 19949 /** 19950 * Allows users to rewrite function inside theme. 19951 */ 19952 if ( typeof window['vc_pieChart'] !== 'function' ) { 19953 window.vc_pieChart = function() { 19954 $('.vc_pie_chart:visible:not(.vc_ready)').vcChat(); 19955 } 19956 } 19957 $(document).ready(function(){ 19958 !window.vc_iframe && vc_pieChart(); 19959 19960 /** 19961 * Tab and collapse integration. 19962 */ 19963 $('.nav-tabs a').on('shown.bs.tab', function(e){ 19964 var $cont = $(e.target).closest('.tab-container'), 19965 $active = $('.tab-pane.active', $cont); 19966 $('.vc_pie_chart:not(.vc_ready)', $active).vcChat(); 19967 }); 19968 19969 $('.panel-collapse').on('shown.bs.collapse', function (e) { 19970 $('.vc_pie_chart:not(.vc_ready)', e.target).vcChat(); 19971 }) 19972 }); 19973 19974})(window.jQuery); 19975 19976/* Progress bar 19977 ---------------------------------------------------------- */ 19978function uncode_progress_bar() { 19979 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 19980 if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) { 19981 return; 19982 } 19983 if (!UNCODE.isMobile) { 19984 new Waypoint({ 19985 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 19986 element: val, 19987 handler: function() { 19988 var element = jQuery(this.element); 19989 element.find('.vc_single_bar').each(function(index) { 19990 var $this = jQuery(this), 19991 bar = $this.find('.vc_bar'), 19992 val = bar.data('percentage-value'); 19993 setTimeout(function() { 19994 bar.css({ 19995 "width": val + '%' 19996 }); 19997 }, index * 200); 19998 }); 19999 }, 20000 offset: '80%' 20001 }); 20002 } else { 20003 var element = jQuery(val); 20004 element.find('.vc_single_bar').each(function(index) { 20005 var $this = jQuery(this), 20006 bar = $this.find('.vc_bar'), 20007 val = bar.data('percentage-value'); 20008 setTimeout(function() { 20009 bar.css({ 20010 "width": val + '%' 20011 }); 20012 }, index * 200); 20013 }); 20014 } 20015 }); 20016}; 20017uncode_progress_bar(); 20018 20019/*! 20020 * jquery.counterup.js 1.0 20021 * 20022 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 20023 * Released under the GPL v2 License 20024 * 20025 * Date: Nov 26, 2013 20026 */ 20027(function($) { 20028 "use strict"; 20029 $.fn.counterUp = function(options) { 20030 // Defaults 20031 var settings = $.extend({ 20032 'time': 400, 20033 'delay': 10 20034 }, options); 20035 return this.each(function() { 20036 // Store the object 20037 var $this = $(this); 20038 var $settings = settings; 20039 var counterUpper = function() { 20040 var nums = []; 20041 var divisions = $settings.time / $settings.delay; 20042 var numReal = $this.attr('data-val'), 20043 num = numReal; 20044 var isComma = /[0-9]+,[0-9]+/.test(num); 20045 num = num.replace(/,/g, ''); 20046 var isInt = /^[0-9]+$/.test(num); 20047 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 20048 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 20049 // Generate list of incremental numbers to display 20050 for (var i = divisions; i >= 1; i--) { 20051 // Preserve as int if input was int 20052 var newNum = parseInt(num / divisions * i); 20053 // Preserve float if input was float 20054 if (isFloat) { 20055 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 20056 } 20057 // Preserve commas if input had commas 20058 if (isComma) { 20059 while (/(\d+)(\d{3})/.test(newNum.toString())) { 20060 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 20061 } 20062 } 20063 nums.unshift(newNum); 20064 } 20065 nums.push(numReal); 20066 $this.data('counterup-nums', nums); 20067 $this.text('0'); 20068 // Updates the number until we're done 20069 var f = function() { 20070 if ($this.data('counterup-nums') != null) { 20071 $this.text($this.data('counterup-nums').shift()); 20072 if ($this.data('counterup-nums').length) { 20073 setTimeout($this.data('counterup-func'), $settings.delay); 20074 } else { 20075 delete $this.data('counterup-nums'); 20076 $this.data('counterup-nums', null); 20077 $this.data('counterup-func', null); 20078 } 20079 } 20080 }; 20081 $this.data('counterup-func', f); 20082 // Start the count up 20083 setTimeout($this.data('counterup-func'), $settings.delay); 20084 }; 20085 // Perform counts when the element gets into view 20086 new Waypoint({ 20087 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 20088 element: this, 20089 handler: function() { 20090 counterUpper(); 20091 if (!UNCODE.isUnmodalOpen) { 20092 this.destroy(); 20093 } 20094 }, 20095 offset: '100%' 20096 }); 20097 }); 20098 }; 20099})(jQuery); 20100 20101/*! 20102 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/) 20103 * Copyright (c) 2016 Edson Hilios 20104 * 20105 * Permission is hereby granted, free of charge, to any person obtaining a copy of 20106 * this software and associated documentation files (the "Software"), to deal in 20107 * the Software without restriction, including without limitation the rights to 20108 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 20109 * the Software, and to permit persons to whom the Software is furnished to do so, 20110 * subject to the following conditions: 20111 * 20112 * The above copyright notice and this permission notice shall be included in all 20113 * copies or substantial portions of the Software. 20114 * 20115 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20116 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 20117 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20118 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20119 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20120 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20121 */ 20122(function(factory) { 20123 "use strict"; 20124 if (typeof define === "function" && define.amd) { 20125 define([ "jquery" ], factory); 20126 } else { 20127 factory(jQuery); 20128 } 20129})(function($) { 20130 "use strict"; 20131 var instances = [], matchers = [], defaultOptions = { 20132 precision: 100, 20133 elapse: false, 20134 defer: false 20135 }; 20136 matchers.push(/^[0-9]*$/.source); 20137 matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 20138 matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 20139 matchers = new RegExp(matchers.join("|")); 20140 function parseDateString(dateString) { 20141 if (dateString instanceof Date) { 20142 return dateString; 20143 } 20144 if (String(dateString).match(matchers)) { 20145 if (String(dateString).match(/^[0-9]*$/)) { 20146 dateString = Number(dateString); 20147 } 20148 if (String(dateString).match(/\-/)) { 20149 dateString = String(dateString).replace(/\-/g, "/"); 20150 } 20151 return new Date(dateString); 20152 } else { 20153 throw new Error("Couldn't cast `" + dateString + "` to a date object."); 20154 } 20155 } 20156 var DIRECTIVE_KEY_MAP = { 20157 Y: "years", 20158 m: "months", 20159 n: "daysToMonth", 20160 d: "daysToWeek", 20161 w: "weeks", 20162 W: "weeksToMonth", 20163 H: "hours", 20164 M: "minutes", 20165 S: "seconds", 20166 D: "totalDays", 20167 I: "totalHours", 20168 N: "totalMinutes", 20169 T: "totalSeconds" 20170 }; 20171 function escapedRegExp(str) { 20172 var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); 20173 return new RegExp(sanitize); 20174 } 20175 function strftime(offsetObject) { 20176 return function(format) { 20177 var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi); 20178 if (directives) { 20179 for (var i = 0, len = directives.length; i < len; ++i) { 20180 var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null; 20181 directive = directive[2]; 20182 if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) { 20183 value = DIRECTIVE_KEY_MAP[directive]; 20184 value = Number(offsetObject[value]); 20185 } 20186 if (value !== null) { 20187 if (modifier === "!") { 20188 value = pluralize(plural, value); 20189 } 20190 if (modifier === "") { 20191 if (value < 10) { 20192 value = "0" + value.toString(); 20193 } 20194 } 20195 format = format.replace(regexp, value.toString()); 20196 } 20197 } 20198 } 20199 format = format.replace(/%%/, "%"); 20200 return format; 20201 }; 20202 } 20203 function pluralize(format, count) { 20204 var plural = "s", singular = ""; 20205 if (format) { 20206 format = format.rep
vendor: 8,618 bytes, lines 20206-20350
20206lace(/(:|;|\s)/gi, "").split(/\,/); 20207 if (format.length === 1) { 20208 plural = format[0]; 20209 } else { 20210 singular = format[0]; 20211 plural = format[1]; 20212 } 20213 } 20214 if (Math.abs(count) > 1) { 20215 return plural; 20216 } else { 20217 return singular; 20218 } 20219 } 20220 var Countdown = function(el, finalDate, options) { 20221 this.el = el; 20222 this.$el = $(el); 20223 this.interval = null; 20224 this.offset = {}; 20225 this.options = $.extend({}, defaultOptions); 20226 this.instanceNumber = instances.length; 20227 instances.push(this); 20228 this.$el.data("countdown-instance", this.instanceNumber); 20229 if (options) { 20230 if (typeof options === "function") { 20231 this.$el.on("update.countdown", options); 20232 this.$el.on("stoped.countdown", options); 20233 this.$el.on("finish.countdown", options); 20234 } else { 20235 this.options = $.extend({}, defaultOptions, options); 20236 } 20237 } 20238 this.setFinalDate(finalDate); 20239 if (this.options.defer === false) { 20240 this.start(); 20241 } 20242 }; 20243 $.extend(Countdown.prototype, { 20244 start: function() { 20245 if (this.interval !== null) { 20246 clearInterval(this.interval); 20247 } 20248 var self = this; 20249 this.update(); 20250 this.interval = setInterval(function() { 20251 self.update.call(self); 20252 }, this.options.precision); 20253 }, 20254 stop: function() { 20255 clearInterval(this.interval); 20256 this.interval = null; 20257 this.dispatchEvent("stoped"); 20258 }, 20259 toggle: function() { 20260 if (this.interval) { 20261 this.stop(); 20262 } else { 20263 this.start(); 20264 } 20265 }, 20266 pause: function() { 20267 this.stop(); 20268 }, 20269 resume: function() { 20270 this.start(); 20271 }, 20272 remove: function() { 20273 this.stop.call(this); 20274 instances[this.instanceNumber] = null; 20275 delete this.$el.data().countdownInstance; 20276 }, 20277 setFinalDate: function(value) { 20278 this.finalDate = parseDateString(value); 20279 }, 20280 update: function() { 20281 if (this.$el.closest("html").length === 0) { 20282 this.remove(); 20283 return; 20284 } 20285 var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft; 20286 newTotalSecsLeft = this.finalDate.getTime() - now.getTime(); 20287 newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3); 20288 newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft); 20289 if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) { 20290 return; 20291 } else { 20292 this.totalSecsLeft = newTotalSecsLeft; 20293 } 20294 this.elapsed = now >= this.finalDate; 20295 this.offset = { 20296 seconds: this.totalSecsLeft % 60, 20297 minutes: Math.floor(this.totalSecsLeft / 60) % 60, 20298 hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24, 20299 days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 20300 daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 20301 daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368), 20302 weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7), 20303 weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4, 20304 months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368), 20305 years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()), 20306 totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24), 20307 totalHours: Math.floor(this.totalSecsLeft / 60 / 60), 20308 totalMinutes: Math.floor(this.totalSecsLeft / 60), 20309 totalSeconds: this.totalSecsLeft 20310 }; 20311 if (!this.options.elapse && this.totalSecsLeft === 0) { 20312 this.stop(); 20313 this.dispatchEvent("finish"); 20314 } else { 20315 this.dispatchEvent("update"); 20316 } 20317 }, 20318 dispatchEvent: function(eventName) { 20319 var event = $.Event(eventName + ".countdown"); 20320 event.finalDate = this.finalDate; 20321 event.elapsed = this.elapsed; 20322 event.offset = $.extend({}, this.offset); 20323 event.strftime = strftime(this.offset); 20324 this.$el.trigger(event); 20325 } 20326 }); 20327 $.fn.countdown = function() { 20328 var argumentsArray = Array.prototype.slice.call(arguments, 0); 20329 return this.each(function() { 20330 var instanceNumber = $(this).data("countdown-instance"); 20331 if (instanceNumber !== undefined) { 20332 var instance = instances[instanceNumber], method = argumentsArray[0]; 20333 if (Countdown.prototype.hasOwnProperty(method)) { 20334 instance[method].apply(instance, argumentsArray.slice(1)); 20335 } else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) { 20336 instance.setFinalDate.call(instance, method); 20337 instance.start(); 20338 } else { 20339 $.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method)); 20340 } 20341 } else { 20342 new Countdown(this, argumentsArray[0], argumentsArray[1]); 20343 } 20344 }); 20345 }; 20346}); 20347 20348!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; 20349function getStyles(config){ 20350 // 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;
20350left: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+"}" 20351}; 20352 var ShareUtils; 20353 20354if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 20355 Object.defineProperty(HTMLElement.prototype, "classList", { 20356 get: function() { 20357 var ret, self, update; 20358 update = function(fn) { 20359 return function(value) { 20360 var classes, index; 20361 classes = self.className.split(/\s+/); 20362 index = classes.indexOf(value); 20363 fn(classes, index, value); 20364 self.className = classes.join(" "); 20365 }; 20366 }; 20367 self = this; 20368 ret = { 20369 add: update(function(classes, index, value) { 20370 ~index || classes.push(value); 20371 }), 20372 remove: update(function(classes, index) { 20373 ~index && classes.splice(index, 1); 20374 }), 20375 toggle: update(function(classes, index, value) { 20376 if (~index) { 20377 classes.splice(index, 1); 20378 } else { 20379 classes.push(value); 20380 } 20381 }), 20382 contains: function(value) { 20383 return !!~self.className.split(/\s+/).indexOf(value); 20384 }, 20385 item: function(i) { 20386 return self.className.split(/\s+/)[i] || null; 20387 } 20388 }; 20389 Object.defineProperty(ret, "length", { 20390 get: function() { 20391 return self.className.split(/\s+/).length; 20392 } 20393 }); 20394 return ret; 20395 } 20396 }); 20397} 20398 20399String.prototype.to_rfc3986 = function() { 20400 var tmp; 20401 tmp = encodeURIComponent(this); 20402 return tmp.replace(/[!'()*]/g, function(c) { 20403 return "%" + c.charCodeAt(0).toString(16); 20404 }); 20405}; 20406 20407ShareUtils = (function() { 20408 function ShareUtils() {} 20409 20410 ShareUtils.prototype.extend = function(to, from, overwrite) { 20411 var hasProp, prop; 20412 for (prop in from) { 20413 hasProp = to[prop] !== undefined; 20414 if (hasProp && typeof from[prop] === "object") { 20415 this.extend(to[prop], from[prop], overwrite); 20416 } else { 20417 if (overwrite || !hasProp) { 20418 to[prop] = from[prop]; 20419 } 20420 } 20421 } 20422 }; 20423 20424 ShareUtils.prototype.hide = function(el) { 20425 return el.style.display = "none"; 20426 }; 20427 20428 ShareUtils.prototype.show = function(el) { 20429 return el.style.display = "block"; 20430 }; 20431 20432 ShareUtils.prototype.has_class = function(el, class_name) { 20433 return el.classList.contains(class_name); 20434 }; 20435 20436 ShareUtils.prototype.add_class = function(el, class_name) { 20437 return el.classList.add(class_name); 20438 }; 20439 20440 ShareUtils.prototype.remove_class = function(el, class_name) { 20441 return el.classList.remove(class_name); 20442 }; 20443 20444 ShareUtils.prototype.is_encoded = function(str) { 20445 str = str.to_rfc3986(); 20446 return decodeURIComponent(str) !== str; 20447 }; 20448 20449 ShareUtils.prototype.encode = function(str) { 20450 if (typeof str === "undefined" || this.is_encoded(str)) { 20451 return str; 20452 } else { 20453 return str.to_rfc3986(); 20454 } 20455 }; 20456 20457 ShareUtils.prototype.popup = function(url, params) { 20458 var k, popup, qs, v; 20459 if (params == null) { 20460 params = {}; 20461 } 20462 popup = { 20463 width: 500, 20464 height: 350 20465 }; 20466 popup.top = (screen.height / 2) - (popup.height / 2); 20467 popup.left = (screen.width / 2) - (popup.width / 2); 20468 qs = ((function() { 20469 var _results; 20470 _results = []; 20471 for (k in params) { 20472 v = params[k]; 20473 _results.push("" + k + "=" + (this.encode(v))); 20474 } 20475 return _results; 20476 }).call(this)).join('&'); 20477 if (qs) { 20478 qs = "?" + qs; 20479 } 20480 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="
20480+ popup.width + ",height=" + popup.height); 20481 }; 20482 20483 return ShareUtils; 20484 20485})(); 20486var Share, 20487 __hasProp = {}.hasOwnProperty, 20488 __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; }; 20489 20490Share = (function(_super) { 20491 __extends(Share, _super); 20492 20493 function Share(element, options) { 20494 this.element = element; 20495 this.el = { 20496 head: document.getElementsByTagName('head')[0], 20497 body: document.getElementsByTagName('body')[0] 20498 }; 20499 this.config = { 20500 enabled_networks: 0, 20501 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 20502 url: window.location.href.replace("&", "%26"), 20503 caption: null, 20504 title: this.default_title(), 20505 image: this.default_image(), 20506 description: this.default_description(), 20507 ui: { 20508 flyout: 'top center', 20509 button_text: 'Share', 20510 button_font: true, 20511 icon_font: true 20512 }, 20513 networks: { 20514 twitter: { 20515 enabled: true, 20516 url: null, 20517 title: null, 20518 description: null 20519 }, 20520 facebook: { 20521 enabled: true, 20522 load_sdk: true, 20523 url: null, 20524 app_id: null, 20525 title: null, 20526 caption: null, 20527 description: null, 20528 image: null 20529 }, 20530 pinterest: { 20531 enabled: true, 20532 url: null, 20533 image: null, 20534 description: null 20535 }, 20536 reddit: { 20537 enabled: true, 20538 url: null, 20539 title: null 20540 }, 20541 linkedin: { 20542 enabled: true, 20543 url: null, 20544 title: null, 20545 description: null 20546 }, 20547 xing: { 20548 enabled: true, 20549 url: null, 20550 title: null, 20551 image: null, 20552 description: null 20553 }, 20554 whatsapp: { 20555 enabled: true, 20556 description: null, 20557 url: null 20558 }, 20559 email: { 20560 enabled: true, 20561 title: null, 20562 description: null, 20563 url: null 20564 } 20565 } 20566 }; 20567 this.setup(element, options); 20568 return this; 20569 } 20570 20571 Share.prototype.setup = function(element, opts) { 20572 var index, instance, instances, _i, _len; 20573 instances = document.querySelectorAll(element); 20574 this.extend(this.config, opts, true); 20575 this.set_global_configuration(); 20576 this.normalize_network_configuration(); 20577 if (this.config.ui.icon_font) { 20578 this.inject_icons(); 20579 } 20580 if (this.config.ui.button_font) { 20581 this.inject_fonts(); 20582 } 20583 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 20584 this.inject_facebook_sdk(); 20585 } 20586 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 20587 instance = instances[index]; 20588 this.setup_instance(element, index); 20589 } 20590 }; 20591 20592 Share.prototype.setup_instance = function(element, index) { 20593 var button, instance, label, network, networks, _i, _len, _results, 20594 _this = this; 20595 instance = document.querySelectorAll(element)[index]; 20596 this.hide(instance); 20597 this.add_class(instance, "sharer-" + index); 20598 instance = document.querySelectorAll(element)[index]; 20599 this.inject_css(instance); 20600 this.inject_html(instance); 20601 this.show(instance); 20602 label = instance.getElementsByTagName("label")[0]; 20603 button = instance.getElementsByClassName("social")[0]; 20604 networks = instance.getElementsByTagName('li'); 20605 this.add_class(button, "networks-" + this.config.enabled_networks); 20606 label.addEventListener("click", function() { 20607 return _this.event_toggle(button); 20608 }); 20609 _this = this; 20610 _results = []; 20611 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 20612 network = networks[index]; 20613 _results.push(network.addEventListener("click", function() { 20614 _this.event_network(instance, this); 20615 return _this.event_close(button); 20616 })); 20617 } 20618 return _results; 20619 }; 20620 20621 Share.prototype.event_toggle = function(button) { 20622 if (this.has_class(button, "active")) { 20623 return this.event_close(button); 20624 } else { 20625 return this.event_open(button); 20626 } 20627 }; 20628 20629 Share.prototype.event_open = function(button) { 20630 if (this.has_class(button, "load")) { 20631 this.remove_class(button, "load"); 20632 } 20633 return this.add_class(button, "active"); 20634 }; 20635 20636 Share.prototype.event_close = function(button) { 20637 return this.remove_class(button, "active"); 20638 }; 20639 20640 Share.prototype.event_network = function(instance, network) { 20641 var name; 20642 name = network.getAttribute("data-network"); 20643 this.hook("before", name, instance);
20644 this["network_" + name](); 20645 return this.hook("after", name, instance); 20646 }; 20647 20648 Share.prototype.open = function() { 20649 return this["public"]("open"); 20650 }; 20651 20652 Share.prototype.close = function() { 20653 return this["public"]("close"); 20654 }; 20655 20656 Share.prototype.toggle = function() { 20657 return this["public"]("toggle"); 20658 }; 20659 20660 Share.prototype["public"] = function(action) { 20661 var button, index, instance, _i, _len, _ref, _results; 20662 _ref = document.querySelectorAll(this.element); 20663 _results = []; 20664 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 20665 instance = _ref[index]; 20666 button = instance.getElementsByClassName("social")[0]; 20667 _results.push(this["event_" + action](button)); 20668 } 20669 return _results; 20670 }; 20671 20672 Share.prototype.network_facebook = function() { 20673 if (this.config.networks.facebook.load_sdk) { 20674 if (!window.FB) { 20675 return console.error("The Facebook JS SDK hasn't loaded yet."); 20676 } 20677 return FB.ui({ 20678 method: 'feed', 20679 name: this.config.networks.facebook.title, 20680 link: this.config.networks.facebook.url, 20681 picture: this.config.networks.facebook.image, 20682 caption: this.config.networks.facebook.caption, 20683 description: this.config.networks.facebook.description 20684 }); 20685 } else { 20686 return this.popup('https://www.facebook.com/sharer/sharer.php', { 20687 u: this.config.networks.facebook.url 20688 }); 20689 } 20690 }; 20691 20692 Share.prototype.network_twitter = function() { 20693 return this.popup('https://twitter.com/intent/tweet', { 20694 text: this.config.networks.twitter.title, 20695 url: this.config.networks.twitter.url 20696 }); 20697 }; 20698 20699 Share.prototype.network_pinterest = function() { 20700 return this.popup('https://www.pinterest.com/pin/create/button', { 20701 url: this.config.networks.pinterest.url, 20702 media: this.config.networks.pinterest.image, 20703 description: this.config.networks.pinterest.description 20704 }); 20705 }; 20706 20707 Share.prototype.network_linkedin = function() { 20708 return this.popup('https://www.linkedin.com/shareArticle', { 20709 url: this.config.networks.linkedin.url, 20710 title: this.config.networks.linkedin.title, 20711 summary: this.config.networks.linkedin.description 20712 }); 20713 } 20714 20715 Share.prototype.network_xing = function() { 20716 return this.popup('https://www.xing.com/spi/shares/new', { 20717 url: this.config.networks.xing.url, 20718 image: this.config.networks.xing.image, 20719 title: this.config.networks.xing.title, 20720 summary: this.config.networks.xing.description 20721 }); 20722 } 20723 20724 Share.prototype.network_email = function() { 20725 return this.popup('mailto:', { 20726 subject: this.config.networks.email.title, 20727 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 20728 }); 20729 }; 20730 20731 Share.prototype.inject_icons = function() { 20732 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 20733 }; 20734 20735 Share.prototype.inject_fonts = function() { 20736 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 20737 }; 20738 20739 Share.prototype.inject_stylesheet = function(url) { 20740 var link; 20741 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 20742 link = document.createElement("link"); 20743 link.setAttribute("rel", "stylesheet"); 20744 link.setAttribute("href", url); 20745 return this.el.head.appendChild(link); 20746 } 20747 }; 20748 20749 Share.prototype.inject_css = function(instance) { 20750 var css, meta, selector, style; 20751 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 20752 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 20753 this.config.selector = selector; 20754 css = getStyles(this.config); 20755 style = document.createElement("style"); 20756 style.type = "text/css"; 20757 if (style.styleSheet) { 20758 style.styleSheet.cssText = css; 20759 } else { 20760 style.appendChild(document.createTextNode(css)); 20761 } 20762 this.el.head.appendChild(style); 20763 delete this.config.selector; 20764 meta = document.createElement("meta"); 20765 meta.setAttribute("name", "sharer" + selector); 20766 return this.el.head.appendChild(meta); 20767 } 20768 }; 20769 20770 Share.prototype.inject_html = function(instance) { 20771 //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>"; 20772 return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>"; 20773 }; 20774 20775 Share.prototype.inject_facebook_sdk = function() { 20776 var fb_root, script; 20777 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 20778 script = document.createElement("script"); 20779 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')"; 20780 fb_root = document.createElement("div"); 20781 fb_root.id = "fb-root"; 20782 this.el.body.appendChild(fb_root); 20783 return this.el.body.appendChild(script); 20784 } 20785 }; 20786 20787 Share.prototype.hook = function(type, network, instance) { 20788 var fn, opts; 20789 fn = this.config.networks[network][type]; 20790 if (typeof fn === "function") { 20791 opts = fn.call(this.config.networks[network], instance); 20792 if (opts !== void 0) { 20793 opts = this.normalize_filter_config_updates(opts); 20794 this.extend(this.config.networks[network], opts, true); 20795 this.normalize_network_configuration(); 20796 } 20797 } 20798 }; 20799 20800 Share.prototype.default_title = function() { 20801 var content; 20802 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 20803 return encodeURIComponent(content.getAttribute('content')); 20804 } else if (content = document.querySelector('title')) { 20805 return encodeURIComponent(content.innerText); 20806 } 20807 }; 20808 20809 Share.prototype.default_image = function() { 20810 var content; 20811 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 20812 return content.getAttribute('content'); 20813 } 20814 }; 20815 20816 Share.prototype.default_description = function() { 20817 var content; 20818 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 20819 return encodeURIComponent(content.getAttribute('content')); 20820 } else { 20821 return ''; 20822 } 20823 }; 20824 20825 Share.prototype.set_global_configuration = function() { 20826 var display, network, option, options, _ref, _results; 20827 _ref = this.config.networks; 20828 _results = []; 20829 for (network in _ref) { 20830 options = _ref[network]; 20831 for (option in options) { 20832 if (this.config.networks[network][option] == null) { 20833 this.config.networks[network][option] = this.config[option]; 20834 } 20835 } 20836 if (this.config.networks[network].enabled) { 20837 display = 'block'; 20838 this.config.enabled_networks += 1; 20839 } else { 20840 display = 'none'; 20841 } 20842 _results.push(this.config.networks[network].display = display); 20843 } 20844 return _results; 20845 }; 20846 20847 Share.prototype.normalize_network_configuration = function() { 20848 if (!this.config.networks.facebook.app_id) { 20849 this.config.networks.facebook.load_sdk = false;
20850 } 20851 if (!this.is_encoded(this.config.networks.twitter.description)) { 20852 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 20853 } 20854 if (typeof this.config.networks.facebook.app_id === 'number') { 20855 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 20856 } 20857 }; 20858 20859 Share.prototype.normalize_filter_config_updates = function(opts) { 20860 if (this.config.networks.facebook.app_id !== opts.app_id) { 20861 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."); 20862 delete opts.app_id; 20863 } 20864 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 20865 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."); 20866 delete opts.app_id; 20867 } 20868 return opts; 20869 }; 20870 20871 return Share; 20872 20873})(ShareUtils); 20874 return Share; 20875}); 20876 20877// Generated by CoffeeScript 1.9.2 20878 20879// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 20880 20881(function() { 20882 var $, win; 20883 20884 $ = this.jQuery || window.jQuery; 20885 20886 win = $(window); 20887 20888 $.fn.stick_in_parent = function(opts) { 20889 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 20890 if (opts == null) { 20891 opts = {}; 20892 } 20893 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; 20894 if (offset_top == null) { 20895 offset_top = 0; 20896 } 20897 if (parent_selector == null) { 20898 parent_selector = void 0; 20899 } 20900 if (inner_scrolling == null) { 20901 inner_scrolling = true; 20902 } 20903 if (sticky_class == null) { 20904 sticky_class = "is_stuck"; 20905 } 20906 doc = $(document); 20907 if (enable_bottoming == null) { 20908 enable_bottoming = true; 20909 } 20910 outer_width = function(el) { 20911 var _el, computed, w; 20912 if (window.getComputedStyle) { 20913 _el = el[0]; 20914 computed = window.getComputedStyle(el[0]); 20915 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 20916 if (computed.getPropertyValue("box-sizing") !== "border-box") { 20917 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 20918 } 20919 return w; 20920 } else { 20921 return el.outerWidth(true); 20922 } 20923 }; 20924 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 20925 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 20926 if (elm.data("sticky_kit")) { 20927 return; 20928 } 20929 elm.data("sticky_kit", true); 20930 last_scroll_height = doc.height(); 20931 parent = elm.parent(); 20932 if (parent_selector != null) { 20933 parent = parent.closest(parent_selector); 20934 } 20935 if (!parent.length) { 20936 throw "failed to find stick parent"; 20937 } 20938 fixed = false; 20939 bottomed = false; 20940 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 20941 if (spacer) { 20942 spacer.css('position', elm.css('position')); 20943 } 20944 recalc = function() { 20945 var border_top, padding_top, restore; 20946 if (detached) { 20947 return; 20948 } 20949 last_scroll_height = doc.height(); 20950 border_top = parseInt(parent.css("border-top-width"), 10); 20951 padding_top = parseInt(parent.css("padding-top"), 10); 20952 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 20953 parent_top = parent.offset().top + border_top + padding_top; 20954 parent_height = parent.height(); 20955 if (fixed) { 20956 fixed = false;
vendor: 6,068 bytes, lines 20957-21151
20957 bottomed = false; 20958 if (manual_spacer == null) { 20959 elm.insertAfter(spacer); 20960 spacer.detach(); 20961 } 20962 elm.css({ 20963 position: "", 20964 top: "", 20965 width: "", 20966 bottom: "" 20967 }).removeClass(sticky_class); 20968 restore = true; 20969 } 20970 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 20971 height = elm.outerHeight(true); 20972 el_float = elm.css("float"); 20973 if (spacer) { 20974 spacer.css({ 20975 width: outer_width(elm), 20976 height: height, 20977 display: elm.css("display"), 20978 "vertical-align": elm.css("vertical-align"), 20979 "float": el_float 20980 }); 20981 } 20982 if (restore) { 20983 return tick(); 20984 } 20985 }; 20986 recalc(); 20987 if (height === parent_height) { 20988 return; 20989 } 20990 last_pos = void 0; 20991 offset = offset_top; 20992 recalc_counter = recalc_every; 20993 tick = function() { 20994 var css, delta, recalced, scroll, will_bottom, win_height; 20995 if (detached) { 20996 return; 20997 } 20998 recalced = false; 20999 if (recalc_counter != null) { 21000 recalc_counter -= 1; 21001 if (recalc_counter <= 0) { 21002 recalc_counter = recalc_every; 21003 recalc(); 21004 recalced = true; 21005 } 21006 } 21007 if (!recalced && doc.height() !== last_scroll_height) { 21008 recalc(); 21009 recalced = true; 21010 } 21011 scroll = win.scrollTop(); 21012 if (last_pos != null) { 21013 delta = scroll - last_pos; 21014 } 21015 last_pos = scroll; 21016 if (fixed) { 21017 if (enable_bottoming) { 21018 will_bottom = scroll + height + offset > parent_height + parent_top; 21019 if (bottomed && !will_bottom) { 21020 bottomed = false; 21021 elm.css({ 21022 position: "fixed", 21023 bottom: "", 21024 top: offset 21025 }).trigger("sticky_kit:unbottom"); 21026 } 21027 } 21028 if (scroll < top) { 21029 fixed = false; 21030 offset = offset_top; 21031 if (manual_spacer == null) { 21032 if (el_float === "left" || el_float === "right") { 21033 elm.insertAfter(spacer); 21034 } 21035 spacer.detach(); 21036 } 21037 css = { 21038 position: "", 21039 width: "", 21040 top: "" 21041 }; 21042 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 21043 } 21044 if (inner_scrolling) { 21045 win_height = win.height(); 21046 if (height + offset_top > win_height) { 21047 if (!bottomed) { 21048 offset -= delta; 21049 offset = Math.max(win_height - height, offset); 21050 offset = Math.min(offset_top, offset); 21051 if (fixed) { 21052 elm.css({ 21053 top: offset + "px" 21054 }); 21055 } 21056 } 21057 } 21058 } 21059 } else { 21060 if (scroll > top) { 21061 fixed = true; 21062 css = { 21063 position: "fixed", 21064 top: offset 21065 }; 21066 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 21067 elm.css(css).addClass(sticky_class); 21068 if (manual_spacer == null) { 21069 elm.after(spacer); 21070 if (el_float === "left" || el_float === "right") { 21071 spacer.append(elm); 21072 } 21073 } 21074 elm.trigger("sticky_kit:stick"); 21075 } 21076 } 21077 if (fixed && enable_bottoming) { 21078 if (will_bottom == null) { 21079 will_bottom = scroll + height + offset > parent_height + parent_top; 21080 } 21081 if (!bottomed && will_bottom) { 21082 bottomed = true; 21083 if (parent.css("position") === "static") { 21084 parent.css({ 21085 position: "relative" 21086 }); 21087 } 21088 return elm.css({ 21089 position: "absolute", 21090 bottom: padding_bottom, 21091 top: "auto" 21092 }).trigger("sticky_kit:bottom"); 21093 } 21094 } 21095 }; 21096 recalc_and_tick = function() { 21097 recalc(); 21098 return tick(); 21099 }; 21100 detach = function() { 21101 detached = true; 21102 win.off("touchmove", tick); 21103 win.off("scroll", tick); 21104 win.off("resize", recalc_and_tick); 21105 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 21106 elm.off("sticky_kit:detach", detach); 21107 elm.removeData("sticky_kit"); 21108 elm.css({ 21109 position: "", 21110 bottom: "", 21111 top: "", 21112 width: "" 21113 }); 21114 parent.position("position", ""); 21115 if (fixed) { 21116 if (manual_spacer == null) { 21117 if (el_float === "left" || el_float === "right") { 21118 elm.insertAfter(spacer); 21119 } 21120 spacer.remove(); 21121 } 21122 return elm.removeClass(sticky_class); 21123 } 21124 }; 21125 win.on("touchmove", tick); 21126 win.on("scroll", tick); 21127 win.on("resize", recalc_and_tick); 21128 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 21129 elm.on("sticky_kit:detach", detach); 21130 return setTimeout(tick, 0); 21131 }; 21132 for (i = 0, len = this.length; i < len; i++) { 21133 elm = this[i]; 21134 fn($(elm)); 21135 } 21136 return this; 21137 }; 21138 21139}).call(this); 21140/* ========================================================================== 21141 * bootstrap-tab-history.js 21142 * Author: Michael Narayan <[email protected]> 21143 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 21144 * ========================================================================== 21145 * Licensed under the Apache License, Version 2.0 (the "License"); you may 21146 * not use this file except in compliance with the License. You may obtain a 21147 * copy of the License at 21148 * 21149 * http://www.apache.org/licenses/LICENSE-2.0 21150 * 21151 * Unless required by applicable law or agreed to in writing, softw
21151are 21152 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 21153 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 21154 * License for the specific language governing permissions and limitations 21155 * under the License. 21156 * ========================================================================== */ 21157 21158/* ========================================================================== */ 21159/* JSHint directives */ 21160/* */ 21161/* global BootstrapTabHistory: true */ 21162/* */ 21163/* global document */ 21164/* global jQuery */ 21165/* global history */ 21166/* global window */ 21167/* ========================================================================== */ 21168 21169/** 21170 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 21171 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 21172 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 21173 * 21174 * See the README for additional information. 21175 * 21176 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 21177 */ 21178 21179BootstrapTabHistory = { 21180 options: { 21181 /** 21182 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 21183 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 21184 * 21185 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 21186 * 21187 * @public 21188 * @type {?number} 21189 */ 21190 defaultAnchorYOffset: 0, 21191 /** 21192 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 21193 * 21194 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 21195 * 21196 * @public 21197 * @type {string} 21198 */ 21199 defaultChanger: 'replace', 21200 /** 21201 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 21202 * `null` is passed as the third parameter to these calls. 21203 * 21204 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 21205 * 21206 * @public 21207 * @type {boolean} 21208 */ 21209 defaultUpdateURL: false, 21210 /** 21211 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 21212 * load. 21213 * 21214 * @public 21215 * @type {boolean} 21216 */ 21217 showTabsBasedOnAnchor: true 21218 } 21219}; 21220 21221(function () { 21222 'use strict'; 21223 21224 jQuery(function () { 21225 if(history && history.pushState && history.replaceState) { 21226 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 21227 21228 if(bootstrapTabHistory) { 21229 showTabsBasedOnState(bootstrapTabHistory); 21230 } else { 21231 showTabsBasedOnAnchor(); 21232 } 21233 21234 backfillHistoryState(); 21235 21236 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 21237 jQuery(window).on('popstate', onPopState); 21238 } else { 21239 showTabsBasedOnAnchor(); 21240 } 21241 }); 21242 21243 /** 21244 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 21245 * 21246 * @type {boolean} 21247 */ 21248 var showingTabsBasedOnState = false; 21249 21250 /** 21251 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 21252 * `history.back` handling when `data-tab-history-update-url` is true. 21253 */ 21254 function backfillHistoryState() { 21255 var newState = null; 21256 21257 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 21258 var $activeTabElement = jQuery(this); 21259 var selector = getTabSelector($activeTabElement); 21260 21261 if(selector) { 21262 var tabGroup = getTabGroup($activeTabElement); 21263 21264 if(tabGroup) { 21265 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 21266 } 21267 } 21268 }); 21269 21270 if(newState) { 21271 history.replaceState(newState, '', null); 21272 } 21273 } 21274 21275 /** 21276 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 21277 * said bootstrapTabHistory attribute. 21278 * 21279 * @param {?object} existingState 21280 * @param {!string} tabGroup 21281 * @param {!string} selector 21282 * @returns {!object} 21283 */ 21284 function createNewHistoryState(existingState, tabGroup, selector) { 21285 // Clone history.state and ensure it has a bootstrapTabHistory entry. 21286 var newState = jQuery.extend(true, {}, existingState, { 21287 bootstrapTabHistory: {} 21288 }); 21289 21290 newState.bootstrapTabHistory[tabGroup] = selector; 21291 21292 return newState; 21293 } 21294 21295 /** 21296 * @param {jQuery} $tab
21297 * @returns {?string} 21298 */ 21299 function getTabGroup($tab) { 21300 return parseTruthyAttributeValue($tab.data('tab-history')); 21301 } 21302 21303 /** 21304 * @param {jQuery} $tab 21305 * @returns {?string} 21306 */ 21307 function getTabSelector($tab) { 21308 return $tab.data('target') || $tab.attr('href'); 21309 } 21310 21311 /** 21312 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 21313 * 21314 * @param {jQuery.Event} shownEvt 21315 */ 21316 function onShownTab(shownEvt) { 21317 if(!showingTabsBasedOnState) { 21318 var $activatedTab = jQuery(shownEvt.target); 21319 if ( $activatedTab.hasClass('panel-collapse') ) 21320 $activatedTab = $activatedTab.closest('.panel').find('a'); 21321 var selector = getTabSelector($activatedTab); 21322 21323 if(selector) { 21324 var tabGroup = getTabGroup($activatedTab); 21325 21326 if(tabGroup) { 21327 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 21328 var newState = createNewHistoryState(history.state, tabGroup, selector); 21329 var updateURL = (function ($activatedTab) { 21330 if(selector[0] === '#') { 21331 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 21332 21333 if(elementUpdateURLOption === undefined) { 21334 return BootstrapTabHistory.options.defaultUpdateURL; 21335 } else { 21336 return elementUpdateURLOption; 21337 } 21338 } else { 21339 return false; 21340 } 21341 })($activatedTab); 21342 21343 switch(historyChanger) { 21344 case 'push': 21345 history.pushState(newState, '', updateURL ? selector : null); 21346 break; 21347 case 'replace': 21348 history.replaceState(newState, '', updateURL ? selector : null); 21349 break; 21350 default: 21351 throw new Error('Unknown tab-history-changer: ' + historyChanger); 21352 } 21353 } 21354 } 21355 } 21356 } 21357 21358 /** 21359 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 21360 */ 21361 function onPopState() { 21362 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 21363 21364 if(bootstrapTabHistory) { 21365 showTabsBasedOnState(bootstrapTabHistory); 21366 } 21367 } 21368 21369 /** 21370 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 21371 * 21372 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 21373 * 21374 * @param {*} value 21375 * @returns {*} 21376 */ 21377 function parseTruthyAttributeValue(value) { 21378 if(value) { 21379 return value; 21380 } else if(value === '') { 21381 return true; 21382 } else { 21383 return value; 21384 } 21385 } 21386 21387 /** 21388 * Show tabs based upon the anchor component of `window.location`. 21389 */ 21390 function showTabsBasedOnAnchor() { 21391 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 21392 var anchor = window.location && window.location.hash; 21393 21394 if(anchor) { 21395 var $tabElement = showTabForSelector(anchor); 21396 21397 if($tabElement && window.addEventListener && window.removeEventListener) { 21398 var anchorYOffset = (function ($tabElement) { 21399 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 21400 21401 if(elementSetting === undefined) { 21402 return BootstrapTabHistory.options.defaultAnchorYOffset; 21403 } else { 21404 return elementSetting; 21405 } 21406 })($tabElement); 21407 21408 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 21409 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 21410 // `history.state` object should have been used (unless the browser did not support the modern History API). 21411 if(anchorYOffset || anchorYOffset === 0) { 21412 var scrollListener = function resetAnchorScroll () { 21413 window.removeEventListener('scroll', scrollListener); 21414 window.scrollTo(0, anchorYOffset); 21415 }; 21416 21417 window.addEventListener('scroll', scrollListener); 21418 } 21419 } 21420 } 21421 } 21422 } 21423 21424 /** 21425 * Show a tab which corresponds to the provided selector. 21426 * 21427 * @param {string} selector - A CSS selector. 21428 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 21429 */ 21430 function showTabForSelector(selector) { 21431 var $tabElement = (function (selector) { 21432 var $ret = null; 21433 21434 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 21435 var $potentialTab = jQuery(this); 21436 21437 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 21438 $ret = $potentialTab; 21439 return false;
vendor: 43,417 bytes, lines 21440-22654
21440 } else { 21441 return null; 21442 } 21443 }); 21444 21445 return $ret; 21446 })(selector); 21447 21448 if($tabElement) { 21449 $tabElement.trigger('click'); 21450 //$tabElement.tab('show'); 21451 } 21452 21453 return $tabElement; 21454 } 21455 21456 /** 21457 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 21458 * 21459 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 21460 */ 21461 function showTabsBasedOnState(bootstrapTabHistory) { 21462 showingTabsBasedOnState = true; 21463 21464 try { 21465 for(var k in bootstrapTabHistory) { 21466 if(bootstrapTabHistory.hasOwnProperty(k)) { 21467 showTabForSelector(bootstrapTabHistory[k]); 21468 } 21469 } 21470 } finally { 21471 showingTabsBasedOnState = false; 21472 } 21473 } 21474})(); 21475 21476/*! 21477 * justifiedGallery - v3.8.1 21478 * http://miromannino.github.io/Justified-Gallery/ 21479 * Copyright (c) 2020 Miro Mannino 21480 * Licensed under the MIT license. 21481 */ 21482(function (factory) { 21483 if (typeof define === 'function' && define.amd) { 21484 // AMD. Register as an anonymous module. 21485 define(['jquery'], factory); 21486 } else if (typeof module === 'object' && module.exports) { 21487 // Node/CommonJS 21488 module.exports = function (root, jQuery) { 21489 if (jQuery === undefined) { 21490 // require('jQuery') returns a factory that requires window to 21491 // build a jQuery instance, we normalize how we use modules 21492 // that require this pattern but the window provided is a noop 21493 // if it's defined (how jquery works) 21494 if (typeof window !== 'undefined') { 21495 jQuery = require('jquery'); 21496 } 21497 else { 21498 jQuery = require('jquery')(root); 21499 } 21500 } 21501 factory(jQuery); 21502 return jQuery; 21503 }; 21504 } else { 21505 // Browser globals 21506 factory(jQuery); 21507 } 21508}(function ($) { 21509 21510 /** 21511 * Justified Gallery controller constructor 21512 * 21513 * @param $gallery the gallery to build 21514 * @param settings the settings (the defaults are in JustifiedGallery.defaults) 21515 * @constructor 21516 */ 21517 var JustifiedGallery = function ($gallery, settings) { 21518 21519 this.settings = settings; 21520 this.checkSettings(); 21521 21522 this.imgAnalyzerTimeout = null; 21523 this.entries = null; 21524 this.buildingRow = { 21525 entriesBuff: [], 21526 width: 0, 21527 height: 0, 21528 aspectRatio: 0 21529 }; 21530 this.lastFetchedEntry = null; 21531 this.lastAnalyzedIndex = -1; 21532 this.yield = { 21533 every: 2, // do a flush every n flushes (must be greater than 1) 21534 flushed: 0 // flushed rows without a yield 21535 }; 21536 this.border = settings.border >= 0 ? settings.border : settings.margins; 21537 this.maxRowHeight = this.retrieveMaxRowHeight(); 21538 this.suffixRanges = this.retrieveSuffixRanges(); 21539 this.offY = this.border; 21540 this.rows = 0; 21541 this.spinner = { 21542 phase: 0, 21543 timeSlot: 150, 21544 $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'), 21545 intervalId: null 21546 }; 21547 this.scrollBarOn = false; 21548 this.checkWidthIntervalId = null; 21549 this.galleryWidth = $gallery.width(); 21550 this.$gallery = $gallery; 21551 21552 }; 21553 21554 /** @returns {String} the best suffix given the width and the height */ 21555 JustifiedGallery.prototype.getSuffix = function (width, height) { 21556 var longestSide, i; 21557 longestSide = (width > height) ? width : height; 21558 for (i = 0; i < this.suffixRanges.length; i++) { 21559 if (longestSide <= this.suffixRanges[i]) { 21560 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 21561 } 21562 } 21563 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 21564 }; 21565 21566 /** 21567 * Remove the suffix from the string 21568 * 21569 * @returns {string} a new string without the suffix 21570 */ 21571 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 21572 return str.substring(0, str.length - suffix.length); 21573 }; 21574 21575 /** 21576 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 21577 */ 21578 JustifiedGallery.prototype.endsWith = function (str, suffix) { 21579 return str.indexOf(suffix, str.length - suffix.length) !== -1; 21580 }; 21581 21582 /** 21583 * Get the used suffix of a particular url 21584 * 21585 * @param str 21586 * @returns {String} return the used suffix 21587 */ 21588 JustifiedGallery.prototype.getUsedSuffix = function (str) { 21589 for (var si in this.settings.sizeRangeSuffixes) { 21590 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 21591 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 21592 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 21593 } 21594 } 21595 return ''; 21596 }; 21597 21598 /** 21599 * Given an image src, with the width and the height, returns the new image src with the 21600 * best suffix to show the best quality thumbnail. 21601 * 21602 * @returns {String} the suffix to use 21603 */ 21604 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 21605 var newImageSrc; 21606 21607 if (this.settings.thumbnailPath) { 21608 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 21609 } else { 21610 var matchRes = imageSrc.match(this.settings.extension); 21611 var ext = (matchRes !== null) ? matchRes[0] : ''; 21612 newImageSrc = imageSrc.replace(this.settings.extension, ''); 21613 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc)); 21614 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 21615 } 21616 21617 return newImageSrc; 21618 }; 21619 21620 /** 21621 * Shows the images that is in the given entry 21622 * 21623 * @param $entry the entry 21624 * @param callback the callback that is called when the show animation is finished 21625 */ 21626 JustifiedGallery.prototype.showImg = function ($entry, callback) { 21627 if (this.settings.cssAnimation) { 21628 $entry.addClass('jg-entry-visible'); 21629 if (callback) callback(); 21630 } else { 21631 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 21632 $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 21633 } 21634 }; 21635 21636 /** 21637 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 21638 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 21639 * 21640 * @param $image the image to analyze 21641 * @returns {String} the extracted src 21642 */ 21643 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 21644 var imageSrc = $image.data('safe-src'); 21645 var imageSrcLoc = 'data-safe-src'; 21646 // Begin Uncode edit 21647 if (typeof imageSrc === 'undefined') { 21648 var imageCurrentSrc = $image[0].currentSrc; 21649 if (imageCurrentSrc) { 21650 imageSrc = imageCurrentSrc; 21651 } else { 21652 imageSrc = $image.attr('src'); 21653 } 21654 imageSrcLoc = 'src'; 21655 } 21656 // End Uncode edit 21657 $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method 21658 $image.data('jg.src', imageSrc); // this will change overtime 21659 $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method 21660 return imageSrc; 21661 }; 21662 21663 /** @returns {jQuery} the image in the given entry */ 21664 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 21665 var $img = $entry.find(this.settings.imgSelector); 21666 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 21667 return $img.length === 0 ? null : $img; 21668 }; 21669 21670 /** @returns {jQuery} the caption in the given entry */ 21671 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 21672 var $caption = $entry.find('> .jg-caption'); 21673 return $caption.length === 0 ? null : $caption; 21674 }; 21675 21676 /** 21677 * Display the entry 21678 * 21679 * @param {jQuery} $entry the entry to display 21680 * @param {int} x the x position where the entry must be positioned 21681 * @param y the y position where the entry must be positioned 21682 * @param imgWidth the image width 21683 * @param imgHeight the image height 21684 * @param rowHeight the row height of the row that owns the entry 21685 */ 21686 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 21687 $entry.width(imgWidth); 21688 $entry.height(Math.floor(rowHeight));//hacked by Uncode 21689 $entry.css('top', Math.floor(y));//hacked by Uncode 21690 $entry.css('left', x); 21691 21692 var $image = this.imgFromEntry($entry); 21693 if ($image !== null) { 21694 $image.css('width', imgWidth); 21695 $image.css('height', imgHeight); 21696 $image.css('margin-left', - imgWidth / 2); 21697 $image.css('margin-top', - imgHeight / 2); 21698 21699 // Image reloading for an high quality of thumbnails 21700 var imageSrc = $image.data('jg.src'); 21701 if (imageSrc) { 21702 imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 21703 21704 $image.one('error', function () { 21705 this.resetImgSrc($image); //revert to the original thumbnail 21706 }); 21707 21708 var loadNewImage = function () { 21709 // if (imageSrc !== newImageSrc) { 21710 $image.attr('src', imageSrc); 21711 // } 21712 }; 21713 21714 if ($entry.data('jg.loaded') === 'skipped' && imageSrc) { 21715 this.onImageEvent(imageSrc, (function() { 21716 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 21717 $entry.data('jg.loaded', true); 21718 }).bind(this)); 21719 } else { 21720 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 21721 } 21722 21723 } 21724 21725 } else { 21726 this.showImg($entry); 21727 } 21728 21729 this.displayEntryCaption($entry); 21730 }; 21731 21732 /** 21733 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 21734 * or the 'title' attributes. 21735 * 21736 * @param {jQuery} $entry the entry to process 21737 */ 21738 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 21739 var $image = this.imgFromEntry($entry); 21740 if ($image !== null && this.settings.captions) { 21741 var $imgCaption = this.captionFromEntry($entry); 21742 21743 // Create it if it doesn't exists 21744 if ($imgCaption === null) { 21745 var caption = $image.attr('alt'); 21746 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 21747 if (this.isValidCaption(caption)) { // Create only we found something 21748 $imgCaption = $('<div class="jg-caption">' + caption + '</div>'); 21749 $entry.append($imgCaption); 21750 $entry.data('jg.createdCaption', true); 21751 } 21752 } 21753 21754 // Create events (we check again the $imgCaption because it can be still inexistent) 21755 if ($imgCaption !== null) { 21756 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 21757 this.addCaptionEventsHandlers($entry); 21758 } 21759 } else { 21760 this.removeCaptionEventsHandlers($entry); 21761 } 21762 }; 21763 21764 /** 21765 * Validates the caption 21766 * 21767 * @param caption The caption that should be validated 21768 * @return {boolean} Validation result 21769 */ 21770 JustifiedGallery.prototype.isValidCaption = function (caption) { 21771 return (typeof caption !== 'undefined' && caption.length > 0); 21772 }; 21773 21774 /** 21775 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 21776 * It shows the caption using jQuery (or using CSS if it is configured so) 21777 * 21778 * @param {Event} eventObject the event object 21779 */ 21780 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 21781 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 21782 if (this.settings.cssAnimation) { 21783 $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden'); 21784 } else { 21785 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 21786 this.settings.captionSettings.visibleOpacity); 21787 } 21788 }; 21789 21790 /** 21791 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 21792 * It hides the caption using jQuery (or using CSS if it is configured so) 21793 * 21794 * @param {Event} eventObject the event object 21795 */ 21796 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 21797 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 21798 if (this.settings.cssAnimation) { 21799 $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden'); 21800 } else { 21801 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 21802 this.settings.captionSettings.nonVisibleOpacity); 21803 } 21804 }; 21805 21806 /** 21807 * Add the handlers of the entry for the caption 21808 * 21809 * @param $entry the entry to modify 21810 */ 21811 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 21812 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 21813 if (typeof captionMouseEvents === 'undefined') { 21814 captionMouseEvents = { 21815 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 21816 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 21817 }; 21818 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 21819 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 21820 $entry.data('jg.captionMouseEvents', captionMouseEvents); 21821 } 21822 }; 21823 21824 /** 21825 * Remove the handlers of the entry for the caption 21826 * 21827 * @param $entry the entry to modify 21828 */ 21829 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 21830 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 21831 if (typeof captionMouseEvents !== 'undefined') { 21832 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 21833 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 21834 $entry.removeData('jg.captionMouseEvents'); 21835 } 21836 }; 21837 21838 /** 21839 * Clear the building row data to be used for a new row 21840 */ 21841 JustifiedGallery.prototype.clearBuildingRow = function () { 21842 this.buildingRow.entriesBuff = []; 21843 this.buildingRow.aspectRatio = 0; 21844 this.buildingRow.width = 0; 21845 }; 21846 21847 /** 21848 * Justify the building row, preparing it to 21849 * 21850 * @param isLastRow 21851 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 21852 * @returns a boolean to know if the row has been justified or not 21853 */ 21854 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) { 21855 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 21856 var minHeight = 0; 21857 var availableWidth = this.galleryWidth - 2 * this.border - ( 21858 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 21859 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 21860 var defaultRowHeight = this.settings.rowHeight; 21861 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 21862 21863 //Skip the last row if we can't justify it and the lastRow == 'hide' 21864 if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) { 21865 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 21866 $entry = this.buildingRow.entriesBuff[i]; 21867 if (this.settings.cssAnimation) 21868 $entry.removeClass('jg-entry-visible'); 21869 else { 21870 $entry.stop().fadeTo(0, 0.1); 21871 $entry.find('> img, > a > img').fadeTo(0, 0); 21872 } 21873 } 21874 return -1; 21875 } 21876 21877 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 21878 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 21879 justify = false; 21880 21881 if (this.rows > 0) { 21882 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 21883 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 21884 } 21885 } 21886 21887 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 21888 $entry = this.buildingRow.entriesBuff[i]; 21889 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 21890 21891 if (justify) { 21892 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 21893 newImgH = rowHeight; 21894 } else { 21895 newImgW = defaultRowHeight * imgAspectRatio; 21896 newImgH = defaultRowHeight; 21897 } 21898 21899 availableWidth -= Math.round(newImgW); 21900 $entry.data('jg.jwidth', Math.round(newImgW)); 21901 $entry.data('jg.jheight', Math.ceil(newImgH)); 21902 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 21903 } 21904 21905 this.buildingRow.height = minHeight; 21906 return justify; 21907 }; 21908 21909 /** 21910 * Flush a row: justify it, modify the gallery height accordingly to the row height 21911 * 21912 * @param isLastRow 21913 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 21914 */ 21915 JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) { 21916 var settings = this.settings; 21917 var $entry, buildingRowRes, offX = this.border, i; 21918 21919 buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow); 21920 if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) { 21921 this.clearBuildingRow(); 21922 return; 21923 } 21924 21925 if (this.maxRowHeight) { 21926 if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight; 21927 } 21928 21929 //Align last (unjustified) row 21930 if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) { 21931 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 21932 21933 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 21934 $entry = this.buildingRow.entriesBuff[i]; 21935 availableWidth -= $entry.data('jg.jwidth'); 21936 } 21937 21938 if (settings.lastRow === 'center') 21939 offX += Math.round(availableWidth / 2); 21940 else if (settings.lastRow === 'right') 21941 offX += availableWidth; 21942 } 21943 21944 var lastEntryIdx = this.buildingRow.entriesBuff.length - 1; 21945 for (i = 0; i <= lastEntryIdx; i++) { 21946 $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i]; 21947 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 21948 offX += $entry.data('jg.jwidth') + settings.margins; 21949 } 21950 21951 //Gallery Height 21952 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 21953 this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight()); 21954 21955 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 21956 //Ready for a new row 21957 this.offY += this.buildingRow.height + settings.margins; 21958 this.rows += 1; 21959 this.clearBuildingRow(); 21960 this.settings.triggerEvent.call(this, 'jg.rowflush'); 21961 } 21962 }; 21963 21964 21965 // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221 21966 var galleryPrevStaticHeight = 0; 21967 21968 JustifiedGallery.prototype.rememberGalleryHeight = function () { 21969 galleryPrevStaticHeight = this.$gallery.height(); 21970 this.$gallery.height(galleryPrevStaticHeight); 21971 }; 21972 21973 // grow only 21974 JustifiedGallery.prototype.setGalleryTempHeight = function (height) { 21975 galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight); 21976 this.$gallery.height(galleryPrevStaticHeight); 21977 }; 21978 21979 JustifiedGallery.prototype.setGalleryFinalHeight = function (height) { 21980 galleryPrevStaticHeight = height; 21981 this.$gallery.height(height); 21982 }; 21983 21984 /** 21985 * Checks the width of the gallery container, to know if a new justification is needed 21986 */ 21987 JustifiedGallery.prototype.checkWidth = function () { 21988 this.checkWidthIntervalId = setInterval($.proxy(function () { 21989 21990 // if the gallery is not currently visible, abort. 21991 if (!this.$gallery.is(":visible")) return; 21992 21993 var galleryWidth = parseFloat(this.$gallery.width()); 21994 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 21995 this.galleryWidth = galleryWidth; 21996 this.rewind(); 21997 21998 this.rememberGalleryHeight(); 21999 22000 // Restart to analyze 22001 this.startImgAnalyzer(true); 22002 } 22003 }, this), this.settings.refreshTime); 22004 }; 22005 22006 /** 22007 * @returns {boolean} a boolean saying if the spinner is active or not 22008 */ 22009 JustifiedGallery.prototype.isSpinnerActive = function () { 22010 return this.spinner.intervalId !== null; 22011 }; 22012 22013 /** 22014 * @returns {int} the spinner height 22015 */ 22016 JustifiedGallery.prototype.getSpinnerHeight = function () { 22017 return this.spinner.$el.innerHeight(); 22018 }; 22019 22020 /** 22021 * Stops the spinner animation and modify the gallery height to exclude the spinner 22022 */ 22023 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 22024 clearInterval(this.spinner.intervalId); 22025 this.spinner.intervalId = null; 22026 this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight()); 22027 this.spinner.$el.detach(); 22028 }; 22029 22030 /** 22031 * Starts the spinner animation 22032 */ 22033 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 22034 var spinnerContext = this.spinner; 22035 var $spinnerPoints = spinnerContext.$el.find('span'); 22036 clearInterval(spinnerContext.intervalId); 22037 this.$gallery.append(spinnerContext.$el); 22038 this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 22039 spinnerContext.intervalId = setInterval(function () { 22040 if (spinnerContext.phase < $spinnerPoints.length) { 22041 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 22042 } else { 22043 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 22044 } 22045 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 22046 }, spinnerContext.timeSlot); 22047 }; 22048 22049 /** 22050 * Rewind the image analysis to start from the first entry. 22051 */ 22052 JustifiedGallery.prototype.rewind = function () { 22053 this.lastFetchedEntry = null; 22054 this.lastAnalyzedIndex = -1; 22055 this.offY = this.border; 22056 this.rows = 0; 22057 this.clearBuildingRow(); 22058 }; 22059 22060 /** 22061 * @returns {String} `settings.selector` rejecting spinner element 22062 */ 22063 JustifiedGallery.prototype.getSelectorWithoutSpinner = function () { 22064 return this.settings.selector + ', div:not(.jg-spinner)'; 22065 }; 22066 22067 /** 22068 * @returns {Array} all entries matched by `settings.selector` 22069 */ 22070 JustifiedGallery.prototype.getAllEntries = function () { 22071 var selector = this.getSelectorWithoutSpinner(); 22072 return this.$gallery.children(selector).toArray(); 22073 }; 22074 22075 /** 22076 * Update the entries searching it from the justified gallery HTML element 22077 * 22078 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 22079 * @returns {boolean} true if some entries has been founded 22080 */ 22081 JustifiedGallery.prototype.updateEntries = function (norewind) { 22082 var newEntries; 22083 22084 if (norewind && this.lastFetchedEntry != null) { 22085 var selector = this.getSelectorWithoutSpinner(); 22086 newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray(); 22087 } else { 22088 this.entries = []; 22089 newEntries = this.getAllEntries(); 22090 } 22091 22092 if (newEntries.length > 0) { 22093 22094 // Sort or randomize 22095 if ($.isFunction(this.settings.sort)) { 22096 newEntries = this.sortArray(newEntries); 22097 } else if (this.settings.randomize) { 22098 newEntries = this.shuffleArray(newEntries); 22099 } 22100 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 22101 22102 // Filter 22103 if (this.settings.filter) { 22104 newEntries = this.filterArray(newEntries); 22105 } else { 22106 this.resetFilters(newEntries); 22107 } 22108 22109 } 22110 22111 this.entries = this.entries.concat(newEntries); 22112 return true; 22113 }; 22114 22115 /** 22116 * Apply the entries order to the DOM, iterating the entries and appending the images 22117 * 22118 * @param entries the entries that has been modified and that must be re-ordered in the DOM 22119 */ 22120 JustifiedGallery.prototype.insertToGallery = function (entries) { 22121 var that = this; 22122 $.each(entries, function () { 22123 $(this).appendTo(that.$gallery); 22124 }); 22125 }; 22126 22127 /** 22128 * Shuffle the array using the Fisher-Yates shuffle algorithm 22129 * 22130 * @param a the array to shuffle 22131 * @return the shuffled array 22132 */ 22133 JustifiedGallery.prototype.shuffleArray = function (a) { 22134 var i, j, temp; 22135 for (i = a.length - 1; i > 0; i--) { 22136 j = Math.floor(Math.random() * (i + 1)); 22137 temp = a[i]; 22138 a[i] = a[j]; 22139 a[j] = temp; 22140 } 22141 this.insertToGallery(a); 22142 return a; 22143 }; 22144 22145 /** 22146 * Sort the array using settings.comparator as comparator 22147 * 22148 * @param a the array to sort (it is sorted) 22149 * @return the sorted array 22150 */ 22151 JustifiedGallery.prototype.sortArray = function (a) { 22152 a.sort(this.settings.sort); 22153 this.insertToGallery(a); 22154 return a; 22155 }; 22156 22157 /** 22158 * Reset the filters removing the 'jg-filtered' class from all the entries 22159 * 22160 * @param a the array to reset 22161 */ 22162 JustifiedGallery.prototype.resetFilters = function (a) { 22163 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 22164 }; 22165 22166 /** 22167 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 22168 * 22169 * @param a the array to filter 22170 * @return the filtered array 22171 */ 22172 JustifiedGallery.prototype.filterArray = function (a) { 22173 var settings = this.settings; 22174 if ($.type(settings.filter) === 'string') { 22175 // Filter only keeping the entries passed in the string 22176 return a.filter(function (el) { 22177 var $el = $(el); 22178 if ($el.is(settings.filter)) { 22179 $el.removeClass('jg-filtered'); 22180 return true; 22181 } else { 22182 $el.addClass('jg-filtered').removeClass('jg-visible'); 22183 return false; 22184 } 22185 }); 22186 } else if ($.isFunction(settings.filter)) { 22187 // Filter using the passed function 22188 var filteredArr = a.filter(settings.filter); 22189 for (var i = 0; i < a.length; i++) { 22190 if (filteredArr.indexOf(a[i]) === -1) { 22191 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 22192 } else { 22193 $(a[i]).removeClass('jg-filtered'); 22194 } 22195 } 22196 return filteredArr; 22197 } 22198 }; 22199 22200 /** 22201 * Revert the image src to the default value. 22202 */ 22203 JustifiedGallery.prototype.resetImgSrc = function ($img) { 22204 if ($img.data('jg.originalSrcLoc') === 'src') { 22205 $img.attr('src', $img.data('jg.originalSrc')); 22206 } else { 22207 $img.attr('src', ''); 22208 } 22209 }; 22210 22211 /** 22212 * Destroy the Justified Gallery instance. 22213 * 22214 * It clears all the css properties added in the style attributes. We doesn't backup the original 22215 * values for those css attributes, because it costs (performance) and because in general one 22216 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 22217 * classes). Creating a backup is also difficult because JG could be called multiple times and 22218 * with different style attributes. 22219 */ 22220 JustifiedGallery.prototype.destroy = function () { 22221 clearInterval(this.checkWidthIntervalId); 22222 this.stopImgAnalyzerStarter(); 22223 22224 // Get fresh entries list since filtered entries are absent in `this.entries` 22225 $.each(this.getAllEntries(), $.proxy(function (_, entry) { 22226 var $entry = $(entry); 22227 22228 // Reset entry style 22229 $entry.css('width', ''); 22230 $entry.css('height', ''); 22231 $entry.css('top', ''); 22232 $entry.css('left', ''); 22233 $entry.data('jg.loaded', undefined); 22234 $entry.removeClass('jg-entry jg-filtered jg-entry-visible'); 22235 22236 // Reset image style 22237 var $img = this.imgFromEntry($entry); 22238 if ($img) { 22239 $img.css('width', ''); 22240 $img.css('height', ''); 22241 $img.css('margin-left', ''); 22242 $img.css('margin-top', ''); 22243 this.resetImgSrc($img); 22244 $img.data('jg.originalSrc', undefined); 22245 $img.data('jg.originalSrcLoc', undefined); 22246 $img.data('jg.src', undefined); 22247 } 22248 22249 // Remove caption 22250 this.removeCaptionEventsHandlers($entry); 22251 var $caption = this.captionFromEntry($entry); 22252 if ($entry.data('jg.createdCaption')) { 22253 // remove also the caption element (if created by jg) 22254 $entry.data('jg.createdCaption', undefined); 22255 if ($caption !== null) $caption.remove(); 22256 } else { 22257 if ($caption !== null) $caption.fadeTo(0, 1); 22258 } 22259 22260 }, this)); 22261 22262 this.$gallery.css('height', ''); 22263 this.$gallery.removeClass('justified-gallery'); 22264 this.$gallery.data('jg.controller', undefined); 22265 this.settings.triggerEvent.call(this, 'jg.destroy'); 22266 }; 22267 22268 /** 22269 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 22270 * 22271 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 22272 */ 22273 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 22274 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 22275 var $entry = $(this.entries[i]); 22276 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 22277 var availableWidth = this.galleryWidth - 2 * this.border - ( 22278 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 22279 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 22280 22281 this.buildingRow.entriesBuff.push($entry); 22282 this.buildingRow.aspectRatio += imgAspectRatio; 22283 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 22284 this.lastAnalyzedIndex = i; 22285 22286 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 22287 this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 22288 22289 if (++this.yield.flushed >= this.yield.every) { 22290 this.startImgAnalyzer(isForResize); 22291 return; 22292 } 22293 } 22294 } else if ($entry.data('jg.loaded') !== 'error') { 22295 return; 22296 } 22297 } 22298 22299 // Last row flush (the row is not full) 22300 if (this.buildingRow.entriesBuff.length > 0) { 22301 this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 22302 } 22303 22304 if (this.isSpinnerActive()) { 22305 this.stopLoadingSpinnerAnimation(); 22306 } 22307 22308 /* Stop, if there is, the timeout to start the analyzeImages. 22309 This is because an image can be set loaded, and the timeout can be set, 22310 but this image can be analyzed yet. 22311 */ 22312 this.stopImgAnalyzerStarter(); 22313 22314 this.setGalleryFinalHeight(this.galleryHeightToSet); 22315 22316 //On complete callback 22317 this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete'); 22318 }; 22319 22320 /** 22321 * Stops any ImgAnalyzer starter (that has an assigned timeout) 22322 */ 22323 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 22324 this.yield.flushed = 0; 22325 if (this.imgAnalyzerTimeout !== null) { 22326 clearTimeout(this.imgAnalyzerTimeout); 22327 this.imgAnalyzerTimeout = null; 22328 } 22329 }; 22330 22331 /** 22332 * Starts the image analyzer. It is not immediately called to let the browser to update the view 22333 * 22334 * @param isForResize specifies if the image analyzer must be called for resizing or not 22335 */ 22336 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 22337 var that = this; 22338 this.stopImgAnalyzerStarter(); 22339 this.imgAnalyzerTimeout = setTimeout(function () { 22340 that.analyzeImages(isForResize); 22341 }, 0.001); // we can't start it immediately due to a IE different behaviour 22342 }; 22343 22344 /** 22345 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 22346 * because some browsers, with a 404 set complete = true. 22347 * 22348 * @param imageSrc the image src to load 22349 * @param onLoad callback that is called when the image has been loaded 22350 * @param onError callback that is called in case of an error 22351 */ 22352 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 22353 if (!onLoad && !onError) return; 22354 22355 var memImage = new Image(); 22356 var $memImage = $(memImage); 22357 if (onLoad) { 22358 $memImage.one('load', function () { 22359 $memImage.off('load error'); 22360 onLoad(memImage); 22361 }); 22362 } 22363 if (onError) { 22364 $memImage.one('error', function () { 22365 $memImage.off('load error'); 22366 onError(memImage); 22367 }); 22368 } 22369 memImage.src = imageSrc; 22370 }; 22371 22372 /** 22373 * Init of Justified Gallery controlled 22374 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 22375 */ 22376 JustifiedGallery.prototype.init = function () { 22377 var imagesToLoad = false, skippedImages = false, that = this; 22378 $.each(this.entries, function (index, entry) { 22379 var $entry = $(entry); 22380 var $image = that.imgFromEntry($entry); 22381 22382 $entry.addClass('jg-entry'); 22383 22384 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 22385 22386 // Link Rel global overwrite 22387 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 22388 22389 // Link Target global overwrite 22390 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 22391 22392 if ($image !== null) { 22393 22394 // Image src 22395 var imageSrc = that.extractImgSrcFromImage($image); 22396 22397 /* If we have the height and the width, we don't wait that the image is loaded, 22398 but we start directly with the justification */ 22399 if (that.settings.waitThumbnailsLoad === false || !imageSrc) { 22400 var width = parseFloat($image.attr('width')); 22401 var height = parseFloat($image.attr('height')); 22402 if ($image.prop('tagName') === 'svg') { 22403 width = parseFloat($image[0].getBBox().width); 22404 height = parseFloat($image[0].getBBox().height); 22405 } 22406 if (!isNaN(width) && !isNaN(height)) { 22407 $entry.data('jg.width', width); 22408 $entry.data('jg.height', height); 22409 $entry.data('jg.loaded', 'skipped'); 22410 skippedImages = true; 22411 that.startImgAnalyzer(false); 22412 return true; // continue 22413 } 22414 } 22415 22416 $entry.data('jg.loaded', false); 22417 imagesToLoad = true; 22418 22419 // Spinner start 22420 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 22421 22422 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 22423 $entry.data('jg.width', loadImg.width); 22424 $entry.data('jg.height', loadImg.height); 22425 $entry.data('jg.loaded', true); 22426 that.startImgAnalyzer(false); 22427 }, function () { // image load error 22428 $entry.data('jg.loaded', 'error'); 22429 that.startImgAnalyzer(false); 22430 }); 22431 22432 } else { 22433 $entry.data('jg.loaded', true); 22434 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 22435 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 22436 } 22437 22438 } 22439 22440 }); 22441 22442 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 22443 this.checkWidth(); 22444 }; 22445 22446 /** 22447 * Checks that it is a valid number. If a string is passed it is converted to a number 22448 * 22449 * @param settingContainer the object that contains the setting (to allow the conversion) 22450 * @param settingName the setting name 22451 */ 22452 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 22453 if ($.type(settingContainer[settingName]) === 'string') { 22454 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 22455 } 22456 22457 if ($.type(settingContainer[settingName]) === 'number') { 22458 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 22459 } else { 22460 throw settingName + ' must be a number'; 22461 } 22462 }; 22463 22464 /** 22465 * Checks the sizeRangeSuffixes and, if necessary, converts 22466 * its keys from string (e.g. old settings with 'lt100') to int. 22467 */ 22468 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 22469 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 22470 throw 'sizeRangeSuffixes must be defined and must be an object'; 22471 } 22472 22473 var suffixRanges = []; 22474 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 22475 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 22476 } 22477 22478 var newSizeRngSuffixes = { 0: '' }; 22479 for (var i = 0; i < suffixRanges.length; i++) { 22480 if ($.type(suffixRanges[i]) === 'string') { 22481 try { 22482 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 22483 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 22484 } catch (e) { 22485 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 22486 } 22487 } else { 22488 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 22489 } 22490 } 22491 22492 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 22493 }; 22494 22495 /** 22496 * check and convert the maxRowHeight setting 22497 * requires rowHeight to be already set 22498 * TODO: should be always called when only rowHeight is changed 22499 * @return number or null 22500 */ 22501 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 22502 var newMaxRowHeight = null; 22503 var rowHeight = this.settings.rowHeight; 22504 22505 if ($.type(this.settings.maxRowHeight) === 'string') { 22506 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 22507 newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 22508 } else { 22509 newMaxRowHeight = parseFloat(this.settings.maxRowHeight); 22510 } 22511 } else if ($.type(this.settings.maxRowHeight) === 'number') { 22512 newMaxRowHeight = this.settings.maxRowHeight; 22513 } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) { 22514 return null; 22515 } else { 22516 throw 'maxRowHeight must be a number or a percentage'; 22517 } 22518 22519 // check if the converted value is not a number 22520 if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight'; 22521 22522 // check values, maxRowHeight must be >= rowHeight 22523 if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight; 22524 22525 return newMaxRowHeight; 22526 }; 22527 22528 /** 22529 * Checks the settings 22530 */ 22531 JustifiedGallery.prototype.checkSettings = function () { 22532 this.checkSizeRangesSuffixes(); 22533 22534 this.checkOrConvertNumber(this.settings, 'rowHeight'); 22535 this.checkOrConvertNumber(this.settings, 'margins'); 22536 this.checkOrConvertNumber(this.settings, 'border'); 22537 this.checkOrConvertNumber(this.settings, 'maxRowsCount'); 22538 22539 var lastRowModes = [ 22540 'justify', 22541 'nojustify', 22542 'left', 22543 'center', 22544 'right', 22545 'hide' 22546 ]; 22547 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 22548 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 22549 } 22550 22551 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 22552 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 22553 throw 'justifyThreshold must be in the interval [0,1]'; 22554 } 22555 if ($.type(this.settings.cssAnimation) !== 'boolean') { 22556 throw 'cssAnimation must be a boolean'; 22557 } 22558 22559 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 22560 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 22561 22562 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 22563 if (this.settings.captionSettings.visibleOpacity < 0 || 22564 this.settings.captionSettings.visibleOpacity > 1) { 22565 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 22566 } 22567 22568 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 22569 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 22570 this.settings.captionSettings.nonVisibleOpacity > 1) { 22571 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 22572 } 22573 22574 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 22575 this.checkOrConvertNumber(this.settings, 'refreshTime'); 22576 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 22577 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 22578 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 22579 22580 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 22581 throw 'sort must be false or a comparison function'; 22582 } 22583 22584 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 22585 $.type(this.settings.filter) !== 'string') { 22586 throw 'filter must be false, a string or a filter function'; 22587 } 22588 }; 22589 22590 /** 22591 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 22592 * @returns {Array} sorted suffix ranges 22593 */ 22594 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 22595 var suffixRanges = []; 22596 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 22597 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 22598 } 22599 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 22600 return suffixRanges; 22601 }; 22602 22603 /** 22604 * Update the existing settings only changing some of them 22605 * 22606 * @param newSettings the new settings (or a subgroup of them) 22607 */ 22608 JustifiedGallery.prototype.updateSettings = function (newSettings) { 22609 // In this case Justified Gallery has been called again changing only some options 22610 this.settings = $.extend({}, this.settings, newSettings); 22611 this.checkSettings(); 22612 22613 // As reported in the settings: negative value = same as margins, 0 = disabled 22614 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 22615 22616 this.maxRowHeight = this.retrieveMaxRowHeight(); 22617 this.suffixRanges = this.retrieveSuffixRanges(); 22618 }; 22619 22620 JustifiedGallery.prototype.defaults = { 22621 sizeRangeSuffixes: {}, /* e.g. Flickr configuration 22622 { 22623 100: '_t', // used when longest is less than 100px 22624 240: '_m', // used when longest is between 101px and 240px 22625 320: '_n', // ... 22626 500: '', 22627 640: '_z', 22628 1024: '_b' // used as else case because it is the last 22629 } 22630 */ 22631 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 22632 path relative to a specific thumbnail size. The function should accept respectively three arguments: 22633 current path, width and height */ 22634 rowHeight: 120, // required? required to be > 0? 22635 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 22636 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 22637 // can't exceed 3 * rowHeight) 22638 maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled) 22639 margins: 1, 22640 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 22641 22642 lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 22643 22644 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 22645 * (i.e. lastRow setting is not considered) */ 22646 waitThumbnailsLoad: true, 22647 captions: true, 22648 cssAnimation: true, 22649 imagesAnimationDuration: 500, // ignored with css animations 22650 captionSettings: { // ignored with css animations 22651 animationDuration: 500, 22652 visibleOpacity: 0.7, 22653 nonVisibleOpacity: 0.0 22654 },
22655 rel: null, // rewrite the rel of each analyzed links 22656 target: null, // rewrite the target of all links 22657 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 22658 refreshTime: 200, // time interval (in ms) to check if the page changes its width 22659 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 22660 randomize: false, 22661 rtl: false, // right-to-left mode 22662 sort: false, /* 22663 - false: to do not sort 22664 - function: to sort them using the function as comparator (see Array.prototype.sort()) 22665 */ 22666 filter: false, /* 22667 - false, null or undefined: for a disabled filter 22668 - a string: an entry is kept if entry.is(filter string) returns true 22669 see jQuery's .is() function for further information 22670 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 22671 It follows the specifications of the Array.prototype.filter() function of JavaScript. 22672 */ 22673 selector: 'a', // The selector that is used to know what are the entries of the gallery 22674 imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry 22675 triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger 22676 this.$gallery.trigger(event); // Consider that 'this' is this set to the JustifiedGallery object, so it can 22677 } // access to fields such as $gallery, useful to trigger events with jQuery. 22678 }; 22679 22680 22681 /** 22682 * Justified Gallery plugin for jQuery 22683 * 22684 * Events 22685 * - jg.complete : called when all the gallery has been created 22686 * - jg.resize : called when the gallery has been resized 22687 * - jg.rowflush : when a new row appears 22688 * 22689 * @param arg the action (or the settings) passed when the plugin is called 22690 * @returns {*} the object itself 22691 */ 22692 $.fn.justifiedGallery = function (arg) { 22693 return this.each(function (index, gallery) { 22694 22695 var $gallery = $(gallery); 22696 $gallery.addClass('justified-gallery'); 22697 22698 var controller = $gallery.data('jg.controller'); 22699 if (typeof controller === 'undefined') { 22700 // Create controller and assign it to the object data 22701 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 22702 if (arg === 'destroy') return; // Just a call to an unexisting object 22703 throw 'The argument must be an object'; 22704 } 22705 controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg)); 22706 $gallery.data('jg.controller', controller); 22707 } else if (arg === 'norewind') { 22708 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 22709 // ... left to be more readable 22710 } else if (arg === 'destroy') { 22711 controller.destroy(); 22712 return; 22713 } else { 22714 // In this case Justified Gallery has been called again changing only some options 22715 controller.updateSettings(arg); 22716 controller.rewind(); 22717 } 22718 22719 // Update the entries list 22720 if (!controller.updateEntries(arg === 'norewind')) return; 22721 22722 // Init justified gallery 22723 controller.init(); 22724 22725 }); 22726 }; 22727 22728})); 22729 22730/*! 22731* Customized version of iScroll.js 0.0.1 22732* It fixes bugs affecting its integration with fullpage.js 22733*/ 22734/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 22735(function (window, document, Math) { 22736var rAF = window.requestAnimationFrame || 22737 window.webkitRequestAnimationFrame || 22738 window.mozRequestAnimationFrame || 22739 window.oRequestAnimationFrame || 22740 window.msRequestAnimationFrame || 22741 function (callback) { window.setTimeout(callback, 1000 / 60); }; 22742 22743var utils = (function () { 22744 var me = {}; 22745 22746 var _elementStyle = document.createElement('div').style; 22747 var _vendor = (function () { 22748 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 22749 transform, 22750 i = 0, 22751 l = vendors.length; 22752 22753 for ( ; i < l; i++ ) { 22754 transform = vendors[i] + 'ransform'; 22755 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 22756 } 22757 22758 return false;
22759 })(); 22760 22761 function _prefixStyle (style) { 22762 if ( _vendor === false ) return false; 22763 if ( _vendor === '' ) return style; 22764 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 22765 } 22766 22767 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 22768 22769 me.extend = function (target, obj) { 22770 for ( var i in obj ) { 22771 target[i] = obj[i]; 22772 } 22773 }; 22774 22775 me.addEvent = function (el, type, fn, capture) { 22776 el.addEventListener(type, fn, !!capture); 22777 }; 22778 22779 me.removeEvent = function (el, type, fn, capture) { 22780 el.removeEventListener(type, fn, !!capture); 22781 }; 22782 22783 me.prefixPointerEvent = function (pointerEvent) { 22784 return window.MSPointerEvent ? 22785 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 22786 pointerEvent; 22787 }; 22788 22789 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 22790 var distance = current - start, 22791 speed = Math.abs(distance) / time, 22792 destination, 22793 duration; 22794 22795 deceleration = deceleration === undefined ? 0.0006 : deceleration; 22796 22797 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 22798 duration = speed / deceleration; 22799 22800 if ( destination < lowerMargin ) { 22801 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 22802 distance = Math.abs(destination - current); 22803 duration = distance / speed; 22804 } else if ( destination > 0 ) { 22805 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 22806 distance = Math.abs(current) + destination; 22807 duration = distance / speed; 22808 } 22809 22810 return { 22811 destination: Math.round(destination), 22812 duration: duration 22813 }; 22814 }; 22815 22816 var _transform = _prefixStyle('transform'); 22817 22818 me.extend(me, { 22819 hasTransform: _transform !== false, 22820 hasPerspective: _prefixStyle('perspective') in _elementStyle, 22821 hasTouch: 'ontouchstart' in window, 22822 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 22823 hasTransition: _prefixStyle('transition') in _elementStyle 22824 }); 22825 22826 /* 22827 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 22828 - galaxy S2 is ok 22829 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 22830 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 22831 - galaxy S3 is badAndroid (stock brower, webview) 22832 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 22833 - galaxy S4 is badAndroid (stock brower, webview) 22834 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 22835 - galaxy S5 is OK 22836 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 22837 - galaxy S6 is OK 22838 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 22839 */ 22840 me.isBadAndroid = (function() { 22841 var appVersion = window.navigator.appVersion; 22842 // Android browser is not a chrome browser. 22843 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 22844 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 22845 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 22846 return parseFloat(safariVersion[1]) < 535.19; 22847 } else { 22848 return true; 22849 } 22850 } else { 22851 return false; 22852 } 22853 })(); 22854 22855 me.extend(me.style = {}, { 22856 transform: _transform, 22857 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 22858 transitionDuration: _prefixStyle('transitionDuration'), 22859 transitionDelay: _prefixStyle('transitionDelay'), 22860 transformOrigin: _prefixStyle('transformOrigin') 22861 }); 22862 22863 me.hasClass = function (e, c) { 22864 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 22865 return re.test(e.className); 22866 }; 22867 22868 me.addClass = function (e, c) { 22869 if ( me.hasClass(e, c) ) { 22870 return; 22871 } 22872 22873 var newclass = e.className.split(' '); 22874 newclass.push(c); 22875 e.className = newclass.join(' '); 22876 }; 22877 22878 me.removeClass = function (e, c) { 22879 if ( !me.hasClass(e, c) ) { 22880 return; 22881 } 22882 22883 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 22884 e.className = e.className.replace(re, ' '); 22885 }; 22886 22887 me.offset = function (el) { 22888 var left = -el.offsetLeft, 22889 top = -el.offsetTop; 22890 22891 // jshint -W084 22892 while (el = el.offsetParent) { 22893 left -= el.offsetLeft; 22894 top -= el.offsetTop; 22895 } 22896 // jshint +W084 22897 22898 return { 22899 left: left, 22900 top: top 22901 }; 22902 }; 22903 22904 me.preventDefaultException = function (el, exceptions) { 22905 for ( var i in exceptions ) { 22906 if ( exceptions[i].test(el[i]) ) { 22907 return true; 22908 } 22909 } 22910 22911 return false;
22912 }; 22913 22914 me.extend(me.eventType = {}, { 22915 touchstart: 1, 22916 touchmove: 1, 22917 touchend: 1, 22918 22919 mousedown: 2, 22920 mousemove: 2, 22921 mouseup: 2, 22922 22923 pointerdown: 3, 22924 pointermove: 3, 22925 pointerup: 3, 22926 22927 MSPointerDown: 3, 22928 MSPointerMove: 3, 22929 MSPointerUp: 3 22930 }); 22931 22932 me.extend(me.ease = {}, { 22933 quadratic: { 22934 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 22935 fn: function (k) { 22936 return k * ( 2 - k ); 22937 } 22938 }, 22939 circular: { 22940 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) 22941 fn: function (k) { 22942 return Math.sqrt( 1 - ( --k * k ) ); 22943 } 22944 }, 22945 back: { 22946 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 22947 fn: function (k) { 22948 var b = 4; 22949 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 22950 } 22951 }, 22952 bounce: { 22953 style: '', 22954 fn: function (k) { 22955 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 22956 return 7.5625 * k * k; 22957 } else if ( k < ( 2 / 2.75 ) ) { 22958 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 22959 } else if ( k < ( 2.5 / 2.75 ) ) { 22960 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 22961 } else { 22962 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 22963 } 22964 } 22965 }, 22966 elastic: { 22967 style: '', 22968 fn: function (k) { 22969 var f = 0.22, 22970 e = 0.4; 22971 22972 if ( k === 0 ) { return 0; } 22973 if ( k == 1 ) { return 1; } 22974 22975 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 22976 } 22977 } 22978 }); 22979 22980 me.tap = function (e, eventName) { 22981 var ev = document.createEvent('Event'); 22982 ev.initEvent(eventName, true, true); 22983 ev.pageX = e.pageX; 22984 ev.pageY = e.pageY; 22985 e.target.dispatchEvent(ev); 22986 }; 22987 22988 me.click = function (e) { 22989 var target = e.target, 22990 ev; 22991 22992 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 22993 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 22994 // initMouseEvent is deprecated. 22995 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 22996 ev.initEvent('click', true, true); 22997 ev.view = e.view || window; 22998 ev.detail = 1; 22999 ev.screenX = target.screenX || 0; 23000 ev.screenY = target.screenY || 0; 23001 ev.clientX = target.clientX || 0; 23002 ev.clientY = target.clientY || 0; 23003 ev.ctrlKey = !!e.ctrlKey; 23004 ev.altKey = !!e.altKey; 23005 ev.shiftKey = !!e.shiftKey; 23006 ev.metaKey = !!e.metaKey; 23007 ev.button = 0; 23008 ev.relatedTarget = null; 23009 ev._constructed = true; 23010 target.dispatchEvent(ev); 23011 } 23012 }; 23013 23014 return me; 23015})(); 23016function IScroll (el, options) { 23017 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 23018 this.scroller = this.wrapper.children[0]; 23019 this.scrollerStyle = this.scroller.style; // cache style for better performance 23020 23021 this.options = { 23022 23023 resizeScrollbars: true, 23024 23025 mouseWheelSpeed: 20, 23026 23027 snapThreshold: 0.334, 23028 23029// INSERT POINT: OPTIONS 23030 disablePointer : !utils.hasPointer, 23031 disableTouch : utils.hasPointer || !utils.hasTouch, 23032 disableMouse : utils.hasPointer || utils.hasTouch, 23033 startX: 0, 23034 startY: 0, 23035 scrollY: true, 23036 directionLockThreshold: 5, 23037 momentum: true, 23038 23039 bounce: true, 23040 bounceTime: 600, 23041 bounceEasing: '', 23042 23043 preventDefault: true, 23044 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ }, 23045 23046 HWCompositing: true, 23047 useTransition: true, 23048 useTransform: true, 23049 bindToWrapper: typeof window.onmousedown === "undefined" 23050 }; 23051 23052 for ( var i in options ) { 23053 this.options[i] = options[i]; 23054 } 23055 23056 // Normalize options 23057 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 23058 23059 this.options.useTransition = utils.hasTransition && this.options.useTransition; 23060 this.options.useTransform = utils.hasTransform && this.options.useTransform; 23061 23062 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 23063 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 23064 23065 // If you want eventPassthrough I have to lock one of the axes 23066 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 23067 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 23068 23069 // With eventPassthrough we also need lockDirection mechanism 23070 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 23071 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 23072 23073 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 23074 23075 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 23076 23077 if ( this.options.tap === true ) {
23078 this.options.tap = 'tap'; 23079 } 23080 23081 // https://github.com/cubiq/iscroll/issues/1029 23082 if (!this.options.useTransition && !this.options.useTransform) { 23083 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 23084 this.scrollerStyle.position = "relative"; 23085 } 23086 } 23087 23088 if ( this.options.shrinkScrollbars == 'scale' ) { 23089 this.options.useTransition = false; 23090 } 23091 23092 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 23093 23094// INSERT POINT: NORMALIZATION 23095 23096 // Some defaults 23097 this.x = 0; 23098 this.y = 0; 23099 this.directionX = 0; 23100 this.directionY = 0; 23101 this._events = {}; 23102 23103// INSERT POINT: DEFAULTS 23104 23105 this._init(); 23106 this.refresh(); 23107 23108 this.scrollTo(this.options.startX, this.options.startY); 23109 this.enable(); 23110} 23111 23112IScroll.prototype = { 23113 version: '5.2.0', 23114 23115 _init: function () { 23116 this._initEvents(); 23117 23118 if ( this.options.scrollbars || this.options.indicators ) { 23119 this._initIndicators(); 23120 } 23121 23122 if ( this.options.mouseWheel ) { 23123 this._initWheel(); 23124 } 23125 23126 if ( this.options.snap ) { 23127 this._initSnap(); 23128 } 23129 23130 if ( this.options.keyBindings ) { 23131 this._initKeys(); 23132 } 23133 23134// INSERT POINT: _init 23135 23136 }, 23137 23138 destroy: function () { 23139 this._initEvents(true); 23140 clearTimeout(this.resizeTimeout); 23141 this.resizeTimeout = null; 23142 this._execEvent('destroy'); 23143 }, 23144 23145 _transitionEnd: function (e) { 23146 if ( e.target != this.scroller || !this.isInTransition ) { 23147 return; 23148 } 23149 23150 this._transitionTime(); 23151 if ( !this.resetPosition(this.options.bounceTime) ) { 23152 this.isInTransition = false; 23153 this._execEvent('scrollEnd'); 23154 } 23155 }, 23156 23157 _start: function (e) { 23158 // React to left mouse button only 23159 if ( utils.eventType[e.type] != 1 ) { 23160 // for button property 23161 // http://unixpapa.com/js/mouse.html 23162 var button; 23163 if (!e.which) { 23164 /* IE case */ 23165 button = (e.button < 2) ? 0 : 23166 ((e.button == 4) ? 1 : 2); 23167 } else { 23168 /* All others */ 23169 button = e.button; 23170 } 23171 if ( button !== 0 ) { 23172 return; 23173 } 23174 } 23175 23176 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 23177 return; 23178 } 23179 23180 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 23181 e.preventDefault(); 23182 } 23183 23184 var point = e.touches ? e.touches[0] : e, 23185 pos; 23186 23187 this.initiated = utils.eventType[e.type]; 23188 this.moved = false; 23189 this.distX = 0; 23190 this.distY = 0; 23191 this.directionX = 0; 23192 this.directionY = 0; 23193 this.directionLocked = 0; 23194 23195 this.startTime = utils.getTime(); 23196 23197 if ( this.options.useTransition && this.isInTransition ) { 23198 this._transitionTime(); 23199 this.isInTransition = false; 23200 pos = this.getComputedPosition(); 23201 this._translate(Math.round(pos.x), Math.round(pos.y)); 23202 this._execEvent('scrollEnd'); 23203 } else if ( !this.options.useTransition && this.isAnimating ) { 23204 this.isAnimating = false; 23205 this._execEvent('scrollEnd'); 23206 } 23207 23208 this.startX = this.x; 23209 this.startY = this.y; 23210 this.absStartX = this.x; 23211 this.absStartY = this.y; 23212 this.pointX = point.pageX; 23213 this.pointY = point.pageY; 23214 23215 this._execEvent('beforeScrollStart'); 23216 }, 23217 23218 _move: function (e) { 23219 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 23220 return; 23221 } 23222 23223 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 23224 e.preventDefault(); 23225 } 23226 23227 var point = e.touches ? e.touches[0] : e, 23228 deltaX = point.pageX - this.pointX, 23229 deltaY = point.pageY - this.pointY, 23230 timestamp = utils.getTime(), 23231 newX, newY, 23232 absDistX, absDistY; 23233 23234 this.pointX = point.pageX; 23235 this.pointY = point.pageY; 23236 23237 this.distX += deltaX; 23238 this.distY += deltaY; 23239 absDistX = Math.abs(this.distX); 23240 absDistY = Math.abs(this.distY); 23241 23242 // We need to move at least 10 pixels for the scrolling to initiate 23243 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 23244 return; 23245 } 23246 23247 // If you are scrolling in one direction lock the other 23248 if ( !this.directionLocked && !this.options.freeScroll ) { 23249 if ( absDistX > absDistY + this.options.directionLockThreshold ) {
23250 this.directionLocked = 'h'; // lock horizontally 23251 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 23252 this.directionLocked = 'v'; // lock vertically 23253 } else { 23254 this.directionLocked = 'n'; // no lock 23255 } 23256 } 23257 23258 if ( this.directionLocked == 'h' ) { 23259 if ( this.options.eventPassthrough == 'vertical' ) { 23260 e.preventDefault(); 23261 } else if ( this.options.eventPassthrough == 'horizontal' ) { 23262 this.initiated = false; 23263 return; 23264 } 23265 23266 deltaY = 0; 23267 } else if ( this.directionLocked == 'v' ) { 23268 if ( this.options.eventPassthrough == 'horizontal' ) { 23269 e.preventDefault(); 23270 } else if ( this.options.eventPassthrough == 'vertical' ) { 23271 this.initiated = false; 23272 return; 23273 } 23274 23275 deltaX = 0; 23276 } 23277 23278 deltaX = this.hasHorizontalScroll ? deltaX : 0; 23279 deltaY = this.hasVerticalScroll ? deltaY : 0; 23280 23281 newX = this.x + deltaX; 23282 newY = this.y + deltaY; 23283 23284 // Slow down if outside of the boundaries 23285 if ( newX > 0 || newX < this.maxScrollX ) { 23286 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 23287 } 23288 if ( newY > 0 || newY < this.maxScrollY ) { 23289 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 23290 } 23291 23292 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 23293 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 23294 23295 if ( !this.moved ) { 23296 this._execEvent('scrollStart'); 23297 } 23298 23299 this.moved = true; 23300 23301 this._translate(newX, newY); 23302 23303/* REPLACE START: _move */ 23304 23305 if ( timestamp - this.startTime > 300 ) { 23306 this.startTime = timestamp; 23307 this.startX = this.x; 23308 this.startY = this.y; 23309 } 23310 23311/* REPLACE END: _move */ 23312 23313 }, 23314 23315 _end: function (e) { 23316 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 23317 return; 23318 } 23319 23320 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 23321 e.preventDefault(); 23322 } 23323 23324 var point = e.changedTouches ? e.changedTouches[0] : e, 23325 momentumX, 23326 momentumY, 23327 duration = utils.getTime() - this.startTime, 23328 newX = Math.round(this.x), 23329 newY = Math.round(this.y), 23330 distanceX = Math.abs(newX - this.startX), 23331 distanceY = Math.abs(newY - this.startY), 23332 time = 0, 23333 easing = ''; 23334 23335 this.isInTransition = 0; 23336 this.initiated = 0; 23337 this.endTime = utils.getTime(); 23338 23339 // reset if we are outside of the boundaries 23340 if ( this.resetPosition(this.options.bounceTime) ) { 23341 return; 23342 } 23343 23344 this.scrollTo(newX, newY); // ensures that the last position is rounded 23345 23346 // we scrolled less than 10 pixels 23347 if ( !this.moved ) { 23348 if ( this.options.tap ) { 23349 utils.tap(e, this.options.tap); 23350 } 23351 23352 if ( this.options.click ) { 23353 utils.click(e); 23354 } 23355 23356 this._execEvent('scrollCancel'); 23357 return; 23358 } 23359 23360 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 23361 this._execEvent('flick'); 23362 return; 23363 } 23364 23365 // start momentum animation if needed 23366 if ( this.options.momentum && duration < 300 ) { 23367 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 }; 23368 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 }; 23369 newX = momentumX.destination; 23370 newY = momentumY.destination; 23371 time = Math.max(momentumX.duration, momentumY.duration); 23372 this.isInTransition = 1; 23373 } 23374 23375 23376 if ( this.options.snap ) { 23377 var snap = this._nearestSnap(newX, newY); 23378 this.currentPage = snap; 23379 time = this.options.snapSpeed || Math.max( 23380 Math.max( 23381 Math.min(Math.abs(newX - snap.x), 1000), 23382 Math.min(Math.abs(newY - snap.y), 1000) 23383 ), 300); 23384 newX = snap.x; 23385 newY = snap.y; 23386 23387 this.directionX = 0; 23388 this.directionY = 0; 23389 easing = this.options.bounceEasing; 23390 } 23391 23392// INSERT POINT: _end 23393 23394 if ( newX != this.x || newY != this.y ) { 23395 // change easing function when scroller goes out of the boundaries 23396 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 23397 easing = utils.ease.quadratic; 23398 } 23399 23400 this.scrollTo(newX, newY, time, easing); 23401 return; 23402 } 23403 23404 this._execEvent('scrollEnd'); 23405 }, 23406 23407 _resize: function () { 23408 var that = this; 23409 23410 clearTimeout(this.resizeTimeout); 23411 23412 this.resizeTimeout = setTimeout(function () { 23413 that.refresh(); 23414 }, this.options.resizePolling); 23415 }, 23416 23417 resetPosition: function (time) { 23418 var x = this.x, 23419 y = this.y; 23420 23421 time = time || 0; 23422 23423 if ( !this.hasHorizontalScroll || this.x > 0 ) { 23424 x = 0; 23425 } else if ( this.x < this.maxScrollX ) { 23426 x = this.maxScrollX; 23427 } 23428 23429 if ( !this.hasVerticalScroll || this.y > 0 ) { 23430 y = 0; 23431 } else if ( this.y < this.maxScrollY ) { 23432 y = this.maxScrollY; 23433 } 23434 23435 if ( x == this.x && y == this.y ) { 23436 return false;
23437 } 23438 23439 this.scrollTo(x, y, time, this.options.bounceEasing); 23440 23441 return true; 23442 }, 23443 23444 disable: function () { 23445 this.enabled = false; 23446 }, 23447 23448 enable: function () { 23449 this.enabled = true; 23450 }, 23451 23452 refresh: function () { 23453 var rf = this.wrapper.offsetHeight; // Force reflow 23454 23455 this.wrapperWidth = this.wrapper.clientWidth; 23456 this.wrapperHeight = this.wrapper.clientHeight; 23457 23458/* REPLACE START: refresh */ 23459 23460 this.scrollerWidth = this.scroller.offsetWidth; 23461 this.scrollerHeight = this.scroller.offsetHeight; 23462 23463 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 23464 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 23465 23466/* REPLACE END: refresh */ 23467 23468 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 23469 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 23470 23471 if ( !this.hasHorizontalScroll ) { 23472 this.maxScrollX = 0; 23473 this.scrollerWidth = this.wrapperWidth; 23474 } 23475 23476 if ( !this.hasVerticalScroll ) { 23477 this.maxScrollY = 0; 23478 this.scrollerHeight = this.wrapperHeight; 23479 } 23480 23481 this.endTime = 0; 23482 this.directionX = 0; 23483 this.directionY = 0; 23484 23485 this.wrapperOffset = utils.offset(this.wrapper); 23486 23487 this._execEvent('refresh'); 23488 23489 this.resetPosition(); 23490 23491// INSERT POINT: _refresh 23492 23493 }, 23494 23495 23496 on: function (type, fn) { 23497 if ( !this._events[type] ) { 23498 this._events[type] = []; 23499 } 23500 23501 this._events[type].push(fn); 23502 }, 23503 23504 off: function (type, fn) { 23505 if ( !this._events[type] ) { 23506 return; 23507 } 23508 23509 var index = this._events[type].indexOf(fn); 23510 23511 if ( index > -1 ) { 23512 this._events[type].splice(index, 1); 23513 } 23514 }, 23515 23516 _execEvent: function (type) { 23517 if ( !this._events[type] ) { 23518 return; 23519 } 23520 23521 var i = 0, 23522 l = this._events[type].length; 23523 23524 if ( !l ) { 23525 return; 23526 } 23527 23528 for ( ; i < l; i++ ) { 23529 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 23530 } 23531 }, 23532 23533 scrollBy: function (x, y, time, easing) { 23534 x = this.x + x; 23535 y = this.y + y; 23536 time = time || 0; 23537 23538 this.scrollTo(x, y, time, easing); 23539 }, 23540 23541 scrollTo: function (x, y, time, easing) { 23542 easing = easing || utils.ease.circular; 23543 23544 this.isInTransition = this.options.useTransition && time > 0; 23545 var transitionType = this.options.useTransition && easing.style; 23546 if ( !time || transitionType ) { 23547 if(transitionType) { 23548 this._transitionTimingFunction(easing.style); 23549 this._transitionTime(time); 23550 } 23551 this._translate(x, y); 23552 } else { 23553 this._animate(x, y, time, easing.fn); 23554 } 23555 }, 23556 23557 scrollToElement: function (el, time, offsetX, offsetY, easing) { 23558 el = el.nodeType ? el : this.scroller.querySelector(el); 23559 23560 if ( !el ) { 23561 return; 23562 } 23563 23564 var pos = utils.offset(el); 23565 23566 pos.left -= this.wrapperOffset.left; 23567 pos.top -= this.wrapperOffset.top; 23568 23569 // if offsetX/Y are true we center the element to the screen 23570 if ( offsetX === true ) { 23571 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 23572 } 23573 if ( offsetY === true ) { 23574 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 23575 } 23576 23577 pos.left -= offsetX || 0; 23578 pos.top -= offsetY || 0; 23579 23580 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 23581 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 23582 23583 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 23584 23585 this.scrollTo(pos.left, pos.top, time, easing); 23586 }, 23587 23588 _transitionTime: function (time) { 23589 if (!this.options.useTransition) { 23590 return; 23591 } 23592 time = time || 0; 23593 var durationProp = utils.style.transitionDuration; 23594 if(!durationProp) { 23595 return; 23596 } 23597 23598 this.scrollerStyle[durationProp] = time + 'ms'; 23599 23600 if ( !time && utils.isBadAndroid ) { 23601 this.scrollerStyle[durationProp] = '0.0001ms'; 23602 // remove 0.0001ms 23603 var self = this; 23604 rAF(function() { 23605 if(self.scrollerStyle[durationProp] === '0.0001ms') { 23606 self.scrollerStyle[durationProp] = '0s'; 23607 } 23608 }); 23609 } 23610 23611 23612 if ( this.indicators ) { 23613 for ( var i = this.indicators.length; i--; ) { 23614 this.indicators[i].transitionTime(time); 23615 } 23616 } 23617 23618 23619// INSERT POINT: _transitionTime 23620 23621 }, 23622 23623 _transitionTimingFunction: function (easing) { 23624 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 23625 23626 23627 if ( this.indicators ) { 23628 for ( var i = this.indicators.length; i--; ) { 23629 this.indicators[i].transitionTimingFunction(easing); 23630 } 23631 } 23632 23633 23634// INSERT POINT: _transitionTimingFunction 23635 23636 }, 23637 23638 _translate: function (x, y) { 23639 //Uncode addition 23640 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 23641 return false;
23642 23643 if ( this.options.useTransform ) { 23644 23645/* REPLACE START: _translate */ 23646 23647 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 23648 23649/* REPLACE END: _translate */ 23650 23651 } else { 23652 x = Math.round(x); 23653 y = Math.round(y); 23654 this.scrollerStyle.left = x + 'px'; 23655 this.scrollerStyle.top = y + 'px'; 23656 } 23657 23658 this.x = x; 23659 this.y = y; 23660 23661 23662 if ( this.indicators ) { 23663 for ( var i = this.indicators.length; i--; ) { 23664 this.indicators[i].updatePosition(); 23665 } 23666 } 23667 23668 //Uncode addition 23669 var uncodevent = new CustomEvent('fp-slide-scroll'); 23670 window.dispatchEvent(uncodevent); 23671 23672// INSERT POINT: _translate 23673 23674 }, 23675 23676 _initEvents: function (remove) { 23677 var eventType = remove ? utils.removeEvent : utils.addEvent, 23678 target = this.options.bindToWrapper ? this.wrapper : window; 23679 23680 eventType(window, 'orientationchange', this); 23681 eventType(window, 'resize', this); 23682 23683 if ( this.options.click ) { 23684 eventType(this.wrapper, 'click', this, true); 23685 } 23686 23687 if ( !this.options.disableMouse ) { 23688 eventType(this.wrapper, 'mousedown', this); 23689 eventType(target, 'mousemove', this); 23690 eventType(target, 'mousecancel', this); 23691 eventType(target, 'mouseup', this); 23692 } 23693 23694 if ( utils.hasPointer && !this.options.disablePointer ) { 23695 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 23696 eventType(target, utils.prefixPointerEvent('pointermove'), this); 23697 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 23698 eventType(target, utils.prefixPointerEvent('pointerup'), this); 23699 } 23700 23701 if ( utils.hasTouch && !this.options.disableTouch ) { 23702 eventType(this.wrapper, 'touchstart', this); 23703 eventType(target, 'touchmove', this); 23704 eventType(target, 'touchcancel', this); 23705 eventType(target, 'touchend', this); 23706 } 23707 23708 eventType(this.scroller, 'transitionend', this); 23709 eventType(this.scroller, 'webkitTransitionEnd', this); 23710 eventType(this.scroller, 'oTransitionEnd', this); 23711 eventType(this.scroller, 'MSTransitionEnd', this); 23712 }, 23713 23714 getComputedPosition: function () { 23715 var matrix = window.getComputedStyle(this.scroller, null), 23716 x, y; 23717 23718 if ( this.options.useTransform ) { 23719 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 23720 x = +(matrix[12] || matrix[4]); 23721 y = +(matrix[13] || matrix[5]); 23722 } else { 23723 x = +matrix.left.replace(/[^-\d.]/g, ''); 23724 y = +matrix.top.replace(/[^-\d.]/g, ''); 23725 } 23726 23727 return { x: x, y: y }; 23728 }, 23729 _initIndicators: function () { 23730 var interactive = this.options.interactiveScrollbars, 23731 customStyle = typeof this.options.scrollbars != 'string', 23732 indicators = [], 23733 indicator; 23734 23735 var that = this; 23736 23737 this.indicators = []; 23738 23739 if ( this.options.scrollbars ) { 23740 // Vertical scrollbar 23741 if ( this.options.scrollY ) { 23742 indicator = { 23743 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 23744 interactive: interactive, 23745 defaultScrollbars: true, 23746 customStyle: customStyle, 23747 resize: this.options.resizeScrollbars, 23748 shrink: this.options.shrinkScrollbars, 23749 fade: this.options.fadeScrollbars, 23750 listenX: false 23751 }; 23752 23753 this.wrapper.appendChild(indicator.el); 23754 indicators.push(indicator); 23755 } 23756 23757 // Horizontal scrollbar 23758 if ( this.options.scrollX ) { 23759 indicator = { 23760 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 23761 interactive: interactive, 23762 defaultScrollbars: true, 23763 customStyle: customStyle, 23764 resize: this.options.resizeScrollbars, 23765 shrink: this.options.shrinkScrollbars, 23766 fade: this.options.fadeScrollbars, 23767 listenY: false 23768 }; 23769 23770 this.wrapper.appendChild(indicator.el); 23771 indicators.push(indicator); 23772 } 23773 } 23774 23775 if ( this.options.indicators ) { 23776 // TODO: check concat compatibility 23777 indicators = indicators.concat(this.options.indicators); 23778 } 23779 23780 for ( var i = indicators.length; i--; ) { 23781 this.indicators.push( new Indicator(this, indicators[i]) ); 23782 } 23783 23784 // TODO: check if we can use array.map (wide compatibility and performance issues) 23785 function _indicatorsMap (fn) { 23786 if (that.indicators) { 23787 for ( var i = that.indicators.length; i--; ) { 23788 fn.call(that.indicators[i]); 23789 } 23790 } 23791 } 23792 23793 if ( this.options.fadeScrollbars ) { 23794 this.on('scrollEnd', function () { 23795 _indicatorsMap(function () { 23796 this.fade(); 23797 }); 23798 }); 23799 23800 this.on('scrollCancel', function () { 23801 _indicatorsMap(function () { 23802 this.fade(); 23803 }); 23804 }); 23805 23806 this.on('scrollStart', function () { 23807 _indicatorsMap(function () { 23808 this.fade(1); 23809 }); 23810 }); 23811 23812 this.on('beforeScrollStart', function () { 23813 _indicatorsMap(function () { 23814 this.fade(1, true); 23815 }); 23816 }); 23817 } 23818 23819 23820 this.on('refresh', function () { 23821 _indicatorsMap(function () { 23822 this.refresh(); 23823 }); 23824 }); 23825 23826 this.on('destroy', function () { 23827 _indicatorsMap(function () { 23828 this.destroy(); 23829 }); 23830 23831 delete this.indicators; 23832 }); 23833 }, 23834 23835 _initWheel: function () { 23836 utils.addEvent(this.wrapper, 'wheel', this); 23837 utils.addEvent(this.wrapper, 'mousewheel', this); 23838 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 23839 23840 this.on('destroy', function () { 23841 clearTimeout(this.wheelTimeout); 23842 this.wheelTimeout = null; 23843 utils.removeEvent(this.wrapper, 'wheel', this); 23844 utils.removeEvent(this.wrapper, 'mousewheel', this); 23845 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 23846 }); 23847 }, 23848 23849 _wheel: function (e) { 23850 if ( !this.enabled ) { 23851 return; 23852 } 23853 23854 var wheelDeltaX, wheelDeltaY, 23855 newX, newY, 23856 that = this; 23857 23858 if ( this.wheelTimeout === undefined ) { 23859 that._execEvent('scrollStart'); 23860 } 23861 23862 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 23863 clearTimeout(this.wheelTimeout); 23864 this.wheelTimeout = setTimeout(function () { 23865 if(!that.options.snap) { 23866 that._execEvent('scrollEnd'); 23867 } 23868 that.wheelTimeout = undefined; 23869 }, 400); 23870 23871 if ( 'deltaX' in e ) { 23872 if (e.deltaMode === 1) { 23873 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 23874 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 23875 } else { 23876 wheelDeltaX = -e.deltaX; 23877 wheelDeltaY = -e.deltaY; 23878 } 23879 } else if ( 'wheelDeltaX' in e ) { 23880 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 23881 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 23882 } else if ( 'wheelDelta' in e ) { 23883 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 23884 } else if ( 'detail' in e ) { 23885 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 23886 } else { 23887 return; 23888 } 23889 23890 wheelDeltaX *= this.options.invertWheelDirection; 23891 wheelDeltaY *= this.options.invertWheelDirection; 23892 23893 if ( !this.hasVerticalScroll ) { 23894 wheelDeltaX = wheelDeltaY; 23895 wheelDeltaY = 0; 23896 } 23897 23898 if ( this.options.snap ) { 23899 newX = this.currentPage.pageX; 23900 newY = this.currentPage.pageY; 23901 23902 if ( wheelDeltaX > 0 ) { 23903 newX--; 23904 } else if ( wheelDeltaX < 0 ) { 23905 newX++; 23906 } 23907 23908 if ( wheelDeltaY > 0 ) { 23909 newY--; 23910 } else if ( wheelDeltaY < 0 ) { 23911 newY++; 23912 } 23913 23914 this.goToPage(newX, newY); 23915 23916 return; 23917 } 23918 23919 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 23920 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 23921 23922 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 23923 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 23924 23925 if ( newX > 0 ) { 23926 newX = 0; 23927 } else if ( newX < this.maxScrollX ) { 23928 newX = this.maxScrollX; 23929 } 23930 23931 if ( newY > 0 ) { 23932 newY = 0; 23933 } else if ( newY < this.maxScrollY ) { 23934 newY = this.maxScrollY; 23935 } 23936 23937 this.scrollTo(newX, newY, 0); 23938 23939// INSERT POINT: _wheel 23940 }, 23941 23942 _initSnap: function () { 23943 this.currentPage = {}; 23944 23945 if ( typeof this.options.snap == 'string' ) { 23946 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 23947 } 23948 23949 this.on('refresh', function () { 23950 var i = 0, l, 23951 m = 0, n, 23952 cx, cy, 23953 x = 0, y,
23954 stepX = this.options.snapStepX || this.wrapperWidth, 23955 stepY = this.options.snapStepY || this.wrapperHeight, 23956 el; 23957 23958 this.pages = []; 23959 23960 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 23961 return; 23962 } 23963 23964 if ( this.options.snap === true ) { 23965 cx = Math.round( stepX / 2 ); 23966 cy = Math.round( stepY / 2 ); 23967 23968 while ( x > -this.scrollerWidth ) { 23969 this.pages[i] = []; 23970 l = 0; 23971 y = 0; 23972 23973 while ( y > -this.scrollerHeight ) { 23974 this.pages[i][l] = { 23975 x: Math.max(x, this.maxScrollX), 23976 y: Math.max(y, this.maxScrollY), 23977 width: stepX, 23978 height: stepY, 23979 cx: x - cx, 23980 cy: y - cy 23981 }; 23982 23983 y -= stepY; 23984 l++; 23985 } 23986 23987 x -= stepX; 23988 i++; 23989 } 23990 } else { 23991 el = this.options.snap; 23992 l = el.length; 23993 n = -1; 23994 23995 for ( ; i < l; i++ ) { 23996 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 23997 m = 0; 23998 n++; 23999 } 24000 24001 if ( !this.pages[m] ) { 24002 this.pages[m] = []; 24003 } 24004 24005 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 24006 y = Math.max(-el[i].offsetTop, this.maxScrollY); 24007 cx = x - Math.round(el[i].offsetWidth / 2); 24008 cy = y - Math.round(el[i].offsetHeight / 2); 24009 24010 this.pages[m][n] = { 24011 x: x, 24012 y: y, 24013 width: el[i].offsetWidth, 24014 height: el[i].offsetHeight, 24015 cx: cx, 24016 cy: cy 24017 }; 24018 24019 if ( x > this.maxScrollX ) { 24020 m++; 24021 } 24022 } 24023 } 24024 24025 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 24026 24027 // Update snap threshold if needed 24028 if ( this.options.snapThreshold % 1 === 0 ) { 24029 this.snapThresholdX = this.options.snapThreshold; 24030 this.snapThresholdY = this.options.snapThreshold; 24031 } else { 24032 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 24033 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 24034 } 24035 }); 24036 24037 this.on('flick', function () { 24038 var time = this.options.snapSpeed || Math.max( 24039 Math.max( 24040 Math.min(Math.abs(this.x - this.startX), 1000), 24041 Math.min(Math.abs(this.y - this.startY), 1000) 24042 ), 300); 24043 24044 this.goToPage( 24045 this.currentPage.pageX + this.directionX, 24046 this.currentPage.pageY + this.directionY, 24047 time 24048 ); 24049 }); 24050 }, 24051 24052 _nearestSnap: function (x, y) { 24053 if ( !this.pages.length ) { 24054 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 24055 } 24056 24057 var i = 0, 24058 l = this.pages.length, 24059 m = 0; 24060 24061 // Check if we exceeded the snap threshold 24062 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 24063 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 24064 return this.currentPage; 24065 } 24066 24067 if ( x > 0 ) { 24068 x = 0; 24069 } else if ( x < this.maxScrollX ) { 24070 x = this.maxScrollX; 24071 } 24072 24073 if ( y > 0 ) { 24074 y = 0; 24075 } else if ( y < this.maxScrollY ) { 24076 y = this.maxScrollY; 24077 } 24078 24079 for ( ; i < l; i++ ) { 24080 if ( x >= this.pages[i][0].cx ) { 24081 x = this.pages[i][0].x; 24082 break; 24083 } 24084 } 24085 24086 l = this.pages[i].length; 24087 24088 for ( ; m < l; m++ ) { 24089 if ( y >= this.pages[0][m].cy ) { 24090 y = this.pages[0][m].y; 24091 break; 24092 } 24093 } 24094 24095 if ( i == this.currentPage.pageX ) { 24096 i += this.directionX; 24097 24098 if ( i < 0 ) { 24099 i = 0; 24100 } else if ( i >= this.pages.length ) { 24101 i = this.pages.length - 1; 24102 } 24103 24104 x = this.pages[i][0].x; 24105 } 24106 24107 if ( m == this.currentPage.pageY ) { 24108 m += this.directionY; 24109 24110 if ( m < 0 ) { 24111 m = 0; 24112 } else if ( m >= this.pages[0].length ) { 24113 m = this.pages[0].length - 1; 24114 } 24115 24116 y = this.pages[0][m].y; 24117 } 24118 24119 return { 24120 x: x, 24121 y: y, 24122 pageX: i, 24123 pageY: m 24124 }; 24125 }, 24126 24127 goToPage: function (x, y, time, easing) { 24128 easing = easing || this.options.bounceEasing; 24129 24130 if ( x >= this.pages.length ) { 24131 x = this.pages.length - 1; 24132 } else if ( x < 0 ) { 24133 x = 0; 24134 } 24135 24136 if ( y >= this.pages[x].length ) { 24137 y = this.pages[x].length - 1; 24138 } else if ( y < 0 ) { 24139 y = 0; 24140 } 24141 24142 var posX = this.pages[x][y].x, 24143 posY = this.pages[x][y].y; 24144 24145 time = time === undefined ? this.options.snapSpeed || Math.max( 24146 Math.max( 24147 Math.min(Math.abs(posX - this.x), 1000), 24148 Math.min(Math.abs(posY - this.y), 1000) 24149 ), 300) : time; 24150 24151 this.currentPage = { 24152 x: posX, 24153 y: posY, 24154 pageX: x, 24155 pageY: y 24156 }; 24157 24158 this.scrollTo(posX, posY, time, easing); 24159 }, 24160 24161 next: function (time, easing) { 24162 var x = this.currentPage.pageX, 24163 y = this.currentPage.pageY; 24164 24165 x++; 24166 24167 if ( x >= this.pages.length && this.hasVerticalScroll ) { 24168 x = 0; 24169 y++; 24170 } 24171 24172 this.goToPage(x, y, time, easing); 24173 }, 24174 24175 prev: function (time, easing) { 24176 var x = this.currentPage.pageX, 24177 y = this.currentPage.pageY; 24178 24179 x--; 24180 24181 if ( x < 0 && this.hasVerticalScroll ) { 24182 x = 0; 24183 y--; 24184 } 24185 24186 this.goToPage(x, y, time, easing); 24187 }, 24188 24189 _initKeys: function (e) { 24190 // default key bindings 24191 var keys = { 24192 pageUp: 33, 24193 pageDown: 34, 24194 end: 35, 24195 home: 36, 24196 left: 37, 24197 up: 38, 24198 right: 39, 24199 down: 40 24200 }; 24201 var i; 24202 24203 // if you give me characters I give you keycode 24204 if ( typeof this.options.keyBindings == 'object' ) { 24205 for ( i in this.options.keyBindings ) { 24206 if ( typeof this.options.keyBindings[i] == 'string' ) { 24207 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
24207deAt(0); 24208 } 24209 } 24210 } else { 24211 this.options.keyBindings = {}; 24212 } 24213 24214 for ( i in keys ) { 24215 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 24216 } 24217 24218 utils.addEvent(window, 'keydown', this); 24219 24220 this.on('destroy', function () { 24221 utils.removeEvent(window, 'keydown', this); 24222 }); 24223 }, 24224 24225 _key: function (e) { 24226 if ( !this.enabled ) { 24227 return; 24228 } 24229 24230 var snap = this.options.snap, // we are using this alot, better to cache it 24231 newX = snap ? this.currentPage.pageX : this.x, 24232 newY = snap ? this.currentPage.pageY : this.y, 24233 now = utils.getTime(), 24234 prevTime = this.keyTime || 0, 24235 acceleration = 0.250, 24236 pos; 24237 24238 if ( this.options.useTransition && this.isInTransition ) { 24239 pos = this.getComputedPosition(); 24240 24241 this._translate(Math.round(pos.x), Math.round(pos.y)); 24242 this.isInTransition = false; 24243 } 24244 24245 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 24246 24247 switch ( e.keyCode ) { 24248 case this.options.keyBindings.pageUp: 24249 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 24250 newX += snap ? 1 : this.wrapperWidth; 24251 } else { 24252 newY += snap ? 1 : this.wrapperHeight; 24253 } 24254 break; 24255 case this.options.keyBindings.pageDown: 24256 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 24257 newX -= snap ? 1 : this.wrapperWidth; 24258 } else { 24259 newY -= snap ? 1 : this.wrapperHeight; 24260 } 24261 break; 24262 case this.options.keyBindings.end: 24263 newX = snap ? this.pages.length-1 : this.maxScrollX; 24264 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 24265 break; 24266 case this.options.keyBindings.home: 24267 newX = 0; 24268 newY = 0; 24269 break; 24270 case this.options.keyBindings.left: 24271 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 24272 break; 24273 case this.options.keyBindings.up: 24274 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 24275 break; 24276 case this.options.keyBindings.right: 24277 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 24278 break; 24279 case this.options.keyBindings.down: 24280 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 24281 break; 24282 default: 24283 return; 24284 } 24285 24286 if ( snap ) { 24287 this.goToPage(newX, newY); 24288 return; 24289 } 24290 24291 if ( newX > 0 ) { 24292 newX = 0; 24293 this.keyAcceleration = 0; 24294 } else if ( newX < this.maxScrollX ) { 24295 newX = this.maxScrollX; 24296 this.keyAcceleration = 0; 24297 } 24298 24299 if ( newY > 0 ) { 24300 newY = 0; 24301 this.keyAcceleration = 0; 24302 } else if ( newY < this.maxScrollY ) { 24303 newY = this.maxScrollY; 24304 this.keyAcceleration = 0; 24305 } 24306 24307 this.scrollTo(newX, newY, 0); 24308 24309 this.keyTime = now; 24310 }, 24311 24312 _animate: function (destX, destY, duration, easingFn) { 24313 var that = this, 24314 startX = this.x, 24315 startY = this.y, 24316 startTime = utils.getTime(), 24317 destTime = startTime + duration; 24318 24319 function step () { 24320 var now = utils.getTime(), 24321 newX, newY, 24322 easing; 24323 24324 if ( now >= destTime ) { 24325 that.isAnimating = false; 24326 that._translate(destX, destY); 24327 24328 if ( !that.resetPosition(that.options.bounceTime) ) { 24329 that._execEvent('scrollEnd'); 24330 } 24331 24332 return; 24333 } 24334 24335 now = ( now - startTime ) / duration; 24336 easing = easingFn(now); 24337 newX = ( destX - startX ) * easing + startX; 24338 newY = ( destY - startY ) * easing + startY; 24339 that._translate(newX, newY); 24340 24341 if ( that.isAnimating ) { 24342 rAF(step); 24343 } 24344 } 24345 24346 this.isAnimating = true; 24347 step(); 24348 }, 24349 handleEvent: function (e) { 24350 switch ( e.type ) { 24351 case 'touchstart': 24352 case 'pointerdown': 24353 case 'MSPointerDown': 24354 case 'mousedown': 24355 this._start(e); 24356 break; 24357 case 'touchmove': 24358 case 'pointermove': 24359 case 'MSPointerMove': 24360 case 'mousemove': 24361 this._move(e); 24362 break; 24363 case 'touchend': 24364 case 'pointerup': 24365 case 'MSPointerUp': 24366 case 'mouseup': 24367 case 'touchcancel': 24368 case 'pointercancel': 24369 case 'MSPointerCancel': 24370 case 'mousecancel': 24371 this._end(e); 24372 break; 24373 case 'orientationchange': 24374 case 'resize': 24375 this._resize(); 24376 break; 24377 case 'transitionend': 24378 case 'webkitTransitionEnd': 24379 case 'oTransitionEnd': 24380 case 'MSTransitionEnd': 24381 this._transitionEnd(e); 24382 break; 24383 case 'wheel': 24384 case 'DOMMouseScroll': 24385 case 'mousewheel': 24386 this._wheel(e); 24387 break; 24388 case 'keydown': 24389 this._key(e); 24390 break; 24391 case 'click': 24392 if ( this.enabled && !e._constructed ) { 24393 e.preventDefault(); 24394 e.stopPropagation(); 24395 } 24396 break; 24397 } 24398 } 24399}; 24400function createDefaultScrollbar (direction, interactive, type) { 24401 var scrollbar = document.createElement('div'), 24402 indicator = document.createElement('div'); 24403 24404 if ( type === true ) { 24405 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 24406 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'; 24407 } 24408 24409 indicator.className = 'iScrollIndicator'; 24410 24411 if ( direction == 'h' ) { 24412 if ( type === true ) { 24413 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 24414 indicator.style.height = '100%'; 24415 } 24416 scrollbar.className = 'iScrollHorizontalScrollbar'; 24417 } else { 24418 if ( type === true ) { 24419 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 24420 indicator.style.width = '100%'; 24421 } 24422 scrollbar.className = 'iScrollVerticalScrollbar'; 24423 } 24424 24425 scrollbar.style.cssText += ';overflow:hidden'; 24426 24427 if ( !interactive ) { 24428 scrollbar.style.pointerEvents = 'none'; 24429 } 24430 24431 scrollbar.appendChild(indicator); 24432 24433 return scrollbar; 24434} 24435 24436function Indicator (scroller, options) { 24437 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 24438 this.wrapperStyle = this.wrapper.style; 24439 this.indicator = this.wrapper.children[0]; 24440 this.indicatorStyle = this.indicator.style; 24441 this.scroller = scroller; 24442 24443 this.options = { 24444 listenX: true, 24445 listenY: true, 24446 interactive: false, 24447 resize: true, 24448 defaultScrollbars: false, 24449 shrink: false, 24450 fade: false, 24451 speedRatioX: 0, 24452 speedRatioY: 0 24453 }; 24454 24455 for ( var i in options ) { 24456 this.options[i] = options[i]; 24457 } 24458 24459 this.sizeRatioX = 1; 24460 this.sizeRatioY = 1; 24461 this.maxPosX = 0; 24462 this.maxPosY = 0; 24463 24464 if ( this.options.interactive ) { 24465 if ( !this.options.disableTouch ) { 24466 utils.addEvent(this.indicator, 'touchstart', this); 24467 utils.addEvent(window, 'touchend', this); 24468 } 24469 if ( !this.options.disablePointer ) { 24470 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 24471 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 24472 } 24473 if ( !this.options.disableMouse ) { 24474 utils.addEvent(this.indicator, 'mousedown', this); 24475 utils.addEvent(window, 'mouseup', this); 24476 } 24477 } 24478 24479 if ( this.options.fade ) { 24480 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 24481 var durationProp = utils.style.transitionDuration; 24482 if(!durationProp) { 24483 return; 24484 } 24485 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 24486 // remove 0.0001ms 24487 var self = this; 24488 if(utils.isBadAndroid) { 24489 rAF(function() { 24490 if(self.wrapperStyle[durationProp] === '0.0001ms') { 24491 self.wrapperStyle[durationProp] = '0s'; 24492 } 24493 }); 24494 } 24495 this.wrapperStyle.opacity = '0'; 24496 } 24497} 24498 24499Indicator.prototype = { 24500 handleEvent: function (e) { 24501 switch ( e.type ) { 24502 case 'touchstart': 24503 case 'pointerdown': 24504 case 'MSPointerDown': 24505 case 'mousedown': 24506 this._start(e); 24507 break; 24508 case 'touchmove': 24509 case 'pointermove': 24510 case 'MSPointerMove': 24511 case 'mousemove': 24512 this._move(e); 24513 break; 24514 case 'touchend': 24515 case 'pointerup': 24516 case 'MSPointerUp': 24517 case 'mouseup': 24518 case 'touchcancel': 24519 case 'pointercancel': 24520 case 'MSPointerCancel': 24521 case 'mousecancel': 24522 this._end(e); 24523 break; 24524 } 24525 }, 24526 24527 destroy: function () { 24528 if ( this.options.fadeScrollbars ) { 24529 clearTimeout(this.fadeTimeout); 24530 this.fadeTimeout = null; 24531 } 24532 if ( this.options.interactive ) { 24533 utils.removeEvent(this.indicator, 'touchstart', this); 24534 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 24535 utils.removeEvent(this.indicator, 'mousedown', this); 24536 24537 utils.removeEvent(window, 'touchmove', this); 24538 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 24539 utils.removeEvent(window, 'mousemove', this); 24540 24541 utils.removeEvent(window, 'touchend', this); 24542 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 24543 utils.removeEvent(window, 'mouseup', this); 24544 } 24545 24546 if ( this.options.defaultScrollbars ) { 24547 this.wrapper.parentNode.removeChild(this.wrapper); 24548 } 24549 }, 24550 24551 _start: function (e) { 24552 var point = e.touches ? e.touches[0] : e; 24553 24554 e.preventDefault(); 24555 e.stopPropagation(); 24556 24557 this.transitionTime(); 24558 24559 this.initiated = true; 24560 this.moved = false;
24561 this.lastPointX = point.pageX; 24562 this.lastPointY = point.pageY; 24563 24564 this.startTime = utils.getTime(); 24565 24566 if ( !this.options.disableTouch ) { 24567 utils.addEvent(window, 'touchmove', this); 24568 } 24569 if ( !this.options.disablePointer ) { 24570 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 24571 } 24572 if ( !this.options.disableMouse ) { 24573 utils.addEvent(window, 'mousemove', this); 24574 } 24575 24576 this.scroller._execEvent('beforeScrollStart'); 24577 }, 24578 24579 _move: function (e) { 24580 var point = e.touches ? e.touches[0] : e, 24581 deltaX, deltaY, 24582 newX, newY, 24583 timestamp = utils.getTime(); 24584 24585 if ( !this.moved ) { 24586 this.scroller._execEvent('scrollStart'); 24587 } 24588 24589 this.moved = true; 24590 24591 deltaX = point.pageX - this.lastPointX; 24592 this.lastPointX = point.pageX; 24593 24594 deltaY = point.pageY - this.lastPointY; 24595 this.lastPointY = point.pageY; 24596 24597 newX = this.x + deltaX; 24598 newY = this.y + deltaY; 24599 24600 this._pos(newX, newY); 24601 24602// INSERT POINT: indicator._move 24603 24604 e.preventDefault(); 24605 e.stopPropagation(); 24606 }, 24607 24608 _end: function (e) { 24609 if ( !this.initiated ) { 24610 return; 24611 } 24612 24613 this.initiated = false; 24614 24615 e.preventDefault(); 24616 e.stopPropagation(); 24617 24618 utils.removeEvent(window, 'touchmove', this); 24619 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 24620 utils.removeEvent(window, 'mousemove', this); 24621 24622 if ( this.scroller.options.snap ) { 24623 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 24624 24625 var time = this.options.snapSpeed || Math.max( 24626 Math.max( 24627 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 24628 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 24629 ), 300); 24630 24631 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 24632 this.scroller.directionX = 0; 24633 this.scroller.directionY = 0; 24634 this.scroller.currentPage = snap; 24635 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 24636 } 24637 } 24638 24639 if ( this.moved ) { 24640 this.scroller._execEvent('scrollEnd'); 24641 } 24642 }, 24643 24644 transitionTime: function (time) { 24645 time = time || 0; 24646 var durationProp = utils.style.transitionDuration; 24647 if(!durationProp) { 24648 return; 24649 } 24650 24651 this.indicatorStyle[durationProp] = time + 'ms'; 24652 24653 if ( !time && utils.isBadAndroid ) { 24654 this.indicatorStyle[durationProp] = '0.0001ms'; 24655 // remove 0.0001ms 24656 var self = this; 24657 rAF(function() { 24658 if(self.indicatorStyle[durationProp] === '0.0001ms') { 24659 self.indicatorStyle[durationProp] = '0s'; 24660 } 24661 }); 24662 } 24663 }, 24664 24665 transitionTimingFunction: function (easing) { 24666 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 24667 }, 24668 24669 refresh: function () { 24670 this.transitionTime(); 24671 24672 if ( this.options.listenX && !this.options.listenY ) { 24673 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 24674 } else if ( this.options.listenY && !this.options.listenX ) { 24675 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 24676 } else { 24677 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 24678 } 24679 24680 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 24681 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 24682 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 24683 24684 if ( this.options.defaultScrollbars && this.options.customStyle ) { 24685 if ( this.options.listenX ) { 24686 this.wrapper.style.right = '8px'; 24687 } else { 24688 this.wrapper.style.bottom = '8px'; 24689 } 24690 } 24691 } else { 24692 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 24693 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 24694 24695 if ( this.options.defaultScrollbars && this.options.customStyle ) { 24696 if ( this.options.listenX ) { 24697 this.wrapper.style.right = '2px'; 24698 } else { 24699 this.wrapper.style.bottom = '2px'; 24700 } 24701 } 24702 } 24703 24704 var r = this.wrapper.offsetHeight; // force refresh 24705 24706 if ( this.options.listenX ) {
24707 this.wrapperWidth = this.wrapper.clientWidth; 24708 if ( this.options.resize ) { 24709 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 24710 this.indicatorStyle.width = this.indicatorWidth + 'px'; 24711 } else { 24712 this.indicatorWidth = this.indicator.clientWidth; 24713 } 24714 24715 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 24716 24717 if ( this.options.shrink == 'clip' ) { 24718 this.minBoundaryX = -this.indicatorWidth + 8; 24719 this.maxBoundaryX = this.wrapperWidth - 8; 24720 } else { 24721 this.minBoundaryX = 0; 24722 this.maxBoundaryX = this.maxPosX; 24723 } 24724 24725 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 24726 } 24727 24728 if ( this.options.listenY ) { 24729 this.wrapperHeight = this.wrapper.clientHeight; 24730 if ( this.options.resize ) { 24731 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 24732 this.indicatorStyle.height = this.indicatorHeight + 'px'; 24733 } else { 24734 this.indicatorHeight = this.indicator.clientHeight; 24735 } 24736 24737 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 24738 24739 if ( this.options.shrink == 'clip' ) { 24740 this.minBoundaryY = -this.indicatorHeight + 8; 24741 this.maxBoundaryY = this.wrapperHeight - 8; 24742 } else { 24743 this.minBoundaryY = 0; 24744 this.maxBoundaryY = this.maxPosY; 24745 } 24746 24747 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 24748 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 24749 } 24750 24751 this.updatePosition(); 24752 }, 24753 24754 updatePosition: function () { 24755 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 24756 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 24757 24758 if ( !this.options.ignoreBoundaries ) { 24759 if ( x < this.minBoundaryX ) { 24760 if ( this.options.shrink == 'scale' ) { 24761 this.width = Math.max(this.indicatorWidth + x, 8); 24762 this.indicatorStyle.width = this.width + 'px'; 24763 } 24764 x = this.minBoundaryX; 24765 } else if ( x > this.maxBoundaryX ) { 24766 if ( this.options.shrink == 'scale' ) { 24767 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 24768 this.indicatorStyle.width = this.width + 'px'; 24769 x = this.maxPosX + this.indicatorWidth - this.width; 24770 } else { 24771 x = this.maxBoundaryX; 24772 } 24773 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 24774 this.width = this.indicatorWidth; 24775 this.indicatorStyle.width = this.width + 'px'; 24776 } 24777 24778 if ( y < this.minBoundaryY ) { 24779 if ( this.options.shrink == 'scale' ) { 24780 this.height = Math.max(this.indicatorHeight + y * 3, 8); 24781 this.indicatorStyle.height = this.height + 'px'; 24782 } 24783 y = this.minBoundaryY; 24784 } else if ( y > this.maxBoundaryY ) { 24785 if ( this.options.shrink == 'scale' ) { 24786 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 24787 this.indicatorStyle.height = this.height + 'px'; 24788 y = this.maxPosY + this.indicatorHeight - this.height; 24789 } else { 24790 y = this.maxBoundaryY; 24791 } 24792 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 24793 this.height = this.indicatorHeight; 24794 this.indicatorStyle.height = this.height + 'px'; 24795 } 24796 } 24797 24798 this.x = x; 24799 this.y = y; 24800 24801 if ( this.scroller.options.useTransform ) { 24802 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 24803 } else { 24804 this.indicatorStyle.left = x + 'px'; 24805 this.indicatorStyle.top = y + 'px'; 24806 } 24807 }, 24808 24809 _pos: function (x, y) { 24810 if ( x < 0 ) { 24811 x = 0; 24812 } else if ( x > this.maxPosX ) { 24813 x = this.maxPosX; 24814 } 24815 24816 if ( y < 0 ) { 24817 y = 0; 24818 } else if ( y > this.maxPosY ) { 24819 y = this.maxPosY;
24820 } 24821 24822 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 24823 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 24824 24825 this.scroller.scrollTo(x, y); 24826 }, 24827 24828 fade: function (val, hold) { 24829 if ( hold && !this.visible ) { 24830 return; 24831 } 24832 24833 clearTimeout(this.fadeTimeout); 24834 this.fadeTimeout = null; 24835 24836 var time = val ? 250 : 500, 24837 delay = val ? 0 : 300; 24838 24839 val = val ? '1' : '0'; 24840 24841 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 24842 24843 this.fadeTimeout = setTimeout((function (val) { 24844 this.wrapperStyle.opacity = val; 24845 this.visible = +val; 24846 }).bind(this, val), delay); 24847 } 24848}; 24849 24850IScroll.utils = utils; 24851 24852if ( typeof module != 'undefined' && module.exports ) { 24853 module.exports = IScroll; 24854} else if ( typeof define == 'function' && define.amd ) { 24855 define( function () { return IScroll; } ); 24856} else { 24857 window.IScroll = IScroll; 24858} 24859 24860})(window, document, Math); 24861/*! 24862 * fullPage 2.9.4 24863 * https://github.com/alvarotrigo/fullPage.js 24864 * @license MIT licensed 24865 * 24866 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 24867 */ 24868(function(global, factory) { 24869 'use strict'; 24870 if (typeof define === 'function' && define.amd) { 24871 define(['jquery'], function($) { 24872 return factory($, global, global.document, global.Math); 24873 }); 24874 } else if (typeof exports === "object" && exports) { 24875 module.exports = factory(require('jquery'), global, global.document, global.Math); 24876 } else { 24877 factory(jQuery, global, global.document, global.Math); 24878 } 24879})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 24880 'use strict'; 24881 24882 // keeping central set of classnames and selectors 24883 var WRAPPER = 'fullpage-wrapper'; 24884 var WRAPPER_SEL = '.' + WRAPPER; 24885 24886 // slimscroll 24887 var SCROLLABLE = 'fp-scrollable'; 24888 var SCROLLABLE_SEL = '.' + SCROLLABLE; 24889 24890 // util 24891 var RESPONSIVE = 'fp-responsive'; 24892 var NO_TRANSITION = 'fp-notransition'; 24893 var DESTROYED = 'fp-destroyed'; 24894 var ENABLED = 'fp-enabled'; 24895 var VIEWING_PREFIX = 'fp-viewing'; 24896 var ACTIVE = 'active'; 24897 var ACTIVE_SEL = '.' + ACTIVE; 24898 var COMPLETELY = 'fp-completely'; 24899 var COMPLETELY_SEL = '.' + COMPLETELY; 24900 24901 // section 24902 var SECTION_DEFAULT_SEL = '.section'; 24903 var SECTION = 'fp-section'; 24904 var SECTION_SEL = '.' + SECTION; 24905 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 24906 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 24907 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 24908 var TABLE_CELL = 'fp-tableCell'; 24909 var TABLE_CELL_SEL = '.' + TABLE_CELL; 24910 var AUTO_HEIGHT = 'fp-auto-height'; 24911 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 24912 var NORMAL_SCROLL = 'fp-normal-scroll'; 24913 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 24914 24915 // section nav 24916 var SECTION_NAV = 'fp-nav'; 24917 var SECTION_NAV_SEL = '#' + SECTION_NAV; 24918 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 24919 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 24920 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 24921 24922 // slide 24923 var SLIDE_DEFAULT_SEL = '.slide'; 24924 var SLIDE = 'fp-slide'; 24925 var SLIDE_SEL = '.' + SLIDE; 24926 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 24927 var SLIDES_WRAPPER = 'fp-slides'; 24928 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 24929 var SLIDES_CONTAINER = 'fp-slidesContainer'; 24930 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 24931 var TABLE = 'fp-table'; 24932 24933 // slide nav 24934 var SLIDES_NAV = 'fp-slidesNav'; 24935 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 24936 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 24937 var SLIDES_ARROW = 'fp-controlArrow'; 24938 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 24939 var SLIDES_PREV = 'fp-prev'; 24940 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 24941 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 24942 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 24943 var SLIDES_NEXT = 'fp-next';
24944 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 24945 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 24946 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 24947 24948 var $window = $(window); 24949 var $document = $(document); 24950 24951 // Default options for iScroll.js used when using scrollOverflow 24952 var iscrollOptions = { 24953 scrollbars: true, 24954 mouseWheel: true, 24955 hideScrollbars: false, 24956 fadeScrollbars: false, 24957 disableMouse: true, 24958 interactiveScrollbars: true, 24959 bounce: false, 24960 }; 24961 24962 $.fn.fullpage = function(options) { 24963 //only once my friend! 24964 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 24965 24966 // common jQuery objects 24967 var $htmlBody = $('html, body'); 24968 var $body = $('body'); 24969 24970 var FP = $.fn.fullpage; 24971 24972 // Creating some defaults, extending them with any options that were provided 24973 options = $.extend({ 24974 //navigation 24975 menu: false, 24976 anchors:[], 24977 lockAnchors: false, 24978 navigation: false, 24979 navigationPosition: 'right', 24980 navigationTooltips: [], 24981 showActiveTooltip: false, 24982 slidesNavigation: false, 24983 slidesNavPosition: 'bottom', 24984 scrollBar: false, 24985 hybrid: false, 24986 24987 //scrolling 24988 css3: true, 24989 scrollingSpeed: 700, 24990 autoScrolling: true, 24991 fitToSection: true, 24992 fitToSectionDelay: 1000, 24993 easing: 'easeInOutCubic', 24994 easingcss3: 'ease', 24995 loopBottom: false, 24996 loopTop: false, 24997 loopHorizontal: true, 24998 continuousVertical: false, 24999 continuousHorizontal: false, 25000 scrollHorizontally: false, 25001 interlockedSlides: false, 25002 dragAndMove: false, 25003 offsetSections: false, 25004 resetSliders: false, 25005 fadingEffect: false, 25006 normalScrollElements: null, 25007 scrollOverflow: false, 25008 scrollOverflowReset: false, 25009 scrollOverflowHandler: iscrollHandler, 25010 scrollOverflowOptions: null, 25011 touchSensitivity: 5, 25012 normalScrollElementTouchThreshold: 5, 25013 bigSectionsDestination: null, 25014 25015 //Accessibility 25016 keyboardScrolling: true, 25017 animateAnchor: true, 25018 recordHistory: true, 25019 25020 //design 25021 controlArrows: true, 25022 controlArrowColor: '#fff', 25023 verticalCentered: true, 25024 sectionsColor : [], 25025 paddingTop: 0, 25026 paddingBottom: 0, 25027 fixedElements: null, 25028 responsive: 0, //backwards compabitility with responsiveWiddth 25029 responsiveWidth: 0, 25030 responsiveHeight: 0, 25031 responsiveSlides: false, 25032 parallax: false, 25033 parallaxOptions: { 25034 type: 'reveal', 25035 percentage: 62, 25036 property: 'translate' 25037 }, 25038 25039 //Custom selectors 25040 sectionSelector: SECTION_DEFAULT_SEL, 25041 slideSelector: SLIDE_DEFAULT_SEL, 25042 25043 //events 25044 afterLoad: null, 25045 onLeave: null, 25046 afterRender: null, 25047 afterResize: null, 25048 afterReBuild: null, 25049 afterSlideLoad: null, 25050 onSlideLeave: null, 25051 afterResponsive: null, 25052 25053 lazyLoading: true 25054 }, options); 25055 25056 //flag to avoid very fast sliding for landscape sliders 25057 var slideMoving = false; 25058 25059 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 25060 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 25061 var container = $(this); 25062 var windowsHeight = $window.height(); 25063 var isResizing = false; 25064 var isWindowFocused = true; 25065 var lastScrolledDestiny; 25066 var lastScrolledSlide; 25067 var canScroll = true; 25068 var scrollings = []; 25069 var controlPressed; 25070 var startingSection; 25071 var isScrollAllowed = {}; 25072 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 25073 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 25074 var MSPointer = getMSPointer(); 25075 var events = { 25076 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 25077 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 25078 }; 25079 25080 //cheks for passive event support 25081 //added by Uncode from new fullPage updates 25082 var g_supportsPassive = false;
25083 try { 25084 var opts = Object.defineProperty({}, 'passive', { 25085 get: function() { 25086 g_supportsPassive = true; 25087 } 25088 }); 25089 window.addEventListener("testPassive", null, opts); 25090 window.removeEventListener("testPassive", null, opts); 25091 } catch (e) {} 25092 25093 //timeouts 25094 var resizeId; 25095 var afterSectionLoadsId; 25096 var afterSlideLoadsId; 25097 var scrollId; 25098 var scrollId2; 25099 var keydownId; 25100 var originals = $.extend(true, {}, options); //deep copy 25101 25102 //Uncode addition 25103 var $masthead = $('#masthead'); 25104 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 25105 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 25106 var bodyBorder = UNCODE.bodyBorder; 25107 var adminBarHeight = UNCODE.adminBarHeight; 25108 25109 displayWarnings(); 25110 25111 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 25112 iscrollOptions.click = isTouch; // see #2035 25113 25114 //extending iScroll options with the user custom ones 25115 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 25116 25117 //easeInOutCubic animation included in the plugin 25118 $.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;}}); 25119 25120 /** 25121 * Sets the autoScroll option. 25122 * It changes the scroll bar visibility and the history of the site as a result. 25123 */ 25124 function setAutoScrolling(value, type){ 25125 //removing the transformation 25126 if(!value){ 25127 silentScroll(0); 25128 } 25129 25130 setVariableState('autoScrolling', value, type); 25131 25132 var element = $(SECTION_ACTIVE_SEL); 25133 25134 if(options.autoScrolling && !options.scrollBar){ 25135 $htmlBody.css({ 25136 'overflow' : 'hidden !important', 25137 'height' : '100%' 25138 }); 25139 25140 //Uncode addition 25141 //setRecordHistory(originals.recordHistory, 'internal'); 25142 25143 //for IE touch devices 25144 container.css({ 25145 '-ms-touch-action': 'none', 25146 'touch-action': 'none' 25147 }); 25148 25149 if(element.length){ 25150 //moving the container up 25151 silentScroll(element.position().top); 25152 } 25153 25154 }else{ 25155 $htmlBody.css({ 25156 'overflow' : 'visible !important', 25157 'height' : 'initial' 25158 }); 25159 25160 //Uncode addition 25161 //setRecordHistory(false, 'internal'); 25162 25163 //for IE touch devices 25164 container.css({ 25165 '-ms-touch-action': '', 25166 'touch-action': '' 25167 }); 25168 25169 //scrolling the page to the section with no animation 25170 if (element.length) { 25171 $htmlBody.scrollTop(element.position().top); 25172 } 25173 } 25174 } 25175 25176 /** 25177 * Defines wheter to record the history for each hash change in the URL. 25178 */ 25179 function setRecordHistory(value, type){ 25180 setVariableState('recordHistory', value, type); 25181 } 25182 25183 /** 25184 * Defines the scrolling speed 25185 */ 25186 function setScrollingSpeed(value, type){ 25187 setVariableState('scrollingSpeed', value, type); 25188 } 25189 25190 /** 25191 * Sets fitToSection 25192 */ 25193 function setFitToSection(value, type){ 25194 setVariableState('fitToSection', value, type); 25195 } 25196 25197 /** 25198 * Sets lockAnchors 25199 */ 25200 function setLockAnchors(value){ 25201 options.lockAnchors = value; 25202 } 25203 25204 /** 25205 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 25206 */ 25207 function setMouseWheelScrolling(value){ 25208 if(value){ 25209 addMouseWheelHandler(); 25210 addMiddleWheelHandler(); 25211 }else{ 25212 removeMouseWheelHandler(); 25213 removeMiddleWheelHandler(); 25214 } 25215 } 25216 25217 /** 25218 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 25219 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 25220 * 25221 * @param directions string containing the direction or directions separated by comma. 25222 */ 25223 function setAllowScrolling(value, directions){ 25224 if(typeof directions !== 'undefined'){ 25225 directions = directions.replace(/ /g,'').split(','); 25226 25227 $.each(directions, function (index, direction){ 25228 setIsScrollAllowed(value, direction, 'm'); 25229 }); 25230 } 25231 else if(value){ 25232 setMouseWheelScrolling(true); 25233 addTouchHandler(); 25234 }else{ 25235 setMouseWheelScrolling(false); 25236 removeTouchHandler(); 25237 } 25238 } 25239 25240 /** 25241 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 25242 */ 25243 function setKeyboardScrolling(value, directions){ 25244 if(typeof directions !== 'undefined'){ 25245 directions = directions.replace(/ /g,'').split(','); 25246 25247 $.each(directions, function (index, direction){ 25248 setIsScrollAllowed(value, direction, 'k'); 25249 }); 25250 }else{ 25251 options.keyboardScrolling = value; 25252 } 25253 } 25254 25255 /** 25256 * Moves the page up one section. 25257 */ 25258 function moveSectionUp(){ 25259 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 25260 25261 //looping to the bottom if there's no more sections above 25262 if (!prev.length && (options.loopTop || options.continuousVertical)) {
25263 prev = $(SECTION_SEL).last(); 25264 } 25265 25266 if (prev.length) { 25267 scrollPage(prev, null, true); 25268 } 25269 } 25270 25271 /** 25272 * Moves the page down one section. 25273 */ 25274 function moveSectionDown(){ 25275 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 25276 25277 //looping to the top if there's no more sections below 25278 if(!next.length && 25279 (options.loopBottom || options.continuousVertical)){ 25280 next = $(SECTION_SEL).first(); 25281 } 25282 25283 if(next.length){ 25284 scrollPage(next, null, false); 25285 } 25286 } 25287 25288 /** 25289 * Moves the page to the given section and slide with no animation. 25290 * Anchors or index positions can be used as params. 25291 */ 25292 function silentMoveTo(sectionAnchor, slideAnchor){ 25293 setScrollingSpeed (0, 'internal'); 25294 moveTo(sectionAnchor, slideAnchor); 25295 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 25296 } 25297 25298 /** 25299 * Moves the page to the given section and slide. 25300 * Anchors or index positions can be used as params. 25301 */ 25302 function moveTo(sectionAnchor, slideAnchor){ 25303 var destiny = getSectionByAnchor(sectionAnchor); 25304 25305 if (typeof slideAnchor !== 'undefined'){ 25306 scrollPageAndSlide(sectionAnchor, slideAnchor); 25307 }else if(destiny.length > 0){ 25308 scrollPage(destiny); 25309 } 25310 } 25311 25312 /** 25313 * Slides right the slider of the active section. 25314 * Optional `section` param. 25315 */ 25316 function moveSlideRight(section){ 25317 moveSlide('right', section); 25318 } 25319 25320 /** 25321 * Slides left the slider of the active section. 25322 * Optional `section` param. 25323 */ 25324 function moveSlideLeft(section){ 25325 moveSlide('left', section); 25326 } 25327 25328 /** 25329 * When resizing is finished, we adjust the slides sizes and positions 25330 */ 25331 function reBuild(resizing){ 25332 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 25333 25334 isResizing = true; 25335 25336 windowsHeight = $window.height(); //updating global var 25337 25338 $(SECTION_SEL).each(function(){ 25339 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 25340 var slides = $(this).find(SLIDE_SEL); 25341 25342 //adjusting the height of the table-cell for IE and Firefox 25343 if(options.verticalCentered){ 25344 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 25345 } 25346 25347 $(this).css('height', windowsHeight + 'px'); 25348 25349 //resizing the scrolling divs 25350 if(options.scrollOverflow){ 25351 if(slides.length){ 25352 slides.each(function(){ 25353 createScrollBar($(this)); 25354 }); 25355 }else{ 25356 createScrollBar($(this)); 25357 } 25358 } 25359 25360 //adjusting the position fo the FULL WIDTH slides... 25361 if (slides.length > 1) { 25362 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 25363 } 25364 }); 25365 25366 var activeSection = $(SECTION_ACTIVE_SEL); 25367 var sectionIndex = activeSection.index(SECTION_SEL); 25368 25369 //isn't it the first section? 25370 if(sectionIndex){ 25371 //adjusting the position for the current section 25372 silentMoveTo(sectionIndex + 1); 25373 } 25374 25375 isResizing = false; 25376 // Uncode change 25377 // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 25378 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight()); 25379 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 25380 } 25381 25382 /** 25383 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 25384 * are smaller than the set limit values. 25385 */ 25386 function setResponsive(active){ 25387 var isResponsive = $body.hasClass(RESPONSIVE); 25388 25389 if(active){ 25390 if(!isResponsive){ 25391 setAutoScrolling(false, 'internal'); 25392 setFitToSection(false, 'internal'); 25393 $(SECTION_NAV_SEL).hide(); 25394 $body.addClass(RESPONSIVE); 25395 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 25396 } 25397 } 25398 else if(isResponsive){ 25399 setAutoScrolling(originals.autoScrolling, 'internal'); 25400 setFitToSection(originals.autoScrolling, 'internal'); 25401 $(SECTION_NAV_SEL).show(); 25402 $body.removeClass(RESPONSIVE); 25403 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 25404 } 25405 } 25406 25407 if($(this).length){ 25408 //public functions 25409 FP.setAutoScrolling = setAutoScrolling; 25410 FP.setRecordHistory = setRecordHistory; 25411 FP.setScrollingSpeed = setScrollingSpeed; 25412 FP.setFitToSection = setFitToSection; 25413 FP.setLockAnchors = setLockAnchors; 25414 FP.setMouseWheelScrolling = setMouseWheelScrolling; 25415 FP.setAllowScrolling = setAllowScrolling; 25416 FP.setKeyboardScrolling = setKeyboardScrolling; 25417 FP.moveSectionUp = moveSectionUp; 25418 FP.moveSectionDown = moveSectionDown; 25419 FP.silentMoveTo = silentMoveTo; 25420 FP.moveTo = moveTo; 25421 FP.moveSlideRight = moveSlideRight; 25422 FP.moveSlideLeft = moveSlideLeft; 25423 FP.fitToSection = fitToSection; 25424 FP.reBuild = reBuild; 25425 FP.setResponsive = setResponsive; 25426 FP.destroy = destroy; 25427 25428 init(); 25429 25430 bindEvents(); 25431 } 25432
25433 function init(){ 25434 //if css3 is not supported, it will use jQuery animations 25435 if(options.css3){ 25436 options.css3 = support3d(); 25437 } 25438 25439 options.scrollBar = options.scrollBar || options.hybrid; 25440 25441 setOptionsFromDOM(); 25442 prepareDom(); 25443 setAllowScrolling(true); 25444 setAutoScrolling(options.autoScrolling, 'internal'); 25445 responsive(); 25446 25447 //setting the class for the body element 25448 setBodyClass(); 25449 25450 //Uncode addition 25451 // if(document.readyState === 'complete'){ 25452 // scrollToAnchor(); 25453 // } 25454 // $window.on('load', scrollToAnchor); 25455 } 25456 25457 function bindEvents(){ 25458 $window 25459 //when scrolling... 25460 //.on('scroll', scrollHandler) 25461 25462 //detecting any change on the URL to scroll to the given anchor link 25463 //(a way to detect back history button as we play with the hashes on the URL) 25464 .on('hashchange', hashChangeHandler) 25465 25466 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 25467 .blur(blurHandler) 25468 25469 //when resizing the site, we adjust the heights of the sections, slimScroll... 25470 .resize(resizeHandler); 25471 25472 $document 25473 //Sliding with arrow keys, both, vertical and horizontal 25474 .keydown(keydownHandler) 25475 25476 //to prevent scrolling while zooming 25477 .keyup(keyUpHandler) 25478 25479 //Scrolls to the section when clicking the navigation bullet 25480 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 25481 25482 //Scrolls the slider to the given slide destination for the given section 25483 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 25484 25485 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 25486 25487 //Scrolling horizontally when clicking on the slider controls. 25488 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 25489 25490 /** 25491 * Applying normalScroll elements. 25492 * Ignoring the scrolls over the specified selectors. 25493 */ 25494 if(options.normalScrollElements){ 25495 $document.on('mouseenter', options.normalScrollElements, function () { 25496 setMouseWheelScrolling(false); 25497 }); 25498 25499 $document.on('mouseleave', options.normalScrollElements, function(){ 25500 setMouseWheelScrolling(true); 25501 }); 25502 } 25503 } 25504 25505 /** 25506 * Setting options from DOM elements if they are not provided. 25507 */ 25508 function setOptionsFromDOM(){ 25509 var sections = container.find(options.sectionSelector); 25510 25511 //no anchors option? Checking for them in the DOM attributes 25512 if(!options.anchors.length){ 25513 options.anchors = sections.filter('[data-anchor]').map(function(){ 25514 return $(this).data('anchor').toString(); 25515 }).get(); 25516 } 25517 25518 //no tooltips option? Checking for them in the DOM attributes 25519 if(!options.navigationTooltips.length){ 25520 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 25521 return $(this).data('tooltip').toString(); 25522 }).get(); 25523 } 25524 } 25525 25526 /** 25527 * Works over the DOM structure to set it up for the current fullpage options. 25528 */ 25529 function prepareDom(){ 25530 container.css({ 25531 'height': '100%', 25532 'position': 'relative' 25533 }); 25534 25535 //adding a class to recognize the container internally in the code 25536 container.addClass(WRAPPER); 25537 $('html').addClass(ENABLED); 25538 25539 windowsHeight = $window.height(); 25540 25541 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 25542 25543 addInternalSelectors(); 25544 25545 //styling the sections / slides / menu 25546 $(SECTION_SEL).each(function(index){ 25547 var section = $(this); 25548 var slides = section.find(SLIDE_SEL); 25549 var numSlides = slides.length; 25550 25551 styleSection(section, index); 25552 styleMenu(section, index); 25553 25554 // if there's any slide 25555 if (numSlides > 0) { 25556 styleSlides(section, slides, numSlides); 25557 }else{ 25558 if(options.verticalCentered){ 25559 addTableClass(section); 25560 } 25561 } 25562 }); 25563 25564 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 25565 if(options.fixedElements && options.css3){ 25566 $(options.fixedElements).appendTo($body); 25567 } 25568 25569 //vertical centered of the navigation + active bullet 25570 if(options.navigation){ 25571 addVerticalNavigation(); 25572 } 25573 25574 enableYoutubeAPI(); 25575 25576 if(options.scrollOverflow){ 25577 if(document.readyState === 'complete'){ 25578 createScrollBarHandler(); 25579 } 25580 //after DOM and images are loaded 25581 $window.on('load', createScrollBarHandler); 25582 }else{ 25583 afterRenderActions(); 25584 } 25585 } 25586 25587 /** 25588 * Styles the horizontal slides for a section. 25589 */ 25590 function styleSlides(section, slides, numSlides){ 25591 var sliderWidth = numSlides * 100; 25592 var slideWidth = 100 / numSlides; 25593 25594 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 25595 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 25596 25597 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 25598 25599 if(numSlides > 1){ 25600 if(options.controlArrows){ 25601 createSlideArrows(section); 25602 } 25603 25604 if(options.slidesNavigation){ 25605 addSlidesNavigation(section, numSlides); 25606 } 25607 } 25608 25609 slides.each(function(index) { 25610 $(this).css('width', slideWidth + '%'); 25611 25612 if(options.verticalCentered){ 25613 addTableClass($(this)); 25614 } 25615 }); 25616 25617 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 25618 25619 //if the slide won't be an starting point, the default will be the first one 25620 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
25620ide by default. 25621 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 25622 silentLandscapeScroll(startingSlide, 'internal'); 25623 }else{ 25624 slides.eq(0).addClass(ACTIVE); 25625 } 25626 } 25627 25628 /** 25629 * Styling vertical sections 25630 */ 25631 function styleSection(section, index){ 25632 //if no active section is defined, the 1st one will be the default one 25633 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 25634 section.addClass(ACTIVE); 25635 } 25636 startingSection = $(SECTION_ACTIVE_SEL); 25637 25638 section.css('height', windowsHeight + 'px'); 25639 25640 if(options.paddingTop){ 25641 section.css('padding-top', options.paddingTop); 25642 } 25643 25644 if(options.paddingBottom){ 25645 section.css('padding-bottom', options.paddingBottom); 25646 } 25647 25648 if (typeof options.sectionsColor[index] !== 'undefined') { 25649 section.css('background-color', options.sectionsColor[index]); 25650 } 25651 25652 if (typeof options.anchors[index] !== 'undefined') { 25653 section.attr('data-anchor', options.anchors[index]); 25654 } 25655 } 25656 25657 /** 25658 * Sets the data-anchor attributes to the menu elements and activates the current one. 25659 */ 25660 function styleMenu(section, index){ 25661 if (typeof options.anchors[index] !== 'undefined') { 25662 //activating the menu / nav element on load 25663 if(section.hasClass(ACTIVE)){ 25664 activateMenuAndNav(options.anchors[index], index); 25665 } 25666 } 25667 25668 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 25669 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 25670 $(options.menu).appendTo($body); 25671 } 25672 } 25673 25674 /** 25675 * Adds internal classes to be able to provide customizable selectors 25676 * keeping the link with the style sheet. 25677 */ 25678 function addInternalSelectors(){ 25679 container.find(options.sectionSelector).addClass(SECTION); 25680 container.find(options.slideSelector).addClass(SLIDE); 25681 } 25682 25683 /** 25684 * Creates the control arrows for the given section 25685 */ 25686 function createSlideArrows(section){ 25687 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 25688 25689 if(options.controlArrowColor!='#fff'){ 25690 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 25691 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 25692 } 25693 25694 if(!options.loopHorizontal){ 25695 section.find(SLIDES_ARROW_PREV_SEL).hide(); 25696 } 25697 } 25698 25699 /** 25700 * Creates a vertical navigation bar. 25701 */ 25702 function addVerticalNavigation(){ 25703 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 25704 var nav = $(SECTION_NAV_SEL); 25705 25706 nav.addClass(function() { 25707 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 25708 }); 25709 25710 for (var i = 0; i < $(SECTION_SEL).length; i++) { 25711 var link = ''; 25712 if (options.anchors.length) { 25713 link = options.anchors[i]; 25714 } 25715 25716 var li = '<li><a href="#' + link + '"><span></span></a>'; 25717 25718 // Only add tooltip if needed (defined by user) 25719 var tooltip = options.navigationTooltips[i]; 25720 25721 if (typeof tooltip !== 'undefined' && tooltip !== '') { 25722 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 25723 } 25724 25725 li += '</li>'; 25726 25727 nav.find('ul').append(li); 25728 } 25729 25730 //centering it vertically 25731 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 25732 25733 //activating the current active section 25734 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 25735 } 25736 25737 /** 25738 * Creates the slim scroll scrollbar for the sections and slides inside them. 25739 */ 25740 function createScrollBarHandler(){ 25741 $(SECTION_SEL).each(function(){ 25742 var slides = $(this).find(SLIDE_SEL); 25743 25744 if(slides.length){ 25745 slides.each(function(){ 25746 createScrollBar($(this)); 25747 }); 25748 }else{ 25749 createScrollBar($(this)); 25750 } 25751 25752 }); 25753 afterRenderActions(); 25754 } 25755 25756 /*
25757 * Enables the Youtube videos API so we can control their flow if necessary. 25758 */ 25759 function enableYoutubeAPI(){ 25760 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 25761 addURLParam($(this), 'enablejsapi=1'); 25762 }); 25763 } 25764 25765 /** 25766 * Adds a new parameter and its value to the `src` of a given element 25767 */ 25768 function addURLParam(element, newParam){ 25769 var originalSrc = element.attr('src'); 25770 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 25771 } 25772 25773 /* 25774 * Returns the prefix sign to use for a new parameter in an existen URL. 25775 * 25776 * @return {String} ? | & 25777 */ 25778 function getUrlParamSign(url){ 25779 return ( !/\?/.test( url ) ) ? '?' : '&'; 25780 } 25781 25782 /** 25783 * Actions and callbacks to fire afterRender 25784 */ 25785 function afterRenderActions(){ 25786 var section = $(SECTION_ACTIVE_SEL); 25787 25788 section.addClass(COMPLETELY); 25789 25790 if(options.scrollOverflowHandler.afterRender){ 25791 options.scrollOverflowHandler.afterRender(section); 25792 } 25793 lazyLoad(section); 25794 playMedia(section); 25795 options.scrollOverflowHandler.afterLoad(); 25796 25797 if(isDestinyTheStartingSection()){ 25798 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 25799 } 25800 25801 // Uncode change 25802 // $.isFunction( options.afterRender ) && options.afterRender.call(container); 25803 $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight()); 25804 } 25805 25806 /** 25807 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 25808 */ 25809 function isDestinyTheStartingSection(){ 25810 var anchors = window.location.hash.replace('#', '').split('/'); 25811 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 25812 25813 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 25814 } 25815 25816 25817 var isScrolling = false; 25818 var lastScroll = 0; 25819 25820 //when scrolling... 25821 function scrollHandler(){ 25822 var currentSection; 25823 25824 if(!options.autoScrolling || options.scrollBar){ 25825 var currentScroll = $window.scrollTop(); 25826 var scrollDirection = getScrollDirection(currentScroll); 25827 var visibleSectionIndex = 0; 25828 var screen_mid = currentScroll + ($window.height() / 2.0); 25829 var isAtBottom = $body.height() - $window.height() === currentScroll; 25830 var sections = document.querySelectorAll(SECTION_SEL); 25831 25832 //when using `auto-height` for a small last section it won't be centered in the viewport 25833 if(isAtBottom){ 25834 visibleSectionIndex = sections.length - 1; 25835 } 25836 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 25837 else if(!currentScroll){ 25838 visibleSectionIndex = 0; 25839 } 25840 25841 //taking the section which is showing more content in the viewport 25842 else{ 25843 for (var i = 0; i < sections.length; ++i) { 25844 var section = sections[i]; 25845 25846 // Pick the the last section which passes the middle line of the screen. 25847 if (section.offsetTop <= screen_mid) 25848 { 25849 visibleSectionIndex = i; 25850 } 25851 } 25852 } 25853 25854 if(isCompletelyInViewPort(scrollDirection)){ 25855 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 25856 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 25857 } 25858 } 25859 25860 //geting the last one, the current one on the screen 25861 currentSection = $(sections).eq(visibleSectionIndex); 25862 25863 //setting the visible section as active when manually scrolling 25864 //executing only once the first time we reach the section 25865 if(!currentSection.hasClass(ACTIVE)){ 25866 isScrolling = true; 25867 var leavingSection = $(SECTION_ACTIVE_SEL); 25868 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 25869 var yMovement = getYmovement(currentSection); 25870 var anchorLink = currentSection.data('anchor'); 25871 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 25872 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 25873 var slideIndex; 25874 var slideAnchorLink; 25875 25876 if(activeSlide.length){ 25877 slideAnchorLink = activeSlide.data('anchor'); 25878 slideIndex = activeSlide.index(); 25879 } 25880 25881 if(canScroll){ 25882 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 25883 25884 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 25885 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 25886 25887 stopMedia(leavingSection); 25888 lazyLoad(currentSection); 25889 playMedia(currentSection); 25890 25891 activateMenuAndNav(anchorLink, sectionIndex - 1); 25892 25893 if(options.anchors.length){ 25894 //needed to enter in hashChange event when using the menu with anchor links 25895 lastScrolledDestiny = anchorLink; 25896 } 25897 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 25898 } 25899 25900 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 25901 clearTimeout(scrollId); 25902 scrollId = setTimeout(function(){ 25903 isScrolling = false;
25904 }, 100); 25905 } 25906 25907 if(options.fitToSection){ 25908 //for the auto adjust of the viewport to fit a whole section 25909 clearTimeout(scrollId2); 25910 25911 scrollId2 = setTimeout(function(){ 25912 //checking it again in case it changed during the delay 25913 if(options.fitToSection){ 25914 fitToSection(); 25915 } 25916 }, options.fitToSectionDelay); 25917 } 25918 } 25919 } 25920 25921 /** 25922 * Fits the site to the nearest active section 25923 */ 25924 function fitToSection(){ 25925 //checking fitToSection again in case it was set to false before the timeout delay 25926 if(canScroll){ 25927 //allows to scroll to an active section and 25928 //if the section is already active, we prevent firing callbacks 25929 isResizing = true; 25930 25931 scrollPage($(SECTION_ACTIVE_SEL)); 25932 isResizing = false; 25933 } 25934 } 25935 25936 /** 25937 * Determines whether the active section has seen in its whole or not. 25938 */ 25939 function isCompletelyInViewPort(movement){ 25940 var top = $(SECTION_ACTIVE_SEL).position().top; 25941 var bottom = top + $window.height(); 25942 25943 if(movement == 'up'){ 25944 return bottom >= ($window.scrollTop() + $window.height()); 25945 } 25946 return top <= $window.scrollTop(); 25947 } 25948 25949 /** 25950 * Gets the directon of the the scrolling fired by the scroll event. 25951 */ 25952 function getScrollDirection(currentScroll){ 25953 var direction = currentScroll > lastScroll ? 'down' : 'up'; 25954 25955 lastScroll = currentScroll; 25956 25957 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 25958 previousDestTop = currentScroll; 25959 25960 return direction; 25961 } 25962 25963 /** 25964 * Determines the way of scrolling up or down: 25965 * by 'automatically' scrolling a section or by using the default and normal scrolling. 25966 */ 25967 function scrolling(type, scrollable){ 25968 if (!isScrollAllowed.m[type]){ 25969 return; 25970 } 25971 var check = (type === 'down') ? 'bottom' : 'top'; 25972 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 25973 25974 if(scrollable.length > 0 ){ 25975 //is the scrollbar at the start/end of the scroll? 25976 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 25977 scrollSection(); 25978 }else{ 25979 return true; 25980 } 25981 }else{ 25982 // moved up/down 25983 scrollSection(); 25984 } 25985 } 25986 25987 /* 25988 * Preventing bouncing in iOS #2285 25989 */ 25990 function preventBouncing(event){ 25991 var e = event.originalEvent; 25992 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){ 25993 //preventing the easing on iOS devices 25994 event.preventDefault(); 25995 } 25996 } 25997 25998 var touchStartY = 0; 25999 var touchStartX = 0; 26000 var touchEndY = 0; 26001 var touchEndX = 0; 26002 26003 /* Detecting touch events 26004 26005 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 26006 * This way, the touchstart and the touch moves shows an small difference between them which is the 26007 * used one to determine the direction. 26008 */ 26009 function touchMoveHandler(event){ 26010 var e = event.originalEvent; 26011 var activeSection = $(e.target).closest(SECTION_SEL); 26012 26013 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 26014 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 26015 26016 if(options.autoScrolling){ 26017 //preventing the easing on iOS devices 26018 event.preventDefault(); 26019 } 26020 26021 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 26022 var touchEvents = getEventsPage(e); 26023 26024 touchEndY = touchEvents.y; 26025 touchEndX = touchEvents.x; 26026 26027 //if movement in the X axys is greater than in the Y and the currect section has slides... 26028 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 26029 26030 //is the movement greater than the minimum resistance to scroll? 26031 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 26032 if (touchStartX > touchEndX) { 26033 if(isScrollAllowed.m.right){ 26034 moveSlideRight(activeSection); //next 26035 } 26036 } else { 26037 if(isScrollAllowed.m.left){ 26038 moveSlideLeft(activeSection); //prev 26039 } 26040 } 26041 } 26042 } 26043 26044 //vertical scrolling (only when autoScrolling is enabled) 26045 else if(options.autoScrolling && canScroll){ 26046 26047 //is the movement greater than the minimum resistance to scroll? 26048 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 26049 if (touchStartY > touchEndY) { 26050 scrolling('down', scrollable); 26051 } else if (touchEndY > touchStartY) { 26052 scrolling('up', scrollable); 26053 } 26054 } 26055 } 26056 } 26057 } 26058 26059 /** 26060 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 26061 * Currently works well for iOS - Android might need some testing 26062 * @param {Element} el target element / jquery selector (in subsequent nodes) 26063 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 26064 * @return {boolean} true if there is a match to options.normalScrollElements 26065 */ 26066 function checkParentForNormalScrollElement (el, hop) { 26067 hop = hop || 0; 26068 var parent = $(el).parent(); 26069 26070 if (hop < options.normalScrollElementTouchThreshold && 26071 parent.is(options.normalScrollElements) ) { 26072 return true; 26073 } else if (hop == options.normalScrollElementTouchThreshold) { 26074 return false;
26075 } else { 26076 return checkParentForNormalScrollElement(parent, ++hop); 26077 } 26078 } 26079 26080 /** 26081 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 26082 * this way we make sure that is really a touch event what IE is detecting. 26083 */ 26084 function isReallyTouch(e){ 26085 //if is not IE || IE is detecting `touch` or `pen` 26086 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 26087 } 26088 26089 /** 26090 * Handler for the touch start event. 26091 */ 26092 function touchStartHandler(event){ 26093 var e = event.originalEvent; 26094 26095 //stopping the auto scroll to adjust to a section 26096 if(options.fitToSection){ 26097 $htmlBody.stop(); 26098 } 26099 26100 if(isReallyTouch(e)){ 26101 var touchEvents = getEventsPage(e); 26102 touchStartY = touchEvents.y; 26103 touchStartX = touchEvents.x; 26104 } 26105 } 26106 26107 /** 26108 * Gets the average of the last `number` elements of the given array. 26109 */ 26110 function getAverage(elements, number){ 26111 var sum = 0; 26112 26113 //taking `number` elements from the end to make the average, if there are not enought, 1 26114 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 26115 26116 for(var i = 0; i < lastElements.length; i++){ 26117 sum = sum + lastElements[i]; 26118 } 26119 26120 return Math.ceil(sum/number); 26121 } 26122 26123 /** 26124 * Detecting mousewheel scrolling 26125 * 26126 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 26127 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 26128 */ 26129 var prevTime = new Date().getTime(); 26130 26131 function MouseWheelHandler(e) { 26132 var curTime = new Date().getTime(); 26133 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 26134 26135 //autoscrolling and not zooming? 26136 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 26137 // cross-browser wheel delta 26138 e = e || window.event; 26139 var value = e.wheelDelta || -e.deltaY || -e.detail; 26140 var delta = Math.max(-1, Math.min(1, value)); 26141 26142 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 26143 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 26144 26145 //Limiting the array to 150 (lets not waste memory!) 26146 if(scrollings.length > 149){ 26147 scrollings.shift(); 26148 } 26149 26150 //keeping record of the previous scrollings 26151 scrollings.push(Math.abs(value)); 26152 26153 //preventing to scroll the site on mouse wheel when scrollbar is present 26154 if(options.scrollBar){ 26155 e.preventDefault ? e.preventDefault() : e.returnValue = false; 26156 } 26157 26158 var activeSection = $(SECTION_ACTIVE_SEL); 26159 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 26160 26161 //time difference between the last scroll and the current one 26162 var timeDiff = curTime-prevTime; 26163 prevTime = curTime; 26164 26165 //haven't they scrolled in a while? 26166 //(enough to be consider a different scrolling action to scroll another section) 26167 if(timeDiff > 200){ 26168 //emptying the array, we dont care about old scrollings for our averages 26169 scrollings = []; 26170 } 26171 26172 if(canScroll){ 26173 var averageEnd = getAverage(scrollings, 10); 26174 var averageMiddle = getAverage(scrollings, 70); 26175 var isAccelerating = averageEnd >= averageMiddle; 26176 26177 //to avoid double swipes... 26178 if(isAccelerating && isScrollingVertically){ 26179 //scrolling down? 26180 if (delta < 0) { 26181 scrolling('down', scrollable); 26182 26183 //scrolling up? 26184 }else { 26185 scrolling('up', scrollable); 26186 } 26187 } 26188 } 26189 26190 return false;
26191 } 26192 26193 if(options.fitToSection){ 26194 //stopping the auto scroll to adjust to a section 26195 $htmlBody.stop(); 26196 } 26197 } 26198 26199 /** 26200 * Slides a slider to the given direction. 26201 * Optional `section` param. 26202 */ 26203 function moveSlide(direction, section){ 26204 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 26205 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 26206 var numSlides = slides.find(SLIDE_SEL).length; 26207 26208 // more than one slide needed and nothing should be sliding 26209 if (!slides.length || slideMoving || numSlides < 2) { 26210 return; 26211 } 26212 26213 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 26214 var destiny = null; 26215 26216 if(direction === 'left'){ 26217 destiny = currentSlide.prev(SLIDE_SEL); 26218 }else{ 26219 destiny = currentSlide.next(SLIDE_SEL); 26220 } 26221 26222 //isn't there a next slide in the secuence? 26223 if(!destiny.length){ 26224 //respect loopHorizontal settin 26225 if (!options.loopHorizontal) return; 26226 26227 if(direction === 'left'){ 26228 destiny = currentSlide.siblings(':last'); 26229 }else{ 26230 destiny = currentSlide.siblings(':first'); 26231 } 26232 } 26233 26234 slideMoving = true; 26235 26236 landscapeScroll(slides, destiny, direction); 26237 } 26238 26239 /** 26240 * Maintains the active slides in the viewport 26241 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 26242 */ 26243 function keepSlidesPosition(){ 26244 $(SLIDE_ACTIVE_SEL).each(function(){ 26245 silentLandscapeScroll($(this), 'internal'); 26246 }); 26247 } 26248 26249 var previousDestTop = 0; 26250 /** 26251 * Returns the destination Y position based on the scrolling direction and 26252 * the height of the section. 26253 */ 26254 function getDestinationPosition(element){ 26255 var elemPosition = element.position(); 26256 26257 //top of the desination will be at the top of the viewport 26258 var position = elemPosition.top; 26259 var isScrollingDown = elemPosition.top > previousDestTop; 26260 var sectionBottom = position - windowsHeight + element.outerHeight(); 26261 var bigSectionsDestination = options.bigSectionsDestination; 26262 26263 //Uncode addition 26264 var containerH = container.outerHeight(); 26265 var containerPosition = container.offset(); 26266 26267 //########### Commented by Uncode - START ########### 26268 //is the destination element bigger than the viewport? 26269 // if(element.outerHeight() > windowsHeight){ 26270 // //scrolling up? 26271 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 26272 // position = sectionBottom; 26273 // } 26274 // } 26275 26276 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 26277 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 26278 // //The bottom of the destination will be at the bottom of the viewport 26279 // position = sectionBottom; 26280 // } 26281 //########### Commented by Uncode - END ########### 26282 26283 //Uncode addition 26284 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 26285 position += 18; 26286 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 26287 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 26288 } 26289 26290 /* 26291 Keeping record of the last scrolled position to determine the scrolling direction. 26292 No conventional methods can be used as the scroll bar might not be present 26293 AND the section might not be active if it is auto-height and didnt reach the middle 26294 of the viewport. 26295 */ 26296 previousDestTop = position; 26297 return position; 26298 } 26299 26300 /** 26301 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 26302 */ 26303 function scrollPage(element, callback, isMovementUp){ 26304 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 26305 26306 var dtop = getDestinationPosition(element); 26307 var slideAnchorLink; 26308 var slideIndex; 26309 26310 //local variables 26311 var v = { 26312 element: element, 26313 callback: callback, 26314 isMovementUp: isMovementUp, 26315 dtop: dtop, 26316 yMovement: getYmovement(element), 26317 anchorLink: element.data('anchor'), 26318 sectionIndex: element.index(SECTION_SEL), 26319 activeSlide: element.find(SLIDE_ACTIVE_SEL), 26320 activeSection: $(SECTION_ACTIVE_SEL), 26321 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 26322 26323 //caching the value of isResizing at the momment the function is called 26324 //because it will be checked later inside a setTimeout and the value might change 26325 localIsResizing: isResizing 26326 }; 26327 26328 //quiting when destination scroll is the same as the current one 26329 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 26330 26331 if(v.activeSlide.length){ 26332 slideAnchorLink = v.activeSlide.data('anchor'); 26333 slideIndex = v.activeSlide.index(); 26334 } 26335 26336 // If continuousVertical && we need to wrap around 26337 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 26338 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 26339 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 26340 26341 v = createInfiniteSections(v); 26342 } 26343 26344 //callback (onLeave) if the site is not just resizing and readjusting the slides 26345 if($.isFunction(options.onLeave) && !v.localIsResizing){ 26346 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 26347 return; 26348 } 26349 } 26350 26351 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 26352 if(!v.localIsResizing){ 26353 stopMedia(v.activeSection); 26354 } 26355 26356 options.scrollOverflowHandler.beforeLeave(); 26357 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 26358 lazyLoad(element); 26359 options.scrollOverflowHandler.onLeave(); 26360 26361 26362 //preventing from activating the MouseWheelHandler event 26363 //more than once if the page is scrolling 26364 canScroll = false;
26365 26366 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 26367 26368 performMovement(v); 26369 26370 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 26371 lastScrolledDestiny = v.anchorLink; 26372 26373 //avoid firing it twice (as it does also on scroll) 26374 activateMenuAndNav(v.anchorLink, v.sectionIndex); 26375 } 26376 26377 /** 26378 * Performs the vertical movement (by CSS3 or by jQuery) 26379 */ 26380 function performMovement(v){ 26381 // using CSS3 translate functionality 26382 if (options.css3 && options.autoScrolling && !options.scrollBar) { 26383 26384 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 26385 // that's why we round it to 0. 26386 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 26387 transformContainer(translate3d, true); 26388 26389 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 26390 //scrollingSpeed to change in case of using silentMoveTo(); 26391 if(options.scrollingSpeed){ 26392 clearTimeout(afterSectionLoadsId); 26393 afterSectionLoadsId = setTimeout(function () { 26394 afterSectionLoads(v); 26395 }, options.scrollingSpeed); 26396 }else{ 26397 afterSectionLoads(v); 26398 } 26399 } 26400 26401 // using jQuery animate 26402 else{ 26403 var scrollSettings = getScrollSettings(v); 26404 26405 $(scrollSettings.element).animate( 26406 scrollSettings.options, 26407 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 26408 if(options.scrollBar){ 26409 26410 /* Hack! 26411 The timeout prevents setting the most dominant section in the viewport as "active" when the user 26412 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 26413 26414 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 26415 */ 26416 setTimeout(function(){ 26417 afterSectionLoads(v); 26418 },30); 26419 }else{ 26420 afterSectionLoads(v); 26421 } 26422 }); 26423 } 26424 } 26425 26426 /** 26427 * Gets the scrolling settings depending on the plugin autoScrolling option 26428 */ 26429 function getScrollSettings(v){ 26430 var scroll = {}; 26431 26432 if(options.autoScrolling && !options.scrollBar){ 26433 scroll.options = { 'top': -v.dtop}; 26434 scroll.element = WRAPPER_SEL; 26435 }else{ 26436 scroll.options = { 'scrollTop': v.dtop}; 26437 scroll.element = 'html, body'; 26438 } 26439 26440 return scroll; 26441 } 26442 26443 /** 26444 * Adds sections before or after the current one to create the infinite effect. 26445 */ 26446 function createInfiniteSections(v){ 26447 // Scrolling down 26448 if (!v.isMovementUp) { 26449 // Move all previous sections to after the active section 26450 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 26451 } 26452 else { // Scrolling up 26453 // Move all next sections to before the active section 26454 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 26455 } 26456 26457 // Maintain the displayed position (now that we changed the element order) 26458 silentScroll($(SECTION_ACTIVE_SEL).position().top); 26459 26460 // Maintain the active slides visible in the viewport 26461 keepSlidesPosition(); 26462 26463 // save for later the elements that still need to be reordered 26464 v.wrapAroundElements = v.activeSection; 26465 26466 // Recalculate animation variables 26467 v.dtop = v.element.position().top; 26468 v.yMovement = getYmovement(v.element); 26469 26470 return v; 26471 } 26472 26473 /** 26474 * Fix section order after continuousVertical changes have been animated 26475 */ 26476 function continuousVerticalFixSectionOrder (v) {
26477 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 26478 // finish moving the elements around so the direct navigation will function more simply 26479 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 26480 return; 26481 } 26482 26483 if (v.isMovementUp) { 26484 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 26485 } 26486 else { 26487 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 26488 } 26489 26490 silentScroll($(SECTION_ACTIVE_SEL).position().top); 26491 26492 // Maintain the active slides visible in the viewport 26493 keepSlidesPosition(); 26494 } 26495 26496 26497 /** 26498 * Actions to do once the section is loaded. 26499 */ 26500 function afterSectionLoads (v){ 26501 continuousVerticalFixSectionOrder(v); 26502 26503 //callback (afterLoad) if the site is not just resizing and readjusting the slides 26504 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 26505 options.scrollOverflowHandler.afterLoad(); 26506 26507 if(!v.localIsResizing){ 26508 playMedia(v.element); 26509 } 26510 26511 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 26512 26513 canScroll = true; 26514 26515 $.isFunction(v.callback) && v.callback.call(this); 26516 } 26517 26518 /** 26519 * Sets the value for the given attribute from the `data-` attribute with the same suffix 26520 * ie: data-srcset ==> srcset | data-src ==> src 26521 */ 26522 function setSrc(element, attribute){ 26523 element 26524 .attr(attribute, element.data(attribute)) 26525 .removeAttr('data-' + attribute); 26526 } 26527 26528 /** 26529 * Lazy loads image, video and audio elements. 26530 */ 26531 function lazyLoad(destiny){ 26532 if (!options.lazyLoading){ 26533 return; 26534 } 26535 26536 var panel = getSlideOrSection(destiny); 26537 var element; 26538 26539 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 26540 element = $(this); 26541 26542 $.each(['src', 'srcset'], function(index, type){ 26543 var attribute = element.attr('data-' + type); 26544 if(typeof attribute !== 'undefined' && attribute){ 26545 setSrc(element, type); 26546 } 26547 }); 26548 26549 if(element.is('source')){ 26550 element.closest('video').get(0).load(); 26551 } 26552 }); 26553 } 26554 26555 /** 26556 * Plays video and audio elements. 26557 */ 26558 function playMedia(destiny){ 26559 var panel = getSlideOrSection(destiny); 26560 26561 //playing HTML5 media elements 26562 panel.find('video, audio').each(function(){ 26563 var element = $(this).get(0); 26564 26565 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 26566 element.play(); 26567 } 26568 }); 26569 26570 //youtube videos 26571 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 26572 var element = $(this).get(0); 26573 26574 if ( element.hasAttribute('data-autoplay') ){ 26575 playYoutube(element); 26576 } 26577 26578 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 26579 element.onload = function() { 26580 if ( element.hasAttribute('data-autoplay') ){ 26581 playYoutube(element); 26582 } 26583 }; 26584 }); 26585 } 26586 26587 /** 26588 * Plays a youtube video 26589 */ 26590 function playYoutube(element){ 26591 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 26592 } 26593 26594 /** 26595 * Stops video and audio elements. 26596 */ 26597 function stopMedia(destiny){ 26598 var panel = getSlideOrSection(destiny); 26599 26600 //stopping HTML5 media elements 26601 panel.find('video, audio').each(function(){ 26602 var element = $(this).get(0); 26603 26604 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 26605 element.pause(); 26606 } 26607 }); 26608 26609 //youtube videos 26610 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 26611 var element = $(this).get(0); 26612 26613 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 26614 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 26615 } 26616 }); 26617 } 26618 26619 /** 26620 * Gets the active slide (or section) for the given section 26621 */ 26622 function getSlideOrSection(destiny){ 26623 var slide = destiny.find(SLIDE_ACTIVE_SEL); 26624 if( slide.length ) { 26625 destiny = $(slide); 26626 } 26627 26628 return destiny; 26629 } 26630 26631 /**
26632 * Scrolls to the anchor in the URL when loading the site 26633 */ 26634 function scrollToAnchor(){ 26635 //getting the anchor link in the URL and deleting the `#` 26636 var value = window.location.hash.replace('#', '').split('/'); 26637 var sectionAnchor = decodeURIComponent(value[0]); 26638 var slideAnchor = decodeURIComponent(value[1]); 26639 26640 if(sectionAnchor){ //if theres any # 26641 if(options.animateAnchor){ 26642 scrollPageAndSlide(sectionAnchor, slideAnchor); 26643 }else{ 26644 silentMoveTo(sectionAnchor, slideAnchor); 26645 } 26646 } 26647 } 26648 26649 /** 26650 * Detecting any change on the URL to scroll to the given anchor link 26651 * (a way to detect back history button as we play with the hashes on the URL) 26652 */ 26653 function hashChangeHandler(){ 26654 if(!isScrolling && !options.lockAnchors){ 26655 var value = window.location.hash.replace('#', '').split('/'); 26656 var sectionAnchor = decodeURIComponent(value[0]); 26657 var slideAnchor = decodeURIComponent(value[1]); 26658 26659 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 26660 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 26661 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 26662 26663 26664 if(sectionAnchor.length){ 26665 /*in order to call scrollpage() only once for each destination at a time 26666 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 26667 event is fired on every scroll too.*/ 26668 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 26669 scrollPageAndSlide(sectionAnchor, slideAnchor); 26670 } 26671 } 26672 } 26673 } 26674 26675 //Sliding with arrow keys, both, vertical and horizontal 26676 function keydownHandler(e) { 26677 26678 clearTimeout(keydownId); 26679 26680 var activeElement = $(':focus'); 26681 26682 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 26683 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 26684 options.keyboardScrolling && options.autoScrolling){ 26685 var keyCode = e.which; 26686 26687 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 26688 var keyControls = [40, 38, 32, 33, 34]; 26689 if($.inArray(keyCode, keyControls) > -1){ 26690 e.preventDefault(); 26691 } 26692 26693 controlPressed = e.ctrlKey; 26694 26695 keydownId = setTimeout(function(){ 26696 onkeydown(e); 26697 },150); 26698 } 26699 } 26700 26701 function tooltipTextHandler(){ 26702 $(this).prev().trigger('click'); 26703 } 26704 26705 //to prevent scrolling while zooming 26706 function keyUpHandler(e){ 26707 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 26708 controlPressed = e.ctrlKey; 26709 } 26710 } 26711 26712 //binding the mousemove when the mouse's middle button is released 26713 function mouseDownHandler(e){ 26714 //middle button 26715 if (e.which == 2){ 26716 oldPageY = e.pageY; 26717 container.on('mousemove', mouseMoveHandler); 26718 } 26719 } 26720 26721 //unbinding the mousemove when the mouse's middle button is released 26722 function mouseUpHandler(e){ 26723 //middle button 26724 if (e.which == 2){ 26725 container.off('mousemove'); 26726 } 26727 } 26728 26729 //Scrolling horizontally when clicking on the slider controls. 26730 function slideArrowHandler(){ 26731 var section = $(this).closest(SECTION_SEL); 26732 26733 if ($(this).hasClass(SLIDES_PREV)) { 26734 if(isScrollAllowed.m.left){ 26735 moveSlideLeft(section); 26736 } 26737 } else { 26738 if(isScrollAllowed.m.right){ 26739 moveSlideRight(section); 26740 } 26741 } 26742 } 26743 26744 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 26745 function blurHandler(){ 26746 isWindowFocused = false;
26747 controlPressed = false; 26748 } 26749 26750 //Scrolls to the section when clicking the navigation bullet 26751 function sectionBulletHandler(e){ 26752 e.preventDefault(); 26753 var index = $(this).parent().index(); 26754 scrollPage($(SECTION_SEL).eq(index)); 26755 } 26756 26757 //Scrolls the slider to the given slide destination for the given section 26758 function slideBulletHandler(e){ 26759 e.preventDefault(); 26760 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 26761 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 26762 26763 landscapeScroll(slides, destiny); 26764 } 26765 26766 /** 26767 * Keydown event 26768 */ 26769 function onkeydown(e){ 26770 var shiftPressed = e.shiftKey; 26771 26772 //do nothing if we can not scroll or we are not using horizotnal key arrows. 26773 if(!canScroll && [37,39].indexOf(e.which) < 0){ 26774 return; 26775 } 26776 26777 switch (e.which) { 26778 //up 26779 case 38: 26780 case 33: 26781 if(isScrollAllowed.k.up){ 26782 moveSectionUp(); 26783 } 26784 break; 26785 26786 //down 26787 case 32: //spacebar 26788 if(shiftPressed && isScrollAllowed.k.up){ 26789 moveSectionUp(); 26790 break; 26791 } 26792 /* falls through */ 26793 case 40: 26794 case 34: 26795 if(isScrollAllowed.k.down){ 26796 moveSectionDown(); 26797 } 26798 break; 26799 26800 //Home 26801 case 36: 26802 if(isScrollAllowed.k.up){ 26803 moveTo(1); 26804 } 26805 break; 26806 26807 //End 26808 case 35: 26809 if(isScrollAllowed.k.down){ 26810 moveTo( $(SECTION_SEL).length ); 26811 } 26812 break; 26813 26814 //left 26815 case 37: 26816 if(isScrollAllowed.k.left){ 26817 moveSlideLeft(); 26818 } 26819 break; 26820 26821 //right 26822 case 39: 26823 if(isScrollAllowed.k.right){ 26824 moveSlideRight(); 26825 } 26826 break; 26827 26828 default: 26829 return; // exit this handler for other keys 26830 } 26831 } 26832 26833 /** 26834 * Detecting the direction of the mouse movement. 26835 * Used only for the middle button of the mouse. 26836 */ 26837 var oldPageY = 0; 26838 function mouseMoveHandler(e){ 26839 if(canScroll){ 26840 // moving up 26841 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 26842 moveSectionUp(); 26843 } 26844 26845 // moving down 26846 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 26847 moveSectionDown(); 26848 } 26849 } 26850 oldPageY = e.pageY; 26851 } 26852 26853 /** 26854 * Scrolls horizontal sliders. 26855 */ 26856 function landscapeScroll(slides, destiny, direction){ 26857 var section = slides.closest(SECTION_SEL); 26858 var v = { 26859 slides: slides, 26860 destiny: destiny, 26861 direction: direction, 26862 destinyPos: destiny.position(), 26863 slideIndex: destiny.index(), 26864 section: section, 26865 sectionIndex: section.index(SECTION_SEL), 26866 anchorLink: section.data('anchor'), 26867 slidesNav: section.find(SLIDES_NAV_SEL), 26868 slideAnchor: getAnchor(destiny), 26869 prevSlide: section.find(SLIDE_ACTIVE_SEL), 26870 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 26871 26872 //caching the value of isResizing at the momment the function is called 26873 //because it will be checked later inside a setTimeout and the value might change 26874 localIsResizing: isResizing 26875 }; 26876 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 26877 v.direction = v.direction ? v.direction : v.xMovement; 26878 26879 //important!! Only do it when not resizing 26880 if(!v.localIsResizing){ 26881 //preventing from scrolling to the next/prev section when using scrollHorizontally 26882 canScroll = false;
26883 } 26884 26885 if(options.onSlideLeave){ 26886 26887 //if the site is not just resizing and readjusting the slides 26888 if(!v.localIsResizing && v.xMovement!=='none'){ 26889 if($.isFunction( options.onSlideLeave )){ 26890 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 26891 slideMoving = false; 26892 return; 26893 } 26894 } 26895 } 26896 } 26897 26898 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 26899 26900 if(!v.localIsResizing){ 26901 stopMedia(v.prevSlide); 26902 lazyLoad(destiny); 26903 } 26904 26905 if(!options.loopHorizontal && options.controlArrows){ 26906 //hidding it for the fist slide, showing for the rest 26907 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 26908 26909 //hidding it for the last slide, showing for the rest 26910 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 26911 } 26912 26913 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 26914 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 26915 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 26916 } 26917 26918 performHorizontalMove(slides, v, true); 26919 } 26920 26921 26922 function afterSlideLoads(v){ 26923 activeSlidesNavigation(v.slidesNav, v.slideIndex); 26924 26925 //if the site is not just resizing and readjusting the slides 26926 if(!v.localIsResizing){ 26927 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 26928 26929 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 26930 //and to prevent double scroll right after a windows resize 26931 canScroll = true; 26932 26933 playMedia(v.destiny); 26934 } 26935 26936 //letting them slide again 26937 slideMoving = false; 26938 } 26939 26940 /** 26941 * Performs the horizontal movement. (CSS3 or jQuery) 26942 * 26943 * @param fireCallback {Bool} - determines whether or not to fire the callback 26944 */ 26945 function performHorizontalMove(slides, v, fireCallback){ 26946 var destinyPos = v.destinyPos; 26947 26948 if(options.css3){ 26949 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 26950 26951 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 26952 26953 afterSlideLoadsId = setTimeout(function(){ 26954 fireCallback && afterSlideLoads(v); 26955 }, options.scrollingSpeed, options.easing); 26956 }else{ 26957 slides.animate({ 26958 scrollLeft : Math.round(destinyPos.left) 26959 }, options.scrollingSpeed, options.easing, function() { 26960 26961 fireCallback && afterSlideLoads(v); 26962 }); 26963 } 26964 } 26965 26966 /** 26967 * Sets the state for the horizontal bullet navigations. 26968 */ 26969 function activeSlidesNavigation(slidesNav, slideIndex){ 26970 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 26971 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 26972 } 26973 26974 var previousHeight = windowsHeight; 26975 26976 //when resizing the site, we adjust the heights of the sections, slimScroll... 26977 function resizeHandler(){ 26978 //checking if it needs to get responsive 26979 responsive(); 26980 26981 // rebuild immediately on touch devices 26982 if (isTouchDevice) { 26983 var activeElement = $(document.activeElement); 26984 26985 //if the keyboard is NOT visible 26986 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 26987 var currentHeight = $window.height(); 26988 26989 //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) 26990 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 26991 reBuild(true); 26992 previousHeight = currentHeight; 26993 } 26994 } 26995 }else{ 26996 //in order to call the functions only when the resize is finished 26997 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 26998 clearTimeout(resizeId); 26999 27000 resizeId = setTimeout(function(){ 27001 reBuild(true); 27002 }, 350); 27003 } 27004 } 27005 27006 /** 27007 * Checks if the site needs to get responsive and disables autoScrolling if so. 27008 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 27009 */ 27010 function responsive(){ 27011 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 27012 var heightLimit = options.responsiveHeight; 27013 27014 //only calculating what we need. Remember its called on the resize event. 27015 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 27016 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 27017 27018 if(widthLimit && heightLimit){ 27019 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 27020 } 27021 else if(widthLimit){ 27022 setResponsive(isBreakingPointWidth); 27023 } 27024 else if(heightLimit){ 27025 setResponsive(isBreakingPointHeight); 27026 } 27027 } 27028 27029 /** 27030 * Adds transition animations for the given element 27031 */ 27032 function addAnimation(container, element){ 27033 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 27034 27035 container.removeClass(NO_TRANSITION); 27036 return container.css({
27037 '-webkit-transition': transition, 27038 'transition': transition 27039 }); 27040 } 27041 27042 /** 27043 * Remove transition animations for the given element 27044 */ 27045 function removeAnimation(element){ 27046 return element.addClass(NO_TRANSITION); 27047 } 27048 27049 /** 27050 * Activating the vertical navigation bullets according to the given slide name. 27051 */ 27052 function activateNavDots(name, sectionIndex){ 27053 if(options.navigation){ 27054 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 27055 if(name){ 27056 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 27057 }else{ 27058 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 27059 } 27060 } 27061 } 27062 27063 /** 27064 * Activating the website main menu elements according to the given slide name. 27065 */ 27066 function activateMenuElement(name){ 27067 if(options.menu){ 27068 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 27069 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 27070 } 27071 } 27072 27073 /** 27074 * Sets to active the current menu and vertical nav items. 27075 */ 27076 function activateMenuAndNav(anchor, index){ 27077 activateMenuElement(anchor); 27078 activateNavDots(anchor, index); 27079 } 27080 27081 /** 27082 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 27083 * from the current section. 27084 */ 27085 function getYmovement(destiny){ 27086 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 27087 var toIndex = destiny.index(SECTION_SEL); 27088 if( fromIndex == toIndex){ 27089 return 'none'; 27090 } 27091 if(fromIndex > toIndex){ 27092 return 'up'; 27093 } 27094 return 'down'; 27095 } 27096 27097 /** 27098 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 27099 * from the current slide. 27100 */ 27101 function getXmovement(fromIndex, toIndex){ 27102 if( fromIndex == toIndex){ 27103 return 'none'; 27104 } 27105 if(fromIndex > toIndex){ 27106 return 'left'; 27107 } 27108 return 'right'; 27109 } 27110 27111 /** 27112 * Checks if the element needs scrollbar and if the user wants to apply it. 27113 * If so it creates it. 27114 * 27115 * @param {Object} element jQuery object of the section or slide 27116 */ 27117 function createScrollBar(element){ 27118 //User doesn't want scrollbar here? Sayonara baby! 27119 if(element.hasClass('fp-noscroll')) return; 27120 27121 //needed to make `scrollHeight` work under Opera 12 27122 element.css('overflow', 'hidden'); 27123 27124 var scrollOverflowHandler = options.scrollOverflowHandler; 27125 var wrap = scrollOverflowHandler.wrapContent(); 27126 //in case element is a slide 27127 var section = element.closest(SECTION_SEL); 27128 var scrollable = scrollOverflowHandler.scrollable(element); 27129 var contentHeight; 27130 27131 //if there was scroll, the contentHeight will be the one in the scrollable section 27132 if(scrollable.length){ 27133 contentHeight = scrollOverflowHandler.scrollHeight(element); 27134 }else{ 27135 contentHeight = element.get(0).scrollHeight; 27136 if(options.verticalCentered){ 27137 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 27138 } 27139 } 27140 27141 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 27142 27143 //needs scroll? 27144 if ( contentHeight > scrollHeight) { 27145 //did we already have an scrollbar ? Updating it 27146 if(scrollable.length){ 27147 scrollOverflowHandler.update(element, scrollHeight); 27148 } 27149 //creating the scrolling 27150 else{ 27151 if(options.verticalCentered){ 27152 element.find(TABLE_CELL_SEL).wrapInner(wrap); 27153 }else{ 27154 element.wrapInner(wrap); 27155 } 27156 scrollOverflowHandler.create(element, scrollHeight); 27157 } 27158 } 27159 //removing the scrolling when it is not necessary anymore 27160 else{ 27161 scrollOverflowHandler.remove(element); 27162 } 27163 27164 //undo 27165 element.css('overflow', ''); 27166 } 27167 27168 function addTableClass(element){ 27169 //In case we are styling for the 2nd time as in with reponsiveSlides 27170 if(!element.hasClass(TABLE)){ 27171 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 27172 } 27173 } 27174 27175 function getTableHeight(element){ 27176 var sectionHeight = windowsHeight; 27177 27178 if(options.paddingTop || options.paddingBottom){ 27179 var section = element; 27180 if(!section.hasClass(SECTION)){ 27181 section = element.closest(SECTION_SEL); 27182 } 27183 27184 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 27185 sectionHeight = (windowsHeight - paddings); 27186 } 27187 27188 return sectionHeight; 27189 } 27190 27191 /** 27192 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 27193 */ 27194 function transformContainer(translate3d, animated){ 27195 if(animated){ 27196 addAnimation(container); 27197 }else{ 27198 removeAnimation(container); 27199 } 27200 27201 container.css(getTransforms(translate3d)); 27202 27203 //syncronously removing the class after the animation has been applied. 27204 setTimeout(function(){ 27205 container.removeClass(NO_TRANSITION); 27206 },10); 27207 } 27208 27209 /** 27210 * Gets a section by its anchor / index 27211 */ 27212 function getSectionByAnchor(sectionAnchor){ 27213 if(!sectionAnchor) return []; 27214 27215 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 27216 if(!section.length){ 27217 section = $(SECTION_SEL).eq( sectionAnchor -1); 27218 } 27219 27220 return section; 27221 } 27222 27223 /** 27224 * Gets a slide inside a given section by its anchor / index 27225 */ 27226 function getSlideByAnchor(slideAnchor, section){ 27227 var slides = section.find(SLIDES_WRAPPER_SEL); 27228 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 27229
27230 if(!slide.length){ 27231 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 27232 } 27233 27234 return slide; 27235 } 27236 27237 /** 27238 * Scrolls to the given section and slide anchors 27239 */ 27240 function scrollPageAndSlide(destiny, slide){ 27241 var section = getSectionByAnchor(destiny); 27242 27243 //do nothing if there's no section with the given anchor name 27244 if(!section.length) return; 27245 27246 //default slide 27247 if (typeof slide === 'undefined') { 27248 slide = 0; 27249 } 27250 27251 //we need to scroll to the section and then to the slide 27252 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 27253 scrollPage(section, function(){ 27254 scrollSlider(section, slide); 27255 }); 27256 } 27257 //if we were already in the section 27258 else{ 27259 scrollSlider(section, slide); 27260 } 27261 } 27262 27263 /** 27264 * Scrolls the slider to the given slide destination for the given section 27265 */ 27266 function scrollSlider(section, slideAnchor){ 27267 if(typeof slideAnchor !== 'undefined'){ 27268 var slides = section.find(SLIDES_WRAPPER_SEL); 27269 var destiny = getSlideByAnchor(slideAnchor, section); 27270 27271 if(destiny.length){ 27272 landscapeScroll(slides, destiny); 27273 } 27274 } 27275 } 27276 27277 /** 27278 * Creates a landscape navigation bar with dots for horizontal sliders. 27279 */ 27280 function addSlidesNavigation(section, numSlides){ 27281 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 27282 var nav = section.find(SLIDES_NAV_SEL); 27283 27284 //top or bottom 27285 nav.addClass(options.slidesNavPosition); 27286 27287 for(var i=0; i< numSlides; i++){ 27288 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 27289 } 27290 27291 //centering it 27292 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 27293 27294 nav.find('li').first().find('a').addClass(ACTIVE); 27295 } 27296 27297 27298 /** 27299 * Sets the state of the website depending on the active section/slide. 27300 * It changes the URL hash when needed and updates the body class. 27301 */ 27302 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 27303 var sectionHash = ''; 27304 27305 if(options.anchors.length && !options.lockAnchors){ 27306 27307 //isn't it the first slide? 27308 if(slideIndex){ 27309 if(typeof anchorLink !== 'undefined'){ 27310 sectionHash = anchorLink; 27311 } 27312 27313 //slide without anchor link? We take the index instead. 27314 if(typeof slideAnchor === 'undefined'){ 27315 slideAnchor = slideIndex; 27316 } 27317 27318 lastScrolledSlide = slideAnchor; 27319 setUrlHash(sectionHash + '/' + slideAnchor); 27320 27321 //first slide won't have slide anchor, just the section one 27322 }else if(typeof slideIndex !== 'undefined'){ 27323 lastScrolledSlide = slideAnchor; 27324 setUrlHash(anchorLink); 27325 } 27326 27327 //section without slides 27328 else{ 27329 setUrlHash(anchorLink); 27330 } 27331 } 27332 27333 setBodyClass(); 27334 } 27335 27336 /** 27337 * Sets the URL hash. 27338 */ 27339 function setUrlHash(url){ 27340 //Uncode addition 27341 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 27342 return false; 27343 27344 if(options.recordHistory){ 27345 location.hash = url; 27346 }else{ 27347 //Uncode addition 27348 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 27349 // if(isTouchDevice || isTouch){ 27350 // window.history.replaceState(undefined, undefined, '#' + url); 27351 // }else{ 27352 // var baseUrl = window.location.href.split('#')[0]; 27353 // window.location.replace( baseUrl + '#' + url ); 27354 // } 27355 return false;
27356 } 27357 } 27358 27359 /** 27360 * Gets the anchor for the given slide / section. Its index will be used if there's none. 27361 */ 27362 function getAnchor(element){ 27363 var anchor = element.data('anchor'); 27364 var index = element.index(); 27365 27366 //Slide without anchor link? We take the index instead. 27367 if(typeof anchor === 'undefined'){ 27368 anchor = index; 27369 } 27370 27371 return anchor; 27372 } 27373 27374 /** 27375 * Sets a class for the body of the page depending on the active section / slide 27376 */ 27377 function setBodyClass(){ 27378 var section = $(SECTION_ACTIVE_SEL); 27379 var slide = section.find(SLIDE_ACTIVE_SEL); 27380 27381 var sectionAnchor = getAnchor(section); 27382 var slideAnchor = getAnchor(slide); 27383 27384 var text = String(sectionAnchor); 27385 27386 if(slide.length){ 27387 text = text + '-' + slideAnchor; 27388 } 27389 27390 //changing slash for dash to make it a valid CSS style 27391 text = text.replace('/', '-').replace('#',''); 27392 27393 //removing previous anchor classes 27394 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 27395 $body[0].className = $body[0].className.replace(classRe, ''); 27396 27397 //adding the current anchor 27398 $body.addClass(VIEWING_PREFIX + '-' + text); 27399 } 27400 27401 /** 27402 * Checks for translate3d support 27403 * @return boolean 27404 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 27405 */ 27406 function support3d() { 27407 var el = document.createElement('p'), 27408 has3d, 27409 transforms = { 27410 'webkitTransform':'-webkit-transform', 27411 'OTransform':'-o-transform', 27412 'msTransform':'-ms-transform', 27413 'MozTransform':'-moz-transform', 27414 'transform':'transform' 27415 }; 27416 27417 // Add it to the body to get the computed style. 27418 document.body.insertBefore(el, null); 27419 27420 for (var t in transforms) { 27421 if (el.style[t] !== undefined) { 27422 el.style[t] = 'translate3d(1px,1px,1px)'; 27423 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 27424 } 27425 } 27426 27427 document.body.removeChild(el); 27428 27429 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 27430 } 27431 27432 /** 27433 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 27434 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 27435 */ 27436 function removeMouseWheelHandler(){ 27437 if (document.addEventListener) { 27438 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 27439 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 27440 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 27441 } else { 27442 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 27443 } 27444 } 27445 27446 /** 27447 * Adds the auto scrolling action for the mouse wheel and trackpad. 27448 * After this function is called, the mousewheel and trackpad movements will scroll through sections 27449 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 27450 */ 27451 function addMouseWheelHandler(){ 27452 var prefix = ''; 27453 var _addEventListener; 27454 27455 if (window.addEventListener){ 27456 _addEventListener = "addEventListener"; 27457 }else{ 27458 _addEventListener = "attachEvent"; 27459 prefix = 'on'; 27460 } 27461 27462 // detect available wheel event 27463 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 27464 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 27465 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 27466 var passiveEvent = g_supportsPassive ? {passive: false }
27466: false; 27467 27468 27469 if(support == 'DOMMouseScroll'){ 27470 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent); 27471 } 27472 27473 //handle MozMousePixelScroll in older Firefox 27474 else{ 27475 document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent); 27476 } 27477 } 27478 27479 /** 27480 * Binding the mousemove when the mouse's middle button is pressed 27481 */ 27482 function addMiddleWheelHandler(){ 27483 container 27484 .on('mousedown', mouseDownHandler) 27485 .on('mouseup', mouseUpHandler); 27486 } 27487 27488 /** 27489 * Unbinding the mousemove when the mouse's middle button is released 27490 */ 27491 function removeMiddleWheelHandler(){ 27492 container 27493 .off('mousedown', mouseDownHandler) 27494 .off('mouseup', mouseUpHandler); 27495 } 27496 27497 /** 27498 * Adds the possibility to auto scroll through sections on touch devices. 27499 */ 27500 function addTouchHandler(){ 27501 if(isTouchDevice || isTouch){ 27502 if(options.autoScrolling){ 27503 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 27504 } 27505 27506 $(WRAPPER_SEL) 27507 .off(events.touchstart).on(events.touchstart, touchStartHandler) 27508 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 27509 } 27510 } 27511 27512 /** 27513 * Removes the auto scrolling for touch devices. 27514 */ 27515 function removeTouchHandler(){ 27516 if(isTouchDevice || isTouch){ 27517 $(WRAPPER_SEL) 27518 .off(events.touchstart) 27519 .off(events.touchmove); 27520 } 27521 } 27522 27523 /* 27524 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11) 27525 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 27526 */ 27527 function getMSPointer(){ 27528 var pointer; 27529 27530 //IE >= 11 & rest of browsers 27531 if(window.PointerEvent){ 27532 pointer = { down: 'pointerdown', move: 'pointermove'}; 27533 } 27534 27535 //IE < 11 27536 else{ 27537 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 27538 } 27539 27540 return pointer; 27541 } 27542 27543 /** 27544 * Gets the pageX and pageY properties depending on the browser. 27545 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 27546 */ 27547 function getEventsPage(e){ 27548 var events = []; 27549 27550 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 27551 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 27552 27553 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 27554 if(isTouch && isReallyTouch(e) && options.scrollBar){ 27555 events.y = e.touches[0].pageY; 27556 events.x = e.touches[0].pageX; 27557 } 27558 27559 return events; 27560 } 27561 27562 /** 27563 * Slides silently (with no animation) the active slider to the given slide. 27564 * @param noCallback {bool} true or defined -> no callbacks 27565 */ 27566 function silentLandscapeScroll(activeSlide, noCallbacks){ 27567 setScrollingSpeed (0, 'internal'); 27568 27569 if(typeof noCallbacks !== 'undefined'){ 27570 //preventing firing callbacks afterSlideLoad etc. 27571 isResizing = true; 27572 } 27573 27574 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 27575 27576 if(typeof noCallbacks !== 'undefined'){ 27577 isResizing = false; 27578 } 27579 27580 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 27581 } 27582 27583 /** 27584 * Scrolls silently (with no animation) the page to the given Y position. 27585 */ 27586 function silentScroll(top){ 27587 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 27588 // that's why we round it to 0. 27589 var roundedTop = Math.round(top); 27590 27591 if (options.css3 && options.autoScrolling && !options.scrollBar){ 27592 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 27593 transformContainer(translate3d, false); 27594 } 27595 else if(options.autoScrolling && !options.scrollBar){ 27596 container.css('top', -roundedTop); 27597 } 27598 else{ 27599 $htmlBody.scrollTop(roundedTop); 27600 } 27601 } 27602 27603 /** 27604 * Returns the cross-browser transform string. 27605 */ 27606 function getTransforms(translate3d){ 27607 return {
27608 '-webkit-transform': translate3d, 27609 '-moz-transform': translate3d, 27610 '-ms-transform':translate3d, 27611 'transform': translate3d 27612 }; 27613 } 27614 27615 /** 27616 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 27617 * @type m (mouse) or k (keyboard) 27618 */ 27619 function setIsScrollAllowed(value, direction, type){ 27620 switch (direction){ 27621 case 'up': isScrollAllowed[type].up = value; break; 27622 case 'down': isScrollAllowed[type].down = value; break; 27623 case 'left': isScrollAllowed[type].left = value; break; 27624 case 'right': isScrollAllowed[type].right = value; break; 27625 case 'all': 27626 if(type == 'm'){ 27627 setAllowScrolling(value); 27628 }else{ 27629 setKeyboardScrolling(value); 27630 } 27631 } 27632 } 27633 27634 /* 27635 * Destroys fullpage.js plugin events and optinally its html markup and styles 27636 */ 27637 function destroy(all){ 27638 setAutoScrolling(false, 'internal'); 27639 setAllowScrolling(false); 27640 setKeyboardScrolling(false); 27641 container.addClass(DESTROYED); 27642 27643 clearTimeout(afterSlideLoadsId); 27644 clearTimeout(afterSectionLoadsId); 27645 clearTimeout(resizeId); 27646 clearTimeout(scrollId); 27647 clearTimeout(scrollId2); 27648 27649 $window 27650 .off('scroll', scrollHandler) 27651 .off('hashchange', hashChangeHandler) 27652 .off('resize', resizeHandler); 27653 27654 $document 27655 .off('click touchstart', SECTION_NAV_SEL + ' a') 27656 .off('mouseenter', SECTION_NAV_SEL + ' li') 27657 .off('mouseleave', SECTION_NAV_SEL + ' li') 27658 .off('click touchstart', SLIDES_NAV_LINK_SEL) 27659 .off('mouseover', options.normalScrollElements) 27660 .off('mouseout', options.normalScrollElements); 27661 27662 $(SECTION_SEL) 27663 .off('click touchstart', SLIDES_ARROW_SEL); 27664 27665 clearTimeout(afterSlideLoadsId); 27666 clearTimeout(afterSectionLoadsId); 27667 27668 //lets make a mess! 27669 if(all){ 27670 destroyStructure(); 27671 } 27672 } 27673 27674 /* 27675 * Removes inline styles added by fullpage.js 27676 */ 27677 function destroyStructure(){ 27678 //reseting the `top` or `translate` properties to 0 27679 silentScroll(0); 27680 27681 //loading all the lazy load content 27682 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 27683 setSrc($(this), 'src'); 27684 }); 27685 27686 container.find('img[data-srcset]').each(function(){ 27687 setSrc($(this), 'srcset'); 27688 }); 27689 27690 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 27691 27692 //removing inline styles 27693 $(SECTION_SEL).css( { 27694 'height': '', 27695 'background-color' : '', 27696 'padding': '' 27697 }); 27698 27699 $(SLIDE_SEL).css( { 27700 'width': '' 27701 }); 27702 27703 container.css({ 27704 'height': '', 27705 'position': '', 27706 '-ms-touch-action': '', 27707 'touch-action': '' 27708 }); 27709 27710 $htmlBody.css({ 27711 'overflow': '', 27712 'height': '' 27713 }); 27714 27715 // remove .fp-enabled class 27716 $('html').removeClass(ENABLED); 27717 27718 // remove .fp-responsive class 27719 $body.removeClass(RESPONSIVE); 27720 27721 // remove all of the .fp-viewing- classes 27722 $.each($body.get(0).className.split(/\s+/), function (index, className) { 27723 if (className.indexOf(VIEWING_PREFIX) === 0) { 27724 $body.removeClass(className); 27725 } 27726 }); 27727 27728 //removing added classes 27729 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 27730 options.scrollOverflowHandler.remove($(this)); 27731 $(this).removeClass(TABLE + ' ' + ACTIVE); 27732 }); 27733 27734 removeAnimation(container); 27735 27736 //Unwrapping content 27737 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 27738 //unwrap not being use in case there's no child element inside and its just text 27739 $(this).replaceWith(this.childNodes); 27740 }); 27741 27742 //removing the applied transition from the fullpage wrapper 27743 container.css({
27744 '-webkit-transition': 'none', 27745 'transition': 'none' 27746 }); 27747 27748 //scrolling the page to the top with no animation 27749 $htmlBody.scrollTop(0); 27750 27751 //removing selectors 27752 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 27753 $.each(usedSelectors, function(index, value){ 27754 $('.' + value).removeClass(value); 27755 }); 27756 } 27757 27758 /* 27759 * Sets the state for a variable with multiple states (original, and temporal) 27760 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 27761 * This function is used to keep track of both states, the original and the temporal one. 27762 * If type is not 'internal', then we assume the user is globally changing the variable. 27763 */ 27764 function setVariableState(variable, value, type){ 27765 options[variable] = value; 27766 if(type !== 'internal'){ 27767 originals[variable] = value; 27768 } 27769 } 27770 27771 /** 27772 * Displays warnings 27773 */ 27774 function displayWarnings(){ 27775 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 27776 //UNCODE.addition 27777 // if($('html').hasClass(ENABLED)){ 27778 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 27779 // return; 27780 // } 27781 27782 // Disable mutually exclusive settings 27783 //UNCODE.addition 27784 // if (options.continuousVertical && 27785 // (options.loopTop || options.loopBottom)) { 27786 // options.continuousVertical = false;
27787 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 27788 // } 27789 27790 // if(options.scrollBar && options.scrollOverflow){ 27791 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 27792 // } 27793 27794 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 27795 // options.continuousVertical = false; 27796 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 27797 // } 27798 27799 //using extensions? Wrong file! 27800 $.each(extensions, function(index, extension){ 27801 //is the option set to true? 27802 if(options[extension]){ 27803 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 27804 } 27805 }); 27806 27807 //anchors can not have the same value as any element ID or NAME 27808 $.each(options.anchors, function(index, name){ 27809 27810 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 27811 var nameAttr = $document.find('[name]').filter(function() { 27812 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 27813 }); 27814 27815 var idAttr = $document.find('[id]').filter(function() { 27816 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 27817 }); 27818 27819 if(idAttr.length || nameAttr.length ){ 27820 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 27821 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 27822 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 27823 } 27824 }); 27825 } 27826 27827 /** 27828 * Shows a message in the console of the given type. 27829 */ 27830 function showError(type, text){ 27831 console && console[type] && console[type]('fullPage: ' + text); 27832 } 27833 27834 }; //end of $.fn.fullpage 27835 27836 if(typeof IScroll !== 'undefined'){ 27837 /* 27838 * Turns iScroll `mousewheel` option off dynamically 27839 * https://github.com/cubiq/iscroll/issues/1036 27840 */ 27841 IScroll.prototype.wheelOn = function () { 27842 this.wrapper.addEventListener('wheel', this); 27843 this.wrapper.addEventListener('mousewheel', this); 27844 this.wrapper.addEventListener('DOMMouseScroll', this); 27845 }; 27846 27847 /* 27848 * Turns iScroll `mousewheel` option on dynamically 27849 * https://github.com/cubiq/iscroll/issues/1036 27850 */ 27851 IScroll.prototype.wheelOff = function () { 27852 this.wrapper.removeEventListener('wheel', this); 27853 this.wrapper.removeEventListener('mousewheel', this); 27854 this.wrapper.removeEventListener('DOMMouseScroll', this); 27855 }; 27856 } 27857 27858 /** 27859 * An object to handle overflow scrolling. 27860 * This uses jquery.slimScroll to accomplish overflow scrolling. 27861 * It is possible to pass in an alternate scrollOverflowHandler 27862 * to the fullpage.js option that implements the same functions 27863 * as this handler. 27864 * 27865 * @type {Object} 27866 */ 27867 var iscrollHandler = { 27868 refreshId: null, 27869 iScrollInstances: [], 27870 27871 // Enables or disables the mouse wheel for the active section or all slides in it 27872 toggleWheel: function(value){ 27873 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 27874 scrollable.each(function(){ 27875 var iScrollInstance = $(this).data('iscrollInstance'); 27876 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 27877 if(value){ 27878 iScrollInstance.wheelOn(); 27879 } 27880 else{ 27881 iScrollInstance.wheelOff(); 27882 } 27883 } 27884 }); 27885 }, 27886 27887 /** 27888 * Turns off iScroll for the destination section. 27889 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
27890 * scroll the destination section/slide before the sections animations ends. 27891 */ 27892 onLeave: function(){ 27893 iscrollHandler.toggleWheel(false); 27894 }, 27895 27896 // Turns off iScroll for the leaving section 27897 beforeLeave: function(){ 27898 iscrollHandler.onLeave() 27899 }, 27900 27901 // Turns on iScroll on section load 27902 afterLoad: function(){ 27903 iscrollHandler.toggleWheel(true); 27904 }, 27905 27906 /** 27907 * Called when overflow scrolling is needed for a section. 27908 * 27909 * @param {Object} element jQuery object containing current section 27910 * @param {Number} scrollHeight Current window height in pixels 27911 */ 27912 create: function(element, scrollHeight) { 27913 var scrollable = element.find(SCROLLABLE_SEL); 27914 27915 scrollable.height(scrollHeight); 27916 scrollable.each(function() { 27917 var $this = $(this); 27918 var iScrollInstance = $this.data('iscrollInstance'); 27919 if (iScrollInstance) { 27920 $.each(iscrollHandler.iScrollInstances, function(){ 27921 $(this).destroy(); 27922 }); 27923 } 27924 27925 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 27926 iscrollHandler.iScrollInstances.push(iScrollInstance); 27927 27928 //off by default until the section gets active 27929 iScrollInstance.wheelOff(); 27930 27931 $this.data('iscrollInstance', iScrollInstance); 27932 }); 27933 }, 27934 27935 /** 27936 * Return a boolean depending on whether the scrollable element is a 27937 * the end or at the start of the scrolling depending on the given type. 27938 * 27939 * @param {String} type Either 'top' or 'bottom' 27940 * @param {Object} scrollable jQuery object for the scrollable element 27941 * @return {Boolean} 27942 */ 27943 isScrolled: function(type, scrollable) { 27944 var scroller = scrollable.data('iscrollInstance'); 27945 27946 //no scroller? 27947 if (!scroller) { 27948 return true; 27949 } 27950 27951 if (type === 'top') { 27952 return scroller.y >= 0 && !scrollable.scrollTop(); 27953 } else if (type === 'bottom') { 27954 return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight; 27955 } 27956 }, 27957 27958 /** 27959 * Returns the scrollable element for the given section. 27960 * If there are landscape slides, will only return a scrollable element 27961 * if it is in the active slide. 27962 * 27963 * @param {Object} activeSection jQuery object containing current section 27964 * @return {Boolean} 27965 */ 27966 scrollable: function(activeSection){ 27967 // if there are landscape slides, we check if the scrolling bar is in the current one or not 27968 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 27969 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 27970 } 27971 return activeSection.find(SCROLLABLE_SEL); 27972 }, 27973 27974 /** 27975 * Returns the scroll height of the wrapped content. 27976 * If this is larger than the window height minus section padding, 27977 * overflow scrolling is needed. 27978 * 27979 * @param {Object} element jQuery object containing current section 27980 * @return {Number} 27981 */ 27982 scrollHeight: function(element) { 27983 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 27984 }, 27985 27986 /** 27987 * Called when overflow scrolling is no longer needed for a section. 27988 * 27989 * @param {Object} element jQuery object containing current section 27990 */ 27991 remove: function(element) { 27992 var scrollable = element.find(SCROLLABLE_SEL); 27993 if (scrollable.length) { 27994 var iScrollInstance = scrollable.data('iscrollInstance'); 27995 iScrollInstance.destroy(); 27996 27997 scrollable.data('iscrollInstance', null); 27998 } 27999 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 28000 }, 28001 28002 /** 28003 * Called when overflow scrolling has already been setup but the 28004 * window height has potentially changed. 28005 * 28006 * @param {Object}
28006 element jQuery object containing current section 28007 * @param {Number} scrollHeight Current window height in pixels 28008 */ 28009 update: function(element, scrollHeight) { 28010 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 28011 //short period of time. 28012 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 28013 clearTimeout(iscrollHandler.refreshId); 28014 iscrollHandler.refreshId = setTimeout(function(){ 28015 $.each(iscrollHandler.iScrollInstances, function(){ 28016 $(this).get(0).refresh(); 28017 }); 28018 }, 150); 28019 28020 //updating the wrappers height 28021 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 28022 }, 28023 28024 /** 28025 * Called to get any additional elements needed to wrap the section 28026 * content in order to facilitate overflow scrolling. 28027 * 28028 * @return {String|Object} Can be a string containing HTML, 28029 * a DOM element, or jQuery object. 28030 */ 28031 wrapContent: function() { 28032 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 28033 } 28034 }; 28035}); 28036 28037/* ======================================================================== 28038 * Bootstrap: collapse.js v3.1.1 28039 * http://getbootstrap.com/javascript/#collapse 28040 * ======================================================================== 28041 * Copyright 2011-2014 Twitter, Inc. 28042 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 28043 * ======================================================================== */ 28044 28045 28046+function ($) { 28047 'use strict'; 28048 28049 // COLLAPSE PUBLIC CLASS DEFINITION 28050 // ================================ 28051 28052 var Collapse = function (element, options) { 28053 this.$element = $(element) 28054 this.options = $.extend({}, Collapse.DEFAULTS, options) 28055 this.transitioning = null 28056 28057 if (this.options.parent) this.$parent = $(this.options.parent) 28058 if (this.options.toggle) this.toggle() 28059 } 28060 28061 Collapse.DEFAULTS = { 28062 toggle: true 28063 } 28064 28065 Collapse.prototype.dimension = function () { 28066 var hasWidth = this.$element.hasClass('width') 28067 return hasWidth ? 'width' : 'height' 28068 } 28069 28070 Collapse.prototype.show = function () { 28071 if (this.transitioning || this.$element.hasClass('in')) return 28072 28073 var startEvent = $.Event('show.bs.collapse') 28074 this.$element.trigger(startEvent) 28075 if (startEvent.isDefaultPrevented()) return 28076 28077 var actives = this.$parent && this.$parent.find('> .panel > .in') 28078 28079 if (actives && actives.length) { 28080 var hasData = actives.data('bs.collapse') 28081 if (hasData && hasData.transitioning) return 28082 actives.collapse('hide') 28083 hasData || actives.data('bs.collapse', null) 28084 } 28085 28086 var dimension = this.dimension() 28087 28088 this.$element 28089 .removeClass('collapse') 28090 .addClass('collapsing')[dimension](0) 28091 28092 this.transitioning = 1 28093 28094 var complete = function (e) { 28095 if (e && e.target != this.$element[0]) return 28096 this.$element 28097 .removeClass('collapsing') 28098 .addClass('collapse in')[dimension]('auto') 28099 this.transitioning = 0 28100 this.$element.trigger('shown.bs.collapse') 28101 } 28102 28103 if (!$.support.transition) return complete.call(this) 28104 28105 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 28106 28107 this.$element 28108 .one($.support.transition.end, $.proxy(complete, this)) 28109 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 28110 } 28111 28112 Collapse.prototype.hide = function () { 28113 if (this.transitioning || !this.$element.hasClass('in')) return 28114 28115 var startEvent = $.Event('hide.bs.collapse') 28116 this.$element.trigger(startEvent) 28117 if (startEvent.isDefaultPrevented()) return 28118 28119 var dimension = this.dimension() 28120 28121 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 28122 28123 this.$element 28124 .addClass('collapsing') 28125 .removeClass('collapse') 28126 .removeClass('in') 28127 28128 this.transitioning = 1 28129 28130 var complete = function (e) { 28131 if (e && e.target != this.$element[0]) return 28132 this.transitioning = 0 28133 this.$element 28134 .trigger('hidden.bs.collapse') 28135 .removeClass('collapsing') 28136 .addClass('collapse') 28137 } 28138 28139 if (!$.support.transition) return complete.call(this) 28140 28141 this.$element 28142 [dimension](0) 28143 .one($.support.transition.end, $.proxy(complete, this)) 28144 .emulateTransitionEnd(350) 28145 } 28146 28147 Collapse.prototype.toggle = function () { 28148 this[this.$element.hasClass('in') ? 'hide' : 'show']() 28149 } 28150 28151 28152 // COLLAPSE PLUGIN DEFINITION 28153 // ========================== 28154 28155 var old = $.fn.collapse 28156 28157 $.fn.collapse = function (option) { 28158 return this.each(function () { 28159 var $this = $(this) 28160 var data = $this.data('bs.collapse') 28161 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 28162 28163 if (!data && options.toggle && option == 'show') option = !option 28164 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 28165 if (typeof option == 'string') data[option]() 28166 }) 28167 } 28168 28169 $.fn.collapse.Constructor = Collapse 28170 28171 28172 // COLLAPSE NO CONFLICT 28173 // ==================== 28174 28175 $.fn.collapse.noConflict = function () { 28176 $.fn.collapse = old 28177 return this 28178 } 28179 28180 28181 // COLLAPSE DATA-API 28182 // ================= 28183 28184 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 28185 var $this = $(this), href 28186 var target = $this.attr('data-target') 28187 || e.preventDefault() 28188 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 28189 //Edited by Uncode to replace ID in panel [START] 28190 var _target = href.replace(/^#/, ""); 28191 if ( $('[data-id="' + _target + '"]').length ) { 28192 var $target = $('[data-id="' + _target + '"]') 28193 } else { 28194 var $target = $(target) 28195 } 28196 //Edited by Uncode to replace ID in panel [END] 28197 var data = $target.data('bs.collapse') 28198 var option = data ? 'toggle' : $this.data() 28199 var parent = $this.attr('data-parent') 28200 var $parent = parent && $(parent) 28201 28202 if (!data || !data.transitioning) { 28203 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 28204 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 28205 } 28206 28207 $target.collapse(option) 28208 }) 28209 28210}(jQuery); 28211 28212/* ======================================================================== 28213 * Bootstrap: tab.js v3.1.1 28214 * http://getbootstrap.com/javascript/#tabs 28215 * ======================================================================== 28216 * Copyright 2011-2014 Twitter, Inc. 28217 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 28218 * ======================================================================== */ 28219 28220 28221+function ($) { 28222 'use strict'; 28223 28224 // TAB CLASS DEFINITION 28225 // ==================== 28226 28227 var Tab = function (element) { 28228 this.element = $(element) 28229 } 28230 28231 Tab.prototype.show = function () { 28232 var $this = this.element 28233 var $ul = $this.closest('ul:not(.dropdown-menu)') 28234 var selector = $this.data('target') 28235 28236 if (!selector) { 28237 selector = $this.attr('href') 28238 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 28239 } 28240 28241 if ($this.parent('li').hasClass('active')) return 28242 28243 var previous = $ul.find('.active:last a')[0] 28244 var e = $.Event('show.bs.tab', { 28245 relatedTarget: previous 28246 }) 28247 28248 $this.trigger(e) 28249 28250 if (e.isDefaultPrevented()) return 28251 28252 //Edited by Uncode to replace ID in panel [START] 28253 var _target = selector.replace(/^#/, ""); 28254 if ( $('[data-id="' + _target + '"]').length ) 28255 var $target = $('[data-id="' + _target + '"]') 28256 else 28257 var $target = $(selector) 28258 //Edited by Uncode to replace ID in panel [END] 28259 28260 this.activate($this.parent('li'), $ul) 28261 this.activate($target, $target.parent(), function () { 28262 $this.trigger({ 28263 type: 'shown.bs.tab', 28264 relatedTarget: previous 28265 }) 28266 }) 28267 } 28268 28269 Tab.prototype.activate = function (element, container, callback) { 28270 var $active = container.find('> .active') 28271 var transition = callback 28272 && $.support.transition 28273 && $active.hasClass('fade') 28274 28275 function next() { 28276 $active 28277 .removeClass('active') 28278 .find('> .dropdown-menu > .active') 28279 .removeClass('active') 28280 28281 element.addClass('active') 28282 28283 if (transition) { 28284 element[0].offsetWidth // reflow for transition 28285 element.addClass('in') 28286 } else { 28287 element.removeClass('fade') 28288 } 28289 28290 if (element.parent('.dropdown-menu')) { 28291 element.closest('li.dropdown').addClass('active') 28292 } 28293 28294 callback && callback() 28295 } 28296 28297 transition ? 28298 $active 28299 .one($.support.transition.end, next) 28300 .emulateTransitionEnd(150) : 28301 next() 28302 28303 $active.removeClass('in') 28304 } 28305 28306 28307 // TAB PLUGIN DEFINITION 28308 // ===================== 28309 28310 var old = $.fn.tab 28311 28312 $.fn.tab = function ( option ) { 28313 return this.each(function () { 28314 var $this = $(this) 28315 var data = $this.data('bs.tab') 28316 28317 if (!data) $this.data('bs.tab', (data = new Tab(this))) 28318 if (typeof option == 'string') data[option]() 28319 }) 28320 } 28321 28322 $.fn.tab.Constructor = Tab 28323 28324 28325 // TAB NO CONFLICT 28326 // =============== 28327 28328 $.fn.tab.noConflict = function () { 28329 $.fn.tab = old 28330 return this 28331 } 28332 28333 28334 // TAB DATA-API 28335 // ============ 28336 28337 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 28338 e.preventDefault() 28339 $(this).tab('show') 28340 }) 28341 28342}(jQuery); 28343 28344/* ======================================================================== 28345 * Bootstrap: tooltip.js v3.1.1 28346 * http://getbootstrap.com/javascript/#tooltip 28347 * Inspired by the original jQuery.tipsy by Jason Frame 28348 * ======================================================================== 28349 * Copyright 2011-2014 Twitter, Inc. 28350 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 28351 * ======================================================================== */ 28352 28353 28354+function ($) { 28355 'use strict'; 28356 28357 // TOOLTIP PUBLIC CLASS DEFINITION 28358 // =============================== 28359 28360 var Tooltip = function (element, options) { 28361 this.type = 28362 this.options = 28363 this.enabled = 28364 this.timeout = 28365 this.hoverState = 28366 this.$element = null 28367 28368 this.init('tooltip', element, options) 28369 } 28370 28371 Tooltip.DEFAULTS = { 28372 animation: true, 28373 placement: 'top', 28374 selector: false, 28375 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 28376 trigger: 'hover focus', 28377 title: '', 28378 delay: 0, 28379 html: false, 28380 container: false, 28381 viewport: { 28382 selector: 'body', 28383 padding: 0 28384 } 28385 } 28386 28387 Tooltip.prototype.init = function (type, element, options) { 28388 this.enabled = true 28389 this.type = type 28390 this.$element = $(element) 28391 this.options = this.getOptions(options) 28392 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 28393 28394 var triggers = this.options.trigger.split(' ') 28395 28396 for (var i = triggers.length; i--;) { 28397 var trigger = triggers[i] 28398 28399 if (trigger == 'click') { 28400 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 28401 } else if (trigger != 'manual') { 28402 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 28403 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 28404 28405 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 28406 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 28407 } 28408 } 28409 28410 this.options.selector ? 28411 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 28412 this.fixTitle() 28413 } 28414 28415 Tooltip.prototype.getDefaults = function () { 28416 return Tooltip.DEFAULTS 28417 } 28418 28419 Tooltip.prototype.getOptions = function (options) { 28420 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 28421 28422 if (options.delay && typeof options.delay == 'number') { 28423 options.delay = { 28424 show: options.delay, 28425 hide: options.delay 28426 } 28427 } 28428 28429 return options 28430 } 28431 28432 Tooltip.prototype.getDelegateOptions = function () { 28433 var options = {} 28434 var defaults = this.getDefaults() 28435 28436 this._options && $.each(this._options, function (key, value) { 28437 if (defaults[key] != value) options[key] = value 28438 }) 28439 28440 return options 28441 } 28442 28443 Tooltip.prototype.enter = function (obj) { 28444 var self = obj instanceof this.constructor ? 28445 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 28446 28447 clearTimeout(self.timeout) 28448 28449 self.hoverState = 'in' 28450 28451 if (!self.options.delay || !self.options.delay.show) return self.show() 28452 28453 self.timeout = setTimeout(function () { 28454 if (self.hoverState == 'in') self.show() 28455 }, self.options.delay.show) 28456 } 28457 28458 Tooltip.prototype.leave = function (obj) { 28459 var self = obj instanceof this.constructor ? 28460 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 28461 28462 clearTimeout(self.timeout) 28463 28464 self.hoverState = 'out' 28465 28466 if (!self.options.delay || !self.options.delay.hide) return self.hide() 28467 28468 self.timeout = setTimeout(function () { 28469 if (self.hoverState == 'out') self.hide() 28470 }, self.options.delay.hide) 28471 } 28472 28473 Tooltip.prototype.show = function () { 28474 var e = $.Event('show.bs.' + this.type) 28475 28476 if (this.hasContent() && this.enabled) { 28477 this.$element.trigger(e) 28478 28479 if (e.isDefaultPrevented()) return 28480 var that = this; 28481 28482 var $tip = this.tip() 28483 28484 this.setContent() 28485 28486 if (this.options.animation) $tip.addClass('fade') 28487 28488 var placement = typeof this.options.placement == 'function' ? 28489 this.options.placement.call(this, $tip[0], this.$element[0]) : 28490 this.options.placement 28491 28492 var autoToken = /\s?auto?\s?/i 28493 var autoPlace = autoToken.test(placement) 28494 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 28495 28496 $tip 28497 .detach() 28498 .css({ top: 0, left: 0, display: 'block' }) 28499 .addClass(placement) 28500 28501 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 28502 28503 var pos = this.getPosition() 28504 var actualWidth = $tip[0].offsetWidth 28505 var actualHeight = $tip[0].offsetHeight 28506 28507 if (autoPlace) { 28508 var orgPlacement = placement 28509 var $parent = this.$element.parent() 28510 var parentDim = this.getPosition($parent) 28511 28512 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 28513 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 28514 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 28515 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 28516 placement 28517 28518 $tip 28519 .removeClass(orgPlacement) 28520 .addClass(placement) 28521 } 28522 28523 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 28524 28525 this.applyPlacement(calculatedOffset, placement) 28526 this.hoverState = null 28527 28528 var complete = function() { 28529 that.$element.trigger('shown.bs.' + that.type) 28530 } 28531 28532 $.support.transition && this.$tip.hasClass('fade') ? 28533 $tip 28534 .one($.support.transition.end, complete) 28535 .emulateTransitionEnd(150) : 28536 complete() 28537 } 28538 } 28539 28540 Tooltip.prototype.applyPlacement = function (offset, placement) { 28541 var $tip = this.tip() 28542 var width = $tip[0].offsetWidth 28543 var height = $tip[0].offsetHeight 28544 28545 // manually read margins because getBoundingClientRect includes difference 28546 var marginTop = parseInt($tip.css('margin-top'), 10) 28547 var marginLeft = parseInt($tip.css('margin-left'), 10) 28548 28549 // we must check for NaN for ie 8/9 28550 if (isNaN(marginTop)) marginTop = 0 28551 if (isNaN(marginLeft)) marginLeft = 0 28552 28553 offset.top = offset.top + marginTop 28554 offset.left = offset.left + marginLeft 28555 28556 // $.fn.offset doesn't round pixel values 28557 // so we use setOff
28557set directly with our own function B-0 28558 $.offset.setOffset($tip[0], $.extend({ 28559 using: function (props) { 28560 $tip.css({ 28561 top: Math.round(props.top), 28562 left: Math.round(props.left) 28563 }) 28564 } 28565 }, offset), 0) 28566 28567 $tip.addClass('in') 28568 28569 // check to see if placing tip in new offset caused the tip to resize itself 28570 var actualWidth = $tip[0].offsetWidth 28571 var actualHeight = $tip[0].offsetHeight 28572 28573 if (placement == 'top' && actualHeight != height) { 28574 offset.top = offset.top + height - actualHeight 28575 } 28576 28577 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 28578 28579 if (delta.left) offset.left += delta.left 28580 else offset.top += delta.top 28581 28582 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 28583 var arrowPosition = delta.left ? 'left' : 'top' 28584 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 28585 28586 $tip.offset(offset) 28587 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 28588 } 28589 28590 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 28591 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 28592 } 28593 28594 Tooltip.prototype.setContent = function () { 28595 var $tip = this.tip() 28596 var title = this.getTitle() 28597 28598 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 28599 $tip.removeClass('fade in top bottom left right') 28600 } 28601 28602 Tooltip.prototype.hide = function () { 28603 var that = this 28604 var $tip = this.tip() 28605 var e = $.Event('hide.bs.' + this.type) 28606 28607 function complete() { 28608 if (that.hoverState != 'in') $tip.detach() 28609 that.$element.trigger('hidden.bs.' + that.type) 28610 } 28611 28612 this.$element.trigger(e) 28613 28614 if (e.isDefaultPrevented()) return 28615 28616 $tip.removeClass('in') 28617 28618 $.support.transition && this.$tip.hasClass('fade') ? 28619 $tip 28620 .one($.support.transition.end, complete) 28621 .emulateTransitionEnd(150) : 28622 complete() 28623 28624 this.hoverState = null 28625 28626 return this 28627 } 28628 28629 Tooltip.prototype.fixTitle = function () { 28630 var $e = this.$element 28631 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 28632 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 28633 } 28634 } 28635 28636 Tooltip.prototype.hasContent = function () { 28637 return this.getTitle() 28638 } 28639 28640 Tooltip.prototype.getPosition = function ($element) { 28641 $element = $element || this.$element 28642 var el = $element[0] 28643 var isBody = el.tagName == 'BODY' 28644 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 28645 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 28646 width: isBody ? $(window).width() : $element.outerWidth(), 28647 height: isBody ? $(window).height() : $element.outerHeight() 28648 }, isBody ? {top: 0, left: 0} : $element.offset()) 28649 } 28650 28651 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 28652 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 28653 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 28654 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 28655 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 28656 28657 } 28658 28659 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 28660 var delta = { top: 0, left: 0 } 28661 if (!this.$viewport) return delta 28662 28663 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 28664 var viewportDimensions = this.getPosition(this.$viewport) 28665 28666 if (/right|left/.test(placement)) { 28667 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 28668 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 28669 if (topEdgeOffset < viewportDimensions.top) { // top overflow 28670 delta.top = viewportDimensions.top - topEdgeOffset 28671 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 28672 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
28672EdgeOffset 28673 } 28674 } else { 28675 var leftEdgeOffset = pos.left - viewportPadding 28676 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 28677 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 28678 delta.left = viewportDimensions.left - leftEdgeOffset 28679 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 28680 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 28681 } 28682 } 28683 28684 return delta 28685 } 28686 28687 Tooltip.prototype.getTitle = function () { 28688 var title 28689 var $e = this.$element 28690 var o = this.options 28691 28692 title = $e.attr('data-original-title') 28693 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 28694 28695 return title 28696 } 28697 28698 Tooltip.prototype.tip = function () { 28699 return this.$tip = this.$tip || $(this.options.template) 28700 } 28701 28702 Tooltip.prototype.arrow = function () { 28703 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 28704 } 28705 28706 Tooltip.prototype.validate = function () { 28707 if (!this.$element[0].parentNode) { 28708 this.hide() 28709 this.$element = null 28710 this.options = null 28711 } 28712 } 28713 28714 Tooltip.prototype.enable = function () { 28715 this.enabled = true 28716 } 28717 28718 Tooltip.prototype.disable = function () { 28719 this.enabled = false 28720 } 28721 28722 Tooltip.prototype.toggleEnabled = function () { 28723 this.enabled = !this.enabled 28724 } 28725 28726 Tooltip.prototype.toggle = function (e) { 28727 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 28728 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 28729 } 28730 28731 Tooltip.prototype.destroy = function () { 28732 clearTimeout(this.timeout) 28733 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 28734 } 28735 28736 28737 // TOOLTIP PLUGIN DEFINITION 28738 // ========================= 28739 28740 var old = $.fn.tooltip 28741 28742 $.fn.tooltip = function (option) { 28743 return this.each(function () { 28744 var $this = $(this) 28745 var data = $this.data('bs.tooltip') 28746 var options = typeof option == 'object' && option 28747 28748 if (!data && option == 'destroy') return 28749 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 28750 if (typeof option == 'string') data[option]() 28751 }) 28752 } 28753 28754 $.fn.tooltip.Constructor = Tooltip 28755 28756 28757 // TOOLTIP NO CONFLICT 28758 // =================== 28759 28760 $.fn.tooltip.noConflict = function () { 28761 $.fn.tooltip = old 28762 return this 28763 } 28764 28765}(jQuery); 28766 28767/* ======================================================================== 28768 * Bootstrap: transition.js v3.1.1 28769 * http://getbootstrap.com/javascript/#transitions 28770 * ======================================================================== 28771 * Copyright 2011-2014 Twitter, Inc. 28772 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 28773 * ======================================================================== */ 28774 28775 28776+function ($) { 28777 'use strict'; 28778 28779 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 28780 // ============================================================ 28781 28782 function transitionEnd() { 28783 var el = document.createElement('bootstrap') 28784 28785 var transEndEventNames = { 28786 WebkitTransition : 'webkitTransitionEnd', 28787 MozTransition : 'transitionend', 28788 OTransition : 'oTransitionEnd otransitionend', 28789 transition : 'transitionend' 28790 } 28791 28792 for (var name in transEndEventNames) { 28793 if (el.style[name] !== undefined) { 28794 return { end: transEndEventNames[name] } 28795 } 28796 } 28797 28798 return false // explicit for ie8 ( ._.) 28799 } 28800 28801 // http://blog.alexmaccaw.com/css-transitions 28802 $.fn.emulateTransitionEnd = function (duration) { 28803 var called = false, $el = this 28804 $(this).one($.support.transition.end, function () { called = true }) 28805 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 28806 setTimeout(callback, duration) 28807 return this 28808 } 28809 28810 $(function () { 28811 $.support.transition = transitionEnd() 28812 }) 28813 28814}(jQuery); 28815 28816 28817// ------------------------------------------ 28818// Rellax.js 28819// Buttery smooth parallax library 28820// Copyright (c) 2016 Moe Amaya (@moeamaya) 28821// MIT license 28822// 28823// Thanks to Paraxify.js and Jaime Cabllero 28824// for parallax concepts 28825// ------------------------------------------ 28826 28827(function (root, factory) { 28828 if (typeof define === 'function' && define.amd) { 28829 // AMD. Register as an anonymous module. 28830 define([], factory); 28831 } else if (typeof module === 'object' && module.exports) { 28832 // Node. Does not work with strict CommonJS, but 28833 // only CommonJS-like environments that support module.exports, 28834 // like Node. 28835 module.exports = factory(); 28836 } else { 28837 // Browser globals (root is window) 28838 root.Rellax = factory(); 28839 } 28840}(typeof window !== "undefined" ? window : global, function () { 28841 var Rellax = function(el, options){ 28842 "use strict"; 28843 28844 var self = Object.create(Rellax.prototype); 28845 28846 var posY = 0; 28847 var screenY = 0; 28848 var posX = 0; 28849 var screenX = 0; 28850 var blocks = []; 28851 var pause = true; 28852 28853 // check what requestAnimationFrame to use, and if 28854 // it's not supported, use the onscroll event 28855 var loop = window.requestAnimationFrame || 28856 window.webkitRequestAnimationFrame || 28857 window.mozRequestAnimationFrame || 28858 window.msRequestAnimationFrame || 28859 window.oRequestAnimationFrame || 28860 function(callback){ return setTimeout(callback, 1000 / 60); }; 28861 28862 // store the id for later use 28863 var loopId = null; 28864 28865 // Test via a getter in the options object to see if the passive property is accessed 28866 var supportsPassive = false;
vendor: 10,724 bytes, lines 28867-29168
28867 try { 28868 var opts = Object.defineProperty({}, 'passive', { 28869 get: function() { 28870 supportsPassive = true; 28871 } 28872 }); 28873 window.addEventListener("testPassive", null, opts); 28874 window.removeEventListener("testPassive", null, opts); 28875 } catch (e) {} 28876 28877 // check what cancelAnimation method to use 28878 var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout; 28879 28880 // check which transform property to use 28881 var transformProp = window.transformProp || (function(){ 28882 var testEl = document.createElement('div'); 28883 if (testEl.style.transform === null) { 28884 var vendors = ['Webkit', 'Moz', 'ms']; 28885 for (var vendor in vendors) { 28886 if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) { 28887 return vendors[vendor] + 'Transform'; 28888 } 28889 } 28890 } 28891 return 'transform'; 28892 })(); 28893 28894 // Default Settings 28895 self.options = { 28896 speed: -2, 28897 verticalSpeed: null, 28898 horizontalSpeed: null, 28899 breakpoints: [576, 768, 1201], 28900 center: false, 28901 wrapper: null, 28902 relativeToWrapper: false, 28903 round: true, 28904 vertical: true, 28905 horizontal: false, 28906 verticalScrollAxis: "y", 28907 horizontalScrollAxis: "x", 28908 callback: function() {}, 28909 }; 28910 28911 // User defined options (might have more in the future) 28912 if (options){ 28913 Object.keys(options).forEach(function(key){ 28914 self.options[key] = options[key]; 28915 }); 28916 } 28917 28918 function validateCustomBreakpoints () { 28919 if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) { 28920 var isAscending = true; 28921 var isNumerical = true; 28922 var lastVal; 28923 self.options.breakpoints.forEach(function (i) { 28924 if (typeof i !== 'number') isNumerical = false; 28925 if (lastVal !== null) { 28926 if (i < lastVal) isAscending = false; 28927 } 28928 lastVal = i; 28929 }); 28930 if (isAscending && isNumerical) return; 28931 } 28932 // revert defaults if set incorrectly 28933 self.options.breakpoints = [576, 768, 1201]; 28934 console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted"); 28935 } 28936 28937 if (options && options.breakpoints) { 28938 validateCustomBreakpoints(); 28939 } 28940 28941 // By default, rellax class 28942 if (!el) { 28943 el = '.rellax'; 28944 } 28945 28946 // check if el is a className or a node 28947 var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el]; 28948 28949 // Now query selector 28950 if (elements.length > 0) { 28951 self.elems = elements; 28952 } 28953 28954 // The elements don't exist 28955 else { 28956 console.warn("Rellax: The elements you're trying to select don't exist."); 28957 return; 28958 } 28959 28960 // Has a wrapper and it exists 28961 if (self.options.wrapper) { 28962 if (!self.options.wrapper.nodeType) { 28963 var wrapper = document.querySelector(self.options.wrapper); 28964 28965 if (wrapper) { 28966 self.options.wrapper = wrapper; 28967 } else { 28968 console.warn("Rellax: The wrapper you're trying to use doesn't exist."); 28969 return; 28970 } 28971 } 28972 } 28973 28974 // set a placeholder for the current breakpoint 28975 var currentBreakpoint; 28976 28977 // helper to determine current breakpoint 28978 var getCurrentBreakpoint = function (w) { 28979 var bp = self.options.breakpoints; 28980 if (w < bp[0]) return 'xs'; 28981 if (w >= bp[0] && w < bp[1]) return 'sm'; 28982 if (w >= bp[1] && w < bp[2]) return 'md'; 28983 return 'lg'; 28984 }; 28985 28986 // Get and cache initial position of all elements 28987 var cacheBlocks = function() { 28988 for (var i = 0; i < self.elems.length; i++){ 28989 var block = createBlock(self.elems[i]); 28990 blocks.push(block); 28991 } 28992 }; 28993 28994 28995 // Let's kick this script off 28996 // Build array for cached element values 28997 var init = function() { 28998 for (var i = 0; i < blocks.length; i++){ 28999 self.elems[i].style.cssText = blocks[i].style; 29000 } 29001 29002 blocks = []; 29003 29004 screenY = window.innerHeight; 29005 screenX = window.innerWidth; 29006 currentBreakpoint = getCurrentBreakpoint(screenX); 29007 29008 setPosition(); 29009 29010 cacheBlocks(); 29011 29012 animate(); 29013 29014 // If paused, unpause and set listener for window resizing events 29015 if (pause) { 29016 window.addEventListener('resize', init); 29017 pause = false; 29018 // Start the loop 29019 update(); 29020 } 29021 }; 29022 29023 // We want to cache the parallax blocks' 29024 // values: base, top, height, speed 29025 // el: is dom object, return: el cache values 29026 var createBlock = function(el) { 29027 var dataPercentage = el.getAttribute( 'data-rellax-percentage' ); 29028 var dataSpeed = el.getAttribute( 'data-rellax-speed' ); 29029 var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' ); 29030 var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' ); 29031 var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' ); 29032 var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' ); 29033 var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed'); 29034 var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed'); 29035 var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis'); 29036 var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis'); 29037 var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0; 29038 var dataMin = el.getAttribute( 'data-rellax-min' ); 29039 var dataMax = el.getAttribute( 'data-rellax-max' ); 29040 var dataMinX = el.getAttribute('data-rellax-min-x'); 29041 var dataMaxX = el.getAttribute('data-rellax-max-x'); 29042 var dataMinY = el.getAttribute('data-rellax-min-y'); 29043 var dataMaxY = el.getAttribute('data-rellax-max-y'); 29044 var mapBreakpoints; 29045 var breakpoints = true; 29046 29047 if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) { 29048 breakpoints = false; 29049 } else { 29050 mapBreakpoints = { 29051 'xs': dataXsSpeed, 29052 'sm': dataMobileSpeed, 29053 'md': dataTabletSpeed, 29054 'lg': dataDesktopSpeed 29055 }; 29056 } 29057 29058 // initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser) 29059 // ensures elements are positioned based on HTML layout. 29060 // 29061 // If the element has the percentage attribute, the posY and posX needs to be 29062 // the current scroll position's value, so that the elements are still positioned based on HTML layout 29063 var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 29064 // If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll. 29065 if (self.options.relativeToWrapper) { 29066 var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 29067 wrapperPosY = scrollPosY - self.options.wrapper.offsetTop; 29068 } 29069 var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0; 29070 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; 29071 29072 var blockTop = posY + el.getBoundingClientRect().top; 29073 var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight; 29074 29075 var blockLeft = posX + el.getBoundingClientRect().left; 29076 var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth; 29077 29078 // apparently parallax equation everyone uses 29079 var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY); 29080 var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX); 29081 if(self.options.center){ percentageX = 0.5; percentageY = 0.5; } 29082 29083 // Optional individual block speed as data attr, otherwise global speed 29084 var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed); 29085 var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed; 29086 var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed; 29087 29088 // Optional individual block movement axis direction as data attr, otherwise global movement direction 29089 var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis; 29090 var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis; 29091 29092 var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed); 29093 29094 // ~~Store non-translate3d transforms~~ 29095 // Store inline styles and extract transforms 29096 var style = el.style.cssText; 29097 var transform = ''; 29098 29099 // Check if there's an inline styled transform 29100 var searchResult = /transform\s*:/i.exec(style); 29101 if (searchResult) { 29102 // Get the index of the transform 29103 var index = searchResult.index; 29104 29105 // Trim the style to the transform point and get the following semi-colon index 29106 var trimmedStyle = style.slice(index); 29107 var delimiter = trimmedStyle.indexOf(';'); 29108 29109 // Remove "transform" string and save the attribute 29110 if (delimiter) { 29111 transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,''); 29112 } else { 29113 transform = " " + trimmedStyle.slice(11).replace(/\s/g,''); 29114 } 29115 } 29116 29117 return { 29118 baseX: bases.x, 29119 baseY: bases.y, 29120 top: blockTop, 29121 left: blockLeft, 29122 height: blockHeight, 29123 width: blockWidth, 29124 speed: speed, 29125 verticalSpeed: verticalSpeed, 29126 horizontalSpeed: horizontalSpeed, 29127 verticalScrollAxis: verticalScrollAxis, 29128 horizontalScrollAxis: horizontalScrollAxis, 29129 style: style, 29130 transform: transform, 29131 zindex: dataZindex, 29132 min: dataMin, 29133 max: dataMax, 29134 minX: dataMinX, 29135 maxX: dataMaxX, 29136 minY: dataMinY, 29137 maxY: dataMaxY 29138 }; 29139 }; 29140 29141 // set scroll position (posY, posX) 29142 // side effect method is not ideal, but okay for now 29143 // returns true if the scroll changed, false if nothing happened 29144 var setPosition = function() { 29145 var oldY = posY; 29146 var oldX = posX; 29147 29148 posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 29149 posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset; 29150 // If option relativeToWrapper is true, use relative wrapper value instead. 29151 if (self.options.relativeToWrapper) { 29152 var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 29153 posY = scrollPosY - self.options.wrapper.offsetTop; 29154 } 29155 29156 29157 if (oldY != posY && self.options.vertical) { 29158 // scroll changed, return true 29159 return true; 29160 } 29161 29162 if (oldX != posX && self.options.horizontal) { 29163 // scroll changed, return true 29164 return true; 29165 } 29166 29167 // scroll did not change 29168 return false;
29169 }; 29170 29171 // Ahh a pure function, gets new transform value 29172 // based on scrollPosition and speed 29173 // Allow for decimal pixel values 29174 var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) { 29175 var result = {}; 29176 var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX))); 29177 var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY))); 29178 29179 result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100; 29180 result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100; 29181 29182 return result; 29183 }; 29184 29185 // Remove event listeners and loop again 29186 var deferredUpdate = function() { 29187 window.removeEventListener('resize', deferredUpdate); 29188 window.removeEventListener('orientationchange', deferredUpdate); 29189 (self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate); 29190 (self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate); 29191 29192 // loop again 29193 loopId = loop(update); 29194 }; 29195 29196 // Loop 29197 var update = function() { 29198 if (setPosition() && pause === false) { 29199 animate(); 29200 29201 // loop again 29202 loopId = loop(update); 29203 } else { 29204 loopId = null; 29205 29206 // Don't animate until we get a position updating event 29207 window.addEventListener('resize', deferredUpdate); 29208 window.addEventListener('orientationchange', deferredUpdate); 29209 (self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false); 29210 (self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false); 29211 } 29212 }; 29213 29214 // Transform3d on parallax element 29215 var animate = function() { 29216 var positions; 29217 for (var i = 0; i < self.elems.length; i++){ 29218 // Determine relevant movement directions 29219 var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase(); 29220 var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase(); 29221 var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0; 29222 var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0; 29223 var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0; 29224 var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0; 29225 29226 var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY)); 29227 var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX)); 29228 29229 // Subtracting initialize value, so element stays in same spot as HTML 29230 positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed); 29231 var positionY = positions.y - blocks[i].baseY; 29232 var positionX = positions.x - blocks[i].baseX; 29233 29234 // The next two "if" blocks go like this: 29235 // Check if a limit is defined (first "min", then "max"); 29236 // Check if we need to change the Y or the X 29237 // (Currently working only if just one of the axes is enabled) 29238 // Then, check if the new position is inside the allowed limit 29239 // If so, use new position. If not, set position to limit. 29240 29241 // Check if a min limit is defined 29242 if (blocks[i].min !== null) { 29243 if (self.options.vertical && !self.options.horizontal) { 29244 positionY = positionY <= blocks[i].min ? blocks[i].min : positionY; 29245 } 29246 if (self.options.horizontal && !self.options.vertical) { 29247 positionX = positionX <= blocks[i].min ? blocks[i].min : positionX; 29248 } 29249 } 29250 29251 // Check if directional min limits are defined 29252 if (blocks[i].minY != null) { 29253 positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY; 29254 } 29255 if (blocks[i].minX != null) { 29256 positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX; 29257 } 29258 29259 // Check if a max limit is defined 29260 if (blocks[i].max !== null) { 29261 if (self.options.vertical && !self.options.horizontal) { 29262 positionY = positionY >= blocks[i].max ? blocks[i].max : positionY; 29263 } 29264 if (self.options.horizontal && !self.options.vertical) { 29265 positionX = positionX >= blocks[i].max ? blocks[i].max : positionX; 29266 } 29267 } 29268 29269 // Check if directional max limits are defined 29270 if (blocks[i].maxY != null) { 29271 positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY; 29272 } 29273 if (blocks[i].maxX != null) { 29274 positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX; 29275 } 29276 29277 var zindex = blocks[i].zindex; 29278 29279 // Move that element 29280 // (Set the new translation and append initial inline transforms.) 29281 var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform; 29282 self.elems[i].style[transformProp] = translate; 29283 } 29284 self.options.callback(positions); 29285 }; 29286 29287 self.destroy = function() { 29288 for (var i = 0; i < self.elems.length; i++){ 29289 self.elems[i].style.cssText = blocks[i].style; 29290 } 29291 29292 // Remove resize event listener if not pause, and pause 29293 if (!pause) { 29294 window.removeEventListener('resize', init); 29295 pause = true; 29296 } 29297 29298 // Clear the animation loop to prevent possible memory leak 29299 clearLoop(loopId); 29300 loopId = null; 29301 }; 29302 29303 // Init 29304 init(); 29305 29306 // Allow to recalculate the initial values whenever we want 29307 self.refresh = init; 29308 29309 return self; 29310 }; 29311 return Rellax; 29312})); 29313 29314/* 29315 * OKVideo by OKFocus v2.3.2 29316 * http://okfoc.us 29317 * 29318 * Copyright 2014, OKFocus 29319 * Licensed under the MIT license. 29320 * 29321 */ 29322var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array(); 29323// youtube player ready 29324function onYouTubeIframeAPIReady() { 29325 YTplayers = new Array(); 29326 jQuery('.no-touch .uncode-video-container.video').each(function() { 29327 var playerY; 29328 if (jQuery(this).attr('data-provider') == 'youtube') { 29329 var id = jQuery(this).attr('data-id'); 29330 options = jQuery(window).data('okoptions-' + id); 29331 options.time = jQuery(this).attr('data-t'); 29332 playerY = new YT.Player('okplayer-' + id, { 29333 videoId: options.video ? options.video.id : null, 29334 playerVars: { 29335 'autohide': 1, 29336 'autoplay': 0, //options.autoplay, 29337 'disablekb': 1, 29338 'cc_load_policy': options.captions, 29339 'controls': 0, 29340 'enablejsapi': 1, 29341 'fs': 0, 29342 'modestbranding': 1, 29343 'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname), 29344 'iv_load_policy': options.annotations, 29345 'loop': options.loop, 29346 'showinfo': 0, 29347 'rel': 0, 29348 'wmode': 'opaque', 29349 'hd': options.hd, 29350 'mute': 1 29351 }, 29352 events: { 29353 'onReady': OKEvents.yt.ready, 29354 'onStateChange': OKEvents.yt.onStateChange, 29355 'onError': OKEvents.yt.error 29356 } 29357 }); 29358 YTplayers[id] = playerY; 29359 playerY.videoId = id; 29360 } 29361 29362 }); 29363} 29364// vimeo player ready 29365function vimeoPlayerReady(id) { 29366 options = jQuery(window).data('okoptions-' + id); 29367 var jIframe = options.jobject, 29368 iframe = jIframe[0]; 29369 29370 jIframe.attr('src', jIframe.data('src')); 29371 var playerV = $f(iframe); // `$f` is froogaloop, assumed is loaded 29372 // hide player until Vimeo hides controls... 29373 playerV.addEvent('ready', function(e) { 29374 OKEvents.v.onReady(iframe); 29375 var carouselContainer = jQuery(iframe).closest('.owl-carousel'); 29376 if (carouselContainer.length) { 29377 UNCODE.owlPlayVideo(carouselContainer); 29378 } 29379 // "Do not try to add listeners or call functions before receiving this event." 29380 if (OKEvents.utils.isMobile()) { 29381 // mobile devices cannot listen for play event 29382 OKEvents.v.onPlay(playerV); 29383 } else { 29384 playerV.addEvent('play', OKEvents.v.onPlay(playerV)); 29385 playerV.addEvent('pause', OKEvents.v.onPause); 29386 playerV.addEvent('finish', OKEvents.v.onFinish); 29387 } 29388 if (options.time != null) { 29389 var optsTimeStr = (options.time).replace('t=', ''), 29390 timeV = ''; 29391 29392 if ( /[a-zA-Z]/g.test(optsTimeStr) ) { 29393 var timeArr = optsTimeStr.split(/([^\d.-])/); 29394 for ( var i = 0; i < timeArr.length; i++ ) { 29395 if ( timeArr[i] === 'h' ) { 29396 timeV += parseFloat(timeArr[i-1]) * 3600; 29397 } else if ( timeArr[i] === 'm' ) { 29398 timeV += parseFloat(timeArr[i-1]) * 60; 29399 } else if ( timeArr[i] === 's' ) { 29400 timeV += parseFloat(timeArr[i-1]); 29401 } 29402 } 29403 } else { 29404 timeV = optsTimeStr; 29405 } 29406 29407 playerV.api('seekTo', timeV); 29408 } 29409 29410 playerV.api('play'); 29411 jQuery(iframe).css({ 29412 visibility: 'visible', 29413 opacity: 1 29414 }); 29415 jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 29416 jQuery(iframe).closest('#page-header').addClass('video-started'); 29417 jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 29418 29419 }); 29420} 29421OKEvents = { 29422 yt: { 29423 ready: function(event) { 29424 var id = event.target.videoId; 29425 youtubePlayers[id] = event.target; 29426 event.target.setVolume(options.volume); 29427 if (options.autoplay === 1) { 29428 if (options.playlist.list) { 29429 player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality); 29430 } else { 29431 var inCarousel = jQuery('#okplayer-' + id).closest('.owl-item'); 29432 if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) { 29433 if (options.time != null) { 29434 event.target.seekTo(parseInt(options.time)); 29435 } 29436 event.target.playVideo(); 29437 } else { 29438 event.target.pauseVideo(); 29439 } 29440 } 29441 } 29442 OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target); 29443 29444 jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-resume', function(){ 29445 if (options.time != null) { 29446 event.target.seekTo(parseInt(options.time)).playVideo(); 29447 } else { 29448 event.target.seekTo(0).playVideo(); 29449 } 29450 }); 29451 29452 jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-pause', function(){ 29453 if (options.time != null) { 29454 event.target.seekTo(parseInt(options.time)).pauseVideo(); 29455 } else { 29456 event.target.seekTo(0).pauseVideo(); 29457 } 29458 }); 29459 }, 29460 onStateChange: function(event) { 29461 var id = event.target.videoId; 29462 switch (event.data) { 29463 case -1: 29464 OKEvents.utils.isFunction(options.unstarted) && options.unstarted(); 29465 break; 29466 case 0: 29467 OKEvents.utils.isFunction(options.onFinished) && options.onFinished(); 29468 options.loop && event.target.playVideo(); 29469 break; 29470 case 1: 29471 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 29472 setTimeout(function() { 29473 UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)'); 29474 jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 29475 jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started'); 29476 jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 29477 }, 300); 29478 break; 29479 case 2: 29480 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 29481 break; 29482 case 3: 29483 OKEvents.utils.isFunction(options.buffering) && options.buffering(); 29484 break; 29485 case 5: 29486 OKEvents.utils.isFunction(options.cued) && options.cued(); 29487 break; 29488 default:
29489 throw "OKVideo: received invalid data from YT player."; 29490 } 29491 }, 29492 error: function(event) { 29493 throw event; 29494 } 29495 }, 29496 v: { 29497 onReady: function(target) { 29498 OKEvents.utils.isFunction(options.onReady) && options.onReady(target); 29499 }, 29500 onPlay: function(player) { 29501 if (!OKEvents.utils.isMobile()) player.api('setVolume', options.volume); 29502 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 29503 jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 29504 jQuery(player.element).closest('#page-header').addClass('video-started'); 29505 jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 29506 }, 29507 onPause: function() { 29508 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 29509 }, 29510 onFinish: function() { 29511 OKEvents.utils.isFunction(options.onFinish) && options.onFinish(); 29512 } 29513 }, 29514 utils: { 29515 isFunction: function(func) { 29516 if (typeof func === 'function') { 29517 return true; 29518 } else { 29519 return false; 29520 } 29521 }, 29522 isMobile: function() { 29523 if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) { 29524 return true; 29525 } else { 29526 return false; 29527 } 29528 } 29529 } 29530}; 29531 29532/** 29533 * vivus - JavaScript library to make drawing animation on SVG 29534 * @version v0.4.4 29535 * @link https://github.com/maxwellito/vivus 29536 * @license MIT 29537 */ 29538 29539'use strict'; 29540 29541(function () { 29542 29543 'use strict'; 29544 29545/** 29546 * Pathformer 29547 * Beta version 29548 * 29549 * Take any SVG version 1.1 and transform 29550 * child elements to 'path' elements 29551 * 29552 * This code is purely forked from 29553 * https://github.com/Waest/SVGPathConverter 29554 */ 29555 29556/** 29557 * Class constructor 29558 * 29559 * @param {DOM|String} element Dom element of the SVG or id of it 29560 */ 29561function Pathformer(element) { 29562 // Test params 29563 if (typeof element === 'undefined') { 29564 throw new Error('Pathformer [constructor]: "element" parameter is required'); 29565 } 29566 29567 // Set the element 29568 if (element.constructor === String) { 29569 element = document.getElementById(element); 29570 if (!element) { 29571 throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID'); 29572 } 29573 } 29574 if (element instanceof window.SVGElement || 29575 element instanceof window.SVGGElement || 29576 /^svg$/i.test(element.nodeName)) { 29577 this.el = element; 29578 } else { 29579 throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement'); 29580 } 29581 29582 // Start 29583 this.scan(element); 29584} 29585 29586/** 29587 * List of tags which can be transformed 29588 * to path elements 29589 * 29590 * @type {Array} 29591 */ 29592Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect']; 29593 29594/** 29595 * List of attribute names which contain 29596 * data. This array list them to check if 29597 * they contain bad values, like percentage. 29598 * 29599 * @type {Array} 29600 */ 29601Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 29601-30399
29601y1', 'y2']; 29602 29603/** 29604 * Finds the elements compatible for transform 29605 * and apply the liked method 29606 * 29607 * @param {object} options Object from the constructor 29608 */ 29609Pathformer.prototype.scan = function (svg) { 29610 var fn, element, pathData, pathDom, 29611 elements = svg.querySelectorAll(this.TYPES.join(',')); 29612 29613 for (var i = 0; i < elements.length; i++) { 29614 element = elements[i]; 29615 fn = this[element.tagName.toLowerCase() + 'ToPath']; 29616 pathData = fn(this.parseAttr(element.attributes)); 29617 pathDom = this.pathMaker(element, pathData); 29618 element.parentNode.replaceChild(pathDom, element); 29619 } 29620}; 29621 29622 29623/** 29624 * Read `line` element to extract and transform 29625 * data, to make it ready for a `path` object. 29626 * 29627 * @param {DOMelement} element Line element to transform 29628 * @return {object} Data for a `path` element 29629 */ 29630Pathformer.prototype.lineToPath = function (element) { 29631 var newElement = {}, 29632 x1 = element.x1 || 0, 29633 y1 = element.y1 || 0, 29634 x2 = element.x2 || 0, 29635 y2 = element.y2 || 0; 29636 29637 newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2; 29638 return newElement; 29639}; 29640 29641/** 29642 * Read `rect` element to extract and transform 29643 * data, to make it ready for a `path` object. 29644 * The radius-border is not taken in charge yet. 29645 * (your help is more than welcomed) 29646 * 29647 * @param {DOMelement} element Rect element to transform 29648 * @return {object} Data for a `path` element 29649 */ 29650Pathformer.prototype.rectToPath = function (element) { 29651 var newElement = {}, 29652 x = parseFloat(element.x) || 0, 29653 y = parseFloat(element.y) || 0, 29654 width = parseFloat(element.width) || 0, 29655 height = parseFloat(element.height) || 0; 29656 29657 if (element.rx || element.ry) { 29658 var rx = parseInt(element.rx, 10) || -1, 29659 ry = parseInt(element.ry, 10) || -1; 29660 rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2); 29661 ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2); 29662 29663 newElement.d = 'M ' + (x + rx) + ',' + y + ' ' + 29664 'L ' + (x + width - rx) + ',' + y + ' ' + 29665 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' + 29666 'L ' + (x + width) + ',' + (y + height - ry) + ' ' + 29667 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' + 29668 'L ' + (x + rx) + ',' + (y + height) + ' ' + 29669 'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' + 29670 'L ' + x + ',' + (y + ry) + ' ' + 29671 'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y; 29672 } 29673 else { 29674 newElement.d = 'M' + x + ' ' + y + ' ' + 29675 'L' + (x + width) + ' ' + y + ' ' + 29676 'L' + (x + width) + ' ' + (y + height) + ' ' + 29677 'L' + x + ' ' + (y + height) + ' Z'; 29678 } 29679 return newElement; 29680}; 29681 29682/** 29683 * Read `polyline` element to extract and transform 29684 * data, to make it ready for a `path` object. 29685 * 29686 * @param {DOMelement} element Polyline element to transform 29687 * @return {object} Data for a `path` element 29688 */ 29689Pathformer.prototype.polylineToPath = function (element) { 29690 var newElement = {}, 29691 points = element.points.trim().split(' '), 29692 i, path; 29693 29694 // Reformatting if points are defined without commas 29695 if (element.points.indexOf(',') === -1) { 29696 var formattedPoints = []; 29697 for (i = 0; i < points.length; i+=2) { 29698 formattedPoints.push(points[i] + ',' + points[i+1]); 29699 } 29700 points = formattedPoints; 29701 } 29702 29703 // Generate the path.d value 29704 path = 'M' + points[0]; 29705 for(i = 1; i < points.length; i++) { 29706 if (points[i].indexOf(',') !== -1) { 29707 path += 'L' + points[i]; 29708 } 29709 } 29710 newElement.d = path; 29711 return newElement; 29712}; 29713 29714/** 29715 * Read `polygon` element to extract and transform 29716 * data, to make it ready for a `path` object. 29717 * This method rely on polylineToPath, because the 29718 * logic is similar. The path created is just closed, 29719 * so it needs an 'Z' at the end. 29720 * 29721 * @param {DOMelement} element Polygon element to transform 29722 * @return {object} Data for a `path` element 29723 */ 29724Pathformer.prototype.polygonToPath = function (element) { 29725 var newElement = Pathformer.prototype.polylineToPath(element); 29726 29727 newElement.d += 'Z'; 29728 return newElement; 29729}; 29730 29731/** 29732 * Read `ellipse` element to extract and transform 29733 * data, to make it ready for a `path` object. 29734 * 29735 * @param {DOMelement} element ellipse element to transform 29736 * @return {object} Data for a `path` element 29737 */ 29738Pathformer.prototype.ellipseToPath = function (element) { 29739 var newElement = {}, 29740 rx = parseFloat(element.rx) || 0, 29741 ry = parseFloat(element.ry) || 0, 29742 cx = parseFloat(element.cx) || 0, 29743 cy = parseFloat(element.cy) || 0, 29744 startX = cx - rx, 29745 startY = cy, 29746 endX = parseFloat(cx) + parseFloat(rx), 29747 endY = cy; 29748 29749 newElement.d = 'M' + startX + ',' + startY + 29750 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY + 29751 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY; 29752 return newElement; 29753}; 29754 29755/** 29756 * Read `circle` element to extract and transform 29757 * data, to make it ready for a `path` object. 29758 * 29759 * @param {DOMelement} element Circle element to transform 29760 * @return {object} Data for a `path` element 29761 */ 29762Pathformer.prototype.circleToPath = function (element) { 29763 var newElement = {}, 29764 r = parseFloat(element.r) || 0, 29765 cx = parseFloat(element.cx) || 0, 29766 cy = parseFloat(element.cy) || 0, 29767 startX = cx - r, 29768 startY = cy, 29769 endX = parseFloat(cx) + parseFloat(r), 29770 endY = cy; 29771 29772 newElement.d = 'M' + startX + ',' + startY + 29773 'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY + 29774 'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY; 29775 return newElement; 29776}; 29777 29778/** 29779 * Create `path` elements form original element 29780 * and prepared objects 29781 * 29782 * @param {DOMelement} element Original element to transform 29783 * @param {object} pathData Path data (from `toPath` methods) 29784 * @return {DOMelement} Path element 29785 */ 29786Pathformer.prototype.pathMaker = function (element, pathData) { 29787 var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path'); 29788 for(i = 0; i < element.attributes.length; i++) { 29789 attr = element.attributes[i]; 29790 if (this.ATTR_WATCH.indexOf(attr.name) === -1) { 29791 pathTag.setAttribute(attr.name, attr.value); 29792 } 29793 } 29794 for(i in pathData) { 29795 pathTag.setAttribute(i, pathData[i]); 29796 } 29797 return pathTag; 29798}; 29799 29800/** 29801 * Parse attributes of a DOM element to 29802 * get an object of attribute => value 29803 * 29804 * @param {NamedNodeMap} attributes Attributes object from DOM element to parse 29805 * @return {object} Object of attributes 29806 */ 29807Pathformer.prototype.parseAttr = function (element) { 29808 var attr, output = {}; 29809 for (var i = 0; i < element.length; i++) { 29810 attr = element[i]; 29811 // Check if no data attribute contains '%', or the transformation is impossible 29812 if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) { 29813 throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.'); 29814 } 29815 output[attr.name] = attr.value; 29816 } 29817 return output; 29818}; 29819 29820 'use strict'; 29821 29822var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt; 29823 29824/** 29825 * Vivus 29826 * Beta version 29827 * 29828 * Take any SVG and make the animation 29829 * to give give the impression of live drawing 29830 * 29831 * This in more than just inspired from codrops 29832 * At that point, it's a pure fork. 29833 */ 29834 29835/** 29836 * Class constructor 29837 * option structure 29838 * type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed) 29839 * duration: <int> (in frames) 29840 * start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport) 29841 * delay: <int> (delay between the drawing of first and last path) 29842 * dashGap <integer> whitespace extra margin between dashes 29843 * pathTimingFunction <function> timing animation function for each path element of the SVG 29844 * animTimingFunction <function> timing animation function for the complete SVG 29845 * forceRender <boolean> force the browser to re-render all updated path items 29846 * selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original 29847 * 29848 * The attribute 'type' is by default on 'delayed'. 29849 * - 'delayed' 29850 * all paths are draw at the same time but with a 29851 * little delay between them before start 29852 * - 'sync' 29853 * all path are start and finish at the same time 29854 * - 'oneByOne' 29855 * only one path is draw at the time 29856 * the end of the first one will trigger the draw 29857 * of the next one 29858 * 29859 * All these values can be overwritten individually 29860 * for each path item in the SVG 29861 * The value of frames will always take the advantage of 29862 * the duration value. 29863 * If you fail somewhere, an error will be thrown. 29864 * Good luck. 29865 * 29866 * @constructor 29867 * @this {Vivus} 29868 * @param {DOM|String} element Dom element of the SVG or id of it 29869 * @param {Object} options Options about the animation 29870 * @param {Function} callback Callback for the end of the animation 29871 */ 29872function Vivus (element, options, callback) { 29873 29874 setupEnv(); 29875 29876 // Setup 29877 this.isReady = false; 29878 this.setElement(element, options); 29879 this.setOptions(options); 29880 this.setCallback(callback); 29881 29882 if (this.isReady) { 29883 this.init(); 29884 } 29885} 29886 29887/** 29888 * Timing functions 29889 ************************************** 29890 * 29891 * Default functions to help developers. 29892 * It always take a number as parameter (between 0 to 1) then 29893 * return a number (between 0 and 1) 29894 */ 29895Vivus.LINEAR = function (x) {return x;}; 29896Vivus.EASE = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;}; 29897Vivus.EASE_OUT = function (x) {return 1 - Math.pow(1-x, 3);}; 29898Vivus.EASE_IN = function (x) {return Math.pow(x, 3);}; 29899Vivus.EASE_OUT_BOUNCE = function (x) { 29900 var base = -Math.cos(x * (0.5 * Math.PI)) + 1, 29901 rate = Math.pow(base,1.5), 29902 rateR = Math.pow(1 - x, 2), 29903 progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1; 29904 return (1- rateR) + (progress * rateR); 29905}; 29906 29907 29908/** 29909 * Setters 29910 ************************************** 29911 */ 29912 29913/** 29914 * Check and set the element in the instance 29915 * The method will not return anything, but will throw an 29916 * error if the parameter is invalid 29917 * 29918 * @param {DOM|String} element SVG Dom element or id of it 29919 */ 29920Vivus.prototype.setElement = function (element, options) { 29921 var onLoad, self; 29922 29923 // Basic check 29924 if (typeof element === 'undefined') { 29925 throw new Error('Vivus [constructor]: "element" parameter is required'); 29926 } 29927 29928 // Set the element 29929 if (element.constructor === String) { 29930 element = document.getElementById(element); 29931 if (!element) { 29932 throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID'); 29933 } 29934 } 29935 this.parentEl = element; 29936 29937 // Load the SVG with XMLHttpRequest and extract the SVG 29938 if (options && options.file) { 29939 var self = this; 29940 onLoad = function (e) { 29941 var domSandbox = document.createElement('div'); 29942 domSandbox.innerHTML = this.responseText; 29943 29944 var svgTag = domSandbox.querySelector('svg'); 29945 if (!svgTag) { 29946 throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file); 29947 } 29948 29949 self.el = svgTag 29950 self.el.setAttribute('width', '100%'); 29951 self.el.setAttribute('height', '100%'); 29952 self.parentEl.appendChild(self.el) 29953 self.isReady = true; 29954 self.init(); 29955 self = null; 29956 } 29957 29958 var oReq = new window.XMLHttpRequest(); 29959 oReq.addEventListener('load', onLoad); 29960 oReq.open('GET', options.file); 29961 oReq.send(); 29962 return; 29963 } 29964 29965 switch (element.constructor) { 29966 case window.SVGSVGElement: 29967 case window.SVGElement: 29968 case window.SVGGElement: 29969 this.el = element; 29970 this.isReady = true; 29971 break; 29972 29973 case window.HTMLObjectElement: 29974 self = this; 29975 onLoad = function (e) { 29976 if (self.isReady) { 29977 return; 29978 } 29979 self.el = element.contentDocument && element.contentDocument.querySelector('svg'); 29980 if (!self.el && e) { 29981 throw new Error('Vivus [constructor]: object loaded does not contain any SVG'); 29982 } 29983 else if (self.el) { 29984 if (element.getAttribute('built-by-vivus')) { 29985 self.parentEl.insertBefore(self.el, element); 29986 self.parentEl.removeChild(element); 29987 self.el.setAttribute('width', '100%'); 29988 self.el.setAttribute('height', '100%'); 29989 } 29990 self.isReady = true; 29991 self.init(); 29992 self = null; 29993 } 29994 }; 29995 29996 if (!onLoad()) { 29997 element.addEventListener('load', onLoad); 29998 } 29999 break; 30000 30001 default: 30002 throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)'); 30003 } 30004}; 30005 30006/** 30007 * Set up user option to the instance 30008 * The method will not return anything, but will throw an 30009 * error if the parameter is invalid 30010 * 30011 * @param {object} options Object from the constructor 30012 */ 30013Vivus.prototype.setOptions = function (options) { 30014 var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync']; 30015 var allowedStarts = ['inViewport', 'manual', 'autostart']; 30016 30017 // Basic check 30018 if (options !== undefined && options.constructor !== Object) { 30019 throw new Error('Vivus [constructor]: "options" parameter must be an object'); 30020 } 30021 else { 30022 options = options || {}; 30023 } 30024 30025 // Set the animation type 30026 if (options.type && allowedTypes.indexOf(options.type) === -1) { 30027 throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`'); 30028 } 30029 else { 30030 this.type = options.type || allowedTypes[0]; 30031 } 30032 30033 // Set the start type 30034 if (options.start && allowedStarts.indexOf(options.start) === -1) { 30035 throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option'); 30036 } 30037 else { 30038 this.start = options.start || allowedStarts[0]; 30039 } 30040 30041 this.isIE = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 ); 30042 this.duration = parsePositiveInt(options.duration, 120); 30043 this.delay = parsePositiveInt(options.delay, null); 30044 //Uncode addition 30045 this.delayStart = parsePositiveInt(options.delayStart, null); 30046 //#END 30047 this.dashGap = parsePositiveInt(options.dashGap, 1); 30048 this.forceRender = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE; 30049 this.reverseStack = !!options.reverseStack; 30050 this.selfDestroy = !!options.selfDestroy; 30051 this.onReady = options.onReady; 30052 this.map = []; 30053 this.frameLength = this.currentFrame = this.delayUnit = this.speed = this.handle = null; 30054 30055 this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false; 30056 30057 this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR; 30058 this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR; 30059 30060 if (this.delay >= this.duration) { 30061 throw new Error('Vivus [constructor]: delay must be shorter than duration'); 30062 } 30063}; 30064 30065/** 30066 * Set up callback to the instance 30067 * The method will not return enything, but will throw an 30068 * error if the parameter is invalid 30069 * 30070 * @param {Function} callback Callback for the animation end 30071 */ 30072Vivus.prototype.setCallback = function (callback) { 30073 // Basic check 30074 if (!!callback && callback.constructor !== Function) { 30075 throw new Error('Vivus [constructor]: "callback" parameter must be a function'); 30076 } 30077 this.callback = callback || function () {}; 30078}; 30079 30080 30081/** 30082 * Core 30083 ************************************** 30084 */ 30085 30086/** 30087 * Map the svg, path by path. 30088 * The method return nothing, it just fill the 30089 * `map` array. Each item in this array represent 30090 * a path element from the SVG, with informations for 30091 * the animation. 30092 * 30093 * ``` 30094 * [ 30095 * { 30096 * el: <DOMobj> the path element 30097 * length: <number> length of the path line 30098 * startAt: <number> time start of the path animation (in frames) 30099 * duration: <number> path animation duration (in frames) 30100 * }, 30101 * ... 30102 * ] 30103 * ``` 30104 * 30105 */ 30106Vivus.prototype.mapping = function () { 30107 var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint; 30108 timePoint = totalLength = lengthMeter = 0; 30109 paths = this.el.querySelectorAll('path'); 30110 30111 for (i = 0; i < paths.length; i++) { 30112 path = paths[i]; 30113 if (this.isInvisible(path)) { 30114 continue; 30115 } 30116 pathObj = { 30117 el: path, 30118 length: Math.ceil(path.getTotalLength()) 30119 }; 30120 // Test if the path length is correct 30121 if (isNaN(pathObj.length)) { 30122 if (window.console && console.warn) { 30123 console.warn('Vivus [mapping]: cannot retrieve a path element length', path); 30124 } 30125 continue; 30126 } 30127 this.map.push(pathObj); 30128 path.style.strokeDasharray = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2); 30129 path.style.strokeDashoffset = pathObj.length + this.dashGap; 30130 pathObj.length += this.dashGap; 30131 totalLength += pathObj.length; 30132 30133 this.renderPath(i); 30134 } 30135 30136 totalLength = totalLength === 0 ? 1 : totalLength; 30137 this.delay = this.delay === null ? this.duration / 3 : this.delay; 30138 this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1); 30139 30140 // Reverse stack if asked 30141 if (this.reverseStack) { 30142 this.map.reverse(); 30143 } 30144 30145 for (i = 0; i < this.map.length; i++) { 30146 pathObj = this.map[i]; 30147 30148 switch (this.type) { 30149 case 'delayed': 30150 pathObj.startAt = this.delayUnit * i; 30151 pathObj.duration = this.duration - this.delay; 30152 break; 30153 30154 case 'oneByOne': 30155 pathObj.startAt = lengthMeter / totalLength * this.duration; 30156 pathObj.duration = pathObj.length / totalLength * this.duration; 30157 break; 30158 30159 case 'sync': 30160 case 'async': 30161 case 'nsync': 30162 pathObj.startAt = 0; 30163 pathObj.duration = this.duration; 30164 break; 30165 30166 case 'scenario-sync': 30167 path = pathObj.el; 30168 pAttrs = this.parseAttr(path); 30169 pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0); 30170 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 30171 timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration; 30172 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 30173 break; 30174 30175 case 'scenario': 30176 path = pathObj.el; 30177 pAttrs = this.parseAttr(path); 30178 pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0; 30179 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 30180 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 30181 break; 30182 } 30183 lengthMeter += pathObj.length; 30184 this.frameLength = this.frameLength || this.duration; 30185 } 30186}; 30187 30188/** 30189 * Interval method to draw the SVG from current 30190 * position of the animation. It update the value of 30191 * `currentFrame` and re-trace the SVG. 30192 * 30193 * It use this.handle to store the requestAnimationFrame 30194 * and clear it one the animation is stopped. So this 30195 * attribute can be used to know if the animation is 30196 * playing. 30197 * 30198 * Once the animation at the end, this method will 30199 * trigger the Vivus callback. 30200 * 30201 */ 30202Vivus.prototype.drawer = function () { 30203 var self = this; 30204 this.currentFrame += this.speed; 30205 30206 if (this.currentFrame <= 0) { 30207 this.stop(); 30208 this.reset(); 30209 } else if (this.currentFrame >= this.frameLength) { 30210 this.stop(); 30211 this.currentFrame = this.frameLength; 30212 this.trace(); 30213 if (this.selfDestroy) { 30214 this.destroy(); 30215 } 30216 } else { 30217 this.trace(); 30218 this.handle = requestAnimFrame(function () { 30219 self.drawer(); 30220 }); 30221 return; 30222 } 30223 30224 this.callback(this); 30225 if (this.instanceCallback) { 30226 this.instanceCallback(this); 30227 this.instanceCallback = null; 30228 } 30229}; 30230 30231/** 30232 * Draw the SVG at the current instant from the 30233 * `currentFrame` value. Here is where most of the magic is. 30234 * The trick is to use the `strokeDashoffset` style property. 30235 * 30236 * For optimisation reasons, a new property called `progress` 30237 * is added in each item of `map`. This one contain the current 30238 * progress of the path element. Only if the new value is different 30239 * the new value will be applied to the DOM element. This 30240 * method save a lot of resources to re-render the SVG. And could 30241 * be improved if the animation couldn't be played forward. 30242 * 30243 */ 30244Vivus.prototype.trace = function () { 30245 var i, progress, path, currentFrame; 30246 currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength; 30247 for (i = 0; i < this.map.length; i++) { 30248 path = this.map[i]; 30249 progress = (currentFrame - path.startAt) / path.duration; 30250 progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress))); 30251 if (path.progress !== progress) { 30252 path.progress = progress; 30253 path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress)); 30254 this.renderPath(i); 30255 } 30256 } 30257}; 30258 30259/** 30260 * Method forcing the browser to re-render a path element 30261 * from it's index in the map. Depending on the `forceRender` 30262 * value. 30263 * The trick is to replace the path element by it's clone. 30264 * This practice is not recommended because it's asking more 30265 * ressources, too much DOM manupulation.. 30266 * but it's the only way to let the magic happen on IE. 30267 * By default, this fallback is only applied on IE. 30268 * 30269 * @param {Number} index Path index 30270 */ 30271Vivus.prototype.renderPath = function (index) { 30272 if (this.forceRender && this.map && this.map[index]) { 30273 var pathObj = this.map[index], 30274 newPath = pathObj.el.cloneNode(true); 30275 pathObj.el.parentNode.replaceChild(newPath, pathObj.el); 30276 pathObj.el = newPath; 30277 } 30278}; 30279 30280/** 30281 * When the SVG object is loaded and ready, 30282 * this method will continue the initialisation. 30283 * 30284 * This this mainly due to the case of passing an 30285 * object tag in the constructor. It will wait 30286 * the end of the loading to initialise. 30287 * 30288 */ 30289Vivus.prototype.init = function () { 30290 // Set object variables 30291 this.frameLength = 0; 30292 this.currentFrame = 0; 30293 this.map = []; 30294 30295 // Start 30296 new Pathformer(this.el); 30297 this.mapping(); 30298 this.starter(); 30299 30300 if (this.onReady) { 30301 this.onReady(this); 30302 } 30303}; 30304 30305/** 30306 * Trigger to start of the animation. 30307 * Depending on the `start` value, a different script 30308 * will be applied. 30309 * 30310 * If the `start` value is not valid, an error will be thrown. 30311 * Even if technically, this is impossible. 30312 * 30313 */ 30314Vivus.prototype.starter = function () { 30315 switch (this.start) { 30316 case 'manual': 30317 return; 30318 30319 case 'autostart': 30320 this.play(); 30321 break; 30322 30323 case 'inViewport': 30324 var self = this, 30325 listener = function () { 30326 if (self.isInViewport(self.parentEl, 1)) { 30327 self.play(); 30328 window.removeEventListener('scroll', listener); 30329 //Uncode addition 30330 window.removeEventListener('fp-slide-changed', listener); 30331 window.removeEventListener('fp-slide-scroll', listener); 30332 //#END 30333 } 30334 }; 30335 window.addEventListener('scroll', listener); 30336 //Uncode addition 30337 window.addEventListener('fp-slide-changed', listener); 30338 window.addEventListener('fp-slide-scroll', listener); 30339 //#END 30340 listener(); 30341 break; 30342 } 30343}; 30344 30345 30346/** 30347 * Controls 30348 ************************************** 30349 */ 30350 30351/** 30352 * Get the current status of the animation between 30353 * three different states: 'start', 'progress', 'end'. 30354 * @return {string} Instance status 30355 */ 30356Vivus.prototype.getStatus = function () { 30357 return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress'; 30358}; 30359 30360/** 30361 * Reset the instance to the initial state : undraw 30362 * Be careful, it just reset the animation, if you're 30363 * playing the animation, this won't stop it. But just 30364 * make it start from start. 30365 * 30366 */ 30367Vivus.prototype.reset = function () { 30368 return this.setFrameProgress(0); 30369}; 30370 30371/** 30372 * Set the instance to the final state : drawn 30373 * Be careful, it just set the animation, if you're 30374 * playing the animation on rewind, this won't stop it. 30375 * But just make it start from the end. 30376 * 30377 */ 30378Vivus.prototype.finish = function () { 30379 return this.setFrameProgress(1); 30380}; 30381 30382/** 30383 * Set the level of progress of the drawing. 30384 * 30385 * @param {number} progress Level of progress to set 30386 */ 30387Vivus.prototype.setFrameProgress = function (progress) { 30388 progress = Math.min(1, Math.max(0, progress)); 30389 this.currentFrame = Math.round(this.frameLength * progress); 30390 this.trace(); 30391 return this; 30392}; 30393 30394/** 30395 * Play the animation at the desired speed. 30396 * Speed must be a valid number (no zero). 30397 * By default, the speed value is 1. 30398 * But a negative value is accepted to go forward. 30399 *
30400 * And works with float too. 30401 * But don't forget we are in JavaScript, se be nice 30402 * with him and give him a 1/2^x value. 30403 * 30404 * @param {number} speed Animation speed [optional] 30405 */ 30406Vivus.prototype.play = function (speed, callback) { 30407 this.instanceCallback = null; 30408 30409 if (speed && typeof speed === 'function') { 30410 this.instanceCallback = speed; // first parameter is actually the callback function 30411 speed = null; 30412 } 30413 else if (speed && typeof speed !== 'number') { 30414 throw new Error('Vivus [play]: invalid speed'); 30415 } 30416 // if the first parameter wasn't the callback, check if the seconds was 30417 if (callback && typeof(callback) === 'function' && !this.instanceCallback) { 30418 this.instanceCallback = callback; 30419 } 30420 30421 30422 this.speed = speed || 1; 30423 //Uncode addition 30424 if (!this.handle) { 30425 var $this = this, 30426 delay = (this.delayStart != null) ? this.delayStart : 0; 30427 setTimeout(function() { 30428 $this.drawer(); 30429 }, delay); 30430 } 30431 //#END 30432 return this; 30433}; 30434 30435/** 30436 * Stop the current animation, if on progress. 30437 * Should not trigger any error. 30438 * 30439 */ 30440Vivus.prototype.stop = function () { 30441 if (this.handle) { 30442 cancelAnimFrame(this.handle); 30443 this.handle = null; 30444 } 30445 return this; 30446}; 30447 30448/** 30449 * Destroy the instance. 30450 * Remove all bad styling attributes on all 30451 * path tags 30452 * 30453 */ 30454Vivus.prototype.destroy = function () { 30455 this.stop(); 30456 var i, path; 30457 for (i = 0; i < this.map.length; i++) { 30458 path = this.map[i]; 30459 path.el.style.strokeDashoffset = null; 30460 path.el.style.strokeDasharray = null; 30461 this.renderPath(i); 30462 } 30463}; 30464 30465 30466/** 30467 * Utils methods 30468 * include methods from Codrops 30469 ************************************** 30470 */ 30471 30472/** 30473 * Method to best guess if a path should added into 30474 * the animation or not. 30475 * 30476 * 1. Use the `data-vivus-ignore` attribute if set 30477 * 2. Check if the instance must ignore invisible paths 30478 * 3. Check if the path is visible 30479 * 30480 * For now the visibility checking is unstable. 30481 * It will be used for a beta phase. 30482 * 30483 * Other improvments are planned. Like detecting 30484 * is the path got a stroke or a valid opacity. 30485 */ 30486Vivus.prototype.isInvisible = function (el) { 30487 var rect, 30488 ignoreAttr = el.getAttribute('data-ignore'); 30489 30490 if (ignoreAttr !== null) { 30491 return ignoreAttr !== 'false'; 30492 } 30493 30494 if (this.ignoreInvisible) { 30495 rect = el.getBoundingClientRect(); 30496 return !rect.width && !rect.height; 30497 } 30498 else { 30499 return false; 30500 } 30501}; 30502 30503/** 30504 * Parse attributes of a DOM element to 30505 * get an object of {attributeName => attributeValue} 30506 * 30507 * @param {object} element DOM element to parse 30508 * @return {object} Object of attributes 30509 */ 30510Vivus.prototype.parseAttr = function (element) { 30511 var attr, output = {}; 30512 if (element && element.attributes) { 30513 for (var i = 0; i < element.attributes.length; i++) { 30514 attr = element.attributes[i]; 30515 output[attr.name] = attr.value; 30516 } 30517 } 30518 return output; 30519}; 30520 30521/** 30522 * Reply if an element is in the page viewport 30523 * 30524 * @param {object} el Element to observe 30525 * @param {number} h Percentage of height 30526 * @return {boolean} 30527 */ 30528Vivus.prototype.isInViewport = function (el, h) { 30529 var scrolled = this.scrollY(), 30530 viewed = scrolled + this.getViewportH(), 30531 elBCR = el.getBoundingClientRect(), 30532 elHeight = elBCR.height, 30533 elTop = scrolled + elBCR.top, 30534 elBottom = elTop + elHeight; 30535 30536 // if 0, the element is considered in the viewport as soon as it enters. 30537 // if 1, the element is considered in the viewport only when it's fully inside 30538 // value in percentage (1 >= h >= 0) 30539 h = h || 0; 30540 30541 return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled; 30542}; 30543 30544 30545/** 30546 * Get the viewport height in pixels 30547 * 30548 * @return {integer} Viewport height 30549 */ 30550Vivus.prototype.getViewportH = function () { 30551 var client = this.docElem.clientHeight, 30552 inner = window.innerHeight; 30553 30554 if (client < inner) { 30555 return inner; 30556 } 30557 else { 30558 return client; 30559 } 30560}; 30561 30562/** 30563 * Get the page Y offset 30564 * 30565 * @return {integer} Page Y offset 30566 */ 30567Vivus.prototype.scrollY = function () { 30568 return window.pageYOffset || this.docElem.scrollTop; 30569}; 30570 30571setupEnv = function () { 30572 30573 if (Vivus.prototype.docElem) { 30574 return; 30575 } 30576 30577 /** 30578 * Alias for document element 30579 * 30580 * @type {DOMelement} 30581 */ 30582 Vivus.prototype.docElem = window.document.documentElement; 30583 30584 /** 30585 * Alias for `requestAnimationFrame` or 30586 * `setTimeout` function for deprecated browsers. 30587 * 30588 */ 30589 requestAnimFrame = (function () { 30590 return ( 30591 window.requestAnimationFrame || 30592 window.webkitRequestAnimationFrame || 30593 window.mozRequestAnimationFrame || 30594 window.oRequestAnimationFrame || 30595 window.msRequestAnimationFrame || 30596 function(/* function */ callback){ 30597 return window.setTimeout(callback, 1000 / 60); 30598 } 30599 ); 30600 })(); 30601 30602 /** 30603 * Alias for `cancelAnimationFrame` or 30604 * `cancelTimeout` function for deprecated browsers. 30605 * 30606 */ 30607 cancelAnimFrame = (function () { 30608 return ( 30609 window.cancelAnimationFrame || 30610 window.webkitCancelAnimationFrame || 30611 window.mozCancelAnimationFrame || 30612 window.oCancelAnimationFrame || 30613 window.msCancelAnimationFrame || 30614 function(id){ 30615 return window.clearTimeout(id); 30616 } 30617 ); 30618 })(); 30619}; 30620 30621/** 30622 * Parse string to integer. 30623 * If the number is not positive or null 30624 * the method will return the default value 30625 * or 0 if undefined 30626 * 30627 * @param {string} value String to parse 30628 * @param {*}
30628 defaultValue Value to return if the result parsed is invalid 30629 * @return {number} 30630 * 30631 */ 30632parsePositiveInt = function (value, defaultValue) { 30633 var output = parseInt(value, 10); 30634 return (output >= 0) ? output : defaultValue; 30635}; 30636 30637 30638 if (typeof define === 'function' && define.amd) { 30639 // AMD. Register as an anonymous module. 30640 define([], function() { 30641 return Vivus; 30642 }); 30643 } else if (typeof exports === 'object') { 30644 // Node. Does not work with strict CommonJS, but 30645 // only CommonJS-like environments that support module.exports, 30646 // like Node. 30647 module.exports = Vivus; 30648 } else { 30649 // Browser globals 30650 window.Vivus = Vivus; 30651 } 30652 30653}());
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.