LaravelTest
2061 строка · 69.9 Кб
1/*! =======================================================
2VERSION 11.0.2
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) 2019 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) {55if (typeof define === "function" && define.amd) {56define(["jquery"], factory);57} else if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === "object" && module.exports) {58var jQuery;59try {60jQuery = require("jquery");61} catch (err) {62jQuery = null;63}64module.exports = factory(jQuery);65} else if (window) {66window.Slider = factory(window.jQuery);67}68})(function ($) {69// Constants70var NAMESPACE_MAIN = 'slider';71var NAMESPACE_ALTERNATE = 'bootstrapSlider';72
73// Polyfill console methods74if (windowIsDefined && !window.console) {75window.console = {};76}77if (windowIsDefined && !window.console.log) {78window.console.log = function () {};79}80if (windowIsDefined && !window.console.warn) {81window.console.warn = function () {};82}83
84// Reference to Slider constructor85var Slider;86
87(function ($) {88
89'use strict';90
91// -------------------------- utils -------------------------- //92
93var slice = Array.prototype.slice;94
95function noop() {}96
97// -------------------------- definition -------------------------- //98
99function defineBridget($) {100
101// bail if no jQuery102if (!$) {103return;104}105
106// -------------------------- addOptionMethod -------------------------- //107
108/**109* adds option method -> $().plugin('option', {...})
110* @param {Function} PluginClass - constructor class
111*/
112function addOptionMethod(PluginClass) {113// don't overwrite original option method114if (PluginClass.prototype.option) {115return;116}117
118// option setter119PluginClass.prototype.option = function (opts) {120// bail out if not an object121if (!$.isPlainObject(opts)) {122return;123}124this.options = $.extend(true, this.options, opts);125};126}127
128// -------------------------- plugin bridge -------------------------- //129
130// helper function for logging errors131// $.error breaks jQuery chaining132var logError = typeof console === 'undefined' ? noop : function (message) {133console.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*/
141function bridge(namespace, PluginClass) {142// add to jQuery fn namespace143$.fn[namespace] = function (options) {144if (typeof options === 'string') {145// call plugin method when first argument is a string146// get arguments for method147var args = slice.call(arguments, 1);148
149for (var i = 0, len = this.length; i < len; i++) {150var elem = this[i];151var instance = $.data(elem, namespace);152if (!instance) {153logError("cannot call methods on " + namespace + " prior to initialization; " + "attempted to call '" + options + "'");154continue;155}156if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {157logError("no such method '" + options + "' for " + namespace + " instance");158continue;159}160
161// trigger method with arguments162var returnValue = instance[options].apply(instance, args);163
164// break look and return first value if provided165if (returnValue !== undefined && returnValue !== instance) {166return returnValue;167}168}169// return this if no return value170return this;171} else {172var objects = this.map(function () {173var instance = $.data(this, namespace);174if (instance) {175// apply options & init176instance.option(options);177instance._init();178} else {179// initialize new instance180instance = new PluginClass(this, options);181$.data(this, namespace, instance);182}183return $(this);184});185
186if (objects.length === 1) {187return objects[0];188}189return objects;190}191};192}193
194// -------------------------- bridget -------------------------- //195
196/**197* converts a Prototypical class into a proper jQuery plugin
198* the class must have a ._init method
199* @param {String} namespace - plugin name, used in $().pluginName
200* @param {Function} PluginClass - constructor class
201*/
202$.bridget = function (namespace, PluginClass) {203addOptionMethod(PluginClass);204bridge(namespace, PluginClass);205};206
207return $.bridget;208}209
210// get jquery from browser global211defineBridget($);212})($);213
214/*************************************************215BOOTSTRAP-SLIDER SOURCE CODE
216**************************************************/
217
218(function ($) {219var autoRegisterNamespace = void 0;220
221var ErrorMsgs = {222formatInvalidInputErrorMsg: function formatInvalidInputErrorMsg(input) {223return "Invalid input value '" + input + "' passed in";224},225callingContextNotSliderInstance: "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
228var SliderScale = {229linear: {230getValue: function getValue(value, options) {231if (value < options.min) {232return options.min;233} else if (value > options.max) {234return options.max;235} else {236return value;237}238},239toValue: function toValue(percentage) {240var rawValue = percentage / 100 * (this.options.max - this.options.min);241var shouldAdjustWithBase = true;242if (this.options.ticks_positions.length > 0) {243var minv,244maxv,245minp,246maxp = 0;247for (var i = 1; i < this.options.ticks_positions.length; i++) {248if (percentage <= this.options.ticks_positions[i]) {249minv = this.options.ticks[i - 1];250minp = this.options.ticks_positions[i - 1];251maxv = this.options.ticks[i];252maxp = this.options.ticks_positions[i];253
254break;255}256}257var partialPercentage = (percentage - minp) / (maxp - minp);258rawValue = minv + partialPercentage * (maxv - minv);259shouldAdjustWithBase = false;260}261
262var adjustment = shouldAdjustWithBase ? this.options.min : 0;263var value = adjustment + Math.round(rawValue / this.options.step) * this.options.step;264return SliderScale.linear.getValue(value, this.options);265},266toPercentage: function toPercentage(value) {267if (this.options.max === this.options.min) {268return 0;269}270
271if (this.options.ticks_positions.length > 0) {272var minv,273maxv,274minp,275maxp = 0;276for (var i = 0; i < this.options.ticks.length; i++) {277if (value <= this.options.ticks[i]) {278minv = i > 0 ? this.options.ticks[i - 1] : 0;279minp = i > 0 ? this.options.ticks_positions[i - 1] : 0;280maxv = this.options.ticks[i];281maxp = this.options.ticks_positions[i];282
283break;284}285}286if (i > 0) {287var partialPercentage = (value - minv) / (maxv - minv);288return minp + partialPercentage * (maxp - minp);289}290}291
292return 100 * (value - this.options.min) / (this.options.max - this.options.min);293}294},295
296logarithmic: {297/* Based on http://stackoverflow.com/questions/846221/logarithmic-slider */298toValue: function toValue(percentage) {299var offset = 1 - this.options.min;300var min = Math.log(this.options.min + offset);301var max = Math.log(this.options.max + offset);302var value = Math.exp(min + (max - min) * percentage / 100) - offset;303if (Math.round(value) === max) {304return max;305}306value = this.options.min + Math.round((value - this.options.min) / this.options.step) * this.options.step;307/* Rounding to the nearest step could exceed the min or308* max, so clip to those values. */
309return SliderScale.linear.getValue(value, this.options);310},311toPercentage: function toPercentage(value) {312if (this.options.max === this.options.min) {313return 0;314} else {315var offset = 1 - this.options.min;316var max = Math.log(this.options.max + offset);317var min = Math.log(this.options.min + offset);318var v = Math.log(value + offset);319return 100 * (v - min) / (max - min);320}321}322}323};324
325/*************************************************326CONSTRUCTOR
327**************************************************/
328Slider = function Slider(element, options) {329createNewSlider.call(this, element, options);330return this;331};332
333function createNewSlider(element, options) {334
335/*336The internal state object is used to store data about the current 'state' of slider.
337This includes values such as the `value`, `enabled`, etc...
338*/
339this._state = {340value: null,341enabled: null,342offset: null,343size: null,344percentage: null,345inDrag: false,346over: false,347tickIndex: null348};349
350// The objects used to store the reference to the tick methods if ticks_tooltip is on351this.ticksCallbackMap = {};352this.handleCallbackMap = {};353
354if (typeof element === "string") {355this.element = document.querySelector(element);356} else if (element instanceof HTMLElement) {357this.element = element;358}359
360/*************************************************361Process Options
362**************************************************/
363options = options ? options : {};364var optionTypes = Object.keys(this.defaultOptions);365
366var isMinSet = options.hasOwnProperty('min');367var isMaxSet = options.hasOwnProperty('max');368
369for (var i = 0; i < optionTypes.length; i++) {370var optName = optionTypes[i];371
372// First check if an option was passed in via the constructor373var val = options[optName];374// If no data attrib, then check data atrributes375val = typeof val !== 'undefined' ? val : getDataAttrib(this.element, optName);376// Finally, if nothing was specified, use the defaults377val = val !== null ? val : this.defaultOptions[optName];378
379// Set all options on the instance of the Slider380if (!this.options) {381this.options = {};382}383this.options[optName] = val;384}385
386this.ticksAreValid = Array.isArray(this.options.ticks) && this.options.ticks.length > 0;387
388// Lock to ticks only when ticks[] is defined and set389if (!this.ticksAreValid) {390this.options.lock_to_ticks = false;391}392
393// Check options.rtl394if (this.options.rtl === 'auto') {395var computedStyle = window.getComputedStyle(this.element);396if (computedStyle != null) {397this.options.rtl = computedStyle.direction === 'rtl';398} else {399// Fix for Firefox bug in versions less than 62:400// https://bugzilla.mozilla.org/show_bug.cgi?id=548397401// https://bugzilla.mozilla.org/show_bug.cgi?id=1467722402this.options.rtl = this.element.style.direction === 'rtl';403}404}405
406/*407Validate `tooltip_position` against 'orientation`
408- if `tooltip_position` is incompatible with orientation, switch it to a default compatible with specified `orientation`
409-- default for "vertical" -> "right", "left" if rtl
410-- default for "horizontal" -> "top"
411*/
412if (this.options.orientation === "vertical" && (this.options.tooltip_position === "top" || this.options.tooltip_position === "bottom")) {413if (this.options.rtl) {414this.options.tooltip_position = "left";415} else {416this.options.tooltip_position = "right";417}418} else if (this.options.orientation === "horizontal" && (this.options.tooltip_position === "left" || this.options.tooltip_position === "right")) {419
420this.options.tooltip_position = "top";421}422
423function getDataAttrib(element, optName) {424var dataName = "data-slider-" + optName.replace(/_/g, '-');425var dataValString = element.getAttribute(dataName);426
427try {428return JSON.parse(dataValString);429} catch (err) {430return dataValString;431}432}433
434/*************************************************435Create Markup
436**************************************************/
437
438var origWidth = this.element.style.width;439var updateSlider = false;440var parent = this.element.parentNode;441var sliderTrackSelection;442var sliderTrackLow, sliderTrackHigh;443var sliderMinHandle;444var sliderMaxHandle;445
446if (this.sliderElem) {447updateSlider = true;448} else {449/* Create elements needed for slider */450this.sliderElem = document.createElement("div");451this.sliderElem.className = "slider";452
453/* Create slider track elements */454var sliderTrack = document.createElement("div");455sliderTrack.className = "slider-track";456
457sliderTrackLow = document.createElement("div");458sliderTrackLow.className = "slider-track-low";459
460sliderTrackSelection = document.createElement("div");461sliderTrackSelection.className = "slider-selection";462
463sliderTrackHigh = document.createElement("div");464sliderTrackHigh.className = "slider-track-high";465
466sliderMinHandle = document.createElement("div");467sliderMinHandle.className = "slider-handle min-slider-handle";468sliderMinHandle.setAttribute('role', 'slider');469sliderMinHandle.setAttribute('aria-valuemin', this.options.min);470sliderMinHandle.setAttribute('aria-valuemax', this.options.max);471
472sliderMaxHandle = document.createElement("div");473sliderMaxHandle.className = "slider-handle max-slider-handle";474sliderMaxHandle.setAttribute('role', 'slider');475sliderMaxHandle.setAttribute('aria-valuemin', this.options.min);476sliderMaxHandle.setAttribute('aria-valuemax', this.options.max);477
478sliderTrack.appendChild(sliderTrackLow);479sliderTrack.appendChild(sliderTrackSelection);480sliderTrack.appendChild(sliderTrackHigh);481
482/* Create highlight range elements */483this.rangeHighlightElements = [];484var rangeHighlightsOpts = this.options.rangeHighlights;485if (Array.isArray(rangeHighlightsOpts) && rangeHighlightsOpts.length > 0) {486for (var j = 0; j < rangeHighlightsOpts.length; j++) {487var rangeHighlightElement = document.createElement("div");488var customClassString = rangeHighlightsOpts[j].class || "";489rangeHighlightElement.className = "slider-rangeHighlight slider-selection " + customClassString;490this.rangeHighlightElements.push(rangeHighlightElement);491sliderTrack.appendChild(rangeHighlightElement);492}493}494
495/* Add aria-labelledby to handle's */496var isLabelledbyArray = Array.isArray(this.options.labelledby);497if (isLabelledbyArray && this.options.labelledby[0]) {498sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby[0]);499}500if (isLabelledbyArray && this.options.labelledby[1]) {501sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby[1]);502}503if (!isLabelledbyArray && this.options.labelledby) {504sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby);505sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby);506}507
508/* Create ticks */509this.ticks = [];510if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {511this.ticksContainer = document.createElement('div');512this.ticksContainer.className = 'slider-tick-container';513
514for (i = 0; i < this.options.ticks.length; i++) {515var tick = document.createElement('div');516tick.className = 'slider-tick';517if (this.options.ticks_tooltip) {518var tickListenerReference = this._addTickListener();519var enterCallback = tickListenerReference.addMouseEnter(this, tick, i);520var leaveCallback = tickListenerReference.addMouseLeave(this, tick);521
522this.ticksCallbackMap[i] = {523mouseEnter: enterCallback,524mouseLeave: leaveCallback525};526}527this.ticks.push(tick);528this.ticksContainer.appendChild(tick);529}530
531sliderTrackSelection.className += " tick-slider-selection";532}533
534this.tickLabels = [];535if (Array.isArray(this.options.ticks_labels) && this.options.ticks_labels.length > 0) {536this.tickLabelContainer = document.createElement('div');537this.tickLabelContainer.className = 'slider-tick-label-container';538
539for (i = 0; i < this.options.ticks_labels.length; i++) {540var label = document.createElement('div');541var noTickPositionsSpecified = this.options.ticks_positions.length === 0;542var tickLabelsIndex = this.options.reversed && noTickPositionsSpecified ? this.options.ticks_labels.length - (i + 1) : i;543label.className = 'slider-tick-label';544label.innerHTML = this.options.ticks_labels[tickLabelsIndex];545
546this.tickLabels.push(label);547this.tickLabelContainer.appendChild(label);548}549}550
551var createAndAppendTooltipSubElements = function createAndAppendTooltipSubElements(tooltipElem) {552var arrow = document.createElement("div");553arrow.className = "arrow";554
555var inner = document.createElement("div");556inner.className = "tooltip-inner";557
558tooltipElem.appendChild(arrow);559tooltipElem.appendChild(inner);560};561
562/* Create tooltip elements */563var sliderTooltip = document.createElement("div");564sliderTooltip.className = "tooltip tooltip-main";565sliderTooltip.setAttribute('role', 'presentation');566createAndAppendTooltipSubElements(sliderTooltip);567
568var sliderTooltipMin = document.createElement("div");569sliderTooltipMin.className = "tooltip tooltip-min";570sliderTooltipMin.setAttribute('role', 'presentation');571createAndAppendTooltipSubElements(sliderTooltipMin);572
573var sliderTooltipMax = document.createElement("div");574sliderTooltipMax.className = "tooltip tooltip-max";575sliderTooltipMax.setAttribute('role', 'presentation');576createAndAppendTooltipSubElements(sliderTooltipMax);577
578/* Append components to sliderElem */579this.sliderElem.appendChild(sliderTrack);580this.sliderElem.appendChild(sliderTooltip);581this.sliderElem.appendChild(sliderTooltipMin);582this.sliderElem.appendChild(sliderTooltipMax);583
584if (this.tickLabelContainer) {585this.sliderElem.appendChild(this.tickLabelContainer);586}587if (this.ticksContainer) {588this.sliderElem.appendChild(this.ticksContainer);589}590
591this.sliderElem.appendChild(sliderMinHandle);592this.sliderElem.appendChild(sliderMaxHandle);593
594/* Append slider element to parent container, right before the original <input> element */595parent.insertBefore(this.sliderElem, this.element);596
597/* Hide original <input> element */598this.element.style.display = "none";599}600/* If JQuery exists, cache JQ references */601if ($) {602this.$element = $(this.element);603this.$sliderElem = $(this.sliderElem);604}605
606/*************************************************607Setup
608**************************************************/
609this.eventToCallbackMap = {};610this.sliderElem.id = this.options.id;611
612this.touchCapable = 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch;613
614this.touchX = 0;615this.touchY = 0;616
617this.tooltip = this.sliderElem.querySelector('.tooltip-main');618this.tooltipInner = this.tooltip.querySelector('.tooltip-inner');619
620this.tooltip_min = this.sliderElem.querySelector('.tooltip-min');621this.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner');622
623this.tooltip_max = this.sliderElem.querySelector('.tooltip-max');624this.tooltipInner_max = this.tooltip_max.querySelector('.tooltip-inner');625
626if (SliderScale[this.options.scale]) {627this.options.scale = SliderScale[this.options.scale];628}629
630if (updateSlider === true) {631// Reset classes632this._removeClass(this.sliderElem, 'slider-horizontal');633this._removeClass(this.sliderElem, 'slider-vertical');634this._removeClass(this.sliderElem, 'slider-rtl');635this._removeClass(this.tooltip, 'hide');636this._removeClass(this.tooltip_min, 'hide');637this._removeClass(this.tooltip_max, 'hide');638
639// Undo existing inline styles for track640["left", "right", "top", "width", "height"].forEach(function (prop) {641this._removeProperty(this.trackLow, prop);642this._removeProperty(this.trackSelection, prop);643this._removeProperty(this.trackHigh, prop);644}, this);645
646// Undo inline styles on handles647[this.handle1, this.handle2].forEach(function (handle) {648this._removeProperty(handle, 'left');649this._removeProperty(handle, 'right');650this._removeProperty(handle, 'top');651}, this);652
653// Undo inline styles and classes on tooltips654[this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function (tooltip) {655this._removeProperty(tooltip, 'bs-tooltip-left');656this._removeProperty(tooltip, 'bs-tooltip-right');657this._removeProperty(tooltip, 'bs-tooltip-top');658
659this._removeClass(tooltip, 'bs-tooltip-right');660this._removeClass(tooltip, 'bs-tooltip-left');661this._removeClass(tooltip, 'bs-tooltip-top');662}, this);663}664
665if (this.options.orientation === 'vertical') {666this._addClass(this.sliderElem, 'slider-vertical');667this.stylePos = 'top';668this.mousePos = 'pageY';669this.sizePos = 'offsetHeight';670} else {671this._addClass(this.sliderElem, 'slider-horizontal');672this.sliderElem.style.width = origWidth;673this.options.orientation = 'horizontal';674if (this.options.rtl) {675this.stylePos = 'right';676} else {677this.stylePos = 'left';678}679this.mousePos = 'clientX';680this.sizePos = 'offsetWidth';681}682// specific rtl class683if (this.options.rtl) {684this._addClass(this.sliderElem, 'slider-rtl');685}686this._setTooltipPosition();687/* In case ticks are specified, overwrite the min and max bounds */688if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {689if (!isMaxSet) {690this.options.max = Math.max.apply(Math, this.options.ticks);691}692if (!isMinSet) {693this.options.min = Math.min.apply(Math, this.options.ticks);694}695}696
697if (Array.isArray(this.options.value)) {698this.options.range = true;699this._state.value = this.options.value;700} else if (this.options.range) {701// User wants a range, but value is not an array702this._state.value = [this.options.value, this.options.max];703} else {704this._state.value = this.options.value;705}706
707this.trackLow = sliderTrackLow || this.trackLow;708this.trackSelection = sliderTrackSelection || this.trackSelection;709this.trackHigh = sliderTrackHigh || this.trackHigh;710
711if (this.options.selection === 'none') {712this._addClass(this.trackLow, 'hide');713this._addClass(this.trackSelection, 'hide');714this._addClass(this.trackHigh, 'hide');715} else if (this.options.selection === 'after' || this.options.selection === 'before') {716this._removeClass(this.trackLow, 'hide');717this._removeClass(this.trackSelection, 'hide');718this._removeClass(this.trackHigh, 'hide');719}720
721this.handle1 = sliderMinHandle || this.handle1;722this.handle2 = sliderMaxHandle || this.handle2;723
724if (updateSlider === true) {725// Reset classes726this._removeClass(this.handle1, 'round triangle');727this._removeClass(this.handle2, 'round triangle hide');728
729for (i = 0; i < this.ticks.length; i++) {730this._removeClass(this.ticks[i], 'round triangle hide');731}732}733
734var availableHandleModifiers = ['round', 'triangle', 'custom'];735var isValidHandleType = availableHandleModifiers.indexOf(this.options.handle) !== -1;736if (isValidHandleType) {737this._addClass(this.handle1, this.options.handle);738this._addClass(this.handle2, this.options.handle);739
740for (i = 0; i < this.ticks.length; i++) {741this._addClass(this.ticks[i], this.options.handle);742}743}744
745this._state.offset = this._offset(this.sliderElem);746this._state.size = this.sliderElem[this.sizePos];747this.setValue(this._state.value);748
749/******************************************750Bind Event Listeners
751******************************************/
752
753// Bind keyboard handlers754this.handle1Keydown = this._keydown.bind(this, 0);755this.handle1.addEventListener("keydown", this.handle1Keydown, false);756
757this.handle2Keydown = this._keydown.bind(this, 1);758this.handle2.addEventListener("keydown", this.handle2Keydown, false);759
760this.mousedown = this._mousedown.bind(this);761this.touchstart = this._touchstart.bind(this);762this.touchmove = this._touchmove.bind(this);763
764if (this.touchCapable) {765this.sliderElem.addEventListener("touchstart", this.touchstart, false);766this.sliderElem.addEventListener("touchmove", this.touchmove, false);767}768
769this.sliderElem.addEventListener("mousedown", this.mousedown, false);770
771// Bind window handlers772this.resize = this._resize.bind(this);773window.addEventListener("resize", this.resize, false);774
775// Bind tooltip-related handlers776if (this.options.tooltip === 'hide') {777this._addClass(this.tooltip, 'hide');778this._addClass(this.tooltip_min, 'hide');779this._addClass(this.tooltip_max, 'hide');780} else if (this.options.tooltip === 'always') {781this._showTooltip();782this._alwaysShowTooltip = true;783} else {784this.showTooltip = this._showTooltip.bind(this);785this.hideTooltip = this._hideTooltip.bind(this);786
787if (this.options.ticks_tooltip) {788var callbackHandle = this._addTickListener();789//create handle1 listeners and store references in map790var mouseEnter = callbackHandle.addMouseEnter(this, this.handle1);791var mouseLeave = callbackHandle.addMouseLeave(this, this.handle1);792this.handleCallbackMap.handle1 = {793mouseEnter: mouseEnter,794mouseLeave: mouseLeave795};796//create handle2 listeners and store references in map797mouseEnter = callbackHandle.addMouseEnter(this, this.handle2);798mouseLeave = callbackHandle.addMouseLeave(this, this.handle2);799this.handleCallbackMap.handle2 = {800mouseEnter: mouseEnter,801mouseLeave: mouseLeave802};803} else {804this.sliderElem.addEventListener("mouseenter", this.showTooltip, false);805this.sliderElem.addEventListener("mouseleave", this.hideTooltip, false);806
807if (this.touchCapable) {808this.sliderElem.addEventListener("touchstart", this.showTooltip, false);809this.sliderElem.addEventListener("touchmove", this.showTooltip, false);810this.sliderElem.addEventListener("touchend", this.hideTooltip, false);811}812}813
814this.handle1.addEventListener("focus", this.showTooltip, false);815this.handle1.addEventListener("blur", this.hideTooltip, false);816
817this.handle2.addEventListener("focus", this.showTooltip, false);818this.handle2.addEventListener("blur", this.hideTooltip, false);819
820if (this.touchCapable) {821this.handle1.addEventListener("touchstart", this.showTooltip, false);822this.handle1.addEventListener("touchmove", this.showTooltip, false);823this.handle1.addEventListener("touchend", this.hideTooltip, false);824
825this.handle2.addEventListener("touchstart", this.showTooltip, false);826this.handle2.addEventListener("touchmove", this.showTooltip, false);827this.handle2.addEventListener("touchend", this.hideTooltip, false);828}829}830
831if (this.options.enabled) {832this.enable();833} else {834this.disable();835}836}837
838/*************************************************839INSTANCE PROPERTIES/METHODS
840- Any methods bound to the prototype are considered
841part of the plugin's `public` interface
842**************************************************/
843Slider.prototype = {844_init: function _init() {}, // NOTE: Must exist to support bridget845
846constructor: Slider,847
848defaultOptions: {849id: "",850min: 0,851max: 10,852step: 1,853precision: 0,854orientation: 'horizontal',855value: 5,856range: false,857selection: 'before',858tooltip: 'show',859tooltip_split: false,860lock_to_ticks: false,861handle: 'round',862reversed: false,863rtl: 'auto',864enabled: true,865formatter: function formatter(val) {866if (Array.isArray(val)) {867return val[0] + " : " + val[1];868} else {869return val;870}871},872natural_arrow_keys: false,873ticks: [],874ticks_positions: [],875ticks_labels: [],876ticks_snap_bounds: 0,877ticks_tooltip: false,878scale: 'linear',879focus: false,880tooltip_position: null,881labelledby: null,882rangeHighlights: []883},884
885getElement: function getElement() {886return this.sliderElem;887},888
889getValue: function getValue() {890if (this.options.range) {891return this._state.value;892} else {893return this._state.value[0];894}895},896
897setValue: function setValue(val, triggerSlideEvent, triggerChangeEvent) {898if (!val) {899val = 0;900}901var oldValue = this.getValue();902this._state.value = this._validateInputValue(val);903var applyPrecision = this._applyPrecision.bind(this);904
905if (this.options.range) {906this._state.value[0] = applyPrecision(this._state.value[0]);907this._state.value[1] = applyPrecision(this._state.value[1]);908
909if (this.ticksAreValid && this.options.lock_to_ticks) {910this._state.value[0] = this.options.ticks[this._getClosestTickIndex(this._state.value[0])];911this._state.value[1] = this.options.ticks[this._getClosestTickIndex(this._state.value[1])];912}913
914this._state.value[0] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[0]));915this._state.value[1] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[1]));916} else {917this._state.value = applyPrecision(this._state.value);918
919if (this.ticksAreValid && this.options.lock_to_ticks) {920this._state.value = this.options.ticks[this._getClosestTickIndex(this._state.value)];921}922
923this._state.value = [Math.max(this.options.min, Math.min(this.options.max, this._state.value))];924this._addClass(this.handle2, 'hide');925if (this.options.selection === 'after') {926this._state.value[1] = this.options.max;927} else {928this._state.value[1] = this.options.min;929}930}931
932// Determine which ticks the handle(s) are set at (if applicable)933this._setTickIndex();934
935if (this.options.max > this.options.min) {936this._state.percentage = [this._toPercentage(this._state.value[0]), this._toPercentage(this._state.value[1]), this.options.step * 100 / (this.options.max - this.options.min)];937} else {938this._state.percentage = [0, 0, 100];939}940
941this._layout();942var newValue = this.options.range ? this._state.value : this._state.value[0];943
944this._setDataVal(newValue);945if (triggerSlideEvent === true) {946this._trigger('slide', newValue);947}948
949var hasChanged = false;950if (Array.isArray(newValue)) {951hasChanged = oldValue[0] !== newValue[0] || oldValue[1] !== newValue[1];952} else {953hasChanged = oldValue !== newValue;954}955
956if (hasChanged && triggerChangeEvent === true) {957this._trigger('change', {958oldValue: oldValue,959newValue: newValue960});961}962
963return this;964},965
966destroy: function destroy() {967// Remove event handlers on slider elements968this._removeSliderEventHandlers();969
970// Remove the slider from the DOM971this.sliderElem.parentNode.removeChild(this.sliderElem);972/* Show original <input> element */973this.element.style.display = "";974
975// Clear out custom event bindings976this._cleanUpEventCallbacksMap();977
978// Remove data values979this.element.removeAttribute("data");980
981// Remove JQuery handlers/data982if ($) {983this._unbindJQueryEventHandlers();984if (autoRegisterNamespace === NAMESPACE_MAIN) {985this.$element.removeData(autoRegisterNamespace);986}987this.$element.removeData(NAMESPACE_ALTERNATE);988}989},990
991disable: function disable() {992this._state.enabled = false;993this.handle1.removeAttribute("tabindex");994this.handle2.removeAttribute("tabindex");995this._addClass(this.sliderElem, 'slider-disabled');996this._trigger('slideDisabled');997
998return this;999},1000
1001enable: function enable() {1002this._state.enabled = true;1003this.handle1.setAttribute("tabindex", 0);1004this.handle2.setAttribute("tabindex", 0);1005this._removeClass(this.sliderElem, 'slider-disabled');1006this._trigger('slideEnabled');1007
1008return this;1009},1010
1011toggle: function toggle() {1012if (this._state.enabled) {1013this.disable();1014} else {1015this.enable();1016}1017return this;1018},1019
1020isEnabled: function isEnabled() {1021return this._state.enabled;1022},1023
1024on: function on(evt, callback) {1025this._bindNonQueryEventHandler(evt, callback);1026return this;1027},1028
1029off: function off(evt, callback) {1030if ($) {1031this.$element.off(evt, callback);1032this.$sliderElem.off(evt, callback);1033} else {1034this._unbindNonQueryEventHandler(evt, callback);1035}1036},1037
1038getAttribute: function getAttribute(attribute) {1039if (attribute) {1040return this.options[attribute];1041} else {1042return this.options;1043}1044},1045
1046setAttribute: function setAttribute(attribute, value) {1047this.options[attribute] = value;1048return this;1049},1050
1051refresh: function refresh(options) {1052var currentValue = this.getValue();1053this._removeSliderEventHandlers();1054createNewSlider.call(this, this.element, this.options);1055// Don't reset slider's value on refresh if `useCurrentValue` is true1056if (options && options.useCurrentValue === true) {1057this.setValue(currentValue);1058}1059if ($) {1060// Bind new instance of slider to the element1061if (autoRegisterNamespace === NAMESPACE_MAIN) {1062$.data(this.element, NAMESPACE_MAIN, this);1063$.data(this.element, NAMESPACE_ALTERNATE, this);1064} else {1065$.data(this.element, NAMESPACE_ALTERNATE, this);1066}1067}1068return this;1069},1070
1071relayout: function relayout() {1072this._resize();1073return this;1074},1075
1076/******************************+1077HELPERS
1078- Any method that is not part of the public interface.
1079- Place it underneath this comment block and write its signature like so:
1080_fnName : function() {...}
1081********************************/
1082_removeTooltipListener: function _removeTooltipListener(event, handler) {1083this.handle1.removeEventListener(event, handler, false);1084this.handle2.removeEventListener(event, handler, false);1085},1086_removeSliderEventHandlers: function _removeSliderEventHandlers() {1087// Remove keydown event listeners1088this.handle1.removeEventListener("keydown", this.handle1Keydown, false);1089this.handle2.removeEventListener("keydown", this.handle2Keydown, false);1090
1091//remove the listeners from the ticks and handles if they had their own listeners1092if (this.options.ticks_tooltip) {1093var ticks = this.ticksContainer.getElementsByClassName('slider-tick');1094for (var i = 0; i < ticks.length; i++) {1095ticks[i].removeEventListener('mouseenter', this.ticksCallbackMap[i].mouseEnter, false);1096ticks[i].removeEventListener('mouseleave', this.ticksCallbackMap[i].mouseLeave, false);1097}1098if (this.handleCallbackMap.handle1 && this.handleCallbackMap.handle2) {1099this.handle1.removeEventListener('mouseenter', this.handleCallbackMap.handle1.mouseEnter, false);1100this.handle2.removeEventListener('mouseenter', this.handleCallbackMap.handle2.mouseEnter, false);1101this.handle1.removeEventListener('mouseleave', this.handleCallbackMap.handle1.mouseLeave, false);1102this.handle2.removeEventListener('mouseleave', this.handleCallbackMap.handle2.mouseLeave, false);1103}1104}1105
1106this.handleCallbackMap = null;1107this.ticksCallbackMap = null;1108
1109if (this.showTooltip) {1110this._removeTooltipListener("focus", this.showTooltip);1111}1112if (this.hideTooltip) {1113this._removeTooltipListener("blur", this.hideTooltip);1114}1115
1116// Remove event listeners from sliderElem1117if (this.showTooltip) {1118this.sliderElem.removeEventListener("mouseenter", this.showTooltip, false);1119}1120if (this.hideTooltip) {1121this.sliderElem.removeEventListener("mouseleave", this.hideTooltip, false);1122}1123
1124this.sliderElem.removeEventListener("mousedown", this.mousedown, false);1125
1126if (this.touchCapable) {1127// Remove touch event listeners from handles1128if (this.showTooltip) {1129this.handle1.removeEventListener("touchstart", this.showTooltip, false);1130this.handle1.removeEventListener("touchmove", this.showTooltip, false);1131this.handle2.removeEventListener("touchstart", this.showTooltip, false);1132this.handle2.removeEventListener("touchmove", this.showTooltip, false);1133}1134if (this.hideTooltip) {1135this.handle1.removeEventListener("touchend", this.hideTooltip, false);1136this.handle2.removeEventListener("touchend", this.hideTooltip, false);1137}1138
1139// Remove event listeners from sliderElem1140if (this.showTooltip) {1141this.sliderElem.removeEventListener("touchstart", this.showTooltip, false);1142this.sliderElem.removeEventListener("touchmove", this.showTooltip, false);1143}1144if (this.hideTooltip) {1145this.sliderElem.removeEventListener("touchend", this.hideTooltip, false);1146}1147
1148this.sliderElem.removeEventListener("touchstart", this.touchstart, false);1149this.sliderElem.removeEventListener("touchmove", this.touchmove, false);1150}1151
1152// Remove window event listener1153window.removeEventListener("resize", this.resize, false);1154},1155_bindNonQueryEventHandler: function _bindNonQueryEventHandler(evt, callback) {1156if (this.eventToCallbackMap[evt] === undefined) {1157this.eventToCallbackMap[evt] = [];1158}1159this.eventToCallbackMap[evt].push(callback);1160},1161_unbindNonQueryEventHandler: function _unbindNonQueryEventHandler(evt, callback) {1162var callbacks = this.eventToCallbackMap[evt];1163if (callbacks !== undefined) {1164for (var i = 0; i < callbacks.length; i++) {1165if (callbacks[i] === callback) {1166callbacks.splice(i, 1);1167break;1168}1169}1170}1171},1172_cleanUpEventCallbacksMap: function _cleanUpEventCallbacksMap() {1173var eventNames = Object.keys(this.eventToCallbackMap);1174for (var i = 0; i < eventNames.length; i++) {1175var eventName = eventNames[i];1176delete this.eventToCallbackMap[eventName];1177}1178},1179_showTooltip: function _showTooltip() {1180if (this.options.tooltip_split === false) {1181this._addClass(this.tooltip, 'show');1182this.tooltip_min.style.display = 'none';1183this.tooltip_max.style.display = 'none';1184} else {1185this._addClass(this.tooltip_min, 'show');1186this._addClass(this.tooltip_max, 'show');1187this.tooltip.style.display = 'none';1188}1189this._state.over = true;1190},1191_hideTooltip: function _hideTooltip() {1192if (this._state.inDrag === false && this._alwaysShowTooltip !== true) {1193this._removeClass(this.tooltip, 'show');1194this._removeClass(this.tooltip_min, 'show');1195this._removeClass(this.tooltip_max, 'show');1196}1197this._state.over = false;1198},1199_setToolTipOnMouseOver: function _setToolTipOnMouseOver(tempState) {1200var self = this;1201var formattedTooltipVal = this.options.formatter(!tempState ? this._state.value[0] : tempState.value[0]);1202var positionPercentages = !tempState ? getPositionPercentages(this._state, this.options.reversed) : getPositionPercentages(tempState, this.options.reversed);1203this._setText(this.tooltipInner, formattedTooltipVal);1204
1205this.tooltip.style[this.stylePos] = positionPercentages[0] + "%";1206
1207function getPositionPercentages(state, reversed) {1208if (reversed) {1209return [100 - state.percentage[0], self.options.range ? 100 - state.percentage[1] : state.percentage[1]];1210}1211return [state.percentage[0], state.percentage[1]];1212}1213},1214_copyState: function _copyState() {1215return {1216value: [this._state.value[0], this._state.value[1]],1217enabled: this._state.enabled,1218offset: this._state.offset,1219size: this._state.size,1220percentage: [this._state.percentage[0], this._state.percentage[1], this._state.percentage[2]],1221inDrag: this._state.inDrag,1222over: this._state.over,1223// deleted or null'd keys1224dragged: this._state.dragged,1225keyCtrl: this._state.keyCtrl1226};1227},1228_addTickListener: function _addTickListener() {1229return {1230addMouseEnter: function addMouseEnter(reference, element, index) {1231var enter = function enter() {1232var tempState = reference._copyState();1233// Which handle is being hovered over?1234var val = element === reference.handle1 ? tempState.value[0] : tempState.value[1];1235var per = void 0;1236
1237// Setup value and percentage for tick's 'mouseenter'1238if (index !== undefined) {1239val = reference.options.ticks[index];1240per = reference.options.ticks_positions.length > 0 && reference.options.ticks_positions[index] || reference._toPercentage(reference.options.ticks[index]);1241} else {1242per = reference._toPercentage(val);1243}1244
1245tempState.value[0] = val;1246tempState.percentage[0] = per;1247reference._setToolTipOnMouseOver(tempState);1248reference._showTooltip();1249};1250element.addEventListener("mouseenter", enter, false);1251return enter;1252},1253addMouseLeave: function addMouseLeave(reference, element) {1254var leave = function leave() {1255reference._hideTooltip();1256};1257element.addEventListener("mouseleave", leave, false);1258return leave;1259}1260};1261},1262_layout: function _layout() {1263var positionPercentages;1264var formattedValue;1265
1266if (this.options.reversed) {1267positionPercentages = [100 - this._state.percentage[0], this.options.range ? 100 - this._state.percentage[1] : this._state.percentage[1]];1268} else {1269positionPercentages = [this._state.percentage[0], this._state.percentage[1]];1270}1271
1272this.handle1.style[this.stylePos] = positionPercentages[0] + "%";1273this.handle1.setAttribute('aria-valuenow', this._state.value[0]);1274formattedValue = this.options.formatter(this._state.value[0]);1275if (isNaN(formattedValue)) {1276this.handle1.setAttribute('aria-valuetext', formattedValue);1277} else {1278this.handle1.removeAttribute('aria-valuetext');1279}1280
1281this.handle2.style[this.stylePos] = positionPercentages[1] + "%";1282this.handle2.setAttribute('aria-valuenow', this._state.value[1]);1283formattedValue = this.options.formatter(this._state.value[1]);1284if (isNaN(formattedValue)) {1285this.handle2.setAttribute('aria-valuetext', formattedValue);1286} else {1287this.handle2.removeAttribute('aria-valuetext');1288}1289
1290/* Position highlight range elements */1291if (this.rangeHighlightElements.length > 0 && Array.isArray(this.options.rangeHighlights) && this.options.rangeHighlights.length > 0) {1292for (var _i = 0; _i < this.options.rangeHighlights.length; _i++) {1293var startPercent = this._toPercentage(this.options.rangeHighlights[_i].start);1294var endPercent = this._toPercentage(this.options.rangeHighlights[_i].end);1295
1296if (this.options.reversed) {1297var sp = 100 - endPercent;1298endPercent = 100 - startPercent;1299startPercent = sp;1300}1301
1302var currentRange = this._createHighlightRange(startPercent, endPercent);1303
1304if (currentRange) {1305if (this.options.orientation === 'vertical') {1306this.rangeHighlightElements[_i].style.top = currentRange.start + "%";1307this.rangeHighlightElements[_i].style.height = currentRange.size + "%";1308} else {1309if (this.options.rtl) {1310this.rangeHighlightElements[_i].style.right = currentRange.start + "%";1311} else {1312this.rangeHighlightElements[_i].style.left = currentRange.start + "%";1313}1314this.rangeHighlightElements[_i].style.width = currentRange.size + "%";1315}1316} else {1317this.rangeHighlightElements[_i].style.display = "none";1318}1319}1320}1321
1322/* Position ticks and labels */1323if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {1324
1325var styleSize = this.options.orientation === 'vertical' ? 'height' : 'width';1326var styleMargin;1327if (this.options.orientation === 'vertical') {1328styleMargin = 'marginTop';1329} else {1330if (this.options.rtl) {1331styleMargin = 'marginRight';1332} else {1333styleMargin = 'marginLeft';1334}1335}1336var labelSize = this._state.size / (this.options.ticks.length - 1);1337
1338if (this.tickLabelContainer) {1339var extraMargin = 0;1340if (this.options.ticks_positions.length === 0) {1341if (this.options.orientation !== 'vertical') {1342this.tickLabelContainer.style[styleMargin] = -labelSize / 2 + "px";1343}1344
1345extraMargin = this.tickLabelContainer.offsetHeight;1346} else {1347/* Chidren are position absolute, calculate height by finding the max offsetHeight of a child */1348for (i = 0; i < this.tickLabelContainer.childNodes.length; i++) {1349if (this.tickLabelContainer.childNodes[i].offsetHeight > extraMargin) {1350extraMargin = this.tickLabelContainer.childNodes[i].offsetHeight;1351}1352}1353}1354if (this.options.orientation === 'horizontal') {1355this.sliderElem.style.marginBottom = extraMargin + "px";1356}1357}1358for (var i = 0; i < this.options.ticks.length; i++) {1359
1360var percentage = this.options.ticks_positions[i] || this._toPercentage(this.options.ticks[i]);1361
1362if (this.options.reversed) {1363percentage = 100 - percentage;1364}1365
1366this.ticks[i].style[this.stylePos] = percentage + "%";1367
1368/* Set class labels to denote whether ticks are in the selection */1369this._removeClass(this.ticks[i], 'in-selection');1370if (!this.options.range) {1371if (this.options.selection === 'after' && percentage >= positionPercentages[0]) {1372this._addClass(this.ticks[i], 'in-selection');1373} else if (this.options.selection === 'before' && percentage <= positionPercentages[0]) {1374this._addClass(this.ticks[i], 'in-selection');1375}1376} else if (percentage >= positionPercentages[0] && percentage <= positionPercentages[1]) {1377this._addClass(this.ticks[i], 'in-selection');1378}1379
1380if (this.tickLabels[i]) {1381this.tickLabels[i].style[styleSize] = labelSize + "px";1382
1383if (this.options.orientation !== 'vertical' && this.options.ticks_positions[i] !== undefined) {1384this.tickLabels[i].style.position = 'absolute';1385this.tickLabels[i].style[this.stylePos] = percentage + "%";1386this.tickLabels[i].style[styleMargin] = -labelSize / 2 + 'px';1387} else if (this.options.orientation === 'vertical') {1388if (this.options.rtl) {1389this.tickLabels[i].style['marginRight'] = this.sliderElem.offsetWidth + "px";1390} else {1391this.tickLabels[i].style['marginLeft'] = this.sliderElem.offsetWidth + "px";1392}1393this.tickLabelContainer.style[styleMargin] = this.sliderElem.offsetWidth / 2 * -1 + 'px';1394}1395
1396/* Set class labels to indicate tick labels are in the selection or selected */1397this._removeClass(this.tickLabels[i], 'label-in-selection label-is-selection');1398if (!this.options.range) {1399if (this.options.selection === 'after' && percentage >= positionPercentages[0]) {1400this._addClass(this.tickLabels[i], 'label-in-selection');1401} else if (this.options.selection === 'before' && percentage <= positionPercentages[0]) {1402this._addClass(this.tickLabels[i], 'label-in-selection');1403}1404if (percentage === positionPercentages[0]) {1405this._addClass(this.tickLabels[i], 'label-is-selection');1406}1407} else if (percentage >= positionPercentages[0] && percentage <= positionPercentages[1]) {1408this._addClass(this.tickLabels[i], 'label-in-selection');1409if (percentage === positionPercentages[0] || positionPercentages[1]) {1410this._addClass(this.tickLabels[i], 'label-is-selection');1411}1412}1413}1414}1415}1416
1417var formattedTooltipVal;1418
1419if (this.options.range) {1420formattedTooltipVal = this.options.formatter(this._state.value);1421this._setText(this.tooltipInner, formattedTooltipVal);1422this.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0]) / 2 + "%";1423
1424var innerTooltipMinText = this.options.formatter(this._state.value[0]);1425this._setText(this.tooltipInner_min, innerTooltipMinText);1426
1427var innerTooltipMaxText = this.options.formatter(this._state.value[1]);1428this._setText(this.tooltipInner_max, innerTooltipMaxText);1429
1430this.tooltip_min.style[this.stylePos] = positionPercentages[0] + "%";1431
1432this.tooltip_max.style[this.stylePos] = positionPercentages[1] + "%";1433} else {1434formattedTooltipVal = this.options.formatter(this._state.value[0]);1435this._setText(this.tooltipInner, formattedTooltipVal);1436
1437this.tooltip.style[this.stylePos] = positionPercentages[0] + "%";1438}1439
1440if (this.options.orientation === 'vertical') {1441this.trackLow.style.top = '0';1442this.trackLow.style.height = Math.min(positionPercentages[0], positionPercentages[1]) + '%';1443
1444this.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) + '%';1445this.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';1446
1447this.trackHigh.style.bottom = '0';1448this.trackHigh.style.height = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';1449} else {1450if (this.stylePos === 'right') {1451this.trackLow.style.right = '0';1452} else {1453this.trackLow.style.left = '0';1454}1455this.trackLow.style.width = Math.min(positionPercentages[0], positionPercentages[1]) + '%';1456
1457if (this.stylePos === 'right') {1458this.trackSelection.style.right = Math.min(positionPercentages[0], positionPercentages[1]) + '%';1459} else {1460this.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) + '%';1461}1462this.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';1463
1464if (this.stylePos === 'right') {1465this.trackHigh.style.left = '0';1466} else {1467this.trackHigh.style.right = '0';1468}1469this.trackHigh.style.width = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';1470
1471var offset_min = this.tooltip_min.getBoundingClientRect();1472var offset_max = this.tooltip_max.getBoundingClientRect();1473
1474if (this.options.tooltip_position === 'bottom') {1475if (offset_min.right > offset_max.left) {1476this._removeClass(this.tooltip_max, 'bs-tooltip-bottom');1477this._addClass(this.tooltip_max, 'bs-tooltip-top');1478this.tooltip_max.style.top = '';1479this.tooltip_max.style.bottom = 22 + 'px';1480} else {1481this._removeClass(this.tooltip_max, 'bs-tooltip-top');1482this._addClass(this.tooltip_max, 'bs-tooltip-bottom');1483this.tooltip_max.style.top = this.tooltip_min.style.top;1484this.tooltip_max.style.bottom = '';1485}1486} else {1487if (offset_min.right > offset_max.left) {1488this._removeClass(this.tooltip_max, 'bs-tooltip-top');1489this._addClass(this.tooltip_max, 'bs-tooltip-bottom');1490this.tooltip_max.style.top = 18 + 'px';1491} else {1492this._removeClass(this.tooltip_max, 'bs-tooltip-bottom');1493this._addClass(this.tooltip_max, 'bs-tooltip-top');1494this.tooltip_max.style.top = this.tooltip_min.style.top;1495}1496}1497}1498},1499_createHighlightRange: function _createHighlightRange(start, end) {1500if (this._isHighlightRange(start, end)) {1501if (start > end) {1502return { 'start': end, 'size': start - end };1503}1504return { 'start': start, 'size': end - start };1505}1506return null;1507},1508_isHighlightRange: function _isHighlightRange(start, end) {1509if (0 <= start && start <= 100 && 0 <= end && end <= 100) {1510return true;1511} else {1512return false;1513}1514},1515_resize: function _resize(ev) {1516/*jshint unused:false*/1517this._state.offset = this._offset(this.sliderElem);1518this._state.size = this.sliderElem[this.sizePos];1519this._layout();1520},1521_removeProperty: function _removeProperty(element, prop) {1522if (element.style.removeProperty) {1523element.style.removeProperty(prop);1524} else {1525element.style.removeAttribute(prop);1526}1527},1528_mousedown: function _mousedown(ev) {1529if (!this._state.enabled) {1530return false;1531}1532
1533if (ev.preventDefault) {1534ev.preventDefault();1535}1536
1537this._state.offset = this._offset(this.sliderElem);1538this._state.size = this.sliderElem[this.sizePos];1539
1540var percentage = this._getPercentage(ev);1541
1542if (this.options.range) {1543var diff1 = Math.abs(this._state.percentage[0] - percentage);1544var diff2 = Math.abs(this._state.percentage[1] - percentage);1545this._state.dragged = diff1 < diff2 ? 0 : 1;1546this._adjustPercentageForRangeSliders(percentage);1547} else {1548this._state.dragged = 0;1549}1550
1551this._state.percentage[this._state.dragged] = percentage;1552
1553if (this.touchCapable) {1554document.removeEventListener("touchmove", this.mousemove, false);1555document.removeEventListener("touchend", this.mouseup, false);1556}1557
1558if (this.mousemove) {1559document.removeEventListener("mousemove", this.mousemove, false);1560}1561if (this.mouseup) {1562document.removeEventListener("mouseup", this.mouseup, false);1563}1564
1565this.mousemove = this._mousemove.bind(this);1566this.mouseup = this._mouseup.bind(this);1567
1568if (this.touchCapable) {1569// Touch: Bind touch events:1570document.addEventListener("touchmove", this.mousemove, false);1571document.addEventListener("touchend", this.mouseup, false);1572}1573// Bind mouse events:1574document.addEventListener("mousemove", this.mousemove, false);1575document.addEventListener("mouseup", this.mouseup, false);1576
1577this._state.inDrag = true;1578var newValue = this._calculateValue();1579
1580this._trigger('slideStart', newValue);1581
1582this.setValue(newValue, false, true);1583
1584ev.returnValue = false;1585
1586if (this.options.focus) {1587this._triggerFocusOnHandle(this._state.dragged);1588}1589
1590return true;1591},1592_touchstart: function _touchstart(ev) {1593this._mousedown(ev);1594},1595_triggerFocusOnHandle: function _triggerFocusOnHandle(handleIdx) {1596if (handleIdx === 0) {1597this.handle1.focus();1598}1599if (handleIdx === 1) {1600this.handle2.focus();1601}1602},1603_keydown: function _keydown(handleIdx, ev) {1604if (!this._state.enabled) {1605return false;1606}1607
1608var dir;1609switch (ev.keyCode) {1610case 37: // left1611case 40:1612// down1613dir = -1;1614break;1615case 39: // right1616case 38:1617// up1618dir = 1;1619break;1620}1621if (!dir) {1622return;1623}1624
1625// use natural arrow keys instead of from min to max1626if (this.options.natural_arrow_keys) {1627var isHorizontal = this.options.orientation === 'horizontal';1628var isVertical = this.options.orientation === 'vertical';1629var isRTL = this.options.rtl;1630var isReversed = this.options.reversed;1631
1632if (isHorizontal) {1633if (isRTL) {1634if (!isReversed) {1635dir = -dir;1636}1637} else {1638if (isReversed) {1639dir = -dir;1640}1641}1642} else if (isVertical) {1643if (!isReversed) {1644dir = -dir;1645}1646}1647}1648
1649var val;1650if (this.ticksAreValid && this.options.lock_to_ticks) {1651var index = void 0;1652// Find tick index that handle 1/2 is currently on1653index = this.options.ticks.indexOf(this._state.value[handleIdx]);1654if (index === -1) {1655// Set default to first tick1656index = 0;1657window.console.warn('(lock_to_ticks) _keydown: index should not be -1');1658}1659index += dir;1660index = Math.max(0, Math.min(this.options.ticks.length - 1, index));1661val = this.options.ticks[index];1662} else {1663val = this._state.value[handleIdx] + dir * this.options.step;1664}1665var percentage = this._toPercentage(val);1666this._state.keyCtrl = handleIdx;1667if (this.options.range) {1668this._adjustPercentageForRangeSliders(percentage);1669var val1 = !this._state.keyCtrl ? val : this._state.value[0];1670var val2 = this._state.keyCtrl ? val : this._state.value[1];1671// Restrict values within limits1672val = [Math.max(this.options.min, Math.min(this.options.max, val1)), Math.max(this.options.min, Math.min(this.options.max, val2))];1673} else {1674val = Math.max(this.options.min, Math.min(this.options.max, val));1675}1676
1677this._trigger('slideStart', val);1678
1679this.setValue(val, true, true);1680
1681this._trigger('slideStop', val);1682
1683this._pauseEvent(ev);1684delete this._state.keyCtrl;1685
1686return false;1687},1688_pauseEvent: function _pauseEvent(ev) {1689if (ev.stopPropagation) {1690ev.stopPropagation();1691}1692if (ev.preventDefault) {1693ev.preventDefault();1694}1695ev.cancelBubble = true;1696ev.returnValue = false;1697},1698_mousemove: function _mousemove(ev) {1699if (!this._state.enabled) {1700return false;1701}1702
1703var percentage = this._getPercentage(ev);1704this._adjustPercentageForRangeSliders(percentage);1705this._state.percentage[this._state.dragged] = percentage;1706
1707var val = this._calculateValue(true);1708this.setValue(val, true, true);1709
1710return false;1711},1712_touchmove: function _touchmove(ev) {1713if (ev.changedTouches === undefined) {1714return;1715}1716
1717// Prevent page from scrolling and only drag the slider1718if (ev.preventDefault) {1719ev.preventDefault();1720}1721},1722_adjustPercentageForRangeSliders: function _adjustPercentageForRangeSliders(percentage) {1723if (this.options.range) {1724var precision = this._getNumDigitsAfterDecimalPlace(percentage);1725precision = precision ? precision - 1 : 0;1726var percentageWithAdjustedPrecision = this._applyToFixedAndParseFloat(percentage, precision);1727if (this._state.dragged === 0 && this._applyToFixedAndParseFloat(this._state.percentage[1], precision) < percentageWithAdjustedPrecision) {1728this._state.percentage[0] = this._state.percentage[1];1729this._state.dragged = 1;1730} else if (this._state.dragged === 1 && this._applyToFixedAndParseFloat(this._state.percentage[0], precision) > percentageWithAdjustedPrecision) {1731this._state.percentage[1] = this._state.percentage[0];1732this._state.dragged = 0;1733} else if (this._state.keyCtrl === 0 && this._toPercentage(this._state.value[1]) < percentage) {1734this._state.percentage[0] = this._state.percentage[1];1735this._state.keyCtrl = 1;1736this.handle2.focus();1737} else if (this._state.keyCtrl === 1 && this._toPercentage(this._state.value[0]) > percentage) {1738this._state.percentage[1] = this._state.percentage[0];1739this._state.keyCtrl = 0;1740this.handle1.focus();1741}1742}1743},1744_mouseup: function _mouseup(ev) {1745if (!this._state.enabled) {1746return false;1747}1748
1749var percentage = this._getPercentage(ev);1750this._adjustPercentageForRangeSliders(percentage);1751this._state.percentage[this._state.dragged] = percentage;1752
1753if (this.touchCapable) {1754// Touch: Unbind touch event handlers:1755document.removeEventListener("touchmove", this.mousemove, false);1756document.removeEventListener("touchend", this.mouseup, false);1757}1758// Unbind mouse event handlers:1759document.removeEventListener("mousemove", this.mousemove, false);1760document.removeEventListener("mouseup", this.mouseup, false);1761
1762this._state.inDrag = false;1763if (this._state.over === false) {1764this._hideTooltip();1765}1766var val = this._calculateValue(true);1767
1768this.setValue(val, false, true);1769this._trigger('slideStop', val);1770
1771// No longer need 'dragged' after mouse up1772this._state.dragged = null;1773
1774return false;1775},1776_setValues: function _setValues(index, val) {1777var comp = 0 === index ? 0 : 100;1778if (this._state.percentage[index] !== comp) {1779val.data[index] = this._toValue(this._state.percentage[index]);1780val.data[index] = this._applyPrecision(val.data[index]);1781}1782},1783_calculateValue: function _calculateValue(snapToClosestTick) {1784var val = {};1785if (this.options.range) {1786val.data = [this.options.min, this.options.max];1787this._setValues(0, val);1788this._setValues(1, val);1789if (snapToClosestTick) {1790val.data[0] = this._snapToClosestTick(val.data[0]);1791val.data[1] = this._snapToClosestTick(val.data[1]);1792}1793} else {1794val.data = this._toValue(this._state.percentage[0]);1795val.data = parseFloat(val.data);1796val.data = this._applyPrecision(val.data);1797if (snapToClosestTick) {1798val.data = this._snapToClosestTick(val.data);1799}1800}1801
1802return val.data;1803},1804_snapToClosestTick: function _snapToClosestTick(val) {1805var min = [val, Infinity];1806for (var i = 0; i < this.options.ticks.length; i++) {1807var diff = Math.abs(this.options.ticks[i] - val);1808if (diff <= min[1]) {1809min = [this.options.ticks[i], diff];1810}1811}1812if (min[1] <= this.options.ticks_snap_bounds) {1813return min[0];1814}1815return val;1816},1817
1818_applyPrecision: function _applyPrecision(val) {1819var precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.options.step);1820return this._applyToFixedAndParseFloat(val, precision);1821},1822_getNumDigitsAfterDecimalPlace: function _getNumDigitsAfterDecimalPlace(num) {1823var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);1824if (!match) {1825return 0;1826}1827return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));1828},1829_applyToFixedAndParseFloat: function _applyToFixedAndParseFloat(num, toFixedInput) {1830var truncatedNum = num.toFixed(toFixedInput);1831return parseFloat(truncatedNum);1832},1833/*1834Credits to Mike Samuel for the following method!
1835Source: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number
1836*/
1837_getPercentage: function _getPercentage(ev) {1838if (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove' || ev.type === 'touchend')) {1839ev = ev.changedTouches[0];1840}1841
1842var eventPosition = ev[this.mousePos];1843var sliderOffset = this._state.offset[this.stylePos];1844var distanceToSlide = eventPosition - sliderOffset;1845if (this.stylePos === 'right') {1846distanceToSlide = -distanceToSlide;1847}1848// Calculate what percent of the length the slider handle has slid1849var percentage = distanceToSlide / this._state.size * 100;1850percentage = Math.round(percentage / this._state.percentage[2]) * this._state.percentage[2];1851if (this.options.reversed) {1852percentage = 100 - percentage;1853}1854
1855// Make sure the percent is within the bounds of the slider.1856// 0% corresponds to the 'min' value of the slide1857// 100% corresponds to the 'max' value of the slide1858return Math.max(0, Math.min(100, percentage));1859},1860_validateInputValue: function _validateInputValue(val) {1861if (!isNaN(+val)) {1862return +val;1863} else if (Array.isArray(val)) {1864this._validateArray(val);1865return val;1866} else {1867throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(val));1868}1869},1870_validateArray: function _validateArray(val) {1871for (var i = 0; i < val.length; i++) {1872var input = val[i];1873if (typeof input !== 'number') {1874throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(input));1875}1876}1877},1878_setDataVal: function _setDataVal(val) {1879this.element.setAttribute('data-value', val);1880this.element.setAttribute('value', val);1881this.element.value = val;1882},1883_trigger: function _trigger(evt, val) {1884val = val || val === 0 ? val : undefined;1885
1886var callbackFnArray = this.eventToCallbackMap[evt];1887if (callbackFnArray && callbackFnArray.length) {1888for (var i = 0; i < callbackFnArray.length; i++) {1889var callbackFn = callbackFnArray[i];1890callbackFn(val);1891}1892}1893
1894/* If JQuery exists, trigger JQuery events */1895if ($) {1896this._triggerJQueryEvent(evt, val);1897}1898},1899_triggerJQueryEvent: function _triggerJQueryEvent(evt, val) {1900var eventData = {1901type: evt,1902value: val1903};1904this.$element.trigger(eventData);1905this.$sliderElem.trigger(eventData);1906},1907_unbindJQueryEventHandlers: function _unbindJQueryEventHandlers() {1908this.$element.off();1909this.$sliderElem.off();1910},1911_setText: function _setText(element, text) {1912if (typeof element.textContent !== "undefined") {1913element.textContent = text;1914} else if (typeof element.innerText !== "undefined") {1915element.innerText = text;1916}1917},1918_removeClass: function _removeClass(element, classString) {1919var classes = classString.split(" ");1920var newClasses = element.className;1921
1922for (var i = 0; i < classes.length; i++) {1923var classTag = classes[i];1924var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)");1925newClasses = newClasses.replace(regex, " ");1926}1927
1928element.className = newClasses.trim();1929},1930_addClass: function _addClass(element, classString) {1931var classes = classString.split(" ");1932var newClasses = element.className;1933
1934for (var i = 0; i < classes.length; i++) {1935var classTag = classes[i];1936var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)");1937var ifClassExists = regex.test(newClasses);1938
1939if (!ifClassExists) {1940newClasses += " " + classTag;1941}1942}1943
1944element.className = newClasses.trim();1945},1946_offsetLeft: function _offsetLeft(obj) {1947return obj.getBoundingClientRect().left;1948},1949_offsetRight: function _offsetRight(obj) {1950return obj.getBoundingClientRect().right;1951},1952_offsetTop: function _offsetTop(obj) {1953var offsetTop = obj.offsetTop;1954while ((obj = obj.offsetParent) && !isNaN(obj.offsetTop)) {1955offsetTop += obj.offsetTop;1956if (obj.tagName !== 'BODY') {1957offsetTop -= obj.scrollTop;1958}1959}1960return offsetTop;1961},1962_offset: function _offset(obj) {1963return {1964left: this._offsetLeft(obj),1965right: this._offsetRight(obj),1966top: this._offsetTop(obj)1967};1968},1969_css: function _css(elementRef, styleName, value) {1970if ($) {1971$.style(elementRef, styleName, value);1972} else {1973var style = styleName.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function (all, letter) {1974return letter.toUpperCase();1975});1976elementRef.style[style] = value;1977}1978},1979_toValue: function _toValue(percentage) {1980return this.options.scale.toValue.apply(this, [percentage]);1981},1982_toPercentage: function _toPercentage(value) {1983return this.options.scale.toPercentage.apply(this, [value]);1984},1985_setTooltipPosition: function _setTooltipPosition() {1986var tooltips = [this.tooltip, this.tooltip_min, this.tooltip_max];1987if (this.options.orientation === 'vertical') {1988var tooltipPos;1989if (this.options.tooltip_position) {1990tooltipPos = this.options.tooltip_position;1991} else {1992if (this.options.rtl) {1993tooltipPos = 'left';1994} else {1995tooltipPos = 'right';1996}1997}1998var oppositeSide = tooltipPos === 'left' ? 'right' : 'left';1999tooltips.forEach(function (tooltip) {2000this._addClass(tooltip, 'bs-tooltip-' + tooltipPos);2001tooltip.style[oppositeSide] = '100%';2002}.bind(this));2003} else if (this.options.tooltip_position === 'bottom') {2004tooltips.forEach(function (tooltip) {2005this._addClass(tooltip, 'bs-tooltip-bottom');2006tooltip.style.top = 22 + 'px';2007}.bind(this));2008} else {2009tooltips.forEach(function (tooltip) {2010this._addClass(tooltip, 'bs-tooltip-top');2011tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px';2012}.bind(this));2013}2014},2015_getClosestTickIndex: function _getClosestTickIndex(val) {2016var difference = Math.abs(val - this.options.ticks[0]);2017var index = 0;2018for (var i = 0; i < this.options.ticks.length; ++i) {2019var d = Math.abs(val - this.options.ticks[i]);2020if (d < difference) {2021difference = d;2022index = i;2023}2024}2025return index;2026},2027/**2028* Attempts to find the index in `ticks[]` the slider values are set at.
2029* The indexes can be -1 to indicate the slider value is not set at a value in `ticks[]`.
2030*/
2031_setTickIndex: function _setTickIndex() {2032if (this.ticksAreValid) {2033this._state.tickIndex = [this.options.ticks.indexOf(this._state.value[0]), this.options.ticks.indexOf(this._state.value[1])];2034}2035}2036};2037
2038/*********************************2039Attach to global namespace
2040*********************************/
2041if ($ && $.fn) {2042if (!$.fn.slider) {2043$.bridget(NAMESPACE_MAIN, Slider);2044autoRegisterNamespace = NAMESPACE_MAIN;2045} else {2046if (windowIsDefined) {2047window.console.warn("bootstrap-slider.js - WARNING: $.fn.slider namespace is already bound. Use the $.fn.bootstrapSlider namespace instead.");2048}2049autoRegisterNamespace = NAMESPACE_ALTERNATE;2050}2051$.bridget(NAMESPACE_ALTERNATE, Slider);2052
2053// Auto-Register data-provide="slider" Elements2054$(function () {2055$("input[data-provide=slider]")[autoRegisterNamespace]();2056});2057}2058})($);2059
2060return Slider;2061});2062