/*! ========================================================= 
 | 
 * bootstrap-slider.js 
 | 
 * 
 | 
 * Maintainers: 
 | 
 *        Kyle Kemp 
 | 
 *            - Twitter: @seiyria 
 | 
 *            - Github:  seiyria 
 | 
 *        Rohit Kalkur 
 | 
 *            - Twitter: @Rovolutionary 
 | 
 *            - Github:  rovolution 
 | 
 * 
 | 
 * ========================================================= 
 | 
 * 
 | 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 | 
 * you may not use this file except in compliance with the License. 
 | 
 * You may obtain a copy of the License at 
 | 
 * 
 | 
 * http://www.apache.org/licenses/LICENSE-2.0 
 | 
 * 
 | 
 * Unless required by applicable law or agreed to in writing, software 
 | 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 | 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 | 
 * See the License for the specific language governing permissions and 
 | 
 * limitations under the License. 
 | 
 * ========================================================= */ 
 | 
  
 | 
  
 | 
/** 
 | 
 * Bridget makes jQuery widgets 
 | 
 * v1.0.1 
 | 
 * MIT license 
 | 
 */ 
 | 
  
 | 
(function(root, factory) { 
 | 
    if(typeof define === "function" && define.amd) { 
 | 
        define(["jquery"], factory); 
 | 
    } 
 | 
    else if(typeof module === "object" && module.exports) { 
 | 
        var jQuery; 
 | 
        try { 
 | 
            jQuery = require("jquery"); 
 | 
        } 
 | 
        catch (err) { 
 | 
            jQuery = null; 
 | 
        } 
 | 
        module.exports = factory(jQuery); 
 | 
    } 
 | 
    else { 
 | 
        root.Slider = factory(root.jQuery); 
 | 
    } 
 | 
}(this, function($) { 
 | 
    // Reference to Slider constructor 
 | 
    var Slider; 
 | 
  
 | 
  
 | 
    (function( $ ) { 
 | 
  
 | 
        'use strict'; 
 | 
  
 | 
        // -------------------------- utils -------------------------- // 
 | 
  
 | 
        var slice = Array.prototype.slice; 
 | 
  
 | 
        function noop() {} 
 | 
  
 | 
        // -------------------------- definition -------------------------- // 
 | 
  
 | 
        function defineBridget( $ ) { 
 | 
  
 | 
            // bail if no jQuery 
 | 
            if ( !$ ) { 
 | 
                return; 
 | 
            } 
 | 
  
 | 
            // -------------------------- addOptionMethod -------------------------- // 
 | 
  
 | 
            /** 
 | 
             * adds option method -> $().plugin('option', {...}) 
 | 
             * @param {Function} PluginClass - constructor class 
 | 
             */ 
 | 
            function addOptionMethod( PluginClass ) { 
 | 
                // don't overwrite original option method 
 | 
                if ( PluginClass.prototype.option ) { 
 | 
                    return; 
 | 
                } 
 | 
  
 | 
              // option setter 
 | 
              PluginClass.prototype.option = function( opts ) { 
 | 
                // bail out if not an object 
 | 
                if ( !$.isPlainObject( opts ) ){ 
 | 
                  return; 
 | 
                } 
 | 
                this.options = $.extend( true, this.options, opts ); 
 | 
              }; 
 | 
            } 
 | 
  
 | 
  
 | 
            // -------------------------- plugin bridge -------------------------- // 
 | 
  
 | 
            // helper function for logging errors 
 | 
            // $.error breaks jQuery chaining 
 | 
            var logError = typeof console === 'undefined' ? noop : 
 | 
              function( message ) { 
 | 
                console.error( message ); 
 | 
              }; 
 | 
  
 | 
            /** 
 | 
             * jQuery plugin bridge, access methods like $elem.plugin('method') 
 | 
             * @param {String} namespace - plugin name 
 | 
             * @param {Function} PluginClass - constructor class 
 | 
             */ 
 | 
            function bridge( namespace, PluginClass ) { 
 | 
              // add to jQuery fn namespace 
 | 
              $.fn[ namespace ] = function( options ) { 
 | 
                if ( typeof options === 'string' ) { 
 | 
                  // call plugin method when first argument is a string 
 | 
                  // get arguments for method 
 | 
                  var args = slice.call( arguments, 1 ); 
 | 
  
 | 
                  for ( var i=0, len = this.length; i < len; i++ ) { 
 | 
                    var elem = this[i]; 
 | 
                    var instance = $.data( elem, namespace ); 
 | 
                    if ( !instance ) { 
 | 
                      logError( "cannot call methods on " + namespace + " prior to initialization; " + 
 | 
                        "attempted to call '" + options + "'" ); 
 | 
                      continue; 
 | 
                    } 
 | 
                    if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { 
 | 
                      logError( "no such method '" + options + "' for " + namespace + " instance" ); 
 | 
                      continue; 
 | 
                    } 
 | 
  
 | 
                    // trigger method with arguments 
 | 
                    var returnValue = instance[ options ].apply( instance, args); 
 | 
  
 | 
                    // break look and return first value if provided 
 | 
                    if ( returnValue !== undefined && returnValue !== instance) { 
 | 
                      return returnValue; 
 | 
                    } 
 | 
                  } 
 | 
                  // return this if no return value 
 | 
                  return this; 
 | 
                } else { 
 | 
                  var objects = this.map( function() { 
 | 
                    var instance = $.data( this, namespace ); 
 | 
                    if ( instance ) { 
 | 
                      // apply options & init 
 | 
                      instance.option( options ); 
 | 
                      instance._init(); 
 | 
                    } else { 
 | 
                      // initialize new instance 
 | 
                      instance = new PluginClass( this, options ); 
 | 
                      $.data( this, namespace, instance ); 
 | 
                    } 
 | 
                    return $(this); 
 | 
                  }); 
 | 
  
 | 
                  if(!objects || objects.length > 1) { 
 | 
                      return objects; 
 | 
                  } else { 
 | 
                      return objects[0]; 
 | 
                  } 
 | 
                } 
 | 
              }; 
 | 
  
 | 
            } 
 | 
  
 | 
            // -------------------------- bridget -------------------------- // 
 | 
  
 | 
            /** 
 | 
             * converts a Prototypical class into a proper jQuery plugin 
 | 
             *   the class must have a ._init method 
 | 
             * @param {String} namespace - plugin name, used in $().pluginName 
 | 
             * @param {Function} PluginClass - constructor class 
 | 
             */ 
 | 
            $.bridget = function( namespace, PluginClass ) { 
 | 
              addOptionMethod( PluginClass ); 
 | 
              bridge( namespace, PluginClass ); 
 | 
            }; 
 | 
  
 | 
            return $.bridget; 
 | 
  
 | 
        } 
 | 
  
 | 
          // get jquery from browser global 
 | 
          defineBridget( $ ); 
 | 
  
 | 
    })( $ ); 
 | 
  
 | 
  
 | 
    /************************************************* 
 | 
  
 | 
            BOOTSTRAP-SLIDER SOURCE CODE 
 | 
  
 | 
    **************************************************/ 
 | 
  
 | 
    (function($) { 
 | 
  
 | 
        var ErrorMsgs = { 
 | 
            formatInvalidInputErrorMsg : function(input) { 
 | 
                return "Invalid input value '" + input + "' passed in"; 
 | 
            }, 
 | 
            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" 
 | 
        }; 
 | 
  
 | 
        var SliderScale = { 
 | 
            linear: { 
 | 
                toValue: function(percentage) { 
 | 
                    var rawValue = percentage/100 * (this.options.max - this.options.min); 
 | 
                    if (this.options.ticks_positions.length > 0) { 
 | 
                        var minv, maxv, minp, maxp = 0; 
 | 
                        for (var i = 0; i < this.options.ticks_positions.length; i++) { 
 | 
                            if (percentage <= this.options.ticks_positions[i]) { 
 | 
                                minv = (i > 0) ? this.options.ticks[i-1] : 0; 
 | 
                                minp = (i > 0) ? this.options.ticks_positions[i-1] : 0; 
 | 
                                maxv = this.options.ticks[i]; 
 | 
                                maxp = this.options.ticks_positions[i]; 
 | 
  
 | 
                                break; 
 | 
                            } 
 | 
                        } 
 | 
                        if (i > 0) { 
 | 
                            var partialPercentage = (percentage - minp) / (maxp - minp); 
 | 
                            rawValue = minv + partialPercentage * (maxv - minv); 
 | 
                        } 
 | 
                    } 
 | 
  
 | 
                    var value = this.options.min + Math.round(rawValue / this.options.step) * this.options.step; 
 | 
                    if (value < this.options.min) { 
 | 
                        return this.options.min; 
 | 
                    } else if (value > this.options.max) { 
 | 
                        return this.options.max; 
 | 
                    } else { 
 | 
                        return value; 
 | 
                    } 
 | 
                }, 
 | 
                toPercentage: function(value) { 
 | 
                    if (this.options.max === this.options.min) { 
 | 
                        return 0; 
 | 
                    } 
 | 
  
 | 
                    if (this.options.ticks_positions.length > 0) { 
 | 
                        var minv, maxv, minp, maxp = 0; 
 | 
                        for (var i = 0; i < this.options.ticks.length; i++) { 
 | 
                            if (value  <= this.options.ticks[i]) { 
 | 
                                minv = (i > 0) ? this.options.ticks[i-1] : 0; 
 | 
                                minp = (i > 0) ? this.options.ticks_positions[i-1] : 0; 
 | 
                                maxv = this.options.ticks[i]; 
 | 
                                maxp = this.options.ticks_positions[i]; 
 | 
  
 | 
                                break; 
 | 
                            } 
 | 
                        } 
 | 
                        if (i > 0) { 
 | 
                            var partialPercentage = (value - minv) / (maxv - minv); 
 | 
                            return minp + partialPercentage * (maxp - minp); 
 | 
                        } 
 | 
                    } 
 | 
  
 | 
                    return 100 * (value - this.options.min) / (this.options.max - this.options.min); 
 | 
                } 
 | 
            }, 
 | 
  
 | 
            logarithmic: { 
 | 
                /* Based on http://stackoverflow.com/questions/846221/logarithmic-slider */ 
 | 
                toValue: function(percentage) { 
 | 
                    var min = (this.options.min === 0) ? 0 : Math.log(this.options.min); 
 | 
                    var max = Math.log(this.options.max); 
 | 
                    var value = Math.exp(min + (max - min) * percentage / 100); 
 | 
                    value = this.options.min + Math.round((value - this.options.min) / this.options.step) * this.options.step; 
 | 
                    /* Rounding to the nearest step could exceed the min or 
 | 
                     * max, so clip to those values. */ 
 | 
                    if (value < this.options.min) { 
 | 
                        return this.options.min; 
 | 
                    } else if (value > this.options.max) { 
 | 
                        return this.options.max; 
 | 
                    } else { 
 | 
                        return value; 
 | 
                    } 
 | 
                }, 
 | 
                toPercentage: function(value) { 
 | 
                    if (this.options.max === this.options.min) { 
 | 
                        return 0; 
 | 
                    } else { 
 | 
                        var max = Math.log(this.options.max); 
 | 
                        var min = this.options.min === 0 ? 0 : Math.log(this.options.min); 
 | 
                        var v = value === 0 ? 0 : Math.log(value); 
 | 
                        return 100 * (v - min) / (max - min); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        }; 
 | 
  
 | 
  
 | 
        /************************************************* 
 | 
  
 | 
                            CONSTRUCTOR 
 | 
  
 | 
        **************************************************/ 
 | 
        Slider = function(element, options) { 
 | 
            createNewSlider.call(this, element, options); 
 | 
            return this; 
 | 
        }; 
 | 
  
 | 
        function createNewSlider(element, options) { 
 | 
  
 | 
            /* 
 | 
                The internal state object is used to store data about the current 'state' of slider. 
 | 
  
 | 
                This includes values such as the `value`, `enabled`, etc... 
 | 
            */ 
 | 
            this._state = { 
 | 
                value: null, 
 | 
                enabled: null, 
 | 
                offset: null, 
 | 
                size: null, 
 | 
                percentage: null, 
 | 
                inDrag: false, 
 | 
                over: false 
 | 
            }; 
 | 
  
 | 
  
 | 
            if(typeof element === "string") { 
 | 
                this.element = document.querySelector(element); 
 | 
            } else if(element instanceof HTMLElement) { 
 | 
                this.element = element; 
 | 
            } 
 | 
  
 | 
            /************************************************* 
 | 
  
 | 
                            Process Options 
 | 
  
 | 
            **************************************************/ 
 | 
            options = options ? options : {}; 
 | 
            var optionTypes = Object.keys(this.defaultOptions); 
 | 
  
 | 
            for(var i = 0; i < optionTypes.length; i++) { 
 | 
                var optName = optionTypes[i]; 
 | 
  
 | 
                // First check if an option was passed in via the constructor 
 | 
                var val = options[optName]; 
 | 
                // If no data attrib, then check data atrributes 
 | 
                val = (typeof val !== 'undefined') ? val : getDataAttrib(this.element, optName); 
 | 
                // Finally, if nothing was specified, use the defaults 
 | 
                val = (val !== null) ? val : this.defaultOptions[optName]; 
 | 
  
 | 
                // Set all options on the instance of the Slider 
 | 
                if(!this.options) { 
 | 
                    this.options = {}; 
 | 
                } 
 | 
                this.options[optName] = val; 
 | 
            } 
 | 
  
 | 
            /* 
 | 
                Validate `tooltip_position` against 'orientation` 
 | 
                - if `tooltip_position` is incompatible with orientation, swith it to a default compatible with specified `orientation` 
 | 
                    -- default for "vertical" -> "right" 
 | 
                    -- default for "horizontal" -> "left" 
 | 
            */ 
 | 
            if(this.options.orientation === "vertical" && (this.options.tooltip_position === "top" || this.options.tooltip_position === "bottom")) { 
 | 
  
 | 
                this.options.tooltip_position    = "right"; 
 | 
  
 | 
            } 
 | 
            else if(this.options.orientation === "horizontal" && (this.options.tooltip_position === "left" || this.options.tooltip_position === "right")) { 
 | 
  
 | 
                this.options.tooltip_position    = "top"; 
 | 
  
 | 
            } 
 | 
  
 | 
            function getDataAttrib(element, optName) { 
 | 
                var dataName = "data-slider-" + optName.replace(/_/g, '-'); 
 | 
                var dataValString = element.getAttribute(dataName); 
 | 
  
 | 
                try { 
 | 
                    return JSON.parse(dataValString); 
 | 
                } 
 | 
                catch(err) { 
 | 
                    return dataValString; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            /************************************************* 
 | 
  
 | 
                            Create Markup 
 | 
  
 | 
            **************************************************/ 
 | 
  
 | 
            var origWidth = this.element.style.width; 
 | 
            var updateSlider = false; 
 | 
            var parent = this.element.parentNode; 
 | 
            var sliderTrackSelection; 
 | 
            var sliderTrackLow, sliderTrackHigh; 
 | 
            var sliderMinHandle; 
 | 
            var sliderMaxHandle; 
 | 
  
 | 
            if (this.sliderElem) { 
 | 
                updateSlider = true; 
 | 
            } else { 
 | 
                /* Create elements needed for slider */ 
 | 
                this.sliderElem = document.createElement("div"); 
 | 
                this.sliderElem.className = "slider"; 
 | 
  
 | 
                /* Create slider track elements */ 
 | 
                var sliderTrack = document.createElement("div"); 
 | 
                sliderTrack.className = "slider-track"; 
 | 
  
 | 
                sliderTrackLow = document.createElement("div"); 
 | 
                sliderTrackLow.className = "slider-track-low"; 
 | 
  
 | 
                sliderTrackSelection = document.createElement("div"); 
 | 
                sliderTrackSelection.className = "slider-selection"; 
 | 
  
 | 
                sliderTrackHigh = document.createElement("div"); 
 | 
                sliderTrackHigh.className = "slider-track-high"; 
 | 
  
 | 
                sliderMinHandle = document.createElement("div"); 
 | 
                sliderMinHandle.className = "slider-handle min-slider-handle"; 
 | 
                sliderMinHandle.setAttribute('role', 'slider'); 
 | 
                sliderMinHandle.setAttribute('aria-valuemin', this.options.min); 
 | 
                sliderMinHandle.setAttribute('aria-valuemax', this.options.max); 
 | 
  
 | 
                sliderMaxHandle = document.createElement("div"); 
 | 
                sliderMaxHandle.className = "slider-handle max-slider-handle"; 
 | 
                sliderMaxHandle.setAttribute('role', 'slider'); 
 | 
                sliderMaxHandle.setAttribute('aria-valuemin', this.options.min); 
 | 
                sliderMaxHandle.setAttribute('aria-valuemax', this.options.max); 
 | 
  
 | 
                sliderTrack.appendChild(sliderTrackLow); 
 | 
                sliderTrack.appendChild(sliderTrackSelection); 
 | 
                sliderTrack.appendChild(sliderTrackHigh); 
 | 
  
 | 
                /* Add aria-labelledby to handle's */ 
 | 
                var isLabelledbyArray = Array.isArray(this.options.labelledby); 
 | 
                if (isLabelledbyArray && this.options.labelledby[0]) { 
 | 
                    sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby[0]); 
 | 
                } 
 | 
                if (isLabelledbyArray && this.options.labelledby[1]) { 
 | 
                    sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby[1]); 
 | 
                } 
 | 
                if (!isLabelledbyArray && this.options.labelledby) { 
 | 
                    sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby); 
 | 
                    sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby); 
 | 
                } 
 | 
  
 | 
                /* Create ticks */ 
 | 
                this.ticks = []; 
 | 
                if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { 
 | 
                    for (i = 0; i < this.options.ticks.length; i++) { 
 | 
                        var tick = document.createElement('div'); 
 | 
                        tick.className = 'slider-tick'; 
 | 
  
 | 
                        this.ticks.push(tick); 
 | 
                        sliderTrack.appendChild(tick); 
 | 
                    } 
 | 
  
 | 
                    sliderTrackSelection.className += " tick-slider-selection"; 
 | 
                } 
 | 
  
 | 
                sliderTrack.appendChild(sliderMinHandle); 
 | 
                sliderTrack.appendChild(sliderMaxHandle); 
 | 
  
 | 
                this.tickLabels = []; 
 | 
                if (Array.isArray(this.options.ticks_labels) && this.options.ticks_labels.length > 0) { 
 | 
                    this.tickLabelContainer = document.createElement('div'); 
 | 
                    this.tickLabelContainer.className = 'slider-tick-label-container'; 
 | 
  
 | 
                    for (i = 0; i < this.options.ticks_labels.length; i++) { 
 | 
                        var label = document.createElement('div'); 
 | 
                        var noTickPositionsSpecified = this.options.ticks_positions.length === 0; 
 | 
                        var tickLabelsIndex = (this.options.reversed && noTickPositionsSpecified) ? (this.options.ticks_labels.length - (i + 1)) : i; 
 | 
                        label.className = 'slider-tick-label'; 
 | 
                        label.innerHTML = this.options.ticks_labels[tickLabelsIndex]; 
 | 
  
 | 
                        this.tickLabels.push(label); 
 | 
                        this.tickLabelContainer.appendChild(label); 
 | 
                    } 
 | 
                } 
 | 
  
 | 
  
 | 
                var createAndAppendTooltipSubElements = function(tooltipElem) { 
 | 
                    var arrow = document.createElement("div"); 
 | 
                    arrow.className = "tooltip-arrow"; 
 | 
  
 | 
                    var inner = document.createElement("div"); 
 | 
                    inner.className = "tooltip-inner"; 
 | 
  
 | 
                    tooltipElem.appendChild(arrow); 
 | 
                    tooltipElem.appendChild(inner); 
 | 
  
 | 
                }; 
 | 
  
 | 
                /* Create tooltip elements */ 
 | 
                var sliderTooltip = document.createElement("div"); 
 | 
                sliderTooltip.className = "tooltip tooltip-main"; 
 | 
                sliderTooltip.setAttribute('role', 'presentation'); 
 | 
                createAndAppendTooltipSubElements(sliderTooltip); 
 | 
  
 | 
                var sliderTooltipMin = document.createElement("div"); 
 | 
                sliderTooltipMin.className = "tooltip tooltip-min"; 
 | 
                sliderTooltipMin.setAttribute('role', 'presentation'); 
 | 
                createAndAppendTooltipSubElements(sliderTooltipMin); 
 | 
  
 | 
                var sliderTooltipMax = document.createElement("div"); 
 | 
                sliderTooltipMax.className = "tooltip tooltip-max"; 
 | 
                sliderTooltipMax.setAttribute('role', 'presentation'); 
 | 
                createAndAppendTooltipSubElements(sliderTooltipMax); 
 | 
  
 | 
  
 | 
                /* Append components to sliderElem */ 
 | 
                this.sliderElem.appendChild(sliderTrack); 
 | 
                this.sliderElem.appendChild(sliderTooltip); 
 | 
                this.sliderElem.appendChild(sliderTooltipMin); 
 | 
                this.sliderElem.appendChild(sliderTooltipMax); 
 | 
  
 | 
                if (this.tickLabelContainer) { 
 | 
                    this.sliderElem.appendChild(this.tickLabelContainer); 
 | 
                } 
 | 
  
 | 
                /* Append slider element to parent container, right before the original <input> element */ 
 | 
                parent.insertBefore(this.sliderElem, this.element); 
 | 
  
 | 
                /* Hide original <input> element */ 
 | 
                this.element.style.display = "none"; 
 | 
            } 
 | 
            /* If JQuery exists, cache JQ references */ 
 | 
            if($) { 
 | 
                this.$element = $(this.element); 
 | 
                this.$sliderElem = $(this.sliderElem); 
 | 
            } 
 | 
  
 | 
            /************************************************* 
 | 
  
 | 
                                Setup 
 | 
  
 | 
            **************************************************/ 
 | 
            this.eventToCallbackMap = {}; 
 | 
            this.sliderElem.id = this.options.id; 
 | 
  
 | 
            this.touchCapable = 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch); 
 | 
  
 | 
            this.tooltip = this.sliderElem.querySelector('.tooltip-main'); 
 | 
            this.tooltipInner = this.tooltip.querySelector('.tooltip-inner'); 
 | 
  
 | 
            this.tooltip_min = this.sliderElem.querySelector('.tooltip-min'); 
 | 
            this.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner'); 
 | 
  
 | 
            this.tooltip_max = this.sliderElem.querySelector('.tooltip-max'); 
 | 
            this.tooltipInner_max= this.tooltip_max.querySelector('.tooltip-inner'); 
 | 
  
 | 
            if (SliderScale[this.options.scale]) { 
 | 
                this.options.scale = SliderScale[this.options.scale]; 
 | 
            } 
 | 
  
 | 
            if (updateSlider === true) { 
 | 
                // Reset classes 
 | 
                this._removeClass(this.sliderElem, 'slider-horizontal'); 
 | 
                this._removeClass(this.sliderElem, 'slider-vertical'); 
 | 
                this._removeClass(this.tooltip, 'hide'); 
 | 
                this._removeClass(this.tooltip_min, 'hide'); 
 | 
                this._removeClass(this.tooltip_max, 'hide'); 
 | 
  
 | 
                // Undo existing inline styles for track 
 | 
                ["left", "top", "width", "height"].forEach(function(prop) { 
 | 
                    this._removeProperty(this.trackLow, prop); 
 | 
                    this._removeProperty(this.trackSelection, prop); 
 | 
                    this._removeProperty(this.trackHigh, prop); 
 | 
                }, this); 
 | 
  
 | 
                // Undo inline styles on handles 
 | 
                [this.handle1, this.handle2].forEach(function(handle) { 
 | 
                    this._removeProperty(handle, 'left'); 
 | 
                    this._removeProperty(handle, 'top'); 
 | 
                }, this); 
 | 
  
 | 
                // Undo inline styles and classes on tooltips 
 | 
                [this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function(tooltip) { 
 | 
                    this._removeProperty(tooltip, 'left'); 
 | 
                    this._removeProperty(tooltip, 'top'); 
 | 
                    this._removeProperty(tooltip, 'margin-left'); 
 | 
                    this._removeProperty(tooltip, 'margin-top'); 
 | 
  
 | 
                    this._removeClass(tooltip, 'right'); 
 | 
                    this._removeClass(tooltip, 'top'); 
 | 
                }, this); 
 | 
            } 
 | 
  
 | 
            if(this.options.orientation === 'vertical') { 
 | 
                this._addClass(this.sliderElem,'slider-vertical'); 
 | 
                this.stylePos = 'top'; 
 | 
                this.mousePos = 'pageY'; 
 | 
                this.sizePos = 'offsetHeight'; 
 | 
            } else { 
 | 
                this._addClass(this.sliderElem, 'slider-horizontal'); 
 | 
                this.sliderElem.style.width = origWidth; 
 | 
                this.options.orientation = 'horizontal'; 
 | 
                this.stylePos = 'left'; 
 | 
                this.mousePos = 'pageX'; 
 | 
                this.sizePos = 'offsetWidth'; 
 | 
  
 | 
            } 
 | 
            this._setTooltipPosition(); 
 | 
            /* In case ticks are specified, overwrite the min and max bounds */ 
 | 
            if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { 
 | 
                    this.options.max = Math.max.apply(Math, this.options.ticks); 
 | 
                    this.options.min = Math.min.apply(Math, this.options.ticks); 
 | 
            } 
 | 
  
 | 
            if (Array.isArray(this.options.value)) { 
 | 
                this.options.range = true; 
 | 
                this._state.value = this.options.value; 
 | 
            } 
 | 
            else if (this.options.range) { 
 | 
                // User wants a range, but value is not an array 
 | 
                this._state.value = [this.options.value, this.options.max]; 
 | 
            } 
 | 
            else { 
 | 
                this._state.value = this.options.value; 
 | 
            } 
 | 
  
 | 
            this.trackLow = sliderTrackLow || this.trackLow; 
 | 
            this.trackSelection = sliderTrackSelection || this.trackSelection; 
 | 
            this.trackHigh = sliderTrackHigh || this.trackHigh; 
 | 
  
 | 
            if (this.options.selection === 'none') { 
 | 
                this._addClass(this.trackLow, 'hide'); 
 | 
                this._addClass(this.trackSelection, 'hide'); 
 | 
                this._addClass(this.trackHigh, 'hide'); 
 | 
            } 
 | 
  
 | 
            this.handle1 = sliderMinHandle || this.handle1; 
 | 
            this.handle2 = sliderMaxHandle || this.handle2; 
 | 
  
 | 
            if (updateSlider === true) { 
 | 
                // Reset classes 
 | 
                this._removeClass(this.handle1, 'round triangle'); 
 | 
                this._removeClass(this.handle2, 'round triangle hide'); 
 | 
  
 | 
                for (i = 0; i < this.ticks.length; i++) { 
 | 
                    this._removeClass(this.ticks[i], 'round triangle hide'); 
 | 
                } 
 | 
            } 
 | 
  
 | 
            var availableHandleModifiers = ['round', 'triangle', 'custom']; 
 | 
            var isValidHandleType = availableHandleModifiers.indexOf(this.options.handle) !== -1; 
 | 
            if (isValidHandleType) { 
 | 
                this._addClass(this.handle1, this.options.handle); 
 | 
                this._addClass(this.handle2, this.options.handle); 
 | 
  
 | 
                for (i = 0; i < this.ticks.length; i++) { 
 | 
                    this._addClass(this.ticks[i], this.options.handle); 
 | 
                } 
 | 
            } 
 | 
  
 | 
            this._state.offset = this._offset(this.sliderElem); 
 | 
            this._state.size = this.sliderElem[this.sizePos]; 
 | 
            this.setValue(this._state.value); 
 | 
  
 | 
            /****************************************** 
 | 
  
 | 
                        Bind Event Listeners 
 | 
  
 | 
            ******************************************/ 
 | 
  
 | 
            // Bind keyboard handlers 
 | 
            this.handle1Keydown = this._keydown.bind(this, 0); 
 | 
            this.handle1.addEventListener("keydown", this.handle1Keydown, false); 
 | 
  
 | 
            this.handle2Keydown = this._keydown.bind(this, 1); 
 | 
            this.handle2.addEventListener("keydown", this.handle2Keydown, false); 
 | 
  
 | 
            this.mousedown = this._mousedown.bind(this); 
 | 
            if (this.touchCapable) { 
 | 
                // Bind touch handlers 
 | 
                this.sliderElem.addEventListener("touchstart", this.mousedown, false); 
 | 
            } 
 | 
            this.sliderElem.addEventListener("mousedown", this.mousedown, false); 
 | 
  
 | 
  
 | 
            // Bind tooltip-related handlers 
 | 
            if(this.options.tooltip === 'hide') { 
 | 
                this._addClass(this.tooltip, 'hide'); 
 | 
                this._addClass(this.tooltip_min, 'hide'); 
 | 
                this._addClass(this.tooltip_max, 'hide'); 
 | 
            } 
 | 
            else if(this.options.tooltip === 'always') { 
 | 
                this._showTooltip(); 
 | 
                this._alwaysShowTooltip = true; 
 | 
            } 
 | 
            else { 
 | 
                this.showTooltip = this._showTooltip.bind(this); 
 | 
                this.hideTooltip = this._hideTooltip.bind(this); 
 | 
  
 | 
                this.sliderElem.addEventListener("mouseenter", this.showTooltip, false); 
 | 
                this.sliderElem.addEventListener("mouseleave", this.hideTooltip, false); 
 | 
  
 | 
                this.handle1.addEventListener("focus", this.showTooltip, false); 
 | 
                this.handle1.addEventListener("blur", this.hideTooltip, false); 
 | 
  
 | 
                this.handle2.addEventListener("focus", this.showTooltip, false); 
 | 
                this.handle2.addEventListener("blur", this.hideTooltip, false); 
 | 
            } 
 | 
  
 | 
            if(this.options.enabled) { 
 | 
                this.enable(); 
 | 
            } else { 
 | 
                this.disable(); 
 | 
            } 
 | 
        } 
 | 
  
 | 
  
 | 
  
 | 
        /************************************************* 
 | 
  
 | 
                    INSTANCE PROPERTIES/METHODS 
 | 
  
 | 
        - Any methods bound to the prototype are considered 
 | 
        part of the plugin's `public` interface 
 | 
  
 | 
        **************************************************/ 
 | 
        Slider.prototype = { 
 | 
            _init: function() {}, // NOTE: Must exist to support bridget 
 | 
  
 | 
            constructor: Slider, 
 | 
  
 | 
            defaultOptions: { 
 | 
                id: "", 
 | 
              min: 0, 
 | 
                max: 10, 
 | 
                step: 1, 
 | 
                precision: 0, 
 | 
                orientation: 'horizontal', 
 | 
                value: 5, 
 | 
                range: false, 
 | 
                selection: 'before', 
 | 
                tooltip: 'show', 
 | 
                tooltip_split: false, 
 | 
                handle: 'round', 
 | 
                reversed: false, 
 | 
                enabled: true, 
 | 
                formatter: function(val) { 
 | 
                    if (Array.isArray(val)) { 
 | 
                        return val[0] + " : " + val[1]; 
 | 
                    } else { 
 | 
                        return val; 
 | 
                    } 
 | 
                }, 
 | 
                natural_arrow_keys: false, 
 | 
                ticks: [], 
 | 
                ticks_positions: [], 
 | 
                ticks_labels: [], 
 | 
                ticks_snap_bounds: 0, 
 | 
                scale: 'linear', 
 | 
                focus: false, 
 | 
                tooltip_position: null, 
 | 
                labelledby: null 
 | 
            }, 
 | 
  
 | 
            getElement: function() { 
 | 
                return this.sliderElem; 
 | 
            }, 
 | 
  
 | 
            getValue: function() { 
 | 
                if (this.options.range) { 
 | 
                    return this._state.value; 
 | 
                } 
 | 
                else { 
 | 
                    return this._state.value[0]; 
 | 
                } 
 | 
            }, 
 | 
  
 | 
            setValue: function(val, triggerSlideEvent, triggerChangeEvent) { 
 | 
                if (!val) { 
 | 
                    val = 0; 
 | 
                } 
 | 
                var oldValue = this.getValue(); 
 | 
                this._state.value = this._validateInputValue(val); 
 | 
                var applyPrecision = this._applyPrecision.bind(this); 
 | 
  
 | 
                if (this.options.range) { 
 | 
                    this._state.value[0] = applyPrecision(this._state.value[0]); 
 | 
                    this._state.value[1] = applyPrecision(this._state.value[1]); 
 | 
  
 | 
                    this._state.value[0] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[0])); 
 | 
                    this._state.value[1] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[1])); 
 | 
                } 
 | 
                else { 
 | 
                    this._state.value = applyPrecision(this._state.value); 
 | 
                    this._state.value = [ Math.max(this.options.min, Math.min(this.options.max, this._state.value))]; 
 | 
                    this._addClass(this.handle2, 'hide'); 
 | 
                    if (this.options.selection === 'after') { 
 | 
                        this._state.value[1] = this.options.max; 
 | 
                    } else { 
 | 
                        this._state.value[1] = this.options.min; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                if (this.options.max > this.options.min) { 
 | 
                    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) 
 | 
                    ]; 
 | 
                } else { 
 | 
                    this._state.percentage = [0, 0, 100]; 
 | 
                } 
 | 
  
 | 
                this._layout(); 
 | 
                var newValue = this.options.range ? this._state.value : this._state.value[0]; 
 | 
  
 | 
                if(triggerSlideEvent === true) { 
 | 
                    this._trigger('slide', newValue); 
 | 
                } 
 | 
                if( (oldValue !== newValue) && (triggerChangeEvent === true) ) { 
 | 
                    this._trigger('change', { 
 | 
                        oldValue: oldValue, 
 | 
                        newValue: newValue 
 | 
                    }); 
 | 
                } 
 | 
                this._setDataVal(newValue); 
 | 
  
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
            destroy: function(){ 
 | 
                // Remove event handlers on slider elements 
 | 
                this._removeSliderEventHandlers(); 
 | 
  
 | 
                // Remove the slider from the DOM 
 | 
                this.sliderElem.parentNode.removeChild(this.sliderElem); 
 | 
                /* Show original <input> element */ 
 | 
                this.element.style.display = ""; 
 | 
  
 | 
                // Clear out custom event bindings 
 | 
                this._cleanUpEventCallbacksMap(); 
 | 
  
 | 
                // Remove data values 
 | 
                this.element.removeAttribute("data"); 
 | 
  
 | 
                // Remove JQuery handlers/data 
 | 
                if($) { 
 | 
                    this._unbindJQueryEventHandlers(); 
 | 
                    this.$element.removeData('slider'); 
 | 
                } 
 | 
            }, 
 | 
  
 | 
            disable: function() { 
 | 
                this._state.enabled = false; 
 | 
                this.handle1.removeAttribute("tabindex"); 
 | 
                this.handle2.removeAttribute("tabindex"); 
 | 
                this._addClass(this.sliderElem, 'slider-disabled'); 
 | 
                this._trigger('slideDisabled'); 
 | 
  
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
            enable: function() { 
 | 
                this._state.enabled = true; 
 | 
                this.handle1.setAttribute("tabindex", 0); 
 | 
                this.handle2.setAttribute("tabindex", 0); 
 | 
                this._removeClass(this.sliderElem, 'slider-disabled'); 
 | 
                this._trigger('slideEnabled'); 
 | 
  
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
            toggle: function() { 
 | 
                if(this._state.enabled) { 
 | 
                    this.disable(); 
 | 
                } else { 
 | 
                    this.enable(); 
 | 
                } 
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
            isEnabled: function() { 
 | 
                return this._state.enabled; 
 | 
            }, 
 | 
  
 | 
            on: function(evt, callback) { 
 | 
                this._bindNonQueryEventHandler(evt, callback); 
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
      off: function(evt, callback) { 
 | 
          if($) { 
 | 
              this.$element.off(evt, callback); 
 | 
              this.$sliderElem.off(evt, callback); 
 | 
          } else { 
 | 
              this._unbindNonQueryEventHandler(evt, callback); 
 | 
          } 
 | 
      }, 
 | 
  
 | 
            getAttribute: function(attribute) { 
 | 
                if(attribute) { 
 | 
                    return this.options[attribute]; 
 | 
                } else { 
 | 
                    return this.options; 
 | 
                } 
 | 
            }, 
 | 
  
 | 
            setAttribute: function(attribute, value) { 
 | 
                this.options[attribute] = value; 
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
            refresh: function() { 
 | 
                this._removeSliderEventHandlers(); 
 | 
                createNewSlider.call(this, this.element, this.options); 
 | 
                if($) { 
 | 
                    // Bind new instance of slider to the element 
 | 
                    $.data(this.element, 'slider', this); 
 | 
                } 
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
            relayout: function() { 
 | 
                this._layout(); 
 | 
                return this; 
 | 
            }, 
 | 
  
 | 
            /******************************+ 
 | 
  
 | 
                        HELPERS 
 | 
  
 | 
            - Any method that is not part of the public interface. 
 | 
            - Place it underneath this comment block and write its signature like so: 
 | 
  
 | 
                                  _fnName : function() {...} 
 | 
  
 | 
            ********************************/ 
 | 
            _removeSliderEventHandlers: function() { 
 | 
                // Remove keydown event listeners 
 | 
                this.handle1.removeEventListener("keydown", this.handle1Keydown, false); 
 | 
                this.handle2.removeEventListener("keydown", this.handle2Keydown, false); 
 | 
  
 | 
                if (this.showTooltip) { 
 | 
                    this.handle1.removeEventListener("focus", this.showTooltip, false); 
 | 
                    this.handle2.removeEventListener("focus", this.showTooltip, false); 
 | 
                } 
 | 
                if (this.hideTooltip) { 
 | 
                    this.handle1.removeEventListener("blur", this.hideTooltip, false); 
 | 
                    this.handle2.removeEventListener("blur", this.hideTooltip, false); 
 | 
                } 
 | 
  
 | 
                // Remove event listeners from sliderElem 
 | 
                if (this.showTooltip) { 
 | 
                    this.sliderElem.removeEventListener("mouseenter", this.showTooltip, false); 
 | 
                } 
 | 
                if (this.hideTooltip) { 
 | 
                    this.sliderElem.removeEventListener("mouseleave", this.hideTooltip, false); 
 | 
                } 
 | 
                this.sliderElem.removeEventListener("touchstart", this.mousedown, false); 
 | 
                this.sliderElem.removeEventListener("mousedown", this.mousedown, false); 
 | 
            }, 
 | 
            _bindNonQueryEventHandler: function(evt, callback) { 
 | 
                if(this.eventToCallbackMap[evt] === undefined) { 
 | 
                    this.eventToCallbackMap[evt] = []; 
 | 
                } 
 | 
                this.eventToCallbackMap[evt].push(callback); 
 | 
            }, 
 | 
      _unbindNonQueryEventHandler: function(evt, callback) { 
 | 
          var callbacks = this.eventToCallbackMap[evt]; 
 | 
          if(callbacks !== undefined) { 
 | 
              for (var i = 0; i < callbacks.length; i++) { 
 | 
                  if (callbacks[i] === callback) { 
 | 
                      callbacks.splice(i, 1); 
 | 
                      break; 
 | 
                  } 
 | 
              } 
 | 
          } 
 | 
      }, 
 | 
            _cleanUpEventCallbacksMap: function() { 
 | 
                var eventNames = Object.keys(this.eventToCallbackMap); 
 | 
                for(var i = 0; i < eventNames.length; i++) { 
 | 
                    var eventName = eventNames[i]; 
 | 
                    this.eventToCallbackMap[eventName] = null; 
 | 
                } 
 | 
            }, 
 | 
            _showTooltip: function() { 
 | 
                if (this.options.tooltip_split === false ){ 
 | 
            this._addClass(this.tooltip, 'in'); 
 | 
            this.tooltip_min.style.display = 'none'; 
 | 
            this.tooltip_max.style.display = 'none'; 
 | 
            } else { 
 | 
          this._addClass(this.tooltip_min, 'in'); 
 | 
          this._addClass(this.tooltip_max, 'in'); 
 | 
          this.tooltip.style.display = 'none'; 
 | 
            } 
 | 
                this._state.over = true; 
 | 
            }, 
 | 
            _hideTooltip: function() { 
 | 
                if (this._state.inDrag === false && this.alwaysShowTooltip !== true) { 
 | 
                    this._removeClass(this.tooltip, 'in'); 
 | 
                    this._removeClass(this.tooltip_min, 'in'); 
 | 
                    this._removeClass(this.tooltip_max, 'in'); 
 | 
                } 
 | 
                this._state.over = false; 
 | 
            }, 
 | 
            _layout: function() { 
 | 
                var positionPercentages; 
 | 
  
 | 
                if(this.options.reversed) { 
 | 
                    positionPercentages = [ 100 - this._state.percentage[0], this.options.range ? 100 - this._state.percentage[1] : this._state.percentage[1]]; 
 | 
                } 
 | 
                else { 
 | 
                    positionPercentages = [ this._state.percentage[0], this._state.percentage[1] ]; 
 | 
                } 
 | 
  
 | 
                this.handle1.style[this.stylePos] = positionPercentages[0]+'%'; 
 | 
                this.handle1.setAttribute('aria-valuenow', this._state.value[0]); 
 | 
  
 | 
                this.handle2.style[this.stylePos] = positionPercentages[1]+'%'; 
 | 
                this.handle2.setAttribute('aria-valuenow', this._state.value[1]); 
 | 
  
 | 
                /* Position ticks and labels */ 
 | 
                if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { 
 | 
  
 | 
                    var styleSize = this.options.orientation === 'vertical' ? 'height' : 'width'; 
 | 
                    var styleMargin = this.options.orientation === 'vertical' ? 'marginTop' : 'marginLeft'; 
 | 
                    var labelSize = this._state.size / (this.options.ticks.length - 1); 
 | 
  
 | 
                    if (this.tickLabelContainer) { 
 | 
                        var extraMargin = 0; 
 | 
                        if (this.options.ticks_positions.length === 0) { 
 | 
                            if (this.options.orientation !== 'vertical') { 
 | 
                                this.tickLabelContainer.style[styleMargin] = -labelSize/2 + 'px'; 
 | 
                            } 
 | 
  
 | 
                            extraMargin = this.tickLabelContainer.offsetHeight; 
 | 
                        } else { 
 | 
                            /* Chidren are position absolute, calculate height by finding the max offsetHeight of a child */ 
 | 
                            for (i = 0 ; i < this.tickLabelContainer.childNodes.length; i++) { 
 | 
                                if (this.tickLabelContainer.childNodes[i].offsetHeight > extraMargin) { 
 | 
                                    extraMargin = this.tickLabelContainer.childNodes[i].offsetHeight; 
 | 
                                } 
 | 
                            } 
 | 
                        } 
 | 
                        if (this.options.orientation === 'horizontal') { 
 | 
                            this.sliderElem.style.marginBottom = extraMargin + 'px'; 
 | 
                        } 
 | 
                    } 
 | 
                    for (var i = 0; i < this.options.ticks.length; i++) { 
 | 
  
 | 
                        var percentage = this.options.ticks_positions[i] || this._toPercentage(this.options.ticks[i]); 
 | 
  
 | 
                        if (this.options.reversed) { 
 | 
                            percentage = 100 - percentage; 
 | 
                        } 
 | 
  
 | 
                        this.ticks[i].style[this.stylePos] = percentage + '%'; 
 | 
  
 | 
                        /* Set class labels to denote whether ticks are in the selection */ 
 | 
                        this._removeClass(this.ticks[i], 'in-selection'); 
 | 
                        if (!this.options.range) { 
 | 
                            if (this.options.selection === 'after' && percentage >= positionPercentages[0]){ 
 | 
                                this._addClass(this.ticks[i], 'in-selection'); 
 | 
                            } else if (this.options.selection === 'before' && percentage <= positionPercentages[0]) { 
 | 
                                this._addClass(this.ticks[i], 'in-selection'); 
 | 
                            } 
 | 
                        } else if (percentage >= positionPercentages[0] && percentage <= positionPercentages[1]) { 
 | 
                            this._addClass(this.ticks[i], 'in-selection'); 
 | 
                        } 
 | 
  
 | 
                        if (this.tickLabels[i]) { 
 | 
                            this.tickLabels[i].style[styleSize] = labelSize + 'px'; 
 | 
  
 | 
                            if (this.options.orientation !== 'vertical' && this.options.ticks_positions[i] !== undefined) { 
 | 
                                this.tickLabels[i].style.position = 'absolute'; 
 | 
                                this.tickLabels[i].style[this.stylePos] = percentage + '%'; 
 | 
                                this.tickLabels[i].style[styleMargin] = -labelSize/2 + 'px'; 
 | 
                            } else if (this.options.orientation === 'vertical') { 
 | 
                                this.tickLabels[i].style['marginLeft'] =  this.sliderElem.offsetWidth + 'px'; 
 | 
                                this.tickLabelContainer.style['marginTop'] = this.sliderElem.offsetWidth / 2 * -1 + 'px'; 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                var formattedTooltipVal; 
 | 
  
 | 
                if (this.options.range) { 
 | 
                    formattedTooltipVal = this.options.formatter(this._state.value); 
 | 
                    this._setText(this.tooltipInner, formattedTooltipVal); 
 | 
                    this.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0])/2 + '%'; 
 | 
  
 | 
                    if (this.options.orientation === 'vertical') { 
 | 
                        this._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px'); 
 | 
                    } else { 
 | 
                        this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px'); 
 | 
                    } 
 | 
  
 | 
                    if (this.options.orientation === 'vertical') { 
 | 
                        this._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px'); 
 | 
                    } else { 
 | 
                        this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px'); 
 | 
                    } 
 | 
  
 | 
                    var innerTooltipMinText = this.options.formatter(this._state.value[0]); 
 | 
                    this._setText(this.tooltipInner_min, innerTooltipMinText); 
 | 
  
 | 
                    var innerTooltipMaxText = this.options.formatter(this._state.value[1]); 
 | 
                    this._setText(this.tooltipInner_max, innerTooltipMaxText); 
 | 
  
 | 
                    this.tooltip_min.style[this.stylePos] = positionPercentages[0] + '%'; 
 | 
  
 | 
                    if (this.options.orientation === 'vertical') { 
 | 
                        this._css(this.tooltip_min, 'margin-top', -this.tooltip_min.offsetHeight / 2 + 'px'); 
 | 
                    } else { 
 | 
                        this._css(this.tooltip_min, 'margin-left', -this.tooltip_min.offsetWidth / 2 + 'px'); 
 | 
                    } 
 | 
  
 | 
                    this.tooltip_max.style[this.stylePos] = positionPercentages[1] + '%'; 
 | 
  
 | 
                    if (this.options.orientation === 'vertical') { 
 | 
                        this._css(this.tooltip_max, 'margin-top', -this.tooltip_max.offsetHeight / 2 + 'px'); 
 | 
                    } else { 
 | 
                        this._css(this.tooltip_max, 'margin-left', -this.tooltip_max.offsetWidth / 2 + 'px'); 
 | 
                    } 
 | 
                } else { 
 | 
                    formattedTooltipVal = this.options.formatter(this._state.value[0]); 
 | 
                    this._setText(this.tooltipInner, formattedTooltipVal); 
 | 
  
 | 
                    this.tooltip.style[this.stylePos] = positionPercentages[0] + '%'; 
 | 
                    if (this.options.orientation === 'vertical') { 
 | 
                        this._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px'); 
 | 
                    } else { 
 | 
                        this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px'); 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                if (this.options.orientation === 'vertical') { 
 | 
                    this.trackLow.style.top = '0'; 
 | 
                    this.trackLow.style.height = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; 
 | 
  
 | 
                    this.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; 
 | 
                    this.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%'; 
 | 
  
 | 
                    this.trackHigh.style.bottom = '0'; 
 | 
                    this.trackHigh.style.height = (100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1])) +'%'; 
 | 
                } 
 | 
                else { 
 | 
                    this.trackLow.style.left = '0'; 
 | 
                    this.trackLow.style.width = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; 
 | 
  
 | 
                    this.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; 
 | 
                    this.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%'; 
 | 
  
 | 
                    this.trackHigh.style.right = '0'; 
 | 
                    this.trackHigh.style.width = (100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1])) +'%'; 
 | 
  
 | 
                    var offset_min = this.tooltip_min.getBoundingClientRect(); 
 | 
                    var offset_max = this.tooltip_max.getBoundingClientRect(); 
 | 
  
 | 
                    if (offset_min.right > offset_max.left) { 
 | 
                        this._removeClass(this.tooltip_max, 'top'); 
 | 
                        this._addClass(this.tooltip_max, 'bottom'); 
 | 
                        this.tooltip_max.style.top = 18 + 'px'; 
 | 
                    } else { 
 | 
                        this._removeClass(this.tooltip_max, 'bottom'); 
 | 
                        this._addClass(this.tooltip_max, 'top'); 
 | 
                        this.tooltip_max.style.top = this.tooltip_min.style.top; 
 | 
                    } 
 | 
                } 
 | 
            }, 
 | 
            _removeProperty: function(element, prop) { 
 | 
                if (element.style.removeProperty) { 
 | 
                    element.style.removeProperty(prop); 
 | 
                } else { 
 | 
                    element.style.removeAttribute(prop); 
 | 
                } 
 | 
            }, 
 | 
            _mousedown: function(ev) { 
 | 
                if(!this._state.enabled) { 
 | 
                    return false; 
 | 
                } 
 | 
  
 | 
                this._state.offset = this._offset(this.sliderElem); 
 | 
                this._state.size = this.sliderElem[this.sizePos]; 
 | 
  
 | 
                var percentage = this._getPercentage(ev); 
 | 
  
 | 
                if (this.options.range) { 
 | 
                    var diff1 = Math.abs(this._state.percentage[0] - percentage); 
 | 
                    var diff2 = Math.abs(this._state.percentage[1] - percentage); 
 | 
                    this._state.dragged = (diff1 < diff2) ? 0 : 1; 
 | 
                } else { 
 | 
                    this._state.dragged = 0; 
 | 
                } 
 | 
  
 | 
                this._state.percentage[this._state.dragged] = percentage; 
 | 
                this._layout(); 
 | 
  
 | 
                if (this.touchCapable) { 
 | 
                    document.removeEventListener("touchmove", this.mousemove, false); 
 | 
                    document.removeEventListener("touchend", this.mouseup, false); 
 | 
                } 
 | 
  
 | 
                if(this.mousemove){ 
 | 
                    document.removeEventListener("mousemove", this.mousemove, false); 
 | 
                } 
 | 
                if(this.mouseup){ 
 | 
                    document.removeEventListener("mouseup", this.mouseup, false); 
 | 
                } 
 | 
  
 | 
                this.mousemove = this._mousemove.bind(this); 
 | 
                this.mouseup = this._mouseup.bind(this); 
 | 
  
 | 
                if (this.touchCapable) { 
 | 
                    // Touch: Bind touch events: 
 | 
                    document.addEventListener("touchmove", this.mousemove, false); 
 | 
                    document.addEventListener("touchend", this.mouseup, false); 
 | 
                } 
 | 
                // Bind mouse events: 
 | 
                document.addEventListener("mousemove", this.mousemove, false); 
 | 
                document.addEventListener("mouseup", this.mouseup, false); 
 | 
  
 | 
                this._state.inDrag = true; 
 | 
                var newValue = this._calculateValue(); 
 | 
  
 | 
                this._trigger('slideStart', newValue); 
 | 
  
 | 
                this._setDataVal(newValue); 
 | 
                this.setValue(newValue, false, true); 
 | 
  
 | 
                this._pauseEvent(ev); 
 | 
  
 | 
                if (this.options.focus) { 
 | 
                    this._triggerFocusOnHandle(this._state.dragged); 
 | 
                } 
 | 
  
 | 
                return true; 
 | 
            }, 
 | 
            _triggerFocusOnHandle: function(handleIdx) { 
 | 
                if(handleIdx === 0) { 
 | 
                    this.handle1.focus(); 
 | 
                } 
 | 
                if(handleIdx === 1) { 
 | 
                    this.handle2.focus(); 
 | 
                } 
 | 
            }, 
 | 
            _keydown: function(handleIdx, ev) { 
 | 
                if(!this._state.enabled) { 
 | 
                    return false; 
 | 
                } 
 | 
  
 | 
                var dir; 
 | 
                switch (ev.keyCode) { 
 | 
                    case 37: // left 
 | 
                    case 40: // down 
 | 
                        dir = -1; 
 | 
                        break; 
 | 
                    case 39: // right 
 | 
                    case 38: // up 
 | 
                        dir = 1; 
 | 
                        break; 
 | 
                } 
 | 
                if (!dir) { 
 | 
                    return; 
 | 
                } 
 | 
  
 | 
                // use natural arrow keys instead of from min to max 
 | 
                if (this.options.natural_arrow_keys) { 
 | 
                    var ifVerticalAndNotReversed = (this.options.orientation === 'vertical' && !this.options.reversed); 
 | 
                    var ifHorizontalAndReversed = (this.options.orientation === 'horizontal' && this.options.reversed); 
 | 
  
 | 
                    if (ifVerticalAndNotReversed || ifHorizontalAndReversed) { 
 | 
                        dir = -dir; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                var val = this._state.value[handleIdx] + dir * this.options.step; 
 | 
                if (this.options.range) { 
 | 
                    val = [ (!handleIdx) ? val : this._state.value[0], 
 | 
                            ( handleIdx) ? val : this._state.value[1]]; 
 | 
                } 
 | 
  
 | 
                this._trigger('slideStart', val); 
 | 
                this._setDataVal(val); 
 | 
                this.setValue(val, true, true); 
 | 
  
 | 
                this._setDataVal(val); 
 | 
                this._trigger('slideStop', val); 
 | 
                this._layout(); 
 | 
  
 | 
                this._pauseEvent(ev); 
 | 
  
 | 
                return false; 
 | 
            }, 
 | 
            _pauseEvent: function(ev) { 
 | 
                if(ev.stopPropagation) { 
 | 
                    ev.stopPropagation(); 
 | 
                } 
 | 
                if(ev.preventDefault) { 
 | 
                    ev.preventDefault(); 
 | 
                } 
 | 
                ev.cancelBubble=true; 
 | 
                ev.returnValue=false; 
 | 
            }, 
 | 
            _mousemove: function(ev) { 
 | 
                if(!this._state.enabled) { 
 | 
                    return false; 
 | 
                } 
 | 
  
 | 
                var percentage = this._getPercentage(ev); 
 | 
                this._adjustPercentageForRangeSliders(percentage); 
 | 
                this._state.percentage[this._state.dragged] = percentage; 
 | 
                this._layout(); 
 | 
  
 | 
                var val = this._calculateValue(true); 
 | 
                this.setValue(val, true, true); 
 | 
  
 | 
                return false; 
 | 
            }, 
 | 
            _adjustPercentageForRangeSliders: function(percentage) { 
 | 
                if (this.options.range) { 
 | 
                    var precision = this._getNumDigitsAfterDecimalPlace(percentage); 
 | 
                    precision = precision ? precision - 1 : 0; 
 | 
                    var percentageWithAdjustedPrecision = this._applyToFixedAndParseFloat(percentage, precision); 
 | 
                    if (this._state.dragged === 0 && this._applyToFixedAndParseFloat(this._state.percentage[1], precision) < percentageWithAdjustedPrecision) { 
 | 
                        this._state.percentage[0] = this._state.percentage[1]; 
 | 
                        this._state.dragged = 1; 
 | 
                    } else if (this._state.dragged === 1 && this._applyToFixedAndParseFloat(this._state.percentage[0], precision) > percentageWithAdjustedPrecision) { 
 | 
                        this._state.percentage[1] = this._state.percentage[0]; 
 | 
                        this._state.dragged = 0; 
 | 
                    } 
 | 
                } 
 | 
            }, 
 | 
            _mouseup: function() { 
 | 
                if(!this._state.enabled) { 
 | 
                    return false; 
 | 
                } 
 | 
                if (this.touchCapable) { 
 | 
                    // Touch: Unbind touch event handlers: 
 | 
                    document.removeEventListener("touchmove", this.mousemove, false); 
 | 
                    document.removeEventListener("touchend", this.mouseup, false); 
 | 
                } 
 | 
                // Unbind mouse event handlers: 
 | 
                document.removeEventListener("mousemove", this.mousemove, false); 
 | 
                document.removeEventListener("mouseup", this.mouseup, false); 
 | 
  
 | 
                this._state.inDrag = false; 
 | 
                if (this._state.over === false) { 
 | 
                    this._hideTooltip(); 
 | 
                } 
 | 
                var val = this._calculateValue(true); 
 | 
  
 | 
                this._layout(); 
 | 
                this._setDataVal(val); 
 | 
                this._trigger('slideStop', val); 
 | 
  
 | 
                return false; 
 | 
            }, 
 | 
            _calculateValue: function(snapToClosestTick) { 
 | 
                var val; 
 | 
                if (this.options.range) { 
 | 
                    val = [this.options.min,this.options.max]; 
 | 
                    if (this._state.percentage[0] !== 0){ 
 | 
                        val[0] = this._toValue(this._state.percentage[0]); 
 | 
                        val[0] = this._applyPrecision(val[0]); 
 | 
                    } 
 | 
                    if (this._state.percentage[1] !== 100){ 
 | 
                        val[1] = this._toValue(this._state.percentage[1]); 
 | 
                        val[1] = this._applyPrecision(val[1]); 
 | 
                    } 
 | 
                } else { 
 | 
                    val = this._toValue(this._state.percentage[0]); 
 | 
                    val = parseFloat(val); 
 | 
                    val = this._applyPrecision(val); 
 | 
                } 
 | 
  
 | 
                if (snapToClosestTick) { 
 | 
                    var min = [val, Infinity]; 
 | 
                    for (var i = 0; i < this.options.ticks.length; i++) { 
 | 
                        var diff = Math.abs(this.options.ticks[i] - val); 
 | 
                        if (diff <= min[1]) { 
 | 
                            min = [this.options.ticks[i], diff]; 
 | 
                        } 
 | 
                    } 
 | 
                    if (min[1] <= this.options.ticks_snap_bounds) { 
 | 
                        return min[0]; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                return val; 
 | 
            }, 
 | 
            _applyPrecision: function(val) { 
 | 
                var precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.options.step); 
 | 
                return this._applyToFixedAndParseFloat(val, precision); 
 | 
            }, 
 | 
            _getNumDigitsAfterDecimalPlace: function(num) { 
 | 
                var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/); 
 | 
                if (!match) { return 0; } 
 | 
                return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0)); 
 | 
            }, 
 | 
            _applyToFixedAndParseFloat: function(num, toFixedInput) { 
 | 
                var truncatedNum = num.toFixed(toFixedInput); 
 | 
                return parseFloat(truncatedNum); 
 | 
            }, 
 | 
            /* 
 | 
                Credits to Mike Samuel for the following method! 
 | 
                Source: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number 
 | 
            */ 
 | 
            _getPercentage: function(ev) { 
 | 
                if (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove')) { 
 | 
                    ev = ev.touches[0]; 
 | 
                } 
 | 
  
 | 
                var eventPosition = ev[this.mousePos]; 
 | 
                var sliderOffset = this._state.offset[this.stylePos]; 
 | 
                var distanceToSlide = eventPosition - sliderOffset; 
 | 
                // Calculate what percent of the length the slider handle has slid 
 | 
                var percentage = (distanceToSlide / this._state.size) * 100; 
 | 
                percentage = Math.round(percentage / this._state.percentage[2]) * this._state.percentage[2]; 
 | 
                if (this.options.reversed) { 
 | 
                    percentage = 100 - percentage; 
 | 
                } 
 | 
  
 | 
                // Make sure the percent is within the bounds of the slider. 
 | 
                // 0% corresponds to the 'min' value of the slide 
 | 
                // 100% corresponds to the 'max' value of the slide 
 | 
                return Math.max(0, Math.min(100, percentage)); 
 | 
            }, 
 | 
            _validateInputValue: function(val) { 
 | 
                if (typeof val === 'number') { 
 | 
                    return val; 
 | 
                } else if (Array.isArray(val)) { 
 | 
                    this._validateArray(val); 
 | 
                    return val; 
 | 
                } else { 
 | 
                    throw new Error( ErrorMsgs.formatInvalidInputErrorMsg(val) ); 
 | 
                } 
 | 
            }, 
 | 
            _validateArray: function(val) { 
 | 
                for(var i = 0; i < val.length; i++) { 
 | 
                    var input =  val[i]; 
 | 
                    if (typeof input !== 'number') { throw new Error( ErrorMsgs.formatInvalidInputErrorMsg(input) ); } 
 | 
                } 
 | 
            }, 
 | 
            _setDataVal: function(val) { 
 | 
                this.element.setAttribute('data-value', val); 
 | 
                this.element.setAttribute('value', val); 
 | 
        this.element.value = val; 
 | 
            }, 
 | 
            _trigger: function(evt, val) { 
 | 
                val = (val || val === 0) ? val : undefined; 
 | 
  
 | 
                var callbackFnArray = this.eventToCallbackMap[evt]; 
 | 
                if(callbackFnArray && callbackFnArray.length) { 
 | 
                    for(var i = 0; i < callbackFnArray.length; i++) { 
 | 
                        var callbackFn = callbackFnArray[i]; 
 | 
                        callbackFn(val); 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                /* If JQuery exists, trigger JQuery events */ 
 | 
                if($) { 
 | 
                    this._triggerJQueryEvent(evt, val); 
 | 
                } 
 | 
            }, 
 | 
            _triggerJQueryEvent: function(evt, val) { 
 | 
                var eventData = { 
 | 
                    type: evt, 
 | 
                    value: val 
 | 
                }; 
 | 
                this.$element.trigger(eventData); 
 | 
                this.$sliderElem.trigger(eventData); 
 | 
            }, 
 | 
            _unbindJQueryEventHandlers: function() { 
 | 
                this.$element.off(); 
 | 
                this.$sliderElem.off(); 
 | 
            }, 
 | 
            _setText: function(element, text) { 
 | 
                if(typeof element.innerText !== "undefined") { 
 | 
                     element.innerText = text; 
 | 
                 } else if(typeof element.textContent !== "undefined") { 
 | 
                     element.textContent = text; 
 | 
                 } 
 | 
            }, 
 | 
            _removeClass: function(element, classString) { 
 | 
                var classes = classString.split(" "); 
 | 
                var newClasses = element.className; 
 | 
  
 | 
                for(var i = 0; i < classes.length; i++) { 
 | 
                    var classTag = classes[i]; 
 | 
                    var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)"); 
 | 
                    newClasses = newClasses.replace(regex, " "); 
 | 
                } 
 | 
  
 | 
                element.className = newClasses.trim(); 
 | 
            }, 
 | 
            _addClass: function(element, classString) { 
 | 
                var classes = classString.split(" "); 
 | 
                var newClasses = element.className; 
 | 
  
 | 
                for(var i = 0; i < classes.length; i++) { 
 | 
                    var classTag = classes[i]; 
 | 
                    var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)"); 
 | 
                    var ifClassExists = regex.test(newClasses); 
 | 
  
 | 
                    if(!ifClassExists) { 
 | 
                        newClasses += " " + classTag; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                element.className = newClasses.trim(); 
 | 
            }, 
 | 
            _offsetLeft: function(obj){ 
 | 
                return obj.getBoundingClientRect().left; 
 | 
            }, 
 | 
            _offsetTop: function(obj){ 
 | 
                var offsetTop = obj.offsetTop; 
 | 
                while((obj = obj.offsetParent) && !isNaN(obj.offsetTop)){ 
 | 
                    offsetTop += obj.offsetTop; 
 | 
                } 
 | 
                return offsetTop; 
 | 
            }, 
 | 
            _offset: function (obj) { 
 | 
                return { 
 | 
                    left: this._offsetLeft(obj), 
 | 
                    top: this._offsetTop(obj) 
 | 
                }; 
 | 
            }, 
 | 
            _css: function(elementRef, styleName, value) { 
 | 
                if ($) { 
 | 
                    $.style(elementRef, styleName, value); 
 | 
                } else { 
 | 
                    var style = styleName.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function (all, letter) { 
 | 
                        return letter.toUpperCase(); 
 | 
                    }); 
 | 
                    elementRef.style[style] = value; 
 | 
                } 
 | 
            }, 
 | 
            _toValue: function(percentage) { 
 | 
                return this.options.scale.toValue.apply(this, [percentage]); 
 | 
            }, 
 | 
            _toPercentage: function(value) { 
 | 
                return this.options.scale.toPercentage.apply(this, [value]); 
 | 
            }, 
 | 
            _setTooltipPosition: function(){ 
 | 
                var tooltips = [this.tooltip, this.tooltip_min, this.tooltip_max]; 
 | 
                if (this.options.orientation === 'vertical'){ 
 | 
                    var tooltipPos = this.options.tooltip_position || 'right'; 
 | 
                    var oppositeSide = (tooltipPos === 'left') ? 'right' : 'left'; 
 | 
                    tooltips.forEach(function(tooltip){ 
 | 
                        this._addClass(tooltip, tooltipPos); 
 | 
                        tooltip.style[oppositeSide] = '100%'; 
 | 
                    }.bind(this)); 
 | 
                } else if(this.options.tooltip_position === 'bottom') { 
 | 
                    tooltips.forEach(function(tooltip){ 
 | 
                        this._addClass(tooltip, 'bottom'); 
 | 
                        tooltip.style.top = 22 + 'px'; 
 | 
                    }.bind(this)); 
 | 
                } else { 
 | 
                    tooltips.forEach(function(tooltip){ 
 | 
                        this._addClass(tooltip, 'top'); 
 | 
                        tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px'; 
 | 
                    }.bind(this)); 
 | 
                } 
 | 
            } 
 | 
        }; 
 | 
  
 | 
        /********************************* 
 | 
  
 | 
            Attach to global namespace 
 | 
  
 | 
        *********************************/ 
 | 
        if($) { 
 | 
            var namespace = $.fn.slider ? 'bootstrapSlider' : 'slider'; 
 | 
            $.bridget(namespace, Slider); 
 | 
        } 
 | 
  
 | 
    })( $ ); 
 | 
  
 | 
    return Slider; 
 | 
})); 
 |