PageSourceSearch

https://just.hosting/assets/common/libs/slider/bootstrap-slider.js?v=1784722085

js just.hosting collected 2026-10-07 01:21:23 UTC 64,298 bytes, 1,874 lines download raw bytes

vendor: 8,013 bytes, lines 1-250
1/*! =======================================================
2                      VERSION  10.0.0              
3========================================================= */
4"use strict";
5
6var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
7
8/*! =========================================================
9 * bootstrap-slider.js
10 *
11 * Maintainers:
12 *		Kyle Kemp
13 *			- Twitter: @seiyria
14 *			- Github:  seiyria
15 *		Rohit Kalkur
16 *			- Twitter: @Rovolutionary
17 *			- Github:  rovolution
18 *
19 * =========================================================
20 *
21 * bootstrap-slider is released under the MIT License
22 * Copyright (c) 2017 Kyle Kemp, Rohit Kalkur, and contributors
23 *
24 * Permission is hereby granted, free of charge, to any person
25 * obtaining a copy of this software and associated documentation
26 * files (the "Software"), to deal in the Software without
27 * restriction, including without limitation the rights to use,
28 * copy, modify, merge, publish, distribute, sublicense, and/or sell
29 * copies of the Software, and to permit persons to whom the
30 * Software is furnished to do so, subject to the following
31 * conditions:
32 *
33 * The above copyright notice and this permission notice shall be
34 * included in all copies or substantial portions of the Software.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
37 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
38 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
39 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
40 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
41 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
42 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
43 * OTHER DEALINGS IN THE SOFTWARE.
44 *
45 * ========================================================= */
46
47/**
48 * Bridget makes jQuery widgets
49 * v1.0.1
50 * MIT license
51 */
52var windowIsDefined = (typeof window === "undefined" ? "undefined" : _typeof(window)) === "object";
53
54(function (factory) {
55	if (typeof define === "function" && define.amd) {
56		define(["jquery"], factory);
57	} else if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === "object" && module.exports) {
58		var jQuery;
59		try {
60			jQuery = require("jquery");
61		} catch (err) {
62			jQuery = null;
63		}
64		module.exports = factory(jQuery);
65	} else if (window) {
66		window.Slider = factory(window.jQuery);
67	}
68})(function ($) {
69	// Constants
70	var NAMESPACE_MAIN = 'slider';
71	var NAMESPACE_ALTERNATE = 'bootstrapSlider';
72
73	// Polyfill console methods
74	if (windowIsDefined && !window.console) {
75		window.console = {};
76	}
77	if (windowIsDefined && !window.console.log) {
78		window.console.log = function () {};
79	}
80	if (windowIsDefined && !window.console.warn) {
81		window.console.warn = function () {};
82	}
83
84	// Reference to Slider constructor
85	var Slider;
86
87	(function ($) {
88
89		'use strict';
90
91		// -------------------------- utils -------------------------- //
92
93		var slice = Array.prototype.slice;
94
95		function noop() {}
96
97		// -------------------------- definition -------------------------- //
98
99		function defineBridget($) {
100
101			// bail if no jQuery
102			if (!$) {
103				return;
104			}
105
106			// -------------------------- addOptionMethod -------------------------- //
107
108			/**
109    * adds option method -> $().plugin('option', {...})
110    * @param {Function} PluginClass - constructor class
111    */
112			function addOptionMethod(PluginClass) {
113				// don't overwrite original option method
114				if (PluginClass.prototype.option) {
115					return;
116				}
117
118				// option setter
119				PluginClass.prototype.option = function (opts) {
120					// bail out if not an object
121					if (!$.isPlainObject(opts)) {
122						return;
123					}
124					this.options = $.extend(true, this.options, opts);
125				};
126			}
127
128			// -------------------------- plugin bridge -------------------------- //
129
130			// helper function for logging errors
131			// $.error breaks jQuery chaining
132			var logError = typeof console === 'undefined' ? noop : function (message) {
133				console.error(message);
134			};
135
136			/**
137    * jQuery plugin bridge, access methods like $elem.plugin('method')
138    * @param {String} namespace - plugin name
139    * @param {Function} PluginClass - constructor class
140    */
141			function bridge(namespace, PluginClass) {
142				// add to jQuery fn namespace
143				$.fn[namespace] = function (options) {
144					if (typeof options === 'string') {
145						// call plugin method when first argument is a string
146						// get arguments for method
147						var args = slice.call(arguments, 1);
148
149						for (var i = 0, len = this.length; i < len; i++) {
150							var elem = this[i];
151							var instance = $.data(elem, namespace);
152							if (!instance) {
153								logError("cannot call methods on " + namespace + " prior to initialization; " + "attempted to call '" + options + "'");
154								continue;
155							}
156							if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
157								logError("no such method '" + options + "' for " + namespace + " instance");
158								continue;
159							}
160
161							// trigger method with arguments
162							var returnValue = instance[options].apply(instance, args);
163
164							// break look and return first value if provided
165							if (returnValue !== undefined && returnValue !== instance) {
166								return returnValue;
167							}
168						}
169						// return this if no return value
170						return this;
171					} else {
172						var objects = this.map(function () {
173							var instance = $.data(this, namespace);
174							if (instance) {
175								// apply options & init
176								instance.option(options);
177								instance._init();
178							} else {
179								// initialize new instance
180								instance = new PluginClass(this, options);
181								$.data(this, namespace, instance);
182							}
183							return $(this);
184						});
185
186						if (!objects || objects.length > 1) {
187							return objects;
188						} else {
189							return objects[0];
190						}
191					}
192				};
193			}
194
195			// -------------------------- bridget -------------------------- //
196
197			/**
198    * converts a Prototypical class into a proper jQuery plugin
199    *   the class must have a ._init method
200    * @param {String} namespace - plugin name, used in $().pluginName
201    * @param {Function} PluginClass - constructor class
202    */
203			$.bridget = function (namespace, PluginClass) {
204				addOptionMethod(PluginClass);
205				bridge(namespace, PluginClass);
206			};
207
208			return $.bridget;
209		}
210
211		// get jquery from browser global
212		defineBridget($);
213	})($);
214
215	/*************************************************
216 			BOOTSTRAP-SLIDER SOURCE CODE
217 	**************************************************/
218
219	(function ($) {
220
221		var ErrorMsgs = {
222			formatInvalidInputErrorMsg: function formatInvalidInputErrorMsg(input) {
223				return "Invalid input value '" + input + "' passed in";
224			},
225			callingContextNotSliderInstance: "Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method"
226		};
227
228		var SliderScale = {
229			linear: {
230				toValue: function toValue(percentage) {
231					var rawValue = percentage / 100 * (this.options.max - this.options.min);
232					var shouldAdjustWithBase = true;
233					if (this.options.ticks_positions.length > 0) {
234						var minv,
235						    maxv,
236						    minp,
237						    maxp = 0;
238						for (var i = 1; i < this.options.ticks_positions.length; i++) {
239							if (percentage <= this.options.ticks_positions[i]) {
240								minv = this.options.ticks[i - 1];
241								minp = this.options.ticks_positions[i - 1];
242								maxv = this.options.ticks[i];
243								maxp = this.options.ticks_positions[i];
244
245								break;
246							}
247						}
248						var partialPercentage = (percentage - minp) / (maxp - minp);
249						rawValue = minv + partialPercentage * (maxv - minv);
250						shouldAdjustWithBase = false;
251					}
252
253					var adjustment = shouldAdjustWithBase ? this.options.min : 0;
254					var value = adjustment + Math.round(rawValue / this.options.step) * this.options.step;
255					if (value < this.options.min) {
256						return this.options.min;
257					} else if (value > this.options.max) {
258						return this.options.max;
259					} else {
260						return value;
261					}
262				},
263				toPercentage: function toPercentage(value) {
264					if (this.options.max === this.options.min) {
265						return 0;
266					}
267
268					if (this.options.ticks_positions.length > 0) {
269						var minv,
270						    maxv,
271						    minp,
272						    maxp = 0;
273						for (var i = 0; i < this.options.ticks.length; i++) {
274							if (value <= this.options.ticks[i]) {
275								minv = i > 0 ? this.options.ticks[i - 1] : 0;
276								minp = i > 0 ? this.options.ticks_positions[i - 1] : 0;
277								maxv = this.options.ticks[i];
278								maxp = this.options.ticks_positions[i];
279
280								break;
281							}
282						}
283						if (i > 0) {
284							var partialPercentage = (value - minv) / (maxv - minv);
285							return minp + partialPercentage * (maxp - minp);
286						}
287					}
288
289					return 100 * (value - this.options.min) / (this.options.max - this.options.min);
290				}
291			},
292
293			logarithmic: {
294				/* Based on http://stackoverflow.com/questions/846221/logarithmic-slider */
295				toValue: function toValue(percentage) {
296					var min = this.options.min === 0 ? 0 : Math.log(this.options.min);
297					var max = Math.log(this.options.max);
298					var value = Math.exp(min + (max - min) * percentage / 100);
299					if (Math.round(value) === this.options.max) {
300						return this.options.max;
301					}
302					value = this.options.min + Math.round((value - this.options.min) / this.options.step) * this.options.step;
303					/* Rounding to the nearest step could exceed the min or
304      * max, so clip to those values. */
305					if (value < this.options.min) {
306						return this.options.min;
307					} else if (value > this.options.max) {
308						return this.options.max;
309					} else {
310						return value;
311					}
312				},
313				toPercentage: function toPercentage(value) {
314					if (this.options.max === this.options.min) {
315						return 0;
316					} else {
317						var max = Math.log(this.options.max);
318						var min = this.options.min === 0 ? 0 : Math.log(this.options.min);
319						var v = value === 0 ? 0 : Math.log(value);
320						return 100 * (v - min) / (max - min);
321					}
322				}
323			}
324		};
325
326		/*************************************************
327  						CONSTRUCTOR
328  	**************************************************/
329		Slider = function Slider(element, options) {
330			createNewSlider.call(this, element, options);
331			return this;
332		};
333
334		function createNewSlider(element, options) {
335
336			/*
337   	The internal state object is used to store data about the current 'state' of slider.
338   	This includes values such as the `value`, `enabled`, etc...
339   */
340			this._state = {
341				value: null,
342				enabled: null,
343				offset: null,
344				size: null,
345				percentage: null,
346				inDrag: false,
347				over: false
348			};
349
350			// The objects used to store the reference to the tick methods if ticks_tooltip is on
351			this.ticksCallbackMap = {};
352			this.handleCallbackMap = {};
353
354			if (typeof element === "string") {
355				this.element = document.querySelector(element);
356			} else if (element instanceof HTMLElement) {
357				this.element = element;
358			}
359
360			/*************************************************
361   					Process Options
362   	**************************************************/
363			options = options ? options : {};
364			var optionTypes = Object.keys(this.defaultOptions);
365
366			for (var i = 0; i < optionTypes.length; i++) {
367				var optName = optionTypes[i];
368
369				// First check if an option was passed in via the constructor
370				var val = options[optName];
371				// If no data attrib, then check data atrributes
372				val = typeof val !== 'undefined' ? val : getDataAttrib(this.element, optName);
373				// Finally, if nothing was specified, use the defaults
374				val = val !== null ? val : this.defaultOptions[optName];
375
376				// Set all options on the instance of the Slider
377				if (!this.options) {
378					this.options = {};
379				}
380				this.options[optName] = val;
381			}
382
383			// Check options.rtl
384			if (this.options.rtl === 'auto') {
385				this.options.rtl = window.getComputedStyle(this.element).direction === 'rtl';
386			}
387
388			/*
389   	Validate `tooltip_position` against 'orientation`
390   	- if `tooltip_position` is incompatible with orientation, swith it to a default compatible with specified `orientation`
391   		-- default for "vertical" -> "right", "left" if rtl
392   		-- default for "horizontal" -> "top"
393   */
394			if (this.options.orientation === "vertical" && (this.options.tooltip_position === "top" || this.options.tooltip_position === "bottom")) {
395				if (this.options.rtl) {
396					this.options.tooltip_position = "left";
397				} else {
398					this.options.tooltip_position = "right";
399				}
400			} else if (this.options.orientation === "horizontal" && (this.options.tooltip_position === "left" || this.options.tooltip_position === "right")) {
401
402				this.options.tooltip_position = "top";
403			}
404
405			function getDataAttrib(element, optName) {
vendor: 5,182 bytes, lines 406-535
406				var dataName = "data-slider-" + optName.replace(/_/g, '-');
407				var dataValString = element.getAttribute(dataName);
408
409				try {
410					return JSON.parse(dataValString);
411				} catch (err) {
412					return dataValString;
413				}
414			}
415
416			/*************************************************
417   					Create Markup
418   	**************************************************/
419
420			var origWidth = this.element.style.width;
421			var updateSlider = false;
422			var parent = this.element.parentNode;
423			var sliderTrackSelection;
424			var sliderTrackLow, sliderTrackHigh;
425			var sliderMinHandle;
426			var sliderMaxHandle;
427
428			if (this.sliderElem) {
429				updateSlider = true;
430			} else {
431				/* Create elements needed for slider */
432				this.sliderElem = document.createElement("div");
433				this.sliderElem.className = "slider";
434
435				/* Create slider track elements */
436				var sliderTrack = document.createElement("div");
437				sliderTrack.className = "slider-track";
438
439				sliderTrackLow = document.createElement("div");
440				sliderTrackLow.className = "slider-track-low";
441
442				sliderTrackSelection = document.createElement("div");
443				sliderTrackSelection.className = "slider-selection";
444
445				sliderTrackHigh = document.createElement("div");
446				sliderTrackHigh.className = "slider-track-high";
447
448				sliderMinHandle = document.createElement("div");
449				sliderMinHandle.className = "slider-handle min-slider-handle";
450				sliderMinHandle.setAttribute('role', 'slider');
451				sliderMinHandle.setAttribute('aria-valuemin', this.options.min);
452				sliderMinHandle.setAttribute('aria-valuemax', this.options.max);
453
454				sliderMaxHandle = document.createElement("div");
455				sliderMaxHandle.className = "slider-handle max-slider-handle";
456				sliderMaxHandle.setAttribute('role', 'slider');
457				sliderMaxHandle.setAttribute('aria-valuemin', this.options.min);
458				sliderMaxHandle.setAttribute('aria-valuemax', this.options.max);
459
460				sliderTrack.appendChild(sliderTrackLow);
461				sliderTrack.appendChild(sliderTrackSelection);
462				sliderTrack.appendChild(sliderTrackHigh);
463
464				/* Create highlight range elements */
465				this.rangeHighlightElements = [];
466				var rangeHighlightsOpts = this.options.rangeHighlights;
467				if (Array.isArray(rangeHighlightsOpts) && rangeHighlightsOpts.length > 0) {
468					for (var j = 0; j < rangeHighlightsOpts.length; j++) {
469						var rangeHighlightElement = document.createElement("div");
470						var customClassString = rangeHighlightsOpts[j].class || "";
471						rangeHighlightElement.className = "slider-rangeHighlight slider-selection " + customClassString;
472						this.rangeHighlightElements.push(rangeHighlightElement);
473						sliderTrack.appendChild(rangeHighlightElement);
474					}
475				}
476
477				/* Add aria-labelledby to handle's */
478				var isLabelledbyArray = Array.isArray(this.options.labelledby);
479				if (isLabelledbyArray && this.options.labelledby[0]) {
480					sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby[0]);
481				}
482				if (isLabelledbyArray && this.options.labelledby[1]) {
483					sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby[1]);
484				}
485				if (!isLabelledbyArray && this.options.labelledby) {
486					sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby);
487					sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby);
488				}
489
490				/* Create ticks */
491				this.ticks = [];
492				if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {
493					this.ticksContainer = document.createElement('div');
494					this.ticksContainer.className = 'slider-tick-container';
495
496					for (i = 0; i < this.options.ticks.length; i++) {
497						var tick = document.createElement('div');
498						tick.className = 'slider-tick';
499						if (this.options.ticks_tooltip) {
500							var tickListenerReference = this._addTickListener();
501							var enterCallback = tickListenerReference.addMouseEnter(this, tick, i);
502							var leaveCallback = tickListenerReference.addMouseLeave(this, tick);
503
504							this.ticksCallbackMap[i] = {
505								mouseEnter: enterCallback,
506								mouseLeave: leaveCallback
507							};
508						}
509						this.ticks.push(tick);
510						this.ticksContainer.appendChild(tick);
511					}
512
513					sliderTrackSelection.className += " tick-slider-selection";
514				}
515
516				this.tickLabels = [];
517				if (Array.isArray(this.options.ticks_labels) && this.options.ticks_labels.length > 0) {
518					this.tickLabelContainer = document.createElement('div');
519					this.tickLabelContainer.className = 'slider-tick-label-container';
520
521					for (i = 0; i < this.options.ticks_labels.length; i++) {
522						var label = document.createElement('div');
523						var noTickPositionsSpecified = this.options.ticks_positions.length === 0;
524						var tickLabelsIndex = this.options.reversed && noTickPositionsSpecified ? this.options.ticks_labels.length - (i + 1) : i;
525						label.className = 'slider-tick-label';
526						label.innerHTML = this.options.ticks_labels[tickLabelsIndex];
527
528						this.tickLabels.push(label);
529						this.tickLabelContainer.appendChild(label);
530					}
531				}
532
533				var createAndAppendTooltipSubElements = function createAndAppendTooltipSubElements(tooltipElem) {
534					var arrow = document.createElement("div");
535					arrow.className = "tooltip-
vendor: 3,775 bytes, lines 535-637
535arrow";
536
537					var inner = document.createElement("div");
538					inner.className = "tooltip-inner";
539
540					tooltipElem.appendChild(arrow);
541					tooltipElem.appendChild(inner);
542				};
543
544				/* Create tooltip elements */
545				var sliderTooltip = document.createElement("div");
546				sliderTooltip.className = "tooltip tooltip-main";
547				sliderTooltip.setAttribute('role', 'presentation');
548				createAndAppendTooltipSubElements(sliderTooltip);
549
550				var sliderTooltipMin = document.createElement("div");
551				sliderTooltipMin.className = "tooltip tooltip-min";
552				sliderTooltipMin.setAttribute('role', 'presentation');
553				createAndAppendTooltipSubElements(sliderTooltipMin);
554
555				var sliderTooltipMax = document.createElement("div");
556				sliderTooltipMax.className = "tooltip tooltip-max";
557				sliderTooltipMax.setAttribute('role', 'presentation');
558				createAndAppendTooltipSubElements(sliderTooltipMax);
559
560				/* Append components to sliderElem */
561				this.sliderElem.appendChild(sliderTrack);
562				this.sliderElem.appendChild(sliderTooltip);
563				this.sliderElem.appendChild(sliderTooltipMin);
564				this.sliderElem.appendChild(sliderTooltipMax);
565
566				if (this.tickLabelContainer) {
567					this.sliderElem.appendChild(this.tickLabelContainer);
568				}
569				if (this.ticksContainer) {
570					this.sliderElem.appendChild(this.ticksContainer);
571				}
572
573				this.sliderElem.appendChild(sliderMinHandle);
574				this.sliderElem.appendChild(sliderMaxHandle);
575
576				/* Append slider element to parent container, right before the original <input> element */
577				parent.insertBefore(this.sliderElem, this.element);
578
579				/* Hide original <input> element */
580				this.element.style.display = "none";
581			}
582			/* If JQuery exists, cache JQ references */
583			if ($) {
584				this.$element = $(this.element);
585				this.$sliderElem = $(this.sliderElem);
586			}
587
588			/*************************************************
589   						Setup
590   	**************************************************/
591			this.eventToCallbackMap = {};
592			this.sliderElem.id = this.options.id;
593
594			this.touchCapable = 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch;
595
596			this.touchX = 0;
597			this.touchY = 0;
598
599			this.tooltip = this.sliderElem.querySelector('.tooltip-main');
600			this.tooltipInner = this.tooltip.querySelector('.tooltip-inner');
601
602			this.tooltip_min = this.sliderElem.querySelector('.tooltip-min');
603			this.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner');
604
605			this.tooltip_max = this.sliderElem.querySelector('.tooltip-max');
606			this.tooltipInner_max = this.tooltip_max.querySelector('.tooltip-inner');
607
608			if (SliderScale[this.options.scale]) {
609				this.options.scale = SliderScale[this.options.scale];
610			}
611
612			if (updateSlider === true) {
613				// Reset classes
614				this._removeClass(this.sliderElem, 'slider-horizontal');
615				this._removeClass(this.sliderElem, 'slider-vertical');
616				this._removeClass(this.sliderElem, 'slider-rtl');
617				this._removeClass(this.tooltip, 'hide');
618				this._removeClass(this.tooltip_min, 'hide');
619				this._removeClass(this.tooltip_max, 'hide');
620
621				// Undo existing inline styles for track
622				["left", "right", "top", "width", "height"].forEach(function (prop) {
623					this._removeProperty(this.trackLow, prop);
624					this._removeProperty(this.trackSelection, prop);
625					this._removeProperty(this.trackHigh, prop);
626				}, this);
627
628				// Undo inline styles on handles
629				[this.handle1, this.handle2].forEach(function (handle) {
630					this._removeProperty(handle, 'left');
631					this._removeProperty(handle, 'right');
632					this._removeProperty(handle, 'top');
633				}, this);
634
635				// Undo inline styles and classes on tooltips
636				[this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function (tooltip) {
637					this._removeProperty(tooltip, '
vendor: 26,524 bytes, lines 637-1373
637left');
638					this._removeProperty(tooltip, 'right');
639					this._removeProperty(tooltip, 'top');
640
641					this._removeClass(tooltip, 'right');
642					this._removeClass(tooltip, 'left');
643					this._removeClass(tooltip, 'top');
644				}, this);
645			}
646
647			if (this.options.orientation === 'vertical') {
648				this._addClass(this.sliderElem, 'slider-vertical');
649				this.stylePos = 'top';
650				this.mousePos = 'pageY';
651				this.sizePos = 'offsetHeight';
652			} else {
653				this._addClass(this.sliderElem, 'slider-horizontal');
654				this.sliderElem.style.width = origWidth;
655				this.options.orientation = 'horizontal';
656				if (this.options.rtl) {
657					this.stylePos = 'right';
658				} else {
659					this.stylePos = 'left';
660				}
661				this.mousePos = 'pageX';
662				this.sizePos = 'offsetWidth';
663			}
664			// specific rtl class
665			if (this.options.rtl) {
666				this._addClass(this.sliderElem, 'slider-rtl');
667			}
668			this._setTooltipPosition();
669			/* In case ticks are specified, overwrite the min and max bounds */
670			if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {
671				this.options.max = Math.max.apply(Math, this.options.ticks);
672				this.options.min = Math.min.apply(Math, this.options.ticks);
673			}
674
675			if (Array.isArray(this.options.value)) {
676				this.options.range = true;
677				this._state.value = this.options.value;
678			} else if (this.options.range) {
679				// User wants a range, but value is not an array
680				this._state.value = [this.options.value, this.options.max];
681			} else {
682				this._state.value = this.options.value;
683			}
684
685			this.trackLow = sliderTrackLow || this.trackLow;
686			this.trackSelection = sliderTrackSelection || this.trackSelection;
687			this.trackHigh = sliderTrackHigh || this.trackHigh;
688
689			if (this.options.selection === 'none') {
690				this._addClass(this.trackLow, 'hide');
691				this._addClass(this.trackSelection, 'hide');
692				this._addClass(this.trackHigh, 'hide');
693			} else if (this.options.selection === 'after' || this.options.selection === 'before') {
694				this._removeClass(this.trackLow, 'hide');
695				this._removeClass(this.trackSelection, 'hide');
696				this._removeClass(this.trackHigh, 'hide');
697			}
698
699			this.handle1 = sliderMinHandle || this.handle1;
700			this.handle2 = sliderMaxHandle || this.handle2;
701
702			if (updateSlider === true) {
703				// Reset classes
704				this._removeClass(this.handle1, 'round triangle');
705				this._removeClass(this.handle2, 'round triangle hide');
706
707				for (i = 0; i < this.ticks.length; i++) {
708					this._removeClass(this.ticks[i], 'round triangle hide');
709				}
710			}
711
712			var availableHandleModifiers = ['round', 'triangle', 'custom'];
713			var isValidHandleType = availableHandleModifiers.indexOf(this.options.handle) !== -1;
714			if (isValidHandleType) {
715				this._addClass(this.handle1, this.options.handle);
716				this._addClass(this.handle2, this.options.handle);
717
718				for (i = 0; i < this.ticks.length; i++) {
719					this._addClass(this.ticks[i], this.options.handle);
720				}
721			}
722
723			this._state.offset = this._offset(this.sliderElem);
724			this._state.size = this.sliderElem[this.sizePos];
725			this.setValue(this._state.value);
726
727			/******************************************
728   				Bind Event Listeners
729   	******************************************/
730
731			// Bind keyboard handlers
732			this.handle1Keydown = this._keydown.bind(this, 0);
733			this.handle1.addEventListener("keydown", this.handle1Keydown, false);
734
735			this.handle2Keydown = this._keydown.bind(this, 1);
736			this.handle2.addEventListener("keydown", this.handle2Keydown, false);
737
738			this.mousedown = this._mousedown.bind(this);
739			this.touchstart = this._touchstart.bind(this);
740			this.touchmove = this._touchmove.bind(this);
741
742			if (this.touchCapable) {
743				// Test for passive event support
744				var supportsPassive = false;
745				try {
746					var opts = Object.defineProperty({}, 'passive', {
747						get: function get() {
748							supportsPassive = true;
749						}
750					});
751					window.addEventListener("test", null, opts);
752				} catch (e) {}
753				// Use our detect's results. passive applied if supported, capture will be false either way.
754				var eventOptions = supportsPassive ? { passive: true } : false;
755				// Bind touch handlers
756				this.sliderElem.addEventListener("touchstart", this.touchstart, eventOptions);
757				this.sliderElem.addEventListener("touchmove", this.touchmove, eventOptions);
758			}
759			this.sliderElem.addEventListener("mousedown", this.mousedown, false);
760
761			// Bind window handlers
762			this.resize = this._resize.bind(this);
763			window.addEventListener("resize", this.resize, false);
764
765			// Bind tooltip-related handlers
766			if (this.options.tooltip === 'hide') {
767				this._addClass(this.tooltip, 'hide');
768				this._addClass(this.tooltip_min, 'hide');
769				this._addClass(this.tooltip_max, 'hide');
770			} else if (this.options.tooltip === 'always') {
771				this._showTooltip();
772				this._alwaysShowTooltip = true;
773			} else {
774				this.showTooltip = this._showTooltip.bind(this);
775				this.hideTooltip = this._hideTooltip.bind(this);
776
777				if (this.options.ticks_tooltip) {
778					var callbackHandle = this._addTickListener();
779					//create handle1 listeners and store references in map
780					var mouseEnter = callbackHandle.addMouseEnter(this, this.handle1);
781					var mouseLeave = callbackHandle.addMouseLeave(this, this.handle1);
782					this.handleCallbackMap.handle1 = {
783						mouseEnter: mouseEnter,
784						mouseLeave: mouseLeave
785					};
786					//create handle2 listeners and store references in map
787					mouseEnter = callbackHandle.addMouseEnter(this, this.handle2);
788					mouseLeave = callbackHandle.addMouseLeave(this, this.handle2);
789					this.handleCallbackMap.handle2 = {
790						mouseEnter: mouseEnter,
791						mouseLeave: mouseLeave
792					};
793				} else {
794					this.sliderElem.addEventListener("mouseenter", this.showTooltip, false);
795					this.sliderElem.addEventListener("mouseleave", this.hideTooltip, false);
796				}
797
798				this.handle1.addEventListener("focus", this.showTooltip, false);
799				this.handle1.addEventListener("blur", this.hideTooltip, false);
800
801				this.handle2.addEventListener("focus", this.showTooltip, false);
802				this.handle2.addEventListener("blur", this.hideTooltip, false);
803			}
804
805			if (this.options.enabled) {
806				this.enable();
807			} else {
808				this.disable();
809			}
810		}
811
812		/*************************************************
813  				INSTANCE PROPERTIES/METHODS
814  	- Any methods bound to the prototype are considered
815  part of the plugin's `public` interface
816  	**************************************************/
817		Slider.prototype = {
818			_init: function _init() {}, // NOTE: Must exist to support bridget
819
820			constructor: Slider,
821
822			defaultOptions: {
823				id: "",
824				min: 0,
825				max: 10,
826				step: 1,
827				precision: 0,
828				orientation: 'horizontal',
829				value: 5,
830				range: false,
831				selection: 'before',
832				tooltip: 'show',
833				tooltip_split: false,
834				handle: 'round',
835				reversed: false,
836				rtl: 'auto',
837				enabled: true,
838				formatter: function formatter(val) {
839					if (Array.isArray(val)) {
840						return val[0] + " : " + val[1];
841					} else {
842						return val;
843					}
844				},
845				natural_arrow_keys: false,
846				ticks: [],
847				ticks_positions: [],
848				ticks_labels: [],
849				ticks_snap_bounds: 0,
850				ticks_tooltip: false,
851				scale: 'linear',
852				focus: false,
853				tooltip_position: null,
854				labelledby: null,
855				rangeHighlights: []
856			},
857
858			getElement: function getElement() {
859				return this.sliderElem;
860			},
861
862			getValue: function getValue() {
863				if (this.options.range) {
864					return this._state.value;
865				} else {
866					return this._state.value[0];
867				}
868			},
869
870			setValue: function setValue(val, triggerSlideEvent, triggerChangeEvent) {
871				if (!val) {
872					val = 0;
873				}
874				var oldValue = this.getValue();
875				this._state.value = this._validateInputValue(val);
876				var applyPrecision = this._applyPrecision.bind(this);
877
878				if (this.options.range) {
879					this._state.value[0] = applyPrecision(this._state.value[0]);
880					this._state.value[1] = applyPrecision(this._state.value[1]);
881
882					this._state.value[0] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[0]));
883					this._state.value[1] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[1]));
884				} else {
885					this._state.value = applyPrecision(this._state.value);
886					this._state.value = [Math.max(this.options.min, Math.min(this.options.max, this._state.value))];
887					this._addClass(this.handle2, 'hide');
888					if (this.options.selection === 'after') {
889						this._state.value[1] = this.options.max;
890					} else {
891						this._state.value[1] = this.options.min;
892					}
893				}
894
895				if (this.options.max > this.options.min) {
896					this._state.percentage = [this._toPercentage(this._state.value[0]), this._toPercentage(this._state.value[1]), this.options.step * 100 / (this.options.max - this.options.min)];
897				} else {
898					this._state.percentage = [0, 0, 100];
899				}
900
901				this._layout();
902				var newValue = this.options.range ? this._state.value : this._state.value[0];
903
904				this._setDataVal(newValue);
905				if (triggerSlideEvent === true) {
906					this._trigger('slide', newValue);
907				}
908				if (oldValue !== newValue && triggerChangeEvent === true) {
909					this._trigger('change', {
910						oldValue: oldValue,
911						newValue: newValue
912					});
913				}
914
915				return this;
916			},
917
918			destroy: function destroy() {
919				// Remove event handlers on slider elements
920				this._removeSliderEventHandlers();
921
922				// Remove the slider from the DOM
923				this.sliderElem.parentNode.removeChild(this.sliderElem);
924				/* Show original <input> element */
925				this.element.style.display = "";
926
927				// Clear out custom event bindings
928				this._cleanUpEventCallbacksMap();
929
930				// Remove data values
931				this.element.removeAttribute("data");
932
933				// Remove JQuery handlers/data
934				if ($) {
935					this._unbindJQueryEventHandlers();
936					this.$element.removeData('slider');
937				}
938			},
939
940			disable: function disable() {
941				this._state.enabled = false;
942				this.handle1.removeAttribute("tabindex");
943				this.handle2.removeAttribute("tabindex");
944				this._addClass(this.sliderElem, 'slider-disabled');
945				this._trigger('slideDisabled');
946
947				return this;
948			},
949
950			enable: function enable() {
951				this._state.enabled = true;
952				this.handle1.setAttribute("tabindex", 0);
953				this.handle2.setAttribute("tabindex", 0);
954				this._removeClass(this.sliderElem, 'slider-disabled');
955				this._trigger('slideEnabled');
956
957				return this;
958			},
959
960			toggle: function toggle() {
961				if (this._state.enabled) {
962					this.disable();
963				} else {
964					this.enable();
965				}
966				return this;
967			},
968
969			isEnabled: function isEnabled() {
970				return this._state.enabled;
971			},
972
973			on: function on(evt, callback) {
974				this._bindNonQueryEventHandler(evt, callback);
975				return this;
976			},
977
978			off: function off(evt, callback) {
979				if ($) {
980					this.$element.off(evt, callback);
981					this.$sliderElem.off(evt, callback);
982				} else {
983					this._unbindNonQueryEventHandler(evt, callback);
984				}
985			},
986
987			getAttribute: function getAttribute(attribute) {
988				if (attribute) {
989					return this.options[attribute];
990				} else {
991					return this.options;
992				}
993			},
994
995			setAttribute: function setAttribute(attribute, value) {
996				this.options[attribute] = value;
997				return this;
998			},
999
1000			refresh: function refresh() {
1001				this._removeSliderEventHandlers();
1002				createNewSlider.call(this, this.element, this.options);
1003				if ($) {
1004					// Bind new instance of slider to the element
1005					$.data(this.element, 'slider', this);
1006				}
1007				return this;
1008			},
1009
1010			relayout: function relayout() {
1011				this._resize();
1012				this._layout();
1013				return this;
1014			},
1015
1016			/******************************+
1017   				HELPERS
1018   	- Any method that is not part of the public interface.
1019   - Place it underneath this comment block and write its signature like so:
1020   		_fnName : function() {...}
1021   	********************************/
1022			_removeSliderEventHandlers: function _removeSliderEventHandlers() {
1023				// Remove keydown event listeners
1024				this.handle1.removeEventListener("keydown", this.handle1Keydown, false);
1025				this.handle2.removeEventListener("keydown", this.handle2Keydown, false);
1026
1027				//remove the listeners from the ticks and handles if they had their own listeners
1028				if (this.options.ticks_tooltip) {
1029					var ticks = this.ticksContainer.getElementsByClassName('slider-tick');
1030					for (var i = 0; i < ticks.length; i++) {
1031						ticks[i].removeEventListener('mouseenter', this.ticksCallbackMap[i].mouseEnter, false);
1032						ticks[i].removeEventListener('mouseleave', this.ticksCallbackMap[i].mouseLeave, false);
1033					}
1034					this.handle1.removeEventListener('mouseenter', this.handleCallbackMap.handle1.mouseEnter, false);
1035					this.handle2.removeEventListener('mouseenter', this.handleCallbackMap.handle2.mouseEnter, false);
1036					this.handle1.removeEventListener('mouseleave', this.handleCallbackMap.handle1.mouseLeave, false);
1037					this.handle2.removeEventListener('mouseleave', this.handleCallbackMap.handle2.mouseLeave, false);
1038				}
1039
1040				this.handleCallbackMap = null;
1041				this.ticksCallbackMap = null;
1042
1043				if (this.showTooltip) {
1044					this.handle1.removeEventListener("focus", this.showTooltip, false);
1045					this.handle2.removeEventListener("focus", this.showTooltip, false);
1046				}
1047				if (this.hideTooltip) {
1048					this.handle1.removeEventListener("blur", this.hideTooltip, false);
1049					this.handle2.removeEventListener("blur", this.hideTooltip, false);
1050				}
1051
1052				// Remove event listeners from sliderElem
1053				if (this.showTooltip) {
1054					this.sliderElem.removeEventListener("mouseenter", this.showTooltip, false);
1055				}
1056				if (this.hideTooltip) {
1057					this.sliderElem.removeEventListener("mouseleave", this.hideTooltip, false);
1058				}
1059				this.sliderElem.removeEventListener("touchstart", this.touchstart, false);
1060				this.sliderElem.removeEventListener("touchmove", this.touchmove, false);
1061				this.sliderElem.removeEventListener("mousedown", this.mousedown, false);
1062
1063				// Remove window event listener
1064				window.removeEventListener("resize", this.resize, false);
1065			},
1066			_bindNonQueryEventHandler: function _bindNonQueryEventHandler(evt, callback) {
1067				if (this.eventToCallbackMap[evt] === undefined) {
1068					this.eventToCallbackMap[evt] = [];
1069				}
1070				this.eventToCallbackMap[evt].push(callback);
1071			},
1072			_unbindNonQueryEventHandler: function _unbindNonQueryEventHandler(evt, callback) {
1073				var callbacks = this.eventToCallbackMap[evt];
1074				if (callbacks !== undefined) {
1075					for (var i = 0; i < callbacks.length; i++) {
1076						if (callbacks[i] === callback) {
1077							callbacks.splice(i, 1);
1078							break;
1079						}
1080					}
1081				}
1082			},
1083			_cleanUpEventCallbacksMap: function _cleanUpEventCallbacksMap() {
1084				var eventNames = Object.keys(this.eventToCallbackMap);
1085				for (var i = 0; i < eventNames.length; i++) {
1086					var eventName = eventNames[i];
1087					delete this.eventToCallbackMap[eventName];
1088				}
1089			},
1090			_showTooltip: function _showTooltip() {
1091				if (this.options.tooltip_split === false) {
1092					this._addClass(this.tooltip, 'in');
1093					this.tooltip_min.style.display = 'none';
1094					this.tooltip_max.style.display = 'none';
1095				} else {
1096					this._addClass(this.tooltip_min, 'in');
1097					this._addClass(this.tooltip_max, 'in');
1098					this.tooltip.style.display = 'none';
1099				}
1100				this._state.over = true;
1101			},
1102			_hideTooltip: function _hideTooltip() {
1103				if (this._state.inDrag === false && this.alwaysShowTooltip !== true) {
1104					this._removeClass(this.tooltip, 'in');
1105					this._removeClass(this.tooltip_min, 'in');
1106					this._removeClass(this.tooltip_max, 'in');
1107				}
1108				this._state.over = false;
1109			},
1110			_setToolTipOnMouseOver: function _setToolTipOnMouseOver(tempState) {
1111				var formattedTooltipVal = this.options.formatter(!tempState ? this._state.value[0] : tempState.value[0]);
1112				var positionPercentages = !tempState ? getPositionPercentages(this._state, this.options.reversed) : getPositionPercentages(tempState, this.options.reversed);
1113				this._setText(this.tooltipInner, formattedTooltipVal);
1114
1115				this.tooltip.style[this.stylePos] = positionPercentages[0] + "%";
1116
1117				function getPositionPercentages(state, reversed) {
1118					if (reversed) {
1119						return [100 - state.percentage[0], this.options.range ? 100 - state.percentage[1] : state.percentage[1]];
1120					}
1121					return [state.percentage[0], state.percentage[1]];
1122				}
1123			},
1124			_addTickListener: function _addTickListener() {
1125				return {
1126					addMouseEnter: function addMouseEnter(reference, tick, index) {
1127						var enter = function enter() {
1128							var tempState = reference._state;
1129							var idString = index >= 0 ? index : this.attributes['aria-valuenow'].value;
1130							var hoverIndex = parseInt(idString, 10);
1131							tempState.value[0] = hoverIndex;
1132							tempState.percentage[0] = reference.options.ticks_positions[hoverIndex];
1133							reference._setToolTipOnMouseOver(tempState);
1134							reference._showTooltip();
1135						};
1136						tick.addEventListener("mouseenter", enter, false);
1137						return enter;
1138					},
1139					addMouseLeave: function addMouseLeave(reference, tick) {
1140						var leave = function leave() {
1141							reference._hideTooltip();
1142						};
1143						tick.addEventListener("mouseleave", leave, false);
1144						return leave;
1145					}
1146				};
1147			},
1148			_layout: function _layout() {
1149				var positionPercentages;
1150
1151				if (this.options.reversed) {
1152					positionPercentages = [100 - this._state.percentage[0], this.options.range ? 100 - this._state.percentage[1] : this._state.percentage[1]];
1153				} else {
1154					positionPercentages = [this._state.percentage[0], this._state.percentage[1]];
1155				}
1156
1157				this.handle1.style[this.stylePos] = positionPercentages[0] + "%";
1158				this.handle1.setAttribute('aria-valuenow', this._state.value[0]);
1159				if (isNaN(this.options.formatter(this._state.value[0]))) {
1160					this.handle1.setAttribute('aria-valuetext', this.options.formatter(this._state.value[0]));
1161				}
1162
1163				this.handle2.style[this.stylePos] = positionPercentages[1] + "%";
1164				this.handle2.setAttribute('aria-valuenow', this._state.value[1]);
1165				if (isNaN(this.options.formatter(this._state.value[1]))) {
1166					this.handle2.setAttribute('aria-valuetext', this.options.formatter(this._state.value[1]));
1167				}
1168
1169				/* Position highlight range elements */
1170				if (this.rangeHighlightElements.length > 0 && Array.isArray(this.options.rangeHighlights) && this.options.rangeHighlights.length > 0) {
1171					for (var _i = 0; _i < this.options.rangeHighlights.length; _i++) {
1172						var startPercent = this._toPercentage(this.options.rangeHighlights[_i].start);
1173						var endPercent = this._toPercentage(this.options.rangeHighlights[_i].end);
1174
1175						if (this.options.reversed) {
1176							var sp = 100 - endPercent;
1177							endPercent = 100 - startPercent;
1178							startPercent = sp;
1179						}
1180
1181						var currentRange = this._createHighlightRange(startPercent, endPercent);
1182
1183						if (currentRange) {
1184							if (this.options.orientation === 'vertical') {
1185								this.rangeHighlightElements[_i].style.top = currentRange.start + "%";
1186								this.rangeHighlightElements[_i].style.height = currentRange.size + "%";
1187							} else {
1188								if (this.options.rtl) {
1189									this.rangeHighlightElements[_i].style.right = currentRange.start + "%";
1190								} else {
1191									this.rangeHighlightElements[_i].style.left = currentRange.start + "%";
1192								}
1193								this.rangeHighlightElements[_i].style.width = currentRange.size + "%";
1194							}
1195						} else {
1196							this.rangeHighlightElements[_i].style.display = "none";
1197						}
1198					}
1199				}
1200
1201				/* Position ticks and labels */
1202				if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {
1203
1204					var styleSize = this.options.orientation === 'vertical' ? 'height' : 'width';
1205					var styleMargin;
1206					if (this.options.orientation === 'vertical') {
1207						styleMargin = 'marginTop';
1208					} else {
1209						if (this.options.rtl) {
1210							styleMargin = 'marginRight';
1211						} else {
1212							styleMargin = 'marginLeft';
1213						}
1214					}
1215					var labelSize = this._state.size / (this.options.ticks.length - 1);
1216
1217					if (this.tickLabelContainer) {
1218						var extraMargin = 0;
1219						if (this.options.ticks_positions.length === 0) {
1220							if (this.options.orientation !== 'vertical') {
1221								this.tickLabelContainer.style[styleMargin] = -labelSize / 2 + "px";
1222							}
1223
1224							extraMargin = this.tickLabelContainer.offsetHeight;
1225						} else {
1226							/* Chidren are position absolute, calculate height by finding the max offsetHeight of a child */
1227							for (i = 0; i < this.tickLabelContainer.childNodes.length; i++) {
1228								if (this.tickLabelContainer.childNodes[i].offsetHeight > extraMargin) {
1229									extraMargin = this.tickLabelContainer.childNodes[i].offsetHeight;
1230								}
1231							}
1232						}
1233						if (this.options.orientation === 'horizontal') {
1234							this.sliderElem.style.marginBottom = extraMargin + "px";
1235						}
1236					}
1237					for (var i = 0; i < this.options.ticks.length; i++) {
1238
1239						var percentage = this.options.ticks_positions[i] || this._toPercentage(this.options.ticks[i]);
1240
1241						if (this.options.reversed) {
1242							percentage = 100 - percentage;
1243						}
1244
1245						this.ticks[i].style[this.stylePos] = percentage + "%";
1246
1247						/* Set class labels to denote whether ticks are in the selection */
1248						this._removeClass(this.ticks[i], 'in-selection');
1249						if (!this.options.range) {
1250							if (this.options.selection === 'after' && percentage >= positionPercentages[0]) {
1251								this._addClass(this.ticks[i], 'in-selection');
1252							} else if (this.options.selection === 'before' && percentage <= positionPercentages[0]) {
1253								this._addClass(this.ticks[i], 'in-selection');
1254							}
1255						} else if (percentage >= positionPercentages[0] && percentage <= positionPercentages[1]) {
1256							this._addClass(this.ticks[i], 'in-selection');
1257						}
1258
1259						if (this.tickLabels[i]) {
1260							this.tickLabels[i].style[styleSize] = labelSize + "px";
1261
1262							if (this.options.orientation !== 'vertical' && this.options.ticks_positions[i] !== undefined) {
1263								this.tickLabels[i].style.position = 'absolute';
1264								this.tickLabels[i].style[this.stylePos] = percentage + "%";
1265								this.tickLabels[i].style[styleMargin] = -labelSize / 2 + 'px';
1266							} else if (this.options.orientation === 'vertical') {
1267								if (this.options.rtl) {
1268									this.tickLabels[i].style['marginRight'] = this.sliderElem.offsetWidth + "px";
1269								} else {
1270									this.tickLabels[i].style['marginLeft'] = this.sliderElem.offsetWidth + "px";
1271								}
1272								this.tickLabelContainer.style[styleMargin] = this.sliderElem.offsetWidth / 2 * -1 + 'px';
1273							}
1274						}
1275					}
1276				}
1277
1278				var formattedTooltipVal;
1279
1280				if (this.options.range) {
1281					formattedTooltipVal = this.options.formatter(this._state.value);
1282					this._setText(this.tooltipInner, formattedTooltipVal);
1283					this.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0]) / 2 + "%";
1284
1285					var innerTooltipMinText = this.options.formatter(this._state.value[0]);
1286					this._setText(this.tooltipInner_min, innerTooltipMinText);
1287
1288					var innerTooltipMaxText = this.options.formatter(this._state.value[1]);
1289					this._setText(this.tooltipInner_max, innerTooltipMaxText);
1290
1291					this.tooltip_min.style[this.stylePos] = positionPercentages[0] + "%";
1292
1293					this.tooltip_max.style[this.stylePos] = positionPercentages[1] + "%";
1294				} else {
1295					formattedTooltipVal = this.options.formatter(this._state.value[0]);
1296					this._setText(this.tooltipInner, formattedTooltipVal);
1297
1298					this.tooltip.style[this.stylePos] = positionPercentages[0] + "%";
1299				}
1300
1301				if (this.options.orientation === 'vertical') {
1302					this.trackLow.style.top = '0';
1303					this.trackLow.style.height = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1304
1305					this.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1306					this.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1307
1308					this.trackHigh.style.bottom = '0';
1309					this.trackHigh.style.height = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1310				} else {
1311					if (this.stylePos === 'right') {
1312						this.trackLow.style.right = '0';
1313					} else {
1314						this.trackLow.style.left = '0';
1315					}
1316					this.trackLow.style.width = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1317
1318					if (this.stylePos === 'right') {
1319						this.trackSelection.style.right = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1320					} else {
1321						this.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1322					}
1323					this.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1324
1325					if (this.stylePos === 'right') {
1326						this.trackHigh.style.left = '0';
1327					} else {
1328						this.trackHigh.style.right = '0';
1329					}
1330					this.trackHigh.style.width = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1331
1332					var offset_min = this.tooltip_min.getBoundingClientRect();
1333					var offset_max = this.tooltip_max.getBoundingClientRect();
1334
1335					if (this.options.tooltip_position === 'bottom') {
1336						if (offset_min.right > offset_max.left) {
1337							this._removeClass(this.tooltip_max, 'bottom');
1338							this._addClass(this.tooltip_max, 'top');
1339							this.tooltip_max.style.top = '';
1340							this.tooltip_max.style.bottom = 22 + 'px';
1341						} else {
1342							this._removeClass(this.tooltip_max, 'top');
1343							this._addClass(this.tooltip_max, 'bottom');
1344							this.tooltip_max.style.top = this.tooltip_min.style.top;
1345							this.tooltip_max.style.bottom = '';
1346						}
1347					} else {
1348						if (offset_min.right > offset_max.left) {
1349							this._removeClass(this.tooltip_max, 'top');
1350							this._addClass(this.tooltip_max, 'bottom');
1351							this.tooltip_max.style.top = 18 + 'px';
1352						} else {
1353							this._removeClass(this.tooltip_max, 'bottom');
1354							this._addClass(this.tooltip_max, 'top');
1355							this.tooltip_max.style.top = this.tooltip_min.style.top;
1356						}
1357					}
1358				}
1359			},
1360			_createHighlightRange: function _createHighlightRange(start, end) {
1361				if (this._isHighlightRange(start, end)) {
1362					if (start > end) {
1363						return { 'start': end, 'size': start - end };
1364					}
1365					return { 'start': start, 'size': end - start };
1366				}
1367				return null;
1368			},
1369			_isHighlightRange: function _isHighlightRange(start, end) {
1370				if (0 <= start && start <= 100 && 0 <= end && end <= 100) {
1371					return true;
1372				} else {
1373					return false;
1374				}
1375			},
1376			_resize: function _resize(ev) {
1377				/*jshint unused:false*/
1378				this._state.offset = this._offset(this.sliderElem);
1379				this._state.size = this.sliderElem[this.sizePos];
1380				this._layout();
1381			},
1382			_removeProperty: function _removeProperty(element, prop) {
1383				if (element.style.removeProperty) {
1384					element.style.removeProperty(prop);
1385				} else {
1386					element.style.removeAttribute(prop);
1387				}
1388			},
1389			_mousedown: function _mousedown(ev) {
1390				if (!this._state.enabled) {
1391					return false;
1392				}
1393
1394				this._state.offset = this._offset(this.sliderElem);
1395				this._state.size = this.sliderElem[this.sizePos];
1396
1397				var percentage = this._getPercentage(ev);
1398
1399				if (this.options.range) {
1400					var diff1 = Math.abs(this._state.percentage[0] - percentage);
1401					var diff2 = Math.abs(this._state.percentage[1] - percentage);
1402					this._state.dragged = diff1 < diff2 ? 0 : 1;
1403					this._adjustPercentageForRangeSliders(percentage);
1404				} else {
1405					this._state.dragged = 0;
1406				}
1407
1408				this._state.percentage[this._state.dragged] = percentage;
1409				this._layout();
1410
1411				if (this.touchCapable) {
1412					document.removeEventListener("touchmove", this.mousemove, false);
1413					document.removeEventListener("touchend", this.mouseup, false);
1414				}
1415
1416				if (this.mousemove) {
1417					document.removeEventListener("mousemove", this.mousemove, false);
1418				}
1419				if (this.mouseup) {
1420					document.removeEventListener("mouseup", this.mouseup, false);
1421				}
1422
1423				this.mousemove = this._mousemove.bind(this);
1424				this.mouseup = this._mouseup.bind(this);
1425
1426				if (this.touchCapable) {
1427					// Touch: Bind touch events:
1428					document.addEventListener("touchmove", this.mousemove, false);
1429					document.addEventListener("touchend", this.mouseup, false);
1430				}
1431				// Bind mouse events:
1432				document.addEventListener("mousemove", this.mousemove, false);
1433				document.addEventListener("mouseup", this.mouseup, false);
1434
1435				this._state.inDrag = true;
1436				var newValue = this._calculateValue();
1437
1438				this._trigger('slideStart', newValue);
1439
1440				this._setDataVal(newValue);
1441				this.setValue(newValue, false, true);
1442
1443				ev.returnValue = false;
1444
1445				if (this.options.focus) {
1446					this._triggerFocusOnHandle(this._state.dragged);
1447				}
1448
1449				return true;
1450			},
1451			_touchstart: function _touchstart(ev) {
1452				if (ev.changedTouches === undefined) {
1453					this._mousedown(ev);
1454					return;
1455				}
1456
1457				var touch = ev.changedTouches[0];
1458				this.touchX = touch.pageX;
1459				this.touchY = touch.pageY;
1460			},
1461			_triggerFocusOnHandle: function _triggerFocusOnHandle(handleIdx) {
1462				if (handleIdx === 0) {
1463					this.handle1.focus();
1464				}
1465				if (handleIdx === 1) {
1466					this.handle2.focus();
1467				}
1468			},
1469			_keydown: function _keydown(handleIdx, ev) {
1470				if (!this._state.enabled) {
1471					return false;
1472				}
1473
1474				var dir;
1475				switch (ev.keyCode) {
1476					case 37: // left
1477					case 40:
1478						// down
1479						dir = -1;
1480						break;
1481					case 39: // right
1482					case 38:
1483						// up
1484						dir = 1;
1485						break;
1486				}
1487				if (!dir) {
1488					return;
1489				}
1490
1491				// use natural arrow keys instead of from min to max
1492				if (this.options.natural_arrow_keys) {
1493					var ifVerticalAndNotReversed = this.options.orientation === 'vertical' && !this.options.reversed;
1494					var ifHorizontalAndReversed = this.options.orientation === 'horizontal' && this.options.reversed; // @todo control with rtl
1495
1496					if (ifVerticalAndNotReversed || ifHorizontalAndReversed) {
1497						dir = -dir;
1498					}
1499				}
1500
1501				var val = this._state.value[handleIdx] + dir * this.options.step;
1502				var percentage = val / this.options.max * 100;
1503				this._state.keyCtrl = handleIdx;
1504				if (this.options.range) {
1505					this._adjustPercentageForRangeSliders(percentage);
1506					var val1 = !this._state.keyCtrl ? val : this._state.value[0];
1507					var val2 = this._state.keyCtrl ? val : this._state.value[1];
1508					val = [val1, val2];
1509				}
1510
1511				this._trigger('slideStart', val);
1512				this._setDataVal(val);
1513				this.setValue(val, true, true);
1514
1515				this._setDataVal(val);
1516				this._trigger('slideStop', val);
1517				this._layout();
1518
1519				this._pauseEvent(ev);
1520				delete this._state.keyCtrl;
1521
1522				return false;
1523			},
1524			_pauseEvent: function _pauseEvent(ev) {
1525				if (ev.stopPropagation) {
1526					ev.stopPropagation();
1527				}
1528				if (ev.preventDefault) {
1529					ev.preventDefault();
1530				}
1531				ev.cancelBubble = true;
1532				ev.returnValue = false;
1533			},
1534			_mousemove: function _mousemove(ev) {
1535				if (!this._state.enabled) {
1536					return false;
1537				}
1538
1539				var percentage = this._getPercentage(ev);
1540				this._adjustPercentageForRangeSliders(percentage);
1541				this._state.percentage[this._state.dragged] = percentage;
1542				this._layout();
1543
1544				var val = this._calculateValue(true);
1545				this.setValue(val, true, true);
1546
1547				return false;
1548			},
1549			_touchmove: function _touchmove(ev) {
1550				if (ev.changedTouches === undefined) {
1551					return;
1552				}
1553
1554				var touch = ev.changedTouches[0];
1555
1556				var xDiff = touch.pageX - this.touchX;
1557				var yDiff = touch.pageY - this.touchY;
1558
1559				if (!this._state.inDrag) {
1560					// Vertical Slider
1561					if (this.options.orientation === 'vertical' && xDiff <= 5 && xDiff >= -5 && (yDiff >= 15 || yDiff <= -15)) {
1562						this._mousedown(ev);
1563					}
1564					// Horizontal slider.
1565					else if (yDiff <= 5 && yDiff >= -5 && (xDiff >= 15 || xDiff <= -15)) {
1566							this._mousedown(ev);
1567						}
1568				}
1569			},
1570			_adjustPercentageForRangeSliders: function _adjustPercentageForRangeSliders(percentage) {
1571				if (this.options.range) {
1572					var precision = this._getNumDigitsAfterDecimalPlace(percentage);
1573					precision = precision ? precision - 1 : 0;
1574					var percentageWithAdjustedPrecision = this._applyToFixedAndParseFloat(percentage, precision);
1575					if (this._state.dragged === 0 && this._applyToFixedAndParseFloat(this._state.percentage[1], precision) < percentageWithAdjustedPrecision) {
1576						this._state.percentage[0] = this._state.percentage[1];
1577						this._state.dragged = 1;
1578					} else if (this._state.dragged === 1 && this._applyToFixedAndParseFloat(this._state.percentage[0], precision) > percentageWithAdjustedPrecision) {
1579						this._state.percentage[1] = this._state.percentage[0];
1580						this._state.dragged = 0;
1581					} else if (this._state.keyCtrl === 0 && this._state.value[1] / this.options.max * 100 < percentage) {
1582						this._state.percentage[0] = this._state.percentage[1];
1583						this._state.keyCtrl = 1;
1584						this.handle2.focus();
1585					} else if (this._state.keyCtrl === 1 && this._state.value[0] / this.options.max * 100 > percentage) {
1586						this._state.percentage[1] = this._state.percentage[0];
1587						this._state.keyCtrl = 0;
1588						this.handle1.focus();
1589					}
1590				}
1591			},
1592			_mouseup: function _mouseup() {
1593				if (!this._state.enabled) {
1594					return false;
1595				}
1596				if (this.touchCapable) {
1597					// Touch: Unbind touch event handlers:
1598					document.removeEventListener("touchmove", this.mousemove, false);
1599					document.removeEventListener("touchend", this.mouseup, false);
1600				}
1601				// Unbind mouse event handlers:
1602				document.removeEventListener("mousemove", this.mousemove, false);
1603				document.removeEventListener("mouseup", this.mouseup, false);
1604
1605				this._state.inDrag = false;
1606				if (this._state.over === false) {
1607					this._hideTooltip();
1608				}
1609				var val = this._calculateValue(true);
1610
1611				this._layout();
1612				this._setDataVal(val);
1613				this._trigger('slideStop', val);
1614
1615				return false;
1616			},
1617			_calculateValue: function _calculateValue(snapToClosestTick) {
1618				var val;
1619				if (this.options.range) {
1620					val = [this.options.min, this.options.max];
1621					if (this._state.percentage[0] !== 0) {
1622						val[0] = this._toValue(this._state.percentage[0]);
1623						val[0] = this._applyPrecision(val[0]);
1624					}
1625					if (this._state.percentage[1] !== 100) {
1626						val[1] = this._toValue(this._state.percentage[1]);
1627						val[1] = this._applyPrecision(val[1]);
1628					}
1629				} else {
1630					val = this._toValue(this._state.percentage[0]);
1631					val = parseFloat(val);
1632					val = this._applyPrecision(val);
1633				}
1634
1635				if (snapToClosestTick) {
1636					var min = [val, Infinity];
1637					for (var i = 0; i < this.options.ticks.length; i++) {
1638						var diff = Math.abs(this.options.ticks[i] - val);
1639						if (diff <= min[1]) {
1640							min = [this.options.ticks[i], diff];
1641						}
1642					}
1643					if (min[1] <= this.options.ticks_snap_bounds) {
1644						return min[0];
1645					}
1646				}
1647
1648				return val;
1649			},
1650			_applyPrecision: function _applyPrecision(val) {
1651				var precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.options.step);
1652				return this._applyToFixedAndParseFloat(val, precision);
1653			},
1654			_getNumDigitsAfterDecimalPlace: function _getNumDigitsAfterDecimalPlace(num) {
1655				var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
1656				if (!match) {
1657					return 0;
1658				}
1659				return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
1660			},
1661			_applyToFixedAndParseFloat: function _applyToFixedAndParseFloat(num, toFixedInput) {
1662				var truncatedNum = num.toFixed(toFixedInput);
1663				return parseFloat(truncatedNum);
1664			},
1665			/*
1666   	Credits to Mike Samuel for the following method!
1667   	Source: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number
1668   */
1669			_getPercentage: function _getPercentage(ev) {
1670				if (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove')) {
1671					ev = ev.touches[0];
1672				}
1673
1674				var eventPosition = ev[this.mousePos];
1675				var sliderOffset = this._state.offset[this.stylePos];
1676				var distanceToSlide = eventPosition - sliderOffset;
1677				if (this.stylePos === 'right') {
1678					distanceToSlide = -distanceToSlide;
1679				}
1680				// Calculate what percent of the length the slider handle has slid
1681				var percentage = distanceToSlide / this._state.size * 100;
1682				percentage = Math.round(percentage / this._state.percentage[2]) * this._state.percentage[2];
1683				if (this.options.reversed) {
1684					percentage = 100 - percentage;
1685				}
1686
1687				// Make sure the percent is within the bounds of the slider.
1688				// 0% corresponds to the 'min' value of the slide
1689				// 100% corresponds to the 'max' value of the slide
1690				return Math.max(0, Math.min(100, percentage));
1691			},
1692			_validateInputValue: function _validateInputValue(val) {
1693				if (!isNaN(+val)) {
1694					return +val;
1695				} else if (Array.isArray(val)) {
vendor: 5,109 bytes, lines 1696-1860
1696					this._validateArray(val);
1697					return val;
1698				} else {
1699					throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(val));
1700				}
1701			},
1702			_validateArray: function _validateArray(val) {
1703				for (var i = 0; i < val.length; i++) {
1704					var input = val[i];
1705					if (typeof input !== 'number') {
1706						throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(input));
1707					}
1708				}
1709			},
1710			_setDataVal: function _setDataVal(val) {
1711				this.element.setAttribute('data-value', val);
1712				this.element.setAttribute('value', val);
1713				this.element.value = val;
1714			},
1715			_trigger: function _trigger(evt, val) {
1716				val = val || val === 0 ? val : undefined;
1717
1718				var callbackFnArray = this.eventToCallbackMap[evt];
1719				if (callbackFnArray && callbackFnArray.length) {
1720					for (var i = 0; i < callbackFnArray.length; i++) {
1721						var callbackFn = callbackFnArray[i];
1722						callbackFn(val);
1723					}
1724				}
1725
1726				/* If JQuery exists, trigger JQuery events */
1727				if ($) {
1728					this._triggerJQueryEvent(evt, val);
1729				}
1730			},
1731			_triggerJQueryEvent: function _triggerJQueryEvent(evt, val) {
1732				var eventData = {
1733					type: evt,
1734					value: val
1735				};
1736				this.$element.trigger(eventData);
1737				this.$sliderElem.trigger(eventData);
1738			},
1739			_unbindJQueryEventHandlers: function _unbindJQueryEventHandlers() {
1740				this.$element.off();
1741				this.$sliderElem.off();
1742			},
1743			_setText: function _setText(element, text) {
1744				if (typeof element.textContent !== "undefined") {
1745					element.textContent = text;
1746				} else if (typeof element.innerText !== "undefined") {
1747					element.innerText = text;
1748				}
1749			},
1750			_removeClass: function _removeClass(element, classString) {
1751				var classes = classString.split(" ");
1752				var newClasses = element.className;
1753
1754				for (var i = 0; i < classes.length; i++) {
1755					var classTag = classes[i];
1756					var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)");
1757					newClasses = newClasses.replace(regex, " ");
1758				}
1759
1760				element.className = newClasses.trim();
1761			},
1762			_addClass: function _addClass(element, classString) {
1763				var classes = classString.split(" ");
1764				var newClasses = element.className;
1765
1766				for (var i = 0; i < classes.length; i++) {
1767					var classTag = classes[i];
1768					var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)");
1769					var ifClassExists = regex.test(newClasses);
1770
1771					if (!ifClassExists) {
1772						newClasses += " " + classTag;
1773					}
1774				}
1775
1776				element.className = newClasses.trim();
1777			},
1778			_offsetLeft: function _offsetLeft(obj) {
1779				return obj.getBoundingClientRect().left;
1780			},
1781			_offsetRight: function _offsetRight(obj) {
1782				return obj.getBoundingClientRect().right;
1783			},
1784			_offsetTop: function _offsetTop(obj) {
1785				var offsetTop = obj.offsetTop;
1786				while ((obj = obj.offsetParent) && !isNaN(obj.offsetTop)) {
1787					offsetTop += obj.offsetTop;
1788					if (obj.tagName !== 'BODY') {
1789						offsetTop -= obj.scrollTop;
1790					}
1791				}
1792				return offsetTop;
1793			},
1794			_offset: function _offset(obj) {
1795				return {
1796					left: this._offsetLeft(obj),
1797					right: this._offsetRight(obj),
1798					top: this._offsetTop(obj)
1799				};
1800			},
1801			_css: function _css(elementRef, styleName, value) {
1802				if ($) {
1803					$.style(elementRef, styleName, value);
1804				} else {
1805					var style = styleName.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function (all, letter) {
1806						return letter.toUpperCase();
1807					});
1808					elementRef.style[style] = value;
1809				}
1810			},
1811			_toValue: function _toValue(percentage) {
1812				return this.options.scale.toValue.apply(this, [percentage]);
1813			},
1814			_toPercentage: function _toPercentage(value) {
1815				return this.options.scale.toPercentage.apply(this, [value]);
1816			},
1817			_setTooltipPosition: function _setTooltipPosition() {
1818				var tooltips = [this.tooltip, this.tooltip_min, this.tooltip_max];
1819				if (this.options.orientation === 'vertical') {
1820					var tooltipPos;
1821					if (this.options.tooltip_position) {
1822						tooltipPos = this.options.tooltip_position;
1823					} else {
1824						if (this.options.rtl) {
1825							tooltipPos = 'left';
1826						} else {
1827							tooltipPos = 'right';
1828						}
1829					}
1830					var oppositeSide = tooltipPos === 'left' ? 'right' : 'left';
1831					tooltips.forEach(function (tooltip) {
1832						this._addClass(tooltip, tooltipPos);
1833						tooltip.style[oppositeSide] = '100%';
1834					}.bind(this));
1835				} else if (this.options.tooltip_position === 'bottom') {
1836					tooltips.forEach(function (tooltip) {
1837						this._addClass(tooltip, 'bottom');
1838						tooltip.style.top = 22 + 'px';
1839					}.bind(this));
1840				} else {
1841					tooltips.forEach(function (tooltip) {
1842						this._addClass(tooltip, 'top');
1843						tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px';
1844					}.bind(this));
1845				}
1846			}
1847		};
1848
1849		/*********************************
1850  		Attach to global namespace
1851  	*********************************/
1852		if ($ && $.fn) {
1853			var autoRegisterNamespace = void 0;
1854
1855			if (!$.fn.slider) {
1856				$.bridget(NAMESPACE_MAIN, Slider);
1857				autoRegisterNamespace = NAMESPACE_MAIN;
1858			} else {
1859				if (windowIsDefined) {
1860					window.console.warn("bootstrap-slider.js - WARNING: $.fn.slider namespace is already bound. Use the $.fn.bootstrapSl
1860ider namespace instead.");
1861				}
1862				autoRegisterNamespace = NAMESPACE_ALTERNATE;
1863			}
1864			$.bridget(NAMESPACE_ALTERNATE, Slider);
1865
1866			// Auto-Register data-provide="slider" Elements
1867			$(function () {
1868				$("input[data-provide=slider]")[autoRegisterNamespace]();
1869			});
1870		}
1871	})($);
1872
1873	return Slider;
1874});

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.