PageSourceSearch

https://www.zoga-beauty.com/templates/NOVA/js/app/plugins/navscrollbar.js

js zoga-beauty.com collected 2026-10-04 13:25:30 UTC 6,610 bytes, 215 lines download raw bytes

1
2import { debounce, random } from './../helpers.js'
3
4const NAME					= 'navscrollbar'
5const VERSION				= '1.0.0'
6const UNIQID				= random()
7const DATA_KEY				= `jtl.${NAME}`
8const EVENT_KEY				= `.${DATA_KEY}#${UNIQID}`
9const JQUERY_NO_CONFLICT	= $.fn[NAME]
10
11const Default = {
12    classes: {
13        scrollbarInner		: 'nav-scrollbar-inner',
14        scrollbarItems		: 'nav-scrollbar-item',
15        scrollbarArrow		: 'nav-scrollbar-arrow'
16    },
17    templates: {
18        arrowLeft: `
19			<div class="left">
20				<span class="fas fa-chevron-left"></span>
21			</div>
22		`,
23        arrowRight: `
24			<div class="right">
25				<span class="fas fa-chevron-right"></span>
26			</div>
27		`
28    },
29    showArrowOffset: 0,
30    clickTransitionDuration: 500,
31    clickScrollLength: 70, // percentage
32    enableDrag: false,
33}
34
35const Event = {
36    CLICK			: `click${EVENT_KEY}`,
37    MOUSEDOWN		: `mousedown${EVENT_KEY}`,
38    MOUSEMOVE		: `mousemove${EVENT_KEY}`,
39    MOUSEUP			: `mouseup${EVENT_KEY}`,
40    RESIZE			: `resize${EVENT_KEY}`,
41    SCROLL			: `scroll${EVENT_KEY}`
42}
43
44let $document	= $(document)
45let $window		= $(window)
46
47
48export default class NavScrollbar {
49    constructor(element, config = {}) {
50        let self     = this;
51        this.element = $(element)
52        this.config  = $.extend(true, {}, Default, config)
53
54        this._isDragging   = false
55        this._start        = 0
56        this._startClientX = 0
57        this._distance     = 0
58        this._itemWidth    = 0
59
60        this.$scrollBarInner = this.element.find(`.${this.config.classes.scrollbarInner}`)
61        this.$scrollBarItems = this.element.find(`.${this.config.classes.scrollbarItems}`)
62
63        this.$scrollBarArrowLeft	= $(this.config.templates.arrowLeft).addClass(`${this.config.classes.scrollbarArrow} disabled`)
64        this.$scrollBarArrowRight	= $(this.config.templates.arrowRight).addClass(`${this.config.classes.scrollbarArrow} disabled`)
65
66        this.element.prepend(this.$scrollBarArrowLeft)
67        this.element.append(this.$scrollBarArrowRight)
68
69        setTimeout(function () {
70            self.update();
71            self._bindEvents();
72        }, 100);
73    }
74
75    /* Public */
76
77    scrollToPrev() {
78        this.$scrollBarInner.animate({
79            scrollLeft: this.$scrollBarInner.scrollLeft() - (this.$scrollBarInner.width() / 100 * this.config.clickScrollLength - this.$scrollBarArrowLeft.width())
80        }, { duration: this.config.clickTransitionDuration })
81    }
82
83    scrollToNext() {
84        this.$scrollBarInner.animate({
85            scrollLeft: this.$scrollBarInner.scrollLeft() + (this.$scrollBarInner.width() / 100 * this.config.clickScrollLength - this.$scrollBarArrowLeft.width())
86        }, { duration: this.config.clickTransitionDuration })
87    }
88
89    update() {
90        this._updateItemWidth()
91
92        let widthDifference = Math.round(this._itemWidth - this.$scrollBarInner.width())
93        let scrolledFromLeft = this.$scrollBarInner.scrollLeft()
94
95        if(widthDifference <= 0) {
96            this.$scrollBarArrowLeft.addClass('disabled')
97            this.$scrollBarArrowRight.addClass('disabled')
98            return
99        }
100
101        this.$scrollBarArrowLeft[scrolledFromLeft > this.config.showArrowOffset ? 'removeClass' : 'addClass']('disabled')
102        this.$scrollBarArrowRight[scrolledFromLeft + this.config.showArrowOffset < (widthDifference - 8) ? 'removeClass' : 'addClass']('disabled')
103    }
104
105    destroy() {
106        this.element.removeData(DATA_KEY)
107        this.element = null
108        this.$scrollBarInner.off(EVENT_KEY)
109        this.$scrollBarArrowLeft.off(EVENT_KEY).remove()
110        this.$scrollBarArrowRight.off(EVENT_KEY).remove()
111        $document.off(EVENT_KEY)
112        $window.off(EVENT_KEY)
113    }
114
115    /* Private */
116
117    _dragStart(e) {
118        e.preventDefault()
119
120        this._startClientX = e.clientX
121
122        this._isDragging = true
123        this._start = e.clientX + this.$scrollBarInner.scrollLeft()
124    }
125
126    _dragMove(e) {
127        if(!this._isDragging)
128            return
129
130        this.$scrollBarInner.scrollLeft(this._start - e.clientX)
131    }
132
133    _dragEnd(e) {
134        if(!this._isDragging)
135            return
136
137        this._isDragging = false
138
139        if($.contains(this.element.get(0), e.target)) {
140            e.target.removeEventListener('click', this._preventDragClick)
141
142            if(this._startClientX - e.clientX != 0)
143                e.target.addEventListener('click', this._preventDragClick)
144        }
145
146        this.$scrollBarInner.scrollLeft(this._start - e.clientX)
147    }
148
149    _preventDragClick(e) {
150        e.preventDefault()
151        e.stopImmediatePropagation()
152    }
153
154    _updateItemWidth() {
155        this._itemWidth = 0
156
157        $.each(this.$scrollBarItems, (i, element) => {
158            this._itemWidth += Math.round(element.offsetWidth)
159        })
160    }
161
162    _bindEvents() {
163        this.$scrollBarInner.on(Event.SCROLL, debounce(() => this.update()))
164
165        this.$scrollBarArrowLeft.on(Event.CLICK, () => this.scrollToPrev())
166        this.$scrollBarArrowRight.on(Event.CLICK, () => this.scrollToNext())
167
168        if(this.config.enableDrag) {
169            this.$scrollBarInner.on(Event.MOUSEDOWN, (e) => this._dragStart(e))
170            $document.on(Event.MOUSEMOVE, (e) => this._dragMove(e))
171            $document.on(Event.MOUSEUP, (e) => this._dragEnd(e))
172        }
173
174        $window.on(Event.RESIZE, debounce(() => this.update()))
175    }
176
177    /* Static */
178
179    static _jQueryInterface(config = {}) {
180        let _arguments = arguments || null
181
182        return this.each(function() {
183            const $element	= $(this)
184            let data		= $element.data(DATA_KEY)
185
186            if(!data) {
187                if(typeof config === 'object') {
188                    data = new NavScrollbar(this, config)
189                    $element.data(DATA_KEY, data)
190                } else {
191                    $.error(`cannot call methods on ${NAME} prior to initialization`)
192                }
193            } else {
194                if(typeof data[config] === 'function') {
195                    data[config].apply(data, Array.prototype.slice.call(_arguments, 1))
196                } else {
197                    $.error(`method ${config} does not exist.`)
198                }
199            }
200        })
201    }
202}
203
204/**
205 * ------------------------------------------------------------------------
206 * jQuery
207 * ------------------------------------------------------------------------
208 */
209
210$.fn[NAME]             = NavScrollbar._jQueryInterface
211$.fn[NAME].Constructor = NavScrollbar
212$.fn[NAME].noConflict  = () => {
213    $.fn[NAME] = JQUERY_NO_CONFLICT
214    return NavScrollbar._jQueryInterface
215}

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.