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