vendor: 14,666 bytes, lines 1-417
1/*! nouislider - 15.7.1 - 6/14/2023 */ 2// reformatted code by ThemeComplete 3( function( global, factory ) { 4 'use strict'; 5 6 factory( global.noUiSlider = {} ); 7}( this, ( function( exports ) { 8 'use strict'; 9 10 var nouislider; 11 //region Defaults 12 var defaultFormatter = { 13 to: function( value ) { 14 return value === undefined ? '' : value.toFixed( 2 ); 15 }, 16 from: Number 17 }; 18 var cssClasses = { 19 target: 'target', 20 base: 'base', 21 origin: 'origin', 22 handle: 'handle', 23 handleLower: 'handle-lower', 24 handleUpper: 'handle-upper', 25 touchArea: 'touch-area', 26 horizontal: 'horizontal', 27 vertical: 'vertical', 28 background: 'background', 29 connect: 'connect', 30 connects: 'connects', 31 ltr: 'ltr', 32 rtl: 'rtl', 33 textDirectionLtr: 'txt-dir-ltr', 34 textDirectionRtl: 'txt-dir-rtl', 35 draggable: 'draggable', 36 drag: 'state-drag', 37 tap: 'state-tap', 38 active: 'active', 39 tooltip: 'tooltip', 40 pips: 'pips', 41 pipsHorizontal: 'pips-horizontal', 42 pipsVertical: 'pips-vertical', 43 marker: 'marker', 44 markerHorizontal: 'marker-horizontal', 45 markerVertical: 'marker-vertical', 46 markerNormal: 'marker-normal', 47 markerLarge: 'marker-large', 48 markerSub: 'marker-sub', 49 value: 'value', 50 valueHorizontal: 'value-horizontal', 51 valueVertical: 'value-vertical', 52 valueNormal: 'value-normal', 53 valueLarge: 'value-large', 54 valueSub: 'value-sub' 55 }; 56 // Namespaces of internal event listeners 57 var INTERNAL_EVENT_NS = { 58 tooltips: '.__tooltips', 59 aria: '.__aria' 60 }; 61 //endregion 62 //region Spectrum 63 var Spectrum = /** @class */ ( function() { 64 function Spectrumc( entry, snap, singleStep ) { 65 var index; 66 var ordered = []; 67 this.xPct = []; 68 this.xVal = []; 69 this.xSteps = []; 70 this.xNumSteps = []; 71 this.xHighestCompleteStep = []; 72 this.xSteps = [ singleStep || false ]; 73 this.xNumSteps = [ false ]; 74 this.snap = snap; 75 // Map the object keys to an array. 76 Object.keys( entry ).forEach( function( iindex ) { 77 ordered.push( [ asArray( entry[ iindex ] ), iindex ] ); 78 } ); 79 // Sort all entries by value (numeric sort). 80 ordered.sort( function( a, b ) { 81 return a[ 0 ][ 0 ] - b[ 0 ][ 0 ]; 82 } ); 83 // Convert all entries to subranges. 84 for ( index = 0; index < ordered.length; index++ ) { 85 this.handleEntryPoint( ordered[ index ][ 1 ], ordered[ index ][ 0 ] ); 86 } 87 // Store the actual step values. 88 // xSteps is sorted in the same order as xPct and xVal. 89 this.xNumSteps = this.xSteps.slice( 0 ); 90 // Convert all numeric steps to the percentage of the subrange they represent. 91 for ( index = 0; index < this.xNumSteps.length; index++ ) { 92 this.handleStepPoint( index, this.xNumSteps[ index ] ); 93 } 94 } 95 Spectrumc.prototype.getDistance = function( value ) { 96 var index; 97 var distances = []; 98 for ( index = 0; index < this.xNumSteps.length - 1; index++ ) { 99 distances[ index ] = fromPercentage( this.xVal, value, index ); 100 } 101 return distances; 102 }; 103 // Calculate the percentual distance over the whole scale of ranges. 104 // direction: 0 = backwards / 1 = forwards 105 Spectrumc.prototype.getAbsoluteDistance = function( value, distances, direction ) { 106 var xPct_index = 0; 107 var start_factor; 108 var rest_factor = 1; 109 var rest_rel_distance; 110 var range_pct = 0; 111 var rel_range_distance = 0; 112 var abs_distance_counter = 0; 113 var range_counter = 0; 114 115 // Calculate range where to start calculation 116 if ( value < this.xPct[ this.xPct.length - 1 ] ) { 117 while ( value > this.xPct[ xPct_index + 1 ] ) { 118 xPct_index++; 119 } 120 } else if ( value === this.xPct[ this.xPct.length - 1 ] ) { 121 xPct_index = this.xPct.length - 2; 122 } 123 // If looking backwards and the value is exactly at a range separator then look one range further 124 if ( ! direction && value === this.xPct[ xPct_index + 1 ] ) { 125 xPct_index++; 126 } 127 if ( distances === null ) { 128 distances = []; 129 } 130 rest_rel_distance = distances[ xPct_index ]; 131 132 // Calculate what part of the start range the value is 133 if ( direction ) { 134 start_factor = ( value - this.xPct[ xPct_index ] ) / ( this.xPct[ xPct_index + 1 ] - this.xPct[ xPct_index ] ); 135 } else { 136 start_factor = ( this.xPct[ xPct_index + 1 ] - value ) / ( this.xPct[ xPct_index + 1 ] - this.xPct[ xPct_index ] ); 137 } 138 // Do until the complete distance across ranges is calculated 139 while ( rest_rel_distance > 0 ) { 140 // Calculate the percentage of total range 141 range_pct = this.xPct[ xPct_index + 1 + range_counter ] - this.xPct[ xPct_index + range_counter ]; 142 // Detect if the margin, padding or limit is larger then the current range and calculate 143 if ( ( distances[ xPct_index + range_counter ] * rest_factor ) + 100 - ( start_factor * 100 ) > 100 ) { 144 // If larger then take the percentual distance of the whole range 145 rel_range_distance = range_pct * start_factor; 146 // Rest factor of relative percentual distance still to be calculated 147 rest_factor = ( rest_rel_distance - ( 100 * start_factor ) ) / distances[ xPct_index + range_counter ]; 148 // Set start factor to 1 as for next range it does not apply. 149 start_factor = 1; 150 } else { 151 // If smaller or equal then take the percentual distance of the calculate percentual part of that range 152 rel_range_distance = ( ( distances[ xPct_index + range_counter ] * range_pct ) / 100 ) * rest_factor; 153 // No rest left as the rest fits in current range 154 rest_factor = 0; 155 } 156 if ( direction ) { 157 abs_distance_counter = abs_distance_counter - rel_range_distance; 158 // Limit range to first range when distance becomes outside of minimum range 159 if ( this.xPct.length + range_counter >= 1 ) { 160 range_counter--; 161 } 162 } else { 163 abs_distance_counter = abs_distance_counter + rel_range_distance; 164 // Limit range to last range when distance becomes outside of maximum range 165 if ( this.xPct.length - range_counter >= 1 ) { 166 range_counter++; 167 } 168 } 169 // Rest of relative percentual distance still to be calculated 170 rest_rel_distance = distances[ xPct_index + range_counter ] * rest_factor; 171 } 172 return value + abs_distance_counter; 173 }; 174 Spectrumc.prototype.toStepping = function( value ) { 175 value = toStepping( this.xVal, this.xPct, value ); 176 return value; 177 }; 178 Spectrumc.prototype.fromStepping = function( value ) { 179 return fromStepping( this.xVal, this.xPct, value ); 180 }; 181 Spectrumc.prototype.getStep = function( value ) { 182 value = getStep( this.xPct, this.xSteps, this.snap, value ); 183 return value; 184 }; 185 Spectrumc.prototype.getDefaultStep = function( value, isDown, size ) { 186 var j = getJ( value, this.xPct ); 187 // When at the top or stepping down, look at the previous sub-range 188 if ( value === 100 || ( isDown && value === this.xPct[ j - 1 ] ) ) { 189 j = Math.max( j - 1, 1 ); 190 } 191 return ( this.xVal[ j ] - this.xVal[ j - 1 ] ) / size; 192 }; 193 Spectrumc.prototype.getNearbySteps = function( value ) { 194 var j = getJ( value, this.xPct ); 195 return { 196 stepBefore: { 197 startValue: this.xVal[ j - 2 ], 198 step: this.xNumSteps[ j - 2 ], 199 highestStep: this.xHighestCompleteStep[ j - 2 ] 200 }, 201 thisStep: { 202 startValue: this.xVal[ j - 1 ], 203 step: this.xNumSteps[ j - 1 ], 204 highestStep: this.xHighestCompleteStep[ j - 1 ] 205 }, 206 stepAfter: { 207 startValue: this.xVal[ j ], 208 step: this.xNumSteps[ j ], 209 highestStep: this.xHighestCompleteStep[ j ] 210 } 211 }; 212 }; 213 Spectrumc.prototype.countStepDecimals = function() { 214 var stepDecimals = this.xNumSteps.map( countDecimals ); 215 return Math.max.apply( null, stepDecimals ); 216 }; 217 Spectrumc.prototype.hasNoSize = function() { 218 return this.xVal[ 0 ] === this.xVal[ this.xVal.length - 1 ]; 219 }; 220 // Outside testing 221 Spectrumc.prototype.convert = function( value ) { 222 return this.getStep( this.toStepping( value ) ); 223 }; 224 Spectrumc.prototype.handleEntryPoint = function( index, value ) { 225 var percentage; 226 var value1; 227 // Covert min/max syntax to 0 and 100. 228 if ( index === 'min' ) { 229 percentage = 0; 230 } else if ( index === 'max' ) { 231 percentage = 100; 232 } else { 233 percentage = parseFloat( index ); 234 } 235 // Check for correct input. 236 if ( ! isNumeric( percentage ) || ! isNumeric( value[ 0 ] ) ) { 237 throw new Error( "noUiSlider: 'range' value isn't numeric." ); 238 } 239 // Store values. 240 this.xPct.push( percentage ); 241 this.xVal.push( value[ 0 ] ); 242 value1 = Number( value[ 1 ] ); 243 // NaN will evaluate to false too, but to keep 244 // logging clear, set step explicitly. Make sure 245 // not to override the 'step' setting with false. 246 if ( ! percentage ) { 247 if ( ! isNaN( value1 ) ) { 248 this.xSteps[ 0 ] = value1; 249 } 250 } else { 251 this.xSteps.push( isNaN( value1 ) ? false : value1 ); 252 } 253 this.xHighestCompleteStep.push( 0 ); 254 }; 255 Spectrumc.prototype.handleStepPoint = function( i, n ) { 256 var totalSteps; 257 var highestStep; 258 var step; 259 // Ignore 'false' stepping. 260 if ( ! n ) { 261 return; 262 } 263 // Step over zero-length ranges (#948); 264 if ( this.xVal[ i ] === this.xVal[ i + 1 ] ) { 265 this.xSteps[ i ] = this.xHighestCompleteStep[ i ] = this.xVal[ i ]; 266 return; 267 } 268 // Factor to range ratio 269 this.xSteps[ i ] = 270 fromPercentage( [ this.xVal[ i ], this.xVal[ i + 1 ] ], n, 0 ) / subRangeRatio( this.xPct[ i ], this.xPct[ i + 1 ] ); 271 totalSteps = ( this.xVal[ i + 1 ] - this.xVal[ i ] ) / this.xNumSteps[ i ]; 272 highestStep = Math.ceil( Number( totalSteps.toFixed( 3 ) ) - 1 ); 273 step = this.xVal[ i ] + ( this.xNumSteps[ i ] * highestStep ); 274 this.xHighestCompleteStep[ i ] = step; 275 }; 276 return Spectrumc; 277 }() ); 278 //endregion 279 exports.PipsMode = void 0; 280 ( function( PipsMode ) { 281 PipsMode.Range = 'range'; 282 PipsMode.Steps = 'steps'; 283 PipsMode.Positions = 'positions'; 284 PipsMode.Count = 'count'; 285 PipsMode.Values = 'values'; 286 }( exports.PipsMode || ( exports.PipsMode = {} ) ) ); 287 exports.PipsType = void 0; 288 ( function( PipsType ) { 289 PipsType[ PipsType.None = -1 ] = 'None'; 290 PipsType[ PipsType.NoValue = 0 ] = 'NoValue'; 291 PipsType[ PipsType.LargeValue = 1 ] = 'LargeValue'; 292 PipsType[ PipsType.SmallValue = 2 ] = 'SmallValue'; 293 }( exports.PipsType || ( exports.PipsType = {} ) ) ); 294 //region Helper Methods 295 function isValidFormatter( entry ) { 296 return isValidPartialFormatter( entry ) && typeof entry.from === 'function'; 297 } 298 function isValidPartialFormatter( entry ) { 299 // partial formatters only need a to function and not a from function 300 return typeof entry === 'object' && typeof entry.to === 'function'; 301 } 302 function removeElement( el ) { 303 el.parentElement.removeChild( el ); 304 } 305 function isSet( value ) { 306 return value !== null && value !== undefined; 307 } 308 // Bindable version 309 function preventDefault( e ) { 310 e.preventDefault(); 311 } 312 // Removes duplicates from an array. 313 function unique( array ) { 314 return array.filter( function( a ) { 315 return ! this[ a ] ? ( this[ a ] = true ) : false; 316 }, {} ); 317 } 318 // Round a value to the closest 'to'. 319 function closest( value, to ) { 320 return Math.round( value / to ) * to; 321 } 322 // Current position of an element relative to the document. 323 function offset( elem, orientation ) { 324 var rect = elem.getBoundingClientRect(); 325 var doc = elem.ownerDocument; 326 var docElem = doc.documentElement; 327 var pageOffset = getPageOffset( doc ); 328 // getBoundingClientRect contains left scroll in Chrome on Android. 329 // I haven't found a feature detection that proves this. Worst case 330 // scenario on mis-match: the 'tap' feature on horizontal sliders breaks. 331 if ( /webkit.*Chrome.*Mobile/i.test( navigator.userAgent ) ) { 332 pageOffset.x = 0; 333 } 334 return orientation ? rect.top + pageOffset.y - docElem.clientTop : rect.left + pageOffset.x - docElem.clientLeft; 335 } 336 // Checks whether a value is numerical. 337 function isNumeric( a ) { 338 return typeof a === 'number' && ! isNaN( a ) && isFinite( a ); 339 } 340 // Sets a class and removes it after [duration] ms. 341 function addClassFor( element, className, duration ) { 342 if ( duration > 0 ) { 343 addClass( element, className ); 344 setTimeout( function() { 345 removeClass( element, className ); 346 }, duration ); 347 } 348 } 349 // Limits a value to 0 - 100 350 function limit( a ) { 351 return Math.max( Math.min( a, 100 ), 0 ); 352 } 353 // Wraps a variable as an array, if it isn't one yet. 354 // Note that an input array is returned by reference! 355 function asArray( a ) { 356 return Array.isArray( a ) ? a : [ a ]; 357 } 358 // Counts decimals 359 function countDecimals( numStr ) { 360 var pieces; 361 numStr = String( numStr ); 362 pieces = numStr.split( '.' ); 363 return pieces.length > 1 ? pieces[ 1 ].length : 0; 364 } 365 // http://youmightnotneedjquery.com/#add_class 366 function addClass( el, className ) { 367 if ( el.classList && ! /\s/.test( className ) ) { 368 el.classList.add( className ); 369 } else { 370 el.className += ' ' + className; 371 } 372 } 373 // http://youmightnotneedjquery.com/#remove_class 374 function removeClass( el, className ) { 375 if ( el.classList && ! /\s/.test( className ) ) { 376 el.classList.remove( className ); 377 } else { 378 el.className = el.className.replace( new RegExp( '(^|\\b)' + className.split( ' ' ).join( '|' ) + '(\\b|$)', 'gi' ), ' ' ); 379 } 380 } 381 // https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/ 382 function hasClass( el, className ) { 383 return el.classList ? el.classList.contains( className ) : new RegExp( '\\b' + className + '\\b' ).test( el.className ); 384 } 385 // https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes 386 function getPageOffset( doc ) { 387 var supportPageOffset = window.pageXOffset !== undefined; 388 var isCSS1Compat = ( doc.compatMode || '' ) === 'CSS1Compat'; 389 var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? doc.documentElement.scrollLeft : doc.body.scrollLeft; 390 var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? doc.documentElement.scrollTop : doc.body.scrollTop; 391 return { 392 x: x, 393 y: y 394 }; 395 } 396 // we provide a function to compute constants instead 397 // of accessing window.* as soon as the module needs it 398 // so that we do not compute anything if not needed 399 function getActions() { 400 // Determine the events to bind. IE11 implements pointerEvents without 401 // a prefix, which breaks compatibility with the IE10 implementation. 402 return window.navigator.pointerEnabled ? { 403 start: 'pointerdown', 404 move: 'pointermove', 405 end: 'pointerup' 406 } : window.navigator.msPointerEnabled ? { 407 start: 'MSPointerDown', 408 move: 'MSPointerMove', 409 end: 'MSPointerUp' 410 } : { 411 start: 'mousedown touchstart', 412 move: 'mousemove touchmove', 413 end: 'mouseup touchend' 414 }; 415 } 416 // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md 417 // Issue #785
418 function getSupportsPassive() { 419 var supportsPassive = false; 420 /* eslint-disable */ 421 try { 422 var opts = Object.defineProperty({}, "passive", { 423 get: function () { 424 supportsPassive = true; 425 }, 426 }); 427 // @ts-ignore 428 window.addEventListener("test", null, opts); 429 } 430 catch (e) { } 431 /* eslint-enable */ 432 return supportsPassive; 433 } 434 function getSupportsTouchActionNone() { 435 return window.CSS && CSS.supports && CSS.supports( 'touch-action', 'none' ); 436 } 437 //endregion 438 //region Range Calculation 439 // Determine the size of a sub-range in relation to a full range. 440 function subRangeRatio( pa, pb ) { 441 return 100 / ( pb - pa ); 442 } 443 // (percentage) How many percent is this value of this range? 444 function fromPercentage( range, value, startRange ) { 445 return ( value * 100 ) / ( range[ startRange + 1 ] - range[ startRange ] ); 446 } 447 // (percentage) Where is this value on this range? 448 function toPercentage( range, value ) { 449 return fromPercentage( range, range[ 0 ] < 0 ? value + Math.abs( range[ 0 ] ) : value - range[ 0 ], 0 ); 450 } 451 // (value) How much is this percentage on this range? 452 function isPercentage( range, value ) { 453 return ( ( value * ( range[ 1 ] - range[ 0 ] ) ) / 100 ) + range[ 0 ]; 454 } 455 function getJ( value, arr ) { 456 var j = 1; 457 while ( value >= arr[ j ] ) { 458 j += 1; 459 } 460 return j; 461 } 462 // (percentage) Input a value, find where, on a scale of 0-100, it applies. 463 function toStepping( xVal, xPct, value ) { 464 var j; 465 var va; 466 var vb; 467 var pa; 468 var pb; 469 if ( value >= xVal.slice( -1 )[ 0 ] ) { 470 return 100; 471 } 472 j = getJ( value, xVal ); 473 va = xVal[ j - 1 ]; 474 vb = xVal[ j ]; 475 pa = xPct[ j - 1 ]; 476 pb = xPct[ j ]; 477 return pa + ( toPercentage( [ va, vb ], value ) / subRangeRatio( pa, pb ) ); 478 } 479 // (value) Input a percentage, find where it is on the specified range. 480 function fromStepping( xVal, xPct, value ) { 481 var j; 482 var va; 483 var vb; 484 var pa; 485 var pb; 486 // There is no range group that fits 100 487 if ( value >= 100 ) { 488 return xVal.slice( -1 )[ 0 ]; 489 } 490 j = getJ( value, xPct ); 491 va = xVal[ j - 1 ]; 492 vb = xVal[ j ]; 493 pa = xPct[ j - 1 ]; 494 pb = xPct[ j ]; 495 return isPercentage( [ va, vb ], ( value - pa ) * subRangeRatio( pa, pb ) ); 496 } 497 // (percentage) Get the step that applies at a certain value. 498 function getStep( xPct, xSteps, snap, value ) { 499 var j; 500 var a; 501 var b; 502 if ( value === 100 ) { 503 return value; 504 } 505 j = getJ( value, xPct ); 506 a = xPct[ j - 1 ]; 507 b = xPct[ j ]; 508 // If 'snap' is set, steps are used as fixed points on the slider. 509 if ( snap ) { 510 // Find the closest position, a or b. 511 if ( value - a > ( b - a ) / 2 ) { 512 return b; 513 } 514 return a; 515 } 516 if ( ! xSteps[ j - 1 ] ) { 517 return value; 518 } 519 return xPct[ j - 1 ] + closest( value - xPct[ j - 1 ], xSteps[ j - 1 ] ); 520 } 521 //endregion 522 //region Options 523 /* Every input option is tested and parsed. This will prevent 524 endless validation in internal methods. These tests are 525 structured with an item for every option available. An 526 option can be marked as required by setting the 'r' flag. 527 The testing function is provided with three arguments: 528 - The provided value for the option; 529 - A reference to the options object; 530 - The name for the option; 531 532 The testing function returns false when an error is detected, 533 or true when everything is OK. It can also modify the option 534 object, to make sure all values can be correctly looped elsewhere. */ 535 536 function testStep( parsed, entry ) { 537 if ( ! isNumeric( entry ) ) { 538 throw new Error( "noUiSlider: 'step' is not numeric." ); 539 } 540 // The step option can still be used to set stepping 541 // for linear sliders. Overwritten if set in 'range'. 542 parsed.singleStep = entry; 543 } 544 function testKeyboardPageMultiplier( parsed, entry ) { 545 if ( ! isNumeric( entry ) ) { 546 throw new Error( "noUiSlider: 'keyboardPageMultiplier' is not numeric." ); 547 } 548 parsed.keyboardPageMultiplier = entry; 549 } 550 function testKeyboardMultiplier( parsed, entry ) { 551 if ( ! isNumeric( entry ) ) { 552 throw new Error( "noUiSlider: 'keyboardMultiplier' is not numeric." ); 553 } 554 parsed.keyboardMultiplier = entry; 555 } 556 function testKeyboardDefaultStep( parsed, entry ) { 557 if ( ! isNumeric( entry ) ) { 558 throw new Error( "noUiSlider: 'keyboardDefaultStep' is not numeric." ); 559 } 560 parsed.keyboardDefaultStep = entry; 561 } 562 function testRange( parsed, entry ) { 563 // Filter incorrect input. 564 if ( typeof entry !== 'object' || Array.isArray( entry ) ) { 565 throw new Error( "noUiSlider: 'range' is not an object." ); 566 } 567 // Catch missing start or end. 568 if ( entry.min === undefined || entry.max === undefined ) { 569 throw new Error( "noUiSlider: Missing 'min' or 'max' in 'range'." ); 570 } 571 parsed.spectrum = new Spectrum( entry, parsed.snap || false, parsed.singleStep ); 572 } 573 function testStart( parsed, entry ) { 574 entry = asArray( entry ); 575 // Validate input. Values aren't tested, as the public .val method 576 // will always provide a valid location. 577 if ( ! Array.isArray( entry ) || ! entry.length ) { 578 throw new Error( "noUiSlider: 'start' option is incorrect." ); 579 } 580 // Store the number of handles. 581 parsed.handles = entry.length;
vendor: 7,473 bytes, lines 582-808
582 // When the slider is initialized, the .val method will 583 // be called with the start options. 584 parsed.start = entry; 585 } 586 function testSnap( parsed, entry ) { 587 if ( typeof entry !== 'boolean' ) { 588 throw new Error( "noUiSlider: 'snap' option must be a boolean." ); 589 } 590 // Enforce 100% stepping within subranges. 591 parsed.snap = entry; 592 } 593 function testAnimate( parsed, entry ) { 594 if ( typeof entry !== 'boolean' ) { 595 throw new Error( "noUiSlider: 'animate' option must be a boolean." ); 596 } 597 // Enforce 100% stepping within subranges. 598 parsed.animate = entry; 599 } 600 function testAnimationDuration( parsed, entry ) { 601 if ( typeof entry !== 'number' ) { 602 throw new Error( "noUiSlider: 'animationDuration' option must be a number." ); 603 } 604 parsed.animationDuration = entry; 605 } 606 function testConnect( parsed, entry ) { 607 var connect = [ false ]; 608 var i; 609 // Map legacy options 610 if ( entry === 'lower' ) { 611 entry = [ true, false ]; 612 } else if ( entry === 'upper' ) { 613 entry = [ false, true ]; 614 } 615 // Handle boolean options 616 if ( entry === true || entry === false ) { 617 for ( i = 1; i < parsed.handles; i++ ) { 618 connect.push( entry ); 619 } 620 connect.push( false ); 621 } else if ( ! Array.isArray( entry ) || ! entry.length || entry.length !== parsed.handles + 1 ) { // Reject invalid input 622 throw new Error( "noUiSlider: 'connect' option doesn't match handle count." ); 623 } else { 624 connect = entry; 625 } 626 parsed.connect = connect; 627 } 628 function testOrientation( parsed, entry ) { 629 // Set orientation to an a numerical value for easy 630 // array selection. 631 switch ( entry ) { 632 case 'horizontal': 633 parsed.ort = 0; 634 break; 635 case 'vertical': 636 parsed.ort = 1; 637 break; 638 default: 639 throw new Error( "noUiSlider: 'orientation' option is invalid." ); 640 } 641 } 642 function testMargin( parsed, entry ) { 643 if ( ! isNumeric( entry ) ) { 644 throw new Error( "noUiSlider: 'margin' option must be numeric." ); 645 } 646 // Issue #582 647 if ( entry === 0 ) { 648 return; 649 } 650 parsed.margin = parsed.spectrum.getDistance( entry ); 651 } 652 function testLimit( parsed, entry ) { 653 if ( ! isNumeric( entry ) ) { 654 throw new Error( "noUiSlider: 'limit' option must be numeric." ); 655 } 656 parsed.limit = parsed.spectrum.getDistance( entry ); 657 if ( ! parsed.limit || parsed.handles < 2 ) { 658 throw new Error( "noUiSlider: 'limit' option is only supported on linear sliders with 2 or more handles." ); 659 } 660 } 661 function testPadding( parsed, entry ) { 662 var index; 663 var totalPadding; 664 var firstValue; 665 var lastValue; 666 if ( ! isNumeric( entry ) && ! Array.isArray( entry ) ) { 667 throw new Error( "noUiSlider: 'padding' option must be numeric or array of exactly 2 numbers." ); 668 } 669 if ( Array.isArray( entry ) && ! ( entry.length === 2 || isNumeric( entry[ 0 ] ) || isNumeric( entry[ 1 ] ) ) ) { 670 throw new Error( "noUiSlider: 'padding' option must be numeric or array of exactly 2 numbers." ); 671 } 672 if ( entry === 0 ) { 673 return; 674 } 675 if ( ! Array.isArray( entry ) ) { 676 entry = [ entry, entry ]; 677 } 678 // 'getDistance' returns false for invalid values. 679 parsed.padding = [ parsed.spectrum.getDistance( entry[ 0 ] ), parsed.spectrum.getDistance( entry[ 1 ] ) ]; 680 for ( index = 0; index < parsed.spectrum.xNumSteps.length - 1; index++ ) { 681 // last "range" can't contain step size as it is purely an endpoint. 682 if ( parsed.padding[ 0 ][ index ] < 0 || parsed.padding[ 1 ][ index ] < 0 ) { 683 throw new Error( "noUiSlider: 'padding' option must be a positive number(s)." ); 684 } 685 } 686 totalPadding = entry[ 0 ] + entry[ 1 ]; 687 firstValue = parsed.spectrum.xVal[ 0 ]; 688 lastValue = parsed.spectrum.xVal[ parsed.spectrum.xVal.length - 1 ]; 689 if ( totalPadding / ( lastValue - firstValue ) > 1 ) { 690 throw new Error( "noUiSlider: 'padding' option must not exceed 100% of the range." ); 691 } 692 } 693 function testDirection( parsed, entry ) { 694 // Set direction as a numerical value for easy parsing. 695 // Invert connection for RTL sliders, so that the proper 696 // handles get the connect/background classes. 697 switch ( entry ) { 698 case 'ltr': 699 parsed.dir = 0; 700 break; 701 case 'rtl': 702 parsed.dir = 1; 703 break; 704 default: 705 throw new Error( "noUiSlider: 'direction' option was not recognized." ); 706 } 707 } 708 function testBehaviour( parsed, entry ) { 709 var tap; 710 var drag; 711 var fixed; 712 var snap; 713 var hover; 714 var unconstrained; 715 var dragAll; 716 var smoothSteps; 717 // Make sure the input is a string. 718 if ( typeof entry !== 'string' ) { 719 throw new Error( "noUiSlider: 'behaviour' must be a string containing options." ); 720 } 721 // Check if the string contains any keywords. 722 // None are required. 723 tap = entry.indexOf( 'tap' ) >= 0; 724 drag = entry.indexOf( 'drag' ) >= 0; 725 fixed = entry.indexOf( 'fixed' ) >= 0; 726 snap = entry.indexOf( 'snap' ) >= 0; 727 hover = entry.indexOf( 'hover' ) >= 0; 728 unconstrained = entry.indexOf( 'unconstrained' ) >= 0; 729 dragAll = entry.indexOf( 'drag-all' ) >= 0; 730 smoothSteps = entry.indexOf( 'smooth-steps' ) >= 0; 731 if ( fixed ) { 732 if ( parsed.handles !== 2 ) { 733 throw new Error( "noUiSlider: 'fixed' behaviour must be used with 2 handles" ); 734 } 735 // Use margin to enforce fixed state 736 testMargin( parsed, parsed.start[ 1 ] - parsed.start[ 0 ] ); 737 } 738 if ( unconstrained && ( parsed.margin || parsed.limit ) ) { 739 throw new Error( "noUiSlider: 'unconstrained' behaviour cannot be used with margin or limit" ); 740 } 741 parsed.events = { 742 tap: tap || snap, 743 drag: drag, 744 dragAll: dragAll, 745 smoothSteps: smoothSteps, 746 fixed: fixed, 747 snap: snap, 748 hover: hover, 749 unconstrained: unconstrained 750 }; 751 } 752 function testTooltips( parsed, entry ) { 753 var i; 754 if ( entry === false ) { 755 return; 756 } 757 if ( entry === true || isValidPartialFormatter( entry ) ) { 758 parsed.tooltips = []; 759 for ( i = 0; i < parsed.handles; i++ ) { 760 parsed.tooltips.push( entry ); 761 } 762 } else { 763 entry = asArray( entry ); 764 if ( entry.length !== parsed.handles ) { 765 throw new Error( 'noUiSlider: must pass a formatter for all handles.' ); 766 } 767 entry.forEach( function( formatter ) { 768 if ( typeof formatter !== 'boolean' && ! isValidPartialFormatter( formatter ) ) { 769 throw new Error( "noUiSlider: 'tooltips' must be passed a formatter or 'false'." ); 770 } 771 } ); 772 parsed.tooltips = entry; 773 } 774 } 775 function testHandleAttributes( parsed, entry ) { 776 if ( entry.length !== parsed.handles ) { 777 throw new Error( 'noUiSlider: must pass a attributes for all handles.' ); 778 } 779 parsed.handleAttributes = entry; 780 } 781 function testAriaFormat( parsed, entry ) { 782 if ( ! isValidPartialFormatter( entry ) ) { 783 throw new Error( "noUiSlider: 'ariaFormat' requires 'to' method." ); 784 } 785 parsed.ariaFormat = entry; 786 } 787 function testFormat( parsed, entry ) { 788 if ( ! isValidFormatter( entry ) ) { 789 throw new Error( "noUiSlider: 'format' requires 'to' and 'from' methods." ); 790 } 791 parsed.format = entry; 792 } 793 function testKeyboardSupport( parsed, entry ) { 794 if ( typeof entry !== 'boolean' ) { 795 throw new Error( "noUiSlider: 'keyboardSupport' option must be a boolean." ); 796 } 797 parsed.keyboardSupport = entry; 798 } 799 function testDocumentElement( parsed, entry ) { 800 // This is an advanced option. Passed values are used without validation. 801 parsed.documentElement = entry; 802 } 803 function testCssPrefix( parsed, entry ) { 804 if ( typeof entry !== 'string' && entry !== false ) { 805 throw new Error( "noUiSlider: 'cssPrefix' must be a string or `false`." ); 806 } 807 parsed.cssPrefix = entry; 808 }
809 function testCssClasses( parsed, entry ) { 810 if ( typeof entry !== 'object' ) { 811 throw new Error( "noUiSlider: 'cssClasses' must be an object." ); 812 } 813 if ( typeof parsed.cssPrefix === 'string' ) { 814 parsed.cssClasses = {}; 815 Object.keys( entry ).forEach( function( key ) { 816 parsed.cssClasses[ key ] = parsed.cssPrefix + entry[ key ]; 817 } ); 818 } else { 819 parsed.cssClasses = entry; 820 } 821 } 822 // Test all developer settings and parse to assumption-safe values. 823 function testOptions( options ) { 824 // To prove a fix for #537, freeze options here. 825 // If the object is modified, an error will be thrown. 826 // Object.freeze(options); 827 var parsed = { 828 margin: null, 829 limit: null, 830 padding: null, 831 animate: true, 832 animationDuration: 300, 833 ariaFormat: defaultFormatter, 834 format: defaultFormatter 835 }; 836 // Tests are executed in the order they are presented here. 837 var tests = { 838 step: { r: false, t: testStep }, 839 keyboardPageMultiplier: { r: false, t: testKeyboardPageMultiplier }, 840 keyboardMultiplier: { r: false, t: testKeyboardMultiplier }, 841 keyboardDefaultStep: { r: false, t: testKeyboardDefaultStep }, 842 start: { r: true, t: testStart }, 843 connect: { r: true, t: testConnect }, 844 direction: { r: true, t: testDirection }, 845 snap: { r: false, t: testSnap }, 846 animate: { r: false, t: testAnimate }, 847 animationDuration: { r: false, t: testAnimationDuration }, 848 range: { r: true, t: testRange }, 849 orientation: { r: false, t: testOrientation }, 850 margin: { r: false, t: testMargin }, 851 limit: { r: false, t: testLimit }, 852 padding: { r: false, t: testPadding }, 853 behaviour: { r: true, t: testBehaviour }, 854 ariaFormat: { r: false, t: testAriaFormat }, 855 format: { r: false, t: testFormat }, 856 tooltips: { r: false, t: testTooltips }, 857 keyboardSupport: { r: true, t: testKeyboardSupport }, 858 documentElement: { r: false, t: testDocumentElement }, 859 cssPrefix: { r: true, t: testCssPrefix },
860 cssClasses: { r: true, t: testCssClasses }, 861 handleAttributes: { r: false, t: testHandleAttributes } 862 }; 863 var defaults = { 864 connect: false, 865 direction: 'ltr', 866 behaviour: 'tap', 867 orientation: 'horizontal', 868 keyboardSupport: true, 869 cssPrefix: 'noui-', 870 cssClasses: cssClasses, 871 keyboardPageMultiplier: 5, 872 keyboardMultiplier: 1, 873 keyboardDefaultStep: 10 874 }; 875 var d; 876 var msPrefix; 877 var noPrefix; 878 var styles; 879 // AriaFormat defaults to regular format, if any. 880 if ( options.format && ! options.ariaFormat ) { 881 options.ariaFormat = options.format; 882 } 883 // Run all options through a testing mechanism to ensure correct 884 // input. It should be noted that options might get modified to 885 // be handled properly. E.g. wrapping integers in arrays. 886 Object.keys( tests ).forEach( function( name ) { 887 // If the option isn't set, but it is required, throw an error. 888 if ( ! isSet( options[ name ] ) && defaults[ name ] === undefined ) { 889 if ( tests[ name ].r ) { 890 throw new Error( "noUiSlider: '" + name + "' is required." ); 891 } 892 return; 893 } 894 tests[ name ].t( parsed, ! isSet( options[ name ] ) ? defaults[ name ] : options[ name ] ); 895 } ); 896 // Forward pips options 897 parsed.pips = options.pips; 898 // All recent browsers accept unprefixed transform. 899 // We need -ms- for IE9 and -webkit- for older Android; 900 // Assume use of -webkit- if unprefixed and -ms- are not supported. 901 // https://caniuse.com/#feat=transforms2d 902 d = document.createElement( 'div' ); 903 msPrefix = d.style.msTransform !== undefined; 904 noPrefix = d.style.transform !== undefined; 905 parsed.transformRule = noPrefix ? 'transform' : msPrefix ? 'msTransform' : 'webkitTransform'; 906 // Pips don't move, so we can place them using left/top. 907 styles = [ 908 [ 'left', 'top' ], 909 [ 'right', 'bottom' ] 910 ]; 911 parsed.style = styles[ parsed.dir ][ parsed.ort ]; 912 return parsed; 913 } 914 //endregion 915 function scope( target, options, originalOptions ) { 916 var actions = getActions(); 917 var supportsTouchActionNone = getSupportsTouchActionNone(); 918 var supportsPassive = supportsTouchActionNone && getSupportsPassive(); 919 // All variables local to 'scope' are prefixed with 'scope_' 920 // Slider DOM Nodes 921 var scope_Target = target; 922 var scope_Base; 923 var scope_Handles; 924 var scope_Connects; 925 var scope_Pips; 926 var scope_Tooltips; 927 // Slider state values 928 var scope_Spectrum = options.spectrum; 929 var scope_Values = []; 930 var scope_Locations = []; 931 var scope_HandleNumbers = []; 932 var scope_ActiveHandlesCount = 0; 933 var scope_Events = {}; 934 // Document Nodes 935 var scope_Document = target.ownerDocument; 936 var scope_DocumentElement = options.documentElement || scope_Document.documentElement; 937 var scope_Body = scope_Document.body; 938 // For horizontal sliders in standard ltr documents, 939 // make .noUi-origin overflow to the left so the document doesn't scroll. 940 var scope_DirOffset = scope_Document.dir === 'rtl' || options.ort === 1 ? 0 : 100; 941 var scope_Self; 942 // Creates a node, adds it to target, returns the new node. 943 function addNodeTo( addTarget, className ) { 944 var div = scope_Document.createElement( 'div' ); 945 if ( className ) { 946 addClass( div, className ); 947 } 948 addTarget.appendChild( div ); 949 return div; 950 } 951 // Append a origin to the base 952 function addOrigin( base, handleNumber ) { 953 var origin = addNodeTo( base, options.cssClasses.origin ); 954 var handle = addNodeTo( origin, options.cssClasses.handle ); 955 var attributes_1; 956 addNodeTo( handle, options.cssClasses.touchArea ); 957 handle.setAttribute( 'data-handle', String( handleNumber ) ); 958 if ( options.keyboardSupport ) { 959 // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex 960 // 0 = focusable and reachable 961 handle.setAttribute( 'tabindex', '0' ); 962 handle.addEventListener( 'keydown', function( event ) {
vendor: 19,677 bytes, lines 963-1460
963 return eventKeydown( event, handleNumber ); 964 } ); 965 } 966 if ( options.handleAttributes !== undefined ) { 967 attributes_1 = options.handleAttributes[ handleNumber ]; 968 Object.keys( attributes_1 ).forEach( function( attribute ) { 969 handle.setAttribute( attribute, attributes_1[ attribute ] ); 970 } ); 971 } 972 handle.setAttribute( 'role', 'slider' ); 973 handle.setAttribute( 'aria-orientation', options.ort ? 'vertical' : 'horizontal' ); 974 if ( handleNumber === 0 ) { 975 addClass( handle, options.cssClasses.handleLower ); 976 } else if ( handleNumber === options.handles - 1 ) { 977 addClass( handle, options.cssClasses.handleUpper ); 978 } 979 origin.handle = handle; 980 return origin; 981 } 982 // Insert nodes for connect elements 983 function addConnect( base, add ) { 984 if ( ! add ) { 985 return false; 986 } 987 return addNodeTo( base, options.cssClasses.connect ); 988 } 989 // Add handles to the slider base. 990 function addElements( connectOptions, base ) { 991 var connectBase = addNodeTo( base, options.cssClasses.connects ); 992 var i; 993 scope_Handles = []; 994 scope_Connects = []; 995 scope_Connects.push( addConnect( connectBase, connectOptions[ 0 ] ) ); 996 // [::::O====O====O====] 997 // connectOptions = [0, 1, 1, 1] 998 for ( i = 0; i < options.handles; i++ ) { 999 // Keep a list of all added handles. 1000 scope_Handles.push( addOrigin( base, i ) ); 1001 scope_HandleNumbers[ i ] = i; 1002 scope_Connects.push( addConnect( connectBase, connectOptions[ i + 1 ] ) ); 1003 } 1004 } 1005 // Initialize a single slider. 1006 function addSlider( addTarget ) { 1007 var textDirection; 1008 // Apply classes and data to the target. 1009 addClass( addTarget, options.cssClasses.target ); 1010 if ( options.dir === 0 ) { 1011 addClass( addTarget, options.cssClasses.ltr ); 1012 } else { 1013 addClass( addTarget, options.cssClasses.rtl ); 1014 } 1015 if ( options.ort === 0 ) { 1016 addClass( addTarget, options.cssClasses.horizontal ); 1017 } else { 1018 addClass( addTarget, options.cssClasses.vertical ); 1019 } 1020 textDirection = getComputedStyle( addTarget ).direction; 1021 if ( textDirection === 'rtl' ) { 1022 addClass( addTarget, options.cssClasses.textDirectionRtl ); 1023 } else { 1024 addClass( addTarget, options.cssClasses.textDirectionLtr ); 1025 } 1026 return addNodeTo( addTarget, options.cssClasses.base ); 1027 } 1028 function addTooltip( handle, handleNumber ) { 1029 if ( ! options.tooltips || ! options.tooltips[ handleNumber ] ) { 1030 return false; 1031 } 1032 return addNodeTo( handle.firstChild, options.cssClasses.tooltip ); 1033 } 1034 function isSliderDisabled() { 1035 return scope_Target.hasAttribute( 'disabled' ); 1036 } 1037 // Disable the slider dragging if any handle is disabled 1038 function isHandleDisabled( handleNumber ) { 1039 var handleOrigin = scope_Handles[ handleNumber ]; 1040 return handleOrigin.hasAttribute( 'disabled' ); 1041 } 1042 function disable( handleNumber ) { 1043 if ( handleNumber !== null && handleNumber !== undefined ) { 1044 scope_Handles[ handleNumber ].setAttribute( 'disabled', '' ); 1045 scope_Handles[ handleNumber ].handle.removeAttribute( 'tabindex' ); 1046 } else { 1047 scope_Target.setAttribute( 'disabled', '' ); 1048 scope_Handles.forEach( function( handle ) { 1049 handle.handle.removeAttribute( 'tabindex' ); 1050 } ); 1051 } 1052 } 1053 function enable( handleNumber ) { 1054 if ( handleNumber !== null && handleNumber !== undefined ) { 1055 scope_Handles[ handleNumber ].removeAttribute( 'disabled' ); 1056 scope_Handles[ handleNumber ].handle.setAttribute( 'tabindex', '0' ); 1057 } else { 1058 scope_Target.removeAttribute( 'disabled' ); 1059 scope_Handles.forEach( function( handle ) { 1060 handle.removeAttribute( 'disabled' ); 1061 handle.handle.setAttribute( 'tabindex', '0' ); 1062 } ); 1063 } 1064 } 1065 function removeTooltips() { 1066 if ( scope_Tooltips ) { 1067 removeEvent( 'update' + INTERNAL_EVENT_NS.tooltips ); 1068 scope_Tooltips.forEach( function( tooltip ) { 1069 if ( tooltip ) { 1070 removeElement( tooltip ); 1071 } 1072 } ); 1073 scope_Tooltips = null; 1074 } 1075 } 1076 // The tooltips option is a shorthand for using the 'update' event. 1077 function tooltips() { 1078 var formattedValue; 1079 removeTooltips(); 1080 // Tooltips are added with options.tooltips in original order. 1081 scope_Tooltips = scope_Handles.map( addTooltip ); 1082 bindEvent( 'update' + INTERNAL_EVENT_NS.tooltips, function( values, handleNumber, unencoded ) { 1083 if ( ! scope_Tooltips || ! options.tooltips ) { 1084 return; 1085 } 1086 if ( scope_Tooltips[ handleNumber ] === false ) { 1087 return; 1088 } 1089 formattedValue = values[ handleNumber ]; 1090 if ( options.tooltips[ handleNumber ] !== true ) { 1091 formattedValue = options.tooltips[ handleNumber ].to( unencoded[ handleNumber ] ); 1092 } 1093 scope_Tooltips[ handleNumber ].innerHTML = formattedValue; 1094 } ); 1095 } 1096 function aria() { 1097 removeEvent( 'update' + INTERNAL_EVENT_NS.aria ); 1098 bindEvent( 'update' + INTERNAL_EVENT_NS.aria, function( values, handleNumber, unencoded, tap, positions ) { 1099 // Update Aria Values for all handles, as a change in one changes min and max values for the next. 1100 scope_HandleNumbers.forEach( function( index ) { 1101 var handle = scope_Handles[ index ]; 1102 var min = checkHandlePosition( scope_Locations, index, 0, true, true, true ); 1103 var max = checkHandlePosition( scope_Locations, index, 100, true, true, true ); 1104 var now = positions[ index ]; 1105 // Formatted value for display 1106 var text = String( options.ariaFormat.to( unencoded[ index ] ) ); 1107 // Map to slider range values 1108 min = scope_Spectrum.fromStepping( min ).toFixed( 1 ); 1109 max = scope_Spectrum.fromStepping( max ).toFixed( 1 ); 1110 now = scope_Spectrum.fromStepping( now ).toFixed( 1 ); 1111 handle.children[ 0 ].setAttribute( 'aria-valuemin', min ); 1112 handle.children[ 0 ].setAttribute( 'aria-valuemax', max ); 1113 handle.children[ 0 ].setAttribute( 'aria-valuenow', now ); 1114 handle.children[ 0 ].setAttribute( 'aria-valuetext', text ); 1115 } ); 1116 } ); 1117 } 1118 function getGroup( ipips ) { 1119 var interval; 1120 var spread; 1121 var values; 1122 // Use the range. 1123 if ( ipips.mode === exports.PipsMode.Range || ipips.mode === exports.PipsMode.Steps ) { 1124 return scope_Spectrum.xVal; 1125 } 1126 if ( ipips.mode === exports.PipsMode.Count ) { 1127 if ( ipips.values < 2 ) { 1128 throw new Error( "noUiSlider: 'values' (>= 2) required for mode 'count'." ); 1129 } 1130 // Divide 0 - 100 in 'count' parts. 1131 interval = ipips.values - 1; 1132 spread = 100 / interval; 1133 values = []; 1134 // List these parts and have them handled as 'positions'. 1135 while ( interval-- ) { 1136 values[ interval ] = interval * spread; 1137 } 1138 values.push( 100 ); 1139 return mapToRange( values, ipips.stepped ); 1140 } 1141 if ( ipips.mode === exports.PipsMode.Positions ) { 1142 // Map all percentages to on-range values. 1143 return mapToRange( ipips.values, ipips.stepped ); 1144 } 1145 if ( ipips.mode === exports.PipsMode.Values ) { 1146 // If the value must be stepped, it needs to be converted to a percentage first. 1147 if ( ipips.stepped ) { 1148 return ipips.values.map( function( value ) { 1149 // Convert to percentage, apply step, return to value. 1150 return scope_Spectrum.fromStepping( scope_Spectrum.getStep( scope_Spectrum.toStepping( value ) ) ); 1151 } ); 1152 } 1153 // Otherwise, we can simply use the values. 1154 return ipips.values; 1155 } 1156 return []; // ipips.mode = never 1157 } 1158 function mapToRange( values, stepped ) { 1159 return values.map( function( value ) { 1160 return scope_Spectrum.fromStepping( stepped ? scope_Spectrum.getStep( value ) : value ); 1161 } ); 1162 } 1163 function generateSpread( ipips ) { 1164 var group = getGroup( ipips ); 1165 var indexes = {}; 1166 var firstInRange = scope_Spectrum.xVal[ 0 ]; 1167 var lastInRange = scope_Spectrum.xVal[ scope_Spectrum.xVal.length - 1 ]; 1168 var ignoreFirst = false; 1169 var ignoreLast = false; 1170 var prevPct = 0; 1171 function safeIncrement( value, increment ) { 1172 // Avoid floating point variance by dropping the smallest decimal places. 1173 return Number( ( value + increment ).toFixed( 7 ) ); 1174 } 1175 // Create a copy of the group, sort it and filter away all duplicates. 1176 group = unique( group.slice().sort( function( a, b ) { 1177 return a - b; 1178 } ) ); 1179 // Make sure the range starts with the first element. 1180 if ( group[ 0 ] !== firstInRange ) { 1181 group.unshift( firstInRange ); 1182 ignoreFirst = true; 1183 } 1184 // Likewise for the last one. 1185 if ( group[ group.length - 1 ] !== lastInRange ) { 1186 group.push( lastInRange ); 1187 ignoreLast = true; 1188 } 1189 group.forEach( function( current, index ) { 1190 // Get the current step and the lower + upper positions. 1191 var step; 1192 var i; 1193 var q; 1194 var low = current; 1195 var high = group[ index + 1 ]; 1196 var newPct; 1197 var pctDifference; 1198 var pctPos; 1199 var type; 1200 var steps; 1201 var realSteps; 1202 var stepSize; 1203 var isSteps = ipips.mode === exports.PipsMode.Steps; 1204 // When using 'steps' mode, use the provided steps. 1205 // Otherwise, we'll step on to the next subrange. 1206 if ( isSteps ) { 1207 step = scope_Spectrum.xNumSteps[ index ]; 1208 } 1209 // Default to a 'full' step. 1210 if ( ! step ) { 1211 step = high - low; 1212 } 1213 // If high is undefined we are at the last subrange. Make sure it iterates once (#1088) 1214 if ( high === undefined ) { 1215 high = low; 1216 } 1217 // Make sure step isn't 0, which would cause an infinite loop (#654) 1218 step = Math.max( step, 0.0000001 ); 1219 // Find all steps in the subrange. 1220 for ( i = low; i <= high; i = safeIncrement( i, step ) ) { 1221 // Get the percentage value for the current step, 1222 // calculate the size for the subrange. 1223 newPct = scope_Spectrum.toStepping( i ); 1224 pctDifference = newPct - prevPct; 1225 steps = pctDifference / ( ipips.density || 1 ); 1226 realSteps = Math.round( steps ); 1227 // This ratio represents the amount of percentage-space a point indicates. 1228 // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-divided. 1229 // Round the percentage offset to an even number, then divide by two 1230 // to spread the offset on both sides of the range. 1231 stepSize = pctDifference / realSteps; 1232 // Divide all points evenly, adding the correct number to this subrange. 1233 // Run up to <= so that 100% gets a point, event if ignoreLast is set. 1234 for ( q = 1; q <= realSteps; q += 1 ) { 1235 // The ratio between the rounded value and the actual size might be ~1% off. 1236 // Correct the percentage offset by the number of points 1237 // per subrange. density = 1 will result in 100 points on the 1238 // full range, 2 for 50, 4 for 25, etc. 1239 pctPos = prevPct + ( q * stepSize ); 1240 indexes[ pctPos.toFixed( 5 ) ] = [ scope_Spectrum.fromStepping( pctPos ), 0 ]; 1241 } 1242 // Determine the point type. 1243 type = group.indexOf( i ) > -1 ? exports.PipsType.LargeValue : isSteps ? exports.PipsType.SmallValue : exports.PipsType.NoValue; 1244 // Enforce the 'ignoreFirst' option by overwriting the type for 0. 1245 if ( ! index && ignoreFirst && i !== high ) { 1246 type = 0; 1247 } 1248 if ( ! ( i === high && ignoreLast ) ) { 1249 // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value. 1250 indexes[ newPct.toFixed( 5 ) ] = [ i, type ]; 1251 } 1252 // Update the percentage count. 1253 prevPct = newPct; 1254 } 1255 } ); 1256 return indexes; 1257 } 1258 function addMarking( spread, filterFunc, formatter ) { 1259 var _a, _b; 1260 var element = scope_Document.createElement( 'div' ); 1261 var valueSizeClasses = ( _a = {}, 1262 _a[ exports.PipsType.None ] = '', 1263 _a[ exports.PipsType.NoValue ] = options.cssClasses.valueNormal, 1264 _a[ exports.PipsType.LargeValue ] = options.cssClasses.valueLarge, 1265 _a[ exports.PipsType.SmallValue ] = options.cssClasses.valueSub, 1266 _a ); 1267 var markerSizeClasses = ( _b = {}, 1268 _b[ exports.PipsType.None ] = '', 1269 _b[ exports.PipsType.NoValue ] = options.cssClasses.markerNormal, 1270 _b[ exports.PipsType.LargeValue ] = options.cssClasses.markerLarge, 1271 _b[ exports.PipsType.SmallValue ] = options.cssClasses.markerSub, 1272 _b ); 1273 var valueOrientationClasses = [ options.cssClasses.valueHorizontal, options.cssClasses.valueVertical ]; 1274 var markerOrientationClasses = [ options.cssClasses.markerHorizontal, options.cssClasses.markerVertical ]; 1275 addClass( element, options.cssClasses.pips ); 1276 addClass( element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical ); 1277 function getClasses( type, source ) { 1278 var a = source === options.cssClasses.value; 1279 var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses; 1280 var sizeClasses = a ? valueSizeClasses : markerSizeClasses; 1281 return source + ' ' + orientationClasses[ options.ort ] + ' ' + sizeClasses[ type ]; 1282 } 1283 function addSpread( key, value, type ) { 1284 var node; 1285 // Apply the filter function, if it is set. 1286 type = filterFunc ? filterFunc( value, type ) : type; 1287 if ( type === exports.PipsType.None ) { 1288 return; 1289 } 1290 // Add a marker for every point 1291 node = addNodeTo( element, false ); 1292 node.className = getClasses( type, options.cssClasses.marker ); 1293 node.style[ options.style ] = key + '%'; 1294 // Values are only appended for points marked '1' or '2'. 1295 if ( type > exports.PipsType.NoValue ) { 1296 node = addNodeTo( element, false ); 1297 node.className = getClasses( type, options.cssClasses.value ); 1298 node.setAttribute( 'data-value', String( value ) ); 1299 node.style[ options.style ] = key + '%'; 1300 node.innerHTML = String( formatter.to( value ) ); 1301 } 1302 } 1303 // Append all points. 1304 Object.keys( spread ).forEach( function( key ) { 1305 addSpread( key, spread[ key ][ 0 ], spread[ key ][ 1 ] ); 1306 } ); 1307 return element; 1308 } 1309 function removePips() { 1310 if ( scope_Pips ) { 1311 removeElement( scope_Pips ); 1312 scope_Pips = null; 1313 } 1314 } 1315 function pips( ipips ) { 1316 var filter; 1317 var spread; 1318 var format; 1319 // Fix #669 1320 removePips(); 1321 spread = generateSpread( ipips ); 1322 filter = ipips.filter; 1323 format = ipips.format || { 1324 to: function( value ) { 1325 return String( Math.round( value ) ); 1326 } 1327 }; 1328 scope_Pips = scope_Target.appendChild( addMarking( spread, filter, format ) ); 1329 return scope_Pips; 1330 } 1331 // Shorthand for base dimensions. 1332 function baseSize() { 1333 var rect = scope_Base.getBoundingClientRect(); 1334 var alt = ( 'offset' + [ 'Width', 'Height' ][ options.ort ] ); 1335 return options.ort === 0 ? rect.width || scope_Base[ alt ] : rect.height || scope_Base[ alt ]; 1336 } 1337 // Handler for attaching events trough a proxy. 1338 function attachEvent( events, element, callback, data ) { 1339 // This function can be used to 'filter' events to the slider. 1340 // element is a node, not a nodeList 1341 var method = function( event ) { 1342 var e = fixEvent( event, data.pageOffset, data.target || element ); 1343 // fixEvent returns false if this event has a different target 1344 // when handling (multi-) touch events; 1345 if ( ! e ) { 1346 return false; 1347 } 1348 // doNotReject is passed by all end events to make sure released touches 1349 // are not rejected, leaving the slider "stuck" to the cursor; 1350 if ( isSliderDisabled() && ! data.doNotReject ) { 1351 return false; 1352 } 1353 // Stop if an active 'tap' transition is taking place. 1354 if ( hasClass( scope_Target, options.cssClasses.tap ) && ! data.doNotReject ) { 1355 return false; 1356 } 1357 // Ignore right or middle clicks on start #454 1358 if ( events === actions.start && e.buttons !== undefined && e.buttons > 1 ) { 1359 return false; 1360 } 1361 // Ignore right or middle clicks on start #454 1362 if ( data.hover && e.buttons ) { 1363 return false; 1364 } 1365 // 'supportsPassive' is only true if a browser also supports touch-action: none in CSS. 1366 // iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support 1367 // touch-action: manipulation, but that allows panning, which breaks 1368 // sliders after zooming/on non-responsive pages. 1369 // See: https://bugs.webkit.org/show_bug.cgi?id=133112 1370 if ( ! supportsPassive ) { 1371 e.preventDefault(); 1372 } 1373 e.calcPoint = e.points[ options.ort ]; 1374 // Call the event handler with the event [ and additional data ]. 1375 callback( e, data ); 1376 }; 1377 var methods = []; 1378 // Bind a closure on the target for every event type. 1379 events.split( ' ' ).forEach( function( eventName ) { 1380 element.addEventListener( eventName, method, supportsPassive ? { passive: true } : false ); 1381 methods.push( [ eventName, method ] ); 1382 } ); 1383 return methods; 1384 } 1385 // Provide a clean event with standardized offset values. 1386 function fixEvent( e, pageOffset, eventTarget ) { 1387 // Filter the event to register the type, which can be 1388 // touch, mouse or pointer. Offset changes need to be 1389 // made on an event specific basis. 1390 var touch = e.type.indexOf( 'touch' ) === 0; 1391 var mouse = e.type.indexOf( 'mouse' ) === 0; 1392 var pointer = e.type.indexOf( 'pointer' ) === 0; 1393 var x = 0; 1394 var y = 0; 1395 var isTouchOnTarget; 1396 var targetTouches; 1397 var targetTouch; 1398 // IE10 implemented pointer events with a prefix; 1399 if ( e.type.indexOf( 'MSPointer' ) === 0 ) { 1400 pointer = true; 1401 } 1402 // Erroneous events seem to be passed in occasionally on iOS/iPadOS after user finishes interacting with 1403 // the slider. They appear to be of type MouseEvent, yet they don't have usual properties set. Ignore 1404 // events that have no touches or buttons associated with them. (#1057, #1079, #1095) 1405 if ( e.type === 'mousedown' && ! e.buttons && ! e.touches ) { 1406 return false; 1407 } 1408 // The only thing one handle should be concerned about is the touches that originated on top of it. 1409 if ( touch ) { 1410 // Returns true if a touch originated on the target. 1411 isTouchOnTarget = function( checkTouch ) { 1412 return ( checkTouch.target === eventTarget || 1413 eventTarget.contains( checkTouch.target ) || 1414 ( e.composed && e.composedPath().shift() === eventTarget ) ); 1415 }; 1416 // In the case of touchstart events, we need to make sure there is still no more than one 1417 // touch on the target so we look amongst all touches. 1418 if ( e.type === 'touchstart' ) { 1419 targetTouches = Array.prototype.filter.call( e.touches, isTouchOnTarget ); 1420 // Do not support more than one touch per handle. 1421 if ( targetTouches.length > 1 ) { 1422 return false; 1423 } 1424 x = targetTouches[ 0 ].pageX; 1425 y = targetTouches[ 0 ].pageY; 1426 } else { 1427 // In the other cases, find on changedTouches is enough. 1428 targetTouch = Array.prototype.find.call( e.changedTouches, isTouchOnTarget ); 1429 // Cancel if the target touch has not moved. 1430 if ( ! targetTouch ) { 1431 return false; 1432 } 1433 x = targetTouch.pageX; 1434 y = targetTouch.pageY; 1435 } 1436 } 1437 pageOffset = pageOffset || getPageOffset( scope_Document ); 1438 if ( mouse || pointer ) { 1439 x = e.clientX + pageOffset.x; 1440 y = e.clientY + pageOffset.y; 1441 } 1442 e.pageOffset = pageOffset; 1443 e.points = [ x, y ]; 1444 e.cursor = mouse || pointer; // Fix #435 1445 return e; 1446 } 1447 // Translate a coordinate in the document to a percentage on the slider 1448 function calcPointToPercentage( calcPoint ) { 1449 var location = calcPoint - offset( scope_Base, options.ort ); 1450 var proposal = ( location * 100 ) / baseSize(); 1451 // Clamp proposal between 0% and 100% 1452 // Out-of-bound coordinates may occur when .noUi-base pseudo-elements 1453 // are used (e.g. contained handles feature) 1454 proposal = limit( proposal ); 1455 return options.dir ? 100 - proposal : proposal; 1456 } 1457 // Find handle closest to a certain percentage on the slider 1458 function getClosestHandle( clickedPosition ) { 1459 var smallestDifference = 100; 1460 var handleNumber = false;
1461 scope_Handles.forEach( function( handle, index ) { 1462 var handlePosition; 1463 var differenceWithThisHandle; 1464 var clickAtEdge; 1465 var isCloser; 1466 var isCloserAfter; 1467 // Disabled handles are ignored 1468 if ( isHandleDisabled( index ) ) { 1469 return; 1470 } 1471 handlePosition = scope_Locations[ index ]; 1472 differenceWithThisHandle = Math.abs( handlePosition - clickedPosition ); 1473 // Initial state 1474 clickAtEdge = differenceWithThisHandle === 100 && smallestDifference === 100; 1475 // Difference with this handle is smaller than the previously checked handle 1476 isCloser = differenceWithThisHandle < smallestDifference; 1477 isCloserAfter = differenceWithThisHandle <= smallestDifference && clickedPosition > handlePosition; 1478 if ( isCloser || isCloserAfter || clickAtEdge ) { 1479 handleNumber = index; 1480 smallestDifference = differenceWithThisHandle; 1481 } 1482 } ); 1483 return handleNumber; 1484 } 1485 // Fire 'end' when a mouse or pen leaves the document. 1486 function documentLeave( event, data ) { 1487 if ( event.type === 'mouseout' && 1488 event.target.nodeName === 'HTML' && 1489 event.relatedTarget === null ) { 1490 eventEnd( event, data ); 1491 } 1492 } 1493 // Handle movement on document for handle and range drag. 1494 function eventMove( event, data ) { 1495 var movement; 1496 var proposal; 1497 // Fix #498 1498 // Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty). 1499 // https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero 1500 // IE9 has .buttons and .which zero on mousemove. 1501 // Firefox breaks the spec MDN defines. 1502 if ( navigator.appVersion.indexOf( 'MSIE 9' ) === -1 && event.buttons === 0 && data.buttonsProperty !== 0 ) { 1503 return eventEnd( event, data ); 1504 } 1505 // Check if we are moving up or down 1506 movement = ( options.dir ? -1 : 1 ) * ( event.calcPoint - data.startCalcPoint ); 1507 // Convert the movement into a percentage of the slider width/height 1508 proposal = ( movement * 100 ) / data.baseSize; 1509 moveHandles( movement > 0, proposal, data.locations, data.handleNumbers, data.connect ); 1510 } 1511 // Unbind move events on document, call callbacks. 1512 function eventEnd( event, data ) { 1513 // The handle is no longer active, so remove the class. 1514 if ( data.handle ) { 1515 removeClass( data.handle, options.cssClasses.active ); 1516 scope_ActiveHandlesCount -= 1; 1517 } 1518 // Unbind the move and end events, which are added on 'start'. 1519 data.listeners.forEach( function( c ) { 1520 scope_DocumentElement.removeEventListener( c[ 0 ], c[ 1 ] ); 1521 } ); 1522 if ( scope_ActiveHandlesCount === 0 ) { 1523 // Remove dragging class. 1524 removeClass( scope_Target, options.cssClasses.drag ); 1525 setZindex(); 1526 // Remove cursor styles and text-selection events bound to the body. 1527 if ( event.cursor ) { 1528 scope_Body.style.cursor = ''; 1529 scope_Body.removeEventListener( 'selectstart', preventDefault ); 1530 } 1531 } 1532 if ( options.events.smoothSteps ) { 1533 data.handleNumbers.forEach( function( handleNumber ) { 1534 setHandle( handleNumber, scope_Locations[ handleNumber ], true, true, false, false ); 1535 } ); 1536 data.handleNumbers.forEach( function( handleNumber ) { 1537 fireEvent( 'update', handleNumber ); 1538 } ); 1539 } 1540 data.handleNumbers.forEach( function( handleNumber ) { 1541 fireEvent( 'change', handleNumber ); 1542 fireEvent( 'set', handleNumber ); 1543 fireEvent( 'end', handleNumber ); 1544 } ); 1545 } 1546 // Bind move events on document. 1547 function eventStart( event, data ) { 1548 var handle; 1549 var handleOrigin; 1550 var listeners; 1551 var moveEvent; 1552 var endEvent; 1553 var outEvent; 1554 // Ignore event if any handle is disabled 1555 if ( data.handleNumbers.some( isHandleDisabled ) ) { 1556 return; 1557 } 1558 if ( data.handleNumbers.length === 1 ) { 1559 handleOrigin = scope_Handles[ data.handleNumbers[ 0 ] ]; 1560 handle = handleOrigin.children[ 0 ]; 1561 scope_ActiveHandlesCount += 1; 1562 // Mark the handle as 'active' so it can be styled. 1563 addClass( handle, options.cssClasses.active ); 1564 } 1565 // A drag should never propagate up to the 'tap' event. 1566 event.stopPropagation(); 1567 // Record the event listeners. 1568 listeners = []; 1569 // Attach the move and end events. 1570 moveEvent = attachEvent( actions.move, scope_DocumentElement, eventMove, { 1571 // The event target has changed so we need to propagate the original one so that we keep 1572 // relying on it to extract target touches. 1573 target: event.target, 1574 handle: handle, 1575 connect: data.connect, 1576 listeners: listeners, 1577 startCalcPoint: event.calcPoint, 1578 baseSize: baseSize(), 1579 pageOffset: event.pageOffset, 1580 handleNumbers: data.handleNumbers, 1581 buttonsProperty: event.buttons, 1582 locations: scope_Locations.slice() 1583 } ); 1584 endEvent = attachEvent( actions.end, scope_DocumentElement, eventEnd, { 1585 target: event.target, 1586 handle: handle, 1587 listeners: listeners, 1588 doNotReject: true, 1589 handleNumbers: data.handleNumbers 1590 } ); 1591 outEvent = attachEvent( 'mouseout', scope_DocumentElement, documentLeave, { 1592 target: event.target, 1593 handle: handle, 1594 listeners: listeners, 1595 doNotReject: true, 1596 handleNumbers: data.handleNumbers 1597 } ); 1598 // We want to make sure we pushed the listeners in the listener list rather than creating 1599 // a new one as it has already been passed to the event handlers. 1600 listeners.push.apply( listeners, moveEvent.concat( endEvent, outEvent ) ); 1601 // Text selection isn't an issue on touch devices, 1602 // so adding cursor styles can be skipped. 1603 if ( event.cursor ) { 1604 // Prevent the 'I' cursor and extend the range-drag cursor. 1605 scope_Body.style.cursor = getComputedStyle( event.target ).cursor; 1606 // Mark the target with a dragging state. 1607 if ( scope_Handles.length > 1 ) {
1608 addClass( scope_Target, options.cssClasses.drag ); 1609 } 1610 // Prevent text selection when dragging the handles. 1611 // In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move, 1612 // which is scroll blocking. The selectstart event is supported by FireFox starting from version 52, 1613 // meaning the only holdout is iOS Safari. This doesn't matter: text selection isn't triggered there. 1614 // The 'cursor' flag is false. 1615 // See: http://caniuse.com/#search=selectstart 1616 scope_Body.addEventListener( 'selectstart', preventDefault, false ); 1617 } 1618 data.handleNumbers.forEach( function( handleNumber ) { 1619 fireEvent( 'start', handleNumber ); 1620 } ); 1621 } 1622 // Move closest handle to tapped location. 1623 function eventTap( event ) { 1624 var proposal; 1625 var handleNumber; 1626 // The tap event shouldn't propagate up 1627 event.stopPropagation(); 1628 proposal = calcPointToPercentage( event.calcPoint ); 1629 handleNumber = getClosestHandle( proposal ); 1630 // Tackle the case that all handles are 'disabled'. 1631 if ( handleNumber === false ) { 1632 return; 1633 } 1634 // Flag the slider as it is now in a transitional state. 1635 // Transition takes a configurable amount of ms (default 300). Re-enable the slider after that. 1636 if ( ! options.events.snap ) { 1637 addClassFor( scope_Target, options.cssClasses.tap, options.animationDuration ); 1638 } 1639 setHandle( handleNumber, proposal, true, true ); 1640 setZindex(); 1641 fireEvent( 'slide', handleNumber, true ); 1642 fireEvent( 'update', handleNumber, true ); 1643 if ( ! options.events.snap ) { 1644 fireEvent( 'change', handleNumber, true ); 1645 fireEvent( 'set', handleNumber, true ); 1646 } else { 1647 eventStart( event, { handleNumbers: [ handleNumber ] } ); 1648 } 1649 } 1650 // Fires a 'hover' event for a hovered mouse/pen position. 1651 function eventHover( event ) { 1652 var proposal = calcPointToPercentage( event.calcPoint ); 1653 var to = scope_Spectrum.getStep( proposal ); 1654 var value = scope_Spectrum.fromStepping( to ); 1655 Object.keys( scope_Events ).forEach( function( targetEvent ) { 1656 if ( 'hover' === targetEvent.split( '.' )[ 0 ] ) { 1657 scope_Events[ targetEvent ].forEach( function( callback ) { 1658 callback.call( scope_Self, value ); 1659 } ); 1660 } 1661 } ); 1662 } 1663 // Handles keydown on focused handles 1664 // Don't move the document when pressing arrow keys on focused handles 1665 function eventKeydown( event, handleNumber ) { 1666 var horizontalKeys; 1667 var verticalKeys; 1668 var largeStepKeys; 1669 var edgeKeys; 1670 var key; 1671 var isLargeDown; 1672 var isLargeUp; 1673 var isDown; 1674 var isUp; 1675 var isMin; 1676 var isMax; 1677 var to; 1678 var direction; 1679 var steps; 1680 var step; 1681 if ( isSliderDisabled() || isHandleDisabled( handleNumber ) ) { 1682 return false; 1683 } 1684 horizontalKeys = [ 'Left', 'Right' ]; 1685 verticalKeys = [ 'Down', 'Up' ]; 1686 largeStepKeys = [ 'PageDown', 'PageUp' ]; 1687 edgeKeys = [ 'Home', 'End' ]; 1688 if ( options.dir && ! options.ort ) { 1689 // On an right-to-left slider, the left and right keys act inverted 1690 horizontalKeys.reverse(); 1691 } else if ( options.ort && ! options.dir ) { 1692 // On a top-to-bottom slider, the up and down keys act inverted 1693 verticalKeys.reverse(); 1694 largeStepKeys.reverse(); 1695 } 1696 // Strip "Arrow" for IE compatibility. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 1697 key = event.key.replace( 'Arrow', '' ); 1698 isLargeDown = key === largeStepKeys[ 0 ]; 1699 isLargeUp = key === largeStepKeys[ 1 ]; 1700 isDown = key === verticalKeys[ 0 ] || key === horizontalKeys[ 0 ] || isLargeDown; 1701 isUp = key === verticalKeys[ 1 ] || key === horizontalKeys[ 1 ] || isLargeUp; 1702 isMin = key === edgeKeys[ 0 ]; 1703 isMax = key === edgeKeys[ 1 ]; 1704 if ( ! isDown && ! isUp && ! isMin && ! isMax ) { 1705 return true; 1706 } 1707 event.preventDefault(); 1708 if ( isUp || isDown ) { 1709 direction = isDown ? 0 : 1; 1710 steps = getNextStepsForHandle( handleNumber ); 1711 step = steps[ direction ]; 1712 // At the edge of a slider, do nothing 1713 if ( step === null ) { 1714 return false; 1715 } 1716 // No step set, use the default of 10% of the sub-range 1717 if ( step === false ) { 1718 step = scope_Spectrum.getDefaultStep( scope_Locations[ handleNumber ], isDown, options.keyboardDefaultStep ); 1719 } 1720 if ( isLargeUp || isLargeDown ) { 1721 step *= options.keyboardPageMultiplier; 1722 } else { 1723 step *= options.keyboardMultiplier; 1724 } 1725 // Step over zero-length ranges (#948); 1726 step = Math.max( step, 0.0000001 ); 1727 // Decrement for down steps 1728 step = ( isDown ? -1 : 1 ) * step; 1729 to = scope_Values[ handleNumber ] + step; 1730 } else if ( isMax ) { 1731 // End key 1732 to = options.spectrum.xVal[ options.spectrum.xVal.length - 1 ]; 1733 } else { 1734 // Home key 1735 to = options.spectrum.xVal[ 0 ]; 1736 } 1737 setHandle( handleNumber, scope_Spectrum.toStepping( to ), true, true ); 1738 fireEvent( 'slide', handleNumber ); 1739 fireEvent( 'update', handleNumber ); 1740 fireEvent( 'change', handleNumber ); 1741 fireEvent( 'set', handleNumber ); 1742 return false;
vendor: 6,566 bytes, lines 1743-1906
1743 } 1744 // Attach events to several slider parts. 1745 function bindSliderEvents( behaviour ) { 1746 var handleBefore; 1747 var handleAfter; 1748 var eventHolders; 1749 var handlesToDrag; 1750 var handleNumbersToDrag; 1751 // Attach the standard drag event to the handles. 1752 if ( ! behaviour.fixed ) { 1753 scope_Handles.forEach( function( handle, index ) { 1754 // These events are only bound to the visual handle 1755 // element, not the 'real' origin element. 1756 attachEvent( actions.start, handle.children[ 0 ], eventStart, { 1757 handleNumbers: [ index ] 1758 } ); 1759 } ); 1760 } 1761 // Attach the tap event to the slider base. 1762 if ( behaviour.tap ) { 1763 attachEvent( actions.start, scope_Base, eventTap, {} ); 1764 } 1765 // Fire hover events 1766 if ( behaviour.hover ) { 1767 attachEvent( actions.move, scope_Base, eventHover, { 1768 hover: true 1769 } ); 1770 } 1771 // Make the range draggable. 1772 if ( behaviour.drag ) { 1773 scope_Connects.forEach( function( connect, index ) { 1774 if ( connect === false || index === 0 || index === scope_Connects.length - 1 ) { 1775 return; 1776 } 1777 handleBefore = scope_Handles[ index - 1 ]; 1778 handleAfter = scope_Handles[ index ]; 1779 eventHolders = [ connect ]; 1780 handlesToDrag = [ handleBefore, handleAfter ]; 1781 handleNumbersToDrag = [ index - 1, index ]; 1782 addClass( connect, options.cssClasses.draggable ); 1783 // When the range is fixed, the entire range can 1784 // be dragged by the handles. The handle in the first 1785 // origin will propagate the start event upward, 1786 // but it needs to be bound manually on the other. 1787 if ( behaviour.fixed ) { 1788 eventHolders.push( handleBefore.children[ 0 ] ); 1789 eventHolders.push( handleAfter.children[ 0 ] ); 1790 } 1791 if ( behaviour.dragAll ) { 1792 handlesToDrag = scope_Handles; 1793 handleNumbersToDrag = scope_HandleNumbers; 1794 } 1795 eventHolders.forEach( function( eventHolder ) { 1796 attachEvent( actions.start, eventHolder, eventStart, { 1797 handles: handlesToDrag, 1798 handleNumbers: handleNumbersToDrag, 1799 connect: connect 1800 } ); 1801 } ); 1802 } ); 1803 } 1804 } 1805 // Attach an event to this slider, possibly including a namespace 1806 function bindEvent( namespacedEvent, callback ) { 1807 scope_Events[ namespacedEvent ] = scope_Events[ namespacedEvent ] || []; 1808 scope_Events[ namespacedEvent ].push( callback ); 1809 // If the event bound is 'update,' fire it immediately for all handles. 1810 if ( namespacedEvent.split( '.' )[ 0 ] === 'update' ) { 1811 scope_Handles.forEach( function( a, index ) { 1812 fireEvent( 'update', index ); 1813 } ); 1814 } 1815 } 1816 function isInternalNamespace( namespace ) { 1817 return namespace === INTERNAL_EVENT_NS.aria || namespace === INTERNAL_EVENT_NS.tooltips; 1818 } 1819 // Undo attachment of event 1820 function removeEvent( namespacedEvent ) { 1821 var event = namespacedEvent && namespacedEvent.split( '.' )[ 0 ]; 1822 var namespace = event ? namespacedEvent.substring( event.length ) : namespacedEvent; 1823 Object.keys( scope_Events ).forEach( function( bind ) { 1824 var tEvent = bind.split( '.' )[ 0 ]; 1825 var tNamespace = bind.substring( tEvent.length ); 1826 if ( ( ! event || event === tEvent ) && ( ! namespace || namespace === tNamespace ) ) { 1827 // only delete protected internal event if intentional 1828 if ( ! isInternalNamespace( tNamespace ) || namespace === tNamespace ) { 1829 delete scope_Events[ bind ]; 1830 } 1831 } 1832 } ); 1833 } 1834 // External event handling 1835 function fireEvent( eventName, handleNumber, tap ) { 1836 Object.keys( scope_Events ).forEach( function( targetEvent ) { 1837 var eventType = targetEvent.split( '.' )[ 0 ]; 1838 if ( eventName === eventType ) { 1839 scope_Events[ targetEvent ].forEach( function( callback ) { 1840 callback.call( 1841 // Use the slider public API as the scope ('this') 1842 scope_Self, 1843 // Return values as array, so arg_1[arg_2] is always valid. 1844 scope_Values.map( options.format.to ), 1845 // Handle index, 0 or 1 1846 handleNumber, 1847 // Un-formatted slider values 1848 scope_Values.slice(), 1849 // Event is fired by tap, true or false 1850 tap || false, 1851 // Left offset of the handle, in relation to the slider 1852 scope_Locations.slice(), 1853 // add the slider public API to an accessible parameter when this is unavailable 1854 scope_Self ); 1855 } ); 1856 } 1857 } ); 1858 } 1859 // Split out the handle positioning logic so the Move event can use it, too 1860 function checkHandlePosition( reference, handleNumber, to, lookBackward, lookForward, getValue, smoothSteps ) { 1861 var distance; 1862 // For sliders with multiple handles, limit movement to the other handle. 1863 // Apply the margin option by adding it to the handle positions. 1864 if ( scope_Handles.length > 1 && ! options.events.unconstrained ) { 1865 if ( lookBackward && handleNumber > 0 ) { 1866 distance = scope_Spectrum.getAbsoluteDistance( reference[ handleNumber - 1 ], options.margin, false ); 1867 to = Math.max( to, distance ); 1868 } 1869 if ( lookForward && handleNumber < scope_Handles.length - 1 ) { 1870 distance = scope_Spectrum.getAbsoluteDistance( reference[ handleNumber + 1 ], options.margin, true ); 1871 to = Math.min( to, distance ); 1872 } 1873 } 1874 // The limit option has the opposite effect, limiting handles to a 1875 // maximum distance from another. Limit must be > 0, as otherwise 1876 // handles would be unmovable. 1877 if ( scope_Handles.length > 1 && options.limit ) { 1878 if ( lookBackward && handleNumber > 0 ) { 1879 distance = scope_Spectrum.getAbsoluteDistance( reference[ handleNumber - 1 ], options.limit, false ); 1880 to = Math.min( to, distance ); 1881 } 1882 if ( lookForward && handleNumber < scope_Handles.length - 1 ) { 1883 distance = scope_Spectrum.getAbsoluteDistance( reference[ handleNumber + 1 ], options.limit, true ); 1884 to = Math.max( to, distance ); 1885 } 1886 } 1887 // The padding option keeps the handles a certain distance from the 1888 // edges of the slider. Padding must be > 0. 1889 if ( options.padding ) { 1890 if ( handleNumber === 0 ) { 1891 distance = scope_Spectrum.getAbsoluteDistance( 0, options.padding[ 0 ], false ); 1892 to = Math.max( to, distance ); 1893 } 1894 if ( handleNumber === scope_Handles.length - 1 ) { 1895 distance = scope_Spectrum.getAbsoluteDistance( 100, options.padding[ 1 ], true ); 1896 to = Math.min( to, distance ); 1897 } 1898 } 1899 if ( ! smoothSteps ) { 1900 to = scope_Spectrum.getStep( to ); 1901 } 1902 // Limit percentage to the 0 - 100 range 1903 to = limit( to ); 1904 // Return false if handle can't move 1905 if ( to === reference[ handleNumber ] && ! getValue ) { 1906 return false;
1907 } 1908 return to; 1909 } 1910 // Uses slider orientation to create CSS rules. a = base value; 1911 function inRuleOrder( v, a ) { 1912 var o = options.ort; 1913 return ( o ? a : v ) + ', ' + ( o ? v : a ); 1914 } 1915 // Moves handle(s) by a percentage 1916 // (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...]) 1917 function moveHandles( upward, proposal, locations, handleNumbers, connect ) { 1918 var proposals = locations.slice(); 1919 // Store first handle now, so we still have it in case handleNumbers is reversed 1920 var firstHandle = handleNumbers[ 0 ]; 1921 var smoothSteps = options.events.smoothSteps; 1922 var b = [ ! upward, upward ]; 1923 var f = [ upward, ! upward ]; 1924 var state = false; 1925 // Copy handleNumbers so we don't change the dataset 1926 handleNumbers = handleNumbers.slice(); 1927 // Check to see which handle is 'leading'. 1928 // If that one can't move the second can't either. 1929 if ( upward ) { 1930 handleNumbers.reverse(); 1931 } 1932 // Step 1: get the maximum percentage that any of the handles can move 1933 if ( handleNumbers.length > 1 ) { 1934 handleNumbers.forEach( function( handleNumber, o ) { 1935 var to = checkHandlePosition( proposals, handleNumber, proposals[ handleNumber ] + proposal, b[ o ], f[ o ], false, smoothSteps ); 1936 // Stop if one of the handles can't move. 1937 if ( to === false ) { 1938 proposal = 0; 1939 } else { 1940 proposal = to - proposals[ handleNumber ]; 1941 proposals[ handleNumber ] = to; 1942 } 1943 } ); 1944 } else { // If using one handle, check backward AND forward 1945 b = f = [ true ]; 1946 } 1947 // Step 2: Try to set the handles with the found percentage 1948 handleNumbers.forEach( function( handleNumber, o ) { 1949 state = 1950 setHandle( handleNumber, locations[ handleNumber ] + proposal, b[ o ], f[ o ], false, smoothSteps ) || state; 1951 } ); 1952 // Step 3: If a handle moved, fire events 1953 if ( state ) { 1954 handleNumbers.forEach( function( handleNumber ) { 1955 fireEvent( 'update', handleNumber ); 1956 fireEvent( 'slide', handleNumber ); 1957 } ); 1958 // If target is a connect, then fire drag event 1959 if ( connect !== undefined ) { 1960 fireEvent( 'drag', firstHandle ); 1961 } 1962 } 1963 } 1964 // Takes a base value and an offset. This offset is used for the connect bar size. 1965 // In the initial design for this feature, the origin element was 1% wide. 1966 // Unfortunately, a rounding bug in Chrome makes it impossible to implement this feature 1967 // in this manner: https://bugs.chromium.org/p/chromium/issues/detail?id=798223 1968 function transformDirection( a, b ) { 1969 return options.dir ? 100 - a - b : a; 1970 } 1971 // Updates scope_Locations and scope_Values, updates visual state 1972 function updateHandlePosition( handleNumber, to ) { 1973 var translation; 1974 var translateRule; 1975 // Update locations. 1976 scope_Locations[ handleNumber ] = to; 1977 // Convert the value to the slider stepping/range. 1978 scope_Values[ handleNumber ] = scope_Spectrum.fromStepping( to ); 1979 translation = transformDirection( to, 0 ) - scope_DirOffset; 1980 translateRule = 'translate(' + inRuleOrder( translation + '%', '0' ) + ')'; 1981 scope_Handles[ handleNumber ].style[ options.transformRule ] = translateRule; 1982 updateConnect( handleNumber ); 1983 updateConnect( handleNumber + 1 ); 1984 } 1985 // Handles before the slider middle are stacked later = higher, 1986 // Handles after the middle later is lower 1987 // [[7] [8] .......... | .......... [5] [4] 1988 function setZindex() { 1989 scope_HandleNumbers.forEach( function( handleNumber ) { 1990 var dir = scope_Locations[ handleNumber ] > 50 ? -1 : 1; 1991 var zIndex = 3 + ( scope_Handles.length + ( dir * handleNumber ) ); 1992 scope_Handles[ handleNumber ].style.zIndex = String( zIndex ); 1993 } ); 1994 } 1995 // Test suggested values and apply margin, step. 1996 // if exactInput is true, don't run checkHandlePosition, then the handle can be placed in between steps (#436) 1997 function setHandle( handleNumber, to, lookBackward, lookForward, exactInput, smoothSteps ) { 1998 if ( ! exactInput ) { 1999 to = checkHandlePosition( scope_Locations, handleNumber, to, lookBackward, lookForward, false, smoothSteps ); 2000 } 2001 if ( to === false ) { 2002 return false;
2003 } 2004 updateHandlePosition( handleNumber, to ); 2005 return true; 2006 } 2007 // Updates style attribute for connect nodes 2008 function updateConnect( index ) { 2009 var l; 2010 var h; 2011 var connectWidth; 2012 var translateRule; 2013 var scaleRule; 2014 // Skip connects set to false 2015 if ( ! scope_Connects[ index ] ) { 2016 return; 2017 } 2018 l = 0; 2019 h = 100; 2020 if ( index !== 0 ) { 2021 l = scope_Locations[ index - 1 ]; 2022 } 2023 if ( index !== scope_Connects.length - 1 ) { 2024 h = scope_Locations[ index ]; 2025 } 2026 // We use two rules: 2027 // 'translate' to change the left/top offset; 2028 // 'scale' to change the width of the element; 2029 // As the element has a width of 100%, a translation of 100% is equal to 100% of the parent (.noUi-base) 2030 connectWidth = h - l; 2031 translateRule = 'translate(' + inRuleOrder( transformDirection( l, connectWidth ) + '%', '0' ) + ')'; 2032 scaleRule = 'scale(' + inRuleOrder( connectWidth / 100, '1' ) + ')'; 2033 scope_Connects[ index ].style[ options.transformRule ] = 2034 translateRule + ' ' + scaleRule; 2035 } 2036 // Parses value passed to .set method. Returns current value if not parse-able. 2037 function resolveToValue( to, handleNumber ) { 2038 // Setting with null indicates an 'ignore'. 2039 // Inputting 'false' is invalid. 2040 if ( to === null || to === false || to === undefined ) { 2041 return scope_Locations[ handleNumber ]; 2042 } 2043 // If a formatted number was passed, attempt to decode it. 2044 if ( typeof to === 'number' ) { 2045 to = String( to ); 2046 } 2047 to = options.format.from( to ); 2048 if ( to !== false ) { 2049 to = scope_Spectrum.toStepping( to ); 2050 } 2051 // If parsing the number failed, use the current value. 2052 if ( to === false || isNaN( to ) ) { 2053 return scope_Locations[ handleNumber ]; 2054 } 2055 return to; 2056 } 2057 function scope_HandleNumbersCallback( exactInput ) { 2058 return function( handleNumber ) { 2059 setHandle( handleNumber, scope_Locations[ handleNumber ], true, true, exactInput ); 2060 }; 2061 } 2062 // Set the slider value. 2063 function valueSet( input, fireSetEvent, exactInput ) { 2064 var values = asArray( input ); 2065 var isInit = scope_Locations[ 0 ] === undefined; 2066 var i; 2067 var space_1; 2068 // Event fires by default 2069 fireSetEvent = fireSetEvent === undefined ? true : fireSetEvent; 2070 // Animation is optional. 2071 // Make sure the initial values were set before using animated placement. 2072 if ( options.animate && ! isInit ) { 2073 addClassFor( scope_Target, options.cssClasses.tap, options.animationDuration ); 2074 } 2075 // First pass, without lookAhead but with lookBackward. Values are set from left to right. 2076 scope_HandleNumbers.forEach( function( handleNumber ) { 2077 setHandle( handleNumber, resolveToValue( values[ handleNumber ], handleNumber ), true, false, exactInput ); 2078 } ); 2079 i = scope_HandleNumbers.length === 1 ? 0 : 1; 2080 // Spread handles evenly across the slider if the range has no size (min=max) 2081 if ( isInit && scope_Spectrum.hasNoSize() ) { 2082 exactInput = true; 2083 scope_Locations[ 0 ] = 0; 2084 if ( scope_HandleNumbers.length > 1 ) { 2085 space_1 = 100 / ( scope_HandleNumbers.length - 1 ); 2086 scope_HandleNumbers.forEach( function( handleNumber ) { 2087 scope_Locations[ handleNumber ] = handleNumber * space_1; 2088 } ); 2089 } 2090 } 2091 // Secondary passes. Now that all base values are set, apply constraints. 2092 // Iterate all handles to ensure constraints are applied for the entire slider (Issue #1009) 2093 for ( ; i < scope_HandleNumbers.length; ++i ) { 2094 scope_HandleNumbers.forEach( scope_HandleNumbersCallback( exactInput ) ); 2095 } 2096 setZindex(); 2097 scope_HandleNumbers.forEach( function( handleNumber ) { 2098 fireEvent( 'update', handleNumber ); 2099 // Fire the event only for handles that received a new value, as per #579 2100 if ( values[ handleNumber ] !== null && fireSetEvent ) { 2101 fireEvent( 'set', handleNumber ); 2102 } 2103 } ); 2104 } 2105 // Reset slider to initial values 2106 function valueReset( fireSetEvent ) { 2107 valueSet( options.start, fireSetEvent ); 2108 } 2109 // Set value for a single handle 2110 function valueSetHandle( handleNumber, value, fireSetEvent, exactInput ) { 2111 // Ensure numeric input 2112 handleNumber = Number( handleNumber ); 2113 if ( ! ( handleNumber >= 0 && handleNumber < scope_HandleNumbers.length ) ) { 2114 throw new Error( 'noUiSlider: invalid handle number, got: ' + handleNumber ); 2115 } 2116 // Look both backward and forward, since we don't want this handle to "push" other handles (#960); 2117 // The exactInput argument can be used to ignore slider stepping (#436) 2118 setHandle( handleNumber, resolveToValue( value, handleNumber ), true, true, exactInput ); 2119 fireEvent( 'update', handleNumber ); 2120 if ( fireSetEvent ) { 2121 fireEvent( 'set', handleNumber ); 2122 } 2123 } 2124 // Get the slider value. 2125 function valueGet( unencoded ) { 2126 var values; 2127 if ( unencoded === void 0 ) { 2128 unencoded = false;
vendor: 6,568 bytes, lines 2129-2328
2129 } 2130 if ( unencoded ) { 2131 // return a copy of the raw values 2132 return scope_Values.length === 1 ? scope_Values[ 0 ] : scope_Values.slice( 0 ); 2133 } 2134 values = scope_Values.map( options.format.to ); 2135 // If only one handle is used, return a single value. 2136 if ( values.length === 1 ) { 2137 return values[ 0 ]; 2138 } 2139 return values; 2140 } 2141 // Removes classes from the root and empties it. 2142 function destroy() { 2143 // remove protected internal listeners 2144 removeEvent( INTERNAL_EVENT_NS.aria ); 2145 removeEvent( INTERNAL_EVENT_NS.tooltips ); 2146 Object.keys( options.cssClasses ).forEach( function( key ) { 2147 removeClass( scope_Target, options.cssClasses[ key ] ); 2148 } ); 2149 while ( scope_Target.firstChild ) { 2150 scope_Target.removeChild( scope_Target.firstChild ); 2151 } 2152 delete scope_Target.noUiSlider; 2153 } 2154 function getNextStepsForHandle( handleNumber ) { 2155 var location = scope_Locations[ handleNumber ]; 2156 var nearbySteps = scope_Spectrum.getNearbySteps( location ); 2157 var value = scope_Values[ handleNumber ]; 2158 var increment = nearbySteps.thisStep.step; 2159 var decrement = null; 2160 var stepDecimals; 2161 // If snapped, directly use defined step value 2162 if ( options.snap ) { 2163 return [ 2164 value - nearbySteps.stepBefore.startValue || null, 2165 nearbySteps.stepAfter.startValue - value || null 2166 ]; 2167 } 2168 // If the next value in this step moves into the next step, 2169 // the increment is the start of the next step - the current value 2170 if ( increment !== false ) { 2171 if ( value + increment > nearbySteps.stepAfter.startValue ) { 2172 increment = nearbySteps.stepAfter.startValue - value; 2173 } 2174 } 2175 // If the value is beyond the starting point 2176 if ( value > nearbySteps.thisStep.startValue ) { 2177 decrement = nearbySteps.thisStep.step; 2178 } else if ( nearbySteps.stepBefore.step === false ) { 2179 decrement = false; 2180 } else { // If a handle is at the start of a step, it always steps back into the previous step first 2181 decrement = value - nearbySteps.stepBefore.highestStep; 2182 } 2183 // Now, if at the slider edges, there is no in/decrement 2184 if ( location === 100 ) { 2185 increment = null; 2186 } else if ( location === 0 ) { 2187 decrement = null; 2188 } 2189 // As per #391, the comparison for the decrement step can have some rounding issues. 2190 stepDecimals = scope_Spectrum.countStepDecimals(); 2191 // Round per #391 2192 if ( increment !== null && increment !== false ) { 2193 increment = Number( increment.toFixed( stepDecimals ) ); 2194 } 2195 if ( decrement !== null && decrement !== false ) { 2196 decrement = Number( decrement.toFixed( stepDecimals ) ); 2197 } 2198 return [ decrement, increment ]; 2199 } 2200 // Get the current step size for the slider. 2201 function getNextSteps() { 2202 return scope_HandleNumbers.map( getNextStepsForHandle ); 2203 } 2204 // Updatable: margin, limit, padding, step, range, animate, snap 2205 function updateOptions( optionsToUpdate, fireSetEvent ) { 2206 // Spectrum is created using the range, snap, direction and step options. 2207 // 'snap' and 'step' can be updated. 2208 // If 'snap' and 'step' are not passed, they should remain unchanged. 2209 var v = valueGet(); 2210 var updateAble = [ 2211 'margin', 2212 'limit', 2213 'padding', 2214 'range', 2215 'animate', 2216 'snap', 2217 'step', 2218 'format', 2219 'pips', 2220 'tooltips' 2221 ]; 2222 var newOptions; 2223 // Only change options that we're actually passed to update. 2224 updateAble.forEach( function( name ) { 2225 // Check for undefined. null removes the value. 2226 if ( optionsToUpdate[ name ] !== undefined ) { 2227 originalOptions[ name ] = optionsToUpdate[ name ]; 2228 } 2229 } ); 2230 newOptions = testOptions( originalOptions ); 2231 // Load new options into the slider state 2232 updateAble.forEach( function( name ) { 2233 if ( optionsToUpdate[ name ] !== undefined ) { 2234 options[ name ] = newOptions[ name ]; 2235 } 2236 } ); 2237 scope_Spectrum = newOptions.spectrum; 2238 // Limit, margin and padding depend on the spectrum but are stored outside of it. (#677) 2239 options.margin = newOptions.margin; 2240 options.limit = newOptions.limit; 2241 options.padding = newOptions.padding; 2242 // Update pips, removes existing. 2243 if ( options.pips ) { 2244 pips( options.pips ); 2245 } else { 2246 removePips(); 2247 } 2248 // Update tooltips, removes existing. 2249 if ( options.tooltips ) { 2250 tooltips(); 2251 } else { 2252 removeTooltips(); 2253 } 2254 // Invalidate the current positioning so valueSet forces an update. 2255 scope_Locations = []; 2256 valueSet( isSet( optionsToUpdate.start ) ? optionsToUpdate.start : v, fireSetEvent ); 2257 } 2258 // Initialization steps 2259 function setupSlider() { 2260 // Create the base element, initialize HTML and set classes. 2261 // Add handles and connect elements. 2262 scope_Base = addSlider( scope_Target ); 2263 addElements( options.connect, scope_Base ); 2264 // Attach user events. 2265 bindSliderEvents( options.events ); 2266 // Use the public value method to set the start values. 2267 valueSet( options.start ); 2268 if ( options.pips ) { 2269 pips( options.pips ); 2270 } 2271 if ( options.tooltips ) { 2272 tooltips(); 2273 } 2274 aria(); 2275 } 2276 setupSlider(); 2277 scope_Self = { 2278 destroy: destroy, 2279 steps: getNextSteps, 2280 on: bindEvent, 2281 off: removeEvent, 2282 get: valueGet, 2283 set: valueSet, 2284 setHandle: valueSetHandle, 2285 reset: valueReset, 2286 disable: disable, 2287 enable: enable, 2288 // Exposed for unit testing, don't use this in your application. 2289 __moveHandles: function( upward, proposal, handleNumbers ) { 2290 moveHandles( upward, proposal, scope_Locations, handleNumbers ); 2291 }, 2292 options: originalOptions, 2293 updateOptions: updateOptions, 2294 target: scope_Target, 2295 removePips: removePips, 2296 removeTooltips: removeTooltips, 2297 getPositions: function() { 2298 return scope_Locations.slice(); 2299 }, 2300 getTooltips: function() { 2301 return scope_Tooltips; 2302 }, 2303 getOrigins: function() { 2304 return scope_Handles; 2305 }, 2306 pips: pips // Issue #594 2307 }; 2308 return scope_Self; 2309 } 2310 // Run the standard initializer 2311 function initialize( target, originalOptions ) { 2312 var options; 2313 var api; 2314 if ( ! target || ! target.nodeName ) { 2315 throw new Error( 'noUiSlider: create requires a single element, got: ' + target ); 2316 } 2317 // Throw an error if the slider was already initialized. 2318 if ( target.noUiSlider ) { 2319 throw new Error( 'noUiSlider: Slider was already initialized.' ); 2320 } 2321 // Test the options and create the slider environment; 2322 options = testOptions( originalOptions ); 2323 api = scope( target, options, originalOptions ); 2324 target.noUiSlider = api; 2325 return api; 2326 } 2327 nouislider = { 2328 // Exposed for unit testing, don't use this in your application.
2329 __spectrum: Spectrum, 2330 // A reference to the default classes, allows global changes. 2331 // Use the cssClasses option for changes to one slider. 2332 cssClasses: cssClasses, 2333 create: initialize 2334 }; 2335 2336 exports.create = initialize; 2337 exports.cssClasses = cssClasses; 2338 exports.default = nouislider; 2339 2340 Object.defineProperty( exports, '__esModule', { value: true } ); 2341} ) ) );
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.