PageSourceSearch

https://pafikotabadung.org/js/smooth-scroll.js

js pafikotabadung.org collected 2026-09-30 12:46:17 UTC 26,291 bytes, 799 lines download raw bytes

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

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.