1/*! 2 * jQuery Scrollify 3 * Version 1.0.17 4 * 5 * Requires: 6 * - jQuery 1.7 or higher 7 * 8 * https://github.com/lukehaas/Scrollify 9 * 10 * Copyright 2016, Luke Haas 11 * Permission is hereby granted, free of charge, to any person obtaining a copy of 12 * this software and associated documentation files (the "Software"), to deal in 13 * the Software without restriction, including without limitation the rights to 14 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 15 * the Software, and to permit persons to whom the Software is furnished to do so, 16 * subject to the following conditions: 17 * 18 * The above copyright notice and this permission notice shall be included in all 19 * copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 23 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 24 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 25 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28if touchScroll is false - update index 29 30 */ 31(function (global, factory) { 32 "use strict"; 33 if (typeof define === 'function' && define.amd) { 34 // AMD. Register as an anonymous module. 35 define(['jquery'], function ($) { 36 return factory($, global, global.document); 37 }); 38 } else if (typeof module === 'object' && module.exports) { 39 // Node/CommonJS 40 module.exports = factory(require('jquery'), global, global.document); 41 } else { 42 // Browser globals 43 factory(jQuery, global, global.document); 44 } 45}(typeof window !== 'undefined' ? window : this, function ($, window, document, undefined) { 46 "use strict"; 47 var heights = [], 48 names = [], 49 elements = [], 50 overflow = [], 51 index = 0, 52 currentIndex = 0, 53 interstitialIndex = 1, 54 hasLocation = false, 55 timeoutId, 56 timeoutId2, 57 $window = $(window), 58 top = $window.scrollTop(), 59 scrollable = false, 60 locked = false, 61 scrolled = false, 62 manualScroll, 63 swipeScroll, 64 util, 65 disabled = false, 66 scrollSamples = [], 67 scrollTime = new Date().getTime(), 68 firstLoad = true, 69 initialised = false, 70 destination = 0, 71 wheelEvent = 'onwheel' in document ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll', 72 settings = { 73 //section should be an identifier that is the same for each section 74 section: ".section", 75 sectionName: "section-name", 76 interstitialSection: "", 77 easing: "easeOutExpo", 78 scrollSpeed: 1100, 79 offset: 0, 80 scrollbars: true, 81 target: "html,body", 82 standardScrollElements: false, 83 setHeights: true, 84 overflowScroll: true, 85 updateHash: true, 86 touchScroll: true, 87 before: function () { }, 88 after: function () { }, 89 afterResize: function () { }, 90 afterRender: function () { } 91 }; 92 function animateScroll(index, instant, callbacks, toTop) { 93 if (currentIndex === index) { 94 callbacks = false; 95 } 96 if (disabled === true) { 97 return true; 98 } 99 if (names[index]) { 100 scrollable = false; 101 if (callbacks) { 102 settings.before(index, elements); 103 } 104 interstitialIndex = 1; 105 destination = heights[index]; 106 if (firstLoad === false && currentIndex > index && toTop === false) { 107 //We're going backwards 108 if (overflow[index]) { 109 interstitialIndex = parseInt(elements[index].outerHeight() / $window.height()); 110 destination = parseInt(heights[index]) + (elements[index].outerHeight() - $window.height()); 111 } 112 } 113 if (settings.updateHash && settings.sectionName && !(firstLoad === true && index === 0)) { 114 if (history.pushState) { 115 try { 116 117 } catch (e) { 118 if (window.console) { 119 console.warn("Scrollify warning: Page must be hosted to manipulate the hash value."); 120 } 121 } 122 } else { 123 124 } 125 } 126 if (firstLoad) { 127 settings.afterRender(); 128 firstLoad = false;
vendor: 25,703 bytes, lines 129-798
129 } 130 currentIndex = index; 131 if (instant) { 132 $(settings.target).stop().scrollTop(destination); 133 if (callbacks) { 134 settings.after(index, elements); 135 } 136 } else { 137 locked = true; 138 if ($().velocity) { 139 $(settings.target).stop().velocity('scroll', { 140 duration: settings.scrollSpeed, 141 easing: settings.easing, 142 offset: destination, 143 mobileHA: false 144 }); 145 } else { 146 $(settings.target).stop().animate({ 147 scrollTop: destination 148 }, settings.scrollSpeed, settings.easing); 149 } 150 if (window.location.hash.length && settings.sectionName && window.console) { 151 try { 152 if ($(window.location.hash).length) { 153 console.warn("Scrollify warning: ID matches hash value - this will cause the page to anchor."); 154 } 155 } catch (e) { } 156 } 157 $(settings.target).promise().done(function () { 158 locked = false; 159 firstLoad = false; 160 if (callbacks) { 161 settings.after(index, elements); 162 } 163 }); 164 } 165 } 166 } 167 168 function isAccelerating(samples) { 169 function average(num) { 170 var sum = 0; 171 var lastElements = samples.slice(Math.max(samples.length - num, 1)); 172 for (var i = 0; i < lastElements.length; i++) { 173 sum += lastElements[i]; 174 } 175 return Math.ceil(sum / num); 176 } 177 178 var avEnd = average(10); 179 var avMiddle = average(70); 180 181 if (avEnd >= avMiddle) { 182 return true; 183 } else { 184 return false; 185 } 186 } 187 var scrollify = function (options) { 188 initialised = true; 189 $.easing['easeOutExpo'] = function (x, t, b, c, d) { 190 return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; 191 }; 192 193 manualScroll = { 194 handleMousedown: function () { 195 if (disabled === true) { 196 return true; 197 } 198 scrollable = false; 199 scrolled = false; 200 }, 201 handleMouseup: function () { 202 if (disabled === true) { 203 return true; 204 } 205 scrollable = true; 206 if (scrolled) { 207 //instant,callbacks 208 manualScroll.calculateNearest(false, true); 209 } 210 }, 211 handleScroll: function () { 212 if (disabled === true) { 213 return true; 214 } 215 if (timeoutId) { 216 clearTimeout(timeoutId); 217 } 218 timeoutId = setTimeout(function () { 219 scrolled = true; 220 if (scrollable === false) { 221 return false; 222 } 223 scrollable = false; 224 //instant,callbacks 225 manualScroll.calculateNearest(false, true); 226 }, 200); 227 }, 228 calculateNearest: function (instant, callbacks) { 229 top = $window.scrollTop(); 230 var i = 1, 231 max = heights.length, 232 closest = 0, 233 prev = Math.abs(heights[0] - top), 234 diff; 235 for (; i < max; i++) { 236 diff = Math.abs(heights[i] - top); 237 238 if (diff < prev) { 239 prev = diff; 240 closest = i; 241 } 242 } 243 if ((atBottom() && closest > index) || atTop()) { 244 index = closest; 245 //index, instant, callbacks, toTop 246 animateScroll(closest, instant, callbacks, false); 247 } 248 }, 249 wheelHandler: function (e) { 250 if (disabled === true) { 251 return true; 252 } else if (settings.standardScrollElements) { 253 if ($(e.target).is(settings.standardScrollElements) || $(e.target).closest(settings.standardScrollElements).length) { 254 return true; 255 } 256 } 257 if (!overflow[index]) { 258 e.preventDefault(); 259 } 260 var currentScrollTime = new Date().getTime(); 261 e = e || window.event; 262 var value = e.originalEvent.wheelDelta || -e.originalEvent.deltaY || -e.originalEvent.detail; 263 var delta = Math.max(-1, Math.min(1, value)); 264 //delta = delta || -e.originalEvent.detail / 3 || e.originalEvent.wheelDelta / 120; 265 if (scrollSamples.length > 149) { 266 scrollSamples.shift(); 267 } 268 //scrollSamples.push(Math.abs(delta*10)); 269 scrollSamples.push(Math.abs(value)); 270 271 if ((currentScrollTime - scrollTime) > 200) { 272 scrollSamples = []; 273 } 274 scrollTime = currentScrollTime; 275 if (locked) { 276 return false; 277 } 278 if (delta < 0) { 279 if (index < heights.length - 1) { 280 if (atBottom()) { 281 if (isAccelerating(scrollSamples)) { 282 e.preventDefault(); 283 index++; 284 locked = true; 285 //index, instant, callbacks, toTop 286 animateScroll(index, false, true, false); 287 } else { 288 return false; 289 } 290 } 291 } 292 } else if (delta > 0) { 293 if (index > 0) { 294 if (atTop()) { 295 if (isAccelerating(scrollSamples)) { 296 e.preventDefault(); 297 index--; 298 locked = true; 299 //index, instant, callbacks, toTop 300 animateScroll(index, false, true, false); 301 } else { 302 return false 303 } 304 } 305 } 306 } 307 }, 308 keyHandler: function (e) { 309 if (disabled === true || document.activeElement.readOnly === false) { 310 return true; 311 } 312 if (locked === true) { 313 return false; 314 } 315 if (e.keyCode == 38 || e.keyCode == 33) { 316 if (index > 0) { 317 if (atTop()) { 318 e.preventDefault(); 319 index--; 320 //index, instant, callbacks, toTop 321 animateScroll(index, false, true, false); 322 } 323 } 324 } else if (e.keyCode == 40 || e.keyCode == 34) { 325 if (index < heights.length - 1) { 326 if (atBottom()) { 327 e.preventDefault(); 328 index++; 329 //index, instant, callbacks, toTop 330 animateScroll(index, false, true, false); 331 } 332 } 333 } 334 }, 335 init: function () { 336 if (settings.scrollbars) { 337 $window.on('mousedown', manualScroll.handleMousedown); 338 $window.on('mouseup', manualScroll.handleMouseup); 339 $window.on('scroll', manualScroll.handleScroll); 340 } else { 341 $("body").css({ "overflow": "hidden" }); 342 } 343 $window.on(wheelEvent, manualScroll.wheelHandler); 344 345 $window.on('keydown', manualScroll.keyHandler); 346 } 347 }; 348 349 swipeScroll = { 350 touches: { 351 "touchstart": { "y": -1, "x": -1 }, 352 "touchmove": { "y": -1, "x": -1 }, 353 "touchend": false, 354 "direction": "undetermined" 355 }, 356 options: { 357 "distance": 30, 358 "timeGap": 800, 359 "timeStamp": new Date().getTime() 360 }, 361 touchHandler: function (event) { 362 if (disabled === true) { 363 return true; 364 } else if (settings.standardScrollElements) { 365 if ($(event.target).is(settings.standardScrollElements) || $(event.target).closest(settings.standardScrollElements).length) { 366 return true; 367 } 368 } 369 var touch; 370 if (typeof event !== 'undefined') { 371 if (typeof event.touches !== 'undefined') { 372 touch = event.touches[0]; 373 switch (event.type) { 374 case 'touchstart': 375 swipeScroll.touches.touchstart.y = touch.pageY; 376 swipeScroll.touches.touchmove.y = -1; 377 378 swipeScroll.touches.touchstart.x = touch.pageX; 379 swipeScroll.touches.touchmove.x = -1; 380 381 swipeScroll.options.timeStamp = new Date().getTime(); 382 swipeScroll.touches.touchend = false; 383 case 'touchmove': 384 swipeScroll.touches.touchmove.y = touch.pageY; 385 swipeScroll.touches.touchmove.x = touch.pageX; 386 if (swipeScroll.touches.touchstart.y !== swipeScroll.touches.touchmove.y && (Math.abs(swipeScroll.touches.touchstart.y - swipeScroll.touches.touchmove.y) > Math.abs(swipeScroll.touches.touchstart.x - swipeScroll.touches.touchmove.x))) { 387 //if(!overflow[index]) { 388 event.preventDefault(); 389 //} 390 swipeScroll.touches.direction = "y"; 391 if ((swipeScroll.options.timeStamp + swipeScroll.options.timeGap) < (new Date().getTime()) && swipeScroll.touches.touchend == false) { 392 393 swipeScroll.touches.touchend = true; 394 if (swipeScroll.touches.touchstart.y > -1) { 395 396 if (Math.abs(swipeScroll.touches.touchmove.y - swipeScroll.touches.touchstart.y) > swipeScroll.options.distance) { 397 if (swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) { 398 399 swipeScroll.up(); 400 401 } else { 402 swipeScroll.down(); 403 404 } 405 } 406 } 407 } 408 } 409 break; 410 case 'touchend': 411 if (swipeScroll.touches[event.type] === false) { 412 swipeScroll.touches[event.type] = true; 413 if (swipeScroll.touches.touchstart.y > -1 && swipeScroll.touches.touchmove.y > -1 && swipeScroll.touches.direction === "y") { 414 415 if (Math.abs(swipeScroll.touches.touchmove.y - swipeScroll.touches.touchstart.y) > swipeScroll.options.distance) { 416 if (swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) { 417 swipeScroll.up(); 418 419 } else { 420 swipeScroll.down(); 421 422 } 423 } 424 swipeScroll.touches.touchstart.y = -1; 425 swipeScroll.touches.touchstart.x = -1; 426 swipeScroll.touches.direction = "undetermined"; 427 } 428 } 429 default: 430 break; 431 } 432 } 433 } 434 }, 435 down: function () { 436 437 if (index < heights.length) { 438 439 if (atBottom() && index < heights.length - 1) { 440 441 index++; 442 //index, instant, callbacks, toTop 443 animateScroll(index, false, true, false); 444 } else { 445 if (Math.floor(elements[index].height() / $window.height()) > interstitialIndex) { 446 447 interstitialScroll(parseInt(heights[index]) + ($window.height() * interstitialIndex)); 448 interstitialIndex += 1; 449 450 } else { 451 interstitialScroll(parseInt(heights[index]) + (elements[index].outerHeight() - $window.height())); 452 } 453 454 } 455 } 456 }, 457 up: function () { 458 if (index >= 0) { 459 if (atTop() && index > 0) { 460 index--; 461 //index, instant, callbacks, toTop 462 animateScroll(index, false, true, false); 463 } else { 464 if (interstitialIndex > 2) { 465 interstitialIndex -= 1; 466 interstitialScroll(parseInt(heights[index]) + ($window.height() * interstitialIndex)); 467 } else { 468 interstitialIndex = 1; 469 interstitialScroll(parseInt(heights[index])); 470 } 471 } 472 } 473 }, 474 init: function () { 475 if (document.addEventListener && settings.touchScroll) { 476 document.addEventListener('touchstart', swipeScroll.touchHandler, false); 477 document.addEventListener('touchmove', swipeScroll.touchHandler, false); 478 document.addEventListener('touchend', swipeScroll.touchHandler, false); 479 } 480 } 481 }; 482 483 484 util = { 485 refresh: function (withCallback, scroll) { 486 clearTimeout(timeoutId2); 487 timeoutId2 = setTimeout(function () { 488 //retain position 489 sizePanels(true); 490 //scroll, firstLoad 491 calculatePositions(scroll, false); 492 if (withCallback) { 493 settings.afterResize(); 494 } 495 }, 400); 496 }, 497 handleUpdate: function () { 498 //callbacks, scroll 499 //changed from false,true to false,false 500 util.refresh(false, false); 501 }, 502 handleResize: function () { 503 //callbacks, scroll 504 util.refresh(true, false); 505 }, 506 handleOrientation: function () { 507 //callbacks, scroll 508 util.refresh(true, true); 509 } 510 }; 511 settings = $.extend(settings, options); 512 513 //retain position 514 sizePanels(false); 515 516 calculatePositions(false, true); 517 518 if (true === hasLocation) { 519 //index, instant, callbacks, toTop 520 animateScroll(index, false, true, true); 521 } else { 522 setTimeout(function () { 523 //instant,callbacks 524 manualScroll.calculateNearest(true, false); 525 }, 200); 526 } 527 if (heights.length) { 528 manualScroll.init(); 529 swipeScroll.init(); 530 531 $window.on("resize", util.handleResize); 532 if (document.addEventListener) { 533 window.addEventListener("orientationchange", util.handleOrientation, false); 534 } 535 } 536 function interstitialScroll(pos) { 537 if ($().velocity) { 538 $(settings.target).stop().velocity('scroll', { 539 duration: settings.scrollSpeed, 540 easing: settings.easing, 541 offset: pos, 542 mobileHA: false 543 }); 544 } else { 545 $(settings.target).stop().animate({ 546 scrollTop: pos 547 }, settings.scrollSpeed, settings.easing); 548 } 549 } 550 551 function sizePanels(keepPosition) { 552 if (keepPosition) { 553 top = $window.scrollTop(); 554 } 555 556 var selector = settings.section; 557 overflow = []; 558 if (settings.interstitialSection.length) { 559 selector += "," + settings.interstitialSection; 560 } 561 if (settings.scrollbars === false) { 562 settings.overflowScroll = false; 563 } 564 $(selector).each(function (i) { 565 var $this = $(this); 566 567 if (settings.setHeights) { 568 if ($this.is(settings.interstitialSection)) { 569 overflow[i] = false; 570 } else { 571 if (($this.css("height", "auto").outerHeight() < $window.height()) || $this.css("overflow") === "hidden") { 572 $this.css({ "height": $window.height() }); 573 overflow[i] = false; 574 } else { 575 576 $this.css({ "height": $this.height() }); 577 578 if (settings.overflowScroll) { 579 overflow[i] = true; 580 } else { 581 overflow[i] = false; 582 } 583 } 584 585 } 586 } 587 else { 588 if (($this.outerHeight() < $window.height()) || (settings.overflowScroll === false)) { 589 overflow[i] = false; 590 } else { 591 overflow[i] = true; 592 } 593 } 594 }); 595 if (keepPosition) { 596 $window.scrollTop(top); 597 } 598 } 599 function calculatePositions(scroll, firstLoad) { 600 var selector = settings.section; 601 if (settings.interstitialSection.length) { 602 selector += "," + settings.interstitialSection; 603 } 604 heights = []; 605 names = []; 606 elements = []; 607 $(selector).each(function (i) { 608 var $this = $(this); 609 if (i > 0) { 610 heights[i] = parseInt($this.offset().top) + settings.offset; 611 } else { 612 heights[i] = parseInt($this.offset().top); 613 } 614 if (settings.sectionName && $this.data(settings.sectionName)) { 615 names[i] = "#" + $this.data(settings.sectionName).toString().replace(/ /g, "-"); 616 } else { 617 if ($this.is(settings.interstitialSection) === false) { 618 names[i] = "#" + (i + 1); 619 } else { 620 names[i] = "#"; 621 if (i === $(selector).length - 1 && i > 1) { 622 623 heights[i] = heights[i - 1] + (parseInt($($(selector)[i - 1]).outerHeight()) - parseInt($(window).height())) + parseInt($this.outerHeight()); 624 } 625 } 626 } 627 elements[i] = $this; 628 try { 629 if ($(names[i]).length && window.console) { 630 console.warn("Scrollify warning: Section names can't match IDs - this will cause the browser to anchor."); 631 } 632 } catch (e) { } 633 634 if (window.location.hash === names[i]) { 635 index = i; 636 hasLocation = true; 637 } 638 }); 639 640 if (true === scroll) { 641 //index, instant, callbacks, toTop 642 animateScroll(index, false, false, false); 643 } 644 } 645 646 function atTop() { 647 if (!overflow[index]) { 648 return true; 649 } 650 top = $window.scrollTop(); 651 if (top > parseInt(heights[index])) { 652 return false; 653 } else { 654 return true; 655 } 656 } 657 function atBottom() { 658 if (!overflow[index]) { 659 return true; 660 } 661 top = $window.scrollTop(); 662 663 if (top < parseInt(heights[index]) + (elements[index].outerHeight() - $window.height()) - 28) { 664 return false; 665 } else { 666 return true; 667 } 668 } 669 } 670 671 function move(panel, instant) { 672 var z = names.length; 673 for (; z >= 0; z--) { 674 if (typeof panel === 'string') { 675 if (names[z] === panel) { 676 index = z; 677 //index, instant, callbacks, toTop 678 animateScroll(z, instant, true, true); 679 } 680 } else { 681 if (z === panel) { 682 index = z; 683 //index, instant, callbacks, toTop 684 animateScroll(z, instant, true, true); 685 } 686 } 687 } 688 } 689 scrollify.move = function (panel) { 690 if (panel === undefined) { 691 return false; 692 } 693 if (panel.originalEvent) { 694 panel = $(this).attr("href"); 695 } 696 move(panel, false); 697 }; 698 scrollify.instantMove = function (panel) { 699 if (panel === undefined) { 700 return false; 701 } 702 move(panel, true); 703 }; 704 scrollify.next = function () { 705 if (index < names.length) { 706 index += 1; 707 //index, instant, callbacks, toTop 708 animateScroll(index, false, true, true); 709 } 710 }; 711 scrollify.previous = function () { 712 if (index > 0) { 713 index -= 1; 714 //index, instant, callbacks, toTop 715 animateScroll(index, false, true, true); 716 } 717 }; 718 scrollify.instantNext = function () { 719 if (index < names.length) { 720 index += 1; 721 //index, instant, callbacks, toTop 722 animateScroll(index, true, true, true); 723 } 724 }; 725 scrollify.instantPrevious = function () { 726 if (index > 0) { 727 index -= 1; 728 //index, instant, callbacks, toTop 729 animateScroll(index, true, true, true); 730 } 731 }; 732 scrollify.destroy = function () { 733 if (!initialised) { 734 return false; 735 } 736 if (settings.setHeights) { 737 $(settings.section).each(function () { 738 $(this).css("height", "auto"); 739 }); 740 } 741 $window.off("resize", util.handleResize); 742 if (settings.scrollbars) { 743 $window.off('mousedown', manualScroll.handleMousedown); 744 $window.off('mouseup', manualScroll.handleMouseup); 745 $window.off('scroll', manualScroll.handleScroll); 746 } 747 $window.off(wheelEvent, manualScroll.wheelHandler); 748 $window.off('keydown', manualScroll.keyHandler); 749 750 if (document.addEventListener && settings.touchScroll) { 751 document.removeEventListener('touchstart', swipeScroll.touchHandler, false); 752 document.removeEventListener('touchmove', swipeScroll.touchHandler, false); 753 document.removeEventListener('touchend', swipeScroll.touchHandler, false); 754 } 755 heights = []; 756 names = []; 757 elements = []; 758 overflow = []; 759 }; 760 scrollify.update = function () { 761 if (!initialised) { 762 return false; 763 } 764 util.handleUpdate(); 765 }; 766 scrollify.current = function () { 767 return elements[index]; 768 }; 769 scrollify.currentIndex = function () { 770 return index; 771 }; 772 scrollify.disable = function () { 773 disabled = true; 774 }; 775 scrollify.enable = function () { 776 disabled = false; 777 if (initialised) { 778 //instant,callbacks 779 manualScroll.calculateNearest(false, false); 780 } 781 }; 782 scrollify.isDisabled = function () { 783 return disabled; 784 }; 785 scrollify.setOptions = function (updatedOptions) { 786 if (!initialised) { 787 return false; 788 } 789 if (typeof updatedOptions === "object") { 790 settings = $.extend(settings, updatedOptions); 791 util.handleUpdate(); 792 } else if (window.console) { 793 console.warn("Scrollify warning: setOptions expects an object."); 794 } 795 }; 796 $.scrollify = scrollify; 797 return scrollify; 798}));
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.