summaryrefslogtreecommitdiff
path: root/js/assets/nouislider/5.0.0/full/jquery.nouislider.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/assets/nouislider/5.0.0/full/jquery.nouislider.js')
-rw-r--r--js/assets/nouislider/5.0.0/full/jquery.nouislider.js1420
1 files changed, 0 insertions, 1420 deletions
diff --git a/js/assets/nouislider/5.0.0/full/jquery.nouislider.js b/js/assets/nouislider/5.0.0/full/jquery.nouislider.js
deleted file mode 100644
index a5ffa0edc92..00000000000
--- a/js/assets/nouislider/5.0.0/full/jquery.nouislider.js
+++ /dev/null
@@ -1,1420 +0,0 @@
-/*! $.noUiSlider
- @version 5.0.0
- @author Leon Gersen https://twitter.com/LeonGersen
- @license WTFPL http://www.wtfpl.net/about/
- @documentation http://refreshless.com/nouislider/
-*/
-
-// ==ClosureCompiler==
-// @externs_url http://refreshless.com/externs/jquery-1.8.js
-// @compilation_level ADVANCED_OPTIMIZATIONS
-// @warning_level VERBOSE
-// ==/ClosureCompiler==
-
-/*jshint laxcomma: true */
-/*jshint smarttabs: true */
-/*jshint sub: true */
-
-/*jslint browser: true */
-/*jslint continue: true */
-/*jslint plusplus: true */
-/*jslint white: true */
-/*jslint sub: true */
-
-(function( $ ){
-
- 'use strict';
-
- if ( $['zepto'] && !$.fn.removeData ) {
- throw new ReferenceError('Zepto is loaded without the data module.');
- }
-
- $.fn['noUiSlider'] = function( options, rebuild ){
-
- var
- // Cache the document and body selectors;
- doc = $(document)
- ,body = $('body')
-
- // Namespace for binding and unbinding slider events;
- ,namespace = '.nui'
-
- // Copy of the current value function;
- ,$VAL = $.fn.val
-
- // Re-usable list of classes;
- ,clsList = [
- /* 0 */ 'noUi-base'
- /* 1 */ ,'noUi-origin'
- /* 2 */ ,'noUi-handle'
- /* 3 */ ,'noUi-input'
- /* 4 */ ,'noUi-active'
- /* 5 */ ,'noUi-state-tap'
- /* 6 */ ,'noUi-target'
- /* 7 */ ,'-lower'
- /* 8 */ ,'-upper'
- /* 9 */ ,'noUi-connect'
- /* 10 */ ,'noUi-horizontal'
- /* 11 */ ,'noUi-vertical'
- /* 12 */ ,'noUi-background'
- /* 13 */ ,'noUi-stacking'
- /* 14 */ ,'noUi-block'
- /* 15 */ ,'noUi-state-blocked'
- /* 16 */ ,'noUi-ltr'
- /* 17 */ ,'noUi-rtl'
- /* 18 */ ,'noUi-dragable'
- /* 19 */ ,'noUi-extended'
- /* 20 */ ,'noUi-state-drag'
- ]
-
- // Determine the events to bind. IE11 implements pointerEvents without
- // a prefix, which breaks compatibility with the IE10 implementation.
- ,actions = window.navigator['pointerEnabled'] ? {
- start: 'pointerdown'
- ,move: 'pointermove'
- ,end: 'pointerup'
- } : window.navigator['msPointerEnabled'] ? {
- start: 'MSPointerDown'
- ,move: 'MSPointerMove'
- ,end: 'MSPointerUp'
- } : {
- start: 'mousedown touchstart'
- ,move: 'mousemove touchmove'
- ,end: 'mouseup touchend'
- };
-
-
-// Percentage calculation
-
- // (percentage) How many percent is this value of this range?
- function fromPercentage ( range, value ) {
- return (value * 100) / ( range[1] - range[0] );
- }
-
- // (percentage) Where is this value on this range?
- function toPercentage ( range, value ) {
- return fromPercentage( range, range[0] < 0 ?
- value + Math.abs(range[0]) :
- value - range[0] );
- }
-
- // (value) How much is this percentage on this range?
- function isPercentage ( range, value ) {
- return ((value * ( range[1] - range[0] )) / 100) + range[0];
- }
-
-
-// Type tests
-
- // Test in an object is an instance of jQuery or Zepto.
- function isInstance ( a ) {
- return a instanceof $ || ( $['zepto'] && $['zepto']['isZ'](a) );
- }
-
- // Checks whether a value is numerical.
- function isNumeric ( a ) {
- return !isNaN( parseFloat( a ) ) && isFinite( a );
- }
-
-
-// General helper functions
-
- // Test an array of objects, and calls them if they are a function.
- function call ( functions, scope ) {
-
- // Allow the passing of an unwrapped function.
- // Leaves other code a more comprehensible.
- if( !$.isArray( functions ) ){
- functions = [ functions ];
- }
-
- $.each( functions, function(){
- if (typeof this === 'function') {
- this.call(scope);
- }
- });
- }
-
- // Returns a proxy to set a target using the public value method.
- function setN ( target, number ) {
-
- return function(){
-
- // Determine the correct position to set,
- // leave the other one unchanged.
- var val = [null, null];
- val[ number ] = $(this).val();
-
- // Trigger the 'set' callback
- target.val(val, true);
- };
- }
-
- // Round a value to the closest 'to'.
- function closest ( value, to ){
- return Math.round(value / to) * to;
- }
-
- // Format output value to specified standards.
- function format ( value, options ) {
-
- // Round the value to the resolution that was set
- // with the serialization options.
- value = value.toFixed( options['decimals'] );
-
- // Rounding away decimals might cause a value of -0
- // when using very small ranges. Remove those cases.
- if ( parseFloat(value) === 0 ) {
- value = value.replace('-0', '0');
- }
-
- // Apply the proper decimal mark to the value.
- return value.replace( '.', options['serialization']['mark'] );
- }
-
- // Determine the handle closest to an event.
- function closestHandle ( handles, location, style ) {
-
- if ( handles.length === 1 ) {
- return handles[0];
- }
-
- var total = handles[0].offset()[style] +
- handles[1].offset()[style];
-
- return handles[ location < total / 2 ? 0 : 1 ];
- }
-
- // Round away small numbers in floating point implementation.
- function digits ( value, round ) {
- return parseFloat(value.toFixed(round));
- }
-
-// Event abstraction
-
- // Provide a clean event with standardized offset values.
- function fixEvent ( e ) {
-
- // Prevent scrolling and panning on touch events, while
- // attempting to slide. The tap event also depends on this.
- e.preventDefault();
-
- // Filter the event to register the type, which can be
- // touch, mouse or pointer. Offset changes need to be
- // made on an event specific basis.
- var touch = e.type.indexOf('touch') === 0
- ,mouse = e.type.indexOf('mouse') === 0
- ,pointer = e.type.indexOf('pointer') === 0
- ,x,y, event = e;
-
- // IE10 implemented pointer events with a prefix;
- if ( e.type.indexOf('MSPointer') === 0 ) {
- pointer = true;
- }
-
- // Get the originalEvent, if the event has been wrapped
- // by jQuery. Zepto doesn't wrap the event.
- if ( e.originalEvent ) {
- e = e.originalEvent;
- }
-
- if ( touch ) {
- // noUiSlider supports one movement at a time,
- // so we can select the first 'changedTouch'.
- x = e.changedTouches[0].pageX;
- y = e.changedTouches[0].pageY;
- }
- if ( mouse || pointer ) {
-
- // Polyfill the pageXOffset and pageYOffset
- // variables for IE7 and IE8;
- if( !pointer && window.pageXOffset === undefined ){
- window.pageXOffset = document.documentElement.scrollLeft;
- window.pageYOffset = document.documentElement.scrollTop;
- }
-
- x = e.clientX + window.pageXOffset;
- y = e.clientY + window.pageYOffset;
- }
-
- return $.extend( event, {
- 'pointX': x
- ,'pointY': y
- ,cursor: mouse
- });
- }
-
- // Handler for attaching events trough a proxy
- function attach ( events, element, callback, pass ) {
-
- var target = pass.target;
-
- // Add the noUiSlider namespace to all events.
- events = events.replace( /\s/g, namespace + ' ' ) + namespace;
-
- // Bind a closure on the target.
- return element.on( events, function( e ){
-
- // jQuery and Zepto handle unset attributes differently.
- var disabled = target.attr('disabled');
- disabled = !( disabled === undefined || disabled === null );
-
- // Test if there is anything that should prevent an event
- // from being handled, such as a disabled state or an active
- // 'tap' transition.
- if( target.hasClass('noUi-state-tap') || disabled ) {
- return false;
- }
-
- // Call the event handler with three arguments:
- // - The event;
- // - An object with data for the event;
- // - The slider options;
- // Having the slider options as a function parameter prevents
- // getting it in every function, which muddies things up.
- callback (
- fixEvent( e )
- ,pass
- ,target.data('base').data('options')
- );
- });
- }
-
-
-// Serialization and value storage
-
- // Store a value on all serialization targets, or get the current value.
- function serialize ( a ) {
-
- /*jshint validthis: true */
-
- // Re-scope target for availability within .each;
- var target = this.target;
-
- // Get the value for this handle
- if ( a === undefined ) {
- return this.element.data('value');
- }
-
- // Write the value to all serialization objects
- // or store a new value on the handle
- if ( a === true ) {
- a = this.element.data('value');
- } else {
- this.element.data('value', a);
- }
-
- // Prevent a serialization call if the value wasn't initialized.
- if ( a === undefined ) {
- return;
- }
-
- // If the provided element was a function,
- // call it with the slider as scope. Otherwise,
- // simply call the function on the object.
- $.each( this.elements, function() {
- if ( typeof this === 'function' ) {
- this.call(target, a);
- } else {
- this[0][this[1]](a);
- }
- });
- }
-
- // Map serialization to [ element, method ]. Attach events where required.
- function storeElement ( handle, item, number ) {
-
- // Add a change event to the supplied jQuery objects,
- // which triggers the value-setting function on the target.
- if ( isInstance( item ) ) {
-
- var elements = [], target = handle.data('target');
-
- // Link the field to the other handle if the
- // slider is inverted.
- if ( handle.data('options').direction ) {
- number = number ? 0 : 1;
- }
-
- // Loop all items so the change event is properly bound,
- // and the items can individually be added to the array.
- item.each(function(){
-
- // Bind the change event.
- $(this).on('change' + namespace, setN( target, number ));
-
- // Store the element with the proper handler.
- elements.push([ $(this), 'val' ]);
- });
-
- return elements;
- }
-
- // Append a new input to the noUiSlider base.
- // Prevent the change event from flowing upward.
- if ( typeof item === 'string' ) {
-
- item = [ $('<input type="hidden" name="'+ item +'">')
- .appendTo(handle)
- .addClass(clsList[3])
- .change(function ( e ) {
- e.stopPropagation();
- }), 'val'];
- }
-
- return [item];
- }
-
- // Access point and abstraction for serialization.
- function store ( handle, i, serialization ) {
-
- var elements = [];
-
- // Loops all items in the provided serialization setting,
- // add the proper events to them or create new input fields,
- // and add them as data to the handle so they can be kept
- // in sync with the slider value.
- $.each( serialization['to'][i], function( index ){
- elements = elements.concat(
- storeElement( handle, serialization['to'][i][index], i )
- );
- });
-
- return {
- element: handle
- ,elements: elements
- ,target: handle.data('target')
- ,'val': serialize
- };
- }
-
-
-// Handle placement
-
- // Fire callback on unsuccessful handle movement.
- function block ( base, stateless ) {
-
- var target = base.data('target');
-
- if ( !target.hasClass(clsList[14]) ){
-
- // The visual effects should not always be applied.
- if ( !stateless ) {
- target.addClass(clsList[15]);
- setTimeout(function(){
- target.removeClass(clsList[15]);
- }, 450);
- }
-
- target.addClass(clsList[14]);
- call( base.data('options').block, target );
- }
- }
-
- // Change inline style and apply proper classes.
- function placeHandle ( handle, to ) {
-
- var settings = handle.data('options');
-
- to = digits(to, 7);
-
- // If the slider can move, remove the class
- // indicating the block state.
- handle.data('target').removeClass(clsList[14]);
-
- // Set handle to new location
- handle.css( settings['style'], to + '%' ).data('pct', to);
-
- // Force proper handle stacking
- if ( handle.is(':first-child') ) {
- handle.toggleClass(clsList[13], to > 50 );
- }
-
- if ( settings['direction'] ) {
- to = 100 - to;
- }
-
- // Write the value to the serialization object.
- handle.data('store').val(
- format ( isPercentage( settings['range'], to ), settings )
- );
- }
-
- // Test suggested values and apply margin, step.
- function setHandle ( handle, to ) {
-
- var base = handle.data('base'), settings = base.data('options'),
- handles = base.data('handles'), lower = 0, upper = 100;
-
- // Catch invalid user input
- if ( !isNumeric( to ) ){
- return false;
- }
-
- // Handle the step option.
- if ( settings['step'] ){
- to = closest( to, settings['step'] );
- }
-
- if ( handles.length > 1 ){
- if ( handle[0] !== handles[0][0] ) {
- lower = digits(handles[0].data('pct')+settings['margin'],7);
- } else {
- upper = digits(handles[1].data('pct')-settings['margin'],7);
- }
- }
-
- // Limit position to boundaries. When the handles aren't set yet,
- // they return -1 as a percentage value.
- to = Math.min( Math.max( to, lower ), upper < 0 ? 100 : upper );
-
- // Stop handling this call if the handle can't move past another.
- // Return an array containing the hit limit, so the caller can
- // provide feedback. ( block callback ).
- if ( to === handle.data('pct') ) {
- return [!lower ? false : lower, upper === 100 ? false : upper];
- }
-
- placeHandle ( handle, to );
- return true;
- }
-
- // Handles movement by tapping
- function jump ( base, handle, to, callbacks ) {
-
- // Flag the slider as it is now in a transitional state.
- // Transition takes 300 ms, so re-enable the slider afterwards.
- base.addClass(clsList[5]);
- setTimeout(function(){
- base.removeClass(clsList[5]);
- }, 300);
-
- // Move the handle to the new position.
- setHandle( handle, to );
-
- // Trigger the 'slide' and 'set' callbacks,
- // pass the target so that it is 'this'.
- call( callbacks, base.data('target') );
-
- base.data('target').change();
- }
-
-
-// Event handlers
-
- // Handle movement on document for handle and range drag.
- function move ( event, Dt, Op ) {
-
- // Map event movement to a slider percentage.
- var handles = Dt.handles, limits,
- proposal = event[ Dt.point ] - Dt.start[ Dt.point ];
-
- proposal = ( proposal * 100 ) / Dt.size;
-
- if ( handles.length === 1 ) {
-
- // Run handle placement, receive true for success or an
- // array with potential limits.
- limits = setHandle( handles[0], Dt.positions[0] + proposal );
-
- if ( limits !== true ) {
-
- if ( $.inArray ( handles[0].data('pct'), limits ) >= 0 ){
- block ( Dt.base, !Op['margin'] );
- }
- return;
- }
-
- } else {
-
- // Dragging the range could be implemented by forcing the
- // 'move' event on both handles, but this solution proved
- // lagging on slower devices, resulting in range errors. The
- // slightly ugly solution below is considerably faster, and
- // it can't move the handle out of sync. Bypass the standard
- // setting method, as other checks are needed.
-
- var l1, u1, l2, u2;
-
- // Round the proposal to the step setting.
- if ( Op['step'] ) {
- proposal = closest( proposal, Op['step'] );
- }
-
- // Determine the new position, store it twice. Once for
- // limiting, once for checking whether placement should occur.
- l1 = l2 = Dt.positions[0] + proposal;
- u1 = u2 = Dt.positions[1] + proposal;
-
- // Round the values within a sensible range.
- if ( l1 < 0 ) {
- u1 += -1 * l1;
- l1 = 0;
- } else if ( u1 > 100 ) {
- l1 -= ( u1 - 100 );
- u1 = 100;
- }
-
- // Don't perform placement if no handles are to be changed.
- // Check if the lowest value is set to zero.
- if ( l2 < 0 && !l1 && !handles[0].data('pct') ) {
- return;
- }
- // The highest value is limited to 100%.
- if ( u1 === 100 && u2 > 100 && handles[1].data('pct') === 100 ){
- return;
- }
-
- placeHandle ( handles[0], l1 );
- placeHandle ( handles[1], u1 );
- }
-
- // Trigger the 'slide' event, if the handle was moved.
- call( Op['slide'], Dt.target );
- }
-
- // Unbind move events on document, call callbacks.
- function end ( event, Dt, Op ) {
-
- // The handle is no longer active, so remove the class.
- if ( Dt.handles.length === 1 ) {
- Dt.handles[0].data('grab').removeClass(clsList[4]);
- }
-
- // Remove cursor styles and text-selection events bound to the body.
- if ( event.cursor ) {
- body.css('cursor', '').off( namespace );
- }
-
- // Unbind the move and end events, which are added on 'start'.
- doc.off( namespace );
-
- // Trigger the change event.
- Dt.target.removeClass( clsList[14] +' '+ clsList[20]).change();
-
- // Trigger the 'end' callback.
- call( Op['set'], Dt.target );
- }
-
- // Bind move events on document.
- function start ( event, Dt, Op ) {
-
- // Mark the handle as 'active' so it can be styled.
- if( Dt.handles.length === 1 ) {
- Dt.handles[0].data('grab').addClass(clsList[4]);
- }
-
- // A drag should never propagate up to the 'tap' event.
- event.stopPropagation();
-
- // Attach the move event.
- attach ( actions.move, doc, move, {
- start: event
- ,base: Dt.base
- ,target: Dt.target
- ,handles: Dt.handles
- ,positions: [ Dt.handles[0].data('pct')
- ,Dt.handles[ Dt.handles.length - 1 ].data('pct') ]
- ,point: Op['orientation'] ? 'pointY' : 'pointX'
- ,size: Op['orientation'] ? Dt.base.height() : Dt.base.width()
- });
-
- // Unbind all movement when the drag ends.
- attach ( actions.end, doc, end, {
- target: Dt.target
- ,handles: Dt.handles
- });
-
- // Text selection isn't an issue on touch devices,
- // so adding additional callbacks isn't required.
- if ( event.cursor ) {
-
- // Prevent the 'I' cursor and extend the range-drag cursor.
- body.css('cursor', $(event.target).css('cursor'));
-
- // Mark the target with a dragging state.
- if ( Dt.handles.length > 1 ) {
- Dt.target.addClass(clsList[20]);
- }
-
- // Prevent text selection when dragging the handles.
- body.on('selectstart' + namespace, function( ){
- return false;
- });
- }
- }
-
- // Move closest handle to tapped location.
- function tap ( event, Dt, Op ) {
-
- var base = Dt.base, handle, to, point, size;
-
- // The tap event shouldn't propagate up to trigger 'edge'.
- event.stopPropagation();
-
- // Determine the direction of the slider.
- if ( Op['orientation'] ) {
- point = event['pointY'];
- size = base.height();
- } else {
- point = event['pointX'];
- size = base.width();
- }
-
- // Find the closest handle and calculate the tapped point.
- handle = closestHandle( base.data('handles'), point, Op['style'] );
- to = (( point - base.offset()[ Op['style'] ] ) * 100 ) / size;
-
- // The set handle to the new position.
- jump( base, handle, to, [ Op['slide'], Op['set'] ]);
- }
-
- // Move handle to edges when target gets tapped.
- function edge ( event, Dt, Op ) {
-
- var handles = Dt.base.data('handles'), to, i;
-
- i = Op['orientation'] ? event['pointY'] : event['pointX'];
- i = i < Dt.base.offset()[Op['style']];
-
- to = i ? 0 : 100;
- i = i ? 0 : handles.length - 1;
-
- jump ( Dt.base, handles[i], to, [ Op['slide'], Op['set'] ]);
- }
-
-// API
-
- // Validate and standardize input.
- function test ( input, sliders ){
-
- /* Every input option is tested and parsed. This'll prevent
- endless validation in internal methods. These tests are
- structured with an item for every option available. An
- option can be marked as required by setting the 'r' flag.
- The testing function is provided with three arguments:
- - The provided value for the option;
- - A reference to the options object;
- - The name for the option;
-
- The testing function returns false when an error is detected,
- or true when everything is OK. It can also modify the option
- object, to make sure all values can be correctly looped elsewhere. */
-
- function values ( a ) {
-
- if ( a.length !== 2 ){
- return false;
- }
-
- // Convert the array to floats
- a = [ parseFloat(a[0]), parseFloat(a[1]) ];
-
- // Test if all values are numerical
- if( !isNumeric(a[0]) || !isNumeric(a[1]) ){
- return false;
- }
-
- // The lowest value must really be the lowest value.
- if( a[1] < a[0] ){
- return false;
- }
-
- return a;
- }
-
- var serialization = {
- resolution: function(q,o){
-
- // Parse the syntactic sugar that is the serialization
- // resolution option to a usable integer.
- // Checking for a string '1', since the resolution needs
- // to be cast to a string to split in on the period.
- switch( q ){
- case 1:
- case 0.1:
- case 0.01:
- case 0.001:
- case 0.0001:
- case 0.00001:
- q = q.toString().split('.');
- o['decimals'] = q[0] === '1' ? 0 : q[1].length;
- break;
- case undefined:
- o['decimals'] = 2;
- break;
- default:
- return false;
- }
-
- return true;
- }
- ,mark: function(q,o,w){
-
- if ( !q ) {
- o[w]['mark'] = '.';
- return true;
- }
-
- switch( q ){
- case '.':
- case ',':
- return true;
- default:
- return false;
- }
- }
- ,to: function(q,o,w){
-
- // Checks whether a variable is a candidate to be a
- // valid serialization target.
- function ser(r){
- return isInstance ( r ) ||
- typeof r === 'string' ||
- typeof r === 'function' ||
- r === false ||
- ( isInstance ( r[0] ) &&
- typeof r[0][r[1]] === 'function' );
- }
-
- // Flatten the serialization array into a reliable
- // set of elements, which can be tested and looped.
- function filter ( value ) {
-
- var items = [[],[]];
-
- // If a single value is provided it can be pushed
- // immediately.
- if ( ser(value) ) {
- items[0].push(value);
- } else {
-
- // Otherwise, determine whether this is an
- // array of single elements or sets.
- $.each(value, function(i, val) {
-
- // Don't handle an overflow of elements.
- if( i > 1 ){
- return;
- }
-
- // Decide if this is a group or not
- if( ser(val) ){
- items[i].push(val);
- } else {
- items[i] = items[i].concat(val);
- }
- });
- }
-
- return items;
- }
-
- if ( !q ) {
- o[w]['to'] = [[],[]];
- } else {
-
- var i, j;
-
- // Flatten the serialization array
- q = filter ( q );
-
- // Reverse the API for RTL sliders.
- if ( o['direction'] && q[1].length ) {
- q.reverse();
- }
-
- // Test all elements in the flattened array.
- for ( i = 0; i < o['handles']; i++ ) {
- for ( j = 0; j < q[i].length; j++ ) {
-
- // Return false on invalid input
- if( !ser(q[i][j]) ){
- return false;
- }
-
- // Remove 'false' elements, since those
- // won't be handled anyway.
- if( !q[i][j] ){
- q[i].splice(j, 1);
- }
- }
- }
-
- // Write the new values back
- o[w]['to'] = q;
- }
-
- return true;
- }
- }, tests = {
- /* Handles.
- * Has default, can be 1 or 2.
- */
- 'handles': {
- 'r': true
- ,'t': function(q){
- q = parseInt(q, 10);
- return ( q === 1 || q === 2 );
- }
- }
- /* Range.
- * Must be an array of two numerical floats,
- * which can't be identical.
- */
- ,'range': {
- 'r': true
- ,'t': function(q,o,w){
-
- o[w] = values(q);
-
- // The values can't be identical.
- return o[w] && o[w][0] !== o[w][1];
- }
- }
- /* Start.
- * Must be an array of two numerical floats when handles = 2;
- * Uses 'range' test.
- * When handles = 1, a single float is also allowed.
- */
- ,'start': {
- 'r': true
- ,'t': function(q,o,w){
- if( o['handles'] === 1 ){
- if( $.isArray(q) ){
- q = q[0];
- }
- q = parseFloat(q);
- o.start = [q];
- return isNumeric(q);
- }
-
- o[w] = values(q);
- return !!o[w];
- }
- }
- /* Connect.
- * Must be true or false when handles = 2;
- * Can use 'lower' and 'upper' when handles = 1.
- */
- ,'connect': {
- 'r': true
- ,'t': function(q,o,w){
-
- if ( q === 'lower' ) {
- o[w] = 1;
- } else if ( q === 'upper' ) {
- o[w] = 2;
- } else if ( q === true ) {
- o[w] = 3;
- } else if ( q === false ) {
- o[w] = 0;
- } else {
- return false;
- }
-
- return true;
- }
- }
- /* Connect.
- * Will default to horizontal, not required.
- */
- ,'orientation': {
- 't': function(q,o,w){
- switch (q){
- case 'horizontal':
- o[w] = 0;
- break;
- case 'vertical':
- o[w] = 1;
- break;
- default: return false;
- }
- return true;
- }
- }
- /* Margin.
- * Must be a float, has a default value.
- */
- ,'margin': {
- 'r': true
- ,'t': function(q,o,w){
- q = parseFloat(q);
- o[w] = fromPercentage(o['range'], q);
- return isNumeric(q);
- }
- }
- /* Direction.
- * Required, can be 'ltr' or 'rtl'.
- */
- ,'direction': {
- 'r': true
- ,'t': function(q,o,w){
-
- switch ( q ) {
- case 'ltr': o[w] = 0;
- break;
- case 'rtl': o[w] = 1;
- // Invert connection for RTL sliders;
- o['connect'] = [0,2,1,3][o['connect']];
- break;
- default:
- return false;
- }
-
- return true;
- }
- }
- /* Behaviour.
- * Required, defines responses to tapping and
- * dragging elements.
- */
- ,'behaviour': {
- 'r': true
- ,'t': function(q,o,w){
-
- o[w] = {
- 'tap': q !== (q = q.replace('tap', ''))
- ,'extend': q !== (q = q.replace('extend', ''))
- ,'drag': q !== (q = q.replace('drag', ''))
- ,'fixed': q !== (q = q.replace('fixed', ''))
- };
-
- return !q.replace('none','').replace(/\-/g,'');
- }
- }
- /* Serialization.
- * Required, but has default. Must be an array
- * when using two handles, can be a single value when using
- * one handle. 'mark' can be period (.) or comma (,).
- */
- ,'serialization': {
- 'r': true
- ,'t': function(q,o,w){
-
- return serialization.to( q['to'], o, w ) &&
- serialization.resolution( q['resolution'], o ) &&
- serialization.mark( q['mark'], o, w );
- }
- }
- /* Slide.
- * Not required. Must be a function.
- */
- ,'slide': {
- 't': function(q){
- return $.isFunction(q);
- }
- }
- /* Set.
- * Not required. Must be a function.
- * Tested using the 'slide' test.
- */
- ,'set': {
- 't': function(q){
- return $.isFunction(q);
- }
- }
- /* Block.
- * Not required. Must be a function.
- * Tested using the 'slide' test.
- */
- ,'block': {
- 't': function(q){
- return $.isFunction(q);
- }
- }
- /* Step.
- * Not required.
- */
- ,'step': {
- 't': function(q,o,w){
- q = parseFloat(q);
- o[w] = fromPercentage ( o['range'], q );
- return isNumeric(q);
- }
- }
- };
-
- $.each( tests, function( name, test ){
-
- /*jslint devel: true */
-
- var value = input[name], isSet = value !== undefined;
-
- // If the value is required but not set, fail.
- if( ( test['r'] && !isSet ) ||
- // If the test returns false, fail.
- ( isSet && !test['t']( value, input, name ) ) ){
-
- // For debugging purposes it might be very useful to know
- // what option caused the trouble. Since throwing an error
- // will prevent further script execution, log the error
- // first. Test for console, as it might not be available.
- if( console && console.log && console.group ){
- console.group( 'Invalid noUiSlider initialisation:' );
- console.log( 'Option:\t', name );
- console.log( 'Value:\t', value );
- console.log( 'Slider(s):\t', sliders );
- console.groupEnd();
- }
-
- throw new RangeError('noUiSlider');
- }
- });
- }
-
- // Parse options, add classes, attach events, create HTML.
- function create ( options ) {
-
- /*jshint validthis: true */
-
- // Store the original set of options on all targets,
- // so they can be re-used and re-tested later.
- // Make sure to break the relation with the options,
- // which will be changed by the 'test' function.
- this.data('options', $.extend(true, {}, options));
-
- // Set defaults where applicable;
- options = $.extend({
- 'handles': 2
- ,'margin': 0
- ,'connect': false
- ,'direction': 'ltr'
- ,'behaviour': 'tap'
- ,'orientation': 'horizontal'
- }, options);
-
- // Make sure the test for serialization runs.
- options['serialization'] = options['serialization'] || {};
-
- // Run all options through a testing mechanism to ensure correct
- // input. The test function will throw errors, so there is
- // no need to capture the result of this call. It should be noted
- // that options might get modified to be handled properly. E.g.
- // wrapping integers in arrays.
- test( options, this );
-
- // Pre-define the styles.
- options['style'] = options['orientation'] ? 'top' : 'left';
-
- return this.each(function(){
-
- var target = $(this), i, dragable, handles = [], handle,
- base = $('<div/>').appendTo(target);
-
- // Throw an error if the slider was already initialized.
- if ( target.data('base') ) {
- throw new Error('Slider was already initialized.');
- }
-
- // Apply classes and data to the target.
- target.data('base', base).addClass([
- clsList[6]
- ,clsList[16 + options['direction']]
- ,clsList[10 + options['orientation']] ].join(' '));
-
- for (i = 0; i < options['handles']; i++ ) {
-
- handle = $('<div><div/></div>').appendTo(base);
-
- // Add all default and option-specific classes to the
- // origins and handles.
- handle.addClass( clsList[1] );
-
- handle.children().addClass([
- clsList[2]
- ,clsList[2] + clsList[ 7 + options['direction'] +
- ( options['direction'] ? -1 * i : i ) ]].join(' ') );
-
- // Make sure every handle has access to all variables.
- handle.data({
- 'base': base
- ,'target': target
- ,'options': options
- ,'grab': handle.children()
- ,'pct': -1
- }).attr('data-style', options['style']);
-
- // Every handle has a storage point, which takes care
- // of triggering the proper serialization callbacks.
- handle.data({
- 'store': store(handle, i, options['serialization'])
- });
-
- // Store handles on the base
- handles.push(handle);
- }
-
- // Apply the required connection classes to the elements
- // that need them. Some classes are made up for several
- // segments listed in the class list, to allow easy
- // renaming and provide a minor compression benefit.
- switch ( options['connect'] ) {
- case 1: target.addClass( clsList[9] );
- handles[0].addClass( clsList[12] );
- break;
- case 3: handles[1].addClass( clsList[12] );
- /* falls through */
- case 2: handles[0].addClass( clsList[9] );
- /* falls through */
- case 0: target.addClass(clsList[12]);
- break;
- }
-
- // Merge base classes with default,
- // and store relevant data on the base element.
- base.addClass( clsList[0] ).data({
- 'target': target
- ,'options': options
- ,'handles': handles
- });
-
- // Use the public value method to set the start values.
- target.val( options['start'] );
-
- // Attach the standard drag event to the handles.
- if ( !options['behaviour']['fixed'] ) {
- for ( i = 0; i < handles.length; i++ ) {
-
- // These events are only bound to the visual handle
- // element, not the 'real' origin element.
- attach ( actions.start, handles[i].children(), start, {
- base: base
- ,target: target
- ,handles: [ handles[i] ]
- });
- }
- }
-
- // Attach the tap event to the slider base.
- if ( options['behaviour']['tap'] ) {
- attach ( actions.start, base, tap, {
- base: base
- ,target: target
- });
- }
-
- // Extend tapping behaviour to target
- if ( options['behaviour']['extend'] ) {
-
- target.addClass( clsList[19] );
-
- if ( options['behaviour']['tap'] ) {
- attach ( actions.start, target, edge, {
- base: base
- ,target: target
- });
- }
- }
-
- // Make the range dragable.
- if ( options['behaviour']['drag'] ){
-
- dragable = base.find('.'+clsList[9]).addClass(clsList[18]);
-
- // When the range is fixed, the entire range can
- // be dragged by the handles. The handle in the first
- // origin will propagate the start event upward,
- // but it needs to be bound manually on the other.
- if ( options['behaviour']['fixed'] ) {
- dragable = dragable
- .add( base.children().not(dragable).data('grab') );
- }
-
- attach ( actions.start, dragable, start, {
- base: base
- ,target: target
- ,handles: handles
- });
- }
- });
- }
-
- // Return value for the slider, relative to 'range'.
- function getValue ( ) {
-
- /*jshint validthis: true */
-
- var base = $(this).data('base'), answer = [];
-
- // Loop the handles, and get the value from the input
- // for every handle on its' own.
- $.each( base.data('handles'), function(){
- answer.push( $(this).data('store').val() );
- });
-
- // If the slider has just one handle, return a single value.
- // Otherwise, return an array, which is in reverse order
- // if the slider is used RTL.
- if ( answer.length === 1 ) {
- return answer[0];
- }
-
- if ( base.data('options').direction ) {
- return answer.reverse();
- }
-
- return answer;
- }
-
- // Set value for the slider, relative to 'range'.
- function setValue ( args, set ) {
-
- /*jshint validthis: true */
-
- // If the value is to be set to a number, which is valid
- // when using a one-handle slider, wrap it in an array.
- if( !$.isArray(args) ){
- args = [args];
- }
-
- // Setting is handled properly for each slider in the data set.
- return this.each(function(){
-
- var b = $(this).data('base'), to, i,
- handles = Array.prototype.slice.call(b.data('handles'),0),
- settings = b.data('options');
-
- // If there are multiple handles to be set run the setting
- // mechanism twice for the first handle, to make sure it
- // can be bounced of the second one properly.
- if ( handles.length > 1) {
- handles[2] = handles[0];
- }
-
- // The RTL settings is implemented by reversing the front-end,
- // internal mechanisms are the same.
- if ( settings['direction'] ) {
- args.reverse();
- }
-
- for ( i = 0; i < handles.length; i++ ){
-
- // Calculate a new position for the handle.
- to = args[ i%2 ];
-
- // The set request might want to ignore this handle.
- // Test for 'undefined' too, as a two-handle slider
- // can still be set with an integer.
- if( to === null || to === undefined ) {
- continue;
- }
-
- // Add support for the comma (,) as a decimal symbol.
- // Replace it by a period so it is handled properly by
- // parseFloat. Omitting this would result in a removal
- // of decimals. This way, the developer can also
- // input a comma separated string.
- if( $.type(to) === 'string' ) {
- to = to.replace(',', '.');
- }
-
- // Calculate the new handle position
- to = toPercentage( settings['range'], parseFloat( to ) );
-
- // Invert the value if this is an right-to-left slider.
- if ( settings['direction'] ) {
- to = 100 - to;
- }
-
- // If the value of the input doesn't match the slider,
- // reset it. Sometimes the input is changed to a value the
- // slider has rejected. This can occur when using 'select'
- // or 'input[type="number"]' elements. In this case, set
- // the value back to the input.
- if ( setHandle( handles[i], to ) !== true ){
- handles[i].data('store').val( true );
- }
-
- // Optionally trigger the 'set' event.
- if( set === true ) {
- call( settings['set'], $(this) );
- }
- }
- });
- }
-
- // Unbind all attached events, remove classed and HTML.
- function destroy ( target ) {
-
- // Start the list of elements to be unbound with the target.
- var elements = [[target,'']];
-
- // Get the fields bound to both handles.
- $.each(target.data('base').data('handles'), function(){
- elements = elements.concat( $(this).data('store').elements );
- });
-
- // Remove all events added by noUiSlider.
- $.each(elements, function(){
- if( this.length > 1 ){
- this[0].off( namespace );
- }
- });
-
- // Remove all classes from the target.
- target.removeClass(clsList.join(' '));
-
- // Empty the target and remove all data.
- target.empty().removeData('base options');
- }
-
- // Merge options with current initialization, destroy slider
- // and reinitialize.
- function build ( options ) {
-
- /*jshint validthis: true */
-
- return this.each(function(){
-
- // When uninitialised, jQuery will return '',
- // Zepto returns undefined. Both are falsy.
- var values = $(this).val() || false,
- current = $(this).data('options'),
- // Extend the current setup with the new options.
- setup = $.extend( {}, current, options );
-
- // If there was a slider initialised, remove it first.
- if ( values !== false ) {
- destroy( $(this) );
- }
-
- // Make the destroy method publicly accessible.
- if( !options ) {
- return;
- }
-
- // Create a new slider
- $(this)['noUiSlider']( setup );
-
- // Set the slider values back. If the start options changed,
- // it gets precedence.
- if ( values !== false && setup.start === current.start ) {
- $(this).val( values );
- }
- });
- }
-
- // Overwrite the native jQuery value function
- // with a simple handler. noUiSlider will use the internal
- // value method, anything else will use the standard method.
- $.fn.val = function(){
-
- // If the function is called without arguments,
- // act as a 'getter'. Call the getValue function
- // in the same scope as this call.
- if ( this.hasClass( clsList[6] ) ){
- return arguments.length ?
- setValue.apply( this, arguments ) :
- getValue.apply( this );
- }
-
- // If this isn't noUiSlider, continue with jQuery's
- // original method.
- return $VAL.apply( this, arguments );
- };
-
- return ( rebuild ? build : create ).call( this, options );
- };
-
-}( window['jQuery'] || window['Zepto'] ));