PageSourceSearch

https://manarat.ac.bd/wp-content/themes/manarat/assets/js/fakescroll.js

js manarat.ac.bd collected 2026-10-02 08:46:12 UTC 8,077 bytes, 203 lines download raw bytes

1/**
2 * By Yair Even Or (C)
3 * https://github.com/yairEO/fakescroll
4 */
5;(function(){
6    raf = window.requestAnimationFrame || function(cb) { return window.setTimeout(cb, 1000 / 60) };
7
8    function FakeScroll(targetElm, settings){
9        if( !targetElm ) return;
10
11        this.settings = Object.assign({}, this.defaults, settings || {});
12        this.callback = settings.callback ? settings.callback : null;
13
14        this.state = {};
15        this.listeners = {};
16
17        this.DOM = this.build(targetElm);
18        this.events.binding.call(this, this.DOM);
19
20        // run "moveBar" once
21        setTimeout(this.moveBar.bind(this));
22    }
23
24    FakeScroll.prototype = {
25        defaults : {
26            classname : "",
27            track     : false // "smooth" will enable smooth scroll
28        },
29
30        /**
31         * Build the DOM needed
32         */
33        build( targetElm ){
34            var DOM = {};
35                scopeHTML = `<div class="fakeScroll__wrap">
36                                <div class="fakeScroll__content"></div>
37                             </div>
38                             <div class='fakeScroll__track ${this.settings.classname}'>
39                                <div class="fakeScroll__bar"></div>
40                             </div>`,
41                fragment = document.createDocumentFragment();
42
43            // move all the children of the target element into a fragment
44            while( targetElm.childNodes.length ){
45                fragment.appendChild(targetElm.childNodes[0]);
46            }
47
48            targetElm.insertAdjacentHTML('afterbegin', scopeHTML);
49
50            DOM.scope = targetElm;
51            DOM.scrollWrap = targetElm.firstElementChild;
52            DOM.scrollContent = DOM.scrollWrap.firstElementChild;
53            DOM.scrollContent.appendChild(fragment);
54
55            DOM.track = DOM.scrollWrap.nextElementSibling;
56            DOM.bar = DOM.track.firstElementChild;
57
58            DOM.scope.classList.add("fakeScroll__scope");
59
60            return DOM;
61        },
62
63        destroy(){
64            this.events.off.call(this, window, 'resize', 'onScrollResize');
65        },
66
67        events : {
68            on(elm, eName, cbName){
69                // to be able tp unbind the events, callback refferece must be saved somewhere
70                eName.split(' ').forEach(e => {
71                    if( !(cbName in this.events.callbacks) ) console.warn(cbName, " doesn't exist in Callbacks: ", this.events.callbacks);
72
73                    this.listeners[e] = this.events.callbacks[cbName].bind(this);
74                    elm.addEventListener(e, this.listeners[e])
75                });
76
77                return this.events;
78            },
79
80            off(elm, eName, cbName){
81                eName.split(' ').forEach(e => elm.removeEventListener(e, this.listeners[e]))
82                return this.events;
83            },
84
85            binding(DOM){
86                this.events.on.call(this, DOM.scrollContent, 'scroll', 'onScrollResize')
87                           .on.call(this, DOM.scope, 'mouseenter', 'onScrollResize')
88                           .on.call(this, DOM.bar, 'mousedown', 'onBarMouseDown')
89                           .on.call(this, window, 'resize', 'onScrollResize')
90
91                if( this.settings.track )
92                    this.events.on.call(this, DOM.track, 'click', 'onTrackClick')
93            },
94
95            /**
96             * events only binded when Bar element gets a "mousedown" event
97             * @param  {[type]} onOff [description]
98             * @return {[type]}       [description]
99             */
100            drag(onOff){
101                this.events[onOff].call(this, document, 'mousemove', 'onDrag')
102                           [onOff].call(this, document, 'mouseup', 'onStopDrag')
103            },
104
105            callbacks : {
106                onScrollResize(e){
107                    this.moveBar.call(this);
108
109                    // debounce - get track bounds
110                    clearTimeout(this.listeners.timeout__resize);
111                    this.listeners.timeout__resize = setTimeout(this.getTrackBounds.bind(this), 200)
112                },
113
114                onDrag(e){
115                    var delta = e.pageY - this.state.lastPageY;
116
117                    raf(() => {
118                        var sTop = document.documentElement.scrollTop,
119                            isDragWithinTrackBounds = e.pageY >= (this.state.trackBounds.top + sTop) && e.pageY <= (this.state.trackBounds.bottom + sTop);
120
121                        if( isDragWithinTrackBounds )
122                            this.DOM.scrollContent.scrollTop = this.state.drag + delta / this.state.scrollRatio;
123                        // update variables when mouse position is outside the Track bounds
124                        else{
125                            this.state.drag = this.DOM.scrollContent.scrollTop;
126                            this.state.lastPageY = e.pageY;
127                        }
128                    });
129                },
130
131                onStopDrag(e){
132                    [this.DOM.bar, document.body].map(el => el.classList.remove('fakeScroll--grabbed'))
133                    this.events.drag.call(this, 'off');
134                    setTimeout(()=>{ this.state.drag = false })
135                },
136
137                onBarMouseDown(e){
138                    this.state.drag = this.DOM.scrollContent.scrollTop;
139                    this.state.lastPageY = e.pageY;
140
141                    [this.DOM.bar, document.body].map(el => el.classList.add('fakeScroll--grabbed'))
142                    this.events.drag.call(this, 'on');
143                },
144
145                onTrackClick(e){
146                    if( this.state.drag ) return;
147
148                    var perc         = (e.clientY - this.state.trackBounds.top) / (this.state.trackBounds.height - this.state.trackBounds.topPad - this.state.trackBounds.bottomPad),
149                        scrollHeight = this.DOM.scrollContent.scrollHeight,
150                        ownHeight    = this.DOM.scrollWrap.clientHeight,
151                        newScrollTop = perc * (scrollHeight - ownHeight);
152
153                    if( this.settings.track == 'smooth' ){
154                        this.DOM.scrollContent.style.scrollBehavior = 'smooth';
155                        setTimeout(()=>{ this.DOM.scrollContent.style.scrollBehavior = 'unset' }, 500)
156                    }
157
158                    this.DOM.scrollContent.scrollTop = newScrollTop;
159                }
160            }
161        },
162
163        getTrackBounds(){
164            var bounds = this.DOM.track.getBoundingClientRect(),
165                styles = window.getComputedStyle(this.DOM.track, null);
166
167            bounds.topPad = parseInt(styles.paddingTop, 10);
168            bounds.bottomPad = parseInt(styles.paddingBottom, 10);
169
170            this.state.trackBounds = bounds;
171            return bounds;
172        },
173
174        moveBar(){
175            // if( !this.DOM.scrollContent ) return false;
176
177            var _scrollContent = this.DOM.scrollContent,
178                scrollHeight = _scrollContent.scrollHeight,
179                ownHeight   = this.DOM.scrollWrap.clientHeight;
180
181            this.state.scrollRatio = this.DOM.track.clientHeight / scrollHeight;
182
183            // update fake scrollbar location on the Y axis using requestAnimationFrame
184            raf(()=> {
185                var height = (ownHeight / scrollHeight) * 100,
186                    top = (_scrollContent.scrollTop / scrollHeight ) * 100;
187
188                this.DOM.bar.style.cssText = `height  : ${height}%;
189                                              top     : ${top}%;
190                                              display : ${scrollHeight <= ownHeight ? 'none' : ''}`;
191            });
192        }
193    }
194
195    /**
196     * Extend the DOM with "fakeScroll" method. The chances of the same name already be taken are slim to none,
197     * But you should now; it's your code you're putting this into.
198     */
199    Element.prototype.fakeScroll = function( settings ){
200        this._fakeScroll = this._fakeScroll || new FakeScroll(this, settings || {});
201        return this._fakeScroll;
202    }
203})();

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.