JAVASCRIPT   72

smooth-scroll.js

Guest on 29th August 2021 02:52:13 PM

  1. //
  2. // SmoothScroll for websites v1.4.5 (Balazs Galambosi)
  3. // http://www.smoothscroll.net/
  4. //
  5. // Licensed under the terms of the MIT license.
  6. //
  7. // You may use it in your theme if you credit me.
  8. // It is also free to use on any individual website.
  9. //
  10. // Exception:
  11. // The only restriction is to not publish any
  12. // extension for browsers or native application
  13. // without getting a written permission first.
  14. //
  15.  
  16. (function () {
  17.  
  18. // Scroll Variables (tweakable)
  19. var defaultOptions = {
  20.  
  21.     // Scrolling Core
  22.     frameRate        : 150, // [Hz]
  23.     animationTime    : 400, // [ms]
  24.     stepSize         : 100, // [px]
  25.  
  26.     // Pulse (less tweakable)
  27.     // ratio of "tail" to "acceleration"
  28.     pulseAlgorithm   : true,
  29.     pulseScale       : 4,
  30.     pulseNormalize   : 1,
  31.  
  32.     // Acceleration
  33.     accelerationDelta : 50,  // 50
  34.     accelerationMax   : 3,   // 3
  35.  
  36.     // Keyboard Settings
  37.     keyboardSupport   : true,  // option
  38.     arrowScroll       : 50,    // [px]
  39.  
  40.     // Other
  41.     touchpadSupport   : false, // ignore touchpad by default
  42.     fixedBackground   : true,
  43.     excluded          : ''
  44. };
  45.  
  46. var options = defaultOptions;
  47.  
  48.  
  49. // Other Variables
  50. var isExcluded = false;
  51. var isFrame = false;
  52. var direction = { x: 0, y: 0 };
  53. var initDone  = false;
  54. var root = document.documentElement;
  55. var activeElement;
  56. var observer;
  57. var refreshSize;
  58. var deltaBuffer = [];
  59. var isMac = /^Mac/.test(navigator.platform);
  60.  
  61. var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32,
  62.             pageup: 33, pagedown: 34, end: 35, home: 36 };
  63. var arrowKeys = { 37: 1, 38: 1, 39: 1, 40: 1 };
  64.  
  65. /***********************************************
  66.  * INITIALIZE
  67.  ***********************************************/
  68.  
  69. /**
  70.  * Tests if smooth scrolling is allowed. Shuts down everything if not.
  71.  */
  72. function initTest() {
  73.     if (options.keyboardSupport) {
  74.         addEvent('keydown', keydown);
  75.     }
  76. }
  77.  
  78. /**
  79.  * Sets up scrolls array, determines if frames are involved.
  80.  */
  81. function init() {
  82.  
  83.     if (initDone || !document.body) return;
  84.  
  85.     initDone = true;
  86.  
  87.     var body = document.body;
  88.     var html = document.documentElement;
  89.     var windowHeight = window.innerHeight;
  90.     var scrollHeight = body.scrollHeight;
  91.  
  92.     // check compat mode for root element
  93.     root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
  94.     activeElement = body;
  95.  
  96.     initTest();
  97.  
  98.     // Checks if this script is running in a frame
  99.     if (top != self) {
  100.         isFrame = true;
  101.     }
  102.  
  103.     /**
  104.      * Safari 10 fixed it, Chrome fixed it in v45:
  105.      * This fixes a bug where the areas left and right to
  106.      * the content does not trigger the onmousewheel event
  107.      * on some pages. e.g.: html, body { height: 100% }
  108.      */
  109.     else if (isOldSafari &&
  110.              scrollHeight > windowHeight &&
  111.             (body.offsetHeight <= windowHeight ||
  112.              html.offsetHeight <= windowHeight)) {
  113.  
  114.         var fullPageElem = document.createElement('div');
  115.         fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' +
  116.                                      'top:0; left:0; right:0; height:' +
  117.                                       root.scrollHeight + 'px';
  118.         document.body.appendChild(fullPageElem);
  119.  
  120.         // DOM changed (throttled) to fix height
  121.         var pendingRefresh;
  122.         refreshSize = function () {
  123.             if (pendingRefresh) return; // could also be: clearTimeout(pendingRefresh);
  124.             pendingRefresh = setTimeout(function () {
  125.                 if (isExcluded) return; // could be running after cleanup
  126.                 fullPageElem.style.height = '0';
  127.                 fullPageElem.style.height = root.scrollHeight + 'px';
  128.                 pendingRefresh = null;
  129.             }, 500); // act rarely to stay fast
  130.         };
  131.  
  132.         setTimeout(refreshSize, 10);
  133.  
  134.         addEvent('resize', refreshSize);
  135.  
  136.         // TODO: attributeFilter?
  137.         var config = {
  138.             attributes: true,
  139.             childList: true,
  140.             characterData: false
  141.             // subtree: true
  142.         };
  143.  
  144.         observer = new MutationObserver(refreshSize);
  145.         observer.observe(body, config);
  146.  
  147.         if (root.offsetHeight <= windowHeight) {
  148.             var clearfix = document.createElement('div');
  149.             clearfix.style.clear = 'both';
  150.             body.appendChild(clearfix);
  151.         }
  152.     }
  153.  
  154.     // disable fixed background
  155.     if (!options.fixedBackground && !isExcluded) {
  156.         body.style.backgroundAttachment = 'scroll';
  157.         html.style.backgroundAttachment = 'scroll';
  158.     }
  159. }
  160.  
  161. /**
  162.  * Removes event listeners and other traces left on the page.
  163.  */
  164. function cleanup() {
  165.     observer && observer.disconnect();
  166.     removeEvent(wheelEvent, wheel);
  167.     removeEvent('mousedown', mousedown);
  168.     removeEvent('keydown', keydown);
  169.     removeEvent('resize', refreshSize);
  170.     removeEvent('load', init);
  171. }
  172.  
  173.  
  174. /************************************************
  175.  * SCROLLING
  176.  ************************************************/
  177.  
  178. var que = [];
  179. var pending = false;
  180. var lastScroll = Date.now();
  181.  
  182. /**
  183.  * Pushes scroll actions to the scrolling queue.
  184.  */
  185. function scrollArray(elem, left, top) {
  186.  
  187.     directionCheck(left, top);
  188.  
  189.     if (options.accelerationMax != 1) {
  190.         var now = Date.now();
  191.         var elapsed = now - lastScroll;
  192.         if (elapsed < options.accelerationDelta) {
  193.             var factor = (1 + (50 / elapsed)) / 2;
  194.             if (factor > 1) {
  195.                 factor = Math.min(factor, options.accelerationMax);
  196.                 left *= factor;
  197.                 top  *= factor;
  198.             }
  199.         }
  200.         lastScroll = Date.now();
  201.     }
  202.  
  203.     // push a scroll command
  204.     que.push({
  205.         x: left,
  206.         y: top,
  207.         lastX: (left < 0) ? 0.99 : -0.99,
  208.         lastY: (top  < 0) ? 0.99 : -0.99,
  209.         start: Date.now()
  210.     });
  211.  
  212.     // don't act if there's a pending queue
  213.     if (pending) {
  214.         return;
  215.     }
  216.  
  217.     var scrollWindow = (elem === document.body);
  218.  
  219.     var step = function (time) {
  220.  
  221.         var now = Date.now();
  222.         var scrollX = 0;
  223.         var scrollY = 0;
  224.  
  225.         for (var i = 0; i < que.length; i++) {
  226.  
  227.             var item = que[i];
  228.             var elapsed  = now - item.start;
  229.             var finished = (elapsed >= options.animationTime);
  230.  
  231.             // scroll position: [0, 1]
  232.             var position = (finished) ? 1 : elapsed / options.animationTime;
  233.  
  234.             // easing [optional]
  235.             if (options.pulseAlgorithm) {
  236.                 position = pulse(position);
  237.             }
  238.  
  239.             // only need the difference
  240.             var x = (item.x * position - item.lastX) >> 0;
  241.             var y = (item.y * position - item.lastY) >> 0;
  242.  
  243.             // add this to the total scrolling
  244.             scrollX += x;
  245.             scrollY += y;
  246.  
  247.             // update last values
  248.             item.lastX += x;
  249.             item.lastY += y;
  250.  
  251.             // delete and step back if it's over
  252.             if (finished) {
  253.                 que.splice(i, 1); i--;
  254.             }
  255.         }
  256.  
  257.         // scroll left and top
  258.         if (scrollWindow) {
  259.             window.scrollBy(scrollX, scrollY);
  260.         }
  261.         else {
  262.             if (scrollX) elem.scrollLeft += scrollX;
  263.             if (scrollY) elem.scrollTop  += scrollY;
  264.         }
  265.  
  266.         // clean up if there's nothing left to do
  267.         if (!left && !top) {
  268.             que = [];
  269.         }
  270.  
  271.         if (que.length) {
  272.             requestFrame(step, elem, (1000 / options.frameRate + 1));
  273.         } else {
  274.             pending = false;
  275.         }
  276.     };
  277.  
  278.     // start a new queue of actions
  279.     requestFrame(step, elem, 0);
  280.     pending = true;
  281. }
  282.  
  283.  
  284. /***********************************************
  285.  * EVENTS
  286.  ***********************************************/
  287.  
  288. /**
  289.  * Mouse wheel handler.
  290.  * @param {Object} event
  291.  */
  292. function wheel(event) {
  293.  
  294.     if (!initDone) {
  295.         init();
  296.     }
  297.  
  298.     var target = event.target;
  299.  
  300.     // leave early if default action is prevented
  301.     // or it's a zooming event with CTRL
  302.     if (event.defaultPrevented || event.ctrlKey) {
  303.         return true;
  304.     }
  305.  
  306.     // leave embedded content alone (flash & pdf)
  307.     if (isNodeName(activeElement, 'embed') ||
  308.        (isNodeName(target, 'embed') && /\.pdf/i.test(target.src)) ||
  309.         isNodeName(activeElement, 'object') ||
  310.         target.shadowRoot) {
  311.         return true;
  312.     }
  313.  
  314.     var deltaX = -event.wheelDeltaX || event.deltaX || 0;
  315.     var deltaY = -event.wheelDeltaY || event.deltaY || 0;
  316.  
  317.     if (isMac) {
  318.         if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) {
  319.             deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX));
  320.         }
  321.         if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) {
  322.             deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY));
  323.         }
  324.     }
  325.  
  326.     // use wheelDelta if deltaX/Y is not available
  327.     if (!deltaX && !deltaY) {
  328.         deltaY = -event.wheelDelta || 0;
  329.     }
  330.  
  331.     // line based scrolling (Firefox mostly)
  332.     if (event.deltaMode === 1) {
  333.         deltaX *= 40;
  334.         deltaY *= 40;
  335.     }
  336.  
  337.     var overflowing = overflowingAncestor(target);
  338.  
  339.     // nothing to do if there's no element that's scrollable
  340.     if (!overflowing) {
  341.         // except Chrome iframes seem to eat wheel events, which we need to
  342.         // propagate up, if the iframe has nothing overflowing to scroll
  343.         if (isFrame && isChrome)  {
  344.             // change target to iframe element itself for the parent frame
  345.             Object.defineProperty(event, "target", {value: window.frameElement});
  346.             return parent.wheel(event);
  347.         }
  348.         return true;
  349.     }
  350.  
  351.     // check if it's a touchpad scroll that should be ignored
  352.     if (!options.touchpadSupport && isTouchpad(deltaY)) {
  353.         return true;
  354.     }
  355.  
  356.     // scale by step size
  357.     // delta is 120 most of the time
  358.     // synaptics seems to send 1 sometimes
  359.     if (Math.abs(deltaX) > 1.2) {
  360.         deltaX *= options.stepSize / 120;
  361.     }
  362.     if (Math.abs(deltaY) > 1.2) {
  363.         deltaY *= options.stepSize / 120;
  364.     }
  365.  
  366.     scrollArray(overflowing, deltaX, deltaY);
  367.     if(event.type === 'touchstart')
  368.         event.preventDefault();
  369.     scheduleClearCache();
  370. }
  371.  
  372. /**
  373.  * Keydown event handler.
  374.  * @param {Object} event
  375.  */
  376. function keydown(event) {
  377.  
  378.     var target   = event.target;
  379.     var modifier = event.ctrlKey || event.altKey || event.metaKey ||
  380.                   (event.shiftKey && event.keyCode !== key.spacebar);
  381.  
  382.     // our own tracked active element could've been removed from the DOM
  383.     if (!document.body.contains(activeElement)) {
  384.         activeElement = document.activeElement;
  385.     }
  386.  
  387.     // do nothing if user is editing text
  388.     // or using a modifier key (except shift)
  389.     // or in a dropdown
  390.     // or inside interactive elements
  391.     var inputNodeNames = /^(textarea|select|embed|object)$/i;
  392.     var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i;
  393.     if ( event.defaultPrevented ||
  394.          inputNodeNames.test(target.nodeName) ||
  395.          isNodeName(target, 'input') && !buttonTypes.test(target.type) ||
  396.          isNodeName(activeElement, 'video') ||
  397.          isInsideYoutubeVideo(event) ||
  398.          target.isContentEditable ||
  399.          modifier ) {
  400.       return true;
  401.     }
  402.  
  403.     // [spacebar] should trigger button press, leave it alone
  404.     if ((isNodeName(target, 'button') ||
  405.          isNodeName(target, 'input') && buttonTypes.test(target.type)) &&
  406.         event.keyCode === key.spacebar) {
  407.       return true;
  408.     }
  409.  
  410.     // [arrwow keys] on radio buttons should be left alone
  411.     if (isNodeName(target, 'input') && target.type == 'radio' &&
  412.         arrowKeys[event.keyCode])  {
  413.       return true;
  414.     }
  415.  
  416.     var shift, x = 0, y = 0;
  417.     var overflowing = overflowingAncestor(activeElement);
  418.  
  419.     if (!overflowing) {
  420.         // Chrome iframes seem to eat key events, which we need to
  421.         // propagate up, if the iframe has nothing overflowing to scroll
  422.         return (isFrame && isChrome) ? parent.keydown(event) : true;
  423.     }
  424.  
  425.     var clientHeight = overflowing.clientHeight;
  426.  
  427.     if (overflowing == document.body) {
  428.         clientHeight = window.innerHeight;
  429.     }
  430.  
  431.     switch (event.keyCode) {
  432.         case key.up:
  433.             y = -options.arrowScroll;
  434.             break;
  435.         case key.down:
  436.             y = options.arrowScroll;
  437.             break;
  438.         case key.spacebar: // (+ shift)
  439.             shift = event.shiftKey ? 1 : -1;
  440.             y = -shift * clientHeight * 0.9;
  441.             break;
  442.         case key.pageup:
  443.             y = -clientHeight * 0.9;
  444.             break;
  445.         case key.pagedown:
  446.             y = clientHeight * 0.9;
  447.             break;
  448.         case key.home:
  449.             y = -overflowing.scrollTop;
  450.             break;
  451.         case key.end:
  452.             var scroll = overflowing.scrollHeight - overflowing.scrollTop;
  453.             var scrollRemaining = scroll - clientHeight;
  454.             y = (scrollRemaining > 0) ? scrollRemaining + 10 : 0;
  455.             break;
  456.         case key.left:
  457.             x = -options.arrowScroll;
  458.             break;
  459.         case key.right:
  460.             x = options.arrowScroll;
  461.             break;
  462.         default:
  463.             return true; // a key we don't care about
  464.     }
  465.  
  466.     scrollArray(overflowing, x, y);
  467.     event.preventDefault();
  468.     scheduleClearCache();
  469. }
  470.  
  471. /**
  472.  * Mousedown event only for updating activeElement
  473.  */
  474. function mousedown(event) {
  475.     activeElement = event.target;
  476. }
  477.  
  478.  
  479. /***********************************************
  480.  * OVERFLOW
  481.  ***********************************************/
  482.  
  483. var uniqueID = (function () {
  484.     var i = 0;
  485.     return function (el) {
  486.         return el.uniqueID || (el.uniqueID = i++);
  487.     };
  488. })();
  489.  
  490. var cache = {}; // cleared out after a scrolling session
  491. var clearCacheTimer;
  492.  
  493. //setInterval(function () { cache = {}; }, 10 * 1000);
  494.  
  495. function scheduleClearCache() {
  496.     clearTimeout(clearCacheTimer);
  497.     clearCacheTimer = setInterval(function () { cache = {}; }, 1*1000);
  498. }
  499.  
  500. function setCache(elems, overflowing) {
  501.     for (var i = elems.length; i--;)
  502.         cache[uniqueID(elems[i])] = overflowing;
  503.     return overflowing;
  504. }
  505.  
  506. //  (body)                (root)
  507. //         | hidden | visible | scroll |  auto  |
  508. // hidden  |   no   |    no   |   YES  |   YES  |
  509. // visible |   no   |   YES   |   YES  |   YES  |
  510. // scroll  |   no   |   YES   |   YES  |   YES  |
  511. // auto    |   no   |   YES   |   YES  |   YES  |
  512.  
  513. function overflowingAncestor(el) {
  514.     var elems = [];
  515.     var body = document.body;
  516.     var rootScrollHeight = root.scrollHeight;
  517.     do {
  518.         var cached = cache[uniqueID(el)];
  519.         if (cached) {
  520.             return setCache(elems, cached);
  521.         }
  522.         elems.push(el);
  523.         if (rootScrollHeight === el.scrollHeight) {
  524.             var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body);
  525.             var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root);
  526.             if (isFrame && isContentOverflowing(root) ||
  527.                !isFrame && isOverflowCSS) {
  528.                 return setCache(elems, getScrollRoot());
  529.             }
  530.         } else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) {
  531.             return setCache(elems, el);
  532.         }
  533.     } while (el = el.parentElement);
  534. }
  535.  
  536. function isContentOverflowing(el) {
  537.     return (el.clientHeight + 10 < el.scrollHeight);
  538. }
  539.  
  540. // typically for <body> and <html>
  541. function overflowNotHidden(el) {
  542.     var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
  543.     return (overflow !== 'hidden');
  544. }
  545.  
  546. // for all other elements
  547. function overflowAutoOrScroll(el) {
  548.     var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
  549.     return (overflow === 'scroll' || overflow === 'auto');
  550. }
  551.  
  552.  
  553. /***********************************************
  554.  * HELPERS
  555.  ***********************************************/
  556.  
  557. function addEvent(type, fn) {
  558.     window.addEventListener(type, fn, false);
  559. }
  560.  
  561. function removeEvent(type, fn) {
  562.     window.removeEventListener(type, fn, false);
  563. }
  564.  
  565. function isNodeName(el, tag) {
  566.     return (el.nodeName||'').toLowerCase() === tag.toLowerCase();
  567. }
  568.  
  569. function directionCheck(x, y) {
  570.     x = (x > 0) ? 1 : -1;
  571.     y = (y > 0) ? 1 : -1;
  572.     if (direction.x !== x || direction.y !== y) {
  573.         direction.x = x;
  574.         direction.y = y;
  575.         que = [];
  576.         lastScroll = 0;
  577.     }
  578. }
  579.  
  580. var deltaBufferTimer;
  581.  
  582. if (window.localStorage && localStorage.SS_deltaBuffer) {
  583.     try { // #46 Safari throws in private browsing for localStorage
  584.         deltaBuffer = localStorage.SS_deltaBuffer.split(',');
  585.     } catch (e) { }
  586. }
  587.  
  588. function isTouchpad(deltaY) {
  589.     if (!deltaY) return;
  590.     if (!deltaBuffer.length) {
  591.         deltaBuffer = [deltaY, deltaY, deltaY];
  592.     }
  593.     deltaY = Math.abs(deltaY);
  594.     deltaBuffer.push(deltaY);
  595.     deltaBuffer.shift();
  596.     clearTimeout(deltaBufferTimer);
  597.     deltaBufferTimer = setTimeout(function () {
  598.         try { // #46 Safari throws in private browsing for localStorage
  599.             localStorage.SS_deltaBuffer = deltaBuffer.join(',');
  600.         } catch (e) { }
  601.     }, 1000);
  602.     return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100);
  603. }
  604.  
  605. function isDivisible(n, divisor) {
  606.     return (Math.floor(n / divisor) == n / divisor);
  607. }
  608.  
  609. function allDeltasDivisableBy(divisor) {
  610.     return (isDivisible(deltaBuffer[0], divisor) &&
  611.             isDivisible(deltaBuffer[1], divisor) &&
  612.             isDivisible(deltaBuffer[2], divisor));
  613. }
  614.  
  615. function isInsideYoutubeVideo(event) {
  616.     var elem = event.target;
  617.     var isControl = false;
  618.     if (document.URL.indexOf ('www.youtube.com/watch') != -1) {
  619.         do {
  620.             isControl = (elem.classList &&
  621.                          elem.classList.contains('html5-video-controls'));
  622.             if (isControl) break;
  623.         } while (elem = elem.parentNode);
  624.     }
  625.     return isControl;
  626. }
  627.  
  628. var requestFrame = (function () {
  629.       return (window.requestAnimationFrame       ||
  630.               window.webkitRequestAnimationFrame ||
  631.               window.mozRequestAnimationFrame    ||
  632.               function (callback, element, delay) {
  633.                  window.setTimeout(callback, delay || (1000/60));
  634.              });
  635. })();
  636.  
  637. var MutationObserver = (window.MutationObserver ||
  638.                         window.WebKitMutationObserver ||
  639.                         window.MozMutationObserver);
  640.  
  641. var getScrollRoot = (function() {
  642.   var SCROLL_ROOT;
  643.   return function() {
  644.     if (!SCROLL_ROOT) {
  645.       var dummy = document.createElement('div');
  646.       dummy.style.cssText = 'height:10000px;width:1px;';
  647.       document.body.appendChild(dummy);
  648.       var bodyScrollTop  = document.body.scrollTop;
  649.       var docElScrollTop = document.documentElement.scrollTop;
  650.       window.scrollBy(0, 3);
  651.       if (document.body.scrollTop != bodyScrollTop)
  652.         (SCROLL_ROOT = document.body);
  653.       else
  654.         (SCROLL_ROOT = document.documentElement);
  655.       window.scrollBy(0, -3);
  656.       document.body.removeChild(dummy);
  657.     }
  658.     return SCROLL_ROOT;
  659.   };
  660. })();
  661.  
  662.  
  663. /***********************************************
  664.  * PULSE (by Michael Herf)
  665.  ***********************************************/
  666.  
  667. /**
  668.  * Viscous fluid with a pulse for part and decay for the rest.
  669.  * - Applies a fixed force over an interval (a damped acceleration), and
  670.  * - Lets the exponential bleed away the velocity over a longer interval
  671.  * - Michael Herf, http://stereopsis.com/stopping/
  672.  */
  673. function pulse_(x) {
  674.     var val, start, expx;
  675.     // test
  676.     x = x * options.pulseScale;
  677.     if (x < 1) { // acceleartion
  678.         val = x - (1 - Math.exp(-x));
  679.     } else {     // tail
  680.         // the previous animation ended here:
  681.         start = Math.exp(-1);
  682.         // simple viscous drag
  683.         x -= 1;
  684.         expx = 1 - Math.exp(-x);
  685.         val = start + (expx * (1 - start));
  686.     }
  687.     return val * options.pulseNormalize;
  688. }
  689.  
  690. function pulse(x) {
  691.     if (x >= 1) return 1;
  692.     if (x <= 0) return 0;
  693.  
  694.     if (options.pulseNormalize == 1) {
  695.         options.pulseNormalize /= pulse_(1);
  696.     }
  697.     return pulse_(x);
  698. }
  699.  
  700.  
  701. /***********************************************
  702.  * FIRST RUN
  703.  ***********************************************/
  704.  
  705. var userAgent = window.navigator.userAgent;
  706. var isEdge    = /Edge/.test(userAgent); // thank you MS
  707. var isChrome  = /chrome/i.test(userAgent) && !isEdge;
  708. var isSafari  = /safari/i.test(userAgent) && !isEdge;
  709. var isMobile  = /mobile/i.test(userAgent);
  710. var isIEWin7  = /Windows NT 6.1/i.test(userAgent) && /rv:11/i.test(userAgent);
  711. var isOldSafari = isSafari && (/Version\/8/i.test(userAgent) || /Version\/9/i.test(userAgent));
  712. var isEnabledForBrowser = (isChrome || isSafari || isIEWin7) && !isMobile;
  713.  
  714. var wheelEvent;
  715. if ('onwheel' in document.createElement('div'))
  716.     wheelEvent = 'wheel';
  717. else if ('onmousewheel' in document.createElement('div'))
  718.     wheelEvent = 'mousewheel';
  719.  
  720. if (wheelEvent && isEnabledForBrowser) {
  721.     addEvent(wheelEvent, wheel);
  722.     addEvent('mousedown', mousedown);
  723.     addEvent('load', init);
  724. }
  725.  
  726.  
  727. /***********************************************
  728.  * PUBLIC INTERFACE
  729.  ***********************************************/
  730.  
  731. function SmoothScroll(optionsToSet) {
  732.     for (var key in optionsToSet)
  733.         if (defaultOptions.hasOwnProperty(key))
  734.             options[key] = optionsToSet[key];
  735. }
  736. SmoothScroll.destroy = cleanup;
  737.  
  738. if (window.SmoothScrollOptions) // async API
  739.     SmoothScroll(window.SmoothScrollOptions);
  740.  
  741. if (typeof define === 'function' && define.amd)
  742.     define(function() {
  743.         return SmoothScroll;
  744.     });
  745. else if ('object' == typeof exports)
  746.     module.exports = SmoothScroll;
  747. else
  748.     window.SmoothScroll = SmoothScroll;
  749.  
  750. })();

Raw Paste


Login or Register to edit or fork this paste. It's free.