PageSourceSearch

https://sib.gob.ar/assets/vendors/bower_components/nouislider/jquery.nouislider.js

js sib.gob.ar collected 2026-10-02 10:11:24 UTC 31,897 bytes, 1,291 lines download raw bytes

1/**@preserve
2$.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
3
4/*jslint browser: true */
5/*jslint sub: true */
6/*jslint white: true */
7/*jslint continue: true */
8/*jslint plusplus: true */
9
10(function( $ ){
11
12	'use strict';
13
14	var
15	// Cache the document selector;
16	/** @const */
17	doc = $(document),
18	// Make a backup of the original jQuery/Zepto .val() method.
19	/** @const */
20	$val = $.fn.val,
21	// Namespace for binding and unbinding slider events;
22	/** @const */
23	namespace = '.nui',
24	// Determine the events to bind. IE11 implements pointerEvents without
25	// a prefix, which breaks compatibility with the IE10 implementation.
26	/** @const */
27	actions = window.navigator['pointerEnabled'] ? {
28		start: 'pointerdown',
29		move: 'pointermove',
30		end: 'pointerup'
31	} : window.navigator['msPointerEnabled'] ? {
32		start: 'MSPointerDown',
33		move: 'MSPointerMove',
34		end: 'MSPointerUp'
35	} : {
36		start: 'mousedown touchstart',
37		move: 'mousemove touchmove',
38		end: 'mouseup touchend'
39	},
40	// Re-usable list of classes;
41	/** @const */
42	Classes = [
43/*  0 */  'noUi-target'
44/*  1 */ ,'noUi-base'
45/*  2 */ ,'noUi-origin'
46/*  3 */ ,'noUi-handle'
47/*  4 */ ,'noUi-horizontal'
48/*  5 */ ,'noUi-vertical'
49/*  6 */ ,'noUi-background'
50/*  7 */ ,'noUi-connect'
51/*  8 */ ,'noUi-ltr'
52/*  9 */ ,'noUi-rtl'
53/* 10 */ ,'noUi-dragable'
54/* 11 */ ,''
55/* 12 */ ,'noUi-state-drag'
56/* 13 */ ,''
57/* 14 */ ,'noUi-state-tap'
58/* 15 */ ,'noUi-active'
59/* 16 */ ,'noUi-extended'
60/* 17 */ ,'noUi-stacking'
61	];
62
63
64// General helpers
65
66	// Limits a value to 0 - 100
67	function limit ( a ) {
68		return Math.max(Math.min(a, 100), 0);
69	}
70
71	// Round a value to the closest 'to'.
72	function closest ( value, to ) {
73		return Math.round(value / to) * to;
74	}
75
76	// Determine the size of a sub-range in relation to a full range.
77	function subRangeRatio ( pa, pb ) {
78		return (100 / (pb - pa));
79	}
80
81
82// Type validation
83
84	// Checks whether a value is numerical.
85	function isNumeric ( a ) {
86		return typeof a === 'number' && !isNaN( a ) && isFinite( a );
87	}
88
89	// Wraps a variable as an array, if it isn't one yet.
90	function asArray ( a ) {
91		return $.isArray(a) ? a : [a];
92	}
93
94
95// Class handling
96
97	// Sets a class and removes it after [duration] ms.
98	function addClassFor ( element, className, duration ) {
99		element.addClass(className);
100		setTimeout(function(){
101			element.removeClass(className);
102		}, duration);
103	}
104
105
106// Value calculation
107
108	// (percentage) How many percent is this value of this range?
109	function fromPercentage ( range, value ) {
110		return (value * 100) / ( range[1] - range[0] );
111	}
112
113	// (percentage) Where is this value on this range?
114	function toPercentage ( range, value ) {
115		return fromPercentage( range, range[0] < 0 ?
116			value + Math.abs(range[0]) :
117				value - range[0] );
118	}
119
120	// (value) How much is this percentage on this range?
121	function isPercentage ( range, value ) {
122		return ((value * ( range[1] - range[0] )) / 100) + range[0];
123	}
124
125	// (percentage)
126	function toStepping ( options, value ) {
127
128		if ( value >= options.xVal.slice(-1)[0] ){
129			return 100;
130		}
131
132		var j = 1, va, vb, pa, pb;
133		while ( value >= options.xVal[j] ){
134			j++;
135		}
136
137		va = options.xVal[j-1];
138		vb = options.xVal[j];
139		pa = options.xPct[j-1];
140		pb = options.xPct[j];
141
142		return pa + (toPercentage([va, vb], value) / subRangeRatio (pa, pb));
143	}
144
145	// (value)
146	function fromStepping ( options, value ) {
147
148		// There is no range group that fits 100
149		if ( value >= 100 ){
150			return options.xVal.slice(-1)[0];
151		}
152
153		var j = 1, va, vb, pa, pb;
154		while ( value >= options.xPct[j] ){
155			j++;
156		}
157
158		va = options.xVal[j-1];
159		vb = options.xVal[j];
160		pa = options.xPct[j-1];
161		pb = options.xPct[j];
162
163		return isPercentage([va, vb], (value - pa) * subRangeRatio (pa, pb));
164	}
165
166	// (percentage) Get the step that applies at a certain value.
167	function getStep ( options, value ){
168
169		var j = 1, a, b;
170
171		// Find the proper step for rtl sliders by search in inverse direction.
172		// Fixes issue #262.
173		while ( (options.dir ? (100 - value) : value) >= options.xPct[j] ){
174			j++;
175		}
176
177		if ( options.snap ) {
178
179			a = options.xPct[j-1];
180			b = options.xPct[j];
181
182			if ((value - a) > ((b-a)/2)){
183				return b;
184			}
185
186			return a;
187		}
188
189		if ( !options.xSteps[j-1] ){
190			return value;
191		}
192
193		return options.xPct[j-1] + closest(
194			value - options.xPct[j-1],
195			options.xSteps[j-1]
196		);
197	}
198
199
200// Event handling
201
202	// Provide a clean event with standardized offset values.
203	function fixEvent ( e ) {
204
205		// Prevent scrolling and panning on touch events, while
206		// attempting to slide. The tap event also depends on this.
207		e.preventDefault();
208
209		// Filter the event to register the type, which can be
210		// touch, mouse or pointer. Offset changes need to be
211		// made on an event specific basis.
212		var  touch = e.type.indexOf('touch') === 0
213			,mouse = e.type.indexOf('mouse') === 0
214			,pointer = e.type.indexOf('pointer') === 0
215			,x,y, event = e;
216
217		// IE10 implemented pointer events with a prefix;
218		if ( e.type.indexOf('MSPointer') === 0 ) {
219			pointer = true;
220		}
221
222		// Get the originalEvent, if the event has been wrapped
223		// by jQuery. Zepto doesn't wrap the event.
224		if ( e.originalEvent ) {
225			e = e.originalEvent;
226		}
227
228		if ( touch ) {
229			// noUiSlider supports one movement at a time,
230			// so we can select the first 'changedTouch'.
231			x = e.changedTouches[0].pageX;
232			y = e.changedTouches[0].pageY;
233		}
234
235		if ( mouse || pointer ) {
236
237			// Polyfill the pageXOffset and pageYOffset
238			// variables for IE7 and IE8;
239			if( !pointer && window.pageXOffset === undefined ){
240				window.pageXOffset = document.documentElement.scrollLeft;
241				window.pageYOffset = document.documentElement.scrollTop;
242			}
243
244			x = e.clientX + window.pageXOffset;
245			y = e.clientY + window.pageYOffset;
246		}
247
248		event.points = [x, y];
249		event.cursor = mouse;
250
251		return event;
252	}
253
254
255// Input validation
256
257	function testStep ( parsed, entry ) {
258
259		if ( !isNumeric( entry ) ) {
260			throw new Error("noUiSlider: 'step' is not numeric.");
261		}
262
263		// The step option can still be used to set stepping
264		// for linear sliders. Overwritten if set in 'range'.
265		parsed.xSteps[0] = entry;
266	}
267
268	function testRange ( parsed, entry ) {
269
270		// Filter incorrect input.
271		if ( typeof entry !== 'object' || $.isArray(entry) ) {
272			throw new Error("noUiSlider: 'range' is not an object.");
273		}
274
275		// Catch missing start or end.
276		if ( entry['min'] === undefined ||
277				entry['max'] === undefined ) {
278			throw new Error("noUiSlider: Missing 'min' or 'max' in 'range'.");
279		}
280
281		// Loop all entries.
282		$.each( entry, function ( index, value ) {
283
284			var percentage;
285
286			// Wrap numerical input in an array.
287			if ( typeof value === "number" ) {
288				value = [value];
289			}
290
291			// Reject any invalid input.
292			if ( !$.isArray( value ) ){
293				throw new Error("noUiSlider: 'range' contains invalid value.");
294			}
295
296			// Covert min/max syntax to 0 and 100.
297			if ( index === 'min' ) {
298				percentage = 0;
299			} else if ( index === 'max' ) {
300				percentage = 100;
301			} else {
302				percentage = parseFloat( index );
303			}
304
305			// Check for correct input.
306			if ( !isNumeric( percentage ) || !isNumeric( value[0] ) ) {
307				throw new Error("noUiSlider: 'range' value isn't numeric.");
308			}
309
310			// Store values.
311			parsed.xPct.push( percentage );
312			parsed.xVal.push( value[0] );
313
314			// NaN will evaluate to false too, but to keep
315			// logging clear, set step explicitly. Make sure
316			// not to override the 'step' setting with false.
317			if ( !percentage ) {
318				if ( !isNaN( value[1] ) ) {
319					parsed.xSteps[0] = value[1];
320				}
321			} else {
322				parsed.xSteps.push( isNaN(value[1]) ? false : value[1] );
323			}
324		});
325
326		$.each(parsed.xSteps, function(i,n){
327
328			// Ignore 'false' stepping.
329			if ( !n ) {
330				return true;
331			}
332
333			// Check if step fits. Not required, but this might serve some goal.
334			// !((parsed.xVal[i+1] - parsed.xVal[i]) % n);
335
336			// Factor to range ratio
337			parsed.xSteps[i] = fromPercentage([
338				 parsed.xVal[i]
339				,parsed.xVal[i+1]
340			], n) / subRangeRatio (
341				parsed.xPct[i],
342				parsed.xPct[i+1] );
343		});
344	}
345
346	function testStart ( parsed, entry ) {
347
348		if ( typeof entry === "number" ) {
349			entry = [entry];
350		}
351
352		// Validate input. Values aren't tested, the internal Link will do
353		// that and provide a valid location.
354		if ( !$.isArray( entry ) || !entry.length || entry.length > 2 ) {
355			throw new Error("noUiSlider: 'start' option is incorrect.");
356		}
357
358		// Store the number of handles.
359		parsed.handles = entry.length;
360
361		// When the slider is initialized, the .val method will
362		// be called with the start options.
363		parsed.start = entry;
364	}
365
366	function testSnap ( parsed, entry ) {
367
368		// Enforce 100% stepping within subranges.
369		parsed.snap = entry;
370
371		if ( typeof entry !== 'boolean' ){
372			throw new Error("noUiSlider: 'snap' option must be a boolean.");
373		}
374	}
375
376	function testConnect ( parsed, entry ) {
377
378		if ( entry === 'lower' && parsed.handles === 1 ) {
379			parsed.connect = 1;
380		} else if ( entry === 'upper' && parsed.handles === 1 ) {
381			parsed.connect = 2;
382		} else if ( entry === true && parsed.handles === 2 ) {
383			parsed.connect = 3;
384		} else if ( entry === false ) {
385			parsed.connect = 0;
386		} else {
387			throw new Error("noUiSlider: 'connect' option doesn't match handle count.");
388		}
389	}
390
391	function testOrientation ( parsed, entry ) {
392
393		// Set orientation to an a numerical value for easy
394		// array selection.
395		switch ( entry ){
396		  case 'horizontal':
397			parsed.ort = 0;
398			break;
399		  case 'vertical':
400			parsed.ort = 1;
401			break;
402		  default:
403			throw new Error("noUiSlider: 'orientation' option is invalid.");
404		}
405	}
406
407	function testMargin ( parsed, entry ) {
408
409		if ( parsed.xPct.length > 2 ) {
410			throw new Error("noUiSlider: 'margin' option is only supported on linear sliders.");
411		}
412
413		// Parse value to range and store. As xVal is checked
414		// to be no bigger than 2, use it as range.
415		parsed.margin = fromPercentage(parsed.xVal, entry);
416
417		if ( !isNumeric(entry) ){
418			throw new Error("noUiSlider: 'margin' option must be numeric.");
419		}
420	}
421
422	function testDirection ( parsed, entry ) {
423
424		// Set direction as a numerical value for easy parsing.
425		// Invert connection for RTL sliders, so that the proper
426		// handles get the connect/background classes.
427		switch ( entry ) {
428		  case 'ltr':
429			parsed.dir = 0;
430			break;
431		  case 'rtl':
432			parsed.dir = 1;
433			parsed.connect = [0,2,1,3][parsed.connect];
434			break;
435		  default:
436			throw new Error("noUiSlider: 'direction' option was not recognized.");
437		}
438	}
439
440	function testBehaviour ( parsed, entry ) {
441
442		// Make sure the input is a string.
443		if ( typeof entry !== 'string' ) {
444			throw new Error("noUiSlider: 'behaviour' must be a string containing options.");
445		}
446
447		// Check if the string contains any keywords.
448		// None are required.
449		var tap = entry.indexOf('tap') >= 0,
450			extend = entry.indexOf('extend') >= 0,
451			drag = entry.indexOf('drag') >= 0,
452			fixed = entry.indexOf('fixed') >= 0,
453			snap = entry.indexOf('snap') >= 0;
454
455		parsed.events = {
456			tap: tap || snap,
457			extend: extend,
458			drag: drag,
459			fixed: fixed,
460			snap: snap
461		};
462	}
463
464	function testSerialization ( parsed, entry, sliders ) {
465
466		parsed.ser = [ entry['lower'], entry['upper'] ];
467		parsed.formatting = entry['format'];
468
469		$.each( parsed.ser, function( index, linkInstances ){
470
471			// Check if the provided option is an array.
472			if ( !$.isArray(linkInstances) ) {
473				throw new Error("noUiSlider: 'serialization."+(!index ? 'lower' : 'upper')+"' must be an array.");
474			}
475
476			$.each(linkInstances, function(){
477
478				// Check if entry is a Link.
479				if ( !(this instanceof $.Link) ) {
480					throw new Error("noUiSlider: 'serialization."+(!index ? 'lower' : 'upper')+"' can only contain Link instances.");
481				}
482
483				// Assign properties.
484				this.setIndex ( index );
485				this.setObject( sliders );
486				this.setFormatting( entry['format'] );
487			});
488		});
489
490		// If the slider has two handles and is RTL,
491		// reverse the serialization input. For one handle,
492		// lower is still lower.
493		if ( parsed.dir && parsed.handles > 1 ) {
494			parsed.ser.reverse();
495		}
496	}
497
498	// Test all developer settings and parse to assumption-safe values.
499	function test ( options, sliders ){
500
501	/*	Every input option is tested and parsed. This'll prevent
502		endless validation in internal methods. These tests are
503		structured with an item for every option available. An
504		option can be marked as required by setting the 'r' flag.
505		The testing function is provided with three arguments:
506			- The provided value for the option;
507			- A reference to the options object;
508			- The name for the option;
509
510		The testing function returns false when an error is detected,
511		or true when everything is OK. It can also modify the option
512		object, to make sure all values can be correctly looped elsewhere. */
513
514		var parsed = {
515			 xPct: []
516			,xVal: []
517			,xSteps: [ false ]
518			,margin: 0
519		}, tests;
520
521		// Tests are executed in the order they are presented here.
522		tests = {
523			'step': { r: false, t: testStep },
524			'start': { r: true, t: testStart },
525			'connect': { r: true, t: testConnect },
526			'direction': { r: true, t: testDirection },
527			'range': { r: true, t: testRange },
528			'snap': { r: false, t: testSnap },
529			'orientation': { r: false, t: testOrientation },
530			'margin': { r: false, t: testMargin },
531			'behaviour': { r: true, t: testBehaviour },
532			'serialization': { r: true, t: testSerialization }
533		};
534
535		// Set defaults where applicable.
536		options = $.extend({
537			'connect': false,
538			'direction': 'ltr',
539			'behaviour': 'tap',
540			'orientation': 'horizontal'
541		}, options);
542
543		// Make sure the test for serialization runs.
544		options['serialization'] = $.extend({
545			 'lower': []
546			,'upper': []
547			,'format': {}
548		}, options['serialization']);
549
550		// Run all options through a testing mechanism to ensure correct
551		// input. It should be noted that options might get modified to
552		// be handled properly. E.g. wrapping integers in arrays.
553		$.each( tests, function( name, test ){
554
555			if ( options[name] === undefined ) {
556
557				if ( test.r ) {
558					throw new Error("noUiSlider: '" + name + "' is required.");
559				}
560
561				return true;
562			}
563
564			test.t( parsed, options[name], sliders );
565		});
566
567		// Pre-define the styles.
568		parsed.style = parsed.ort ? 'top' : 'left';
569
570		return parsed;
571	}
572
573
574// DOM additions
575
576	// Append a handle to the base.
577	function addHandle ( options, index ) {
578
579		var handle = $('<div><div/></div>').addClass( Classes[2] ),
580			additions = [ '-lower', '-upper' ];
581
582		if ( options.dir ) {
583			additions.reverse();
584		}
585
586		handle.children().addClass(
587			Classes[3] + " " + Classes[3]+additions[index]
588		);
589
590		return handle;
591	}
592
593	// Create a copy of an element-creating Link.
594	function addElement ( handle, link ) {
595
596		// If the Link requires creation of a new element,
597		// create this element and return a new Link instance.
598		if ( link.el ) {
599
600			link = new $.Link({
601				'target': $(link.el).clone().appendTo( handle ),
602				'method': link.method,
603				'format': link.formatting
604			}, true);
605		}
606
607		// Otherwise, return the reference.
608		return link;
609	}
610
611	// Loop all links for a handle.
612	function addElements ( elements, handle, formatting ) {
613
614		var index, list = [], standard = new $.Link({}, true);
615
616		// Use the Link interface to provide unified
617		// formatting for the .val() method.
618		standard.setFormatting(formatting);
619
620		// The list now contains at least one element.
621		list.push( standard );
622
623		// Loop all links in either 'lower' or 'upper'.
624		for ( index = 0; index < elements.length; index++ ) {
625			list.push(addElement(handle, elements[index]));
626		}
627
628		return list;
629	}
630
631	// Go over all Links and assign them to a handle.
632	function addLinks ( options, handles ) {
633
634		var index, links = [];
635
636		// Copy the links into a new array, instead of modifying
637		// the 'options.ser' list. This allows replacement of the invalid
638		// '.el' Links, while the others are still passed by reference.
639		for ( index = 0; index < options.handles; index++ ) {
640
641			// Append a new array.
642			links[index] = addElements(
643				options.ser[index],
644				handles[index].children(),
645				options.formatting
646			);
647		}
648
649		return links;
650	}
651
652	// Add the proper connection classes.
653	function addConnection ( connect, target, handles ) {
654
655		// Apply the required connection classes to the elements
656		// that need them. Some classes are made up for several
657		// segments listed in the class list, to allow easy
658		// renaming and provide a minor compression benefit.
659		switch ( connect ) {
660			case 1:	target.addClass( Classes[7] );
661					handles[0].addClass( Classes[6] );
662					break;
663			case 3: handles[1].addClass( Classes[6] );
664					/* falls through */
665			case 2: handles[0].addClass( Classes[7] );
666					/* falls through */
667			case 0: target.addClass(Classes[6]);
668					break;
669		}
670	}
671
672	// Add handles and loop Link elements.
673	function addHandles ( options, base ) {
674
675		var index, handles = [];
676
677		// Append handles.
678		for ( index = 0; index < options.handles; index++ ) {
679
680			// Keep a list of all added handles.
681			handles.push( addHandle( options, index ).appendTo(base) );
682		}
683
684		return handles;
685	}
686
687	// Initialize a single slider.
688	function addSlider ( options, target ) {
689
690		// Apply classes and data to the target.
691		target.addClass([
692			Classes[0],
693			Classes[8 + options.dir],
694			Classes[4 + options.ort]
695		].join(' '));
696
697		return $('<div/>').appendTo(target).addClass( Classes[1] );
698	}
699
700
701// Slider scope
702
703function closure ( target, options, originalOptions ){
704
705// Internal variables
706
707	// All variables local to 'closure' are marked $.
708	var $Target = $(target),
709		$Locations = [-1, -1],
710		$Base,
711		$Serialization,
712		$Handles;
713
714	// Shorthand for base dimensions.
715	function baseSize ( ) {
716		return $Base[['width', 'height'][options.ort]]();
717	}
718
719
720// External event handling
721
722	function fireEvents ( events ) {
723
724		// Use the external api to get the values.
725		// Wrap the values in an array, as .trigger takes
726		// only one additional argument.
727		var index, values = [ $Target.val() ];
728
729		for ( index = 0; index < events.length; index++ ){
730			$Target.trigger(events[index], values);
731		}
732	}
733
734
735// Handle placement
736
737	// Test suggested values and apply margin, step.
738	function setHandle ( handle, to, delimit ) {
739
740		var n = handle[0] !== $Handles[0][0] ? 1 : 0,
741			lower = $Locations[0] + options.margin,
742			upper = $Locations[1] - options.margin;
743
744		// Don't delimit range dragging.
745		if ( delimit && $Handles.length > 1 ) {
746			to = n ? Math.max( to, lower ) : Math.min( to, upper );
747		}
748
749		// Handle the step option.
750		if ( to < 100 ){
751			to = getStep(options, to);
752		}
753
754		// Limit to 0/100 for .val input, trim anything beyond 7 digits, as
755		// JavaScript has some issues in its floating point implementation.
756		to = limit(parseFloat(to.toFixed(7)));
757
758		// Return falsy if handle can't move. False for 0 or 100 limit,
759		// '0' for limiting by another handle.
760		if ( to === $Locations[n] ) {
761			if ( $Handles.length === 1 ) {
762				return false;
763			}
764			return ( to === lower || to === upper ) ? 0 : false;
765		}
766
767		// Set the handle to the new position.
768		handle.css( options.style, to + '%' );
769
770		// Force proper handle stacking
771		if ( handle.is(':first-child') ) {
772			handle.toggleClass(Classes[17], to > 50 );
773		}
774
775		// Update locations.
776		$Locations[n] = to;
777
778		// Invert the value if this is a right-to-left slider.
779		if ( options.dir ) {
780			to = 100 - to;
781		}
782
783		// Write values to serialization Links.
784		// Convert the value to the correct relative representation.
785		// Convert the value to the slider stepping/range.
786		$($Serialization[n]).each(function(){
787			this.write( fromStepping( options, to ), handle.children(), $Target );
788		});
789
790		return true;
791	}
792
793	// Delimit proposed values for handle positions.
794	function getPositions ( a, b, delimit ) {
795
796		// Add movement to current position.
797		var c = a + b[0], d = a + b[1];
798
799		// Only alter the other position on drag,
800		// not on standard sliding.
801		if ( delimit ) {
802			if ( c < 0 ) {
803				d += Math.abs(c);
804			}
805			if ( d > 100 ) {
806				c -= ( d - 100 );
807			}
808
809			// Limit values to 0 and 100.
810			return [limit(c), limit(d)];
811		}
812
813		return [c,d];
814	}
815
816	// Handles movement by tapping.
817	function jump ( handle, to, instant ) {
818
819		if ( !instant ) {
820			// Flag the slider as it is now in a transitional state.
821			// Transition takes 300 ms, so re-enable the slider afterwards.
822			addClassFor( $Target, Classes[14], 300 );
823		}
824
825		// Move the handle to the new position.
826		setHandle( handle, to, false );
827
828		fireEvents(['slide', 'set', 'change']);
829	}
830
831
832// Events
833
834	// Handler for attaching events trough a proxy.
835	function attach ( events, element, callback, data ) {
836
837		// Add the noUiSlider namespace to all events.
838		events = events.replace( /\s/g, namespace + ' ' ) + namespace;
839
840		// Bind a closure on the target.
841		return element.on( events, function( e ){
842
843			// jQuery and Zepto handle unset attributes differently.
844			var disabled = $Target.attr('disabled');
845				disabled = !( disabled === undefined || disabled === null );
846
847			// Test if there is anything that should prevent an event
848			// from being handled, such as a disabled state or an active
849			// 'tap' transition.
850			if( $Target.hasClass( Classes[14] ) || disabled ) {
851				return false;
852			}
853
854			e = fixEvent(e);
855			e.calcPoint = e.points[ options.ort ];
856
857			// Call the event handler with the event [ and additional data ].
858			callback ( e, data );
859		});
860	}
861
862	// Handle movement on document for handle and range drag.
863	function move ( event, data ) {
864
865		var handles = data.handles || $Handles, positions, state = false,
866			proposal = ((event.calcPoint - data.start) * 100) / baseSize(),
867			h = handles[0][0] !== $Handles[0][0] ? 1 : 0;
868
869		// Calculate relative positions for the handles.
870		positions = getPositions( proposal, data.positions, handles.length > 1);
871
872		state = setHandle ( handles[0], positions[h], handles.length === 1 );
873
874		if ( handles.length > 1 ) {
875			state = setHandle ( handles[1], positions[h?0:1], false ) || state;
876		}
877
878		// Fire the 'slide' event if any handle moved.
879		if ( state ) {
880			fireEvents(['slide']);
881		}
882	}
883
884	// Unbind move events on document, call callbacks.
885	function end ( event ) {
886
887		// The handle is no longer active, so remove the class.
888		$('.' + Classes[15]).removeClass(Classes[15]);
889
890		// Remove cursor styles and text-selection events bound to the body.
891		if ( event.cursor ) {
892			$('body').css('cursor', '').off( namespace );
893		}
894
895		// Unbind the move and end events, which are added on 'start'.
896		doc.off( namespace );
897
898		// Remove dragging class.
899		$Target.removeClass(Classes[12]);
900
901		// Fire the change and set events.
902		fireEvents(['set', 'change']);
903	}
904
905	// Bind move events on document.
906	function start ( event, data ) {
907
908		// Mark the handle as 'active' so it can be styled.
909		if( data.handles.length === 1 ) {
910			data.handles[0].children().addClass(Classes[15]);
911		}
912
913		// A drag should never propagate up to the 'tap' event.
914		event.stopPropagation();
915
916		// Attach the move event.
917		attach ( actions.move, doc, move, {
918			start: event.calcPoint,
919			handles: data.handles,
920			positions: [
921				$Locations[0],
922				$Locations[$Handles.length - 1]
923			]
924		});
925
926		// Unbind all movement when the drag ends.
927		attach ( actions.end, doc, end, null );
928
929		// Text selection isn't an issue on touch devices,
930		// so adding cursor styles can be skipped.
931		if ( event.cursor ) {
932
933			// Prevent the 'I' cursor and extend the range-drag cursor.
934			$('body').css('cursor', $(event.target).css('cursor'));
935
936			// Mark the target with a dragging state.
937			if ( $Handles.length > 1 ) {
938				$Target.addClass(Classes[12]);
939			}
940
941			// Prevent text selection when dragging the handles.
942			$('body').on('selectstart' + namespace, false);
943		}
944	}
945
946	// Move closest handle to tapped location.
947	function tap ( event ) {
948
949		var location = event.calcPoint, total = 0, to;
950
951		// The tap event shouldn't propagate up and cause 'edge' to run.
952		event.stopPropagation();
953
954		// Add up the handle offsets.
955		$.each( $Handles, function(){
956			total += this.offset()[ options.style ];
957		});
958
959		// Find the handle closest to the tapped position.
960		total = ( location < total/2 || $Handles.length === 1 ) ? 0 : 1;
961
962		location -= $Base.offset()[ options.style ];
963
964		// Calculate the new position.
965		to = ( location * 100 ) / baseSize();
966
967		// Find the closest handle and calculate the tapped point.
968		// The set handle to the new position.
969		jump( $Handles[total], to, options.events.snap );
970
971		if ( options.events.snap ) {
972			start(event, { handles: [$Handles[total]] });
973		}
974	}
975
976	// Move handle to edges when target gets tapped.
977	function edge ( event ) {
978
979		var i = event.calcPoint < $Base.offset()[ options.style ],
980			to = i ? 0 : 100;
981
982		i = i ? 0 : $Handles.length - 1;
983
984		jump( $Handles[i], to, false );
985	}
986
987	// Attach events to several slider parts.
988	function events ( behaviour ) {
989
990		var i, drag;
991
992		// Attach the standard drag event to the handles.
993		if ( !behaviour.fixed ) {
994
995			for ( i = 0; i < $Handles.length; i++ ) {
996
997				// These events are only bound to the visual handle
998				// element, not the 'real' origin element.
999				attach ( actions.start, $Handles[i].children(), start, {
1000					handles: [ $Handles[i] ]
1001				});
1002			}
1003		}
1004
1005		// Attach the tap event to the slider base.
1006		if ( behaviour.tap ) {
1007			attach ( actions.start, $Base, tap, {
1008				handles: $Handles
1009			});
1010		}
1011
1012		// Extend tapping behaviour to target
1013		if ( behaviour.extend ) {
1014
1015			$Target.addClass( Classes[16] );
1016
1017			if ( behaviour.tap ) {
1018				attach ( actions.start, $Target, edge, {
1019					handles: $Handles
1020				});
1021			}
1022		}
1023
1024		// Make the range dragable.
1025		if ( behaviour.drag ){
1026
1027			drag = $Base.find( '.' + Classes[7] ).addClass( Classes[10] );
1028
1029			// When the range is fixed, the entire range can
1030			// be dragged by the handles. The handle in the first
1031			// origin will propagate the start event upward,
1032			// but it needs to be bound manually on the other.
1033			if ( behaviour.fixed ) {
1034				drag = drag.add($Base.children().not( drag ).children());
1035			}
1036
1037			attach ( actions.start, drag, start, {
1038				handles: $Handles
1039			});
1040		}
1041	}
1042
1043
1044// Initialize slider
1045
1046	// Throw an error if the slider was already initialized.
1047	if ( $Target.hasClass(Classes[0]) ) {
1048		throw new Error('Slider was already initialized.');
1049	}
1050
1051	// Create the base element, initialise HTML and set classes.
1052	// Add handles and links.
1053	$Base = addSlider( options, $Target );
1054	$Handles = addHandles( options, $Base );
1055	$Serialization = addLinks( options, $Handles );
1056
1057	// Set the connect classes.
1058	addConnection ( options.connect, $Target, $Handles );
1059
1060	// Attach user events.
1061	events( options.events );
1062
1063
1064// Methods
1065
1066	// Set the slider value.
1067	/** @expose */
1068	target.vSet = function ( ) {
1069
1070		var args = Array.prototype.slice.call( arguments, 0 ),
1071			callback, link, update, animate,
1072			i, count, actual, to, values = asArray( args[0] );
1073
1074		// Extract modifiers for value method.
1075		if ( typeof args[1] === 'object' ) {
1076			callback = args[1]['set'];
1077			link = args[1]['link'];
1078			update = args[1]['update'];
1079			animate = args[1]['animate'];
1080
1081		// Support the 'true' option.
1082		} else if ( args[1] === true ) {
1083			callback = true;
1084		}
1085
1086		// The RTL settings is implemented by reversing the front-end,
1087		// internal mechanisms are the same.
1088		if ( options.dir && options.handles > 1 ) {
1089			values.reverse();
1090		}
1091
1092		// Animation is optional.
1093		if ( animate ) {
1094			addClassFor( $Target, Classes[14], 300 );
1095		}
1096
1097		// Determine how often to set the handles.
1098		count = $Handles.length > 1 ? 3 : 1;
1099		if ( values.length === 1 ) {
1100			count = 1;
1101		}
1102
1103		// If there are multiple handles to be set run the setting
1104		// mechanism twice for the first handle, to make sure it
1105		// can be bounced of the second one properly.
1106		for ( i = 0; i < count; i++ ) {
1107
1108			to = link || $Serialization[i%2][0];
1109			to = to.getValue( values[i%2] );
1110
1111			if ( to === false ) {
1112				continue;
1113			}
1114
1115			// Calculate the new handle position
1116			to = toStepping( options, to );
1117
1118			// Invert the value if this is a right-to-left slider.
1119			if ( options.dir ) {
1120				to = 100 - to;
1121			}
1122
1123			// Force delimitation.
1124			if ( setHandle( $Handles[i%2], to, true ) === true ) {
1125				continue;
1126			}
1127
1128			// Reset the input if it doesn't match the slider.
1129			$($Serialization[i%2]).each(function(index){
1130
1131				if (!index) {
1132					actual = this.actual;
1133					return true;
1134				}
1135
1136				this.write(
1137					actual,
1138					$Handles[i%2].children(),
1139					$Target,
1140					update
1141				);
1142			});
1143		}
1144
1145		// Optionally fire the 'set' event.
1146		if( callback === true ) {
1147			fireEvents(['set']);
1148		}
1149
1150		return this;
1151	};
1152
1153	// Get the slider value.
1154	/** @expose */
1155	target.vGet = function ( ) {
1156
1157		var i, retour = [];
1158
1159		// Get the value from all handles.
1160		for ( i = 0; i < options.handles; i++ ){
1161			retour[i] = $Serialization[i][0].saved;
1162		}
1163
1164		// If only one handle is used, return a single value.
1165		if ( retour.length === 1 ){
1166			return retour[0];
1167		}
1168
1169		if ( options.dir ) {
1170			return retour.reverse();
1171		}
1172
1173		return retour;
1174	};
1175
1176	// Destroy the slider and unbind all events.
1177	/** @expose */
1178	target.destroy = function ( ) {
1179
1180		// Loop all linked serialization objects and unbind all
1181		// events in the noUiSlider namespace.
1182		$.each($Serialization, function(){
1183			$.each(this, function(){
1184				// Won't remove 'change' when bound implicitly.
1185				if ( this.target ) {
1186					this.target.off( namespace );
1187				}
1188			});
1189		});
1190
1191		// Unbind events on the slider, remove all classes and child elements.
1192		$(this).off(namespace)
1193			.removeClass(Classes.join(' '))
1194			.empty();
1195
1196		// Return the original options from the closure.
1197		return originalOptions;
1198	};
1199
1200
1201// Value setting
1202
1203	// Use the public value method to set the start values.
1204	$Target.val( options.start );
1205}
1206
1207
1208// Access points
1209
1210	// Run the standard initializer
1211	function initialize ( originalOptions ) {
1212
1213		// Throw error if group is empty.
1214		if ( !this.length ){
1215			throw new Error("noUiSlider: Can't initialize slider on empty selection.");
1216		}
1217
1218		// Test the options once, not for every slider.
1219		var options = test( originalOptions, this );
1220
1221		// Loop all items, and provide a new closed-scope environment.
1222		return this.each(function(){
1223			closure(this, options, originalOptions);
1224		});
1225	}
1226
1227	// Destroy the slider, then re-enter initialization.
1228	function rebuild ( options ) {
1229
1230		return this.each(function(){
1231
1232			// Get the current values from the slider,
1233			// including the initialization options.
1234			var values = $(this).val(),
1235				originalOptions = this.destroy(),
1236
1237				// Extend the previous options with the newly provided ones.
1238				newOptions = $.extend( {}, originalOptions, options );
1239
1240			// Run the standard initializer.
1241			$(this).noUiSlider( newOptions );
1242
1243			// If the start option hasn't changed,
1244			// reset the previous values.
1245			if ( originalOptions.start === newOptions.start ) {
1246				$(this).val(values);
1247			}
1248		});
1249	}
1250
1251	// Access the internal getting and setting methods based on argument count.
1252	function value ( ) {
1253		return this[0][ !arguments.length ? 'vGet' : 'vSet' ].apply(this[0], arguments);
1254	}
1255
1256	// Override the .val() method. Test every element. Is it a slider? Go to
1257	// the slider value handling. No? Use the standard method.
1258	// Note how $.fn.val extects 'this' to be an instance of $. For convenience,
1259	// the above 'value' function does too.
1260	$.fn.val = function ( ) {
1261
1262		// this === instanceof $
1263
1264		function valMethod( a ){
1265			return a.hasClass(Classes[0]) ? value : $val;
1266		}
1267
1268		var args = arguments,
1269			first = $(this[0]);
1270
1271		if ( !arguments.length ) {
1272			return valMethod(first).call(first);
1273		}
1274
1275		// Return the set so it remains chainable
1276		return this.each(function(){
1277			valMethod($(this)).apply($(this), args);
1278		});
1279	};
1280
1281// Remap the serialization constructor for legacy support.
1282	/** @expose */
1283	$.noUiSlider = { 'Link': $.Link };
1284
1285// Extend jQuery/Zepto with the noUiSlider method.
1286	/** @expose */
1287	$.fn.noUiSlider = function ( options, re ) {
1288		return ( re ? rebuild : initialize ).call(this, options);
1289	};
1290
1291}( window['jQuery'] || window['Zepto'] ));

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.