PageSourceSearch

https://fabulous.com/local/fabulous/js/libs/rangeSlider.js

js fabulous.com collected 2026-09-29 17:20:31 UTC 30,137 bytes, 855 lines download raw bytes

1(function (factory) {
2    'use strict';
3
4    if (typeof define === 'function' && define.amd) {
5        // AMD. Register as an anonymous module.
6        define([], factory);
7    }
8    else if (typeof module === 'object' && module !== null && module.exports) {
9        // CommonJS
10        module.exports = factory();
11    } else {
12        // Browser globals
13        /* jshint ignore:start */
14        window['rangeSlider'] = factory();
15        /* jshint ignore:end */
16    }
17}(function () {
18        'use strict';
19
20        var EVENT_LISTENER_LIST = 'eventListenerList';
21        var newLineAndTabRegexp = new RegExp('/[\\n\\t]/', 'g');
22        var MAX_SET_BY_DEFAULT = 100;
23        var HANDLE_RESIZE_DELAY = 300;
24        var HANDLE_RESIZE_DEBOUNCE = 50;
25
26        /**
27         * Range feature detection
28         * @return {Boolean}
29         */
30        function supportsRange() {
31            var input = document.createElement('input');
32            input.setAttribute('type', 'range');
33            return input.type !== 'text';
34        }
35
36        var pluginName = 'rangeSlider',
37            pluginIdentifier = 0,
38            inputrange = supportsRange(),
39            defaults = {
40                polyfill: true,
41                rangeClass: 'rangeSlider',
42                disabledClass: 'rangeSlider--disabled',
43                fillClass: 'rangeSlider__fill',
44                bufferClass: 'rangeSlider__buffer',
45                handleClass: 'rangeSlider__handle',
46                startEvent: ['mousedown', 'touchstart', 'pointerdown'],
47                moveEvent: ['mousemove', 'touchmove', 'pointermove'],
48                endEvent: ['mouseup', 'touchend', 'pointerup'],
49                min: null,
50                max: null,
51                step: null,
52                value: null,
53                buffer: null,
54                borderRadius: 10
55            };
56
57        /**
58         * Delays a function for the given number of milliseconds, and then calls
59         * it with the arguments supplied.
60         *
61         * @param  {Function} fn   [description]
62         * @param  {Number}   wait [description]
63         * @return {Function}
64         */
65        function delay(fn, wait) {
66            var args = Array.prototype.slice.call(arguments, 2);
67            return setTimeout(function () {
68                return fn.apply(null, args);
69            }, wait);
70        }
71
72        /**
73         * Returns a debounced function that will make sure the given
74         * function is not triggered too much.
75         *
76         * @param  {Function} fn Function to debounce.
77         * @param  {Number}   debounceDuration OPTIONAL. The amount of time in milliseconds for which we will debounce the function. (defaults to 100ms)
78         * @return {Function}
79         */
80        function debounce(fn, debounceDuration) {
81            debounceDuration = debounceDuration || 100;
82            return function () {
83                if (!fn.debouncing) {
84                    var args = Array.prototype.slice.apply(arguments);
85                    fn.lastReturnVal = fn.apply(window, args);
86                    fn.debouncing = true;
87                }
88                clearTimeout(fn.debounceTimeout);
89                fn.debounceTimeout = setTimeout(function () {
90                    fn.debouncing = false;
91                }, debounceDuration);
92                return fn.lastReturnVal;
93            };
94        }
95
96        /**
97         * Check if a `element` is visible in the DOM
98         *
99         * @param  {Element}  element
100         * @return {Boolean}
101         */
102        function isHidden(element) {
103            return !!(element.offsetWidth === 0 || element.offsetHeight === 0 || element.open === false);
104
105        }
106
107        /**
108         * Get hidden parentNodes of an `element`
109         *
110         * @param  {Element} element
111         * @return {[type]}
112         */
113        function getHiddenParentNodes(element) {
114            var parents = [],
115                node = element.parentNode;
116
117            while (isHidden(node)) {
118                parents.push(node);
119                node = node.parentNode;
120            }
121            return parents;
122        }
123
124        /**
125         * Returns dimensions for an element even if it is not visible in the DOM.
126         *
127         * @param  {Element} element
128         * @param  {string}  key     (e.g. offsetWidth …)
129         * @return {Number}
130         */
131        function getDimension(element, key) {
132            var hiddenParentNodes = getHiddenParentNodes(element),
133                hiddenParentNodesLength = hiddenParentNodes.length,
134                displayProperty = [],
135                dimension = element[key];
136
137            // Used for native `<details>` elements
138            function toggleOpenProperty(element) {
139                if (typeof element.open !== 'undefined') {
140                    element.open = (element.open) ? false : true;
141                }
142            }
143
144            if (hiddenParentNodesLength) {
145                for (var i = 0; i < hiddenParentNodesLength; i++) {
146                    // Cache the display property to restore it later.
147                    displayProperty[i] = hiddenParentNodes[i].style.display;
148
149                    hiddenParentNodes[i].style.display = 'block';
150                    hiddenParentNodes[i].style.height = '0';
151                    hiddenParentNodes[i].style.overflow = 'hidden';
152                    hiddenParentNodes[i].style.visibility = 'hidden';
153                    toggleOpenProperty(hiddenParentNodes[i]);
154                }
155
156                dimension = element[key];
157
158                for (var j = 0; j < hiddenParentNodesLength; j++) {
159                    toggleOpenProperty(hiddenParentNodes[j]);
160                    hiddenParentNodes[j].style.display = displayProperty[j];
161                    hiddenParentNodes[j].style.height = '';
162                    hiddenParentNodes[j].style.overflow = '';
163                    hiddenParentNodes[j].style.visibility = '';
164                }
165            }
166            return dimension;
167        }
168
169        function isString(obj) {
170            return obj === '' + obj;
171        }
172
173        function isNumberLike(obj) {
174            return (obj !== null && obj !== undefined && (isString(obj) && isFinite(parseFloat(obj)) || (isFinite(obj))));
175        }
176
177        function getFirsNumberLike() {
178            if (!arguments.length) {
179                return null;
180            }
181            for (var i = 0, len = arguments.length; i < len; i++) {
182                if (isNumberLike(arguments[i])) {
183                    return arguments[i];
184                }
185            }
186        }
187
188        function isObject(obj) {
189            return Object.prototype.toString.call(obj) === '[object Object]';
190        }
191
192        function simpleExtend(defaultOpt, options) {
193            var opt = {}, key;
194            for (key in defaultOpt) {
195                opt[key] = defaultOpt[key];
196            }
197            for (key in options) {
198                opt[key] = options[key];
199            }
200
201            return opt;
202        }
203
204        /**
205         *
206         * @param {HTMLElement} el
207         * @param {Object} cssObj
208         * @returns {*}
209         */
210        function setCss(el, cssObj) {
211            for (var key in cssObj) {
212                el.style[key] = cssObj[key];
213            }
214            return el.style;
215        }
216
217        /**
218         *
219         * @param {HTMLElement} elem
220         * @param {string} className
221         */
222        function addClass(elem, className) {
223            if (!hasClass(elem, className)) {
224                elem.className += ' ' + className;
225            }
226        }
227
228        /**
229         *
230         * @param {HTMLElement} elem
231         * @param {string} className
232         */
233        function removeClass(elem, className) {
234            var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, ' ') + ' ';
235            if (hasClass(elem, className)) {
236                while (newClass.indexOf(' ' + className + ' ') >= 0) {
237                    newClass = newClass.replace(' ' + className + ' ', ' ');
238                }
239                elem.className = newClass.replace(/^\s+|\s+$/g, '');
240            }
241        }
242
243
244        /**
245         *
246         * @param {HTMLElement} el
247         * @callback callback
248         * @param {boolean} andForElement - apply callback for el
249         * @returns {HTMLElement}
250         */
251        function forEachAncestors(el, callback, andForElement) {
252            if (andForElement) {
253                callback(el);
254            }
255
256            while (el.parentNode && !callback(el)) {
257                el = el.parentNode;
258            }
259
260            return el;
261        }
262
263        /**
264         *
265         * @param {HTMLElement} el
266         * @param {string} name event name
267         * @param {Object} data
268         */
269        function triggerEvent(el, name, data) {
270            if (!isString(name)) {
271                throw new TypeError('event name must be String');
272            }
273            if (!(el instanceof HTMLElement)) {
274                throw new TypeError('element must be HTMLElement');
275            }
276            name = name.trim();
277            var event = document.createEvent('CustomEvent');
278            event.initCustomEvent(name, false, false, data);
279            el.dispatchEvent(event);
280        }
281
282        /**
283         *
284         * @param {HTMLElement} elem
285         * @param {string} className
286         */
287        function hasClass(elem, className) {
288            return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
289        }
290
291        /**
292         * @param {Object} referenceNode after this
293         * @param {Object} newNode insert this
294         */
295        function insertAfter(referenceNode, newNode) {
296            referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
297        }
298
299        /**
300         * Add event listeners and push them to el[EVENT_LISTENER_LIST]
301         * @param {HTMLElement} el DOM element
302         * @param {Array} events
303         * @callback listener
304         */
305        function addEventListeners(el, events, listener) {
306            events.forEach(function (eventName) {
307                if (!el[EVENT_LISTENER_LIST]) {
308                    el[EVENT_LISTENER_LIST] = {};
309                }
310                if (!el[EVENT_LISTENER_LIST][eventName]) {
311                    el[EVENT_LISTENER_LIST][eventName] = [];
312                }
313
314                el.addEventListener(
315                    eventName,
316                    listener,
317                    false
318                );
319                if (el[EVENT_LISTENER_LIST][eventName].indexOf(listener) < 0) {
320                    el[EVENT_LISTENER_LIST][eventName].push(listener);
321                }
322            });
323        }
324
325        /**
326         * Remove event listeners and remove them from el[EVENT_LISTENER_LIST]
327         * @param {HTMLElement} el DOM element
328         * @param {Array} events
329         * @callback listener
330         */
331        function removeEventListeners(el, events, listener) {
332            events.forEach(function (eventName) {
333                el.removeEventListener(
334                    eventName,
335                    listener,
336                    false
337                );
338
339                var index;
340                if (el[EVENT_LISTENER_LIST] && el[EVENT_LISTENER_LIST][eventName] &&
341                    (index = el[EVENT_LISTENER_LIST][eventName].indexOf(listener)) > -1
342                ) {
343                    el[EVENT_LISTENER_LIST][eventName].splice(index, 1);
344                }
345            });
346        }
347
348        /**
349         * Remove ALL event listeners which exists in el[EVENT_LISTENER_LIST]
350         * @param {HTMLElement} el DOM element
351         */
352        function removeAllListenersFromEl(el) {
353            if (!el[EVENT_LISTENER_LIST]) {
354                return;
355            }
356            /* jshint ignore:start */
357            var instance = this;
358
359            /**
360             *
361             * @callback listener
362             * @this {Object} event name
363             */
364            function rm(listener) {
365                if (listener === instance._startEventListener) {
366                    this.el.removeEventListener(this.eventName, listener, false);
367                }
368            }
369
370            for (var eventName in el[EVENT_LISTENER_LIST]) {
371                el[EVENT_LISTENER_LIST][eventName].forEach(rm, {eventName: eventName, el: el});
372            }
373
374            el[EVENT_LISTENER_LIST] = {};
375            /* jshint ignore:end */
376        }
377
378
379        /**
380         * Plugin
381         * @param {HTMLElement} element
382         * @param {this} options
383         */
384        function Plugin(element, options) {
385            var minSetByDefault, maxSetByDefault, stepSetByDefault;
386            this.element = element;
387            this.options = simpleExtend(defaults, options);
388            this.polyfill = this.options.polyfill;
389            this.onInit = this.options.onInit;
390            this.onSlide = this.options.onSlide;
391            this.onSlideStart = this.options.onSlideStart;
392            this.onSlideEnd = this.options.onSlideEnd;
393            this.onSlideEventsCount = -1;
394            this.isInteractsNow = false;
395            this.needTriggerEvents = false;
396
397            // Plugin should only be used as a polyfill
398            if (!this.polyfill) {
399                // Input range support?
400                if (inputrange) {
401                    return false;
402                }
403            }
404
405            this.options.buffer = this.options.buffer || parseFloat(this.element.getAttribute('data-buffer'));
406
407            this.identifier = 'js-' + pluginName + '-' + (pluginIdentifier++);
408            this.min = getFirsNumberLike(this.options.min, parseFloat(this.element.getAttribute('min')), (minSetByDefault = 0));
409            this.max = getFirsNumberLike(this.options.max, parseFloat(this.element.getAttribute('max')), (maxSetByDefault = MAX_SET_BY_DEFAULT));
410            this.value = getFirsNumberLike(this.options.value, this.element.value,
411                parseFloat(this.element.value || this.min + (this.max - this.min) / 2));
412            this.step = getFirsNumberLike(this.options.step,
413                parseFloat(this.element.getAttribute('step')) || (stepSetByDefault = 1));
414            this.percent = null;
415            this._updatePercentFromValue();
416
417            this.toFixed = this._toFixed(this.step);
418
419
420            this.fill = document.createElement('div');
421            this.fill.className = this.options.fillClass;
422
423            this.handle = document.createElement('div');
424            this.handle.className = this.options.handleClass;
425
426            this.handle_icon1 = document.createElement('i');
427            this.handle_icon2 = document.createElement('i');
428            this.handle_icon1.className = 'icon-layout';
429            this.handle_icon2.className = 'icon-layout';
430
431            this.range = document.createElement('div');
432            this.range.className = this.options.rangeClass;
433            this.range.id = this.identifier;
434            this.range.appendChild(this.handle);
435            this.range.appendChild(this.fill);
436			this.handle.appendChild(this.handle_icon1);
437			this.handle.appendChild(this.handle_icon2);
438
439            if (this.options.bufferClass) {
440                this.buffer = document.createElement('div');
441                this.buffer.className = this.options.bufferClass;
442                this.range.appendChild(this.buffer);
443            }
444
445            if (isNumberLike(this.options.value)) {
446                this._setValue(this.options.value, true);
447                this.element.value = this.options.value;
448            }
449
450            if (isNumberLike(this.options.buffer)) {
451                this.element.setAttribute('data-buffer', this.options.buffer);
452            }
453
454            if (isNumberLike(this.options.min) || minSetByDefault) {
455                this.element.setAttribute('min', '' + this.min);
456            }
457
458            if (isNumberLike(this.options.max) || maxSetByDefault) {
459                this.element.setAttribute('max', '' + this.max);
460            }
461
462            if (isNumberLike(this.options.step) || stepSetByDefault) {
463                this.element.setAttribute('step', '' + this.step);
464            }
465
466            insertAfter(this.element, this.range);
467
468            // visually hide the input
469            setCss(this.element, {
470                'position': 'absolute',
471                'width': '1px',
472                'height': '1px',
473                'overflow': 'hidden',
474                'opacity': '0'
475            });
476
477            // Store context
478            this._handleDown = this._handleDown.bind(this);
479            this._handleMove = this._handleMove.bind(this);
480            this._handleEnd = this._handleEnd.bind(this);
481            this._startEventListener = this._startEventListener.bind(this);
482            this._changeEventListener = this._changeEventListener.bind(this);
483            this._handleResize = this._handleResize.bind(this);
484
485            this._init();
486
487            //// Attach Events
488            window.addEventListener('resize', this._handleResize, false);
489
490            addEventListeners(document, this.options.startEvent, this._startEventListener);
491
492            // Listen to programmatic value changes
493            this.element.addEventListener('change', this._changeEventListener, false);
494        }
495
496        Plugin.prototype.constructor = Plugin;
497
498        Plugin.prototype._toFixed = function (step) {
499            return (step + '').replace('.', '').length - 1;
500        };
501
502
503        Plugin.prototype._init = function () {
504            if (this.onInit && typeof this.onInit === 'function') {
505                this.onInit();
506            }
507            this._update();
508        };
509
510        Plugin.prototype._updatePercentFromValue = function () {
511            this.percent = (this.value - this.min) / (this.max - this.min);
512        };
513
514        /**
515         * This method check if this.identifier exists in ev.target's ancestors
516         * @param ev
517         * @param data
518         */
519        Plugin.prototype._startEventListener = function (ev, data) {
520            var _this = this;
521            var el = ev.target;
522            var isEventOnSlider = false;
523            forEachAncestors(el, function (el) {
524                return (isEventOnSlider = el.id === _this.identifier && !hasClass(el, _this.options.disabledClass));
525            }, true);
526            if (isEventOnSlider) {
527                this._handleDown(ev, data);
528            }
529        };
530
531        Plugin.prototype._changeEventListener = function (ev, data) {
532            if (data && data.origin === this.identifier) {
533                return;
534            }
535
536            var value = ev.target.value,
537                pos = this._getPositionFromValue(value);
538            this._setPosition(pos);
539        };
540
541        Plugin.prototype._update = function () {
542            this.handleWidth = getDimension(this.handle, 'offsetWidth');
543            this.rangeWidth = getDimension(this.range, 'offsetWidth');
544            this.maxHandleX = this.rangeWidth - this.handleWidth;
545            this.grabX = this.handleWidth / 2;
546            this.position = this._getPositionFromValue(this.value);
547
548            // Consider disabled state
549            if (this.element.disabled) {
550                addClass(this.range, this.options.disabledClass);
551            } else {
552                removeClass(this.range, this.options.disabledClass);
553            }
554
555            this._setPosition(this.position);
556            if (this.options.bufferClass && this.options.buffer) {
557                this._setBufferPosition(this.options.buffer);
558            }
559            this._updatePercentFromValue();
560            triggerEvent(this.element, 'change', {origin: this.identifier});
561        };
562
563
564        Plugin.prototype._handleResize = function () {
565            var _this = this;
566            return debounce(function () {
567                // Simulate resizeEnd event.
568                delay(function () {
569                    _this._update();
570                }, HANDLE_RESIZE_DELAY);
571            }, HANDLE_RESIZE_DEBOUNCE)();
572        };
573
574        Plugin.prototype._handleDown = function (e) {
575            this.isInteractsNow = true;
576            e.preventDefault();
577            addEventListeners(document, this.options.moveEvent, this._handleMove);
578            addEventListeners(document, this.options.endEvent, this._handleEnd);
579
580            // If we click on the handle don't set the new position
581            if ((' ' + e.target.className + ' ').replace(newLineAndTabRegexp, ' ').indexOf(this.options.handleClass) > -1) {
582                return;
583            }
584
585            var posX = this._getRelativePosition(e),
586                rangeX = this.range.getBoundingClientRect().left,
587                handleX = this._getPositionFromNode(this.handle) - rangeX;
588
589            this._setPosition(posX - this.grabX);
590
591            if (posX >
591= handleX && posX < handleX + this.handleWidth) {
592                this.grabX = posX - handleX;
593            }
594            this._updatePercentFromValue();
595        };
596
597        Plugin.prototype._handleMove = function (e) {
598            this.isInteractsNow = true;
599            e.preventDefault();
600            var posX = this._getRelativePosition(e);
601            this._setPosition(posX - this.grabX);
602            //this.isInteractsNow = false;
603        };
604
605        Plugin.prototype._handleEnd = function (e) {
606            e.preventDefault();
607            removeEventListeners(document, this.options.moveEvent, this._handleMove);
608            removeEventListeners(document, this.options.endEvent, this._handleEnd);
609
610            // Ok we're done fire the change event
611            triggerEvent(this.element, 'change', {origin: this.identifier});
612
613            if (this.isInteractsNow || this.needTriggerEvents) {
614                if (this.onSlideEnd && typeof this.onSlideEnd === 'function') {
615                    this.onSlideEnd(this.value, this.percent, this.position);
616                }
617            }
618            this.onSlideEventsCount = 0;
619            this.isInteractsNow = false;
620        };
621
622        Plugin.prototype._cap = function (pos, min, max) {
623            if (pos < min) {
624                return min;
625            }
626            if (pos > max) {
627                return max;
628            }
629            return pos;
630        };
631
632        Plugin.prototype._setPosition = function (pos) {
633            var value, left;
634
635            // Snapping steps
636            value = this._getValueFromPosition(this._cap(pos, 0, this.maxHandleX));
637            left = this._getPositionFromValue(value);
638
639            // Update ui
640            this.fill.style.width = (left + this.grabX) + 'px';
641            this.handle.style.left = left + 'px';
642            this._setValue(value);
643
644            // Update globals
645            this.position = left;
646            this.value = value;
647            this._updatePercentFromValue();
648
649            if (this.isInteractsNow || this.needTriggerEventss) {
650                if (this.onSlideStart && typeof this.onSlideStart === 'function' && this.onSlideEventsCount === 0) {
651                    this.onSlideStart(this.value, this.percent, this.position);
652                }
653
654                if (this.onSlide && typeof this.onSlide === 'function') {
655                    this.onSlide(this.value, this.percent, this.position);
656                }
657            }
658
659            this.onSlideEventsCount++;
660        };
661
662        Plugin.prototype._setBufferPosition = function (pos) {
663            var isPercent = true,
664                bufferWidth,
665                paddingWidth,
666                bufferWidthWithPadding;
667            if (isFinite(pos)) {
668                pos = parseFloat(pos);
669            } else if (isString(pos)) {
670                if (pos.indexOf('px') > 0) {
671                    isPercent = false;
672                }
673                pos = parseFloat(pos);
674            } else {
675                console.warn('New position must be XXpx or XX%');
676                return;
677            }
678
679            if (isNaN(pos)) {
680                console.warn('New position is NaN');
681                return;
682            }
683            if (!this.options.bufferClass) {
684                console.warn('You disabled buffer, it\'s className is empty');
685                return;
686            }
687            bufferWidth = isPercent ? pos : (pos / this.rangeWidth * 100);
688            if (bufferWidth < 0) {
689                bufferWidth = 0;
690            }
691            if (bufferWidth > 100) {
692                bufferWidth = 100;
693            }
694            this.options.buffer = bufferWidth;
695
696            paddingWidth = this.options.borderRadius / this.rangeWidth * 100;
697            bufferWidthWithPadding = bufferWidth - paddingWidth;
698            if (bufferWidthWithPadding < 0) {
699                bufferWidthWithPadding = 0;
700            }
701
702            this.buffer.style.width = bufferWidthWithPadding + '%';
703            this.buffer.style.left = paddingWidth * 0.5 + '%';
704            this.element.setAttribute('data-buffer', bufferWidth);
705        };
706
707        // Returns element position relative to the parent
708        Plugin.prototype._getPositionFromNode = function (node) {
709            var i = 0;
710            while (node !== null) {
711                i += node.offsetLeft;
712                node = node.offsetParent;
713            }
714            return i;
715        };
716
717        /**
718         *
719         * @param {(MouseEvent|TouchEvent)}e
720         * @returns {number}
721         */
722        Plugin.prototype._getRelativePosition = function (e) {
723            // Get the offset left relative to the viewport
724            var rangeX = this.range.getBoundingClientRect().left,
725                pageX = 0;
726
727            if (typeof e.pageX !== 'undefined') {
728                pageX = (e.touches && e.touches.length) ? e.touches[0].pageX : e.pageX;
729            }
730            else if (typeof e.originalEvent !== 'undefined') {
731                if (typeof e.originalEvent.clientX !== 'undefined') {
732                    pageX = e.originalEvent.clientX;
733                }
734                else if (e.originalEvent.touches && e.originalEvent.touches[0] && typeof e.originalEvent.touches[0].clientX !== 'undefined') {
735                    pageX = e.originalEvent.touches[0].clientX;
736                }
737            }
738            else if (e.touches && e.touches[0] && typeof e.touches[0].clientX !== 'undefined') {
739                pageX = e.touches[0].clientX;
740            }
741            else if (e.currentPoint && typeof e.currentPoint.x !== 'undefined') {
742                pageX = e.currentPoint.x;
743            }
744
745            return pageX - rangeX;
746        };
747
748        Plugin.prototype._getPositionFromValue = function (value) {
749            var percentage, pos;
750            percentage = (value - this.min) / (this.max - this.min);
751            pos = percentage * this.maxHandleX;
752            return pos;
753        };
754
755        Plugin.prototype._getValueFromPosition = function (pos) {
756            var percentage, value;
757            percentage = ((pos) / (this.maxHandleX || 1));
758            value = this.step * Math.round(percentage * (this.max - this.min) / this.step) + this.min;
759            return Number((value).toFixed(this.toFixed));
760        };
761
762        Plugin.prototype._setValue = function (value, force) {
763            if (value === this.value && !force) {
764                return;
765            }
766
767            // Set the new value and fire the `input` event
768            this.element.value = value;
769            this.value = value;
770            triggerEvent(this.element, 'input', {origin: this.identifier});
771        };
772
773
774        /**
775         *
776         * @param {Object} obj like {min : Number, max : Number, value : Number, step : Number, buffer : [String|Number]}
777         * @param {Boolean} triggerEvents
778         * @returns {Plugin}
779         */
780        Plugin.prototype.update = function (obj, triggerEvents) {
781            if (triggerEvents) {
782                this.needTriggerEvents = true;
783            }
784            if (isObject(obj)) {
785                if (isNumberLike(obj.min)) {
786                    this.element.setAttribute('min', '' + obj.min);
787                    this.min = obj.min;
788                }
789
790                if (isNumberLike(obj.max)) {
791                    this.element.setAttribute('max', '' + obj.max);
792                    this.max = obj.max;
793                }
794
795                if (isNumberLike(obj.step)) {
796                    this.element.setAttribute('step', '' + obj.step);
797                    this.step = obj.step;
798                    this.toFixed = this._toFixed(obj.step);
799                }
800
801                if (isNumberLike(obj.buffer)) {
802                    this._setBufferPosition(obj.buffer);
803                }
804
805                if (isNumberLike(obj.value)) {
806                    this._setValue(obj.value);
807                }
808            }
809            this._update();
810            this.onSlideEventsCount = 0;
811            this.needTriggerEvents = false;
812            return this;
813        };
814
815        Plugin.prototype.destroy = function () {
816            removeAllListenersFromEl.call(this, document);
817            window.removeEventListener('resize', this._handleResize, false);
818            this.element.removeEventListener('change', this._changeEventListener, false);
819
820            this.element.style.cssText = '';
821            delete this.element[pluginName];
822
823            // Remove the generated markup
824            if (this.range) {
825                this.range.parentNode.removeChild(this.range);
826            }
827        };
828
829        // A really lightweight plugin wrapper around the constructor,
830        // preventing against multiple instantiations
831
832        Plugin.create = function (el, options) {
833            function createInstance(el) {
834                var data = el[pluginName];
835
836                // Create a new instance.
837                if (!data) {
838                    data = new Plugin(el, options);
839                    el[pluginName] = data;
840                }
841            }
842
843            if (el.length) {
844                Array.prototype.slice.call(el).forEach(function (el) {
845                    createInstance(el);
846                });
847            } else {
848                createInstance(el);
849            }
850        };
851
852        return Plugin;
853
854    }
855));

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.