vendor: 10,254 bytes, lines 1-290
1/*! iScroll v5.2.0-snapshot ~ (c) 2008-2017 Matteo Spinelli ~ http://cubiq.org/license */ 2(function (window, document, Math) { 3 var rAF = window.requestAnimationFrame || 4 window.webkitRequestAnimationFrame || 5 window.mozRequestAnimationFrame || 6 window.oRequestAnimationFrame || 7 window.msRequestAnimationFrame || 8 function (callback) { 9 window.setTimeout(callback, 1000 / 60); 10 }; 11 12 var utils = (function () { 13 var me = {}; 14 15 var _elementStyle = document.createElement('div').style; 16 var _vendor = (function () { 17 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 18 transform, 19 i = 0, 20 l = vendors.length; 21 22 for (; i < l; i++) { 23 transform = vendors[i] + 'ransform'; 24 if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1); 25 } 26 27 return false; 28 })(); 29 30 function _prefixStyle(style) { 31 if (_vendor === false) return false; 32 if (_vendor === '') return style; 33 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 34 } 35 36 me.getTime = Date.now || function getTime() { 37 return new Date().getTime(); 38 }; 39 40 me.extend = function (target, obj) { 41 for (var i in obj) { 42 target[i] = obj[i]; 43 } 44 }; 45 46 me.addEvent = function (el, type, fn, capture) { 47 el.addEventListener(type, fn, !!capture); 48 }; 49 50 me.removeEvent = function (el, type, fn, capture) { 51 el.removeEventListener(type, fn, !!capture); 52 }; 53 54 me.prefixPointerEvent = function (pointerEvent) { 55 return window.MSPointerEvent ? 56 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8) : 57 pointerEvent; 58 }; 59 60 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 61 var distance = current - start, 62 speed = Math.abs(distance) / time, 63 destination, 64 duration; 65 66 deceleration = deceleration === undefined ? 0.0006 : deceleration; 67 68 destination = current + (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1); 69 duration = speed / deceleration; 70 71 if (destination < lowerMargin) { 72 destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin; 73 distance = Math.abs(destination - current); 74 duration = distance / speed; 75 } else if (destination > 0) { 76 destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0; 77 distance = Math.abs(current) + destination; 78 duration = distance / speed; 79 } 80 81 return { 82 destination: Math.round(destination), 83 duration: duration 84 }; 85 }; 86 87 var _transform = _prefixStyle('transform'); 88 89 me.extend(me, { 90 hasTransform: _transform !== false, 91 hasPerspective: _prefixStyle('perspective') in _elementStyle, 92 hasTouch: 'ontouchstart' in window, 93 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 94 hasTransition: _prefixStyle('transition') in _elementStyle 95 }); 96 97 /* 98 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 99 - galaxy S2 is ok 100 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 101 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 102 - galaxy S3 is badAndroid (stock brower, webview) 103 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 104 - galaxy S4 is badAndroid (stock brower, webview) 105 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 106 - galaxy S5 is OK 107 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 108 - galaxy S6 is OK 109 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 110 */ 111 me.isBadAndroid = (function () { 112 var appVersion = window.navigator.appVersion; 113 // Android browser is not a chrome browser. 114 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 115 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 116 if (safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 117 return parseFloat(safariVersion[1]) < 535.19; 118 } else { 119 return true; 120 } 121 } else { 122 return false; 123 } 124 })(); 125 126 me.extend(me.style = {}, { 127 transform: _transform, 128 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 129 transitionDuration: _prefixStyle('transitionDuration'), 130 transitionDelay: _prefixStyle('transitionDelay'), 131 transformOrigin: _prefixStyle('transformOrigin'), 132 touchAction: _prefixStyle('touchAction') 133 }); 134 135 me.hasClass = function (e, c) { 136 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 137 return re.test(e.className); 138 }; 139 140 me.addClass = function (e, c) { 141 if (me.hasClass(e, c)) { 142 return; 143 } 144 145 var newclass = e.className.split(' '); 146 newclass.push(c); 147 e.className = newclass.join(' '); 148 }; 149 150 me.removeClass = function (e, c) { 151 if (!me.hasClass(e, c)) { 152 return; 153 } 154 155 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 156 e.className = e.className.replace(re, ' '); 157 }; 158 159 me.offset = function (el) { 160 var left = -el.offsetLeft, 161 top = -el.offsetTop; 162 163 // jshint -W084 164 while (el = el.offsetParent) { 165 left -= el.offsetLeft; 166 top -= el.offsetTop; 167 } 168 // jshint +W084 169 170 return { 171 left: left, 172 top: top 173 }; 174 }; 175 176 me.preventDefaultException = function (el, exceptions) { 177 for (var i in exceptions) { 178 if (exceptions[i].test(el[i])) { 179 return true; 180 } 181 } 182 183 return false; 184 }; 185 186 me.extend(me.eventType = {}, { 187 touchstart: 1, 188 touchmove: 1, 189 touchend: 1, 190 191 mousedown: 2, 192 mousemove: 2, 193 mouseup: 2, 194 195 pointerdown: 3, 196 pointermove: 3, 197 pointerup: 3, 198 199 MSPointerDown: 3, 200 MSPointerMove: 3, 201 MSPointerUp: 3 202 }); 203 204 me.extend(me.ease = {}, { 205 quadratic: { 206 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 207 fn: function (k) { 208 return k * (2 - k); 209 } 210 }, 211 circular: { 212 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) 213 fn: function (k) { 214 return Math.sqrt(1 - (--k * k)); 215 } 216 }, 217 back: { 218 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 219 fn: function (k) { 220 var b = 4; 221 return (k = k - 1) * k * ((b + 1) * k + b) + 1; 222 } 223 }, 224 bounce: { 225 style: '', 226 fn: function (k) { 227 if ((k /= 1) < (1 / 2.75)) { 228 return 7.5625 * k * k; 229 } else if (k < (2 / 2.75)) { 230 return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; 231 } else if (k < (2.5 / 2.75)) { 232 return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; 233 } else { 234 return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; 235 } 236 } 237 }, 238 elastic: { 239 style: '', 240 fn: function (k) { 241 var f = 0.22, 242 e = 0.4; 243 244 if (k === 0) { 245 return 0; 246 } 247 if (k == 1) { 248 return 1; 249 } 250 251 return (e * Math.pow(2, -10 * k) * Math.sin((k - f / 4) * (2 * Math.PI) / f) + 1); 252 } 253 } 254 }); 255 256 me.tap = function (e, eventName) { 257 var ev = document.createEvent('Event'); 258 ev.initEvent(eventName, true, true); 259 ev.pageX = e.pageX; 260 ev.pageY = e.pageY; 261 e.target.dispatchEvent(ev); 262 }; 263 264 me.click = function (e) { 265 var target = e.target, 266 ev; 267 268 if (!(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName)) { 269 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 270 // initMouseEvent is deprecated. 271 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 272 ev.initEvent('click', true, true); 273 ev.view = e.view || window; 274 ev.detail = 1; 275 ev.screenX = target.screenX || 0; 276 ev.screenY = target.screenY || 0; 277 ev.clientX = target.clientX || 0; 278 ev.clientY = target.clientY || 0; 279 ev.ctrlKey = !!e.ctrlKey; 280 ev.altKey = !!e.altKey; 281 ev.shiftKey = !!e.shiftKey; 282 ev.metaKey = !!e.metaKey; 283 ev.button = 0; 284 ev.relatedTarget = null; 285 ev._constructed = true; 286 target.dispatchEvent(ev); 287 } 288 }; 289 290 me.getTouchAction = function (eventPassthrough, addPinch) {
291 var touchAction = 'none'; 292 if (eventPassthrough === 'vertical') { 293 touchAction = 'pan-y'; 294 } else if (eventPassthrough === 'horizontal') { 295 touchAction = 'pan-x'; 296 } 297 if (addPinch && touchAction != 'none') { 298 // add pinch-zoom support if the browser supports it, but if not (eg. Chrome <55) do nothing 299 touchAction += ' pinch-zoom'; 300 } 301 return touchAction; 302 }; 303 304 me.getRect = function (el) { 305 if (el instanceof SVGElement) { 306 var rect = el.getBoundingClientRect(); 307 return { 308 top: rect.top, 309 left: rect.left, 310 width: rect.width, 311 height: rect.height 312 }; 313 } else { 314 return { 315 top: el.offsetTop, 316 left: el.offsetLeft, 317 width: el.offsetWidth, 318 height: el.offsetHeight 319 }; 320 } 321 }; 322 323 return me; 324 })(); 325 326 function IScroll(el, options) { 327 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 328 this.scroller = this.wrapper.children[0]; 329 this.scrollerStyle = this.scroller.style; // cache style for better performance 330 331 this.options = { 332 333 resizeScrollbars: true, 334 335 mouseWheelSpeed: 20, 336 337 snapThreshold: 0.334, 338 339 // INSERT POINT: OPTIONS 340 disablePointer: !utils.hasPointer, 341 disableTouch: utils.hasPointer || !utils.hasTouch, 342 disableMouse: utils.hasPointer || utils.hasTouch, 343 startX: 0, 344 startY: 0, 345 scrollY: true, 346 directionLockThreshold: 5, 347 momentum: true, 348 349 bounce: true, 350 bounceTime: 600, 351 bounceEasing: '', 352 353 preventDefault: true, 354 preventDefaultException: { 355 tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ 356 }, 357 358 HWCompositing: true, 359 useTransition: true, 360 useTransform: true, 361 bindToWrapper: typeof window.onmousedown === "undefined" 362 }; 363 364 for (var i in options) { 365 this.options[i] = options[i]; 366 } 367 368 // Normalize options 369 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 370 371 this.options.useTransition = utils.hasTransition && this.options.useTransition; 372 this.options.useTransform = utils.hasTransform && this.options.useTransform; 373 374 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 375 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 376 377 // If you want eventPassthrough I have to lock one of the axes 378 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 379 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 380 381 // With eventPassthrough we also need lockDirection mechanism 382 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 383 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 384 385 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 386 387 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 388 389 if (this.options.tap === true) { 390 this.options.tap = 'tap'; 391 } 392 393 // https://github.com/cubiq/iscroll/issues/1029 394 if (!this.options.useTransition && !this.options.useTransform) { 395 if (!(/relative|absolute/i).test(this.scrollerStyle.position)) { 396 this.scrollerStyle.position = "relative"; 397 } 398 } 399 400 if (this.options.shrinkScrollbars == 'scale') { 401 this.options.useTransition = false;
vendor: 4,951 bytes, lines 402-561
402 } 403 404 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 405 406 // INSERT POINT: NORMALIZATION 407 408 // Some defaults 409 this.x = 0; 410 this.y = 0; 411 this.directionX = 0; 412 this.directionY = 0; 413 this._events = {}; 414 415 // INSERT POINT: DEFAULTS 416 417 this._init(); 418 this.refresh(); 419 420 this.scrollTo(this.options.startX, this.options.startY); 421 this.enable(); 422 } 423 424 IScroll.prototype = { 425 version: '5.2.0-snapshot', 426 427 _init: function () { 428 this._initEvents(); 429 430 if (this.options.scrollbars || this.options.indicators) { 431 this._initIndicators(); 432 } 433 434 if (this.options.mouseWheel) { 435 this._initWheel(); 436 } 437 438 if (this.options.snap) { 439 this._initSnap(); 440 } 441 442 if (this.options.keyBindings) { 443 this._initKeys(); 444 } 445 446 // INSERT POINT: _init 447 448 }, 449 450 destroy: function () { 451 this._initEvents(true); 452 clearTimeout(this.resizeTimeout); 453 this.resizeTimeout = null; 454 this._execEvent('destroy'); 455 }, 456 457 _transitionEnd: function (e) { 458 if (e.target != this.scroller || !this.isInTransition) { 459 return; 460 } 461 462 this._transitionTime(); 463 if (!this.resetPosition(this.options.bounceTime)) { 464 this.isInTransition = false; 465 this._execEvent('scrollEnd'); 466 } 467 }, 468 469 _start: function (e) { 470 // React to left mouse button only 471 if (utils.eventType[e.type] != 1) { 472 // for button property 473 // http://unixpapa.com/js/mouse.html 474 var button; 475 if (!e.which) { 476 /* IE case */ 477 button = (e.button < 2) ? 0 : 478 ((e.button == 4) ? 1 : 2); 479 } else { 480 /* All others */ 481 button = e.button; 482 } 483 if (button !== 0) { 484 return; 485 } 486 } 487 488 if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) { 489 return; 490 } 491 492 if (this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) { 493 e.preventDefault(); 494 } 495 496 var point = e.touches ? e.touches[0] : e, 497 pos; 498 499 this.initiated = utils.eventType[e.type]; 500 this.moved = false; 501 this.distX = 0; 502 this.distY = 0; 503 this.directionX = 0; 504 this.directionY = 0; 505 this.directionLocked = 0; 506 507 this.startTime = utils.getTime(); 508 509 if (this.options.useTransition && this.isInTransition) { 510 this._transitionTime(); 511 this.isInTransition = false; 512 pos = this.getComputedPosition(); 513 this._translate(Math.round(pos.x), Math.round(pos.y)); 514 this._execEvent('scrollEnd'); 515 } else if (!this.options.useTransition && this.isAnimating) { 516 this.isAnimating = false; 517 this._execEvent('scrollEnd'); 518 } 519 520 this.startX = this.x; 521 this.startY = this.y; 522 this.absStartX = this.x; 523 this.absStartY = this.y; 524 this.pointX = point.pageX; 525 this.pointY = point.pageY; 526 527 this._execEvent('beforeScrollStart'); 528 }, 529 530 _move: function (e) { 531 if (!this.enabled || utils.eventType[e.type] !== this.initiated) { 532 return; 533 } 534 535 if (this.options.preventDefault) { // increases performance on Android? TODO: check! 536 e.preventDefault(); 537 } 538 539 var point = e.touches ? e.touches[0] : e, 540 deltaX = point.pageX - this.pointX, 541 deltaY = point.pageY - this.pointY, 542 timestamp = utils.getTime(), 543 newX, newY, 544 absDistX, absDistY; 545 546 this.pointX = point.pageX; 547 this.pointY = point.pageY; 548 549 this.distX += deltaX; 550 this.distY += deltaY; 551 absDistX = Math.abs(this.distX); 552 absDistY = Math.abs(this.distY); 553 554 // We need to move at least 10 pixels for the scrolling to initiate 555 if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) { 556 return; 557 } 558 559 // If you are scrolling in one direction lock the other 560 if (!this.directionLocked && !this.options.freeScroll) { 561 if (absDistX > absDistY + this.options.directionLockThreshold) {
vendor: 4,162 bytes, lines 562-679
562 this.directionLocked = 'h'; // lock horizontally 563 } else if (absDistY >= absDistX + this.options.directionLockThreshold) { 564 this.directionLocked = 'v'; // lock vertically 565 } else { 566 this.directionLocked = 'n'; // no lock 567 } 568 } 569 570 if (this.directionLocked == 'h') { 571 if (this.options.eventPassthrough == 'vertical') { 572 e.preventDefault(); 573 } else if (this.options.eventPassthrough == 'horizontal') { 574 this.initiated = false; 575 return; 576 } 577 578 deltaY = 0; 579 } else if (this.directionLocked == 'v') { 580 if (this.options.eventPassthrough == 'horizontal') { 581 e.preventDefault(); 582 } else if (this.options.eventPassthrough == 'vertical') { 583 this.initiated = false; 584 return; 585 } 586 587 deltaX = 0; 588 } 589 590 deltaX = this.hasHorizontalScroll ? deltaX : 0; 591 deltaY = this.hasVerticalScroll ? deltaY : 0; 592 593 newX = this.x + deltaX; 594 newY = this.y + deltaY; 595 596 // Slow down if outside of the boundaries 597 if (newX > 0 || newX < this.maxScrollX) { 598 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 599 } 600 if (newY > 0 || newY < this.maxScrollY) { 601 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 602 } 603 604 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 605 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 606 607 if (!this.moved) { 608 this._execEvent('scrollStart'); 609 } 610 611 this.moved = true; 612 613 this._translate(newX, newY); 614 615 /* REPLACE START: _move */ 616 617 if (timestamp - this.startTime > 300) { 618 this.startTime = timestamp; 619 this.startX = this.x; 620 this.startY = this.y; 621 } 622 623 /* REPLACE END: _move */ 624 625 }, 626 627 _end: function (e) { 628 if (!this.enabled || utils.eventType[e.type] !== this.initiated) { 629 return; 630 } 631 632 if (this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) { 633 e.preventDefault(); 634 } 635 636 var point = e.changedTouches ? e.changedTouches[0] : e, 637 momentumX, 638 momentumY, 639 duration = utils.getTime() - this.startTime, 640 newX = Math.round(this.x), 641 newY = Math.round(this.y), 642 distanceX = Math.abs(newX - this.startX), 643 distanceY = Math.abs(newY - this.startY), 644 time = 0, 645 easing = ''; 646 647 this.isInTransition = 0; 648 this.initiated = 0; 649 this.endTime = utils.getTime(); 650 651 // reset if we are outside of the boundaries 652 if (this.resetPosition(this.options.bounceTime)) { 653 return; 654 } 655 656 this.scrollTo(newX, newY); // ensures that the last position is rounded 657 658 // we scrolled less than 10 pixels 659 if (!this.moved) { 660 if (this.options.tap) { 661 utils.tap(e, this.options.tap); 662 } 663 664 if (this.options.click) { 665 utils.click(e); 666 } 667 668 this._execEvent('scrollCancel'); 669 return; 670 } 671 672 if (this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100) { 673 this._execEvent('flick'); 674 return; 675 } 676 677 // start momentum animation if needed 678 if (this.options.momentum && duration < 300) { 679 momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperW
vendor: 4,788 bytes, lines 679-823
679idth : 0, this.options.deceleration) : { 680 destination: newX, 681 duration: 0 682 }; 683 momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { 684 destination: newY, 685 duration: 0 686 }; 687 newX = momentumX.destination; 688 newY = momentumY.destination; 689 time = Math.max(momentumX.duration, momentumY.duration); 690 this.isInTransition = 1; 691 } 692 693 694 if (this.options.snap) { 695 var snap = this._nearestSnap(newX, newY); 696 this.currentPage = snap; 697 time = this.options.snapSpeed || Math.max( 698 Math.max( 699 Math.min(Math.abs(newX - snap.x), 1000), 700 Math.min(Math.abs(newY - snap.y), 1000) 701 ), 300); 702 newX = snap.x; 703 newY = snap.y; 704 705 this.directionX = 0; 706 this.directionY = 0; 707 easing = this.options.bounceEasing; 708 } 709 710 // INSERT POINT: _end 711 712 if (newX != this.x || newY != this.y) { 713 // change easing function when scroller goes out of the boundaries 714 if (newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) { 715 easing = utils.ease.quadratic; 716 } 717 718 this.scrollTo(newX, newY, time, easing); 719 return; 720 } 721 722 this._execEvent('scrollEnd'); 723 }, 724 725 _resize: function () { 726 var that = this; 727 728 clearTimeout(this.resizeTimeout); 729 730 this.resizeTimeout = setTimeout(function () { 731 that.refresh(); 732 }, this.options.resizePolling); 733 }, 734 735 resetPosition: function (time) { 736 var x = this.x, 737 y = this.y; 738 739 time = time || 0; 740 741 if (!this.hasHorizontalScroll || this.x > 0) { 742 x = 0; 743 } else if (this.x < this.maxScrollX) { 744 x = this.maxScrollX; 745 } 746 747 if (!this.hasVerticalScroll || this.y > 0) { 748 y = 0; 749 } else if (this.y < this.maxScrollY) { 750 y = this.maxScrollY; 751 } 752 753 if (x == this.x && y == this.y) { 754 return false; 755 } 756 757 this.scrollTo(x, y, time, this.options.bounceEasing); 758 759 return true; 760 }, 761 762 disable: function () { 763 this.enabled = false; 764 }, 765 766 enable: function () { 767 this.enabled = true; 768 }, 769 770 refresh: function () { 771 utils.getRect(this.wrapper); // Force reflow 772 773 this.wrapperWidth = this.wrapper.clientWidth; 774 this.wrapperHeight = this.wrapper.clientHeight; 775 776 var rect = utils.getRect(this.scroller); 777 /* REPLACE START: refresh */ 778 779 this.scrollerWidth = rect.width; 780 this.scrollerHeight = rect.height; 781 782 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 783 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 784 785 /* REPLACE END: refresh */ 786 787 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 788 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 789 790 if (!this.hasHorizontalScroll) { 791 this.maxScrollX = 0; 792 this.scrollerWidth = this.wrapperWidth; 793 } 794 795 if (!this.hasVerticalScroll) { 796 this.maxScrollY = 0; 797 this.scrollerHeight = this.wrapperHeight; 798 } 799 800 this.endTime = 0; 801 this.directionX = 0; 802 this.directionY = 0; 803 804 if (utils.hasPointer && !this.options.disablePointer) { 805 // The wrapper should have `touchAction` property for using pointerEvent. 806 this.wrapper.style[utils.style.touchAction] = utils.getTouchAction(this.options.eventPassthrough, true); 807 808 // case. not support 'pinch-zoom' 809 // https://github.com/cubiq/iscroll/issues/1118#issuecomment-270057583 810 if (!this.wrapper.style[utils.style.touchAction]) { 811 this.wrapper.style[utils.style.touchAction] = utils.getTouchAction(this.options.eventPassthrough, false); 812 } 813 } 814 this.wrapperOffset = utils.offset(this.wrapper); 815 816 this._execEvent('refresh'); 817 818 this.resetPosition(); 819 820 // INSERT POINT: _refresh 821 822 }, 823
vendor: 15,364 bytes, lines 824-1285
824 on: function (type, fn) { 825 if (!this._events[type]) { 826 this._events[type] = []; 827 } 828 829 this._events[type].push(fn); 830 }, 831 832 off: function (type, fn) { 833 if (!this._events[type]) { 834 return; 835 } 836 837 var index = this._events[type].indexOf(fn); 838 839 if (index > -1) { 840 this._events[type].splice(index, 1); 841 } 842 }, 843 844 _execEvent: function (type) { 845 if (!this._events[type]) { 846 return; 847 } 848 849 var i = 0, 850 l = this._events[type].length; 851 852 if (!l) { 853 return; 854 } 855 856 for (; i < l; i++) { 857 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 858 } 859 }, 860 861 scrollBy: function (x, y, time, easing) { 862 x = this.x + x; 863 y = this.y + y; 864 time = time || 0; 865 866 this.scrollTo(x, y, time, easing); 867 }, 868 869 scrollTo: function (x, y, time, easing) { 870 easing = easing || utils.ease.circular; 871 872 this.isInTransition = this.options.useTransition && time > 0; 873 var transitionType = this.options.useTransition && easing.style; 874 if (!time || transitionType) { 875 if (transitionType) { 876 this._transitionTimingFunction(easing.style); 877 this._transitionTime(time); 878 } 879 this._translate(x, y); 880 } else { 881 this._animate(x, y, time, easing.fn); 882 } 883 }, 884 885 scrollToElement: function (el, time, offsetX, offsetY, easing) { 886 el = el.nodeType ? el : this.scroller.querySelector(el); 887 888 if (!el) { 889 return; 890 } 891 892 var pos = utils.offset(el); 893 894 pos.left -= this.wrapperOffset.left; 895 pos.top -= this.wrapperOffset.top; 896 897 // if offsetX/Y are true we center the element to the screen 898 var elRect = utils.getRect(el); 899 var wrapperRect = utils.getRect(this.wrapper); 900 if (offsetX === true) { 901 offsetX = Math.round(elRect.width / 2 - wrapperRect.width / 2); 902 } 903 if (offsetY === true) { 904 offsetY = Math.round(elRect.height / 2 - wrapperRect.height / 2); 905 } 906 907 pos.left -= offsetX || 0; 908 pos.top -= offsetY || 0; 909 910 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 911 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 912 913 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x - pos.left), Math.abs(this.y - pos.top)) : time; 914 915 this.scrollTo(pos.left, pos.top, time, easing); 916 }, 917 918 _transitionTime: function (time) { 919 if (!this.options.useTransition) { 920 return; 921 } 922 time = time || 0; 923 var durationProp = utils.style.transitionDuration; 924 if (!durationProp) { 925 return; 926 } 927 928 this.scrollerStyle[durationProp] = time + 'ms'; 929 930 if (!time && utils.isBadAndroid) { 931 this.scrollerStyle[durationProp] = '0.0001ms'; 932 // remove 0.0001ms 933 var self = this; 934 rAF(function () { 935 if (self.scrollerStyle[durationProp] === '0.0001ms') { 936 self.scrollerStyle[durationProp] = '0s'; 937 } 938 }); 939 } 940 941 942 if (this.indicators) { 943 for (var i = this.indicators.length; i--;) { 944 this.indicators[i].transitionTime(time); 945 } 946 } 947 948 949 // INSERT POINT: _transitionTime 950 951 }, 952 953 _transitionTimingFunction: function (easing) { 954 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 955 956 957 if (this.indicators) { 958 for (var i = this.indicators.length; i--;) { 959 this.indicators[i].transitionTimingFunction(easing); 960 } 961 } 962 963 964 // INSERT POINT: _transitionTimingFunction 965 966 }, 967 968 _translate: function (x, y) { 969 if (this.options.useTransform) { 970 971 /* REPLACE START: _translate */ 972 973 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 974 975 /* REPLACE END: _translate */ 976 977 } else { 978 x = Math.round(x); 979 y = Math.round(y); 980 this.scrollerStyle.left = x + 'px'; 981 this.scrollerStyle.top = y + 'px'; 982 } 983 984 this.x = x; 985 this.y = y; 986 987 988 if (this.indicators) { 989 for (var i = this.indicators.length; i--;) { 990 this.indicators[i].updatePosition(); 991 } 992 } 993 994 995 // INSERT POINT: _translate 996 997 }, 998 999 _initEvents: function (remove) { 1000 var eventType = remove ? utils.removeEvent : utils.addEvent, 1001 target = this.options.bindToWrapper ? this.wrapper : window; 1002 1003 eventType(window, 'orientationchange', this); 1004 eventType(window, 'resize', this); 1005 1006 if (this.options.click) { 1007 eventType(this.wrapper, 'click', this, true); 1008 } 1009 1010 if (!this.options.disableMouse) { 1011 eventType(this.wrapper, 'mousedown', this); 1012 eventType(target, 'mousemove', this); 1013 eventType(target, 'mousecancel', this); 1014 eventType(target, 'mouseup', this); 1015 } 1016 1017 if (utils.hasPointer && !this.options.disablePointer) { 1018 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 1019 eventType(target, utils.prefixPointerEvent('pointermove'), this); 1020 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 1021 eventType(target, utils.prefixPointerEvent('pointerup'), this); 1022 } 1023 1024 if (utils.hasTouch && !this.options.disableTouch) { 1025 eventType(this.wrapper, 'touchstart', this); 1026 eventType(target, 'touchmove', this); 1027 eventType(target, 'touchcancel', this); 1028 eventType(target, 'touchend', this); 1029 } 1030 1031 eventType(this.scroller, 'transitionend', this); 1032 eventType(this.scroller, 'webkitTransitionEnd', this); 1033 eventType(this.scroller, 'oTransitionEnd', this); 1034 eventType(this.scroller, 'MSTransitionEnd', this); 1035 }, 1036 1037 getComputedPosition: function () { 1038 var matrix = window.getComputedStyle(this.scroller, null), 1039 x, y; 1040 1041 if (this.options.useTransform) { 1042 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 1043 x = +(matrix[12] || matrix[4]); 1044 y = +(matrix[13] || matrix[5]); 1045 } else { 1046 x = +matrix.left.replace(/[^-\d.]/g, ''); 1047 y = +matrix.top.replace(/[^-\d.]/g, ''); 1048 } 1049 1050 return { 1051 x: x, 1052 y: y 1053 }; 1054 }, 1055 _initIndicators: function () { 1056 var interactive = this.options.interactiveScrollbars, 1057 customStyle = typeof this.options.scrollbars != 'string', 1058 indicators = [], 1059 indicator; 1060 1061 var that = this; 1062 1063 this.indicators = []; 1064 1065 if (this.options.scrollbars) { 1066 // Vertical scrollbar 1067 if (this.options.scrollY) { 1068 indicator = { 1069 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 1070 interactive: interactive, 1071 defaultScrollbars: true, 1072 customStyle: customStyle, 1073 resize: this.options.resizeScrollbars, 1074 shrink: this.options.shrinkScrollbars, 1075 fade: this.options.fadeScrollbars, 1076 listenX: false 1077 }; 1078 1079 this.wrapper.appendChild(indicator.el); 1080 indicators.push(indicator); 1081 } 1082 1083 // Horizontal scrollbar 1084 if (this.options.scrollX) { 1085 indicator = { 1086 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 1087 interactive: interactive, 1088 defaultScrollbars: true, 1089 customStyle: customStyle, 1090 resize: this.options.resizeScrollbars, 1091 shrink: this.options.shrinkScrollbars, 1092 fade: this.options.fadeScrollbars, 1093 listenY: false 1094 }; 1095 1096 this.wrapper.appendChild(indicator.el); 1097 indicators.push(indicator); 1098 } 1099 } 1100 1101 if (this.options.indicators) { 1102 // TODO: check concat compatibility 1103 indicators = indicators.concat(this.options.indicators); 1104 } 1105 1106 for (var i = indicators.length; i--;) { 1107 this.indicators.push(new Indicator(this, indicators[i])); 1108 } 1109 1110 // TODO: check if we can use array.map (wide compatibility and performance issues) 1111 function _indicatorsMap(fn) { 1112 if (that.indicators) { 1113 for (var i = that.indicators.length; i--;) { 1114 fn.call(that.indicators[i]); 1115 } 1116 } 1117 } 1118 1119 if (this.options.fadeScrollbars) { 1120 this.on('scrollEnd', function () { 1121 _indicatorsMap(function () { 1122 this.fade(); 1123 }); 1124 }); 1125 1126 this.on('scrollCancel', function () { 1127 _indicatorsMap(function () { 1128 this.fade(); 1129 }); 1130 }); 1131 1132 this.on('scrollStart', function () { 1133 _indicatorsMap(function () { 1134 this.fade(1); 1135 }); 1136 }); 1137 1138 this.on('beforeScrollStart', function () { 1139 _indicatorsMap(function () { 1140 this.fade(1, true); 1141 }); 1142 }); 1143 } 1144 1145 1146 this.on('refresh', function () { 1147 _indicatorsMap(function () { 1148 this.refresh(); 1149 }); 1150 }); 1151 1152 this.on('destroy', function () { 1153 _indicatorsMap(function () { 1154 this.destroy(); 1155 }); 1156 1157 delete this.indicators; 1158 }); 1159 }, 1160 1161 _initWheel: function () { 1162 utils.addEvent(this.wrapper, 'wheel', this); 1163 utils.addEvent(this.wrapper, 'mousewheel', this); 1164 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 1165 1166 this.on('destroy', function () { 1167 clearTimeout(this.wheelTimeout); 1168 this.wheelTimeout = null; 1169 utils.removeEvent(this.wrapper, 'wheel', this); 1170 utils.removeEvent(this.wrapper, 'mousewheel', this); 1171 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 1172 }); 1173 }, 1174 1175 _wheel: function (e) { 1176 if (!this.enabled) { 1177 return; 1178 } 1179 1180 e.preventDefault(); 1181 1182 var wheelDeltaX, wheelDeltaY, 1183 newX, newY, 1184 that = this; 1185 1186 if (this.wheelTimeout === undefined) { 1187 that._execEvent('scrollStart'); 1188 } 1189 1190 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 1191 clearTimeout(this.wheelTimeout); 1192 this.wheelTimeout = setTimeout(function () { 1193 if (!that.options.snap) { 1194 that._execEvent('scrollEnd'); 1195 } 1196 that.wheelTimeout = undefined; 1197 }, 400); 1198 1199 if ('deltaX' in e) { 1200 if (e.deltaMode === 1) { 1201 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 1202 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 1203 } else { 1204 wheelDeltaX = -e.deltaX; 1205 wheelDeltaY = -e.deltaY; 1206 } 1207 } else if ('wheelDeltaX' in e) { 1208 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 1209 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 1210 } else if ('wheelDelta' in e) { 1211 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 1212 } else if ('detail' in e) { 1213 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 1214 } else { 1215 return; 1216 } 1217 1218 wheelDeltaX *= this.options.invertWheelDirection; 1219 wheelDeltaY *= this.options.invertWheelDirection; 1220 1221 if (!this.hasVerticalScroll) { 1222 wheelDeltaX = wheelDeltaY; 1223 wheelDeltaY = 0; 1224 } 1225 1226 if (this.options.snap) { 1227 newX = this.currentPage.pageX; 1228 newY = this.currentPage.pageY; 1229 1230 if (wheelDeltaX > 0) { 1231 newX--; 1232 } else if (wheelDeltaX < 0) { 1233 newX++; 1234 } 1235 1236 if (wheelDeltaY > 0) { 1237 newY--; 1238 } else if (wheelDeltaY < 0) { 1239 newY++; 1240 } 1241 1242 this.goToPage(newX, newY); 1243 1244 return; 1245 } 1246 1247 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 1248 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 1249 1250 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 1251 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 1252 1253 if (newX > 0) { 1254 newX = 0; 1255 } else if (newX < this.maxScrollX) { 1256 newX = this.maxScrollX; 1257 } 1258 1259 if (newY > 0) { 1260 newY = 0; 1261 } else if (newY < this.maxScrollY) { 1262 newY = this.maxScrollY; 1263 } 1264 1265 this.scrollTo(newX, newY, 0); 1266 1267 // INSERT POINT: _wheel 1268 }, 1269 1270 _initSnap: function () { 1271 this.currentPage = {}; 1272 1273 if (typeof this.options.snap == 'string') { 1274 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 1275 } 1276 1277 this.on('refresh', function () { 1278 var i = 0, 1279 l, 1280 m = 0, 1281 n, 1282 cx, cy, 1283 x = 0, 1284 y, 1285 stepX = this.options.snapStepX || this.wrapperW
vendor: 12,312 bytes, lines 1285-1663
1285idth, 1286 stepY = this.options.snapStepY || this.wrapperHeight, 1287 el, 1288 rect; 1289 1290 this.pages = []; 1291 1292 if (!this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight) { 1293 return; 1294 } 1295 1296 if (this.options.snap === true) { 1297 cx = Math.round(stepX / 2); 1298 cy = Math.round(stepY / 2); 1299 1300 while (x > -this.scrollerWidth) { 1301 this.pages[i] = []; 1302 l = 0; 1303 y = 0; 1304 1305 while (y > -this.scrollerHeight) { 1306 this.pages[i][l] = { 1307 x: Math.max(x, this.maxScrollX), 1308 y: Math.max(y, this.maxScrollY), 1309 width: stepX, 1310 height: stepY, 1311 cx: x - cx, 1312 cy: y - cy 1313 }; 1314 1315 y -= stepY; 1316 l++; 1317 } 1318 1319 x -= stepX; 1320 i++; 1321 } 1322 } else { 1323 el = this.options.snap; 1324 l = el.length; 1325 n = -1; 1326 1327 for (; i < l; i++) { 1328 rect = utils.getRect(el[i]); 1329 if (i === 0 || rect.left <= utils.getRect(el[i - 1]).left) { 1330 m = 0; 1331 n++; 1332 } 1333 1334 if (!this.pages[m]) { 1335 this.pages[m] = []; 1336 } 1337 1338 x = Math.max(-rect.left, this.maxScrollX); 1339 y = Math.max(-rect.top, this.maxScrollY); 1340 cx = x - Math.round(rect.width / 2); 1341 cy = y - Math.round(rect.height / 2); 1342 1343 this.pages[m][n] = { 1344 x: x, 1345 y: y, 1346 width: rect.width, 1347 height: rect.height, 1348 cx: cx, 1349 cy: cy 1350 }; 1351 1352 if (x > this.maxScrollX) { 1353 m++; 1354 } 1355 } 1356 } 1357 1358 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 1359 1360 // Update snap threshold if needed 1361 if (this.options.snapThreshold % 1 === 0) { 1362 this.snapThresholdX = this.options.snapThreshold; 1363 this.snapThresholdY = this.options.snapThreshold; 1364 } else { 1365 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 1366 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 1367 } 1368 }); 1369 1370 this.on('flick', function () { 1371 var time = this.options.snapSpeed || Math.max( 1372 Math.max( 1373 Math.min(Math.abs(this.x - this.startX), 1000), 1374 Math.min(Math.abs(this.y - this.startY), 1000) 1375 ), 300); 1376 1377 this.goToPage( 1378 this.currentPage.pageX + this.directionX, 1379 this.currentPage.pageY + this.directionY, 1380 time 1381 ); 1382 }); 1383 }, 1384 1385 _nearestSnap: function (x, y) { 1386 if (!this.pages.length) { 1387 return { 1388 x: 0, 1389 y: 0, 1390 pageX: 0, 1391 pageY: 0 1392 }; 1393 } 1394 1395 var i = 0, 1396 l = this.pages.length, 1397 m = 0; 1398 1399 // Check if we exceeded the snap threshold 1400 if (Math.abs(x - this.absStartX) < this.snapThresholdX && 1401 Math.abs(y - this.absStartY) < this.snapThresholdY) { 1402 return this.currentPage; 1403 } 1404 1405 if (x > 0) { 1406 x = 0; 1407 } else if (x < this.maxScrollX) { 1408 x = this.maxScrollX; 1409 } 1410 1411 if (y > 0) { 1412 y = 0; 1413 } else if (y < this.maxScrollY) { 1414 y = this.maxScrollY; 1415 } 1416 1417 for (; i < l; i++) { 1418 if (x >= this.pages[i][0].cx) { 1419 x = this.pages[i][0].x; 1420 break; 1421 } 1422 } 1423 1424 l = this.pages[i].length; 1425 1426 for (; m < l; m++) { 1427 if (y >= this.pages[0][m].cy) { 1428 y = this.pages[0][m].y; 1429 break; 1430 } 1431 } 1432 1433 if (i == this.currentPage.pageX) { 1434 i += this.directionX; 1435 1436 if (i < 0) { 1437 i = 0; 1438 } else if (i >= this.pages.length) { 1439 i = this.pages.length - 1; 1440 } 1441 1442 x = this.pages[i][0].x; 1443 } 1444 1445 if (m == this.currentPage.pageY) { 1446 m += this.directionY; 1447 1448 if (m < 0) { 1449 m = 0; 1450 } else if (m >= this.pages[0].length) { 1451 m = this.pages[0].length - 1; 1452 } 1453 1454 y = this.pages[0][m].y; 1455 } 1456 1457 return { 1458 x: x, 1459 y: y, 1460 pageX: i, 1461 pageY: m 1462 }; 1463 }, 1464 1465 goToPage: function (x, y, time, easing) { 1466 easing = easing || this.options.bounceEasing; 1467 1468 if (x >= this.pages.length) { 1469 x = this.pages.length - 1; 1470 } else if (x < 0) { 1471 x = 0; 1472 } 1473 1474 if (y >= this.pages[x].length) { 1475 y = this.pages[x].length - 1; 1476 } else if (y < 0) { 1477 y = 0; 1478 } 1479 1480 var posX = this.pages[x][y].x, 1481 posY = this.pages[x][y].y; 1482 1483 time = time === undefined ? this.options.snapSpeed || Math.max( 1484 Math.max( 1485 Math.min(Math.abs(posX - this.x), 1000), 1486 Math.min(Math.abs(posY - this.y), 1000) 1487 ), 300) : time; 1488 1489 this.currentPage = { 1490 x: posX, 1491 y: posY, 1492 pageX: x, 1493 pageY: y 1494 }; 1495 1496 this.scrollTo(posX, posY, time, easing); 1497 }, 1498 1499 next: function (time, easing) { 1500 var x = this.currentPage.pageX, 1501 y = this.currentPage.pageY; 1502 1503 x++; 1504 1505 if (x >= this.pages.length && this.hasVerticalScroll) { 1506 x = 0; 1507 y++; 1508 } 1509 1510 this.goToPage(x, y, time, easing); 1511 }, 1512 1513 prev: function (time, easing) { 1514 var x = this.currentPage.pageX, 1515 y = this.currentPage.pageY; 1516 1517 x--; 1518 1519 if (x < 0 && this.hasVerticalScroll) { 1520 x = 0; 1521 y--; 1522 } 1523 1524 this.goToPage(x, y, time, easing); 1525 }, 1526 1527 _initKeys: function (e) { 1528 // default key bindings 1529 var keys = { 1530 pageUp: 33, 1531 pageDown: 34, 1532 end: 35, 1533 home: 36, 1534 left: 37, 1535 up: 38, 1536 right: 39, 1537 down: 40 1538 }; 1539 var i; 1540 1541 // if you give me characters I give you keycode 1542 if (typeof this.options.keyBindings == 'object') { 1543 for (i in this.options.keyBindings) { 1544 if (typeof this.options.keyBindings[i] == 'string') { 1545 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0); 1546 } 1547 } 1548 } else { 1549 this.options.keyBindings = {}; 1550 } 1551 1552 for (i in keys) { 1553 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 1554 } 1555 1556 utils.addEvent(window, 'keydown', this); 1557 1558 this.on('destroy', function () { 1559 utils.removeEvent(window, 'keydown', this); 1560 }); 1561 }, 1562 1563 _key: function (e) { 1564 if (!this.enabled) { 1565 return; 1566 } 1567 1568 var snap = this.options.snap, // we are using this alot, better to cache it 1569 newX = snap ? this.currentPage.pageX : this.x, 1570 newY = snap ? this.currentPage.pageY : this.y, 1571 now = utils.getTime(), 1572 prevTime = this.keyTime || 0, 1573 acceleration = 0.250, 1574 pos; 1575 1576 if (this.options.useTransition && this.isInTransition) { 1577 pos = this.getComputedPosition(); 1578 1579 this._translate(Math.round(pos.x), Math.round(pos.y)); 1580 this.isInTransition = false; 1581 } 1582 1583 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 1584 1585 switch (e.keyCode) { 1586 case this.options.keyBindings.pageUp: 1587 if (this.hasHorizontalScroll && !this.hasVerticalScroll) { 1588 newX += snap ? 1 : this.wrapperWidth; 1589 } else { 1590 newY += snap ? 1 : this.wrapperHeight; 1591 } 1592 break; 1593 case this.options.keyBindings.pageDown: 1594 if (this.hasHorizontalScroll && !this.hasVerticalScroll) { 1595 newX -= snap ? 1 : this.wrapperWidth; 1596 } else { 1597 newY -= snap ? 1 : this.wrapperHeight; 1598 } 1599 break; 1600 case this.options.keyBindings.end: 1601 newX = snap ? this.pages.length - 1 : this.maxScrollX; 1602 newY = snap ? this.pages[0].length - 1 : this.maxScrollY; 1603 break; 1604 case this.options.keyBindings.home: 1605 newX = 0; 1606 newY = 0; 1607 break; 1608 case this.options.keyBindings.left: 1609 newX += snap ? -1 : 5 + this.keyAcceleration >> 0; 1610 break; 1611 case this.options.keyBindings.up: 1612 newY += snap ? 1 : 5 + this.keyAcceleration >> 0; 1613 break; 1614 case this.options.keyBindings.right: 1615 newX -= snap ? -1 : 5 + this.keyAcceleration >> 0; 1616 break; 1617 case this.options.keyBindings.down: 1618 newY -= snap ? 1 : 5 + this.keyAcceleration >> 0; 1619 break; 1620 default: 1621 return; 1622 } 1623 1624 if (snap) { 1625 this.goToPage(newX, newY); 1626 return; 1627 } 1628 1629 if (newX > 0) { 1630 newX = 0; 1631 this.keyAcceleration = 0; 1632 } else if (newX < this.maxScrollX) { 1633 newX = this.maxScrollX; 1634 this.keyAcceleration = 0; 1635 } 1636 1637 if (newY > 0) { 1638 newY = 0; 1639 this.keyAcceleration = 0; 1640 } else if (newY < this.maxScrollY) { 1641 newY = this.maxScrollY; 1642 this.keyAcceleration = 0; 1643 } 1644 1645 this.scrollTo(newX, newY, 0); 1646 1647 this.keyTime = now; 1648 }, 1649 1650 _animate: function (destX, destY, duration, easingFn) { 1651 var that = this, 1652 startX = this.x, 1653 startY = this.y, 1654 startTime = utils.getTime(), 1655 destTime = startTime + duration; 1656 1657 function step() { 1658 var now = utils.getTime(), 1659 newX, newY, 1660 easing; 1661 1662 if (now >= destTime) { 1663 that.isAnimating = false;
vendor: 8,137 bytes, lines 1664-1899
1664 that._translate(destX, destY); 1665 1666 if (!that.resetPosition(that.options.bounceTime)) { 1667 that._execEvent('scrollEnd'); 1668 } 1669 1670 return; 1671 } 1672 1673 now = (now - startTime) / duration; 1674 easing = easingFn(now); 1675 newX = (destX - startX) * easing + startX; 1676 newY = (destY - startY) * easing + startY; 1677 that._translate(newX, newY); 1678 1679 if (that.isAnimating) { 1680 rAF(step); 1681 } 1682 } 1683 1684 this.isAnimating = true; 1685 step(); 1686 }, 1687 handleEvent: function (e) { 1688 switch (e.type) { 1689 case 'touchstart': 1690 case 'pointerdown': 1691 case 'MSPointerDown': 1692 case 'mousedown': 1693 this._start(e); 1694 break; 1695 case 'touchmove': 1696 case 'pointermove': 1697 case 'MSPointerMove': 1698 case 'mousemove': 1699 this._move(e); 1700 break; 1701 case 'touchend': 1702 case 'pointerup': 1703 case 'MSPointerUp': 1704 case 'mouseup': 1705 case 'touchcancel': 1706 case 'pointercancel': 1707 case 'MSPointerCancel': 1708 case 'mousecancel': 1709 this._end(e); 1710 break; 1711 case 'orientationchange': 1712 case 'resize': 1713 this._resize(); 1714 break; 1715 case 'transitionend': 1716 case 'webkitTransitionEnd': 1717 case 'oTransitionEnd': 1718 case 'MSTransitionEnd': 1719 this._transitionEnd(e); 1720 break; 1721 case 'wheel': 1722 case 'DOMMouseScroll': 1723 case 'mousewheel': 1724 this._wheel(e); 1725 break; 1726 case 'keydown': 1727 this._key(e); 1728 break; 1729 case 'click': 1730 if (this.enabled && !e._constructed) { 1731 e.preventDefault(); 1732 e.stopPropagation(); 1733 } 1734 break; 1735 } 1736 } 1737 }; 1738 1739 function createDefaultScrollbar(direction, interactive, type) { 1740 var scrollbar = document.createElement('div'), 1741 indicator = document.createElement('div'); 1742 1743 if (type === true) { 1744 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 1745 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'; 1746 } 1747 1748 indicator.className = 'iScrollIndicator'; 1749 1750 if (direction == 'h') { 1751 if (type === true) { 1752 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 1753 indicator.style.height = '100%'; 1754 } 1755 scrollbar.className = 'iScrollHorizontalScrollbar'; 1756 } else { 1757 if (type === true) { 1758 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 1759 indicator.style.width = '100%'; 1760 } 1761 scrollbar.className = 'iScrollVerticalScrollbar'; 1762 } 1763 1764 scrollbar.style.cssText += ';overflow:hidden'; 1765 1766 if (!interactive) { 1767 scrollbar.style.pointerEvents = 'none'; 1768 } 1769 1770 scrollbar.appendChild(indicator); 1771 1772 return scrollbar; 1773 } 1774 1775 function Indicator(scroller, options) { 1776 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 1777 this.wrapperStyle = this.wrapper.style; 1778 this.indicator = this.wrapper.children[0]; 1779 this.indicatorStyle = this.indicator.style; 1780 this.scroller = scroller; 1781 1782 this.options = { 1783 listenX: true, 1784 listenY: true, 1785 interactive: false, 1786 resize: true, 1787 defaultScrollbars: false, 1788 shrink: false, 1789 fade: false, 1790 speedRatioX: 0, 1791 speedRatioY: 0 1792 }; 1793 1794 for (var i in options) { 1795 this.options[i] = options[i]; 1796 } 1797 1798 this.sizeRatioX = 1; 1799 this.sizeRatioY = 1; 1800 this.maxPosX = 0; 1801 this.maxPosY = 0; 1802 1803 if (this.options.interactive) { 1804 if (!this.options.disableTouch) { 1805 utils.addEvent(this.indicator, 'touchstart', this); 1806 utils.addEvent(window, 'touchend', this); 1807 } 1808 if (!this.options.disablePointer) { 1809 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 1810 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 1811 } 1812 if (!this.options.disableMouse) { 1813 utils.addEvent(this.indicator, 'mousedown', this); 1814 utils.addEvent(window, 'mouseup', this); 1815 } 1816 } 1817 1818 if (this.options.fade) { 1819 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 1820 var durationProp = utils.style.transitionDuration; 1821 if (!durationProp) { 1822 return; 1823 } 1824 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 1825 // remove 0.0001ms 1826 var self = this; 1827 if (utils.isBadAndroid) { 1828 rAF(function () { 1829 if (self.wrapperStyle[durationProp] === '0.0001ms') { 1830 self.wrapperStyle[durationProp] = '0s'; 1831 } 1832 }); 1833 } 1834 this.wrapperStyle.opacity = '0'; 1835 } 1836 } 1837 1838 Indicator.prototype = { 1839 handleEvent: function (e) { 1840 switch (e.type) { 1841 case 'touchstart': 1842 case 'pointerdown': 1843 case 'MSPointerDown': 1844 case 'mousedown': 1845 this._start(e); 1846 break; 1847 case 'touchmove': 1848 case 'pointermove': 1849 case 'MSPointerMove': 1850 case 'mousemove': 1851 this._move(e); 1852 break; 1853 case 'touchend': 1854 case 'pointerup': 1855 case 'MSPointerUp': 1856 case 'mouseup': 1857 case 'touchcancel': 1858 case 'pointercancel': 1859 case 'MSPointerCancel': 1860 case 'mousecancel': 1861 this._end(e); 1862 break; 1863 } 1864 }, 1865 1866 destroy: function () { 1867 if (this.options.fadeScrollbars) { 1868 clearTimeout(this.fadeTimeout); 1869 this.fadeTimeout = null; 1870 } 1871 if (this.options.interactive) { 1872 utils.removeEvent(this.indicator, 'touchstart', this); 1873 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 1874 utils.removeEvent(this.indicator, 'mousedown', this); 1875 1876 utils.removeEvent(window, 'touchmove', this); 1877 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 1878 utils.removeEvent(window, 'mousemove', this); 1879 1880 utils.removeEvent(window, 'touchend', this); 1881 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 1882 utils.removeEvent(window, 'mouseup', this); 1883 } 1884 1885 if (this.options.defaultScrollbars && this.wrapper.parentNode) { 1886 this.wrapper.parentNode.removeChild(this.wrapper); 1887 } 1888 }, 1889 1890 _start: function (e) { 1891 var point = e.touches ? e.touches[0] : e; 1892 1893 e.preventDefault(); 1894 e.stopPropagation(); 1895 1896 this.transitionTime(); 1897 1898 this.initiated = true; 1899 this.moved = false;
vendor: 11,556 bytes, lines 1900-2201
1900 this.lastPointX = point.pageX; 1901 this.lastPointY = point.pageY; 1902 1903 this.startTime = utils.getTime(); 1904 1905 if (!this.options.disableTouch) { 1906 utils.addEvent(window, 'touchmove', this); 1907 } 1908 if (!this.options.disablePointer) { 1909 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 1910 } 1911 if (!this.options.disableMouse) { 1912 utils.addEvent(window, 'mousemove', this); 1913 } 1914 1915 this.scroller._execEvent('beforeScrollStart'); 1916 }, 1917 1918 _move: function (e) { 1919 var point = e.touches ? e.touches[0] : e, 1920 deltaX, deltaY, 1921 newX, newY, 1922 timestamp = utils.getTime(); 1923 1924 if (!this.moved) { 1925 this.scroller._execEvent('scrollStart'); 1926 } 1927 1928 this.moved = true; 1929 1930 deltaX = point.pageX - this.lastPointX; 1931 this.lastPointX = point.pageX; 1932 1933 deltaY = point.pageY - this.lastPointY; 1934 this.lastPointY = point.pageY; 1935 1936 newX = this.x + deltaX; 1937 newY = this.y + deltaY; 1938 1939 this._pos(newX, newY); 1940 1941 // INSERT POINT: indicator._move 1942 1943 e.preventDefault(); 1944 e.stopPropagation(); 1945 }, 1946 1947 _end: function (e) { 1948 if (!this.initiated) { 1949 return; 1950 } 1951 1952 this.initiated = false; 1953 1954 e.preventDefault(); 1955 e.stopPropagation(); 1956 1957 utils.removeEvent(window, 'touchmove', this); 1958 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 1959 utils.removeEvent(window, 'mousemove', this); 1960 1961 if (this.scroller.options.snap) { 1962 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 1963 1964 var time = this.options.snapSpeed || Math.max( 1965 Math.max( 1966 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 1967 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 1968 ), 300); 1969 1970 if (this.scroller.x != snap.x || this.scroller.y != snap.y) { 1971 this.scroller.directionX = 0; 1972 this.scroller.directionY = 0; 1973 this.scroller.currentPage = snap; 1974 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 1975 } 1976 } 1977 1978 if (this.moved) { 1979 this.scroller._execEvent('scrollEnd'); 1980 } 1981 }, 1982 1983 transitionTime: function (time) { 1984 time = time || 0; 1985 var durationProp = utils.style.transitionDuration; 1986 if (!durationProp) { 1987 return; 1988 } 1989 1990 this.indicatorStyle[durationProp] = time + 'ms'; 1991 1992 if (!time && utils.isBadAndroid) { 1993 this.indicatorStyle[durationProp] = '0.0001ms'; 1994 // remove 0.0001ms 1995 var self = this; 1996 rAF(function () { 1997 if (self.indicatorStyle[durationProp] === '0.0001ms') { 1998 self.indicatorStyle[durationProp] = '0s'; 1999 } 2000 }); 2001 } 2002 }, 2003 2004 transitionTimingFunction: function (easing) { 2005 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 2006 }, 2007 2008 refresh: function () { 2009 this.transitionTime(); 2010 2011 if (this.options.listenX && !this.options.listenY) { 2012 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 2013 } else if (this.options.listenY && !this.options.listenX) { 2014 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 2015 } else { 2016 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 2017 } 2018 2019 if (this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll) { 2020 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 2021 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 2022 2023 if (this.options.defaultScrollbars && this.options.customStyle) { 2024 if (this.options.listenX) { 2025 this.wrapper.style.right = '8px'; 2026 } else { 2027 this.wrapper.style.bottom = '8px'; 2028 } 2029 } 2030 } else { 2031 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 2032 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 2033 2034 if (this.options.defaultScrollbars && this.options.customStyle) { 2035 if (this.options.listenX) { 2036 this.wrapper.style.right = '2px'; 2037 } else { 2038 this.wrapper.style.bottom = '2px'; 2039 } 2040 } 2041 } 2042 2043 utils.getRect(this.wrapper); // force refresh 2044 2045 if (this.options.listenX) { 2046 this.wrapperWidth = this.wrapper.clientWidth; 2047 if (this.options.resize) { 2048 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 2049 this.indicatorStyle.width = this.indicatorWidth + 'px'; 2050 } else { 2051 this.indicatorWidth = this.indicator.clientWidth; 2052 } 2053 2054 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 2055 2056 if (this.options.shrink == 'clip') { 2057 this.minBoundaryX = -this.indicatorWidth + 8; 2058 this.maxBoundaryX = this.wrapperWidth - 8; 2059 } else { 2060 this.minBoundaryX = 0; 2061 this.maxBoundaryX = this.maxPosX; 2062 } 2063 2064 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 2065 } 2066 2067 if (this.options.listenY) { 2068 this.wrapperHeight = this.wrapper.clientHeight; 2069 if (this.options.resize) { 2070 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 2071 this.indicatorStyle.height = this.indicatorHeight + 'px'; 2072 } else { 2073 this.indicatorHeight = this.indicator.clientHeight; 2074 } 2075 2076 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 2077 2078 if (this.options.shrink == 'clip') { 2079 this.minBoundaryY = -this.indicatorHeight + 8; 2080 this.maxBoundaryY = this.wrapperHeight - 8; 2081 } else { 2082 this.minBoundaryY = 0; 2083 this.maxBoundaryY = this.maxPosY; 2084 } 2085 2086 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 2087 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 2088 } 2089 2090 this.updatePosition(); 2091 }, 2092 2093 updatePosition: function () { 2094 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 2095 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 2096 2097 if (!this.options.ignoreBoundaries) { 2098 if (x < this.minBoundaryX) { 2099 if (this.options.shrink == 'scale') { 2100 this.width = Math.max(this.indicatorWidth + x, 8); 2101 this.indicatorStyle.width = this.width + 'px'; 2102 } 2103 x = this.minBoundaryX; 2104 } else if (x > this.maxBoundaryX) { 2105 if (this.options.shrink == 'scale') { 2106 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 2107 this.indicatorStyle.width = this.width + 'px'; 2108 x = this.maxPosX + this.indicatorWidth - this.width; 2109 } else { 2110 x = this.maxBoundaryX; 2111 } 2112 } else if (this.options.shrink == 'scale' && this.width != this.indicatorWidth) { 2113 this.width = this.indicatorWidth; 2114 this.indicatorStyle.width = this.width + 'px'; 2115 } 2116 2117 if (y < this.minBoundaryY) { 2118 if (this.options.shrink == 'scale') { 2119 this.height = Math.max(this.indicatorHeight + y * 3, 8); 2120 this.indicatorStyle.height = this.height + 'px'; 2121 } 2122 y = this.minBoundaryY; 2123 } else if (y > this.maxBoundaryY) { 2124 if (this.options.shrink == 'scale') { 2125 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 2126 this.indicatorStyle.height = this.height + 'px'; 2127 y = this.maxPosY + this.indicatorHeight - this.height; 2128 } else { 2129 y = this.maxBoundaryY; 2130 } 2131 } else if (this.options.shrink == 'scale' && this.height != this.indicatorHeight) { 2132 this.height = this.indicatorHeight; 2133 this.indicatorStyle.height = this.height + 'px'; 2134 } 2135 } 2136 2137 this.x = x; 2138 this.y = y; 2139 2140 if (this.scroller.options.useTransform) { 2141 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 2142 } else { 2143 this.indicatorStyle.left = x + 'px'; 2144 this.indicatorStyle.top = y + 'px'; 2145 } 2146 }, 2147 2148 _pos: function (x, y) { 2149 if (x < 0) { 2150 x = 0; 2151 } else if (x > this.maxPosX) { 2152 x = this.maxPosX; 2153 } 2154 2155 if (y < 0) { 2156 y = 0; 2157 } else if (y > this.maxPosY) { 2158 y = this.maxPosY; 2159 } 2160 2161 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 2162 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 2163 2164 this.scroller.scrollTo(x, y); 2165 }, 2166 2167 fade: function (val, hold) { 2168 if (hold && !this.visible) { 2169 return; 2170 } 2171 2172 clearTimeout(this.fadeTimeout); 2173 this.fadeTimeout = null; 2174 2175 var time = val ? 250 : 500, 2176 delay = val ? 0 : 300; 2177 2178 val = val ? '1' : '0'; 2179 2180 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 2181 2182 this.fadeTimeout = setTimeout((function (val) { 2183 this.wrapperStyle.opacity = val; 2184 this.visible = +val; 2185 }).bind(this, val), delay); 2186 } 2187 }; 2188 2189 IScroll.utils = utils; 2190 2191 if (typeof module != 'undefined' && module.exports) { 2192 module.exports = IScroll; 2193 } else if (typeof define == 'function' && define.amd) { 2194 define(function () { 2195 return IScroll; 2196 }); 2197 } else { 2198 window.IScroll = IScroll; 2199 } 2200 2201})(window, document, Math);
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.