PageSourceSearch

https://yelosui.com/wp-content/themes/marroco/assets/js/vendors/jq…/jquery.smooth-scroll_ver-1.4.js

js yelosui.com collected 2026-09-27 13:42:41 UTC 16,306 bytes, 586 lines download raw bytes

1// SmoothScroll v1.2.1
2// Licensed under the terms of the MIT license.
3
4// People involved
5//  - Balazs Galambosi (maintainer)  
6//  - Patrick Brunner  (original idea)
7//  - Michael Herf     (Pulse Algorithm)
8
9// Scroll Variables (tweakable)
10var defaultOptions = {
11
12    // Scrolling Core
13    frameRate        : 150, // [Hz]
14    animationTime    : 600, // [px]
15    stepSize         : 120, // [px]
16
17    // Pulse (less tweakable)
18    // ratio of "tail" to "acceleration"
19    pulseAlgorithm   : true,
20    pulseScale       : 8,
21    pulseNormalize   : 1,
22
23    // Acceleration
24    accelerationDelta : 20,  // 20
25    accelerationMax   : 1,   // 1
26
27    // Keyboard Settings
28    keyboardSupport   : true,  // option
29    arrowScroll       : 50,     // [px]
30
31    // Other
32    touchpadSupport   : true,
33    fixedBackground   : true, 
34    excluded          : ""    
35};
36
37var options = defaultOptions;
38
39
40// Other Variables
41var isExcluded = false;
42var isFrame = false;
43var direction = { x: 0, y: 0 };
44var initDone  = false;
45var root = document.documentElement;
46var activeElement;
47var observer;
48var deltaBuffer = [ 120, 120, 120 ];
49
50var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32, 
51            pageup: 33, pagedown: 34, end: 35, home: 36 };
52
53
54/***********************************************
55 * SETTINGS
56 ***********************************************/
57if(typeof(chrome) !== 'undefined' && typeof(chrome.storage) !== 'undefined') {
58chrome.storage.sync.get(defaultOptions, function (syncedOptions) {
59
60    options = syncedOptions;
61
62    // it seems that sometimes settings come late
63    // and we need to test again for excluded pages
64    initTest();
65});
66}
67
68/***********************************************
69 * INITIALIZE
70 ***********************************************/
71
72/**
73 * Tests if smooth scrolling is allowed. Shuts down everything if not.
74 */
75function initTest() {
76
77    var disableKeyboard = false; 
78
79    // disable keys for google reader (spacebar conflict)
80    if (document.URL.indexOf("google.com/reader/view") > -1) {
81        disableKeyboard = true;
82    }
83
84    // disable everything if the page is blacklisted
85    if (options.excluded) {
86        var domains = options.excluded.split(/[,\n] ?/);
87        domains.push("mail.google.com"); // exclude Gmail for now
88        for (var i = domains.length; i--;) {
89            if (document.URL.indexOf(domains[i]) > -1) {
90                observer && observer.disconnect();
91                removeEvent("mousewheel", wheel);
92                disableKeyboard = true;
93                isExcluded = true;
94                break;
95            }
96        }
97    }
98    
99    // disable keyboard support if anything above requested it
100    if (disableKeyboard) {
101        removeEvent("keydown", keydown);
102    }
103
104    if (options.keyboardSupport && !disableKeyboard) {
105        addEvent("keydown", keydown);
106    }
107}
108
109/**
110 * Sets up scrolls array, determines if frames are involved.
111 */
112function init() {
113  
114    if (!document.body) return;
115
116    var body = document.body;
117    var html = document.documentElement;
118    var windowHeight = window.innerHeight; 
119    var scrollHeight = body.scrollHeight;
120    
121    // check compat mode for root element
122    root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
123    activeElement = body;
124    
125    initTest();
126    initDone = true;
127
128    // Checks if this script is running in a frame
129    if (top != self) {
130        isFrame = true;
131    }
132
133    /**
134     * This fixes a bug where the areas left and right to 
135     * the content does not trigger the onmousewheel event
136     * on some pages. e.g.: html, body { height: 100% }
137     */
138    else if (scrollHeight > windowHeight &&
139            (body.offsetHeight <= windowHeight || 
140             html.offsetHeight <= windowHeight)) {
141
142        // DOMChange (throttle): fix height
143        var pending = false;
144        var refresh = function () {
145            if (!pending && html.scrollHeight != document.height) {
146                pending = true; // add a new pending action
147                setTimeout(function () {
148                    html.style.height = document.height + 'px';
149                    pending = false;
150                }, 500); // act rarely to stay fast
151            }
152        };
153        html.style.height = 'auto';
154        setTimeout(refresh, 10);
155
156        var config = {
157            attributes: true, 
158            childList: true, 
159            characterData: false 
160        };
161
162        observer = new MutationObserver(refresh);
163        observer.observe(body, config);
164
165        // clearfix
166        if (root.offsetHeight <= windowHeight) {
167            var underlay = document.createElement("div"); 	
168            underlay.style.clear = "both";
169            body.appendChild(underlay);
170        }
171    }
172    
173    // gmail performance fix
174    if (document.URL.indexOf("mail.google.com") > -1) {
175        var s = document.createElement("style");
176        s.innerHTML = ".iu { visibility: hidden }";
177        (document.getElementsByTagName("head")[0] || html).appendChild(s);
178    }
179    // facebook better home timeline performance
180    // all the HTML resized images make rendering CPU intensive
181    else if (document.URL.indexOf("www.facebook.com") > -1) {
182        var home_stream = document.getElementById("home_stream");
183        home_stream && (home_stream.style.webkitTransform = "translateZ(0)");
184    } 
185    // disable fixed background
186    if (!options.fixedBackground && !isExcluded) {
187        body.style.backgroundAttachment = "scroll";
188        html.style.backgroundAttachment = "scroll";
189    }
190}
191
192
193/************************************************
194 * SCROLLING 
195 ************************************************/
196 
197var que = [];
198var pending = false;
199var lastScroll = +new Date;
200
201/**
202 * Pushes scroll actions to the scrolling queue.
203 */
204function scrollArray(elem, left, top, delay) {
205    
206    delay || (delay = 1000);
207    directionCheck(left, top);
208
209    if (options.accelerationMax != 1) {
210        var now = +new Date;
211        var elapsed = now - lastScroll;
212        if (elapsed < options.accelerationDelta) {
213            var factor = (1 + (30 / elapsed)) / 2;
214            if (factor > 1) {
215                factor = Math.min(factor, options.accelerationMax);
216                left *= factor;
217                top  *= factor;
218            }
219        }
220        lastScroll = +new Date;
221    }          
222    
223    // push a scroll command
224    que.push({
225        x: left, 
226        y: top, 
227        lastX: (left < 0) ? 0.99 : -0.99,
228        lastY: (top  < 0) ? 0.99 : -0.99, 
229        start: +new Date
230    });
231        
232    // don't act if there's a pending queue
233    if (pending) {
234        return;
235    }  
236
237    var scrollWindow = (elem === document.body);
238    
239    var step = function (time) {
240        
241        var now = +new Date;
242        var scrollX = 0;
243        var scrollY = 0; 
244    
245        for (var i = 0; i < que.length; i++) {
246            
247            var item = que[i];
248            var elapsed  = now - item.start;
249            var finished = (elapsed >= options.animationTime);
250            
251            // scroll position: [0, 1]
252            var position = (finished) ? 1 : elapsed / options.animationTime;
253            
254            // easing [optional]
255            if (options.pulseAlgorithm) {
256                position = pulse(position);
257            }
258            
259            // only need the difference
260            var x = (item.x * position - item.lastX) >> 0;
261            var y = (item.y * position - item.lastY) >> 0;
262            
263            // add this to the total scrolling
264            scrollX += x;
265            scrollY += y;            
266            
267            // update last values
268            item.lastX += x;
269            item.lastY += y;
270        
271            // delete and step back if it's over
272            if (finished) {
273                que.splice(i, 1); i--;
274            }           
275        }
276
277        // scroll left and top
278        if (scrollWindow) {
279            window.scrollBy(scrollX, scrollY);
280        } 
281        else {
282            if (scrollX) elem.scrollLeft += scrollX;
283            if (scrollY) elem.scrollTop  += scrollY;                    
284        }
285        
286        // clean up if there's nothing left to do
287        if (!left && !top) {
288            que = [];
289        }
290        
291        if (que.length) { 
292            requestFrame(step, elem, (delay / options.frameRate + 1)); 
293        } else { 
294            pending = false;
vendor: 4,164 bytes, lines 295-458
295        }
296    };
297    
298    // start a new queue of actions
299    requestFrame(step, elem, 0);
300    pending = true;
301}
302
303
304/***********************************************
305 * EVENTS
306 ***********************************************/
307
308/**
309 * Mouse wheel handler.
310 * @param {Object} event
311 */
312function wheel(event) {
313
314    if (!initDone) {
315        init();
316    }
317    
318    var target = event.target;
319    var overflowing = overflowingAncestor(target);
320    
321    // use default if there's no overflowing
322    // element or default action is prevented    
323    if (!overflowing || event.defaultPrevented ||
324        isNodeName(activeElement, "embed") ||
325       (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) {
326        return true;
327    }
328
329    var deltaX = event.wheelDeltaX || 0;
330    var deltaY = event.wheelDeltaY || 0;
331    
332    // use wheelDelta if deltaX/Y is not available
333    if (!deltaX && !deltaY) {
334        deltaY = event.wheelDelta || 0;
335    }
336
337    // check if it's a touchpad scroll that should be ignored
338    if (!options.touchpadSupport && isTouchpad(deltaY)) {
339        return true;
340    }
341
342    // scale by step size
343    // delta is 120 most of the time
344    // synaptics seems to send 1 sometimes
345    if (Math.abs(deltaX) > 1.2) {
346        deltaX *= options.stepSize / 120;
347    }
348    if (Math.abs(deltaY) > 1.2) {
349        deltaY *= options.stepSize / 120;
350    }
351    
352    scrollArray(overflowing, -deltaX, -deltaY);
353    event.preventDefault();
354}
355
356/**
357 * Keydown event handler.
358 * @param {Object} event
359 */
360function keydown(event) {
361
362    var target   = event.target;
363    var modifier = event.ctrlKey || event.altKey || event.metaKey || 
364                  (event.shiftKey && event.keyCode !== key.spacebar);
365    
366    // do nothing if user is editing text
367    // or using a modifier key (except shift)
368    // or in a dropdown
369    if ( /input|textarea|select|embed/i.test(target.nodeName) ||
370         target.isContentEditable || 
371         event.defaultPrevented   ||
372         modifier ) {
373      return true;
374    }
375    // spacebar should trigger button press
376    if (isNodeName(target, "button") &&
377        event.keyCode === key.spacebar) {
378      return true;
379    }
380    
381    var shift, x = 0, y = 0;
382    var elem = overflowingAncestor(activeElement);
383    var clientHeight = elem.clientHeight;
384
385    if (elem == document.body) {
386        clientHeight = window.innerHeight;
387    }
388
389    switch (event.keyCode) {
390        case key.up:
391            y = -options.arrowScroll;
392            break;
393        case key.down:
394            y = options.arrowScroll;
395            break;         
396        case key.spacebar: // (+ shift)
397            shift = event.shiftKey ? 1 : -1;
398            y = -shift * clientHeight * 0.9;
399            break;
400        case key.pageup:
401            y = -clientHeight * 0.9;
402            break;
403        case key.pagedown:
404            y = clientHeight * 0.9;
405            break;
406        case key.home:
407            y = -elem.scrollTop;
408            break;
409        case key.end:
410            var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
411            y = (damt > 0) ? damt+10 : 0;
412            break;
413        case key.left:
414            x = -options.arrowScroll;
415            break;
416        case key.right:
417            x = options.arrowScroll;
418            break;            
419        default:
420            return true; // a key we don't care about
421    }
422
423    scrollArray(elem, x, y);
424    event.preventDefault();
425}
426
427/**
428 * Mousedown event only for updating activeElement
429 */
430function mousedown(event) {
431    activeElement = event.target;
432}
433
434
435/***********************************************
436 * OVERFLOW
437 ***********************************************/
438 
439var cache = {}; // cleared out every once in while
440setInterval(function () { cache = {}; }, 10 * 1000);
441
442var uniqueID = (function () {
443    var i = 0;
444    return function (el) {
445        return el.uniqueID || (el.uniqueID = i++);
446    };
447})();
448
449function setCache(elems, overflowing) {
450    for (var i = elems.length; i--;)
451        cache[uniqueID(elems[i])] = overflowing;
452    return overflowing;
453}
454
455function overflowingAncestor(el) {
456    var elems = [];
457    var rootScrollHeight = root.scrollHeight;
458    do {
459        var cached = cache[uniqueID(el)];
460        if (cached) {
461            return setCache(elems, cached);
462        }
463        elems.push(el);
464        if (rootScrollHeight === el.scrollHeight) {
465            if (!isFrame || root.clientHeight + 10 < rootScrollHeight) {
466                return setCache(elems, document.body); // scrolling root in WebKit
467            }
468        } else if (el.clientHeight + 10 < el.scrollHeight) {
469            overflow = getComputedStyle(el, "").getPropertyValue("overflow-y");
470            if (overflow === "scroll" || overflow === "auto") {
471                return setCache(elems, el);
472            }
473        }
474    } while (el = el.parentNode);
475}
476
477
478/***********************************************
479 * HELPERS
480 ***********************************************/
481
482function addEvent(type, fn, bubble) {
483    window.addEventListener(type, fn, (bubble||false));
484}
485
486function removeEvent(type, fn, bubble) {
487    window.removeEventListener(type, fn, (bubble||false));  
488}
489
490function isNodeName(el, tag) {
491    return (el.nodeName||"").toLowerCase() === tag.toLowerCase();
492}
493
494function directionCheck(x, y) {
495    x = (x > 0) ? 1 : -1;
496    y = (y > 0) ? 1 : -1;
497    if (direction.x !== x || direction.y !== y) {
498        direction.x = x;
499        direction.y = y;
500        que = [];
501        lastScroll = 0;
502    }
503}
504
505var deltaBufferTimer;
506
507function isTouchpad(deltaY) {
508    if (!deltaY) return;
509    deltaY = Math.abs(deltaY)
510    deltaBuffer.push(deltaY);
511    deltaBuffer.shift();
512    clearTimeout(deltaBufferTimer);
513    deltaBufferTimer = setTimeout(function () {
514        chrome.storage.local.set({ deltaBuffer: deltaBuffer });
515    }, 1000);
516    var allEquals    = (deltaBuffer[0] == deltaBuffer[1] && 
517                        deltaBuffer[1] == deltaBuffer[2]);
518    var allDivisable = (isDivisible(deltaBuffer[0], 120) &&
519                        isDivisible(deltaBuffer[1], 120) &&
520                        isDivisible(deltaBuffer[2], 120));
521    return !(allEquals || allDivisable);
522} 
523
524function isDivisible(n, divisor) {
525    return (Math.floor(n / divisor) == n / divisor);
526}
527
528if(typeof(chrome) !== 'undefined' && typeof(chrome.storage) !== 'undefined') {
529chrome.storage.local.get('deltaBuffer', function (stored) {
530    if (stored.deltaBuffer) {
531        deltaBuffer = stored.deltaBuffer;
532    }
533});
534}
535
536var requestFrame = (function () {
537      return  window.requestAnimationFrame       || 
538              window.webkitRequestAnimationFrame || 
539              function (callback, element, delay) {
540                  window.setTimeout(callback, delay || (1000/60));
541              };
542})();
543
544var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;  
545
546
547/***********************************************
548 * PULSE
549 ***********************************************/
550 
551/**
552 * Viscous fluid with a pulse for part and decay for the rest.
553 * - Applies a fixed force over an interval (a damped acceleration), and
554 * - Lets the exponential bleed away the velocity over a longer interval
555 * - Michael Herf, http://stereopsis.com/stopping/
556 */
557function pulse_(x) {
558    var val, start, expx;
559    // test
560    x = x * options.pulseScale;
561    if (x < 1) { // acceleartion
562        val = x - (1 - Math.exp(-x));
563    } else {     // tail
564        // the previous animation ended here:
565        start = Math.exp(-1);
566        // simple viscous drag
567        x -= 1;
568        expx = 1 - Math.exp(-x);
569        val = start + (expx * (1 - start));
570    }
571    return val * options.pulseNormalize;
572}
573
574function pulse(x) {
575    if (x >= 1) return 1;
576    if (x <= 0) return 0;
577
578    if (options.pulseNormalize == 1) {
579        options.pulseNormalize /= pulse_(1);
580    }
581    return pulse_(x);
582}
583
584addEvent("mousedown", mousedown);
585addEvent("mousewheel", wheel);
586addEvent("load", init);

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.