diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 28e29886..00000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "submodules/wNumb"] - path = submodules/wNumb - url = https://github.com/leongersen/wnumb -[submodule "submodules/libLink"] - path = submodules/libLink - url = https://github.com/leongersen/libLink diff --git a/Gruntfile.js b/Gruntfile.js index 417ca4ad..b352b604 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -4,37 +4,29 @@ module.exports = function(grunt) { '<%= grunt.template.today("yyyy-mm-dd HH:MM:ss") %> */' + '\n\n'; - function getFiles ( append ) { + function getFiles ( ) { - var files = [ - 'src/js/helpers/intro.js', + return [ + 'src/js/intro.js', 'src/js/helpers.js', 'src/js/constants.js', 'src/js/range.js', 'src/js/options.js', 'src/js/structure.js', 'src/js/scope_start.js', + 'src/js/pips.js', 'src/js/scope_helpers.js', - 'src/js/scope_link.js', 'src/js/scope_events.js', 'src/js/scope.js', 'src/js/scope_end.js', - 'src/js/interface.js' + 'src/js/interface.js', + 'src/js/outro.js' ]; - - if ( append ) { - files = files.concat(append); - } - - files.push('src/js/helpers/outro.js'); - - return files; } var releaseFiles = [ { src: ['**/*'], dest: '', cwd: 'distribute/', expand: true }, - { src: ['**/*.css'], dest: '', cwd: 'src/', expand: true }, - { src: ['**/archive.md'], rename: function(){ return 'README.md'; }, dest: '', cwd: 'src/', expand: true } + { src: ['**/*.css'], dest: '', cwd: 'src/', expand: true } ]; grunt.initConfig({ @@ -45,14 +37,9 @@ module.exports = function(grunt) { }, basic: { src: getFiles(), - dest: 'distribute/jquery.nouislider.js', + dest: 'distribute/nouislider.js', nonull: true - }, - all: { - src: ['submodules/wNumb/wNumb.js', 'submodules/libLink/jquery.libLink.js'].concat(getFiles('src/js/pips.js')), - dest: 'distribute/jquery.nouislider.all.js', - nonull: true - }, + } }, cssmin: { all: { @@ -60,21 +47,7 @@ module.exports = function(grunt) { banner: VERSION_TEMPLATE }, files: { - 'distribute/jquery.nouislider.min.css': ['src/jquery.nouislider.css'], - 'distribute/jquery.nouislider.pips.min.css': ['src/jquery.nouislider.pips.css'] - } - } - }, - 'string-replace': { - version: { - files: { - 'nouislider.jquery.json': 'src/jquery.json' - }, - options: { - replacements: [{ - pattern: /{{VERSION}}/g, - replacement: '<%= pkg.version %>' - }] + 'distribute/nouislider.min.css': ['src/nouislider.css', 'src/nouislider.pips.css'] } } }, @@ -87,8 +60,7 @@ module.exports = function(grunt) { validthis: true, newcap: false }, - basic: ['distribute/jquery.nouislider.js'], - all: ['distribute/jquery.nouislider.all.js'] + basic: ['distribute/nouislider.js'] }, uglify: { all: { @@ -96,8 +68,7 @@ module.exports = function(grunt) { banner: VERSION_TEMPLATE }, files: { - 'distribute/jquery.nouislider.min.js': 'distribute/jquery.nouislider.js', - 'distribute/jquery.nouislider.all.min.js': 'distribute/jquery.nouislider.all.js' + 'distribute/nouislider.min.js': 'distribute/nouislider.js' } } }, @@ -120,9 +91,6 @@ module.exports = function(grunt) { // https://github.com/gruntjs/grunt-contrib-jshint grunt.loadNpmTasks('grunt-contrib-jshint'); - // https://github.com/erickrdch/grunt-string-replace - grunt.loadNpmTasks('grunt-string-replace'); - // https://github.com/gruntjs/grunt-contrib-cssmin grunt.loadNpmTasks('grunt-contrib-cssmin'); @@ -131,5 +99,5 @@ module.exports = function(grunt) { grunt.registerTask('default', ['concat', 'jshint']); grunt.registerTask('create', ['concat', 'jshint', 'uglify', 'cssmin']); - grunt.registerTask('release', ['string-replace', 'compress']); + grunt.registerTask('release', ['compress']); }; diff --git a/README.md b/README.md index 341986b8..f09c7195 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # noUiSlider -noUiSlider is lightweight plugin, developed to be a jQuery UI alternative. It features cross-browser support, a `just-another-input-type` style of getting and setting values, a wide range of options and support for a bunch of touch devices. It works wonders on Android phones, iPhone & iPad, Windows phone and touch-screen laptops and tablets. It works excellent on the desktop too; All modern browsers and IE7+ are supported. The end result? A lean, extendible and bloat-less plugin that'll just do its job. To add even more flexibility, noUiSlider is compatible with both jQuery and Zepto.js. Oh, and the licensing terms are simple: [just do what you want](http://www.wtfpl.net/about/). +noUiSlider is lightweight JavaScript range slider, originally developed to be a jQuery UI alternative. It features cross-browser support, a wide range of options and support for a bunch of touch devices. It has been tested on Android phones, iPhone & iPad, Windows phone and touch-screen laptops and tablets and desktops; All modern browsers and IE9+ are supported. The end result? A lean, extendible and bloat-less plugin that'll just do its job. + +The best part? noUiSlider has no dependencies! As of version 8, **Query is no longer required!** + +Oh, and the licensing terms are simple: [just do what you want](http://www.wtfpl.net/about/). Documentation ------- @@ -12,48 +16,27 @@ Bower users can install all compiled and minified files easily using `bower inst Changelog --------- -###7.0.10 -+ Fixed an issue where calling `.val(undefined)` wouldn't match specification (#383); -+ Values in `range` are now properly sorted before being used (and can thus be passed in any order) (#393); -+ Fixed an error in `.noUiSlider('step')` where JS floating point precision would mess up a comparison (#391); -+ Fixed the slider styles failing when CSS `direction: rtl` is set (#275, #377); -+ Fixed throwing an error when running `.noUiSlider` on an empty selection (#325); -+ Fixed the filter function for the pips plugin not always being called (#365); - -###7.0.9 -+ Fixed an issue when using the pips plugin with sliders not starting at `0`. (#357) - -###7.0.8 -+ Fixed an issue in the way the `$.fn.val` method is overridden. (#350) - -###7.0.4 ~ 7.0.7 -+ Bower support. - -###7.0.3: -+ Fixed an issue with Link on single-handle RTL sliders. - -###7.0.2: -+ Fixed an issue with the handle `z-index`. (#333) -+ Added pips formatting. (#330) -+ Added Grunt-based tasks. - -###7.x -noUiSlider is currently on version 7. This version contains significant changes from 6, improving various aspects and moving some features in their own module. -+ All serialization features are now supported by my new project, [libLink](http://refreshless.com/liblink/). -+ All number formatting features have been moved into the [wNumb formatting library](http://refreshless.com/wnumb/). -+ The val method now only takes values, as all additional options are now automaticly detected. -+ Documentation overhaul -+ Improved and restructured testing suite. -+ Performance improvements due to painting in another layer. (#268); -+ Minified file is now clearly marked (#320). -+ Added `limit` option to provide 'maximum margin' (#308). -+ Fixed rebuilding an uninitialized slider (#271). -+ Added generation of pips/range points (#254, #260). -+ Fixed `tap` ignoring `margin` (#265). - -Unit Testing ------------- -Unit tests where overhauled for noUiSlider 7. Most code is now covered, with events testing being slightly lacking due to it's browser dependant nature. +###8.0.0 +Remove jQuery dependency! For more info and other changes, see [the release information](http://refreshless.com/nouislider/new-version). + +Browserify +---------- +This library is [UMD](https://github.com/umdjs/umd) compatible, so you can use it in this way: + +```javascript +require('nouislider'); + +var slider = document.getElementById('slider'); + +noUiSlider.create(slider, { + start: 40, + connect: "lower", + range: { + min: 0, + max: 100 + } +}); +``` Version numbering ------------------------------ diff --git a/bower.json b/bower.json index e7ea825a..80c85dfa 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,6 @@ "name": "nouislider", "description": "A lightweight, highly customizable range slider without bloat. Touch support on all modern devices and responsive design ready!", "keywords": [ - "jquery", "slider", "form", "range", @@ -12,13 +11,9 @@ "slide" ], "main": [ - "distribute/jquery.nouislider.all.min.js", - "distribute/jquery.nouislider.min.css", - "distribute/jquery.nouislider.pips.min.css" + "distribute/nouislider.js", + "distribute/nouislider.min.css", ], - "dependencies": { - "jquery": ">= 1.7.0" - }, "ignore": [ "**/.*", "**/*.json" diff --git a/distribute/jquery.nouislider.all.js b/distribute/jquery.nouislider.all.js deleted file mode 100644 index 0f57fba9..00000000 --- a/distribute/jquery.nouislider.all.js +++ /dev/null @@ -1,2314 +0,0 @@ -/*! noUiSlider - 7.0.10 - 2014-12-27 14:50:46 */ - -(function(){ - - 'use strict'; - -var -/** @const */ FormatOptions = [ - 'decimals', - 'thousand', - 'mark', - 'prefix', - 'postfix', - 'encoder', - 'decoder', - 'negativeBefore', - 'negative', - 'edit', - 'undo' -]; - -// General - - // Reverse a string - function strReverse ( a ) { - return a.split('').reverse().join(''); - } - - // Check if a string starts with a specified prefix. - function strStartsWith ( input, match ) { - return input.substring(0, match.length) === match; - } - - // Check is a string ends in a specified postfix. - function strEndsWith ( input, match ) { - return input.slice(-1 * match.length) === match; - } - - // Throw an error if formatting options are incompatible. - function throwEqualError( F, a, b ) { - if ( (F[a] || F[b]) && (F[a] === F[b]) ) { - throw new Error(a); - } - } - - // Check if a number is finite and not NaN - function isValidNumber ( input ) { - return typeof input === 'number' && isFinite( input ); - } - - // Provide rounding-accurate toFixed method. - function toFixed ( value, decimals ) { - var scale = Math.pow(10, decimals); - return ( Math.round(value * scale) / scale).toFixed( decimals ); - } - - -// Formatting - - // Accept a number as input, output formatted string. - function formatTo ( decimals, thousand, mark, prefix, postfix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { - - var originalInput = input, inputIsNegative, inputPieces, inputBase, inputDecimals = '', output = ''; - - // Apply user encoder to the input. - // Expected outcome: number. - if ( encoder ) { - input = encoder(input); - } - - // Stop if no valid number was provided, the number is infinite or NaN. - if ( !isValidNumber(input) ) { - return false; - } - - // Rounding away decimals might cause a value of -0 - // when using very small ranges. Remove those cases. - if ( decimals !== false && parseFloat(input.toFixed(decimals)) === 0 ) { - input = 0; - } - - // Formatting is done on absolute numbers, - // decorated by an optional negative symbol. - if ( input < 0 ) { - inputIsNegative = true; - input = Math.abs(input); - } - - // Reduce the number of decimals to the specified option. - if ( decimals !== false ) { - input = toFixed( input, decimals ); - } - - // Transform the number into a string, so it can be split. - input = input.toString(); - - // Break the number on the decimal separator. - if ( input.indexOf('.') !== -1 ) { - inputPieces = input.split('.'); - - inputBase = inputPieces[0]; - - if ( mark ) { - inputDecimals = mark + inputPieces[1]; - } - - } else { - - // If it isn't split, the entire number will do. - inputBase = input; - } - - // Group numbers in sets of three. - if ( thousand ) { - inputBase = strReverse(inputBase).match(/.{1,3}/g); - inputBase = strReverse(inputBase.join( strReverse( thousand ) )); - } - - // If the number is negative, prefix with negation symbol. - if ( inputIsNegative && negativeBefore ) { - output += negativeBefore; - } - - // Prefix the number - if ( prefix ) { - output += prefix; - } - - // Normal negative option comes after the prefix. Defaults to '-'. - if ( inputIsNegative && negative ) { - output += negative; - } - - // Append the actual number. - output += inputBase; - output += inputDecimals; - - // Apply the postfix. - if ( postfix ) { - output += postfix; - } - - // Run the output through a user-specified post-formatter. - if ( edit ) { - output = edit ( output, originalInput ); - } - - // All done. - return output; - } - - // Accept a sting as input, output decoded number. - function formatFrom ( decimals, thousand, mark, prefix, postfix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { - - var originalInput = input, inputIsNegative, output = ''; - - // User defined pre-decoder. Result must be a non empty string. - if ( undo ) { - input = undo(input); - } - - // Test the input. Can't be empty. - if ( !input || typeof input !== 'string' ) { - return false; - } - - // If the string starts with the negativeBefore value: remove it. - // Remember is was there, the number is negative. - if ( negativeBefore && strStartsWith(input, negativeBefore) ) { - input = input.replace(negativeBefore, ''); - inputIsNegative = true; - } - - // Repeat the same procedure for the prefix. - if ( prefix && strStartsWith(input, prefix) ) { - input = input.replace(prefix, ''); - } - - // And again for negative. - if ( negative && strStartsWith(input, negative) ) { - input = input.replace(negative, ''); - inputIsNegative = true; - } - - // Remove the postfix. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice - if ( postfix && strEndsWith(input, postfix) ) { - input = input.slice(0, -1 * postfix.length); - } - - // Remove the thousand grouping. - if ( thousand ) { - input = input.split(thousand).join(''); - } - - // Set the decimal separator back to period. - if ( mark ) { - input = input.replace(mark, '.'); - } - - // Prepend the negative symbol. - if ( inputIsNegative ) { - output += '-'; - } - - // Add the number - output += input; - - // Trim all non-numeric characters (allow '.' and '-'); - output = output.replace(/[^0-9\.\-.]/g, ''); - - // The value contains no parse-able number. - if ( output === '' ) { - return false; - } - - // Covert to number. - output = Number(output); - - // Run the user-specified post-decoder. - if ( decoder ) { - output = decoder(output); - } - - // Check is the output is valid, otherwise: return false. - if ( !isValidNumber(output) ) { - return false; - } - - return output; - } - - -// Framework - - // Validate formatting options - function validate ( inputOptions ) { - - var i, optionName, optionValue, - filteredOptions = {}; - - for ( i = 0; i < FormatOptions.length; i+=1 ) { - - optionName = FormatOptions[i]; - optionValue = inputOptions[optionName]; - - if ( optionValue === undefined ) { - - // Only default if negativeBefore isn't set. - if ( optionName === 'negative' && !filteredOptions.negativeBefore ) { - filteredOptions[optionName] = '-'; - // Don't set a default for mark when 'thousand' is set. - } else if ( optionName === 'mark' && filteredOptions.thousand !== '.' ) { - filteredOptions[optionName] = '.'; - } else { - filteredOptions[optionName] = false; - } - - // Floating points in JS are stable up to 7 decimals. - } else if ( optionName === 'decimals' ) { - if ( optionValue >= 0 && optionValue < 8 ) { - filteredOptions[optionName] = optionValue; - } else { - throw new Error(optionName); - } - - // These options, when provided, must be functions. - } else if ( optionName === 'encoder' || optionName === 'decoder' || optionName === 'edit' || optionName === 'undo' ) { - if ( typeof optionValue === 'function' ) { - filteredOptions[optionName] = optionValue; - } else { - throw new Error(optionName); - } - - // Other options are strings. - } else { - - if ( typeof optionValue === 'string' ) { - filteredOptions[optionName] = optionValue; - } else { - throw new Error(optionName); - } - } - } - - // Some values can't be extracted from a - // string if certain combinations are present. - throwEqualError(filteredOptions, 'mark', 'thousand'); - throwEqualError(filteredOptions, 'prefix', 'negative'); - throwEqualError(filteredOptions, 'prefix', 'negativeBefore'); - - return filteredOptions; - } - - // Pass all options as function arguments - function passAll ( options, method, input ) { - var i, args = []; - - // Add all options in order of FormatOptions - for ( i = 0; i < FormatOptions.length; i+=1 ) { - args.push(options[FormatOptions[i]]); - } - - // Append the input, then call the method, presenting all - // options as arguments. - args.push(input); - return method.apply('', args); - } - - /** @constructor */ - function wNumb ( options ) { - - if ( !(this instanceof wNumb) ) { - return new wNumb ( options ); - } - - if ( typeof options !== "object" ) { - return; - } - - options = validate(options); - - // Call 'formatTo' with proper arguments. - this.to = function ( input ) { - return passAll(options, formatTo, input); - }; - - // Call 'formatFrom' with proper arguments. - this.from = function ( input ) { - return passAll(options, formatFrom, input); - }; - } - - /** @export */ - window.wNumb = wNumb; - -}()); - -/*jslint browser: true */ -/*jslint white: true */ - -(function( $ ){ - - 'use strict'; - -// Helpers - - // Test in an object is an instance of jQuery or Zepto. - function isInstance ( a ) { - return a instanceof $ || ( $.zepto && $.zepto.isZ(a) ); - } - - -// Link types - - function fromPrefix ( target, method ) { - - // If target is a string, a new hidden input will be created. - if ( typeof target === 'string' && target.indexOf('-inline-') === 0 ) { - - // By default, use the 'html' method. - this.method = method || 'html'; - - // Use jQuery to create the element - this.target = this.el = $( target.replace('-inline-', '') || '
' ); - - return true; - } - } - - function fromString ( target ) { - - // If the string doesn't begin with '-', which is reserved, add a new hidden input. - if ( typeof target === 'string' && target.indexOf('-') !== 0 ) { - - this.method = 'val'; - - var element = document.createElement('input'); - element.name = target; - element.type = 'hidden'; - this.target = this.el = $(element); - - return true; - } - } - - function fromFunction ( target ) { - - // The target can also be a function, which will be called. - if ( typeof target === 'function' ) { - this.target = false; - this.method = target; - - return true; - } - } - - function fromInstance ( target, method ) { - - if ( isInstance( target ) && !method ) { - - // If a jQuery/Zepto input element is provided, but no method is set, - // the element can assume it needs to respond to 'change'... - if ( target.is('input, select, textarea') ) { - - // Default to .val if this is an input element. - this.method = 'val'; - - // Fire the API changehandler when the target changes. - this.target = target.on('change.liblink', this.changeHandler); - - } else { - - this.target = target; - - // If no method is set, and we are not auto-binding an input, default to 'html'. - this.method = 'html'; - } - - return true; - } - } - - function fromInstanceMethod ( target, method ) { - - // The method must exist on the element. - if ( isInstance( target ) && - (typeof method === 'function' || - (typeof method === 'string' && target[method])) - ) { - this.method = method; - this.target = target; - - return true; - } - } - -var -/** @const */ - creationFunctions = [fromPrefix, fromString, fromFunction, fromInstance, fromInstanceMethod]; - - -// Link Instance - -/** @constructor */ - function Link ( target, method, format ) { - - var that = this, valid = false; - - // Forward calls within scope. - this.changeHandler = function ( changeEvent ) { - var decodedValue = that.formatInstance.from( $(this).val() ); - - // If the value is invalid, stop this event, as well as it's propagation. - if ( decodedValue === false || isNaN(decodedValue) ) { - - // Reset the value. - $(this).val(that.lastSetValue); - return false; - } - - that.changeHandlerMethod.call( '', changeEvent, decodedValue ); - }; - - // See if this Link needs individual targets based on its usage. - // If so, return the element that needs to be copied by the - // implementing interface. - // Default the element to false. - this.el = false; - - // Store the formatter, or use the default. - this.formatInstance = format; - - // Try all Link types. - /*jslint unparam: true*/ - $.each(creationFunctions, function(i, fn){ - valid = fn.call(that, target, method); - return !valid; - }); - /*jslint unparam: false*/ - - // Nothing matched, throw error. - if ( !valid ) { - throw new RangeError("(Link) Invalid Link."); - } - } - - // Provides external items with the object value. - Link.prototype.set = function ( value ) { - - // Ignore the value, so only the passed-on arguments remain. - var args = Array.prototype.slice.call( arguments ), - additionalArgs = args.slice(1); - - // Store some values. The actual, numerical value, - // the formatted value and the parameters for use in 'resetValue'. - // Slice additionalArgs to break the relation. - this.lastSetValue = this.formatInstance.to( value ); - - // Prepend the value to the function arguments. - additionalArgs.unshift( - this.lastSetValue - ); - - // When target is undefined, the target was a function. - // In that case, provided the object as the calling scope. - // Branch between writing to a function or an object. - ( typeof this.method === 'function' ? - this.method : - this.target[ this.method ] ).apply( this.target, additionalArgs ); - }; - - -// Developer API - -/** @constructor */ - function LinkAPI ( origin ) { - this.items = []; - this.elements = []; - this.origin = origin; - } - - LinkAPI.prototype.push = function( item, element ) { - this.items.push(item); - - // Prevent 'false' elements - if ( element ) { - this.elements.push(element); - } - }; - - LinkAPI.prototype.reconfirm = function ( flag ) { - var i; - for ( i = 0; i < this.elements.length; i += 1 ) { - this.origin.LinkConfirm(flag, this.elements[i]); - } - }; - - LinkAPI.prototype.remove = function ( flag ) { - var i; - for ( i = 0; i < this.items.length; i += 1 ) { - this.items[i].target.off('.liblink'); - } - for ( i = 0; i < this.elements.length; i += 1 ) { - this.elements[i].remove(); - } - }; - - LinkAPI.prototype.change = function ( value ) { - - if ( this.origin.LinkIsEmitting ) { - return false; - } - - this.origin.LinkIsEmitting = true; - - var args = Array.prototype.slice.call( arguments, 1 ), i; - args.unshift( value ); - - // Write values to serialization Links. - // Convert the value to the correct relative representation. - for ( i = 0; i < this.items.length; i += 1 ) { - this.items[i].set.apply(this.items[i], args); - } - - this.origin.LinkIsEmitting = false; - }; - - -// jQuery plugin - - function binder ( flag, target, method, format ){ - - if ( flag === 0 ) { - flag = this.LinkDefaultFlag; - } - - // Create a list of API's (if it didn't exist yet); - if ( !this.linkAPI ) { - this.linkAPI = {}; - } - - // Add an API point. - if ( !this.linkAPI[flag] ) { - this.linkAPI[flag] = new LinkAPI(this); - } - - var linkInstance = new Link ( target, method, format || this.LinkDefaultFormatter ); - - // Default the calling scope to the linked object. - if ( !linkInstance.target ) { - linkInstance.target = $(this); - } - - // If the Link requires creation of a new element, - // Pass the element and request confirmation to get the changehandler. - // Set the method to be called when a Link changes. - linkInstance.changeHandlerMethod = this.LinkConfirm( flag, linkInstance.el ); - - // Store the linkInstance in the flagged list. - this.linkAPI[flag].push( linkInstance, linkInstance.el ); - - // Now that Link have been connected, request an update. - this.LinkUpdate( flag ); - } - - /** @export */ - $.fn.Link = function( flag ){ - - var that = this; - - // Delete all linkAPI - if ( flag === false ) { - - return that.each(function(){ - - // .Link(false) can be called on elements without Links. - // When that happens, the objects can't be looped. - if ( !this.linkAPI ) { - return; - } - - $.map(this.linkAPI, function(api){ - api.remove(); - }); - - delete this.linkAPI; - }); - } - - if ( flag === undefined ) { - - flag = 0; - - } else if ( typeof flag !== 'string') { - - throw new Error("Flag must be string."); - } - - return { - to: function( a, b, c ){ - return that.each(function(){ - binder.call(this, flag, a, b, c); - }); - } - }; - }; - -}( window.jQuery || window.Zepto )); - -/*jslint browser: true */ -/*jslint white: true */ - -(function( $ ){ - - 'use strict'; - - - // Removes duplicates from an array. - function unique(array) { - return $.grep(array, function(el, index) { - return index === $.inArray(el, array); - }); - } - - // Round a value to the closest 'to'. - function closest ( value, to ) { - return Math.round(value / to) * to; - } - - // Checks whether a value is numerical. - function isNumeric ( a ) { - return typeof a === 'number' && !isNaN( a ) && isFinite( a ); - } - - // Rounds a number to 7 supported decimals. - function accurateNumber( number ) { - var p = Math.pow(10, 7); - return Number((Math.round(number*p)/p).toFixed(7)); - } - - // Sets a class and removes it after [duration] ms. - function addClassFor ( element, className, duration ) { - element.addClass(className); - setTimeout(function(){ - element.removeClass(className); - }, duration); - } - - // Limits a value to 0 - 100 - function limit ( a ) { - return Math.max(Math.min(a, 100), 0); - } - - // Wraps a variable as an array, if it isn't one yet. - function asArray ( a ) { - return $.isArray(a) ? a : [a]; - } - - // Counts decimals - function countDecimals ( numStr ) { - var pieces = numStr.split("."); - return pieces.length > 1 ? pieces[1].length : 0; - } - - - var - // Cache the document selector; - /** @const */ - doc = $(document), - // Make a backup of the original jQuery/Zepto .val() method. - /** @const */ - $val = $.fn.val, - // Namespace for binding and unbinding slider events; - /** @const */ - namespace = '.nui', - // Determine the events to bind. IE11 implements pointerEvents without - // a prefix, which breaks compatibility with the IE10 implementation. - /** @const */ - 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' - }, - // Re-usable list of classes; - /** @const */ - Classes = [ -/* 0 */ 'noUi-target' -/* 1 */ ,'noUi-base' -/* 2 */ ,'noUi-origin' -/* 3 */ ,'noUi-handle' -/* 4 */ ,'noUi-horizontal' -/* 5 */ ,'noUi-vertical' -/* 6 */ ,'noUi-background' -/* 7 */ ,'noUi-connect' -/* 8 */ ,'noUi-ltr' -/* 9 */ ,'noUi-rtl' -/* 10 */ ,'noUi-dragable' -/* 11 */ ,'' -/* 12 */ ,'noUi-state-drag' -/* 13 */ ,'' -/* 14 */ ,'noUi-state-tap' -/* 15 */ ,'noUi-active' -/* 16 */ ,'' -/* 17 */ ,'noUi-stacking' - ]; - - -// Value calculation - - // Determine the size of a sub-range in relation to a full range. - function subRangeRatio ( pa, pb ) { - return (100 / (pb - pa)); - } - - // (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]; - } - - -// Range conversion - - function getJ ( value, arr ) { - - var j = 1; - - while ( value >= arr[j] ){ - j += 1; - } - - return j; - } - - // (percentage) Input a value, find where, on a scale of 0-100, it applies. - function toStepping ( xVal, xPct, value ) { - - if ( value >= xVal.slice(-1)[0] ){ - return 100; - } - - var j = getJ( value, xVal ), va, vb, pa, pb; - - va = xVal[j-1]; - vb = xVal[j]; - pa = xPct[j-1]; - pb = xPct[j]; - - return pa + (toPercentage([va, vb], value) / subRangeRatio (pa, pb)); - } - - // (value) Input a percentage, find where it is on the specified range. - function fromStepping ( xVal, xPct, value ) { - - // There is no range group that fits 100 - if ( value >= 100 ){ - return xVal.slice(-1)[0]; - } - - var j = getJ( value, xPct ), va, vb, pa, pb; - - va = xVal[j-1]; - vb = xVal[j]; - pa = xPct[j-1]; - pb = xPct[j]; - - return isPercentage([va, vb], (value - pa) * subRangeRatio (pa, pb)); - } - - // (percentage) Get the step that applies at a certain value. - function getStep ( xPct, xSteps, snap, value ) { - - if ( value === 100 ) { - return value; - } - - var j = getJ( value, xPct ), a, b; - - // If 'snap' is set, steps are used as fixed points on the slider. - if ( snap ) { - - a = xPct[j-1]; - b = xPct[j]; - - // Find the closest position, a or b. - if ((value - a) > ((b-a)/2)){ - return b; - } - - return a; - } - - if ( !xSteps[j-1] ){ - return value; - } - - return xPct[j-1] + closest( - value - xPct[j-1], - xSteps[j-1] - ); - } - - -// Entry parsing - - function handleEntryPoint ( index, value, that ) { - - var percentage; - - // Wrap numerical input in an array. - if ( typeof value === "number" ) { - value = [value]; - } - - // Reject any invalid input, by testing whether value is an array. - if ( Object.prototype.toString.call( value ) !== '[object Array]' ){ - throw new Error("noUiSlider: 'range' contains invalid value."); - } - - // Covert min/max syntax to 0 and 100. - if ( index === 'min' ) { - percentage = 0; - } else if ( index === 'max' ) { - percentage = 100; - } else { - percentage = parseFloat( index ); - } - - // Check for correct input. - if ( !isNumeric( percentage ) || !isNumeric( value[0] ) ) { - throw new Error("noUiSlider: 'range' value isn't numeric."); - } - - // Store values. - that.xPct.push( percentage ); - that.xVal.push( value[0] ); - - // NaN will evaluate to false too, but to keep - // logging clear, set step explicitly. Make sure - // not to override the 'step' setting with false. - if ( !percentage ) { - if ( !isNaN( value[1] ) ) { - that.xSteps[0] = value[1]; - } - } else { - that.xSteps.push( isNaN(value[1]) ? false : value[1] ); - } - } - - function handleStepPoint ( i, n, that ) { - - // Ignore 'false' stepping. - if ( !n ) { - return true; - } - - // Factor to range ratio - that.xSteps[i] = fromPercentage([ - that.xVal[i] - ,that.xVal[i+1] - ], n) / subRangeRatio ( - that.xPct[i], - that.xPct[i+1] ); - } - - -// Interface - - // The interface to Spectrum handles all direction-based - // conversions, so the above values are unaware. - - function Spectrum ( entry, snap, direction, singleStep ) { - - this.xPct = []; - this.xVal = []; - this.xSteps = [ singleStep || false ]; - this.xNumSteps = [ false ]; - - this.snap = snap; - this.direction = direction; - - var index, ordered = [ /* [0, 'min'], [1, '50%'], [2, 'max'] */ ]; - - // Map the object keys to an array. - for ( index in entry ) { - if ( entry.hasOwnProperty(index) ) { - ordered.push([entry[index], index]); - } - } - - // Sort all entries by value (numeric sort). - ordered.sort(function(a, b) { return a[0] - b[0]; }); - - // Convert all entries to subranges. - for ( index = 0; index < ordered.length; index++ ) { - handleEntryPoint(ordered[index][1], ordered[index][0], this); - } - - // Store the actual step values. - // xSteps is sorted in the same order as xPct and xVal. - this.xNumSteps = this.xSteps.slice(0); - - // Convert all numeric steps to the percentage of the subrange they represent. - for ( index = 0; index < this.xNumSteps.length; index++ ) { - handleStepPoint(index, this.xNumSteps[index], this); - } - } - - Spectrum.prototype.getMargin = function ( value ) { - return this.xPct.length === 2 ? fromPercentage(this.xVal, value) : false; - }; - - Spectrum.prototype.toStepping = function ( value ) { - - value = toStepping( this.xVal, this.xPct, value ); - - // Invert the value if this is a right-to-left slider. - if ( this.direction ) { - value = 100 - value; - } - - return value; - }; - - Spectrum.prototype.fromStepping = function ( value ) { - - // Invert the value if this is a right-to-left slider. - if ( this.direction ) { - value = 100 - value; - } - - return accurateNumber(fromStepping( this.xVal, this.xPct, value )); - }; - - Spectrum.prototype.getStep = function ( value ) { - - // Find the proper step for rtl sliders by search in inverse direction. - // Fixes issue #262. - if ( this.direction ) { - value = 100 - value; - } - - value = getStep(this.xPct, this.xSteps, this.snap, value ); - - if ( this.direction ) { - value = 100 - value; - } - - return value; - }; - - Spectrum.prototype.getApplicableStep = function ( value ) { - - // If the value is 100%, return the negative step twice. - var j = getJ(value, this.xPct), offset = value === 100 ? 2 : 1; - return [this.xNumSteps[j-2], this.xVal[j-offset], this.xNumSteps[j-offset]]; - }; - - // Outside testing - Spectrum.prototype.convert = function ( value ) { - return this.getStep(this.toStepping(value)); - }; - -/* 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. */ - - /** @const */ - var defaultFormatter = { 'to': function( value ){ - return value.toFixed(2); - }, 'from': Number }; - - function testStep ( parsed, entry ) { - - if ( !isNumeric( entry ) ) { - throw new Error("noUiSlider: 'step' is not numeric."); - } - - // The step option can still be used to set stepping - // for linear sliders. Overwritten if set in 'range'. - parsed.singleStep = entry; - } - - function testRange ( parsed, entry ) { - - // Filter incorrect input. - if ( typeof entry !== 'object' || $.isArray(entry) ) { - throw new Error("noUiSlider: 'range' is not an object."); - } - - // Catch missing start or end. - if ( entry.min === undefined || entry.max === undefined ) { - throw new Error("noUiSlider: Missing 'min' or 'max' in 'range'."); - } - - parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.dir, parsed.singleStep); - } - - function testStart ( parsed, entry ) { - - entry = asArray(entry); - - // Validate input. Values aren't tested, as the public .val method - // will always provide a valid location. - if ( !$.isArray( entry ) || !entry.length || entry.length > 2 ) { - throw new Error("noUiSlider: 'start' option is incorrect."); - } - - // Store the number of handles. - parsed.handles = entry.length; - - // When the slider is initialized, the .val method will - // be called with the start options. - parsed.start = entry; - } - - function testSnap ( parsed, entry ) { - - // Enforce 100% stepping within subranges. - parsed.snap = entry; - - if ( typeof entry !== 'boolean' ){ - throw new Error("noUiSlider: 'snap' option must be a boolean."); - } - } - - function testAnimate ( parsed, entry ) { - - // Enforce 100% stepping within subranges. - parsed.animate = entry; - - if ( typeof entry !== 'boolean' ){ - throw new Error("noUiSlider: 'animate' option must be a boolean."); - } - } - - function testConnect ( parsed, entry ) { - - if ( entry === 'lower' && parsed.handles === 1 ) { - parsed.connect = 1; - } else if ( entry === 'upper' && parsed.handles === 1 ) { - parsed.connect = 2; - } else if ( entry === true && parsed.handles === 2 ) { - parsed.connect = 3; - } else if ( entry === false ) { - parsed.connect = 0; - } else { - throw new Error("noUiSlider: 'connect' option doesn't match handle count."); - } - } - - function testOrientation ( parsed, entry ) { - - // Set orientation to an a numerical value for easy - // array selection. - switch ( entry ){ - case 'horizontal': - parsed.ort = 0; - break; - case 'vertical': - parsed.ort = 1; - break; - default: - throw new Error("noUiSlider: 'orientation' option is invalid."); - } - } - - function testMargin ( parsed, entry ) { - - if ( !isNumeric(entry) ){ - throw new Error("noUiSlider: 'margin' option must be numeric."); - } - - parsed.margin = parsed.spectrum.getMargin(entry); - - if ( !parsed.margin ) { - throw new Error("noUiSlider: 'margin' option is only supported on linear sliders."); - } - } - - function testLimit ( parsed, entry ) { - - if ( !isNumeric(entry) ){ - throw new Error("noUiSlider: 'limit' option must be numeric."); - } - - parsed.limit = parsed.spectrum.getMargin(entry); - - if ( !parsed.limit ) { - throw new Error("noUiSlider: 'limit' option is only supported on linear sliders."); - } - } - - function testDirection ( parsed, entry ) { - - // Set direction as a numerical value for easy parsing. - // Invert connection for RTL sliders, so that the proper - // handles get the connect/background classes. - switch ( entry ) { - case 'ltr': - parsed.dir = 0; - break; - case 'rtl': - parsed.dir = 1; - parsed.connect = [0,2,1,3][parsed.connect]; - break; - default: - throw new Error("noUiSlider: 'direction' option was not recognized."); - } - } - - function testBehaviour ( parsed, entry ) { - - // Make sure the input is a string. - if ( typeof entry !== 'string' ) { - throw new Error("noUiSlider: 'behaviour' must be a string containing options."); - } - - // Check if the string contains any keywords. - // None are required. - var tap = entry.indexOf('tap') >= 0, - drag = entry.indexOf('drag') >= 0, - fixed = entry.indexOf('fixed') >= 0, - snap = entry.indexOf('snap') >= 0; - - parsed.events = { - tap: tap || snap, - drag: drag, - fixed: fixed, - snap: snap - }; - } - - function testFormat ( parsed, entry ) { - - parsed.format = entry; - - // Any object with a to and from method is supported. - if ( typeof entry.to === 'function' && typeof entry.from === 'function' ) { - return true; - } - - throw new Error( "noUiSlider: 'format' requires 'to' and 'from' methods."); - } - - // Test all developer settings and parse to assumption-safe values. - function testOptions ( options ) { - - var parsed = { - margin: 0, - limit: 0, - animate: true, - format: defaultFormatter - }, tests; - - // Tests are executed in the order they are presented here. - tests = { - 'step': { r: false, t: testStep }, - 'start': { r: true, t: testStart }, - 'connect': { r: true, t: testConnect }, - 'direction': { r: true, t: testDirection }, - 'snap': { r: false, t: testSnap }, - 'animate': { r: false, t: testAnimate }, - 'range': { r: true, t: testRange }, - 'orientation': { r: false, t: testOrientation }, - 'margin': { r: false, t: testMargin }, - 'limit': { r: false, t: testLimit }, - 'behaviour': { r: true, t: testBehaviour }, - 'format': { r: false, t: testFormat } - }; - - // Set defaults where applicable. - options = $.extend({ - 'connect': false, - 'direction': 'ltr', - 'behaviour': 'tap', - 'orientation': 'horizontal' - }, options); - - // Run all options through a testing mechanism to ensure correct - // input. It should be noted that options might get modified to - // be handled properly. E.g. wrapping integers in arrays. - $.each( tests, function( name, test ){ - - // If the option isn't set, but it is required, throw an error. - if ( options[name] === undefined ) { - - if ( test.r ) { - throw new Error("noUiSlider: '" + name + "' is required."); - } - - return true; - } - - test.t( parsed, options[name] ); - }); - - // Pre-define the styles. - parsed.style = parsed.ort ? 'top' : 'left'; - - return parsed; - } - -// Class handling - - // Delimit proposed values for handle positions. - function getPositions ( a, b, delimit ) { - - // Add movement to current position. - var c = a + b[0], d = a + b[1]; - - // Only alter the other position on drag, - // not on standard sliding. - if ( delimit ) { - if ( c < 0 ) { - d += Math.abs(c); - } - if ( d > 100 ) { - c -= ( d - 100 ); - } - - // Limit values to 0 and 100. - return [limit(c), limit(d)]; - } - - return [c,d]; - } - - -// Event handling - - // 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; - } - - event.points = [x, y]; - event.cursor = mouse; - - return event; - } - - -// DOM additions - - // Append a handle to the base. - function addHandle ( direction, index ) { - - var handle = $('
').addClass( Classes[2] ), - additions = [ '-lower', '-upper' ]; - - if ( direction ) { - additions.reverse(); - } - - handle.children().addClass( - Classes[3] + " " + Classes[3]+additions[index] - ); - - return handle; - } - - // Add the proper connection classes. - function addConnection ( connect, target, handles ) { - - // 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 ( connect ) { - case 1: target.addClass( Classes[7] ); - handles[0].addClass( Classes[6] ); - break; - case 3: handles[1].addClass( Classes[6] ); - /* falls through */ - case 2: handles[0].addClass( Classes[7] ); - /* falls through */ - case 0: target.addClass(Classes[6]); - break; - } - } - - // Add handles to the slider base. - function addHandles ( nrHandles, direction, base ) { - - var index, handles = []; - - // Append handles. - for ( index = 0; index < nrHandles; index += 1 ) { - - // Keep a list of all added handles. - handles.push( addHandle( direction, index ).appendTo(base) ); - } - - return handles; - } - - // Initialize a single slider. - function addSlider ( direction, orientation, target ) { - - // Apply classes and data to the target. - target.addClass([ - Classes[0], - Classes[8 + direction], - Classes[4 + orientation] - ].join(' ')); - - return $('
').appendTo(target).addClass( Classes[1] ); - } - -function closure ( target, options, originalOptions ){ - -// Internal variables - - // All variables local to 'closure' are marked $. - var $Target = $(target), - $Locations = [-1, -1], - $Base, - $Handles, - $Spectrum = options.spectrum, - $Values = [], - // libLink. For rtl sliders, 'lower' and 'upper' should not be inverted - // for one-handle sliders, so trim 'upper' it that case. - triggerPos = ['lower', 'upper'].slice(0, options.handles); - - // Invert the libLink connection for rtl sliders. - if ( options.dir ) { - triggerPos.reverse(); - } - -// Helpers - - // Shorthand for base dimensions. - function baseSize ( ) { - return $Base[['width', 'height'][options.ort]](); - } - - // External event handling - function fireEvents ( events ) { - - // Use the external api to get the values. - // Wrap the values in an array, as .trigger takes - // only one additional argument. - var index, values = [ $Target.val() ]; - - for ( index = 0; index < events.length; index += 1 ){ - $Target.trigger(events[index], values); - } - } - - // Returns the input array, respecting the slider direction configuration. - function inSliderOrder ( values ) { - - // If only one handle is used, return a single value. - if ( values.length === 1 ){ - return values[0]; - } - - if ( options.dir ) { - return values.reverse(); - } - - return values; - } - -// libLink integration - - // Create a new function which calls .val on input change. - function createChangeHandler ( trigger ) { - return function ( ignore, value ){ - // Determine which array position to 'null' based on 'trigger'. - $Target.val( [ trigger ? null : value, trigger ? value : null ], true ); - }; - } - - // Called by libLink when it wants a set of links updated. - function linkUpdate ( flag ) { - - var trigger = $.inArray(flag, triggerPos); - - // The API might not have been set yet. - if ( $Target[0].linkAPI && $Target[0].linkAPI[flag] ) { - $Target[0].linkAPI[flag].change( - $Values[trigger], - $Handles[trigger].children(), - $Target - ); - } - } - - // Called by libLink to append an element to the slider. - function linkConfirm ( flag, element ) { - - // Find the trigger for the passed flag. - var trigger = $.inArray(flag, triggerPos); - - // If set, append the element to the handle it belongs to. - if ( element ) { - element.appendTo( $Handles[trigger].children() ); - } - - // The public API is reversed for rtl sliders, so the changeHandler - // should not be aware of the inverted trigger positions. - // On rtl slider with one handle, 'lower' should be used. - if ( options.dir && options.handles > 1 ) { - trigger = trigger === 1 ? 0 : 1; - } - - return createChangeHandler( trigger ); - } - - // Place elements back on the slider. - function reAppendLink ( ) { - - var i, flag; - - // The API keeps a list of elements: we can re-append them on rebuild. - for ( i = 0; i < triggerPos.length; i += 1 ) { - if ( this.linkAPI && this.linkAPI[(flag = triggerPos[i])] ) { - this.linkAPI[flag].reconfirm(flag); - } - } - } - - target.LinkUpdate = linkUpdate; - target.LinkConfirm = linkConfirm; - target.LinkDefaultFormatter = options.format; - target.LinkDefaultFlag = 'lower'; - - target.reappend = reAppendLink; - - - // Handler for attaching events trough a proxy. - function attach ( events, element, callback, data ) { - - // This function can be used to 'filter' events to the slider. - - // 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 (1) handle unset attributes differently, - // but always falsy; #208 - if ( !!$Target.attr('disabled') ) { - return false; - } - - // Stop if an active 'tap' transition is taking place. - if ( $Target.hasClass( Classes[14] ) ) { - return false; - } - - e = fixEvent(e); - e.calcPoint = e.points[ options.ort ]; - - // Call the event handler with the event [ and additional data ]. - callback ( e, data ); - }); - } - - // Handle movement on document for handle and range drag. - function move ( event, data ) { - - var handles = data.handles || $Handles, positions, state = false, - proposal = ((event.calcPoint - data.start) * 100) / baseSize(), - h = handles[0][0] !== $Handles[0][0] ? 1 : 0; - - // Calculate relative positions for the handles. - positions = getPositions( proposal, data.positions, handles.length > 1); - - state = setHandle ( handles[0], positions[h], handles.length === 1 ); - - if ( handles.length > 1 ) { - state = setHandle ( handles[1], positions[h?0:1], false ) || state; - } - - // Fire the 'slide' event if any handle moved. - if ( state ) { - fireEvents(['slide']); - } - } - - // Unbind move events on document, call callbacks. - function end ( event ) { - - // The handle is no longer active, so remove the class. - $('.' + Classes[15]).removeClass(Classes[15]); - - // 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 ); - - // Remove dragging class. - $Target.removeClass(Classes[12]); - - // Fire the change and set events. - fireEvents(['set', 'change']); - } - - // Bind move events on document. - function start ( event, data ) { - - // Mark the handle as 'active' so it can be styled. - if( data.handles.length === 1 ) { - data.handles[0].children().addClass(Classes[15]); - } - - // A drag should never propagate up to the 'tap' event. - event.stopPropagation(); - - // Attach the move event. - attach ( actions.move, doc, move, { - start: event.calcPoint, - handles: data.handles, - positions: [ - $Locations[0], - $Locations[$Handles.length - 1] - ] - }); - - // Unbind all movement when the drag ends. - attach ( actions.end, doc, end, null ); - - // Text selection isn't an issue on touch devices, - // so adding cursor styles can be skipped. - 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 ( $Handles.length > 1 ) { - $Target.addClass(Classes[12]); - } - - // Prevent text selection when dragging the handles. - $('body').on('selectstart' + namespace, false); - } - } - - // Move closest handle to tapped location. - function tap ( event ) { - - var location = event.calcPoint, total = 0, to; - - // The tap event shouldn't propagate up and cause 'edge' to run. - event.stopPropagation(); - - // Add up the handle offsets. - $.each( $Handles, function(){ - total += this.offset()[ options.style ]; - }); - - // Find the handle closest to the tapped position. - total = ( location < total/2 || $Handles.length === 1 ) ? 0 : 1; - - location -= $Base.offset()[ options.style ]; - - // Calculate the new position. - to = ( location * 100 ) / baseSize(); - - if ( !options.events.snap ) { - // Flag the slider as it is now in a transitional state. - // Transition takes 300 ms, so re-enable the slider afterwards. - addClassFor( $Target, Classes[14], 300 ); - } - - // Find the closest handle and calculate the tapped point. - // The set handle to the new position. - setHandle( $Handles[total], to ); - - fireEvents(['slide', 'set', 'change']); - - if ( options.events.snap ) { - start(event, { handles: [$Handles[total]] }); - } - } - - // Attach events to several slider parts. - function events ( behaviour ) { - - var i, drag; - - // Attach the standard drag event to the handles. - if ( !behaviour.fixed ) { - - for ( i = 0; i < $Handles.length; i += 1 ) { - - // These events are only bound to the visual handle - // element, not the 'real' origin element. - attach ( actions.start, $Handles[i].children(), start, { - handles: [ $Handles[i] ] - }); - } - } - - // Attach the tap event to the slider base. - if ( behaviour.tap ) { - - attach ( actions.start, $Base, tap, { - handles: $Handles - }); - } - - // Make the range dragable. - if ( behaviour.drag ){ - - drag = $Base.find( '.' + Classes[7] ).addClass( Classes[10] ); - - // 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 ( behaviour.fixed ) { - drag = drag.add($Base.children().not( drag ).children()); - } - - attach ( actions.start, drag, start, { - handles: $Handles - }); - } - } - - - // Test suggested values and apply margin, step. - function setHandle ( handle, to, noLimitOption ) { - - var trigger = handle[0] !== $Handles[0][0] ? 1 : 0, - lowerMargin = $Locations[0] + options.margin, - upperMargin = $Locations[1] - options.margin, - lowerLimit = $Locations[0] + options.limit, - upperLimit = $Locations[1] - options.limit; - - // For sliders with multiple handles, - // limit movement to the other handle. - // Apply the margin option by adding it to the handle positions. - if ( $Handles.length > 1 ) { - to = trigger ? Math.max( to, lowerMargin ) : Math.min( to, upperMargin ); - } - - // The limit option has the opposite effect, limiting handles to a - // maximum distance from another. Limit must be > 0, as otherwise - // handles would be unmoveable. 'noLimitOption' is set to 'false' - // for the .val() method, except for pass 4/4. - if ( noLimitOption !== false && options.limit && $Handles.length > 1 ) { - to = trigger ? Math.min ( to, lowerLimit ) : Math.max( to, upperLimit ); - } - - // Handle the step option. - to = $Spectrum.getStep( to ); - - // Limit to 0/100 for .val input, trim anything beyond 7 digits, as - // JavaScript has some issues in its floating point implementation. - to = limit(parseFloat(to.toFixed(7))); - - // Return false if handle can't move. - if ( to === $Locations[trigger] ) { - return false; - } - - // Set the handle to the new position. - handle.css( options.style, to + '%' ); - - // Force proper handle stacking - if ( handle.is(':first-child') ) { - handle.toggleClass(Classes[17], to > 50 ); - } - - // Update locations. - $Locations[trigger] = to; - - // Convert the value to the slider stepping/range. - $Values[trigger] = $Spectrum.fromStepping( to ); - - linkUpdate(triggerPos[trigger]); - - return true; - } - - // Loop values from value method and apply them. - function setValues ( count, values ) { - - var i, trigger, to; - - // With the limit option, we'll need another limiting pass. - if ( options.limit ) { - count += 1; - } - - // 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. - for ( i = 0; i < count; i += 1 ) { - - trigger = i%2; - - // Get the current argument from the array. - to = values[trigger]; - - // Setting with null indicates an 'ignore'. - // Inputting 'false' is invalid. - if ( to !== null && to !== false ) { - - // If a formatted number was passed, attemt to decode it. - if ( typeof to === 'number' ) { - to = String(to); - } - - to = options.format.from( to ); - - // Request an update for all links if the value was invalid. - // Do so too if setting the handle fails. - if ( to === false || isNaN(to) || setHandle( $Handles[trigger], $Spectrum.toStepping( to ), i === (3 - options.dir) ) === false ) { - - linkUpdate(triggerPos[trigger]); - } - } - } - } - - // Set the slider value. - function valueSet ( input ) { - - // LibLink: don't accept new values when currently emitting changes. - if ( $Target[0].LinkIsEmitting ) { - return this; - } - - var count, values = asArray( input ); - - // The RTL settings is implemented by reversing the front-end, - // internal mechanisms are the same. - if ( options.dir && options.handles > 1 ) { - values.reverse(); - } - - // Animation is optional. - // Make sure the initial values where set before using animated - // placement. (no report, unit testing); - if ( options.animate && $Locations[0] !== -1 ) { - addClassFor( $Target, Classes[14], 300 ); - } - - // Determine how often to set the handles. - count = $Handles.length > 1 ? 3 : 1; - - if ( values.length === 1 ) { - count = 1; - } - - setValues ( count, values ); - - // Fire the 'set' event. As of noUiSlider 7, - // this is no longer optional. - fireEvents(['set']); - - return this; - } - - // Get the slider value. - function valueGet ( ) { - - var i, retour = []; - - // Get the value from all handles. - for ( i = 0; i < options.handles; i += 1 ){ - retour[i] = options.format.to( $Values[i] ); - } - - return inSliderOrder( retour ); - } - - // Destroy the slider and unbind all events. - function destroyTarget ( ) { - - // Unbind events on the slider, remove all classes and child elements. - $(this).off(namespace) - .removeClass(Classes.join(' ')) - .empty(); - - delete this.LinkUpdate; - delete this.LinkConfirm; - delete this.LinkDefaultFormatter; - delete this.LinkDefaultFlag; - delete this.reappend; - delete this.vGet; - delete this.vSet; - delete this.getCurrentStep; - delete this.getInfo; - delete this.destroy; - - // Return the original options from the closure. - return originalOptions; - } - - // Get the current step size for the slider. - function getCurrentStep ( ) { - - // Check all locations, map them to their stepping point. - // Get the step point, then find it in the input list. - var retour = $.map($Locations, function( location, index ){ - - var step = $Spectrum.getApplicableStep( location ), - - // As per #391, the comparison for the decrement step can have some rounding issues. - // Round the value to the precision used in the step. - stepDecimals = countDecimals(String(step[2])), - - // Get the current numeric value - value = $Values[index], - - // To move the slider 'one step up', the current step value needs to be added. - // Use null if we are at the maximum slider value. - increment = location === 100 ? null : step[2], - - // Going 'one step down' might put the slider in a different sub-range, so we - // need to switch between the current or the previous step. - prev = Number((value - step[2]).toFixed(stepDecimals)), - - // If the value fits the step, return the current step value. Otherwise, use the - // previous step. Return null if the slider is at its minimum value. - decrement = location === 0 ? null : (prev >= step[1]) ? step[2] : (step[0] || false); - - return [[decrement, increment]]; - }); - - // Return values in the proper order. - return inSliderOrder( retour ); - } - - // Get the original set of options. - function getOriginalOptions ( ) { - return originalOptions; - } - - -// Initialize slider - - // Throw an error if the slider was already initialized. - if ( $Target.hasClass(Classes[0]) ) { - throw new Error('Slider was already initialized.'); - } - - // Create the base element, initialise HTML and set classes. - // Add handles and links. - $Base = addSlider( options.dir, options.ort, $Target ); - $Handles = addHandles( options.handles, options.dir, $Base ); - - // Set the connect classes. - addConnection ( options.connect, $Target, $Handles ); - - // Attach user events. - events( options.events ); - -// Methods - - target.vSet = valueSet; - target.vGet = valueGet; - target.destroy = destroyTarget; - - target.getCurrentStep = getCurrentStep; - target.getOriginalOptions = getOriginalOptions; - - target.getInfo = function(){ - return [ - $Spectrum, - options.style, - options.ort - ]; - }; - - // Use the public value method to set the start values. - $Target.val( options.start ); - -} - - - // Run the standard initializer - function initialize ( originalOptions ) { - - // Test the options once, not for every slider. - var options = testOptions( originalOptions, this ); - - // Loop all items, and provide a new closed-scope environment. - return this.each(function(){ - closure(this, options, originalOptions); - }); - } - - // Destroy the slider, then re-enter initialization. - function rebuild ( options ) { - - return this.each(function(){ - - // The rebuild flag can be used if the slider wasn't initialized yet. - if ( !this.destroy ) { - $(this).noUiSlider( options ); - return; - } - - // Get the current values from the slider, - // including the initialization options. - var values = $(this).val(), originalOptions = this.destroy(), - - // Extend the previous options with the newly provided ones. - newOptions = $.extend( {}, originalOptions, options ); - - // Run the standard initializer. - $(this).noUiSlider( newOptions ); - - // Place Link elements back. - this.reappend(); - - // If the start option hasn't changed, - // reset the previous values. - if ( originalOptions.start === newOptions.start ) { - $(this).val(values); - } - }); - } - - // Access the internal getting and setting methods based on argument count. - function value ( ) { - return this[0][ !arguments.length ? 'vGet' : 'vSet' ].apply(this[0], arguments); - } - - // Override the .val() method. Test every element. Is it a slider? Go to - // the slider value handling. No? Use the standard method. - // Note how $.fn.val expects 'this' to be an instance of $. For convenience, - // the above 'value' function does too. - $.fn.val = function ( arg ) { - - // this === instanceof $ - - function valMethod( a ){ - return a.hasClass(Classes[0]) ? value : $val; - } - - // If no value is passed, this is 'get'. - if ( !arguments.length ) { - var first = $(this[0]); - return valMethod(first).call(first); - } - - var isFunction = $.isFunction(arg); - - // Return the set so it remains chainable. Make sure not to break - // jQuery's .val(function( index, value ){}) signature. - return this.each(function( i ){ - - var val = arg, $t = $(this); - - if ( isFunction ) { - val = arg.call(this, i, $t.val()); - } - - valMethod($t).call($t, val); - }); - }; - -// Extend jQuery/Zepto with the noUiSlider method. - $.fn.noUiSlider = function ( options, rebuildFlag ) { - - switch ( options ) { - case 'step': return this[0].getCurrentStep(); - case 'options': return this[0].getOriginalOptions(); - } - - return ( rebuildFlag ? rebuild : initialize ).call(this, options); - }; - - function getGroup ( $Spectrum, mode, values, stepped ) { - - // Use the range. - if ( mode === 'range' || mode === 'steps' ) { - return $Spectrum.xVal; - } - - if ( mode === 'count' ) { - - // Divide 0 - 100 in 'count' parts. - var spread = ( 100 / (values-1) ), v, i = 0; - values = []; - - // List these parts and have them handled as 'positions'. - while ((v=i++*spread) <= 100 ) { - values.push(v); - } - - mode = 'positions'; - } - - if ( mode === 'positions' ) { - - // Map all percentages to on-range values. - return $.map(values, function( value ){ - return $Spectrum.fromStepping( stepped ? $Spectrum.getStep( value ) : value ); - }); - } - - if ( mode === 'values' ) { - - // If the value must be stepped, it needs to be converted to a percentage first. - if ( stepped ) { - - return $.map(values, function( value ){ - - // Convert to percentage, apply step, return to value. - return $Spectrum.fromStepping( $Spectrum.getStep( $Spectrum.toStepping( value ) ) ); - }); - - } - - // Otherwise, we can simply use the values. - return values; - } - } - - function generateSpread ( $Spectrum, density, mode, group ) { - - var originalSpectrumDirection = $Spectrum.direction, - indexes = {}, - firstInRange = $Spectrum.xVal[0], - lastInRange = $Spectrum.xVal[$Spectrum.xVal.length-1], - ignoreFirst = false, - ignoreLast = false, - prevPct = 0; - - // This function loops the spectrum in an ltr linear fashion, - // while the toStepping method is direction aware. Trick it into - // believing it is ltr. - $Spectrum.direction = 0; - - // Create a copy of the group, sort it and filter away all duplicates. - group = unique(group.slice().sort(function(a, b){ return a - b; })); - - // Make sure the range starts with the first element. - if ( group[0] !== firstInRange ) { - group.unshift(firstInRange); - ignoreFirst = true; - } - - // Likewise for the last one. - if ( group[group.length - 1] !== lastInRange ) { - group.push(lastInRange); - ignoreLast = true; - } - - $.each(group, function ( index ) { - - // Get the current step and the lower + upper positions. - var step, i, q, - low = group[index], - high = group[index+1], - newPct, pctDifference, pctPos, type, - steps, realSteps, stepsize; - - // When using 'steps' mode, use the provided steps. - // Otherwise, we'll step on to the next subrange. - if ( mode === 'steps' ) { - step = $Spectrum.xNumSteps[ index ]; - } - - // Default to a 'full' step. - if ( !step ) { - step = high-low; - } - - // Low can be 0, so test for false. If high is undefined, - // we are at the last subrange. Index 0 is already handled. - if ( low === false || high === undefined ) { - return; - } - - // Find all steps in the subrange. - for ( i = low; i <= high; i += step ) { - - // Get the percentage value for the current step, - // calculate the size for the subrange. - newPct = $Spectrum.toStepping( i ); - pctDifference = newPct - prevPct; - - steps = pctDifference / density; - realSteps = Math.round(steps); - - // This ratio represents the ammount of percentage-space a point indicates. - // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-devided. - // Round the percentage offset to an even number, then divide by two - // to spread the offset on both sides of the range. - stepsize = pctDifference/realSteps; - - // Divide all points evenly, adding the correct number to this subrange. - // Run up to <= so that 100% gets a point, event if ignoreLast is set. - for ( q = 1; q <= realSteps; q += 1 ) { - - // The ratio between the rounded value and the actual size might be ~1% off. - // Correct the percentage offset by the number of points - // per subrange. density = 1 will result in 100 points on the - // full range, 2 for 50, 4 for 25, etc. - pctPos = prevPct + ( q * stepsize ); - indexes[pctPos.toFixed(5)] = ['x', 0]; - } - - // Determine the point type. - type = ($.inArray(i, group) > -1) ? 1 : ( mode === 'steps' ? 2 : 0 ); - - // Enforce the 'ignoreFirst' option by overwriting the type for 0. - if ( !index && ignoreFirst ) { - type = 0; - } - - if ( !(i === high && ignoreLast)) { - // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value. - indexes[newPct.toFixed(5)] = [i, type]; - } - - // Update the percentage count. - prevPct = newPct; - } - }); - - // Reset the spectrum. - $Spectrum.direction = originalSpectrumDirection; - - return indexes; - } - - function addMarking ( CSSstyle, orientation, direction, spread, filterFunc, formatter ) { - - var style = ['horizontal', 'vertical'][orientation], - element = $('
'); - - element.addClass('noUi-pips noUi-pips-'+style); - - function getSize( type, value ){ - return [ '-normal', '-large', '-sub' ][type]; - } - - function getTags( offset, source, values ) { - return 'class="' + source + ' ' + - source + '-' + style + ' ' + - source + getSize(values[1], values[0]) + - '" style="' + CSSstyle + ': ' + offset + '%"'; - } - - function addSpread ( offset, values ){ - - if ( direction ) { - offset = 100 - offset; - } - - // Apply the filter function, if it is set. - values[1] = (values[1] && filterFunc) ? filterFunc(values[0], values[1]) : values[1]; - - // Add a marker for every point - element.append('
'); - - // Values are only appended for points marked '1' or '2'. - if ( values[1] ) { - element.append('
' + formatter.to(values[0]) + '
'); - } - } - - // Append all points. - $.each(spread, addSpread); - - return element; - } - - $.fn.noUiSlider_pips = function ( grid ) { - - var mode = grid.mode, - density = grid.density || 1, - filter = grid.filter || false, - values = grid.values || false, - format = grid.format || { - to: Math.round - }, - stepped = grid.stepped || false; - - return this.each(function(){ - - var info = this.getInfo(), - group = getGroup( info[0], mode, values, stepped ), - spread = generateSpread( info[0], density, mode, group ); - - return $(this).append(addMarking( - info[1], - info[2], - info[0].direction, - spread, - filter, - format - )); - }); - }; - -}( window.jQuery || window.Zepto )); diff --git a/distribute/jquery.nouislider.all.min.js b/distribute/jquery.nouislider.all.min.js deleted file mode 100644 index 3370ec45..00000000 --- a/distribute/jquery.nouislider.all.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! noUiSlider - 7.0.10 - 2014-12-27 14:50:47 */ - -!function(){"use strict";function a(a){return a.split("").reverse().join("")}function b(a,b){return a.substring(0,b.length)===b}function c(a,b){return a.slice(-1*b.length)===b}function d(a,b,c){if((a[b]||a[c])&&a[b]===a[c])throw new Error(b)}function e(a){return"number"==typeof a&&isFinite(a)}function f(a,b){var c=Math.pow(10,b);return(Math.round(a*c)/c).toFixed(b)}function g(b,c,d,g,h,i,j,k,l,m,n,o){var p,q,r,s=o,t="",u="";return i&&(o=i(o)),e(o)?(b!==!1&&0===parseFloat(o.toFixed(b))&&(o=0),0>o&&(p=!0,o=Math.abs(o)),b!==!1&&(o=f(o,b)),o=o.toString(),-1!==o.indexOf(".")?(q=o.split("."),r=q[0],d&&(t=d+q[1])):r=o,c&&(r=a(r).match(/.{1,3}/g),r=a(r.join(a(c)))),p&&k&&(u+=k),g&&(u+=g),p&&l&&(u+=l),u+=r,u+=t,h&&(u+=h),m&&(u=m(u,s)),u):!1}function h(a,d,f,g,h,i,j,k,l,m,n,o){var p,q="";return n&&(o=n(o)),o&&"string"==typeof o?(k&&b(o,k)&&(o=o.replace(k,""),p=!0),g&&b(o,g)&&(o=o.replace(g,"")),l&&b(o,l)&&(o=o.replace(l,""),p=!0),h&&c(o,h)&&(o=o.slice(0,-1*h.length)),d&&(o=o.split(d).join("")),f&&(o=o.replace(f,".")),p&&(q+="-"),q+=o,q=q.replace(/[^0-9\.\-.]/g,""),""===q?!1:(q=Number(q),j&&(q=j(q)),e(q)?q:!1)):!1}function i(a){var b,c,e,f={};for(b=0;b=0&&8>e))throw new Error(c);f[c]=e}else if("encoder"===c||"decoder"===c||"edit"===c||"undo"===c){if("function"!=typeof e)throw new Error(c);f[c]=e}else{if("string"!=typeof e)throw new Error(c);f[c]=e}return d(f,"mark","thousand"),d(f,"prefix","negative"),d(f,"prefix","negativeBefore"),f}function j(a,b,c){var d,e=[];for(d=0;d"),!0):void 0}function d(b){if("string"==typeof b&&0!==b.indexOf("-")){this.method="val";var c=document.createElement("input");return c.name=b,c.type="hidden",this.target=this.el=a(c),!0}}function e(a){return"function"==typeof a?(this.target=!1,this.method=a,!0):void 0}function f(a,c){return b(a)&&!c?(a.is("input, select, textarea")?(this.method="val",this.target=a.on("change.liblink",this.changeHandler)):(this.target=a,this.method="html"),!0):void 0}function g(a,c){return b(a)&&("function"==typeof c||"string"==typeof c&&a[c])?(this.method=c,this.target=a,!0):void 0}function h(b,c,d){var e=this,f=!1;if(this.changeHandler=function(b){var c=e.formatInstance.from(a(this).val());return c===!1||isNaN(c)?(a(this).val(e.lastSetValue),!1):void e.changeHandlerMethod.call("",b,c)},this.el=!1,this.formatInstance=d,a.each(k,function(a,d){return f=d.call(e,b,c),!f}),!f)throw new RangeError("(Link) Invalid Link.")}function i(a){this.items=[],this.elements=[],this.origin=a}function j(b,c,d,e){0===b&&(b=this.LinkDefaultFlag),this.linkAPI||(this.linkAPI={}),this.linkAPI[b]||(this.linkAPI[b]=new i(this));var f=new h(c,d,e||this.LinkDefaultFormatter);f.target||(f.target=a(this)),f.changeHandlerMethod=this.LinkConfirm(b,f.el),this.linkAPI[b].push(f,f.el),this.LinkUpdate(b)}var k=[c,d,e,f,g];h.prototype.set=function(a){var b=Array.prototype.slice.call(arguments),c=b.slice(1);this.lastSetValue=this.formatInstance.to(a),c.unshift(this.lastSetValue),("function"==typeof this.method?this.method:this.target[this.method]).apply(this.target,c)},i.prototype.push=function(a,b){this.items.push(a),b&&this.elements.push(b)},i.prototype.reconfirm=function(a){var b;for(b=0;b1?b[1].length:0}function j(a,b){return 100/(b-a)}function k(a,b){return 100*b/(a[1]-a[0])}function l(a,b){return k(a,a[0]<0?b+Math.abs(a[0]):b-a[0])}function m(a,b){return b*(a[1]-a[0])/100+a[0]}function n(a,b){for(var c=1;a>=b[c];)c+=1;return c}function o(a,b,c){if(c>=a.slice(-1)[0])return 100;var d,e,f,g,h=n(c,a);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],f+l([d,e],c)/j(f,g)}function p(a,b,c){if(c>=100)return a.slice(-1)[0];var d,e,f,g,h=n(c,b);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],m([d,e],(c-f)*j(f,g))}function q(a,b,d,e){if(100===e)return e;var f,g,h=n(e,a);return d?(f=a[h-1],g=a[h],e-f>(g-f)/2?g:f):b[h-1]?a[h-1]+c(e-a[h-1],b[h-1]):e}function r(a,b,c){var e;if("number"==typeof b&&(b=[b]),"[object Array]"!==Object.prototype.toString.call(b))throw new Error("noUiSlider: 'range' contains invalid value.");if(e="min"===a?0:"max"===a?100:parseFloat(a),!d(e)||!d(b[0]))throw new Error("noUiSlider: 'range' value isn't numeric.");c.xPct.push(e),c.xVal.push(b[0]),e?c.xSteps.push(isNaN(b[1])?!1:b[1]):isNaN(b[1])||(c.xSteps[0]=b[1])}function s(a,b,c){return b?void(c.xSteps[a]=k([c.xVal[a],c.xVal[a+1]],b)/j(c.xPct[a],c.xPct[a+1])):!0}function t(a,b,c,d){this.xPct=[],this.xVal=[],this.xSteps=[d||!1],this.xNumSteps=[!1],this.snap=b,this.direction=c;var e,f=[];for(e in a)a.hasOwnProperty(e)&&f.push([a[e],e]);for(f.sort(function(a,b){return a[0]-b[0]}),e=0;e2)throw new Error("noUiSlider: 'start' option is incorrect.");b.handles=c.length,b.start=c}function x(a,b){if(a.snap=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'snap' option must be a boolean.")}function y(a,b){if(a.animate=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'animate' option must be a boolean.")}function z(a,b){if("lower"===b&&1===a.handles)a.connect=1;else if("upper"===b&&1===a.handles)a.connect=2;else if(b===!0&&2===a.handles)a.connect=3;else{if(b!==!1)throw new Error("noUiSlider: 'connect' option doesn't match handle count.");a.connect=0}}function A(a,b){switch(b){case"horizontal":a.ort=0;break;case"vertical":a.ort=1;break;default:throw new Error("noUiSlider: 'orientation' option is invalid.")}}function B(a,b){if(!d(b))throw new Error("noUiSlider: 'margin' option must be numeric.");if(a.margin=a.spectrum.getMargin(b),!a.margin)throw new Error("noUiSlider: 'margin' option is only supported on linear sliders.")}function C(a,b){if(!d(b))throw new Error("noUiSlider: 'limit' option must be numeric.");if(a.limit=a.spectrum.getMargin(b),!a.limit)throw new Error("noUiSlider: 'limit' option is only supported on linear sliders.")}function D(a,b){switch(b){case"ltr":a.dir=0;break;case"rtl":a.dir=1,a.connect=[0,2,1,3][a.connect];break;default:throw new Error("noUiSlider: 'direction' option was not recognized.")}}function E(a,b){if("string"!=typeof b)throw new Error("noUiSlider: 'behaviour' must be a string containing options.");var c=b.indexOf("tap")>=0,d=b.indexOf("drag")>=0,e=b.indexOf("fixed")>=0,f=b.indexOf("snap")>=0;a.events={tap:c||f,drag:d,fixed:e,snap:f}}function F(a,b){if(a.format=b,"function"==typeof b.to&&"function"==typeof b.from)return!0;throw new Error("noUiSlider: 'format' requires 'to' and 'from' methods.")}function G(b){var c,d={margin:0,limit:0,animate:!0,format:Z};return c={step:{r:!1,t:u},start:{r:!0,t:w},connect:{r:!0,t:z},direction:{r:!0,t:D},snap:{r:!1,t:x},animate:{r:!1,t:y},range:{r:!0,t:v},orientation:{r:!1,t:A},margin:{r:!1,t:B},limit:{r:!1,t:C},behaviour:{r:!0,t:E},format:{r:!1,t:F}},b=a.extend({connect:!1,direction:"ltr",behaviour:"tap",orientation:"horizontal"},b),a.each(c,function(a,c){if(void 0===b[a]){if(c.r)throw new Error("noUiSlider: '"+a+"' is required.");return!0}c.t(d,b[a])}),d.style=d.ort?"top":"left",d}function H(a,b,c){var d=a+b[0],e=a+b[1];return c?(0>d&&(e+=Math.abs(d)),e>100&&(d-=e-100),[g(d),g(e)]):[d,e]}function I(a){a.preventDefault();var b,c,d=0===a.type.indexOf("touch"),e=0===a.type.indexOf("mouse"),f=0===a.type.indexOf("pointer"),g=a;return 0===a.type.indexOf("MSPointer")&&(f=!0),a.originalEvent&&(a=a.originalEvent),d&&(b=a.changedTouches[0].pageX,c=a.changedTouches[0].pageY),(e||f)&&(f||void 0!==window.pageXOffset||(window.pageXOffset=document.documentElement.scrollLeft,window.pageYOffset=document.documentElement.scrollTop),b=a.clientX+window.pageXOffset,c=a.clientY+window.pageYOffset),g.points=[b,c],g.cursor=e,g}function J(b,c){var d=a("
").addClass(Y[2]),e=["-lower","-upper"];return b&&e.reverse(),d.children().addClass(Y[3]+" "+Y[3]+e[c]),d}function K(a,b,c){switch(a){case 1:b.addClass(Y[7]),c[0].addClass(Y[6]);break;case 3:c[1].addClass(Y[6]);case 2:c[0].addClass(Y[7]);case 0:b.addClass(Y[6])}}function L(a,b,c){var d,e=[];for(d=0;a>d;d+=1)e.push(J(b,d).appendTo(c));return e}function M(b,c,d){return d.addClass([Y[0],Y[8+b],Y[4+c]].join(" ")),a("
").appendTo(d).addClass(Y[1])}function N(b,c,d){function e(){return C[["width","height"][c.ort]]()}function j(a){var b,c=[E.val()];for(b=0;b1&&(e=1===e?0:1),l(e)}function o(){var a,b;for(a=0;a1),f=v(d[0],c[h],1===d.length),d.length>1&&(f=v(d[1],c[h?0:1],!1)||f),f&&j(["slide"])}function r(b){a("."+Y[15]).removeClass(Y[15]),b.cursor&&a("body").css("cursor","").off(W),U.off(W),E.removeClass(Y[12]),j(["set","change"])}function s(b,c){1===c.handles.length&&c.handles[0].children().addClass(Y[15]),b.stopPropagation(),p(X.move,U,q,{start:b.calcPoint,handles:c.handles,positions:[F[0],F[D.length-1]]}),p(X.end,U,r,null),b.cursor&&(a("body").css("cursor",a(b.target).css("cursor")),D.length>1&&E.addClass(Y[12]),a("body").on("selectstart"+W,!1))}function t(b){var d,g=b.calcPoint,h=0;b.stopPropagation(),a.each(D,function(){h+=this.offset()[c.style]}),h=h/2>g||1===D.length?0:1,g-=C.offset()[c.style],d=100*g/e(),c.events.snap||f(E,Y[14],300),v(D[h],d),j(["slide","set","change"]),c.events.snap&&s(b,{handles:[D[h]]})}function u(a){var b,c;if(!a.fixed)for(b=0;b1&&(b=e?Math.max(b,f):Math.min(b,h)),d!==!1&&c.limit&&D.length>1&&(b=e?Math.min(b,i):Math.max(b,j)),b=G.getStep(b),b=g(parseFloat(b.toFixed(7))),b===F[e]?!1:(a.css(c.style,b+"%"),a.is(":first-child")&&a.toggleClass(Y[17],b>50),F[e]=b,J[e]=G.fromStepping(b),m(N[e]),!0)}function w(a,b){var d,e,f;for(c.limit&&(a+=1),d=0;a>d;d+=1)e=d%2,f=b[e],null!==f&&f!==!1&&("number"==typeof f&&(f=String(f)),f=c.format.from(f),(f===!1||isNaN(f)||v(D[e],G.toStepping(f),d===3-c.dir)===!1)&&m(N[e]))}function x(a){if(E[0].LinkIsEmitting)return this;var b,d=h(a);return c.dir&&c.handles>1&&d.reverse(),c.animate&&-1!==F[0]&&f(E,Y[14],300),b=D.length>1?3:1,1===d.length&&(b=1),w(b,d),j(["set"]),this}function y(){var a,b=[];for(a=0;a=c[1]?c[2]:c[0]||!1;return[[h,f]]});return k(b)}function B(){return d}var C,D,E=a(b),F=[-1,-1],G=c.spectrum,J=[],N=["lower","upper"].slice(0,c.handles);if(c.dir&&N.reverse(),b.LinkUpdate=m,b.LinkConfirm=n,b.LinkDefaultFormatter=c.format,b.LinkDefaultFlag="lower",b.reappend=o,E.hasClass(Y[0]))throw new Error("Slider was already initialized.");C=M(c.dir,c.ort,E),D=L(c.handles,c.dir,C),K(c.connect,E,D),u(c.events),b.vSet=x,b.vGet=y,b.destroy=z,b.getCurrentStep=A,b.getOriginalOptions=B,b.getInfo=function(){return[G,c.style,c.ort]},E.val(c.start)}function O(a){var b=G(a,this);return this.each(function(){N(this,b,a)})}function P(b){return this.each(function(){if(!this.destroy)return void a(this).noUiSlider(b);var c=a(this).val(),d=this.destroy(),e=a.extend({},d,b);a(this).noUiSlider(e),this.reappend(),d.start===e.start&&a(this).val(c)})}function Q(){return this[0][arguments.length?"vSet":"vGet"].apply(this[0],arguments)}function R(b,c,d,e){if("range"===c||"steps"===c)return b.xVal;if("count"===c){var f,g=100/(d-1),h=0;for(d=[];(f=h++*g)<=100;)d.push(f);c="positions"}return"positions"===c?a.map(d,function(a){return b.fromStepping(e?b.getStep(a):a)}):"values"===c?e?a.map(d,function(a){return b.fromStepping(b.getStep(b.toStepping(a)))}):d:void 0}function S(c,d,e,f){var g=c.direction,h={},i=c.xVal[0],j=c.xVal[c.xVal.length-1],k=!1,l=!1,m=0;return c.direction=0,f=b(f.slice().sort(function(a,b){return a-b})),f[0]!==i&&(f.unshift(i),k=!0),f[f.length-1]!==j&&(f.push(j),l=!0),a.each(f,function(b){var g,i,j,n,o,p,q,r,s,t,u=f[b],v=f[b+1];if("steps"===e&&(g=c.xNumSteps[b]),g||(g=v-u),u!==!1&&void 0!==v)for(i=u;v>=i;i+=g){for(n=c.toStepping(i),o=n-m,r=o/d,s=Math.round(r),t=o/s,j=1;s>=j;j+=1)p=m+j*t,h[p.toFixed(5)]=["x",0];q=a.inArray(i,f)>-1?1:"steps"===e?2:0,!b&&k&&(q=0),i===v&&l||(h[n.toFixed(5)]=[i,q]),m=n}}),c.direction=g,h}function T(b,c,d,e,f,g){function h(a){return["-normal","-large","-sub"][a]}function i(a,c,d){return'class="'+c+" "+c+"-"+k+" "+c+h(d[1],d[0])+'" style="'+b+": "+a+'%"'}function j(a,b){d&&(a=100-a),b[1]=b[1]&&f?f(b[0],b[1]):b[1],l.append("
"),b[1]&&l.append("
"+g.to(b[0])+"
")}var k=["horizontal","vertical"][c],l=a("
");return l.addClass("noUi-pips noUi-pips-"+k),a.each(e,j),l}var U=a(document),V=a.fn.val,W=".nui",X=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"},Y=["noUi-target","noUi-base","noUi-origin","noUi-handle","noUi-horizontal","noUi-vertical","noUi-background","noUi-connect","noUi-ltr","noUi-rtl","noUi-dragable","","noUi-state-drag","","noUi-state-tap","noUi-active","","noUi-stacking"];t.prototype.getMargin=function(a){return 2===this.xPct.length?k(this.xVal,a):!1},t.prototype.toStepping=function(a){return a=o(this.xVal,this.xPct,a),this.direction&&(a=100-a),a},t.prototype.fromStepping=function(a){return this.direction&&(a=100-a),e(p(this.xVal,this.xPct,a))},t.prototype.getStep=function(a){return this.direction&&(a=100-a),a=q(this.xPct,this.xSteps,this.snap,a),this.direction&&(a=100-a),a},t.prototype.getApplicableStep=function(a){var b=n(a,this.xPct),c=100===a?2:1;return[this.xNumSteps[b-2],this.xVal[b-c],this.xNumSteps[b-c]]},t.prototype.convert=function(a){return this.getStep(this.toStepping(a))};var Z={to:function(a){return a.toFixed(2)},from:Number};a.fn.val=function(b){function c(a){return a.hasClass(Y[0])?Q:V}if(!arguments.length){var d=a(this[0]);return c(d).call(d)}var e=a.isFunction(b);return this.each(function(d){var f=b,g=a(this);e&&(f=b.call(this,d,g.val())),c(g).call(g,f)})},a.fn.noUiSlider=function(a,b){switch(a){case"step":return this[0].getCurrentStep();case"options":return this[0].getOriginalOptions()}return(b?P:O).call(this,a)},a.fn.noUiSlider_pips=function(b){var c=b.mode,d=b.density||1,e=b.filter||!1,f=b.values||!1,g=b.format||{to:Math.round},h=b.stepped||!1;return this.each(function(){var b=this.getInfo(),i=R(b[0],c,f,h),j=S(b[0],d,c,i);return a(this).append(T(b[1],b[2],b[0].direction,j,e,g))})}}(window.jQuery||window.Zepto); \ No newline at end of file diff --git a/distribute/jquery.nouislider.min.css b/distribute/jquery.nouislider.min.css deleted file mode 100644 index f86b30cd..00000000 --- a/distribute/jquery.nouislider.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! noUiSlider - 7.0.10 - 2014-12-27 14:50:47 */ - - -.noUi-target,.noUi-target *{-webkit-touch-callout:none;-webkit-user-select:none;-ms-touch-action:none;-ms-user-select:none;-moz-user-select:none;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-target{position:relative;direction:ltr}.noUi-base{width:100%;height:100%;position:relative}.noUi-origin{position:absolute;right:0;top:0;left:0;bottom:0}.noUi-handle{position:relative;z-index:1}.noUi-stacking .noUi-handle{z-index:10}.noUi-state-tap .noUi-origin{-webkit-transition:left .3s,top .3s;transition:left .3s,top .3s}.noUi-state-drag *{cursor:inherit!important}.noUi-base{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.noUi-horizontal{height:18px}.noUi-horizontal .noUi-handle{width:34px;height:28px;left:-17px;top:-6px}.noUi-vertical{width:18px}.noUi-vertical .noUi-handle{width:28px;height:34px;left:-6px;top:-17px}.noUi-background{background:#FAFAFA;box-shadow:inset 0 1px 1px #f0f0f0}.noUi-connect{background:#3FB8AF;box-shadow:inset 0 0 3px rgba(51,51,51,.45);-webkit-transition:background 450ms;transition:background 450ms}.noUi-origin{border-radius:2px}.noUi-target{border-radius:4px;border:1px solid #D3D3D3;box-shadow:inset 0 1px 1px #F0F0F0,0 3px 6px -5px #BBB}.noUi-target.noUi-connect{box-shadow:inset 0 0 3px rgba(51,51,51,.45),0 3px 6px -5px #BBB}.noUi-dragable{cursor:w-resize}.noUi-vertical .noUi-dragable{cursor:n-resize}.noUi-handle{border:1px solid #D9D9D9;border-radius:3px;background:#FFF;cursor:default;box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #EBEBEB,0 3px 6px -3px #BBB}.noUi-active{box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #DDD,0 3px 6px -3px #BBB}.noUi-handle:after,.noUi-handle:before{content:"";display:block;position:absolute;height:14px;width:1px;background:#E8E7E6;left:14px;top:6px}.noUi-handle:after{left:17px}.noUi-vertical .noUi-handle:after,.noUi-vertical .noUi-handle:before{width:14px;height:1px;left:6px;top:14px}.noUi-vertical .noUi-handle:after{top:17px}[disabled] .noUi-connect,[disabled].noUi-connect{background:#B8B8B8}[disabled] .noUi-handle{cursor:not-allowed} \ No newline at end of file diff --git a/distribute/jquery.nouislider.min.js b/distribute/jquery.nouislider.min.js deleted file mode 100644 index 888feb51..00000000 --- a/distribute/jquery.nouislider.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! noUiSlider - 7.0.10 - 2014-12-27 14:50:47 */ - -!function(a){"use strict";function b(a,b){return Math.round(a/b)*b}function c(a){return"number"==typeof a&&!isNaN(a)&&isFinite(a)}function d(a){var b=Math.pow(10,7);return Number((Math.round(a*b)/b).toFixed(7))}function e(a,b,c){a.addClass(b),setTimeout(function(){a.removeClass(b)},c)}function f(a){return Math.max(Math.min(a,100),0)}function g(b){return a.isArray(b)?b:[b]}function h(a){var b=a.split(".");return b.length>1?b[1].length:0}function i(a,b){return 100/(b-a)}function j(a,b){return 100*b/(a[1]-a[0])}function k(a,b){return j(a,a[0]<0?b+Math.abs(a[0]):b-a[0])}function l(a,b){return b*(a[1]-a[0])/100+a[0]}function m(a,b){for(var c=1;a>=b[c];)c+=1;return c}function n(a,b,c){if(c>=a.slice(-1)[0])return 100;var d,e,f,g,h=m(c,a);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],f+k([d,e],c)/i(f,g)}function o(a,b,c){if(c>=100)return a.slice(-1)[0];var d,e,f,g,h=m(c,b);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],l([d,e],(c-f)*i(f,g))}function p(a,c,d,e){if(100===e)return e;var f,g,h=m(e,a);return d?(f=a[h-1],g=a[h],e-f>(g-f)/2?g:f):c[h-1]?a[h-1]+b(e-a[h-1],c[h-1]):e}function q(a,b,d){var e;if("number"==typeof b&&(b=[b]),"[object Array]"!==Object.prototype.toString.call(b))throw new Error("noUiSlider: 'range' contains invalid value.");if(e="min"===a?0:"max"===a?100:parseFloat(a),!c(e)||!c(b[0]))throw new Error("noUiSlider: 'range' value isn't numeric.");d.xPct.push(e),d.xVal.push(b[0]),e?d.xSteps.push(isNaN(b[1])?!1:b[1]):isNaN(b[1])||(d.xSteps[0]=b[1])}function r(a,b,c){return b?void(c.xSteps[a]=j([c.xVal[a],c.xVal[a+1]],b)/i(c.xPct[a],c.xPct[a+1])):!0}function s(a,b,c,d){this.xPct=[],this.xVal=[],this.xSteps=[d||!1],this.xNumSteps=[!1],this.snap=b,this.direction=c;var e,f=[];for(e in a)a.hasOwnProperty(e)&&f.push([a[e],e]);for(f.sort(function(a,b){return a[0]-b[0]}),e=0;e2)throw new Error("noUiSlider: 'start' option is incorrect.");b.handles=c.length,b.start=c}function w(a,b){if(a.snap=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'snap' option must be a boolean.")}function x(a,b){if(a.animate=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'animate' option must be a boolean.")}function y(a,b){if("lower"===b&&1===a.handles)a.connect=1;else if("upper"===b&&1===a.handles)a.connect=2;else if(b===!0&&2===a.handles)a.connect=3;else{if(b!==!1)throw new Error("noUiSlider: 'connect' option doesn't match handle count.");a.connect=0}}function z(a,b){switch(b){case"horizontal":a.ort=0;break;case"vertical":a.ort=1;break;default:throw new Error("noUiSlider: 'orientation' option is invalid.")}}function A(a,b){if(!c(b))throw new Error("noUiSlider: 'margin' option must be numeric.");if(a.margin=a.spectrum.getMargin(b),!a.margin)throw new Error("noUiSlider: 'margin' option is only supported on linear sliders.")}function B(a,b){if(!c(b))throw new Error("noUiSlider: 'limit' option must be numeric.");if(a.limit=a.spectrum.getMargin(b),!a.limit)throw new Error("noUiSlider: 'limit' option is only supported on linear sliders.")}function C(a,b){switch(b){case"ltr":a.dir=0;break;case"rtl":a.dir=1,a.connect=[0,2,1,3][a.connect];break;default:throw new Error("noUiSlider: 'direction' option was not recognized.")}}function D(a,b){if("string"!=typeof b)throw new Error("noUiSlider: 'behaviour' must be a string containing options.");var c=b.indexOf("tap")>=0,d=b.indexOf("drag")>=0,e=b.indexOf("fixed")>=0,f=b.indexOf("snap")>=0;a.events={tap:c||f,drag:d,fixed:e,snap:f}}function E(a,b){if(a.format=b,"function"==typeof b.to&&"function"==typeof b.from)return!0;throw new Error("noUiSlider: 'format' requires 'to' and 'from' methods.")}function F(b){var c,d={margin:0,limit:0,animate:!0,format:V};return c={step:{r:!1,t:t},start:{r:!0,t:v},connect:{r:!0,t:y},direction:{r:!0,t:C},snap:{r:!1,t:w},animate:{r:!1,t:x},range:{r:!0,t:u},orientation:{r:!1,t:z},margin:{r:!1,t:A},limit:{r:!1,t:B},behaviour:{r:!0,t:D},format:{r:!1,t:E}},b=a.extend({connect:!1,direction:"ltr",behaviour:"tap",orientation:"horizontal"},b),a.each(c,function(a,c){if(void 0===b[a]){if(c.r)throw new Error("noUiSlider: '"+a+"' is required.");return!0}c.t(d,b[a])}),d.style=d.ort?"top":"left",d}function G(a,b,c){var d=a+b[0],e=a+b[1];return c?(0>d&&(e+=Math.abs(d)),e>100&&(d-=e-100),[f(d),f(e)]):[d,e]}function H(a){a.preventDefault();var b,c,d=0===a.type.indexOf("touch"),e=0===a.type.indexOf("mouse"),f=0===a.type.indexOf("pointer"),g=a;return 0===a.type.indexOf("MSPointer")&&(f=!0),a.originalEvent&&(a=a.originalEvent),d&&(b=a.changedTouches[0].pageX,c=a.changedTouches[0].pageY),(e||f)&&(f||void 0!==window.pageXOffset||(window.pageXOffset=document.documentElement.scrollLeft,window.pageYOffset=document.documentElement.scrollTop),b=a.clientX+window.pageXOffset,c=a.clientY+window.pageYOffset),g.points=[b,c],g.cursor=e,g}function I(b,c){var d=a("
").addClass(U[2]),e=["-lower","-upper"];return b&&e.reverse(),d.children().addClass(U[3]+" "+U[3]+e[c]),d}function J(a,b,c){switch(a){case 1:b.addClass(U[7]),c[0].addClass(U[6]);break;case 3:c[1].addClass(U[6]);case 2:c[0].addClass(U[7]);case 0:b.addClass(U[6])}}function K(a,b,c){var d,e=[];for(d=0;a>d;d+=1)e.push(I(b,d).appendTo(c));return e}function L(b,c,d){return d.addClass([U[0],U[8+b],U[4+c]].join(" ")),a("
").appendTo(d).addClass(U[1])}function M(b,c,d){function i(){return C[["width","height"][c.ort]]()}function j(a){var b,c=[E.val()];for(b=0;b1&&(e=1===e?0:1),l(e)}function o(){var a,b;for(a=0;a1),e=v(d[0],c[g],1===d.length),d.length>1&&(e=v(d[1],c[g?0:1],!1)||e),e&&j(["slide"])}function r(b){a("."+U[15]).removeClass(U[15]),b.cursor&&a("body").css("cursor","").off(S),Q.off(S),E.removeClass(U[12]),j(["set","change"])}function s(b,c){1===c.handles.length&&c.handles[0].children().addClass(U[15]),b.stopPropagation(),p(T.move,Q,q,{start:b.calcPoint,handles:c.handles,positions:[F[0],F[D.length-1]]}),p(T.end,Q,r,null),b.cursor&&(a("body").css("cursor",a(b.target).css("cursor")),D.length>1&&E.addClass(U[12]),a("body").on("selectstart"+S,!1))}function t(b){var d,f=b.calcPoint,g=0;b.stopPropagation(),a.each(D,function(){g+=this.offset()[c.style]}),g=g/2>f||1===D.length?0:1,f-=C.offset()[c.style],d=100*f/i(),c.events.snap||e(E,U[14],300),v(D[g],d),j(["slide","set","change"]),c.events.snap&&s(b,{handles:[D[g]]})}function u(a){var b,c;if(!a.fixed)for(b=0;b1&&(b=e?Math.max(b,g):Math.min(b,h)),d!==!1&&c.limit&&D.length>1&&(b=e?Math.min(b,i):Math.max(b,j)),b=I.getStep(b),b=f(parseFloat(b.toFixed(7))),b===F[e]?!1:(a.css(c.style,b+"%"),a.is(":first-child")&&a.toggleClass(U[17],b>50),F[e]=b,M[e]=I.fromStepping(b),m(N[e]),!0)}function w(a,b){var d,e,f;for(c.limit&&(a+=1),d=0;a>d;d+=1)e=d%2,f=b[e],null!==f&&f!==!1&&("number"==typeof f&&(f=String(f)),f=c.format.from(f),(f===!1||isNaN(f)||v(D[e],I.toStepping(f),d===3-c.dir)===!1)&&m(N[e]))}function x(a){if(E[0].LinkIsEmitting)return this;var b,d=g(a);return c.dir&&c.handles>1&&d.reverse(),c.animate&&-1!==F[0]&&e(E,U[14],300),b=D.length>1?3:1,1===d.length&&(b=1),w(b,d),j(["set"]),this}function y(){var a,b=[];for(a=0;a=c[1]?c[2]:c[0]||!1;return[[i,f]]});return k(b)}function B(){return d}var C,D,E=a(b),F=[-1,-1],I=c.spectrum,M=[],N=["lower","upper"].slice(0,c.handles);if(c.dir&&N.reverse(),b.LinkUpdate=m,b.LinkConfirm=n,b.LinkDefaultFormatter=c.format,b.LinkDefaultFlag="lower",b.reappend=o,E.hasClass(U[0]))throw new Error("Slider was already initialized.");C=L(c.dir,c.ort,E),D=K(c.handles,c.dir,C),J(c.connect,E,D),u(c.events),b.vSet=x,b.vGet=y,b.destroy=z,b.getCurrentStep=A,b.getOriginalOptions=B,b.getInfo=function(){return[I,c.style,c.ort]},E.val(c.start)}function N(a){var b=F(a,this);return this.each(function(){M(this,b,a)})}function O(b){return this.each(function(){if(!this.destroy)return void a(this).noUiSlider(b);var c=a(this).val(),d=this.destroy(),e=a.extend({},d,b);a(this).noUiSlider(e),this.reappend(),d.start===e.start&&a(this).val(c)})}function P(){return this[0][arguments.length?"vSet":"vGet"].apply(this[0],arguments)}var Q=a(document),R=a.fn.val,S=".nui",T=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"},U=["noUi-target","noUi-base","noUi-origin","noUi-handle","noUi-horizontal","noUi-vertical","noUi-background","noUi-connect","noUi-ltr","noUi-rtl","noUi-dragable","","noUi-state-drag","","noUi-state-tap","noUi-active","","noUi-stacking"];s.prototype.getMargin=function(a){return 2===this.xPct.length?j(this.xVal,a):!1},s.prototype.toStepping=function(a){return a=n(this.xVal,this.xPct,a),this.direction&&(a=100-a),a},s.prototype.fromStepping=function(a){return this.direction&&(a=100-a),d(o(this.xVal,this.xPct,a))},s.prototype.getStep=function(a){return this.direction&&(a=100-a),a=p(this.xPct,this.xSteps,this.snap,a),this.direction&&(a=100-a),a},s.prototype.getApplicableStep=function(a){var b=m(a,this.xPct),c=100===a?2:1;return[this.xNumSteps[b-2],this.xVal[b-c],this.xNumSteps[b-c]]},s.prototype.convert=function(a){return this.getStep(this.toStepping(a))};var V={to:function(a){return a.toFixed(2)},from:Number};a.fn.val=function(b){function c(a){return a.hasClass(U[0])?P:R}if(!arguments.length){var d=a(this[0]);return c(d).call(d)}var e=a.isFunction(b);return this.each(function(d){var f=b,g=a(this);e&&(f=b.call(this,d,g.val())),c(g).call(g,f)})},a.fn.noUiSlider=function(a,b){switch(a){case"step":return this[0].getCurrentStep();case"options":return this[0].getOriginalOptions()}return(b?O:N).call(this,a)}}(window.jQuery||window.Zepto); \ No newline at end of file diff --git a/distribute/jquery.nouislider.pips.min.css b/distribute/jquery.nouislider.pips.min.css deleted file mode 100644 index 8139260f..00000000 --- a/distribute/jquery.nouislider.pips.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! noUiSlider - 7.0.10 - 2014-12-27 14:50:47 */ - - -.noUi-pips,.noUi-pips *{-moz-box-sizing:border-box;box-sizing:border-box}.noUi-pips{position:absolute;font:400 12px Arial;color:#999}.noUi-value{width:40px;position:absolute;text-align:center}.noUi-value-sub{color:#ccc;font-size:10px}.noUi-marker{position:absolute;background:#CCC}.noUi-marker-large,.noUi-marker-sub{background:#AAA}.noUi-pips-horizontal{padding:10px 0;height:50px;top:100%;left:0;width:100%}.noUi-value-horizontal{margin-left:-20px;padding-top:20px}.noUi-value-horizontal.noUi-value-sub{padding-top:15px}.noUi-marker-horizontal.noUi-marker{margin-left:-1px;width:2px;height:5px}.noUi-marker-horizontal.noUi-marker-sub{height:10px}.noUi-marker-horizontal.noUi-marker-large{height:15px}.noUi-pips-vertical{padding:0 10px;height:100%;top:0;left:100%}.noUi-value-vertical{width:15px;margin-left:20px;margin-top:-5px}.noUi-marker-vertical.noUi-marker{width:5px;height:2px;margin-top:-1px}.noUi-marker-vertical.noUi-marker-sub{width:10px}.noUi-marker-vertical.noUi-marker-large{width:15px} \ No newline at end of file diff --git a/distribute/jquery.nouislider.js b/distribute/nouislider.js similarity index 58% rename from distribute/jquery.nouislider.js rename to distribute/nouislider.js index 3644bac4..a86e0518 100644 --- a/distribute/jquery.nouislider.js +++ b/distribute/nouislider.js @@ -1,18 +1,36 @@ -/*! noUiSlider - 7.0.10 - 2014-12-27 14:50:46 */ +/*! noUiSlider - 8.0.0 - 2015-06-29 17:25:17 */ /*jslint browser: true */ /*jslint white: true */ -(function( $ ){ +(function (factory) { + + if ( typeof define === 'function' && define.amd ) { + + // AMD. Register as an anonymous module. + define([], factory); + + } else if ( typeof exports === 'object' ) { + + // Node/CommonJS + module.exports = factory(require('jquery')); + + } else { + + // Browser globals + window.noUiSlider = factory(); + } + +}(function( ){ 'use strict'; // Removes duplicates from an array. function unique(array) { - return $.grep(array, function(el, index) { - return index === $.inArray(el, array); - }); + return array.filter(function(a){ + return !this[a] ? this[a] = true : false; + }, {}); } // Round a value to the closest 'to'. @@ -20,6 +38,28 @@ return Math.round(value / to) * to; } + // Current position of an element relative to the document. + function offset ( elem ) { + + var rect = elem.getBoundingClientRect(), + doc = elem.ownerDocument, + win = doc.defaultView || doc.parentWindow, + docElem = doc.documentElement, + xOff = win.pageXOffset; + + // getBoundingClientRect contains left scroll in Chrome on Android. + // I haven't found a feature detection that proves this. Worst case + // scenario on mis-match: the 'tap' feature on horizontal sliders breaks. + if ( /webkit.*Chrome.*Mobile/i.test(navigator.userAgent) ) { + xOff = 0; + } + + return { + top: rect.top + win.pageYOffset - docElem.clientTop, + left: rect.left + xOff - docElem.clientLeft + }; + } + // Checks whether a value is numerical. function isNumeric ( a ) { return typeof a === 'number' && !isNaN( a ) && isFinite( a ); @@ -33,9 +73,9 @@ // Sets a class and removes it after [duration] ms. function addClassFor ( element, className, duration ) { - element.addClass(className); + addClass(element, className); setTimeout(function(){ - element.removeClass(className); + removeClass(element, className); }, duration); } @@ -46,7 +86,7 @@ // Wraps a variable as an array, if it isn't one yet. function asArray ( a ) { - return $.isArray(a) ? a : [a]; + return Array.isArray(a) ? a : [a]; } // Counts decimals @@ -55,17 +95,35 @@ return pieces.length > 1 ? pieces[1].length : 0; } + // http://youmightnotneedjquery.com/#add_class + function addClass ( el, className ) { + if ( el.classList ) { + el.classList.add(className); + } else { + el.className += ' ' + className; + } + } + + // http://youmightnotneedjquery.com/#remove_class + function removeClass ( el, className ) { + if ( el.classList ) { + el.classList.remove(className); + } else { + el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } + } + + // http://youmightnotneedjquery.com/#has_class + function hasClass ( el, className ) { + if ( el.classList ) { + el.classList.contains(className); + } else { + new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className); + } + } + var - // Cache the document selector; - /** @const */ - doc = $(document), - // Make a backup of the original jQuery/Zepto .val() method. - /** @const */ - $val = $.fn.val, - // Namespace for binding and unbinding slider events; - /** @const */ - namespace = '.nui', // Determine the events to bind. IE11 implements pointerEvents without // a prefix, which breaks compatibility with the IE10 implementation. /** @const */ @@ -386,7 +444,6 @@ or true when everything is OK. It can also modify the option object, to make sure all values can be correctly looped elsewhere. */ - /** @const */ var defaultFormatter = { 'to': function( value ){ return value.toFixed(2); }, 'from': Number }; @@ -405,7 +462,7 @@ function testRange ( parsed, entry ) { // Filter incorrect input. - if ( typeof entry !== 'object' || $.isArray(entry) ) { + if ( typeof entry !== 'object' || Array.isArray(entry) ) { throw new Error("noUiSlider: 'range' is not an object."); } @@ -423,7 +480,7 @@ // Validate input. Values aren't tested, as the public .val method // will always provide a valid location. - if ( !$.isArray( entry ) || !entry.length || entry.length > 2 ) { + if ( !Array.isArray( entry ) || !entry.length || entry.length > 2 ) { throw new Error("noUiSlider: 'start' option is incorrect."); } @@ -590,18 +647,26 @@ 'format': { r: false, t: testFormat } }; - // Set defaults where applicable. - options = $.extend({ + var defaults = { 'connect': false, 'direction': 'ltr', 'behaviour': 'tap', 'orientation': 'horizontal' - }, options); + }; + + // Set defaults where applicable. + Object.keys(defaults).forEach(function ( name ) { + if ( options[name] === undefined ) { + options[name] = defaults[name]; + } + }); // Run all options through a testing mechanism to ensure correct // input. It should be noted that options might get modified to // be handled properly. E.g. wrapping integers in arrays. - $.each( tests, function( name, test ){ + Object.keys(tests).forEach(function( name ){ + + var test = tests[name]; // If the option isn't set, but it is required, throw an error. if ( options[name] === undefined ) { @@ -616,13 +681,15 @@ test.t( parsed, options[name] ); }); + // Forward pips options + parsed.pips = options.pips; + // Pre-define the styles. parsed.style = parsed.ort ? 'top' : 'left'; return parsed; } -// Class handling // Delimit proposed values for handle positions. function getPositions ( a, b, delimit ) { @@ -647,9 +714,6 @@ return [c,d]; } - -// Event handling - // Provide a clean event with standardized offset values. function fixEvent ( e ) { @@ -660,22 +724,16 @@ // 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; + 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'. @@ -684,42 +742,34 @@ } 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; } event.points = [x, y]; - event.cursor = mouse; + event.cursor = mouse || pointer; // Fix #435 return event; } - -// DOM additions - // Append a handle to the base. function addHandle ( direction, index ) { - var handle = $('
').addClass( Classes[2] ), + var origin = document.createElement('div'), + handle = document.createElement('div'), additions = [ '-lower', '-upper' ]; if ( direction ) { additions.reverse(); } - handle.children().addClass( - Classes[3] + " " + Classes[3]+additions[index] - ); + addClass(handle, Classes[3]); + addClass(handle, Classes[3] + additions[index]); - return handle; + addClass(origin, Classes[2]); + origin.appendChild(handle); + + return origin; } // Add the proper connection classes. @@ -730,14 +780,14 @@ // segments listed in the class list, to allow easy // renaming and provide a minor compression benefit. switch ( connect ) { - case 1: target.addClass( Classes[7] ); - handles[0].addClass( Classes[6] ); + case 1: addClass(target, Classes[7]); + addClass(handles[0], Classes[6]); break; - case 3: handles[1].addClass( Classes[6] ); + case 3: addClass(handles[1], Classes[6]); /* falls through */ - case 2: handles[0].addClass( Classes[7] ); + case 2: addClass(handles[0], Classes[7]); /* falls through */ - case 0: target.addClass(Classes[6]); + case 0: addClass(target, Classes[6]); break; } } @@ -751,7 +801,7 @@ for ( index = 0; index < nrHandles; index += 1 ) { // Keep a list of all added handles. - handles.push( addHandle( direction, index ).appendTo(base) ); + handles.push( base.appendChild(addHandle( direction, index )) ); } return handles; @@ -761,268 +811,465 @@ function addSlider ( direction, orientation, target ) { // Apply classes and data to the target. - target.addClass([ - Classes[0], - Classes[8 + direction], - Classes[4 + orientation] - ].join(' ')); - - return $('
').appendTo(target).addClass( Classes[1] ); + addClass(target, Classes[0]); + addClass(target, Classes[8 + direction]); + addClass(target, Classes[4 + orientation]); + + var div = document.createElement('div'); + addClass(div, Classes[1]); + target.appendChild(div); + return div; } -function closure ( target, options, originalOptions ){ -// Internal variables +function closure ( target, options ){ - // All variables local to 'closure' are marked $. - var $Target = $(target), - $Locations = [-1, -1], - $Base, - $Handles, - $Spectrum = options.spectrum, - $Values = [], - // libLink. For rtl sliders, 'lower' and 'upper' should not be inverted - // for one-handle sliders, so trim 'upper' it that case. - triggerPos = ['lower', 'upper'].slice(0, options.handles); + // All variables local to 'closure' are prefixed with 'scope_' + var scope_Target = target, + scope_Locations = [-1, -1], + scope_Base, + scope_Handles, + scope_Spectrum = options.spectrum, + scope_Values = [], + scope_Events = {}; - // Invert the libLink connection for rtl sliders. - if ( options.dir ) { - triggerPos.reverse(); - } -// Helpers + function getGroup ( mode, values, stepped ) { - // Shorthand for base dimensions. - function baseSize ( ) { - return $Base[['width', 'height'][options.ort]](); - } + // Use the range. + if ( mode === 'range' || mode === 'steps' ) { + return scope_Spectrum.xVal; + } - // External event handling - function fireEvents ( events ) { + if ( mode === 'count' ) { + + // Divide 0 - 100 in 'count' parts. + var spread = ( 100 / (values-1) ), v, i = 0; + values = []; - // Use the external api to get the values. - // Wrap the values in an array, as .trigger takes - // only one additional argument. - var index, values = [ $Target.val() ]; + // List these parts and have them handled as 'positions'. + while ((v=i++*spread) <= 100 ) { + values.push(v); + } - for ( index = 0; index < events.length; index += 1 ){ - $Target.trigger(events[index], values); + mode = 'positions'; } - } - // Returns the input array, respecting the slider direction configuration. - function inSliderOrder ( values ) { + if ( mode === 'positions' ) { - // If only one handle is used, return a single value. - if ( values.length === 1 ){ - return values[0]; + // Map all percentages to on-range values. + return values.map(function( value ){ + return scope_Spectrum.fromStepping( stepped ? scope_Spectrum.getStep( value ) : value ); + }); } - if ( options.dir ) { - return values.reverse(); - } + if ( mode === 'values' ) { - return values; - } + // If the value must be stepped, it needs to be converted to a percentage first. + if ( stepped ) { -// libLink integration + return values.map(function( value ){ - // Create a new function which calls .val on input change. - function createChangeHandler ( trigger ) { - return function ( ignore, value ){ - // Determine which array position to 'null' based on 'trigger'. - $Target.val( [ trigger ? null : value, trigger ? value : null ], true ); - }; + // Convert to percentage, apply step, return to value. + return scope_Spectrum.fromStepping( scope_Spectrum.getStep( scope_Spectrum.toStepping( value ) ) ); + }); + + } + + // Otherwise, we can simply use the values. + return values; + } } - // Called by libLink when it wants a set of links updated. - function linkUpdate ( flag ) { + function generateSpread ( density, mode, group ) { + + var originalSpectrumDirection = scope_Spectrum.direction, + indexes = {}, + firstInRange = scope_Spectrum.xVal[0], + lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length-1], + ignoreFirst = false, + ignoreLast = false, + prevPct = 0; - var trigger = $.inArray(flag, triggerPos); + // This function loops the spectrum in an ltr linear fashion, + // while the toStepping method is direction aware. Trick it into + // believing it is ltr. + scope_Spectrum.direction = 0; - // The API might not have been set yet. - if ( $Target[0].linkAPI && $Target[0].linkAPI[flag] ) { - $Target[0].linkAPI[flag].change( - $Values[trigger], - $Handles[trigger].children(), - $Target - ); + // Create a copy of the group, sort it and filter away all duplicates. + group = unique(group.slice().sort(function(a, b){ return a - b; })); + + // Make sure the range starts with the first element. + if ( group[0] !== firstInRange ) { + group.unshift(firstInRange); + ignoreFirst = true; + } + + // Likewise for the last one. + if ( group[group.length - 1] !== lastInRange ) { + group.push(lastInRange); + ignoreLast = true; } + + group.forEach(function ( current, index ) { + + // Get the current step and the lower + upper positions. + var step, i, q, + low = current, + high = group[index+1], + newPct, pctDifference, pctPos, type, + steps, realSteps, stepsize; + + // When using 'steps' mode, use the provided steps. + // Otherwise, we'll step on to the next subrange. + if ( mode === 'steps' ) { + step = scope_Spectrum.xNumSteps[ index ]; + } + + // Default to a 'full' step. + if ( !step ) { + step = high-low; + } + + // Low can be 0, so test for false. If high is undefined, + // we are at the last subrange. Index 0 is already handled. + if ( low === false || high === undefined ) { + return; + } + + // Find all steps in the subrange. + for ( i = low; i <= high; i += step ) { + + // Get the percentage value for the current step, + // calculate the size for the subrange. + newPct = scope_Spectrum.toStepping( i ); + pctDifference = newPct - prevPct; + + steps = pctDifference / density; + realSteps = Math.round(steps); + + // This ratio represents the ammount of percentage-space a point indicates. + // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-devided. + // Round the percentage offset to an even number, then divide by two + // to spread the offset on both sides of the range. + stepsize = pctDifference/realSteps; + + // Divide all points evenly, adding the correct number to this subrange. + // Run up to <= so that 100% gets a point, event if ignoreLast is set. + for ( q = 1; q <= realSteps; q += 1 ) { + + // The ratio between the rounded value and the actual size might be ~1% off. + // Correct the percentage offset by the number of points + // per subrange. density = 1 will result in 100 points on the + // full range, 2 for 50, 4 for 25, etc. + pctPos = prevPct + ( q * stepsize ); + indexes[pctPos.toFixed(5)] = ['x', 0]; + } + + // Determine the point type. + type = (group.indexOf(i) > -1) ? 1 : ( mode === 'steps' ? 2 : 0 ); + + // Enforce the 'ignoreFirst' option by overwriting the type for 0. + if ( !index && ignoreFirst ) { + type = 0; + } + + if ( !(i === high && ignoreLast)) { + // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value. + indexes[newPct.toFixed(5)] = [i, type]; + } + + // Update the percentage count. + prevPct = newPct; + } + }); + + // Reset the spectrum. + scope_Spectrum.direction = originalSpectrumDirection; + + return indexes; } - // Called by libLink to append an element to the slider. - function linkConfirm ( flag, element ) { + function addMarking ( spread, filterFunc, formatter ) { + + var style = ['horizontal', 'vertical'][options.ort], + element = document.createElement('div'); - // Find the trigger for the passed flag. - var trigger = $.inArray(flag, triggerPos); + addClass(element, 'noUi-pips'); + addClass(element, 'noUi-pips-' + style); - // If set, append the element to the handle it belongs to. - if ( element ) { - element.appendTo( $Handles[trigger].children() ); + function getSize( type, value ){ + return [ '-normal', '-large', '-sub' ][type]; } - // The public API is reversed for rtl sliders, so the changeHandler - // should not be aware of the inverted trigger positions. - // On rtl slider with one handle, 'lower' should be used. - if ( options.dir && options.handles > 1 ) { - trigger = trigger === 1 ? 0 : 1; + function getTags( offset, source, values ) { + return 'class="' + source + ' ' + + source + '-' + style + ' ' + + source + getSize(values[1], values[0]) + + '" style="' + options.style + ': ' + offset + '%"'; } - return createChangeHandler( trigger ); - } + function addSpread ( offset, values ){ + + if ( scope_Spectrum.direction ) { + offset = 100 - offset; + } - // Place elements back on the slider. - function reAppendLink ( ) { + // Apply the filter function, if it is set. + values[1] = (values[1] && filterFunc) ? filterFunc(values[0], values[1]) : values[1]; - var i, flag; + // Add a marker for every point + element.innerHTML += '
'; - // The API keeps a list of elements: we can re-append them on rebuild. - for ( i = 0; i < triggerPos.length; i += 1 ) { - if ( this.linkAPI && this.linkAPI[(flag = triggerPos[i])] ) { - this.linkAPI[flag].reconfirm(flag); + // Values are only appended for points marked '1' or '2'. + if ( values[1] ) { + element.innerHTML += '
' + formatter.to(values[0]) + '
'; } } + + // Append all points. + Object.keys(spread).forEach(function(a){ + addSpread(a, spread[a]); + }); + + return element; + } + + function pips ( grid ) { + + var mode = grid.mode, + density = grid.density || 1, + filter = grid.filter || false, + values = grid.values || false, + stepped = grid.stepped || false, + group = getGroup( mode, values, stepped ), + spread = generateSpread( density, mode, group ), + format = grid.format || { + to: Math.round + }; + + return scope_Target.appendChild(addMarking( + spread, + filter, + format + )); + } + + + // Shorthand for base dimensions. + function baseSize ( ) { + return scope_Base['offset' + ['Width', 'Height'][options.ort]]; + } + + // External event handling + function fireEvent ( event, handleNumber ) { + + if ( handleNumber !== undefined ) { + handleNumber = Math.abs(handleNumber - options.dir); + } + + Object.keys(scope_Events).forEach(function( targetEvent ) { + + var eventType = targetEvent.split('.')[0]; + + if ( event === eventType ) { + scope_Events[targetEvent].forEach(function( callback ) { + // .reverse is in place + // Return values as array, so arg_1[arg_2] is always valid. + callback( asArray(valueGet()), handleNumber, inSliderOrder(Array.prototype.slice.call(scope_Values)) ); + }); + } + }); } - target.LinkUpdate = linkUpdate; - target.LinkConfirm = linkConfirm; - target.LinkDefaultFormatter = options.format; - target.LinkDefaultFlag = 'lower'; + // Returns the input array, respecting the slider direction configuration. + function inSliderOrder ( values ) { + + // If only one handle is used, return a single value. + if ( values.length === 1 ){ + return values[0]; + } - target.reappend = reAppendLink; + if ( options.dir ) { + return values.reverse(); + } + + return values; + } // Handler for attaching events trough a proxy. function attach ( events, element, callback, data ) { // This function can be used to 'filter' events to the slider. + // element is a node, not a nodeList - // 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 ){ + var method = function ( e ){ - // jQuery and Zepto (1) handle unset attributes differently, - // but always falsy; #208 - if ( !!$Target.attr('disabled') ) { + if ( scope_Target.hasAttribute('disabled') ) { return false; } // Stop if an active 'tap' transition is taking place. - if ( $Target.hasClass( Classes[14] ) ) { + if ( hasClass(scope_Target, Classes[14]) ) { return false; } e = fixEvent(e); + + // Ignore right or middle clicks on start #454 + if ( events === actions.start && e.buttons !== undefined && e.buttons !== 1 ) { + return false; + } + e.calcPoint = e.points[ options.ort ]; // Call the event handler with the event [ and additional data ]. callback ( e, data ); + + }, methods = []; + + // Bind a closure on the target for every event type. + events.split(' ').forEach(function( eventName ){ + element.addEventListener(eventName, method, false); + methods.push([eventName, method]); }); + + return methods; } // Handle movement on document for handle and range drag. function move ( event, data ) { - var handles = data.handles || $Handles, positions, state = false, + var handles = data.handles || scope_Handles, positions, state = false, proposal = ((event.calcPoint - data.start) * 100) / baseSize(), - h = handles[0][0] !== $Handles[0][0] ? 1 : 0; + handleNumber = handles[0] === scope_Handles[0] ? 0 : 1; // Calculate relative positions for the handles. positions = getPositions( proposal, data.positions, handles.length > 1); - state = setHandle ( handles[0], positions[h], handles.length === 1 ); + state = setHandle ( handles[0], positions[handleNumber], handles.length === 1 ); if ( handles.length > 1 ) { - state = setHandle ( handles[1], positions[h?0:1], false ) || state; - } - // Fire the 'slide' event if any handle moved. - if ( state ) { - fireEvents(['slide']); + state = setHandle ( handles[1], positions[handleNumber?0:1], false ) || state; + + if ( state ) { + // fire for both handles + for ( i = 0; i < data.handles.length; i++ ) { + fireEvent('slide', i); + } + } + } else if ( state ) { + // Fire for a single handle + fireEvent('slide', handleNumber); } } // Unbind move events on document, call callbacks. - function end ( event ) { + function end ( event, data ) { // The handle is no longer active, so remove the class. - $('.' + Classes[15]).removeClass(Classes[15]); + var active = scope_Base.getElementsByClassName(Classes[15]), + handleNumber = data.handles[0] === scope_Handles[0] ? 0 : 1; + + if ( active.length ) { + removeClass(active[0], Classes[15]); + } // Remove cursor styles and text-selection events bound to the body. if ( event.cursor ) { - $('body').css('cursor', '').off( namespace ); + document.body.style.cursor = ''; + document.body.removeEventListener('selectstart', document.body.noUiListener); } + var d = document.documentElement; + // Unbind the move and end events, which are added on 'start'. - doc.off( namespace ); + d.noUiListeners.forEach(function( c ) { + d.removeEventListener(c[0], c[1]); + }); // Remove dragging class. - $Target.removeClass(Classes[12]); + removeClass(scope_Target, Classes[12]); // Fire the change and set events. - fireEvents(['set', 'change']); + fireEvent('set', handleNumber); + fireEvent('change', handleNumber); } // Bind move events on document. function start ( event, data ) { + var d = document.documentElement; + // Mark the handle as 'active' so it can be styled. - if( data.handles.length === 1 ) { - data.handles[0].children().addClass(Classes[15]); + if ( data.handles.length === 1 ) { + addClass(data.handles[0].children[0], Classes[15]); + + // Support 'disabled' handles + if ( data.handles[0].hasAttribute('disabled') ) { + return false; + } } // A drag should never propagate up to the 'tap' event. event.stopPropagation(); - // Attach the move event. - attach ( actions.move, doc, move, { + // Attach the move and end events. + var moveEvent = attach(actions.move, d, move, { start: event.calcPoint, handles: data.handles, positions: [ - $Locations[0], - $Locations[$Handles.length - 1] + scope_Locations[0], + scope_Locations[scope_Handles.length - 1] ] + }), endEvent = attach(actions.end, d, end, { + handles: data.handles }); - // Unbind all movement when the drag ends. - attach ( actions.end, doc, end, null ); + d.noUiListeners = moveEvent.concat(endEvent); // Text selection isn't an issue on touch devices, // so adding cursor styles can be skipped. if ( event.cursor ) { // Prevent the 'I' cursor and extend the range-drag cursor. - $('body').css('cursor', $(event.target).css('cursor')); + document.body.style.cursor = getComputedStyle(event.target).cursor; // Mark the target with a dragging state. - if ( $Handles.length > 1 ) { - $Target.addClass(Classes[12]); + if ( scope_Handles.length > 1 ) { + addClass(scope_Target, Classes[12]); } + var f = function(){ + return false; + }; + + document.body.noUiListener = f; + // Prevent text selection when dragging the handles. - $('body').on('selectstart' + namespace, false); + document.body.addEventListener('selectstart', f, false); } } // Move closest handle to tapped location. function tap ( event ) { - var location = event.calcPoint, total = 0, to; + var location = event.calcPoint, total = 0, handleNumber, to; // The tap event shouldn't propagate up and cause 'edge' to run. event.stopPropagation(); // Add up the handle offsets. - $.each( $Handles, function(){ - total += this.offset()[ options.style ]; + scope_Handles.forEach(function(a){ + total += offset(a)[ options.style ]; }); // Find the handle closest to the tapped position. - total = ( location < total/2 || $Handles.length === 1 ) ? 0 : 1; + handleNumber = ( location < total/2 || scope_Handles.length === 1 ) ? 0 : 1; - location -= $Base.offset()[ options.style ]; + location -= offset(scope_Base)[ options.style ]; // Calculate the new position. to = ( location * 100 ) / baseSize(); @@ -1030,17 +1277,24 @@ function closure ( target, options, originalOptions ){ if ( !options.events.snap ) { // Flag the slider as it is now in a transitional state. // Transition takes 300 ms, so re-enable the slider afterwards. - addClassFor( $Target, Classes[14], 300 ); + addClassFor( scope_Target, Classes[14], 300 ); + } + + // Support 'disabled' handles + if ( scope_Handles[handleNumber].hasAttribute('disabled') ) { + return false; } // Find the closest handle and calculate the tapped point. // The set handle to the new position. - setHandle( $Handles[total], to ); + setHandle( scope_Handles[handleNumber], to ); - fireEvents(['slide', 'set', 'change']); + fireEvent('slide', handleNumber); + fireEvent('set', handleNumber); + fireEvent('change', handleNumber); if ( options.events.snap ) { - start(event, { handles: [$Handles[total]] }); + start(event, { handles: [scope_Handles[total]] }); } } @@ -1052,12 +1306,12 @@ function closure ( target, options, originalOptions ){ // Attach the standard drag event to the handles. if ( !behaviour.fixed ) { - for ( i = 0; i < $Handles.length; i += 1 ) { + for ( i = 0; i < scope_Handles.length; i += 1 ) { // These events are only bound to the visual handle // element, not the 'real' origin element. - attach ( actions.start, $Handles[i].children(), start, { - handles: [ $Handles[i] ] + attach ( actions.start, scope_Handles[i].children[0], start, { + handles: [ scope_Handles[i] ] }); } } @@ -1065,26 +1319,29 @@ function closure ( target, options, originalOptions ){ // Attach the tap event to the slider base. if ( behaviour.tap ) { - attach ( actions.start, $Base, tap, { - handles: $Handles + attach ( actions.start, scope_Base, tap, { + handles: scope_Handles }); } // Make the range dragable. if ( behaviour.drag ){ - drag = $Base.find( '.' + Classes[7] ).addClass( Classes[10] ); + drag = [scope_Base.getElementsByClassName( Classes[7] )[0]]; + addClass(drag[0], Classes[10]); // 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 ( behaviour.fixed ) { - drag = drag.add($Base.children().not( drag ).children()); + drag.push(scope_Handles[(drag[0] === scope_Handles[0] ? 1 : 0)].children[0]); } - attach ( actions.start, drag, start, { - handles: $Handles + drag.forEach(function( element ) { + attach ( actions.start, element, start, { + handles: scope_Handles + }); }); } } @@ -1093,16 +1350,16 @@ function closure ( target, options, originalOptions ){ // Test suggested values and apply margin, step. function setHandle ( handle, to, noLimitOption ) { - var trigger = handle[0] !== $Handles[0][0] ? 1 : 0, - lowerMargin = $Locations[0] + options.margin, - upperMargin = $Locations[1] - options.margin, - lowerLimit = $Locations[0] + options.limit, - upperLimit = $Locations[1] - options.limit; + var trigger = handle !== scope_Handles[0] ? 1 : 0, + lowerMargin = scope_Locations[0] + options.margin, + upperMargin = scope_Locations[1] - options.margin, + lowerLimit = scope_Locations[0] + options.limit, + upperLimit = scope_Locations[1] - options.limit; // For sliders with multiple handles, // limit movement to the other handle. // Apply the margin option by adding it to the handle positions. - if ( $Handles.length > 1 ) { + if ( scope_Handles.length > 1 ) { to = trigger ? Math.max( to, lowerMargin ) : Math.min( to, upperMargin ); } @@ -1110,37 +1367,40 @@ function closure ( target, options, originalOptions ){ // maximum distance from another. Limit must be > 0, as otherwise // handles would be unmoveable. 'noLimitOption' is set to 'false' // for the .val() method, except for pass 4/4. - if ( noLimitOption !== false && options.limit && $Handles.length > 1 ) { + if ( noLimitOption !== false && options.limit && scope_Handles.length > 1 ) { to = trigger ? Math.min ( to, lowerLimit ) : Math.max( to, upperLimit ); } // Handle the step option. - to = $Spectrum.getStep( to ); + to = scope_Spectrum.getStep( to ); // Limit to 0/100 for .val input, trim anything beyond 7 digits, as // JavaScript has some issues in its floating point implementation. to = limit(parseFloat(to.toFixed(7))); // Return false if handle can't move. - if ( to === $Locations[trigger] ) { + if ( to === scope_Locations[trigger] ) { return false; } // Set the handle to the new position. - handle.css( options.style, to + '%' ); + handle.style[options.style] = to + '%'; // Force proper handle stacking - if ( handle.is(':first-child') ) { - handle.toggleClass(Classes[17], to > 50 ); + if ( !handle.previousSibling ) { + removeClass(handle, Classes[17]); + if ( to > 50 ) { + addClass(handle, Classes[17]); + } } // Update locations. - $Locations[trigger] = to; + scope_Locations[trigger] = to; // Convert the value to the slider stepping/range. - $Values[trigger] = $Spectrum.fromStepping( to ); + scope_Values[trigger] = scope_Spectrum.fromStepping( to ); - linkUpdate(triggerPos[trigger]); + fireEvent('update', trigger); return true; } @@ -1178,9 +1438,8 @@ function closure ( target, options, originalOptions ){ // Request an update for all links if the value was invalid. // Do so too if setting the handle fails. - if ( to === false || isNaN(to) || setHandle( $Handles[trigger], $Spectrum.toStepping( to ), i === (3 - options.dir) ) === false ) { - - linkUpdate(triggerPos[trigger]); + if ( to === false || isNaN(to) || setHandle( scope_Handles[trigger], scope_Spectrum.toStepping( to ), i === (3 - options.dir) ) === false ) { + fireEvent('update', trigger); } } } @@ -1189,12 +1448,7 @@ function closure ( target, options, originalOptions ){ // Set the slider value. function valueSet ( input ) { - // LibLink: don't accept new values when currently emitting changes. - if ( $Target[0].LinkIsEmitting ) { - return this; - } - - var count, values = asArray( input ); + var count, values = asArray( input ), i; // The RTL settings is implemented by reversing the front-end, // internal mechanisms are the same. @@ -1203,14 +1457,13 @@ function closure ( target, options, originalOptions ){ } // Animation is optional. - // Make sure the initial values where set before using animated - // placement. (no report, unit testing); - if ( options.animate && $Locations[0] !== -1 ) { - addClassFor( $Target, Classes[14], 300 ); + // Make sure the initial values where set before using animated placement. + if ( options.animate && scope_Locations[0] !== -1 ) { + addClassFor( scope_Target, Classes[14], 300 ); } // Determine how often to set the handles. - count = $Handles.length > 1 ? 3 : 1; + count = scope_Handles.length > 1 ? 3 : 1; if ( values.length === 1 ) { count = 1; @@ -1218,11 +1471,10 @@ function closure ( target, options, originalOptions ){ setValues ( count, values ); - // Fire the 'set' event. As of noUiSlider 7, - // this is no longer optional. - fireEvents(['set']); - - return this; + // Fire the 'set' event for both handles. + for ( i = 0; i < scope_Handles.length; i++ ) { + fireEvent('set', i); + } } // Get the slider value. @@ -1232,33 +1484,20 @@ function closure ( target, options, originalOptions ){ // Get the value from all handles. for ( i = 0; i < options.handles; i += 1 ){ - retour[i] = options.format.to( $Values[i] ); + retour[i] = options.format.to( scope_Values[i] ); } return inSliderOrder( retour ); } - // Destroy the slider and unbind all events. - function destroyTarget ( ) { - - // Unbind events on the slider, remove all classes and child elements. - $(this).off(namespace) - .removeClass(Classes.join(' ')) - .empty(); - - delete this.LinkUpdate; - delete this.LinkConfirm; - delete this.LinkDefaultFormatter; - delete this.LinkDefaultFlag; - delete this.reappend; - delete this.vGet; - delete this.vSet; - delete this.getCurrentStep; - delete this.getInfo; - delete this.destroy; - - // Return the original options from the closure. - return originalOptions; + // Removes classes from the root and empties it. + function destroy ( ) { + Classes.forEach(function(cls){ + if ( !cls ) { return; } // Ignore empty classes + removeClass(scope_Target, cls); + }); + scope_Target.innerHTML = ''; + delete scope_Target.noUiSlider; } // Get the current step size for the slider. @@ -1266,16 +1505,16 @@ function closure ( target, options, originalOptions ){ // Check all locations, map them to their stepping point. // Get the step point, then find it in the input list. - var retour = $.map($Locations, function( location, index ){ + var retour = scope_Locations.map(function( location, index ){ - var step = $Spectrum.getApplicableStep( location ), + var step = scope_Spectrum.getApplicableStep( location ), // As per #391, the comparison for the decrement step can have some rounding issues. // Round the value to the precision used in the step. stepDecimals = countDecimals(String(step[2])), // Get the current numeric value - value = $Values[index], + value = scope_Values[index], // To move the slider 'one step up', the current step value needs to be added. // Use null if we are at the maximum slider value. @@ -1289,152 +1528,97 @@ function closure ( target, options, originalOptions ){ // previous step. Return null if the slider is at its minimum value. decrement = location === 0 ? null : (prev >= step[1]) ? step[2] : (step[0] || false); - return [[decrement, increment]]; + return [decrement, increment]; }); // Return values in the proper order. return inSliderOrder( retour ); } - // Get the original set of options. - function getOriginalOptions ( ) { - return originalOptions; + // Attach an event to this slider, possibly including a namespace + function bindEvent ( namespacedEvent, callback ) { + scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || []; + scope_Events[namespacedEvent].push(callback); + + // If the event bound is 'update,' fire it immediately for all handles. + if ( namespacedEvent.split('.')[0] === 'update' ) { + scope_Handles.forEach(function(a, index){ + fireEvent('update', index); + }); + } } + // Undo attachment of event + function removeEvent ( namespacedEvent ) { + + var event = namespacedEvent.split('.')[0], + namespace = namespacedEvent.substring(event.length); + + Object.keys(scope_Events).forEach(function( bind ){ + + var tEvent = bind.split('.')[0], + tNamespace = bind.substring(tEvent.length); + + if ( (!event || event === tEvent) && (!namespace || namespace === tNamespace) ) { + delete scope_Events[bind]; + } + }); + } -// Initialize slider // Throw an error if the slider was already initialized. - if ( $Target.hasClass(Classes[0]) ) { + if ( scope_Target.noUiSlider ) { throw new Error('Slider was already initialized.'); } + // Create the base element, initialise HTML and set classes. // Add handles and links. - $Base = addSlider( options.dir, options.ort, $Target ); - $Handles = addHandles( options.handles, options.dir, $Base ); + scope_Base = addSlider( options.dir, options.ort, scope_Target ); + scope_Handles = addHandles( options.handles, options.dir, scope_Base ); // Set the connect classes. - addConnection ( options.connect, $Target, $Handles ); + addConnection ( options.connect, scope_Target, scope_Handles ); // Attach user events. events( options.events ); -// Methods - - target.vSet = valueSet; - target.vGet = valueGet; - target.destroy = destroyTarget; - - target.getCurrentStep = getCurrentStep; - target.getOriginalOptions = getOriginalOptions; + if ( options.pips ) { + pips(options.pips); + } - target.getInfo = function(){ - return [ - $Spectrum, - options.style, - options.ort - ]; + return { + destroy: destroy, + steps: getCurrentStep, + on: bindEvent, + off: removeEvent, + get: valueGet, + set: valueSet }; - // Use the public value method to set the start values. - $Target.val( options.start ); - } // Run the standard initializer - function initialize ( originalOptions ) { - - // Test the options once, not for every slider. - var options = testOptions( originalOptions, this ); - - // Loop all items, and provide a new closed-scope environment. - return this.each(function(){ - closure(this, options, originalOptions); - }); - } + function initialize ( target, originalOptions ) { - // Destroy the slider, then re-enter initialization. - function rebuild ( options ) { - - return this.each(function(){ - - // The rebuild flag can be used if the slider wasn't initialized yet. - if ( !this.destroy ) { - $(this).noUiSlider( options ); - return; - } - - // Get the current values from the slider, - // including the initialization options. - var values = $(this).val(), originalOptions = this.destroy(), - - // Extend the previous options with the newly provided ones. - newOptions = $.extend( {}, originalOptions, options ); - - // Run the standard initializer. - $(this).noUiSlider( newOptions ); - - // Place Link elements back. - this.reappend(); - - // If the start option hasn't changed, - // reset the previous values. - if ( originalOptions.start === newOptions.start ) { - $(this).val(values); - } - }); - } - - // Access the internal getting and setting methods based on argument count. - function value ( ) { - return this[0][ !arguments.length ? 'vGet' : 'vSet' ].apply(this[0], arguments); - } - - // Override the .val() method. Test every element. Is it a slider? Go to - // the slider value handling. No? Use the standard method. - // Note how $.fn.val expects 'this' to be an instance of $. For convenience, - // the above 'value' function does too. - $.fn.val = function ( arg ) { - - // this === instanceof $ - - function valMethod( a ){ - return a.hasClass(Classes[0]) ? value : $val; + if ( !target.nodeName ) { + throw new Error('noUiSlider.create requires a single element.'); } - // If no value is passed, this is 'get'. - if ( !arguments.length ) { - var first = $(this[0]); - return valMethod(first).call(first); - } - - var isFunction = $.isFunction(arg); - - // Return the set so it remains chainable. Make sure not to break - // jQuery's .val(function( index, value ){}) signature. - return this.each(function( i ){ - - var val = arg, $t = $(this); + // Test the options and create the slider environment; + var options = testOptions( originalOptions, target ), + slider = closure( target, options ); - if ( isFunction ) { - val = arg.call(this, i, $t.val()); - } - - valMethod($t).call($t, val); - }); - }; + // Use the public value method to set the start values. + slider.set(options.start); -// Extend jQuery/Zepto with the noUiSlider method. - $.fn.noUiSlider = function ( options, rebuildFlag ) { - - switch ( options ) { - case 'step': return this[0].getCurrentStep(); - case 'options': return this[0].getOriginalOptions(); - } + target.noUiSlider = slider; + } - return ( rebuildFlag ? rebuild : initialize ).call(this, options); + // Use an object instead of a function for future expansibility; + return { + create: initialize }; -}( window.jQuery || window.Zepto )); +})); \ No newline at end of file diff --git a/distribute/nouislider.min.css b/distribute/nouislider.min.css new file mode 100644 index 00000000..c4799437 --- /dev/null +++ b/distribute/nouislider.min.css @@ -0,0 +1,4 @@ +/*! noUiSlider - 8.0.0 - 2015-06-29 17:25:17 */ + + +.noUi-target,.noUi-target *{-webkit-touch-callout:none;-webkit-user-select:none;-ms-touch-action:none;-ms-user-select:none;-moz-user-select:none;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-target{position:relative;direction:ltr}.noUi-base{width:100%;height:100%;position:relative;z-index:1}.noUi-origin{position:absolute;right:0;top:0;left:0;bottom:0}.noUi-handle{position:relative;z-index:1}.noUi-stacking .noUi-handle{z-index:10}.noUi-state-tap .noUi-origin{-webkit-transition:left .3s,top .3s;transition:left .3s,top .3s}.noUi-state-drag *{cursor:inherit!important}.noUi-base{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.noUi-horizontal{height:18px}.noUi-horizontal .noUi-handle{width:34px;height:28px;left:-17px;top:-6px}.noUi-vertical{width:18px}.noUi-vertical .noUi-handle{width:28px;height:34px;left:-6px;top:-17px}.noUi-background{background:#FAFAFA;box-shadow:inset 0 1px 1px #f0f0f0}.noUi-connect{background:#3FB8AF;box-shadow:inset 0 0 3px rgba(51,51,51,.45);-webkit-transition:background 450ms;transition:background 450ms}.noUi-origin{border-radius:2px}.noUi-target{border-radius:4px;border:1px solid #D3D3D3;box-shadow:inset 0 1px 1px #F0F0F0,0 3px 6px -5px #BBB}.noUi-target.noUi-connect{box-shadow:inset 0 0 3px rgba(51,51,51,.45),0 3px 6px -5px #BBB}.noUi-dragable{cursor:w-resize}.noUi-vertical .noUi-dragable{cursor:n-resize}.noUi-handle{border:1px solid #D9D9D9;border-radius:3px;background:#FFF;cursor:default;box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #EBEBEB,0 3px 6px -3px #BBB}.noUi-active{box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #DDD,0 3px 6px -3px #BBB}.noUi-handle:after,.noUi-handle:before{content:"";display:block;position:absolute;height:14px;width:1px;background:#E8E7E6;left:14px;top:6px}.noUi-handle:after{left:17px}.noUi-vertical .noUi-handle:after,.noUi-vertical .noUi-handle:before{width:14px;height:1px;left:6px;top:14px}.noUi-vertical .noUi-handle:after{top:17px}[disabled] .noUi-connect,[disabled].noUi-connect{background:#B8B8B8}[disabled] .noUi-handle,[disabled].noUi-origin{cursor:not-allowed}.noUi-pips,.noUi-pips *{-moz-box-sizing:border-box;box-sizing:border-box}.noUi-pips{position:absolute;font:400 12px Arial;color:#999}.noUi-value{width:40px;position:absolute;text-align:center}.noUi-value-sub{color:#ccc;font-size:10px}.noUi-marker{position:absolute;background:#CCC}.noUi-marker-large,.noUi-marker-sub{background:#AAA}.noUi-pips-horizontal{padding:10px 0;height:50px;top:100%;left:0;width:100%}.noUi-value-horizontal{margin-left:-20px;padding-top:20px}.noUi-value-horizontal.noUi-value-sub{padding-top:15px}.noUi-marker-horizontal.noUi-marker{margin-left:-1px;width:2px;height:5px}.noUi-marker-horizontal.noUi-marker-sub{height:10px}.noUi-marker-horizontal.noUi-marker-large{height:15px}.noUi-pips-vertical{padding:0 10px;height:100%;top:0;left:100%}.noUi-value-vertical{width:15px;margin-left:20px;margin-top:-5px}.noUi-marker-vertical.noUi-marker{width:5px;height:2px;margin-top:-1px}.noUi-marker-vertical.noUi-marker-sub{width:10px}.noUi-marker-vertical.noUi-marker-large{width:15px} \ No newline at end of file diff --git a/distribute/nouislider.min.js b/distribute/nouislider.min.js new file mode 100644 index 00000000..baf2e06b --- /dev/null +++ b/distribute/nouislider.min.js @@ -0,0 +1,3 @@ +/*! noUiSlider - 8.0.0 - 2015-06-29 17:25:17 */ + +!function(a){"function"==typeof define&&define.amd?define([],a):"object"==typeof exports?module.exports=a(require("jquery")):window.noUiSlider=a()}(function(){"use strict";function a(a){return a.filter(function(a){return this[a]?!1:this[a]=!0},{})}function b(a,b){return Math.round(a/b)*b}function c(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.defaultView||c.parentWindow,e=c.documentElement,f=d.pageXOffset;return/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)&&(f=0),{top:b.top+d.pageYOffset-e.clientTop,left:b.left+f-e.clientLeft}}function d(a){return"number"==typeof a&&!isNaN(a)&&isFinite(a)}function e(a){var b=Math.pow(10,7);return Number((Math.round(a*b)/b).toFixed(7))}function f(a,b,c){k(a,b),setTimeout(function(){l(a,b)},c)}function g(a){return Math.max(Math.min(a,100),0)}function h(a){return Array.isArray(a)?a:[a]}function j(a){var b=a.split(".");return b.length>1?b[1].length:0}function k(a,b){a.classList?a.classList.add(b):a.className+=" "+b}function l(a,b){a.classList?a.classList.remove(b):a.className=a.className.replace(new RegExp("(^|\\b)"+b.split(" ").join("|")+"(\\b|$)","gi")," ")}function m(a,b){a.classList?a.classList.contains(b):new RegExp("(^| )"+b+"( |$)","gi").test(a.className)}function n(a,b){return 100/(b-a)}function o(a,b){return 100*b/(a[1]-a[0])}function p(a,b){return o(a,a[0]<0?b+Math.abs(a[0]):b-a[0])}function q(a,b){return b*(a[1]-a[0])/100+a[0]}function r(a,b){for(var c=1;a>=b[c];)c+=1;return c}function s(a,b,c){if(c>=a.slice(-1)[0])return 100;var d,e,f,g,h=r(c,a);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],f+p([d,e],c)/n(f,g)}function t(a,b,c){if(c>=100)return a.slice(-1)[0];var d,e,f,g,h=r(c,b);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],q([d,e],(c-f)*n(f,g))}function u(a,c,d,e){if(100===e)return e;var f,g,h=r(e,a);return d?(f=a[h-1],g=a[h],e-f>(g-f)/2?g:f):c[h-1]?a[h-1]+b(e-a[h-1],c[h-1]):e}function v(a,b,c){var e;if("number"==typeof b&&(b=[b]),"[object Array]"!==Object.prototype.toString.call(b))throw new Error("noUiSlider: 'range' contains invalid value.");if(e="min"===a?0:"max"===a?100:parseFloat(a),!d(e)||!d(b[0]))throw new Error("noUiSlider: 'range' value isn't numeric.");c.xPct.push(e),c.xVal.push(b[0]),e?c.xSteps.push(isNaN(b[1])?!1:b[1]):isNaN(b[1])||(c.xSteps[0]=b[1])}function w(a,b,c){return b?void(c.xSteps[a]=o([c.xVal[a],c.xVal[a+1]],b)/n(c.xPct[a],c.xPct[a+1])):!0}function x(a,b,c,d){this.xPct=[],this.xVal=[],this.xSteps=[d||!1],this.xNumSteps=[!1],this.snap=b,this.direction=c;var e,f=[];for(e in a)a.hasOwnProperty(e)&&f.push([a[e],e]);for(f.sort(function(a,b){return a[0]-b[0]}),e=0;e2)throw new Error("noUiSlider: 'start' option is incorrect.");a.handles=b.length,a.start=b}function B(a,b){if(a.snap=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'snap' option must be a boolean.")}function C(a,b){if(a.animate=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'animate' option must be a boolean.")}function D(a,b){if("lower"===b&&1===a.handles)a.connect=1;else if("upper"===b&&1===a.handles)a.connect=2;else if(b===!0&&2===a.handles)a.connect=3;else{if(b!==!1)throw new Error("noUiSlider: 'connect' option doesn't match handle count.");a.connect=0}}function E(a,b){switch(b){case"horizontal":a.ort=0;break;case"vertical":a.ort=1;break;default:throw new Error("noUiSlider: 'orientation' option is invalid.")}}function F(a,b){if(!d(b))throw new Error("noUiSlider: 'margin' option must be numeric.");if(a.margin=a.spectrum.getMargin(b),!a.margin)throw new Error("noUiSlider: 'margin' option is only supported on linear sliders.")}function G(a,b){if(!d(b))throw new Error("noUiSlider: 'limit' option must be numeric.");if(a.limit=a.spectrum.getMargin(b),!a.limit)throw new Error("noUiSlider: 'limit' option is only supported on linear sliders.")}function H(a,b){switch(b){case"ltr":a.dir=0;break;case"rtl":a.dir=1,a.connect=[0,2,1,3][a.connect];break;default:throw new Error("noUiSlider: 'direction' option was not recognized.")}}function I(a,b){if("string"!=typeof b)throw new Error("noUiSlider: 'behaviour' must be a string containing options.");var c=b.indexOf("tap")>=0,d=b.indexOf("drag")>=0,e=b.indexOf("fixed")>=0,f=b.indexOf("snap")>=0;a.events={tap:c||f,drag:d,fixed:e,snap:f}}function J(a,b){if(a.format=b,"function"==typeof b.to&&"function"==typeof b.from)return!0;throw new Error("noUiSlider: 'format' requires 'to' and 'from' methods.")}function K(a){var b,c={margin:0,limit:0,animate:!0,format:V};b={step:{r:!1,t:y},start:{r:!0,t:A},connect:{r:!0,t:D},direction:{r:!0,t:H},snap:{r:!1,t:B},animate:{r:!1,t:C},range:{r:!0,t:z},orientation:{r:!1,t:E},margin:{r:!1,t:F},limit:{r:!1,t:G},behaviour:{r:!0,t:I},format:{r:!1,t:J}};var d={connect:!1,direction:"ltr",behaviour:"tap",orientation:"horizontal"};return Object.keys(d).forEach(function(b){void 0===a[b]&&(a[b]=d[b])}),Object.keys(b).forEach(function(d){var e=b[d];if(void 0===a[d]){if(e.r)throw new Error("noUiSlider: '"+d+"' is required.");return!0}e.t(c,a[d])}),c.pips=a.pips,c.style=c.ort?"top":"left",c}function L(a,b,c){var d=a+b[0],e=a+b[1];return c?(0>d&&(e+=Math.abs(d)),e>100&&(d-=e-100),[g(d),g(e)]):[d,e]}function M(a){a.preventDefault();var b,c,d=0===a.type.indexOf("touch"),e=0===a.type.indexOf("mouse"),f=0===a.type.indexOf("pointer"),g=a;return 0===a.type.indexOf("MSPointer")&&(f=!0),d&&(b=a.changedTouches[0].pageX,c=a.changedTouches[0].pageY),(e||f)&&(b=a.clientX+window.pageXOffset,c=a.clientY+window.pageYOffset),g.points=[b,c],g.cursor=e||f,g}function N(a,b){var c=document.createElement("div"),d=document.createElement("div"),e=["-lower","-upper"];return a&&e.reverse(),k(d,U[3]),k(d,U[3]+e[b]),k(c,U[2]),c.appendChild(d),c}function O(a,b,c){switch(a){case 1:k(b,U[7]),k(c[0],U[6]);break;case 3:k(c[1],U[6]);case 2:k(c[0],U[7]);case 0:k(b,U[6])}}function P(a,b,c){var d,e=[];for(d=0;a>d;d+=1)e.push(c.appendChild(N(b,d)));return e}function Q(a,b,c){k(c,U[0]),k(c,U[8+a]),k(c,U[4+b]);var d=document.createElement("div");return k(d,U[1]),c.appendChild(d),d}function R(b,d){function e(a,b,c){if("range"===a||"steps"===a)return N.xVal;if("count"===a){var d,e=100/(b-1),f=0;for(b=[];(d=f++*e)<=100;)b.push(d);a="positions"}return"positions"===a?b.map(function(a){return N.fromStepping(c?N.getStep(a):a)}):"values"===a?c?b.map(function(a){return N.fromStepping(N.getStep(N.toStepping(a)))}):b:void 0}function n(b,c,d){var e=N.direction,f={},g=N.xVal[0],h=N.xVal[N.xVal.length-1],i=!1,j=!1,k=0;return N.direction=0,d=a(d.slice().sort(function(a,b){return a-b})),d[0]!==g&&(d.unshift(g),i=!0),d[d.length-1]!==h&&(d.push(h),j=!0),d.forEach(function(a,e){var g,h,l,m,n,o,p,q,r,s,t=a,u=d[e+1];if("steps"===c&&(g=N.xNumSteps[e]),g||(g=u-t),t!==!1&&void 0!==u)for(h=t;u>=h;h+=g){for(m=N.toStepping(h),n=m-k,q=n/b,r=Math.round(q),s=n/r,l=1;r>=l;l+=1)o=k+l*s,f[o.toFixed(5)]=["x",0];p=d.indexOf(h)>-1?1:"steps"===c?2:0,!e&&i&&(p=0),h===u&&j||(f[m.toFixed(5)]=[h,p]),k=m}}),N.direction=e,f}function o(a,b,c){function e(a){return["-normal","-large","-sub"][a]}function f(a,b,c){return'class="'+b+" "+b+"-"+h+" "+b+e(c[1],c[0])+'" style="'+d.style+": "+a+'%"'}function g(a,d){N.direction&&(a=100-a),d[1]=d[1]&&b?b(d[0],d[1]):d[1],i.innerHTML+="
",d[1]&&(i.innerHTML+="
"+c.to(d[0])+"
")}var h=["horizontal","vertical"][d.ort],i=document.createElement("div");return k(i,"noUi-pips"),k(i,"noUi-pips-"+h),Object.keys(a).forEach(function(b){g(b,a[b])}),i}function p(a){var b=a.mode,c=a.density||1,d=a.filter||!1,f=a.values||!1,g=a.stepped||!1,h=e(b,f,g),i=n(c,b,h),j=a.format||{to:Math.round};return J.appendChild(o(i,d,j))}function q(){return H["offset"+["Width","Height"][d.ort]]}function r(a,b){void 0!==b&&(b=Math.abs(b-d.dir)),Object.keys(S).forEach(function(c){var d=c.split(".")[0];a===d&&S[c].forEach(function(a){a(h(C()),b,s(Array.prototype.slice.call(R)))})})}function s(a){return 1===a.length?a[0]:d.dir?a.reverse():a}function t(a,b,c,e){var f=function(b){return J.hasAttribute("disabled")?!1:m(J,U[14])?!1:(b=M(b),a===T.start&&void 0!==b.buttons&&1!==b.buttons?!1:(b.calcPoint=b.points[d.ort],void c(b,e)))},g=[];return a.split(" ").forEach(function(a){b.addEventListener(a,f,!1),g.push([a,f])}),g}function u(a,b){var c,d=b.handles||I,e=!1,f=100*(a.calcPoint-b.start)/q(),g=d[0]===I[0]?0:1;if(c=L(f,b.positions,d.length>1),e=z(d[0],c[g],1===d.length),d.length>1){if(e=z(d[1],c[g?0:1],!1)||e)for(i=0;i1&&k(J,U[12]);var f=function(){return!1};document.body.noUiListener=f,document.body.addEventListener("selectstart",f,!1)}}function x(a){var b,e,g=a.calcPoint,h=0;return a.stopPropagation(),I.forEach(function(a){h+=c(a)[d.style]}),b=h/2>g||1===I.length?0:1,g-=c(H)[d.style],e=100*g/q(),d.events.snap||f(J,U[14],300),I[b].hasAttribute("disabled")?!1:(z(I[b],e),r("slide",b),r("set",b),r("change",b),void(d.events.snap&&w(a,{handles:[I[h]]})))}function y(a){var b,c;if(!a.fixed)for(b=0;b1&&(b=e?Math.max(b,f):Math.min(b,h)),c!==!1&&d.limit&&I.length>1&&(b=e?Math.min(b,i):Math.max(b,j)),b=N.getStep(b),b=g(parseFloat(b.toFixed(7))),b===K[e]?!1:(a.style[d.style]=b+"%",a.previousSibling||(l(a,U[17]),b>50&&k(a,U[17])),K[e]=b,R[e]=N.fromStepping(b),r("update",e),!0)}function A(a,b){var c,e,f;for(d.limit&&(a+=1),c=0;a>c;c+=1)e=c%2,f=b[e],null!==f&&f!==!1&&("number"==typeof f&&(f=String(f)),f=d.format.from(f),(f===!1||isNaN(f)||z(I[e],N.toStepping(f),c===3-d.dir)===!1)&&r("update",e))}function B(a){var b,c,e=h(a);for(d.dir&&d.handles>1&&e.reverse(),d.animate&&-1!==K[0]&&f(J,U[14],300),b=I.length>1?3:1,1===e.length&&(b=1),A(b,e),c=0;c=c[1]?c[2]:c[0]||!1;return[h,f]});return s(a)}function F(a,b){S[a]=S[a]||[],S[a].push(b),"update"===a.split(".")[0]&&I.forEach(function(a,b){r("update",b)})}function G(a){var b=a.split(".")[0],c=a.substring(b.length);Object.keys(S).forEach(function(a){var d=a.split(".")[0],e=a.substring(d.length);b&&b!==d||c&&c!==e||delete S[a]})}var H,I,J=b,K=[-1,-1],N=d.spectrum,R=[],S={};if(J.noUiSlider)throw new Error("Slider was already initialized.");return H=Q(d.dir,d.ort,J),I=P(d.handles,d.dir,H),O(d.connect,J,I),y(d.events),d.pips&&p(d.pips),{destroy:D,steps:E,on:F,off:G,get:C,set:B}}function S(a,b){if(!a.nodeName)throw new Error("noUiSlider.create requires a single element.");var c=K(b,a),d=R(a,c);d.set(c.start),a.noUiSlider=d}var T=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"},U=["noUi-target","noUi-base","noUi-origin","noUi-handle","noUi-horizontal","noUi-vertical","noUi-background","noUi-connect","noUi-ltr","noUi-rtl","noUi-dragable","","noUi-state-drag","","noUi-state-tap","noUi-active","","noUi-stacking"];x.prototype.getMargin=function(a){return 2===this.xPct.length?o(this.xVal,a):!1},x.prototype.toStepping=function(a){return a=s(this.xVal,this.xPct,a),this.direction&&(a=100-a),a},x.prototype.fromStepping=function(a){return this.direction&&(a=100-a),e(t(this.xVal,this.xPct,a))},x.prototype.getStep=function(a){return this.direction&&(a=100-a),a=u(this.xPct,this.xSteps,this.snap,a),this.direction&&(a=100-a),a},x.prototype.getApplicableStep=function(a){var b=r(a,this.xPct),c=100===a?2:1;return[this.xNumSteps[b-2],this.xVal[b-c],this.xNumSteps[b-c]]},x.prototype.convert=function(a){return this.getStep(this.toStepping(a))};var V={to:function(a){return a.toFixed(2)},from:Number};return{create:S}}); \ No newline at end of file diff --git a/documentation/README.md b/documentation/README.md new file mode 100644 index 00000000..2921f623 --- /dev/null +++ b/documentation/README.md @@ -0,0 +1 @@ +# t.b.a. diff --git a/documentation/_run/404.php b/documentation/_run/404.php new file mode 100644 index 00000000..0b18740c --- /dev/null +++ b/documentation/_run/404.php @@ -0,0 +1,6 @@ + + +Oops, this page is missing. diff --git a/documentation/_run/helpers.php b/documentation/_run/helpers.php new file mode 100644 index 00000000..b840122e --- /dev/null +++ b/documentation/_run/helpers.php @@ -0,0 +1,32 @@ +' . $c . ''; + } + + function run ( $name ){ + echo "\r\n".''; + } + + function loadShowCSS ( $name ) { + + $content = fgc($name . '.css'); + + echo "\r\n".'' . + '
' . $content . '
'; + } + + function sect ( $title ) { + echo '§'; + } diff --git a/documentation/_run/index.php b/documentation/_run/index.php new file mode 100644 index 00000000..9b52f011 --- /dev/null +++ b/documentation/_run/index.php @@ -0,0 +1,64 @@ + + + + + + + + <?php echo $title; ?> | Refreshless.com + + + + + + + + + + + + + + + + +
+ +

noUiSlider

+

JavaScript Range Slider

+ +
+ +
+ + + + Download noUiSlider +
+
+ + + + + +
+ +
+ + + + + + + + diff --git a/documentation/_run/menu.php b/documentation/_run/menu.php new file mode 100644 index 00000000..ca83072a --- /dev/null +++ b/documentation/_run/menu.php @@ -0,0 +1,12 @@ + diff --git a/documentation/_run/router.php b/documentation/_run/router.php new file mode 100644 index 00000000..616fc383 --- /dev/null +++ b/documentation/_run/router.php @@ -0,0 +1,34 @@ + strong { + display: block; + margin-top: 10px; + } + + .example { + position: relative; + padding: 20px 60px 50px 30px; + margin: 20px 0; + overflow: hidden; + } + .example-val { + font: 400 12px Arial; + color: #888; + display: block; + margin: 15px 0; + } + .example-val:before { + content: "Value: "; + font: 700 12px Arial; + } + .example.vertical { + width: 120px; + } + .example.vertical .noUi-target { + height: 150px; + } + + .before-example ~ .example { + margin-top: 0; + } + .before-example ~ .example.vertical .noUi-target { + height: 220px; + } + + .quick { + max-width: 550px; + margin: 0 auto; + } + .quick .noUi-target { + max-width: 300px; + margin: 20px auto 30px; + } + .quick pre { + background: #F3F3F3 !important; + padding: 10px 30px 25px; + margin: 10px auto; + border: 1px solid #BDBDBD; + } + + .logger { + overflow: hidden; + margin-top: 20px; + text-align: center; + } + .logger div { + background-color: #FFF; + -webkit-transition: all 0.25s; + transition: all 0.25s; + padding: 0 5px; + display: inline-block; + margin: 0 2px; + font: 700 10px/26px Arial; + color: #BBB; + text-transform: uppercase; + text-align: center; + border-radius: 4px; + border: 1px solid #ddd; + } + .logger div.tShow { + background-color: #008CBA; + color: #FFF; + } + .logger button { + display: inline-block; + margin: 2px; + } + + .pro-list { + max-width: 300px; + font-size: 17px; + margin: 30px; + list-style: none; + padding: 0; + } + .pro-list li { + margin-bottom: 5px; + position: relative; + } + .pro-list li:before { + content:"\2713\0020"; + display: block; + font-size: 21px; + position: absolute; + left: -22px; + top: 50%; + margin-top: -14px; + color: Teal; + } + + .data-table td { + padding: 10px; + vertical-align: top; + } + .data-table td:first-child, + .data-table th:first-child { + text-align: right; + } + + .styling-table { + table-layout: fixed; + width: 80%; + text-align: left; + } + .styling-table th { + padding: 10px; + } + + .events-table { + width: 100%; + table-layout: fixed; + text-align: center; + } + .events-no { + color: #fff; + } + .events-yes { + text-indent: -9999px; + } + .events-yes span { + display: block; + border-radius: 999px; + width: 10px; + height: 10px; + margin: 0 auto; + background: #95C4B0; + } + + .section-link { + float: left; + color: #999; + padding-right: 10px; + display: block; + font-size: 32px; + text-decoration: none; + } + .section-link:hover { + color: #333; + } + + .button { + background: #9b59b6; + display: table; + text-decoration: none; + margin: 30px auto; + font-size: 19px; + padding: 13px 25px; + text-align: center; + clear: left; + color: #FFF; + } + .button:active { + box-shadow: inset 0 3px 5px rgba(0,0,0,0.125); + } + + .share { + margin: 30px auto; + width: 300px; + } + .quotable { + font-style: italic; + color: #00A0B0; + font-size: 24px; + font-weight: 400; + } + + .index-demo { + padding: 50px 30px; + background: #2980b9; + } + .index-demo h1 { + text-align: center; + font-weight: 700; + font-size: 40px; + color: #fff; + margin: 0; + } + .index-demo h2 { + text-align: center; + color: #fff; + } + .index-demo-dl { + color: #FFF; + font-size: 22px; + letter-spacing: -1px; + text-decoration: none; + display: table; + border-bottom: 1px solid #FFF; + margin: 30px auto 10px; + text-shadow: 0 1px rgba(0,0,0,0.3); + } + + .index-demo, .bar-group, .button { + box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16), 0 2px 5px 0 rgba(0, 0, 0, 0.26); + } + +@media ( min-width: 800px ) { + + .index-demo { + padding: 100px 0 60px; + } + .index-demo h1 { + line-height: 100%; + font-family: Trebuchet MS; + font-size: 100px; + margin: 0 auto; + } + .index-demo h2 { + text-align: right; + font-size: 28px; + margin: -10px auto 30px; + padding-right: 35px; + font-size: 20px; + font-family: Courier; + max-width: 480px; + } +} + +@media ( min-width: 1100px ) { + + .view, .side, .view-more { + display: table-cell; + vertical-align: top; + } + .view { + width: 490px; + padding: 10px 70px 10px 0; + } + .view p { + max-width: 690px; + } + .view-more { + width: 690px; + padding: 10px 70px 10px 0; + } +} + +@media ( max-width: 800px ) { + + /* Break inline code */ + :not(pre) > code[class*="language-"] { + white-space: pre-wrap; + } + + .content { + padding: 20px; + } +} diff --git a/documentation/assets/prism.css b/documentation/assets/prism.css new file mode 100644 index 00000000..e643c21e --- /dev/null +++ b/documentation/assets/prism.css @@ -0,0 +1,137 @@ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + +code[class*="language-"], +pre[class*="language-"] { + color: black; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, pre[class*="language-"] ::selection, +code[class*="language-"]::selection, code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + diff --git a/documentation/assets/prism.js b/documentation/assets/prism.js new file mode 100644 index 00000000..4ba6d68a --- /dev/null +++ b/documentation/assets/prism.js @@ -0,0 +1,6 @@ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */ +self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(d instanceof a)){u.lastIndex=0;var m=u.exec(d);if(m){c&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),N=[p,1];b&&N.push(b);var O=new a(l,g?t.tokenize(m,g):m,h);N.push(O),w&&N.push(w),Array.prototype.splice.apply(r,N)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("Array"===t.util.type(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var i={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code;self.postMessage(JSON.stringify(t.util.encode(t.tokenize(r,t.languages[a])))),self.close()},!1),self.Prism):self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);; +Prism.languages.markup={comment://,prolog:/<\?.+?\?>/,doctype://,cdata://i,tag:{pattern:/<\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/=|>|"/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.hooks.add("wrap",function(t){"entity"===t.type&&(t.attributes.title=t.content.replace(/&/,"&"))});; +Prism.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{punctuation:/[;:]/}},url:/url\((?:(["'])(\\\n|\\?.)*?\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/,string:/("|')(\\\n|\\?.)*?\1/,property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,punctuation:/[\{\};:]/,"function":/[-a-z0-9]+(?=\()/i},Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/[\w\W]*?<\/style>/i,inside:{tag:{pattern:/|<\/style>/i,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css},alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag));; +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:/("|')(\\[\s\S]|(?!\1)[^\\])*\1/,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":{pattern:/[a-z0-9_]+\(/i,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|~|\^|%/,ignore:/&(lt|gt|amp);/i,punctuation:/[{}[\];(),.:]/};; +Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/(?!\d)[a-z0-9_$]+(?=\()/i}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),Prism.languages.insertBefore("javascript","class-name",{"template-string":{pattern:/`(?:\\`|\\?[^`])*`/,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/i,inside:{tag:{pattern:/|<\/script>/i,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript},alias:"language-javascript"}});; diff --git a/documentation/assets/wNumb.js b/documentation/assets/wNumb.js new file mode 100644 index 00000000..722b6291 --- /dev/null +++ b/documentation/assets/wNumb.js @@ -0,0 +1,335 @@ +(function(){ + + 'use strict'; + +var +/** @const */ FormatOptions = [ + 'decimals', + 'thousand', + 'mark', + 'prefix', + 'postfix', + 'encoder', + 'decoder', + 'negativeBefore', + 'negative', + 'edit', + 'undo' +]; + +// General + + // Reverse a string + function strReverse ( a ) { + return a.split('').reverse().join(''); + } + + // Check if a string starts with a specified prefix. + function strStartsWith ( input, match ) { + return input.substring(0, match.length) === match; + } + + // Check is a string ends in a specified postfix. + function strEndsWith ( input, match ) { + return input.slice(-1 * match.length) === match; + } + + // Throw an error if formatting options are incompatible. + function throwEqualError( F, a, b ) { + if ( (F[a] || F[b]) && (F[a] === F[b]) ) { + throw new Error(a); + } + } + + // Check if a number is finite and not NaN + function isValidNumber ( input ) { + return typeof input === 'number' && isFinite( input ); + } + + // Provide rounding-accurate toFixed method. + function toFixed ( value, decimals ) { + var scale = Math.pow(10, decimals); + return ( Math.round(value * scale) / scale).toFixed( decimals ); + } + + +// Formatting + + // Accept a number as input, output formatted string. + function formatTo ( decimals, thousand, mark, prefix, postfix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { + + var originalInput = input, inputIsNegative, inputPieces, inputBase, inputDecimals = '', output = ''; + + // Apply user encoder to the input. + // Expected outcome: number. + if ( encoder ) { + input = encoder(input); + } + + // Stop if no valid number was provided, the number is infinite or NaN. + if ( !isValidNumber(input) ) { + return false; + } + + // Rounding away decimals might cause a value of -0 + // when using very small ranges. Remove those cases. + if ( decimals !== false && parseFloat(input.toFixed(decimals)) === 0 ) { + input = 0; + } + + // Formatting is done on absolute numbers, + // decorated by an optional negative symbol. + if ( input < 0 ) { + inputIsNegative = true; + input = Math.abs(input); + } + + // Reduce the number of decimals to the specified option. + if ( decimals !== false ) { + input = toFixed( input, decimals ); + } + + // Transform the number into a string, so it can be split. + input = input.toString(); + + // Break the number on the decimal separator. + if ( input.indexOf('.') !== -1 ) { + inputPieces = input.split('.'); + + inputBase = inputPieces[0]; + + if ( mark ) { + inputDecimals = mark + inputPieces[1]; + } + + } else { + + // If it isn't split, the entire number will do. + inputBase = input; + } + + // Group numbers in sets of three. + if ( thousand ) { + inputBase = strReverse(inputBase).match(/.{1,3}/g); + inputBase = strReverse(inputBase.join( strReverse( thousand ) )); + } + + // If the number is negative, prefix with negation symbol. + if ( inputIsNegative && negativeBefore ) { + output += negativeBefore; + } + + // Prefix the number + if ( prefix ) { + output += prefix; + } + + // Normal negative option comes after the prefix. Defaults to '-'. + if ( inputIsNegative && negative ) { + output += negative; + } + + // Append the actual number. + output += inputBase; + output += inputDecimals; + + // Apply the postfix. + if ( postfix ) { + output += postfix; + } + + // Run the output through a user-specified post-formatter. + if ( edit ) { + output = edit ( output, originalInput ); + } + + // All done. + return output; + } + + // Accept a sting as input, output decoded number. + function formatFrom ( decimals, thousand, mark, prefix, postfix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { + + var originalInput = input, inputIsNegative, output = ''; + + // User defined pre-decoder. Result must be a non empty string. + if ( undo ) { + input = undo(input); + } + + // Test the input. Can't be empty. + if ( !input || typeof input !== 'string' ) { + return false; + } + + // If the string starts with the negativeBefore value: remove it. + // Remember is was there, the number is negative. + if ( negativeBefore && strStartsWith(input, negativeBefore) ) { + input = input.replace(negativeBefore, ''); + inputIsNegative = true; + } + + // Repeat the same procedure for the prefix. + if ( prefix && strStartsWith(input, prefix) ) { + input = input.replace(prefix, ''); + } + + // And again for negative. + if ( negative && strStartsWith(input, negative) ) { + input = input.replace(negative, ''); + inputIsNegative = true; + } + + // Remove the postfix. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice + if ( postfix && strEndsWith(input, postfix) ) { + input = input.slice(0, -1 * postfix.length); + } + + // Remove the thousand grouping. + if ( thousand ) { + input = input.split(thousand).join(''); + } + + // Set the decimal separator back to period. + if ( mark ) { + input = input.replace(mark, '.'); + } + + // Prepend the negative symbol. + if ( inputIsNegative ) { + output += '-'; + } + + // Add the number + output += input; + + // Trim all non-numeric characters (allow '.' and '-'); + output = output.replace(/[^0-9\.\-.]/g, ''); + + // The value contains no parse-able number. + if ( output === '' ) { + return false; + } + + // Covert to number. + output = Number(output); + + // Run the user-specified post-decoder. + if ( decoder ) { + output = decoder(output); + } + + // Check is the output is valid, otherwise: return false. + if ( !isValidNumber(output) ) { + return false; + } + + return output; + } + + +// Framework + + // Validate formatting options + function validate ( inputOptions ) { + + var i, optionName, optionValue, + filteredOptions = {}; + + for ( i = 0; i < FormatOptions.length; i+=1 ) { + + optionName = FormatOptions[i]; + optionValue = inputOptions[optionName]; + + if ( optionValue === undefined ) { + + // Only default if negativeBefore isn't set. + if ( optionName === 'negative' && !filteredOptions.negativeBefore ) { + filteredOptions[optionName] = '-'; + // Don't set a default for mark when 'thousand' is set. + } else if ( optionName === 'mark' && filteredOptions.thousand !== '.' ) { + filteredOptions[optionName] = '.'; + } else { + filteredOptions[optionName] = false; + } + + // Floating points in JS are stable up to 7 decimals. + } else if ( optionName === 'decimals' ) { + if ( optionValue >= 0 && optionValue < 8 ) { + filteredOptions[optionName] = optionValue; + } else { + throw new Error(optionName); + } + + // These options, when provided, must be functions. + } else if ( optionName === 'encoder' || optionName === 'decoder' || optionName === 'edit' || optionName === 'undo' ) { + if ( typeof optionValue === 'function' ) { + filteredOptions[optionName] = optionValue; + } else { + throw new Error(optionName); + } + + // Other options are strings. + } else { + + if ( typeof optionValue === 'string' ) { + filteredOptions[optionName] = optionValue; + } else { + throw new Error(optionName); + } + } + } + + // Some values can't be extracted from a + // string if certain combinations are present. + throwEqualError(filteredOptions, 'mark', 'thousand'); + throwEqualError(filteredOptions, 'prefix', 'negative'); + throwEqualError(filteredOptions, 'prefix', 'negativeBefore'); + + return filteredOptions; + } + + // Pass all options as function arguments + function passAll ( options, method, input ) { + var i, args = []; + + // Add all options in order of FormatOptions + for ( i = 0; i < FormatOptions.length; i+=1 ) { + args.push(options[FormatOptions[i]]); + } + + // Append the input, then call the method, presenting all + // options as arguments. + args.push(input); + return method.apply('', args); + } + + /** @constructor */ + function wNumb ( options ) { + + if ( !(this instanceof wNumb) ) { + return new wNumb ( options ); + } + + if ( typeof options !== "object" ) { + return; + } + + options = validate(options); + + // Call 'formatTo' with proper arguments. + this.to = function ( input ) { + return passAll(options, formatTo, input); + }; + + // Call 'formatFrom' with proper arguments. + this.from = function ( input ) { + return passAll(options, formatFrom, input); + }; + } + + /** @export */ + window.wNumb = wNumb; + +}()); diff --git a/documentation/behaviour-option.php b/documentation/behaviour-option.php index e107be71..0b906624 100644 --- a/documentation/behaviour-option.php +++ b/documentation/behaviour-option.php @@ -22,7 +22,6 @@
- @@ -67,6 +66,7 @@

Tap

+

A handle snaps to a clicked location. A smooth transition is used. This option is default.

@@ -74,6 +74,7 @@
+
@@ -84,13 +85,15 @@

Drag

+
-

Makes the range dragable. Requires two handles.

+

Makes the range dragable. Requires two handles. The slide event fires for both handles.

+
@@ -101,6 +104,7 @@

Fixed dragging

+

Keeps the distance between handles fixed when the 'drag' flag is set.

@@ -108,6 +112,7 @@
+
@@ -118,6 +123,7 @@

Snap

+

A handle snaps to a clicked location. It can immediatly be moved, without a mouseup + mousedown.

@@ -125,6 +131,7 @@
+
@@ -135,6 +142,7 @@

Combined options

+

Most 'behaviour' flags can be combined.

@@ -142,6 +150,7 @@
+
diff --git a/documentation/behaviour-option/behaviour-option.js b/documentation/behaviour-option/behaviour-option.js index 3b439687..7f4225fc 100644 --- a/documentation/behaviour-option/behaviour-option.js +++ b/documentation/behaviour-option/behaviour-option.js @@ -1,4 +1,6 @@ -$("#behaviour").noUiSlider({ +behaviourSlider = document.getElementById('behaviour'); + +noUiSlider.create(behaviourSlider, { start: [ 20, 40 ], step: 10, behaviour: 'drag', diff --git a/documentation/behaviour-option/combined.js b/documentation/behaviour-option/combined.js index 736d655c..a4f9e211 100644 --- a/documentation/behaviour-option/combined.js +++ b/documentation/behaviour-option/combined.js @@ -1,4 +1,6 @@ -$("#combined").noUiSlider({ +dragTapSlider = document.getElementById('combined'); + +noUiSlider.create(dragTapSlider, { start: [ 40, 60 ], behaviour: 'drag-tap', connect: true, diff --git a/documentation/behaviour-option/drag-fixed.js b/documentation/behaviour-option/drag-fixed.js index 34e21e98..d5752c08 100644 --- a/documentation/behaviour-option/drag-fixed.js +++ b/documentation/behaviour-option/drag-fixed.js @@ -1,4 +1,6 @@ -$("#drag-fixed").noUiSlider({ +dragFixedSlider = document.getElementById('drag-fixed'); + +noUiSlider.create(dragFixedSlider, { start: [ 40, 60 ], behaviour: 'drag-fixed', connect: true, diff --git a/documentation/behaviour-option/drag.js b/documentation/behaviour-option/drag.js index 83b3589e..f3c570ee 100644 --- a/documentation/behaviour-option/drag.js +++ b/documentation/behaviour-option/drag.js @@ -1,4 +1,6 @@ -$("#drag").noUiSlider({ +var dragSlider = document.getElementById('drag'); + +noUiSlider.create(dragSlider, { start: [ 40, 60 ], behaviour: 'drag', connect: true, diff --git a/documentation/behaviour-option/snap.js b/documentation/behaviour-option/snap.js index 82390531..e1d828cc 100644 --- a/documentation/behaviour-option/snap.js +++ b/documentation/behaviour-option/snap.js @@ -1,4 +1,6 @@ -$("#snap").noUiSlider({ +snapSlider = document.getElementById('snap'); + +noUiSlider.create(snapSlider, { start: 40, behaviour: 'snap', connect: 'lower', diff --git a/documentation/behaviour-option/tap.js b/documentation/behaviour-option/tap.js index 3d7764b0..830180ab 100644 --- a/documentation/behaviour-option/tap.js +++ b/documentation/behaviour-option/tap.js @@ -1,4 +1,6 @@ -$("#tap").noUiSlider({ +tapSlider = document.getElementById('tap'); + +noUiSlider.create(tapSlider, { start: 40, behaviour: 'tap', connect: 'upper', diff --git a/documentation/contact.php b/documentation/contact.php index 22890fbe..08f51e5f 100644 --- a/documentation/contact.php +++ b/documentation/contact.php @@ -17,7 +17,6 @@

If you need more general help, you'll usually get you answer by posting a question on StackOverflow. I'll keep an eye on the questions there, as well.

- diff --git a/documentation/download.php b/documentation/download.php index a69bbfd5..96710bb9 100644 --- a/documentation/download.php +++ b/documentation/download.php @@ -5,39 +5,30 @@

Download noUiSlider

- -

Download

-
-

noUiSlider is open source, and you can use it for free in any personal or commercial product. No attribution required. Both the uncompressed and compressed version of noUiSlider are available in a .zip release, which is hosted by Github and available over https.

Download noUiSlider from Github - - -
-

Repository

-
- -
- -

You can also visit the repository: noUiSlider on gitHub. If you need help implementing noUiSlider in your website, or if you'd like to see a new feature, feel free to ask me on twitter: @LeonGersen.

-
- -
+ Help and contact +
+ Release information about the latest Version +
+ Run the unit tests: range and slider.
@@ -49,19 +40,17 @@

You can use noUiSlider for free, under the terms of the WTFPL, which allows everything and has no additional restrictions.

- -
-

Changelog

+

Repository

-

With every release of noUiSlider, a changelog is included in the repository readme on GitHub.

+

You can also visit the repository: noUiSlider on gitHub. If you need help implementing noUiSlider in your website, or if you'd like to see a new feature, feel free to ask me on twitter: @LeonGersen.

- -
+ + diff --git a/documentation/events-callbacks.php b/documentation/events-callbacks.php index ab2e5bbb..1b00b2f0 100644 --- a/documentation/events-callbacks.php +++ b/documentation/events-callbacks.php @@ -9,13 +9,14 @@
-

noUiSlider offers several ways to listen to interaction: 'change', 'set' and 'slide'. You can use these events all at the same time.

+

noUiSlider offers several ways to listen to interaction: 'update', 'change', 'set' and 'slide'. You can use these events all at the same time.

+
Update
Slide
Set
Change
@@ -23,10 +24,12 @@
- +
+ +
@@ -34,41 +37,47 @@   - Slide - Set - Change + Update + Slide + Set + Change A handle is released after dragging - No - Yes - Yes + Yes + No + Yes + Yes A slider is moved by tapping it - Yes - Yes - Yes + Yes + Yes + Yes + Yes A handle moves while dragging - Yes - No - No + Yes + Yes + No + No - A linked input field changes - No - Yes - No + The .set() method is called + Yes + No + Yes + No - The .val() method is called - No - Yes - No + When bound using the .on() method + Yes + No + No + No @@ -76,73 +85,89 @@
+
Temporary set a class
+
+ +
-
Setting up the slider and buttons
+
Setting up the slider
+ +
Bind button and input
+ +
+ +
+
- -

Slide

+ +

Binding

-

This event is useful when you want to update a value or perform an actions every time a handle is dragged. For example, you can use the 'slide' event to update graphs. For convenience, this function also fires on a change by 'tap'.

+

noUiSlider uses a custom binding model with support for namespaces. The event system looks similar to jQuery's. There are two methods, .on( eventName, callback ) and .off( eventName ). Events can be namespaced by appending a period ('.') and an identifier to the event name.

+ +

Nested namespaces ('slide.something.else') are not supported, and are threated as a single namespace (so '.a.b' isn't related to '.a').

-

Alternative available: noUiSlider has a support for the powerful libLink library, which probably does everything you need slide for, such as displaying numbers in text labels or input fields. Additionally, it can also format the slider output. Read more about libLink.

+

Event callbacks receive three arguments. values is always an array, for both one-handle and two-handle sliders. It contains the current slider values, with formatting applied. handle is 0 or 1 and indicates the handle that caused the event. values[handle] gives the value for the current handle. Should you need it, unencodedValues contains the slider values without any formatting.

+ + +
- -

Set

+ +

Update

-

Whenever a slider is changed to a new value, this event is fired. This function will trigger every time a slider stops changing, including after calls to the .val() method. You can consider this 'end of slide'.

+

Use this event when synchronising the slider value to another element, such as an <input>. It fires anytime the slider is changed. Additionally, it fires immediately when bound.

-
- -

Change

+ +

Slide

-

This event is great when you use the slider as 'just-another-input-type'. When your slider is part of a form, you can keep listening to the form change events, without using any events specific to the slider.

- -

Please note: The slider does not fire the change event when an input linked by libLink is changed. Therefore, those fields can be in the same form, without triggering a change event twice.

+

This event is useful when you want to update a value or perform an actions every time a handle is dragged. For example, you can use the 'slide' event to update graphs. For convenience, this function also fires on a change by 'tap'.

- -

Passing functions as arguments

+ +

Set

+

Whenever a slider is changed to a new value, this event is fired. This function will trigger every time a slider stops changing, including after calls to the .val() method. You can consider this 'end of slide'.

+
-

For a full documentation on binding events, have a look at the jQuery .on() documentation.

+
-

In JavaScript, there are multiple ways of providing a function as an argument. In any case, the slider that triggered the event will be the scope of the function, so you can use $(this) to access it again.

-

If you'd like to know more about function declarations, this StackOverflow question is a good starting point.

-
+ +

Change

-
- +
+ +
+

This event is similar to the change events on regular <input> elements. It fires when a user stops sliding, or when a slider value is changed by 'tap'.

diff --git a/documentation/events-callbacks/binding-events.js b/documentation/events-callbacks/binding-events.js index a0effb39..60be4f90 100644 --- a/documentation/events-callbacks/binding-events.js +++ b/documentation/events-callbacks/binding-events.js @@ -1,11 +1,20 @@ -$("#slider-events").on({ - slide: function(){ - $("#l-slide").tShow(450); - }, - set: function(){ - $("#l-set").tShow(450); - }, - change: function(){ - $("#l-change").tShow(450); - } +var lUpdate = document.getElementById('l-update'), + lSlide = document.getElementById('l-slide'), + lSet = document.getElementById('l-set'), + lChange = document.getElementById('l-change'); + +slider.noUiSlider.on('update', function(){ + addClassFor(lUpdate, 'tShow', 450); +}); + +slider.noUiSlider.on('slide', function(){ + addClassFor(lSlide, 'tShow', 450); +}); + +slider.noUiSlider.on('set', function(){ + addClassFor(lSet, 'tShow', 450); +}); + +slider.noUiSlider.on('change', function(){ + addClassFor(lChange, 'tShow', 450); }); diff --git a/documentation/events-callbacks/binding.js b/documentation/events-callbacks/binding.js new file mode 100644 index 00000000..d925caa9 --- /dev/null +++ b/documentation/events-callbacks/binding.js @@ -0,0 +1,18 @@ +// Binding signature +slider.noUiSlider.on(eventName, function ( + values, // Current slider values + handle, // Handle that caused the event + unencodedValues // Slider values without formatting. + ){ + // code + }); + +// Binding namespaced events +slider.noUiSlider.on('set.one', function(){}); +slider.noUiSlider.on('change.one', function(){}); + +// Remove all events in the 'one' namespace. +slider.noUiSlider.off('.one'); + +// Remove all 'change' events in any namespace. +slider.noUiSlider.off('change'); diff --git a/documentation/events-callbacks/buttoninput.js b/documentation/events-callbacks/buttoninput.js new file mode 100644 index 00000000..7878a40f --- /dev/null +++ b/documentation/events-callbacks/buttoninput.js @@ -0,0 +1,13 @@ +setter.addEventListener('click', function(){ + slider.noUiSlider.set([5, 15]); +}); + +slider.noUiSlider.on('update', function ( values, handle ) { + if ( handle == 0 ) { + inputLog.value = values[handle]; + } +}); + +inputLog.addEventListener('change', function ( ) { + slider.noUiSlider.set([null, this.value]); +}); diff --git a/documentation/events-callbacks/class.js b/documentation/events-callbacks/class.js new file mode 100644 index 00000000..3c55ac2c --- /dev/null +++ b/documentation/events-callbacks/class.js @@ -0,0 +1,6 @@ +function addClassFor ( element, className, duration ) { + element.classList.add(className); + setTimeout(function(){ + element.classList.remove(className); + }, duration); +} diff --git a/documentation/events-callbacks/demo.js b/documentation/events-callbacks/demo.js index 59c173d4..4b5699db 100644 --- a/documentation/events-callbacks/demo.js +++ b/documentation/events-callbacks/demo.js @@ -1,20 +1,11 @@ -$.fn.tShow = function(x){ - var s = $(this).addClass('tShow'); - setTimeout(function(){ - s.removeClass('tShow'); - },x); -}; +var slider = document.getElementById('slider-events'), + setter = document.getElementById('setter'), + inputLog = document.getElementById('input-log'); -$("#setter1").click(function(){ - $("#slider-events").val([ 5, 15 ]); -}); - -$("#slider-events").noUiSlider({ +noUiSlider.create(slider, { start: [ 0, 10 ], range: { 'min': [ 0 ], 'max': [ 20 ] } }); - -$("#slider-events").Link('lower').to($("#input-log")); diff --git a/documentation/examples.php b/documentation/examples.php index 1c264725..25daa0f0 100644 --- a/documentation/examples.php +++ b/documentation/examples.php @@ -3,6 +3,22 @@ $description = "noUiSlider has a selection of examples you can use to implement a slider easily. Take a look!"; ?> +
+ +
+

Colorpicker

@@ -18,7 +34,7 @@
-
+
@@ -52,6 +68,55 @@
+
CSS
+ +
+ +
+ +
+ + + + +

Custom connect

+ +
+ +
+ +

When using the connect option, noUiSlider paints the connecting bar in the negative space between handles. This uses one less element and has some nice performance benefits. When you need more control over the connecting option, you can create a custom connecting bar using the update event.

+ +

This custom element can be styled, or special features (like requested in this issue) can be implemented.

+ +
+
+ + +
+
+ +
+ +
Create the slider
+ +
+ +
+ + +
Create a connecting bar and bind it
+ +
+ +
+ + +
CSS for the connecting bar
+ +
+ +
@@ -96,6 +161,12 @@
+ +
Example CSS
+ +
+ +
@@ -144,7 +215,7 @@
-

Using serialization, cross-updating values will results in an infinite loop of updates. To prevent this, each Link has the option to disable synchronisation.

+

Two cross-updating sliders can be created using a combination of the change and slide events.

@@ -153,13 +224,12 @@
- + - - +
@@ -183,12 +253,6 @@
-
Binding the set event
- -
- -
-
Linking the sliders together
@@ -205,11 +269,11 @@
-

To keep the plugin small, features like keyboard interaction haven't been included. However, adding custom features to the input fields linked to the plugin is easy. noUiSlider provides API's to help you. In this example, pressing the keyboard arrow keys will increase/decrease the slider by one step.

+

To keep the library small, features like keyboard interaction haven't been included. However, adding features to input fields linked to a slider is easy. noUiSlider provides API's to help you. In this example, pressing the keyboard arrow keys will increase/decrease the slider by one step.

This example uses the 'step' API to determine by how much the slider should be changed. You don't need this function if your slider is linear. In that case, increase/decrease the value with the ammount of your step.

-

We'll listen to keydown on the $('#input-with-keypress') element, and pass the event to a function so we can read the code that identifies the key.

+

We'll listen to keydown on the '#input-with-keypress' element, and pass the event to a function so we can read the code that identifies the key.

Note that the slider value will be a string, so we'll need to parse it to an integer.

@@ -281,7 +345,7 @@
-

As all dates in JavaScript can be represented as time, noUiSlider can handle them, too. This example will show you how to convert dates to numerical ranges, and then use the serialization feature to display them in a pretty format.

+

As all dates in JavaScript can be represented as time, noUiSlider can handle them, too. This example will show you how to convert dates to numerical ranges, and then use the update event to display them in a pretty format.

We'll be creating timestamps from strings. In order to do this easily, we'll define a new helper function. This function accepts a string, creates a new Date and then returns it as a timestamp.

@@ -337,7 +401,7 @@

Many application interfaces have options that can be turned on or off using switches. noUiSlider is well suited for this, especially because of the wide touch support.

-

The serialization option can be used to keep track of changes to the handle. We'll set the range to [0, 1], which leaves one step of 1.

+

The update event can be used to keep track of changes to the handle. We'll set the range to [0, 1], which leaves one step of 1.

@@ -356,13 +420,7 @@
CSS
-
.toggle {
-	height: 50px;
-}
-.toggle.off .noUi-handle {
-	border-color: red;
-}
-
+
@@ -376,16 +434,13 @@
-

Using the libLink feature, noUiSlider can provided handles with tooltips. These tooltips can be styled and modified on the fly, as demonstrated in this example.

- -

A basic tooltip implementation is part of the libLink implementation.

+

Using the update event, noUiSlider can provided handles with tooltips. These tooltips can be styled and modified on the fly, as demonstrated in this example.

The noUiSlider theme includes no tooltip styling, so by default, the values will resemble the handle on the left.

-
@@ -398,13 +453,7 @@
-
Basic in-handle value
- -
- -
- -
Tooltips with custom HTML
+
Add tooltips
@@ -413,24 +462,7 @@
Example tooltip styling
-
.tooltip {
-	display: block;
-	position: absolute;
-	border: 1px solid #D9D9D9;
-	font: 400 12px/12px Arial;
-	border-radius: 3px;
-	background: #fff;
-	top: -43px;
-	padding: 5px;
-	left: -9px;
-	text-align: center;
-	width: 50px;
-}
-.tooltip strong {
-	display: block;
-	padding: 2px;
-}
-
+
@@ -466,4 +498,4 @@
- \ No newline at end of file + diff --git a/documentation/examples/colorpicker-setcolor.js b/documentation/examples/colorpicker-setcolor.js index a27c176b..98dac3d1 100644 --- a/documentation/examples/colorpicker-setcolor.js +++ b/documentation/examples/colorpicker-setcolor.js @@ -3,13 +3,11 @@ function setColor(){ // Get the slider values, // stick them together. var color = 'rgb(' + - $("#red").val() + ',' + - $("#green").val() + ',' + - $("#blue").val() + ')'; + sliders[0].noUiSlider.get() + ',' + + sliders[1].noUiSlider.get() + ',' + + sliders[2].noUiSlider.get() + ')'; // Fill the color box. - $(".result").css({ - background: color, - color: color - }); + resultElement.style.background = color; + resultElement.style.color = color; } diff --git a/documentation/examples/colorpicker-slider.js b/documentation/examples/colorpicker-slider.js index 1d4174df..34a264e1 100644 --- a/documentation/examples/colorpicker-slider.js +++ b/documentation/examples/colorpicker-slider.js @@ -1,16 +1,22 @@ -$('.sliders').noUiSlider({ - start: 127, - connect: "lower", - orientation: "vertical", - range: { - 'min': 0, - 'max': 255 - }, - format: wNumb({ - decimals: 0 - }) -}); +var resultElement = document.getElementById('result'), + sliders = document.getElementsByClassName('sliders'); -// Bind the color changing function -// to the slide event. -$('.sliders').on('slide', setColor); +for ( var i = 0; i < sliders.length; i++ ) { + + noUiSlider.create(sliders[i], { + start: 127, + connect: "lower", + orientation: "vertical", + range: { + 'min': 0, + 'max': 255 + }, + format: wNumb({ + decimals: 0 + }) + }); + + // Bind the color changing function + // to the slide event. + sliders[i].noUiSlider.on('slide', setColor); +} diff --git a/documentation/examples/colorpicker.css b/documentation/examples/colorpicker.css new file mode 100644 index 00000000..f35787b5 --- /dev/null +++ b/documentation/examples/colorpicker.css @@ -0,0 +1,37 @@ +#red, #green, #blue { + margin: 10px; + display: inline-block; + height: 200px; +} + +#colorpicker { + height: 240px; + width: 310px; + margin: 0 auto; + padding: 10px; + border: 1px solid #BFBFBF; +} + +#result { + margin: 60px 26px; + height: 100px; + width: 100px; + display: inline-block; + vertical-align: top; + color: rgb(127, 127, 127); + background: rgb(127, 127, 127); + border: 1px solid #fff; + box-shadow: 0 0 10px; +} + +#red { + background: #c0392b; +} + +#green { + background: #27ae60; +} + +#blue { + background: #2980b9; +} diff --git a/documentation/examples/colorpicker.php b/documentation/examples/colorpicker.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/custom-connect-slider.js b/documentation/examples/custom-connect-slider.js new file mode 100644 index 00000000..4a6b9ae2 --- /dev/null +++ b/documentation/examples/custom-connect-slider.js @@ -0,0 +1,10 @@ +var connectSlider = document.getElementById('connect'); + +noUiSlider.create(connectSlider, { + start: [20, 80], + connect: false, + range: { + 'min': 0, + 'max': 100 + } +}); diff --git a/documentation/examples/custom-connect.css b/documentation/examples/custom-connect.css new file mode 100644 index 00000000..9e38d89c --- /dev/null +++ b/documentation/examples/custom-connect.css @@ -0,0 +1,21 @@ +/* For this slider, disable the 'origin' size. */ +#connect .noUi-origin { + right: auto; + width: 0; +} + +/* Position the bar and color it. */ +#connect .connect { + position: absolute; + top: 0; + bottom: 0; + background: #80C9F5; + box-shadow: inset 0 0 3px rgba(51,51,51,0.45); +} + +/* When the slider is moved by tap, + transition the connect bar like the handle. */ +#connect.noUi-state-tap .connect { +-webkit-transition: left 300ms, right 300ms; + transition: left 300ms, right 300ms; +} diff --git a/documentation/examples/custom-connect.js b/documentation/examples/custom-connect.js new file mode 100644 index 00000000..e958dc11 --- /dev/null +++ b/documentation/examples/custom-connect.js @@ -0,0 +1,22 @@ +var connectBar = document.createElement('div'), + connectBase = connectSlider.getElementsByClassName('noUi-base')[0], + connectHandles = connectSlider.getElementsByClassName('noUi-origin'); + +// Give the bar a class for styling and add it to the slider. +connectBar.className += 'connect'; +connectBase.appendChild(connectBar); + +connectSlider.noUiSlider.on('update', function( values, handle ) { + + // Pick left for the first handle, right for the second. + var side = handle ? 'right' : 'left', + // Get the handle position and trim the '%' sign. + offset = (connectHandles[handle].style.left).slice(0, - 1); + + // Right offset is 100% - left offset + if ( handle === 1 ) { + offset = 100 - offset; + } + + connectBar.style[side] = offset + '%'; +}); diff --git a/documentation/examples/date-helpers.js b/documentation/examples/date-helpers.js index 53425fbd..d4817501 100644 --- a/documentation/examples/date-helpers.js +++ b/documentation/examples/date-helpers.js @@ -31,8 +31,3 @@ function formatDate ( date ) { months[date.getMonth()] + " " + date.getFullYear(); } - -// Write a date as a pretty value. -function setDate( value ){ - $(this).html(formatDate(new Date(+value))); -} diff --git a/documentation/examples/date-link.js b/documentation/examples/date-link.js index 53bf3905..93f28f80 100644 --- a/documentation/examples/date-link.js +++ b/documentation/examples/date-link.js @@ -1,3 +1,8 @@ -$("#slider-date").Link('lower').to($("#event-start"), setDate); +var dateValues = [ + document.getElementById('event-start'), + document.getElementById('event-end') +]; -$("#slider-date").Link('upper').to($("#event-end"), setDate); +dateSlider.noUiSlider.on('update', function( values, handle ) { + dateValues[handle].innerHTML = formatDate(new Date(+values[handle])); +}); diff --git a/documentation/examples/date-setup.js b/documentation/examples/date-setup.js index 97fd514b..f38f7fa9 100644 --- a/documentation/examples/date-setup.js +++ b/documentation/examples/date-setup.js @@ -1,16 +1,18 @@ -$("#slider-date").noUiSlider({ +var dateSlider = document.getElementById('slider-date'); + +noUiSlider.create(dateSlider, { // Create two timestamps to define a range. range: { min: timestamp('2010'), max: timestamp('2016') }, - + // Steps of one week step: 7 * 24 * 60 * 60 * 1000, - + // Two more timestamps indicate the handle starting positions. start: [ timestamp('2011'), timestamp('2015') ], - + // No decimals format: wNumb({ decimals: 0 diff --git a/documentation/examples/html5-append.js b/documentation/examples/html5-append.js index 005bc250..851c724c 100644 --- a/documentation/examples/html5-append.js +++ b/documentation/examples/html5-append.js @@ -1,6 +1,11 @@ +var select = document.getElementById('input-select'); + // Append the option elements for ( var i = -20; i <= 40; i++ ){ - $('#input-select').append( - '' - ); + + var option = document.createElement("option"); + option.text = i; + option.value = i; + + select.appendChild(option); } diff --git a/documentation/examples/html5-input.php b/documentation/examples/html5-input.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/html5-link.js b/documentation/examples/html5-link.js index 7eef322f..feed0c04 100644 --- a/documentation/examples/html5-link.js +++ b/documentation/examples/html5-link.js @@ -1,6 +1,20 @@ -// A select element can't show any decimals -$('#html5').Link('lower').to($('#input-select'), null, wNumb({ - decimals: 0 -})); +var inputNumber = document.getElementById('input-number'); -$('#html5').Link('upper').to($('#input-number')); +html5Slider.noUiSlider.on('update', function( values, handle ) { + + var value = values[handle]; + + if ( handle ) { + inputNumber.value = value; + } else { + select.value = Math.round(value); + } +}); + +select.addEventListener('change', function(){ + html5Slider.noUiSlider.set([this.value, null]); +}); + +inputNumber.addEventListener('change', function(){ + html5Slider.noUiSlider.set([null, this.value]); +}); diff --git a/documentation/examples/html5-slider.js b/documentation/examples/html5-slider.js index 2cff68af..c9b47c4e 100644 --- a/documentation/examples/html5-slider.js +++ b/documentation/examples/html5-slider.js @@ -1,4 +1,6 @@ -$('#html5').noUiSlider({ +var html5Slider = document.getElementById('html5'); + +noUiSlider.create(html5Slider, { start: [ 10, 30 ], connect: true, range: { diff --git a/documentation/examples/html5.css b/documentation/examples/html5.css new file mode 100644 index 00000000..c534ca33 --- /dev/null +++ b/documentation/examples/html5.css @@ -0,0 +1,6 @@ +#input-select, +#input-number { + padding: 7px; + margin: 15px 5px 5px; + width: 70px; +} diff --git a/documentation/examples/interlock.php b/documentation/examples/interlock.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/keyboard.php b/documentation/examples/keyboard.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/keypress-event.js b/documentation/examples/keypress-event.js index de20e7e4..7d447b3a 100644 --- a/documentation/examples/keypress-event.js +++ b/documentation/examples/keypress-event.js @@ -1,9 +1,9 @@ // Listen to keydown events on the input field. -input.keydown(function( e ) { +input.addEventListener('keydown', function( e ) { // Convert the string to a number. - var value = Number( slider.val() ), - sliderStep = slider.noUiSlider('step'); + var value = Number( slider.noUiSlider.get() ), + sliderStep = slider.noUiSlider.steps() // Select the stepping for the first handle. sliderStep = sliderStep[0]; @@ -13,11 +13,11 @@ input.keydown(function( e ) { // 40 is key down. switch ( e.which ) { case 13: - $(this).change(); + slider.noUiSlider.set(this.value); break; - case 38: slider.val( value + sliderStep[1] ); + case 38: slider.noUiSlider.set( value + sliderStep[1] ); break; - case 40: slider.val( value - sliderStep[0] ); + case 40: slider.noUiSlider.set( value - sliderStep[0] ); break; } }); diff --git a/documentation/examples/keypress-slider.js b/documentation/examples/keypress-slider.js index ba738a98..86da2fb9 100644 --- a/documentation/examples/keypress-slider.js +++ b/documentation/examples/keypress-slider.js @@ -1,7 +1,7 @@ -var slider = $('#keypress'), - input = $('#input-with-keypress'); +var slider = document.getElementById('keypress'), + input = document.getElementById('input-with-keypress'); -slider.noUiSlider({ +noUiSlider.create(slider, { start: 40, step: 10, range: { @@ -12,4 +12,10 @@ slider.noUiSlider({ } }); -slider.Link('lower').to(input); +slider.noUiSlider.on('update', function( values, handle ) { + input.value = values[handle]; +}); + +input.addEventListener('change', function(){ + slider.noUiSlider.set([null, this.value]); +}); diff --git a/documentation/examples/locked-crossupdate.js b/documentation/examples/locked-crossupdate.js index fd835332..d3f4987b 100644 --- a/documentation/examples/locked-crossupdate.js +++ b/documentation/examples/locked-crossupdate.js @@ -1,4 +1,4 @@ -function crossUpdate ( value, handle, slider ) { +function crossUpdate ( value, slider ) { // If the sliders aren't interlocked, don't // cross-update. @@ -6,12 +6,11 @@ function crossUpdate ( value, handle, slider ) { // Select whether to increase or decrease // the other slider value. - var lValue = slider1.is(slider) ? 1 : 0, - hValue = lValue ? 0 : 1; + var a = slider1 === slider ? 0 : 1, b = a ? 0 : 1; - // Modify the slider value. - value -= ( values[hValue] - values[lValue] ); + // Offset the slider value. + value -= lockedValues[b] - lockedValues[a]; // Set the value - $(this).val( value ); + slider.noUiSlider.set(value); } diff --git a/documentation/examples/locked-event.js b/documentation/examples/locked-event.js deleted file mode 100644 index 34e0b6af..00000000 --- a/documentation/examples/locked-event.js +++ /dev/null @@ -1,11 +0,0 @@ -// When a slider changes, store the new values. -$(".slider").on('set', function(){ - - // The .val() function returns a string, - // but we wan't to do substractions, so - // convert the values to numbers. - values = [ - Number(slider1.val()), - Number(slider2.val()) - ]; -}); diff --git a/documentation/examples/locked-link.js b/documentation/examples/locked-link.js index c6680827..9e8760d9 100644 --- a/documentation/examples/locked-link.js +++ b/documentation/examples/locked-link.js @@ -1,10 +1,21 @@ +function setLockedValues ( ) { + lockedValues = [ + Number(slider1.noUiSlider.get()), + Number(slider2.noUiSlider.get()) + ]; +} + +slider1.noUiSlider.on('change', setLockedValues); +slider2.noUiSlider.on('change', setLockedValues); + // The value will be send to the other slider, // using a custom function as the serialization // method. The function uses the global 'lockedState' // variable to decide whether the other slider is updated. +slider1.noUiSlider.on('slide', function( values, handle ){ + crossUpdate(values[handle], slider2); +}); -slider1.Link('lower').to(slider2, crossUpdate); -slider1.Link('lower').to($("#slider1-span")); - -slider2.Link('lower').to(slider1, crossUpdate); -slider2.Link('lower').to($("#slider2-span")); +slider2.noUiSlider.on('slide', function( values, handle ){ + crossUpdate(values[handle], slider1); +}); diff --git a/documentation/examples/locked-setup.js b/documentation/examples/locked-setup.js index 5aa46465..0520fd04 100644 --- a/documentation/examples/locked-setup.js +++ b/documentation/examples/locked-setup.js @@ -1,12 +1,16 @@ // Store the locked state and slider values. var lockedState = false, - values = [60, 80], - slider1 = $("#slider1"), - slider2 = $("#slider2"); + lockedSlider = false, + lockedValues = [60, 80], + slider1 = document.getElementById('slider1'), + slider2 = document.getElementById('slider2'), + lockButton = document.getElementById('lockbutton'), + slider1Value = document.getElementById('slider1-span'), + slider2Value = document.getElementById('slider2-span'); // When the button is clicked, the locked // state is inverted. -$("button").click(function(){ +lockButton.addEventListener('click', function(){ lockedState = !lockedState; - $(this).text(lockedState ? 'unlock' : 'lock'); + this.textContent = lockedState ? 'unlock' : 'lock'; }); diff --git a/documentation/examples/locked-sliders.js b/documentation/examples/locked-sliders.js index 0918befe..162a4f2f 100644 --- a/documentation/examples/locked-sliders.js +++ b/documentation/examples/locked-sliders.js @@ -1,6 +1,6 @@ -slider1.noUiSlider({ +noUiSlider.create(slider1, { start: 60, - + // Disable animation on value-setting, // so the sliders respond immediately. animate: false, @@ -10,7 +10,7 @@ slider1.noUiSlider({ } }); -slider2.noUiSlider({ +noUiSlider.create(slider2, { start: 80, animate: false, range: { @@ -18,3 +18,11 @@ slider2.noUiSlider({ max: 100 } }); + +slider1.noUiSlider.on('update', function( values, handle ){ + slider1Value.innerHTML = values[handle]; +}); + +slider2.noUiSlider.on('update', function( values, handle ){ + slider2Value.innerHTML = values[handle]; +}); diff --git a/documentation/examples/non-linear.php b/documentation/examples/non-linear.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/nonlinear-link.js b/documentation/examples/nonlinear-link.js index 778dc1ab..7b1d4978 100644 --- a/documentation/examples/nonlinear-link.js +++ b/documentation/examples/nonlinear-link.js @@ -1,16 +1,20 @@ // Write the CSS 'left' value to a span. -function leftValue ( value, handle, slider ) { - $(this).text( handle.parent()[0].style.left ); +function leftValue ( handle ) { + return handle.parentElement.style.left; } -// Bind two elements to the lower handle. -// The first item will display the slider value, -// the second shows how far the handle moved -// from the left edge of the slider. -$("#nonlinear").Link('lower').to($('#lower-value')); -$("#nonlinear").Link('lower').to($('#lower-offset'), leftValue); - +var lowerValue = document.getElementById('lower-value'), + lowerOffset = document.getElementById('lower-offset'), + upperValue = document.getElementById('upper-value'), + upperOffset = document.getElementById('upper-offset'), + handles = nonLinearSlider.getElementsByClassName('noUi-handle'); -// Do the same for the upper handle. -$("#nonlinear").Link('upper').to($('#upper-value')); -$("#nonlinear").Link('upper').to($('#upper-offset'), leftValue); +// Display the slider value and how far the handle moved +// from the left edge of the slider. +nonLinearSlider.noUiSlider.on('update', function ( values, handle ) { + if ( !handle ) { + lowerValue.innerHTML = values[handle] + ', ' + leftValue(handles[handle]); + } else { + upperValue.innerHTML = values[handle] + ', ' + leftValue(handles[handle]); + } +}); diff --git a/documentation/examples/nonlinear-slider.js b/documentation/examples/nonlinear-slider.js index e0d454fa..552f2bdf 100644 --- a/documentation/examples/nonlinear-slider.js +++ b/documentation/examples/nonlinear-slider.js @@ -1,4 +1,6 @@ -$("#nonlinear").noUiSlider({ +var nonLinearSlider = document.getElementById('nonlinear'); + +noUiSlider.create(nonLinearSlider, { connect: true, behaviour: 'tap', start: [ 500, 4000 ], diff --git a/documentation/examples/skipping-steps.php b/documentation/examples/skipping-steps.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/skipstep-link.js b/documentation/examples/skipstep-link.js index 730cc1ec..d5c0afbe 100644 --- a/documentation/examples/skipstep-link.js +++ b/documentation/examples/skipstep-link.js @@ -1,3 +1,8 @@ -$("#skipstep").Link('lower').to($("#skip-value-lower")); +var skipValues = [ + document.getElementById('skip-value-lower'), + document.getElementById('skip-value-upper') +]; -$("#skipstep").Link('upper').to($("#skip-value-upper")); +skipSlider.noUiSlider.on('update', function( values, handle ) { + skipValues[handle].innerHTML = values[handle]; +}); diff --git a/documentation/examples/skipstep-slider.js b/documentation/examples/skipstep-slider.js index 1d985968..2899e93d 100644 --- a/documentation/examples/skipstep-slider.js +++ b/documentation/examples/skipstep-slider.js @@ -1,4 +1,6 @@ -$("#skipstep").noUiSlider({ +var skipSlider = document.getElementById('skipstep'); + +noUiSlider.create(skipSlider, { range: { 'min': 0, '10%': 10, diff --git a/documentation/examples/slider-soft-setup.js b/documentation/examples/slider-soft-setup.js index 3ec0aac0..2d5db951 100644 --- a/documentation/examples/slider-soft-setup.js +++ b/documentation/examples/slider-soft-setup.js @@ -1,13 +1,14 @@ -$('#soft').noUiSlider({ +var softSlider = document.getElementById('soft'); + +noUiSlider.create(softSlider, { start: 50, range: { min: 0, max: 100 + }, + pips: { + mode: 'values', + values: [20, 80], + density: 4 } }); - -$('#soft').noUiSlider_pips({ - mode: 'values', - values: [20, 80], - density: 4 -}); diff --git a/documentation/examples/slider-soft.js b/documentation/examples/slider-soft.js index cecbc54a..81b02cf0 100644 --- a/documentation/examples/slider-soft.js +++ b/documentation/examples/slider-soft.js @@ -1,7 +1,7 @@ -$('#soft').on('set', function ( event, value ) { - if ( value < 20 ) { - $(this).val(20); - } else if ( value > 80 ) { - $(this).val(80); +softSlider.noUiSlider.on('change', function ( values, handle ) { + if ( values[handle] < 20 ) { + softSlider.noUiSlider.set(20); + } else if ( values[handle] > 80 ) { + softSlider.noUiSlider.set(80); } }); diff --git a/documentation/examples/toggle-switch.php b/documentation/examples/toggle-switch.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/toggle.css b/documentation/examples/toggle.css new file mode 100644 index 00000000..68406e25 --- /dev/null +++ b/documentation/examples/toggle.css @@ -0,0 +1,6 @@ +#slider-toggle { + height: 50px; +} +#slider-toggle.off .noUi-handle { + border-color: red; +} diff --git a/documentation/examples/toggle.js b/documentation/examples/toggle.js index a66ad934..b7099a3a 100644 --- a/documentation/examples/toggle.js +++ b/documentation/examples/toggle.js @@ -1,8 +1,6 @@ -function toggle( value ){ - $(this).toggleClass('off', value === "1"); -} +var toggleSlider = document.getElementById('slider-toggle'); -$("#slider-toggle").noUiSlider({ +noUiSlider.create(toggleSlider, { orientation: "vertical", start: 0, range: { @@ -14,6 +12,10 @@ $("#slider-toggle").noUiSlider({ }) }) -$("#slider-toggle").addClass('toggle'); - -$("#slider-toggle").Link('lower').to(toggle); +toggleSlider.noUiSlider.on('update', function( values, handle ){ + if ( values[handle] === '1' ) { + toggleSlider.className += ' off'; + } else { + toggleSlider.className = toggleSlider.className.slice(0, -4); + } +}); diff --git a/documentation/examples/tooltip-more.js b/documentation/examples/tooltip-more.js index 8666269c..86af0f51 100644 --- a/documentation/examples/tooltip-more.js +++ b/documentation/examples/tooltip-more.js @@ -1,11 +1,20 @@ -// Tags after '-inline-' are inserted as HTML. -// noUiSlider writes to the first element it finds. -$("#slider-tooltip").Link('upper').to('-inline-
', function ( value ) { +var tipHandles = tooltipSlider.getElementsByClassName('noUi-handle'), + tooltips = []; - // The tooltip HTML is 'this', so additional - // markup can be inserted here. - $(this).html( - 'Value: ' + - '' + value + '' - ); +// Add divs to the slider handles. +for ( var i = 0; i < tipHandles.length; i++ ){ + tooltips[i] = document.createElement('div'); + tipHandles[i].appendChild(tooltips[i]); +} + +// Add a class for styling +tooltips[1].className += 'tooltip'; +// Add additional markup +tooltips[1].innerHTML = 'Value: '; +// Replace the tooltip reference with the span we just added +tooltips[1] = tooltips[1].getElementsByTagName('span')[0]; + +// When the slider changes, write the value to the tooltips. +tooltipSlider.noUiSlider.on('update', function( values, handle ){ + tooltips[handle].innerHTML = values[handle]; }); diff --git a/documentation/examples/tooltip-simple.js b/documentation/examples/tooltip-simple.js deleted file mode 100644 index 68be1c0c..00000000 --- a/documentation/examples/tooltip-simple.js +++ /dev/null @@ -1,2 +0,0 @@ -// When no HTML is provided, noUiSlider creates an empty
-$("#slider-tooltip").Link('lower').to('-inline-'); diff --git a/documentation/examples/tooltip.css b/documentation/examples/tooltip.css new file mode 100644 index 00000000..3bea6bd1 --- /dev/null +++ b/documentation/examples/tooltip.css @@ -0,0 +1,17 @@ +.tooltip { + display: block; + position: absolute; + border: 1px solid #D9D9D9; + font: 400 12px/12px Arial; + border-radius: 3px; + background: #fff; + top: -43px; + padding: 5px; + left: -9px; + text-align: center; + width: 50px; +} +.tooltip strong { + display: block; + padding: 2px; +} diff --git a/documentation/examples/tooltip.js b/documentation/examples/tooltip.js index d25be861..e2c7a244 100644 --- a/documentation/examples/tooltip.js +++ b/documentation/examples/tooltip.js @@ -1,4 +1,6 @@ -$("#slider-tooltip").noUiSlider({ +var tooltipSlider = document.getElementById('slider-tooltip'); + +noUiSlider.create(tooltipSlider, { start: [40, 50], range: { 'min': 30, diff --git a/documentation/examples/tooltip.php b/documentation/examples/tooltip.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/examples/working-with-dates.php b/documentation/examples/working-with-dates.php deleted file mode 100644 index e69de29b..00000000 diff --git a/documentation/index.php b/documentation/index.php index 442007b0..5867a6d7 100644 --- a/documentation/index.php +++ b/documentation/index.php @@ -1,12 +1,9 @@ -
This is noUiSlider.
+

noUiSlider: lightweight JavaScript range slider

@@ -16,96 +13,84 @@
- - + +
- - -

"Lightweight javascript range slider that works with jQuery or Zepto."

- -
    -
  • Responsive design friendly
  • -
  • Linking input fields
  • -
  • Touch support for iOS, Android & Windows (phone)
  • -
  • Dragable range
  • -
  • Works with jQuery (1.7+) or Zepto
  • -
  • No jQueryUI dependencies
  • -
  • Tested in IE7 - IE11, Chrome, Opera, Firefox & Safari
  • -
+ + +
Connect the input to the slider
+ +
+ +
+ +
CSS in this example
+ +
+ +
-

Browser support

-

noUiSlider supports IE7 and up, and of course the latest versions of the 'evergreen' browsers: Chrome, Safari, Firefox and Opera.

+

"Lightweight javascript range slider that works with jQuery or Zepto."

+ +
    +
  • Responsive design friendly
  • +
  • Touch support for iOS, Android & Windows (phone)
  • +
  • Dragable range
  • +
  • No jQuery, jQueryUI or other dependencies
  • +
  • Tested in IE9 - IE11, Chrome, Opera, Firefox & Safari
  • +
- Browser support +

noUiSlider works with pretty much any device, mouse, touchscreen or both, and it'll work beautifully in responsive designs. Have you tried this documentation on your phone?

-

Let's get started!

-

Required scripts

+ +

Getting started

-

noUiSlider requires jQuery 1.7.x or newer, or Zepto 1.0. Zepto's data module is no longer required.

+

noUiSlider 8 has no dependancies, so you don't need jQuery, jQuery UI, Zepto, etc. to use it.

-

To create a slider, call .noUiSlider() with your options on a jQuery element. If you'd like to see a minimal example, you can have a look at this minimal setup document.

+

Putting all your scripts in the page <head> will slow down your site. If you'd like to know why, consider reading this article by Yahoo!. Put the slider CSS in your <head>, and the script at the end of the <body>.

-

Putting all your scripts in the page <head> will likely slow down your site. If you'd like to know why, consider reading this article by Yahoo!.

+

To create a slider, call noUiSlider.create() with an element and your options.

-
<!-- jQuery or Zepto -->
-<script src="jquery / zepto.js"></script>
+
<!-- In <head> -->
+<link href="nouislider.min.css" rel="stylesheet">
 
-<!-- The noUiSlider script and stylesheet -->
-<!-- Use the files with *.min.* for the minified versions. -->
-<link href="jquery.nouislider.min.css" rel="stylesheet">
-
-<!-- Use the 'all' version to get all documented features. -->
-<!-- Includes wNumb, libLink and the pips add-on -->
-<script src="jquery.nouislider.all.min.js"></script>
+<!-- In <body> --> +<script src="nouislider.min.js"></script>
-

Well written and lightweight

+ +

Browser support

-
-

When using noUiSlider in your forms, users get all the functionality they've come to expect, and powerful API's make implementation easy. When gzipped and minified, noUiSlider and the default CSS theme take about 6 KB.

-
-
- -

Super simple API design

- -
-

The noUiSlider API is compatible with the standard HTML input methods, so the slider is extremely easy to use. You can select a group of $('input[type="number"], select, .noUiSlider'), and calling .val(50) will just work.

-
-
- -

Responsive all around

-
-
-

noUiSlider works with pretty much any device, mouse, touchscreen or both, and it'll work beautifully in responsive designs. Have you tried this documentation on your phone?

+

noUiSlider supports IE7 and up, and of course the latest versions of the 'evergreen' browsers: Chrome, Safari, Firefox and Opera.

diff --git a/documentation/index/minimal.js b/documentation/index/minimal.js index 63f33554..5172f719 100644 --- a/documentation/index/minimal.js +++ b/documentation/index/minimal.js @@ -1,4 +1,6 @@ -$("#slider").noUiSlider({ +var slider = document.getElementById('slider'); + +noUiSlider.create(slider, { start: [20, 80], connect: true, range: { diff --git a/documentation/index/showcase-connect.js b/documentation/index/showcase-connect.js new file mode 100644 index 00000000..def12207 --- /dev/null +++ b/documentation/index/showcase-connect.js @@ -0,0 +1,16 @@ +var valueInput = document.getElementById('value-input'), + valueSpan = document.getElementById('value-span'); + +// When the slider value changes, update the input and span +slider.noUiSlider.on('update', function( values, handle ) { + if ( handle ) { + valueInput.value = values[handle]; + } else { + valueSpan.innerHTML = values[handle]; + } +}); + +// When the input changes, set the slider value +valueInput.addEventListener('change', function(){ + slider.noUiSlider.set([null, this.value]); +}); diff --git a/documentation/index/showcase.css b/documentation/index/showcase.css new file mode 100644 index 00000000..12a2f6d2 --- /dev/null +++ b/documentation/index/showcase.css @@ -0,0 +1,16 @@ +#showcase { + margin: 0 20px; + text-align: center; +} +#range { + height: 300px; + margin: 0 auto 30px; +} +#value-span, +#value-input { + width: 50%; + float: left; + display: block; + text-align: center; + margin: 0; +} diff --git a/documentation/index/showcase.js b/documentation/index/showcase.js index ae808598..6d91edaa 100644 --- a/documentation/index/showcase.js +++ b/documentation/index/showcase.js @@ -1,35 +1,19 @@ -$('#range').noUiSlider({ - start: [ 20, 80 ], - step: 10, - margin: 20, - connect: true, - direction: 'rtl', - orientation: 'vertical', - - // Configure tapping, or make the selected range dragable. - behaviour: 'tap-drag', - - // Full number format support. - format: wNumb({ - mark: ',', - decimals: 1 - }), - - // Support for non-linear ranges by adding intervals. - range: { +var slider = document.getElementById('range'); + +noUiSlider.create(slider, { + start: [ 20, 80 ], // Handle start position + step: 10, // Slider moves in increments of '10' + margin: 20, // Handles must be more than '20' apart + connect: true, // Display a colored bar between the handles + direction: 'rtl', // Put '0' at the bottom of the slider + orientation: 'vertical', // Orient the slider vertically + behaviour: 'tap-drag', // Move handle on tap, bar is draggable + range: { // Slider can select '0' to '100' 'min': 0, 'max': 100 + }, + pips: { // Show a scale with the slider + mode: 'steps', + density: 2 } }); - -// Reading/writing + validation from an input? One line. -$('#range').Link('lower').to($('#value-input')); - -// Write to a span? One line. -$('#range').Link('upper').to($('#value-span'), 'html'); - -// Optional addon: creating Pips (Percentage In Point); -$('#range').noUiSlider_pips({ - mode: 'steps', - density: 2 -}); diff --git a/documentation/linking-input-fields.php b/documentation/linking-input-fields.php deleted file mode 100644 index 1c466e8d..00000000 --- a/documentation/linking-input-fields.php +++ /dev/null @@ -1,95 +0,0 @@ - - -

Linking input fields

- - - -

libLink support

- -
- -
- -

noUiSlider has full support for libLink, which will let you write values to input elements very easily. libLink will update the slider if you change an input as well!

- -

As you can see, noUiSlider updates the value in the $('#readout') element, and typing in the input will change the slider.

- -
- - - - -
-
- -
- -
- -
- - - -

Feature overview

- -
- -
-

Play with the example a bit, and look at the samples to see how easy it was to set up all those form-fields. Note how all input is automatically validated, to prevent invalid values anywhere.

- -
- -
<form id="moneyForm">
- -
'); ?> - -
'); ?> - - '."\r\n".''); ?> - -
'); ?> - - - -
</form>
- - - - - - - -
- -
- -
Initializing the slider
- -
- -
- -
Using libLink to link input fields to the lower handle
- -
- -
- -
Using libLink to link input fields to the upper handle
- -
- -
- -
Handling button clicks
- -
- -
- -
- - diff --git a/documentation/linking-input-fields/button.js b/documentation/linking-input-fields/button.js deleted file mode 100644 index df3e3ed7..00000000 --- a/documentation/linking-input-fields/button.js +++ /dev/null @@ -1,8 +0,0 @@ -$('button').click(function(){ - // Use jQuery to make get the values from the form. - // We'll decode the generated URL to keep it readable. - alert(decodeURIComponent( $("#moneyForm").serialize() )); - - // Don't submit the form. - return false; -}); diff --git a/documentation/linking-input-fields/link-lower.js b/documentation/linking-input-fields/link-lower.js deleted file mode 100644 index 44379319..00000000 --- a/documentation/linking-input-fields/link-lower.js +++ /dev/null @@ -1,13 +0,0 @@ -// Place the value in the #value element, -// using the text method. -$("#rangeSlider").Link('lower').to($("#value"), "text"); - -// Any selector is acceptable, so we'll -// select both inputs. -$("#rangeSlider").Link('lower').to($(".inputs"), null, wNumb({ - // Prefix the value with an Euro symbol - prefix: '\u20AC', - // Write the value without decimals - decimals: 0, - postfix: ',-' -})); diff --git a/documentation/linking-input-fields/link-upper.js b/documentation/linking-input-fields/link-upper.js deleted file mode 100644 index b75a8245..00000000 --- a/documentation/linking-input-fields/link-upper.js +++ /dev/null @@ -1,14 +0,0 @@ -function setText( value, handleElement, slider ){ - $("#someElement").text( value ); -} - -// Link accepts functions too. -// The arguments are the slider value, -// the .noUi-handle element and the slider instance. -$("#rangeSlider").Link('upper').to(setText); - -// When you pass a string to a link, -// it will create a hidden input. -// You'll see the value appear when you -// alert the form contents. -$("#rangeSlider").Link('upper').to("inputName"); diff --git a/documentation/linking-input-fields/link.js b/documentation/linking-input-fields/link.js deleted file mode 100644 index 9ee7fe05..00000000 --- a/documentation/linking-input-fields/link.js +++ /dev/null @@ -1,11 +0,0 @@ -$("#slider-link").noUiSlider({ - start: [ 20 ], - step: 10, - range: { - 'min': [ 20 ], - 'max': [ 80 ] - } -}); - -$("#slider-link").Link('lower').to($('#span')); -$("#slider-link").Link('lower').to($('#input')); diff --git a/documentation/linking-input-fields/slider.js b/documentation/linking-input-fields/slider.js deleted file mode 100644 index efc6c87c..00000000 --- a/documentation/linking-input-fields/slider.js +++ /dev/null @@ -1,14 +0,0 @@ -$("#rangeSlider").noUiSlider({ - start: [ 950, 5060 ], - range: { - 'min': 50, - 'max': 5960 - }, - connect: true, - // Set some default formatting options. - // These options will be applied to any Link - // that doesn't overwrite these values. - format: wNumb({ - decimals: 1 - }) -}); diff --git a/documentation/more.php b/documentation/more.php index e0ac1c39..146f93ba 100644 --- a/documentation/more.php +++ b/documentation/more.php @@ -21,15 +21,30 @@

Disabling a slider is identical to disabling a checkbox or textarea; simply set the disabled attribute.

-

A disabled slider can't be changed by sliding, click or touching, but you can still change its value using the .val() method. You can use CSS to show the disabled state. The default theme also sets a not-allowed cursor.

+

A disabled slider can't be changed by sliding, click or touching, but you can still change its value using the .set() method. You can use CSS to show the disabled state. The default theme also sets a not-allowed cursor.

The slider below is disabled when the checkbox gets checked, and re-enabled when it is unchecked.

+

Individual handles can also be disabled by setting the disabled attribute on a .noUi-handle element.

+
-
+
+ +
+ +
+
+ +
@@ -48,25 +63,6 @@ - - -

Reading options back

- -
- -
- -

noUiSlider can return the options that where used to initialize a slider by passing 'options'. Note that the returned object is indentical to the input: values are not sanitized or parsed.

- -
- -
- -
- -
- -

Updating slider options

@@ -74,22 +70,18 @@
-

Sometimes, you'll want to update your setup of noUiSlider after you initialized it. Maybe you've gotten new data from an Ajax request, or you want to reflect changes in other filters in the slider. In any case, you want to rebuild a slider using some of its current settings, but overwrite some others.

- -

With this flag set, the current configuration will be extended by any new options provided. If the slider wasn't initialised yet, it will be initialised normally.

- -

When the start option isn't changed, the slider will set itself back to the current values. Otherwise, the slider will be set to the values provided in start.

- +

Sometimes, you'll want to update your setup of noUiSlider after you initialized it. Maybe you've gotten new data from an Ajax request, or you want to reflect changes in other filters in the slider. noUiSlider has a destroy method, so you can remove a slider. By storing the initial settings in a variable, they can easily be modified.

+

For this example, we'll use a slider, and two buttons to change the range option. We'll show the value in a <span>, so you can always see the value.

-

When a button is clicked, we'll read the data-range attribute it has, and update the slider with the new value.

+

When a button is clicked, we'll read the data-range attribute it has, and rebuild the slider with the new value.

- - + + @@ -98,10 +90,6 @@
-

noUiSlider offers a rebuild flag for this. You can use it by following your options by true, like so:

- -
$('.slider').noUiSlider({ /* ... */ }, true);
-
The HTML for this example
@@ -109,11 +97,11 @@
<div id="update"></div>
 <span id="value"></span>
 
-<button data-range="20,50">
+<button class="update-button" data-range="20,50">
 	Set range [20, 50]
 </button>
 
-<button data-range="10,40">
+<button class="update-button" data-range="10,40">
 	Set range [10, 40]
 </button>
diff --git a/documentation/more/disable-all.js b/documentation/more/disable-all.js index 4cb33152..e23b2868 100644 --- a/documentation/more/disable-all.js +++ b/documentation/more/disable-all.js @@ -1,5 +1,9 @@ // To disable -$('.slider').attr('disabled', 'disabled'); +slider.setAttribute('disabled', true); // To re-enable -$('.slider').removeAttr('disabled'); +slider.removeAttribute('disabled'); + +// To disable one handle +var origins = slider.getElementsByClassName('noUi-origin'); +origins[0].setAttribute('disabled', true); diff --git a/documentation/more/disable.js b/documentation/more/disable.js index a3797527..5aec926d 100644 --- a/documentation/more/disable.js +++ b/documentation/more/disable.js @@ -1,17 +1,22 @@ -var slider = $('#disable'); +var slider1 = document.getElementById('disable1'), + slider2 = document.getElementById('disable2'), + checkbox1 = document.getElementById('checkbox1'), + checkbox2 = document.getElementById('checkbox2'), + checkbox3 = document.getElementById('checkbox3'), + origins = slider2.getElementsByClassName('noUi-origin'); -function toggle(){ +function toggle ( element ){ // If the checkbox is checked, disabled the slider. // Otherwise, re-enable it. if ( this.checked ) { - slider.attr('disabled', 'disabled'); + element.setAttribute('disabled', true); } else { - slider.removeAttr('disabled'); + element.removeAttribute('disabled'); } } -slider.noUiSlider({ +noUiSlider.create(slider1, { start: 80, connect: 'lower', range: { @@ -20,4 +25,22 @@ slider.noUiSlider({ } }); -$('#checkbox').click( toggle ); +noUiSlider.create(slider2, { + start: [20, 80], + range: { + min: 0, + max: 100 + } +}); + +checkbox1.addEventListener('click', function(){ + toggle.call(this, slider1); +}); + +checkbox2.addEventListener('click', function(){ + toggle.call(this, origins[0]); +}); + +checkbox3.addEventListener('click', function(){ + toggle.call(this, origins[1]); +}); diff --git a/documentation/more/options.js b/documentation/more/options.js deleted file mode 100644 index b91da155..00000000 --- a/documentation/more/options.js +++ /dev/null @@ -1,10 +0,0 @@ -$('#slider').noUiSlider({ - start: 80, - range: { - min: 0, - max: 100 - } -}); - -/* { start: 80, range: { min: 0, max: 100 } } */ -$('#slider').noUiSlider('options'); diff --git a/documentation/more/update-setup.js b/documentation/more/update-setup.js index b1176fef..b568c11d 100644 --- a/documentation/more/update-setup.js +++ b/documentation/more/update-setup.js @@ -1,11 +1,20 @@ -$('#slider-update').noUiSlider({ - range: { - 'min': 0, - 'max': 40 - }, - start: 20, - margin: 2, - step: 2 -}); +var updateSlider = document.getElementById('slider-update'), + updateSliderValue = document.getElementById('slider-update-value'), + settings = { + range: { + 'min': 0, + 'max': 40 + }, + start: 20, + margin: 2, + step: 2 + }; -$('#slider-update').Link().to( $('#slider-update-value'), 'text' ); +function bindValue ( ) { + updateSlider.noUiSlider.on('update', function( values, handle ) { + updateSliderValue.innerHTML = values[handle]; + }); +} + +noUiSlider.create(updateSlider, settings); +bindValue(); diff --git a/documentation/more/update.js b/documentation/more/update.js index faa2fab9..7c40f456 100644 --- a/documentation/more/update.js +++ b/documentation/more/update.js @@ -1,14 +1,22 @@ -$('button').click(function(){ +var buttons = document.getElementsByClassName('update-button'); + +function rebuildSlider ( ) { // Get the new values from the button. - var range = $(this).attr('data-range').split(','); - - // The options will be merged with those - // provided on initialization. - $('#slider-update').noUiSlider({ - range: { - 'min': Number(range[0]), - 'max': Number(range[1]) - } - }, true); -}); + var range = this.getAttribute('data-range').split(','), + val = updateSlider.noUiSlider.get(); + + updateSlider.noUiSlider.destroy(); + + // Create a slider with the new options. + settings.range.min = Number(range[0]); + settings.range.max = Number(range[1]); + settings.start = Number(val); + + noUiSlider.create(updateSlider, settings); + + bindValue(); +} + +buttons[0].addEventListener('click', rebuildSlider); +buttons[1].addEventListener('click', rebuildSlider); diff --git a/documentation/new-version.php b/documentation/new-version.php index 1322898f..dca5a94b 100644 --- a/documentation/new-version.php +++ b/documentation/new-version.php @@ -3,37 +3,110 @@ $description = ""; ?> -

Version 7

+

noUiSlider 8 release information

-

New version

+
-

noUiSlider has been updated to version 7! This version adds optional libLink and wNumb support, resulting in a smaller base file. While the serialization API has changed, the concept is still the same, and porting your code should be straightforward. If you require help with any specifics, feel free to email me. If you do, consider providing a jsFiddle demonstrating your problem.

- -
    -
  • Removed .val() modifiers -
      -
    • removed 'update': libLink can work without this hint
    • -
    • removed 'animate': value setting is now animated by default
    • -
    • removed 'set': set callback now always fires on value setting
    • -
    • removed 'link': libLink support value encoding/decoding. Input must now match slider encoding.
    • -
    -
  • -
  • Improved performance by reducing browser paints
  • -
  • Added 'animate' option to disable animation on value setting
  • -
  • Animated setting is now default.
  • -
  • Removed serialization
  • -
  • Added support for libLink
  • -
  • Added support for wNumb
  • -
  • Removed 'extend' behaviour
  • -
  • Added painting sliders in new layers for performance improvement
  • -
  • Added generation of legend
  • -
  • Complete documentation overhaul
  • -
  • Better testing with more structure
  • +

    After a slower, more incremental development period for noUiSlider, it is time for a shakeup. With a lot of attention going to 'You might not need jQuery' and other initiatives, I felt removing the jQuery dependancy in noUiSlider would be a nice project to spend some time on.

    + +

    Add to that the rapid progress on the Internet Explorer front. Up to noUiSlider 7, IE7 remained supported, mainly because there was never any need to explicity break compatibility. With IE currently at version 11 and Microsoft Edge ('Project Spartan') approaching, now is as good a time as any to drop the really old versions.

    + +

    noUiSlider 8 removes the jQuery dependancy completely.

    + +

    Rewriting the plugin, all tests and the documentation is quite an undertaking, so I wanted to get at least the following out of it:

    + +
      +
    • The release cycle has to be easier
    • +
    • Overall file size has to go down
    • +
    • API's had to be simplified
    + +

    The LibLink project, which I've always liked working on, formed a problem in this port. It's API is completely rooted in jQuery's method system. Considering the number of support request for this feature, even though it is rather complex, was low, I'm going to assume it wasn't used a lot. I wanted the spirit to remain in place, so I put a lot of thought into a replacement feature. It had to be 1) simpler, 2) have a smaller footprint and 3) be more obvious to use.

    + +

    The solution I came up with is the new update event. It fires on any change in the slider value, and when it is bound. This allows synchronizing with input elements without calling the bound function manually. A feature that is missing is the automatic adding of change events to the inputs: I've attempted to compensate this by providing some additional examples.

    +
+ + +

What else is new?

+ +
+ +
    +
  • Rebuilding is gone => destroy and rebuild now.
  • +
  • GetOriginalOptions removed
  • +
  • Looping and iterating in the initializer have been removed.
    + create takes one node, and one node only. This saves a lot of code.
  • +
  • Slider fires no native events anymore.
  • +
      +
    • No issues in change events with inputs
    • +
    • The slide event now fires for both handles when using the drag option.
    • +
    • Events now have the handle number as an argument.
    • +
    +
  • Submodules are no longer in the repository. Want wNumb()? Include it!
  • +
  • The Pips feature, an optional addition in noUiSlider 7, has been merged into the core.
    + This allowed removing some overhead, shrinking the overall file size.
  • +
  • Individual handles can now be disabled.
  • +
  • Slider no longer responds to middle/right clicks.
  • +
+
+ + +

Version 7 to 8 migration guide

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
noUiSlider 7noUiSlider 8
Initialization
$('#slider').noUiSlider({options});
var slider = document.getElementById('slider');
+noUiSlider.create(slider, {options});
Get the slider value
var value = $('#slider').val();
var value = slider.noUiSlider.get();
Set the slider value
$('#slider').val( 50 );
slider.noUiSlider.set( 50 );
Add an event listener
$('#slider').on('change', function());
slider.noUiSlider.on('change', function());
Bind to an <input> element
$('#slider').Link().to($('input'));
slider.noUiSlider.on('update', function( values, handle ) {
+	input.value = values[handle];
+});
+
+input.addEventListener('change', function(){
+	slider.noUiSlider.set(this.value);
+});
+ +
diff --git a/documentation/pips.php b/documentation/pips.php index fec33679..b49da04d 100644 --- a/documentation/pips.php +++ b/documentation/pips.php @@ -3,13 +3,13 @@ $description = ""; ?> -

Pips Add-On

+

Adding a scale/pips to a slider

-

This optional extention to noUiSlider allows you to generate points along the slider.

+

This feature allows you to generate points along the slider.

Five options can be set: mode to determine where to place pips, values as additional options for mode, stepped to round pip values to the slider stepping, density to pre-scale the number of pips, and filter to manually modify pip size.

All sliders on the page use the same range, as displayed to the right.

@@ -33,25 +33,6 @@

The range mode uses the slider range to determine where the pips should be. A pip is generated for every percentage specified.

-
- -
- -
Initialize the slider
- -
- -
- - -
- -
- -
- -
-

Left-to-Right (default):

@@ -63,25 +44,25 @@
-
- -

Vertical and vertical, bottom-to-top:

+
- -
+
+ +
+
@@ -98,17 +79,10 @@

Here, we'll use large values for every step matching a thousand (1000, 2000, 3000), and small values for every step matching 500 (2500, 3500, 4500).

The Pips add-on supports format in the same way the slider itself does.

- +
- -
Initialize the slider
- -
- -
-
@@ -120,7 +94,6 @@
-
@@ -138,7 +111,6 @@
-
@@ -146,27 +118,12 @@
-
- -
Initialize the slider
- -
- -
- - -
Initialize the slider
- -
- -
-
@@ -183,7 +140,6 @@
-
@@ -191,27 +147,12 @@
-
- -
Initialize the slider
- -
- -
- - -
Initialize the slider
- -
- -
-
@@ -228,7 +169,6 @@
-
@@ -237,27 +177,12 @@
-
- -
Initialize the slider
- -
- -
- - -
Initialize the slider
- -
- -
-
diff --git a/documentation/pips/count-slider.js b/documentation/pips/count-slider.js deleted file mode 100644 index 68daabce..00000000 --- a/documentation/pips/count-slider.js +++ /dev/null @@ -1,4 +0,0 @@ -$("#pips-count").noUiSlider({ - range: range_all_sliders, - start: 0 -}) diff --git a/documentation/pips/count-stepped-slider.js b/documentation/pips/count-stepped-slider.js deleted file mode 100644 index eceeae07..00000000 --- a/documentation/pips/count-stepped-slider.js +++ /dev/null @@ -1,4 +0,0 @@ -$("#pips-count-stepped").noUiSlider({ - range: range_all_sliders, - start: 0 -}) diff --git a/documentation/pips/count-stepped.js b/documentation/pips/count-stepped.js index 69cbb98b..9d864eaa 100644 --- a/documentation/pips/count-stepped.js +++ b/documentation/pips/count-stepped.js @@ -1,6 +1,12 @@ -$("#pips-count-stepped").noUiSlider_pips({ - mode: 'count', - values: 6, - density: 4, - stepped: true +var pipsCountStepped = document.getElementById('pips-count-stepped'); + +noUiSlider.create(pipsCountStepped, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'count', + values: 6, + density: 4, + stepped: true + } }); diff --git a/documentation/pips/count.js b/documentation/pips/count.js index dd91b625..f0449da7 100644 --- a/documentation/pips/count.js +++ b/documentation/pips/count.js @@ -1,5 +1,11 @@ -$("#pips-count").noUiSlider_pips({ - mode: 'count', - values: 6, - density: 4 +var pipsCount = document.getElementById('pips-count'); + +noUiSlider.create(pipsCount, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'count', + values: 6, + density: 4 + } }); diff --git a/documentation/pips/positions-slider.js b/documentation/pips/positions-slider.js deleted file mode 100644 index f4459dcc..00000000 --- a/documentation/pips/positions-slider.js +++ /dev/null @@ -1,4 +0,0 @@ -$("#pips-positions").noUiSlider({ - range: range_all_sliders, - start: 0 -}) diff --git a/documentation/pips/positions-stepped-slider.js b/documentation/pips/positions-stepped-slider.js deleted file mode 100644 index 29c421e6..00000000 --- a/documentation/pips/positions-stepped-slider.js +++ /dev/null @@ -1,4 +0,0 @@ -$("#pips-positions-stepped").noUiSlider({ - range: range_all_sliders, - start: 0 -}) diff --git a/documentation/pips/positions-stepped.js b/documentation/pips/positions-stepped.js index 18dd7e6c..68be30ec 100644 --- a/documentation/pips/positions-stepped.js +++ b/documentation/pips/positions-stepped.js @@ -1,6 +1,12 @@ -$("#pips-positions-stepped").noUiSlider_pips({ - mode: 'positions', - values: [0,25,50,75,100], - density: 4, - stepped: true +var positionsStepped = document.getElementById('pips-positions-stepped'); + +noUiSlider.create(positionsStepped, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'positions', + values: [0,25,50,75,100], + density: 4, + stepped: true + } }); diff --git a/documentation/pips/positions.js b/documentation/pips/positions.js index 7e1cdf45..01124643 100644 --- a/documentation/pips/positions.js +++ b/documentation/pips/positions.js @@ -1,5 +1,11 @@ -$("#pips-positions").noUiSlider_pips({ - mode: 'positions', - values: [0,25,50,75,100], - density: 4 +var pipsPositions = document.getElementById('pips-positions'); + +noUiSlider.create(pipsPositions, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'positions', + values: [0,25,50,75,100], + density: 4 + } }); diff --git a/documentation/pips/range-slider.js b/documentation/pips/range-slider.js deleted file mode 100644 index 1b1fc936..00000000 --- a/documentation/pips/range-slider.js +++ /dev/null @@ -1,23 +0,0 @@ -$("#pips-range").noUiSlider({ - range: range_all_sliders, - start: 0 -}) - -$("#pips-range-rtl").noUiSlider({ - range: range_all_sliders, - start: 0, - direction: 'rtl' -}); - -$("#pips-range-vertical").noUiSlider({ - range: range_all_sliders, - start: 0, - orientation: 'vertical' -}); - -$("#pips-range-vertical-rtl").noUiSlider({ - range: range_all_sliders, - start: 0, - orientation: 'vertical', - direction: 'rtl' -}); diff --git a/documentation/pips/range.js b/documentation/pips/range.js index e5548083..21841b99 100644 --- a/documentation/pips/range.js +++ b/documentation/pips/range.js @@ -1,4 +1,44 @@ -$(".pips-range").noUiSlider_pips({ - mode: 'range', - density: 3 +var pipsRange = document.getElementById('pips-range'), + pipsRangeRtl = document.getElementById('pips-range-rtl'), + pipsRangeVertical = document.getElementById('pips-range-vertical'), + pipsRangeVerticalRtl = document.getElementById('pips-range-vertical-rtl'); + +noUiSlider.create(pipsRange, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'range', + density: 3 + } +}) + +noUiSlider.create(pipsRangeRtl, { + range: range_all_sliders, + start: 0, + direction: 'rtl', + pips: { + mode: 'range', + density: 3 + } +}); + +noUiSlider.create(pipsRangeVertical, { + range: range_all_sliders, + start: 0, + orientation: 'vertical', + pips: { + mode: 'range', + density: 3 + } +}); + +noUiSlider.create(pipsRangeVerticalRtl, { + range: range_all_sliders, + start: 0, + orientation: 'vertical', + direction: 'rtl', + pips: { + mode: 'range', + density: 3 + } }); diff --git a/documentation/pips/steps-slider.js b/documentation/pips/steps-slider.js deleted file mode 100644 index 6c871742..00000000 --- a/documentation/pips/steps-slider.js +++ /dev/null @@ -1,4 +0,0 @@ -$("#pips-steps").noUiSlider({ - range: range_all_sliders, - start: 0 -}) diff --git a/documentation/pips/steps.js b/documentation/pips/steps.js index 7d5f7a3d..04109109 100644 --- a/documentation/pips/steps.js +++ b/documentation/pips/steps.js @@ -2,12 +2,18 @@ function filter500( value, type ){ return value % 1000 ? 2 : 1; } -$("#pips-steps").noUiSlider_pips({ - mode: 'steps', - density: 3, - filter: filter500, - format: wNumb({ - decimals: 2, - prefix: '$' - }) +var pipsSteps = document.getElementById('pips-steps'); + +noUiSlider.create(pipsSteps, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'steps', + density: 3, + filter: filter500, + format: wNumb({ + decimals: 2, + prefix: '$' + }) + } }); diff --git a/documentation/pips/values-slider.js b/documentation/pips/values-slider.js deleted file mode 100644 index ecdbdbf9..00000000 --- a/documentation/pips/values-slider.js +++ /dev/null @@ -1,4 +0,0 @@ -$("#pips-values").noUiSlider({ - range: range_all_sliders, - start: 0 -}) diff --git a/documentation/pips/values-stepped-slider.js b/documentation/pips/values-stepped-slider.js deleted file mode 100644 index 5ff61d5d..00000000 --- a/documentation/pips/values-stepped-slider.js +++ /dev/null @@ -1,4 +0,0 @@ -$("#pips-values-stepped").noUiSlider({ - range: range_all_sliders, - start: 0 -}) diff --git a/documentation/pips/values-stepped.js b/documentation/pips/values-stepped.js index cee68bf8..33711803 100644 --- a/documentation/pips/values-stepped.js +++ b/documentation/pips/values-stepped.js @@ -1,6 +1,12 @@ -$("#pips-values-stepped").noUiSlider_pips({ - mode: 'values', - values: [50, 552, 4651, 4952, 5000, 7080, 9000], - density: 4, - stepped: true +var pipsValuesStepped = document.getElementById('pips-values-stepped'); + +noUiSlider.create(pipsValuesStepped, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'values', + values: [50, 552, 4651, 4952, 5000, 7080, 9000], + density: 4, + stepped: true + } }); diff --git a/documentation/pips/values.js b/documentation/pips/values.js index bb4a9568..1ecb8514 100644 --- a/documentation/pips/values.js +++ b/documentation/pips/values.js @@ -1,5 +1,11 @@ -$("#pips-values").noUiSlider_pips({ - mode: 'values', - values: [50, 552, 2251, 3200, 5000, 7080, 9000], - density: 4 +var pipsValues = document.getElementById('pips-values'); + +noUiSlider.create(pipsValues, { + range: range_all_sliders, + start: 0, + pips: { + mode: 'values', + values: [50, 552, 2251, 3200, 5000, 7080, 9000], + density: 4 + } }); diff --git a/documentation/slider-options/animate.js b/documentation/slider-options/animate.js index 473f8302..6dc289c1 100644 --- a/documentation/slider-options/animate.js +++ b/documentation/slider-options/animate.js @@ -1,4 +1,8 @@ -$('#slider-animate-true').noUiSlider({ +var trueSlider = document.getElementById('slider-animate-true'), + falseSlider = document.getElementById('slider-animate-false'), + setButton = document.getElementById('set-sliders'); + +noUiSlider.create(trueSlider, { animate: true, start: 20, range: { @@ -7,7 +11,7 @@ $('#slider-animate-true').noUiSlider({ } }); -$('#slider-animate-false').noUiSlider({ +noUiSlider.create(falseSlider, { animate: false, start: 20, range: { @@ -16,6 +20,7 @@ $('#slider-animate-false').noUiSlider({ } }); -$('#set-sliders').click(function(){ - $('.sliders').val(60); +setButton.addEventListener('click', function(){ + trueSlider.noUiSlider.set(60); + falseSlider.noUiSlider.set(60); }); diff --git a/documentation/slider-options/connect.js b/documentation/slider-options/connect.js index 4ac8e0c9..b15fbb99 100644 --- a/documentation/slider-options/connect.js +++ b/documentation/slider-options/connect.js @@ -1,6 +1,8 @@ -$("#slider-connect").noUiSlider({ +var connectSlider = document.getElementById('slider-connect'); + +noUiSlider.create(connectSlider, { start: 40, - connect: "lower", + connect: 'lower', range: { 'min': 0, 'max': 100 diff --git a/documentation/slider-options/direction-link.js b/documentation/slider-options/direction-link.js index aafdb70f..0960d224 100644 --- a/documentation/slider-options/direction-link.js +++ b/documentation/slider-options/direction-link.js @@ -1 +1,5 @@ -$("#slider-direction").Link('lower').to($("#field")); +var directionField = document.getElementById('field'); + +directionSlider.noUiSlider.on('update', function( values, handle ){ + directionField.innerHTML = values[handle]; +}); diff --git a/documentation/slider-options/direction.js b/documentation/slider-options/direction.js index 67383fac..bef21c0d 100644 --- a/documentation/slider-options/direction.js +++ b/documentation/slider-options/direction.js @@ -1,6 +1,8 @@ -$("#slider-direction").noUiSlider({ +var directionSlider = document.getElementById('slider-direction'); + +noUiSlider.create(directionSlider, { start: 20, - direction: "rtl", + direction: 'rtl', range: { 'min': 0, 'max': 100 diff --git a/documentation/slider-options/limit-link.js b/documentation/slider-options/limit-link.js index 63ed7723..8a95e549 100644 --- a/documentation/slider-options/limit-link.js +++ b/documentation/slider-options/limit-link.js @@ -1,2 +1,6 @@ -$("#slider-limit").Link('lower').to( $('#slider-limit-value-min') ) -$("#slider-limit").Link('upper').to( $('#slider-limit-value-max') ); +var limitFieldMin = document.getElementById('slider-limit-value-min'); +var limitFieldMax = document.getElementById('slider-limit-value-max'); + +limitSlider.noUiSlider.on('update', function( values, handle ){ + (handle ? limitFieldMax : limitFieldMin).innerHTML = values[handle]; +}); diff --git a/documentation/slider-options/limit.js b/documentation/slider-options/limit.js index 67ad4a87..97ddec64 100644 --- a/documentation/slider-options/limit.js +++ b/documentation/slider-options/limit.js @@ -1,4 +1,6 @@ -$("#slider-limit").noUiSlider({ +var limitSlider = document.getElementById('slider-limit'); + +noUiSlider.create(limitSlider, { start: [ 10, 120 ], limit: 40, behaviour: 'drag', @@ -7,4 +9,4 @@ $("#slider-limit").noUiSlider({ 'min': 0, 'max': 100 } -}) +}); diff --git a/documentation/slider-options/margin-link.js b/documentation/slider-options/margin-link.js index 0a8bbf23..ea263205 100644 --- a/documentation/slider-options/margin-link.js +++ b/documentation/slider-options/margin-link.js @@ -1,2 +1,10 @@ -$("#slider-margin").Link('lower').to( $('#slider-margin-value-min') ) -$("#slider-margin").Link('upper').to( $('#slider-margin-value-max') ); +var marginMin = document.getElementById('slider-margin-value-min'), + marginMax = document.getElementById('slider-margin-value-max'); + +marginSlider.noUiSlider.on('update', function ( values, handle ) { + if ( handle ) { + marginMax.innerHTML = values[handle]; + } else { + marginMin.innerHTML = values[handle]; + } +}); diff --git a/documentation/slider-options/margin.js b/documentation/slider-options/margin.js index 3174cc9e..10e81e58 100644 --- a/documentation/slider-options/margin.js +++ b/documentation/slider-options/margin.js @@ -1,4 +1,6 @@ -$("#slider-margin").noUiSlider({ +var marginSlider = document.getElementById('slider-margin'); + +noUiSlider.create(marginSlider, { start: [ 20, 80 ], margin: 30, range: { diff --git a/documentation/slider-options/orientation.js b/documentation/slider-options/orientation.js index e3d24a4f..f8f6d20d 100644 --- a/documentation/slider-options/orientation.js +++ b/documentation/slider-options/orientation.js @@ -1,6 +1,8 @@ -$("#slider-vertical").noUiSlider({ +var verticalSlider = document.getElementById('slider-vertical'); + +noUiSlider.create(verticalSlider, { start: 40, - orientation: "vertical", + orientation: 'vertical', range: { 'min': 0, 'max': 100 diff --git a/documentation/slider-options/start.js b/documentation/slider-options/start.js index 9ed5d9f2..72a98b6f 100644 --- a/documentation/slider-options/start.js +++ b/documentation/slider-options/start.js @@ -1,4 +1,6 @@ -$("#slider-start").noUiSlider({ +var startSlider = document.getElementById('slider-start'); + +noUiSlider.create(startSlider, { start: [20, 80], range: { 'min': [ 0 ], diff --git a/documentation/slider-options/step.js b/documentation/slider-options/step.js index 6771c9a9..39294849 100644 --- a/documentation/slider-options/step.js +++ b/documentation/slider-options/step.js @@ -1,4 +1,6 @@ -$("#slider-step").noUiSlider({ +var stepSlider = document.getElementById('slider-step'); + +noUiSlider.create(stepSlider, { start: [ 20, 80 ], step: 10, range: { diff --git a/documentation/slider-read-write.php b/documentation/slider-read-write.php index 3f440944..ed7391e2 100644 --- a/documentation/slider-read-write.php +++ b/documentation/slider-read-write.php @@ -16,12 +16,11 @@
-

noUiSlider has an API which is designed to be compatible with other form elements. That's why you can just use the same method that works on any other input.

-

You can just get the slider value by calling .val(). It is really simple:

+

noUiSlider has an API with two simple methods: .get() and .set(). To get the current slider value:

-

For one-handle sliders, calling .val() will return the value. For two-handle sliders, an array[value, value] will be returned.

+

For one-handle sliders, calling .get() will return the value. For two-handle sliders, an array[value, value] will be returned.

@@ -35,9 +34,9 @@

noUiSlider will keep your values within the slider range, which saves you a bunch of validation.

-

If you have set the slider to use one handle, simply set it on the slider using the .val() method. If you have two handles, pass an array. One-handled sliders will also accept arrays.

+

If you have configured the slider to use one handle, you can change the current value by passing a number to the .set() method. If you have two handles, pass an array. One-handled sliders will also accept arrays.

-

Within an array, you can set a position to null if you want to leave a handle unchanged.

+

Within an array, you can set one position to null if you want to leave a handle unchanged.

@@ -96,7 +95,7 @@
- +
@@ -118,7 +117,7 @@
Linking the input field
- +
diff --git a/documentation/slider-read-write/buttons.js b/documentation/slider-read-write/buttons.js index c5a3d4df..028b967b 100644 --- a/documentation/slider-read-write/buttons.js +++ b/documentation/slider-read-write/buttons.js @@ -1,9 +1,9 @@ // Set the slider value to 20 -$("#write-button").click(function(){ - $('#slider').val( 20 ); +document.getElementById('write-button').addEventListener('click', function(){ + slider.noUiSlider.set( 20 ); }); // Read the slider value. -$("#read-button").click(function(){ - alert( $('#slider').val() ); +document.getElementById('read-button').addEventListener('click', function(){ + alert( slider.noUiSlider.get() ); }); diff --git a/documentation/slider-read-write/format-link.js b/documentation/slider-read-write/format-link.js new file mode 100644 index 00000000..dbb17207 --- /dev/null +++ b/documentation/slider-read-write/format-link.js @@ -0,0 +1,9 @@ +var inputFormat = document.getElementById('input-format'); + +sliderFormat.noUiSlider.on('update', function( values, handle ) { + inputFormat.value = values[handle]; +}); + +inputFormat.addEventListener('change', function(){ + sliderFormat.noUiSlider.set(this.value); +}); diff --git a/documentation/slider-read-write/format.js b/documentation/slider-read-write/format.js index 0469a026..9a2dacc4 100644 --- a/documentation/slider-read-write/format.js +++ b/documentation/slider-read-write/format.js @@ -1,4 +1,6 @@ -$("#slider-format").noUiSlider({ +var sliderFormat = document.getElementById('slider-format'); + +noUiSlider.create(sliderFormat, { start: [ 20 ], step: 10, range: { diff --git a/documentation/slider-read-write/linkformat.js b/documentation/slider-read-write/linkformat.js deleted file mode 100644 index e04db945..00000000 --- a/documentation/slider-read-write/linkformat.js +++ /dev/null @@ -1 +0,0 @@ -$("#slider-format").Link('lower').to($('#input-format')); diff --git a/documentation/slider-read-write/read.js b/documentation/slider-read-write/read.js index b87dc160..5f683261 100644 --- a/documentation/slider-read-write/read.js +++ b/documentation/slider-read-write/read.js @@ -1 +1 @@ -$("#slider").val(); +slider.noUiSlider.get(); diff --git a/documentation/slider-read-write/set.js b/documentation/slider-read-write/set.js index 6ead39b9..ad5b512c 100644 --- a/documentation/slider-read-write/set.js +++ b/documentation/slider-read-write/set.js @@ -1,4 +1,6 @@ -$('#slider').noUiSlider({ +var slider = document.getElementById('slider'); + +noUiSlider.create(slider, { start: [ 80 ], range: { 'min': [ 0 ], diff --git a/documentation/slider-read-write/wnumb.js b/documentation/slider-read-write/wnumb.js index c37079aa..da373838 100644 --- a/documentation/slider-read-write/wnumb.js +++ b/documentation/slider-read-write/wnumb.js @@ -1,4 +1,6 @@ -$("#slider-format").noUiSlider({ +var sliderFormat = document.getElementById('slider-format'); + +noUiSlider.create(sliderFormat, { start: [ 20000 ], step: 1000, range: { diff --git a/documentation/slider-read-write/write.js b/documentation/slider-read-write/write.js index 4b2ef176..576ee2fb 100644 --- a/documentation/slider-read-write/write.js +++ b/documentation/slider-read-write/write.js @@ -1,10 +1,14 @@ -// Set one value -$(".slider").val(10); -$(".slider").val([150]); +var slider = document.getElementById('slider'); + +noUiSlider.create(slider, /* { options } */); + +// Set one .noUiSlider.setue +slider.noUiSlider.set(10); +slider.noUiSlider.set([150]); // Set the upper handle, // don't change the lower one. -$(".slider").val([null, 14]); +slider.noUiSlider.set([null, 14]); // Set both slider handles -$(".slider").val([13.2, 15.7]); +slider.noUiSlider.set([13.2, 15.7]); diff --git a/documentation/slider-values.php b/documentation/slider-values.php index 18ffbb29..4a4947b0 100644 --- a/documentation/slider-values.php +++ b/documentation/slider-values.php @@ -89,8 +89,6 @@
- Advanced Feature -

noUiSlider offers some powerful mechanisms that allow a slider to behave in a non-linear fashion. You can create sliders with ever-increasing increments by specifying the value for the slider at certain intervals. Note how the handle in the example below starts at 30% of the slider width, even though 4000 is not 30% of the span between 2000 and 10000.

diff --git a/documentation/slider-values/handles.js b/documentation/slider-values/handles.js index 56e66308..91cc8ac4 100644 --- a/documentation/slider-values/handles.js +++ b/documentation/slider-values/handles.js @@ -1,4 +1,6 @@ -$('#slider-handles').noUiSlider({ +var handlesSlider = document.getElementById('slider-handles'); + +noUiSlider.create(handlesSlider, { start: [ 4000, 8000 ], range: { 'min': [ 2000 ], diff --git a/documentation/slider-values/non-linear-link.js b/documentation/slider-values/non-linear-link.js index 001b5833..05a6a377 100644 --- a/documentation/slider-values/non-linear-link.js +++ b/documentation/slider-values/non-linear-link.js @@ -1 +1,6 @@ -$('#slider-non-linear').Link('lower').to($("#slider-non-linear-value")); +var nonLinearSliderValueElement = document.getElementById('slider-non-linear-value'); + +// Show the value for the *last* moved handle. +nonLinearSlider.noUiSlider.on('update', function( values, handle ) { + nonLinearSliderValueElement.innerHTML = values[handle]; +}); diff --git a/documentation/slider-values/non-linear-step-link.js b/documentation/slider-values/non-linear-step-link.js index 1b945d7f..2d896d0e 100644 --- a/documentation/slider-values/non-linear-step-link.js +++ b/documentation/slider-values/non-linear-step-link.js @@ -1 +1,5 @@ -$('#slider-non-linear-step').Link('lower').to($('#slider-non-linear-step-value')); +var nonLinearStepSliderValueElement = document.getElementById('slider-non-linear-step-value'); + +nonLinearStepSlider.noUiSlider.on('update', function( values, handle ) { + nonLinearStepSliderValueElement.innerHTML = values[handle]; +}); diff --git a/documentation/slider-values/non-linear-step.js b/documentation/slider-values/non-linear-step.js index 32519ffe..4a558894 100644 --- a/documentation/slider-values/non-linear-step.js +++ b/documentation/slider-values/non-linear-step.js @@ -1,4 +1,6 @@ -$('#slider-non-linear-step').noUiSlider({ +var nonLinearStepSlider = document.getElementById('slider-non-linear-step'); + +noUiSlider.create(nonLinearStepSlider, { start: [ 500, 4000 ], range: { 'min': [ 0 ], diff --git a/documentation/slider-values/non-linear.js b/documentation/slider-values/non-linear.js index 22c396a2..e98a6861 100644 --- a/documentation/slider-values/non-linear.js +++ b/documentation/slider-values/non-linear.js @@ -1,4 +1,6 @@ -$('#slider-non-linear').noUiSlider({ +var nonLinearSlider = document.getElementById('slider-non-linear'); + +noUiSlider.create(nonLinearSlider, { start: [ 4000 ], range: { 'min': [ 2000 ], diff --git a/documentation/slider-values/range-link.js b/documentation/slider-values/range-link.js index 1c9b5379..7a480668 100644 --- a/documentation/slider-values/range-link.js +++ b/documentation/slider-values/range-link.js @@ -1 +1,5 @@ -$('#slider-range').Link('lower').to($('#slider-range-value')); +var rangeSliderValueElement = document.getElementById('slider-range-value'); + +rangeSlider.noUiSlider.on('update', function( values, handle ) { + rangeSliderValueElement.innerHTML = values[handle]; +}); diff --git a/documentation/slider-values/range.js b/documentation/slider-values/range.js index 3ff4681f..dba547d3 100644 --- a/documentation/slider-values/range.js +++ b/documentation/slider-values/range.js @@ -1,4 +1,6 @@ -$('#slider-range').noUiSlider({ +var rangeSlider = document.getElementById('slider-range'); + +noUiSlider.create(rangeSlider, { start: [ 4000 ], range: { 'min': [ 2000 ], diff --git a/documentation/slider-values/snap-link.js b/documentation/slider-values/snap-link.js index ee32e0ec..0fcbc5c2 100644 --- a/documentation/slider-values/snap-link.js +++ b/documentation/slider-values/snap-link.js @@ -1,3 +1,8 @@ -$('#slider-snap').Link('lower').to($('#slider-snap-value-lower')); +var snapValues = [ + document.getElementById('slider-snap-value-lower'), + document.getElementById('slider-snap-value-upper') +]; -$('#slider-snap').Link('upper').to($('#slider-snap-value-upper')); +snapSlider.noUiSlider.on('update', function( values, handle ) { + snapValues[handle].innerHTML = values[handle]; +}); diff --git a/documentation/slider-values/snap.js b/documentation/slider-values/snap.js index 5b1f540a..4a0c386f 100644 --- a/documentation/slider-values/snap.js +++ b/documentation/slider-values/snap.js @@ -1,4 +1,6 @@ -$('#slider-snap').noUiSlider({ +var snapSlider = document.getElementById('slider-snap'); + +noUiSlider.create(snapSlider, { start: [ 0, 500 ], snap: true, connect: true, diff --git a/documentation/slider-values/step-link.js b/documentation/slider-values/step-link.js index 2cf83631..69307560 100644 --- a/documentation/slider-values/step-link.js +++ b/documentation/slider-values/step-link.js @@ -1 +1,5 @@ -$('#slider-step').Link('lower').to($('#slider-step-value')); +var stepSliderValueElement = document.getElementById('slider-step-value'); + +stepSlider.noUiSlider.on('update', function( values, handle ) { + stepSliderValueElement.innerHTML = values[handle]; +}); diff --git a/documentation/slider-values/step.js b/documentation/slider-values/step.js index d817a069..52e0f649 100644 --- a/documentation/slider-values/step.js +++ b/documentation/slider-values/step.js @@ -1,4 +1,6 @@ -$('#slider-step').noUiSlider({ +var stepSlider = document.getElementById('slider-step'); + +noUiSlider.create(stepSlider, { start: [ 4000 ], step: 1000, range: { diff --git a/package.json b/package.json index 777ea0f7..5c6529f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "noUiSlider", - "version": "7.0.10", + "version": "8.0.0", + "main": "distribute/jquery.nouislider", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-compress": "^0.11.0", @@ -8,8 +9,7 @@ "grunt-contrib-copy": "^0.5.0", "grunt-contrib-cssmin": "^0.10.0", "grunt-contrib-jshint": "^0.10.0", - "grunt-contrib-uglify": "^0.5.1", - "grunt-string-replace": "^0.2.7" + "grunt-contrib-uglify": "^0.5.1" }, "repository": { "type": "git", diff --git a/src/archive.md b/src/archive.md deleted file mode 100644 index 214703ae..00000000 --- a/src/archive.md +++ /dev/null @@ -1,7 +0,0 @@ -Use the following files: - -(RECOMMENDED) jquery.nouislider.all.min.js - If you want to use libLink, wNumb and the Pips add-on. Includes noUiSlider. -(ALTERNATIVE) jquery.nouislider.min.js - noUiSlider without any additions - -(REQUIRED) jquery.nouislider.min.css - Styling (REQUIRED) -(RECOMMENDED) jquery.nouislider.pips.min.css - If you are using the Pips add-on. diff --git a/src/jquery.json b/src/jquery.json deleted file mode 100644 index 20280c1f..00000000 --- a/src/jquery.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "nouislider", - "title": "noUiSlider - jQuery Range Slider", - "description": "A lightweight, highly customizable range slider without bloat.", - "keywords": [ - "range", - "slider", - "form", - "input", - "serialize", - "handle" - ], - "licenses": [ - { - "type": "WTFPL", - "url": "http://www.wtfpl.net/" - } - ], - "version": "{{VERSION}}", - "author": { - "name": "Léon Gersen", - "url": "https://twitter.com/LeonGersen" - }, - "bugs": "https://github.com/leongersen/noUiSlider/issues", - "homepage": "http://refreshless.com/nouislider/", - "docs": "http://refreshless.com/nouislider/", - "download": "http://refreshless.com/nouislider/download/", - "dependencies": { - "jquery": ">=1.7" - } -} diff --git a/src/js/constants.js b/src/js/constants.js index df2b2cf9..3b1957c9 100644 --- a/src/js/constants.js +++ b/src/js/constants.js @@ -1,14 +1,5 @@ var - // Cache the document selector; - /** @const */ - doc = $(document), - // Make a backup of the original jQuery/Zepto .val() method. - /** @const */ - $val = $.fn.val, - // Namespace for binding and unbinding slider events; - /** @const */ - namespace = '.nui', // Determine the events to bind. IE11 implements pointerEvents without // a prefix, which breaks compatibility with the IE10 implementation. /** @const */ diff --git a/src/js/helpers.js b/src/js/helpers.js index 58250965..463e591d 100644 --- a/src/js/helpers.js +++ b/src/js/helpers.js @@ -1,9 +1,9 @@ // Removes duplicates from an array. function unique(array) { - return $.grep(array, function(el, index) { - return index === $.inArray(el, array); - }); + return array.filter(function(a){ + return !this[a] ? this[a] = true : false; + }, {}); } // Round a value to the closest 'to'. @@ -11,6 +11,28 @@ return Math.round(value / to) * to; } + // Current position of an element relative to the document. + function offset ( elem ) { + + var rect = elem.getBoundingClientRect(), + doc = elem.ownerDocument, + win = doc.defaultView || doc.parentWindow, + docElem = doc.documentElement, + xOff = win.pageXOffset; + + // getBoundingClientRect contains left scroll in Chrome on Android. + // I haven't found a feature detection that proves this. Worst case + // scenario on mis-match: the 'tap' feature on horizontal sliders breaks. + if ( /webkit.*Chrome.*Mobile/i.test(navigator.userAgent) ) { + xOff = 0; + } + + return { + top: rect.top + win.pageYOffset - docElem.clientTop, + left: rect.left + xOff - docElem.clientLeft + }; + } + // Checks whether a value is numerical. function isNumeric ( a ) { return typeof a === 'number' && !isNaN( a ) && isFinite( a ); @@ -24,9 +46,9 @@ // Sets a class and removes it after [duration] ms. function addClassFor ( element, className, duration ) { - element.addClass(className); + addClass(element, className); setTimeout(function(){ - element.removeClass(className); + removeClass(element, className); }, duration); } @@ -37,7 +59,7 @@ // Wraps a variable as an array, if it isn't one yet. function asArray ( a ) { - return $.isArray(a) ? a : [a]; + return Array.isArray(a) ? a : [a]; } // Counts decimals @@ -45,3 +67,30 @@ var pieces = numStr.split("."); return pieces.length > 1 ? pieces[1].length : 0; } + + // http://youmightnotneedjquery.com/#add_class + function addClass ( el, className ) { + if ( el.classList ) { + el.classList.add(className); + } else { + el.className += ' ' + className; + } + } + + // http://youmightnotneedjquery.com/#remove_class + function removeClass ( el, className ) { + if ( el.classList ) { + el.classList.remove(className); + } else { + el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } + } + + // http://youmightnotneedjquery.com/#has_class + function hasClass ( el, className ) { + if ( el.classList ) { + el.classList.contains(className); + } else { + new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className); + } + } diff --git a/src/js/helpers/intro.js b/src/js/helpers/intro.js deleted file mode 100644 index b412a6cf..00000000 --- a/src/js/helpers/intro.js +++ /dev/null @@ -1,6 +0,0 @@ -/*jslint browser: true */ -/*jslint white: true */ - -(function( $ ){ - - 'use strict'; diff --git a/src/js/helpers/outro.js b/src/js/helpers/outro.js deleted file mode 100644 index 95e20113..00000000 --- a/src/js/helpers/outro.js +++ /dev/null @@ -1 +0,0 @@ -}( window.jQuery || window.Zepto )); diff --git a/src/js/interface.js b/src/js/interface.js index 223b820d..0ac93425 100644 --- a/src/js/interface.js +++ b/src/js/interface.js @@ -1,94 +1,22 @@ // Run the standard initializer - function initialize ( originalOptions ) { + function initialize ( target, originalOptions ) { - // Test the options once, not for every slider. - var options = testOptions( originalOptions, this ); - - // Loop all items, and provide a new closed-scope environment. - return this.each(function(){ - closure(this, options, originalOptions); - }); - } - - // Destroy the slider, then re-enter initialization. - function rebuild ( options ) { - - return this.each(function(){ - - // The rebuild flag can be used if the slider wasn't initialized yet. - if ( !this.destroy ) { - $(this).noUiSlider( options ); - return; - } - - // Get the current values from the slider, - // including the initialization options. - var values = $(this).val(), originalOptions = this.destroy(), - - // Extend the previous options with the newly provided ones. - newOptions = $.extend( {}, originalOptions, options ); - - // Run the standard initializer. - $(this).noUiSlider( newOptions ); - - // Place Link elements back. - this.reappend(); - - // If the start option hasn't changed, - // reset the previous values. - if ( originalOptions.start === newOptions.start ) { - $(this).val(values); - } - }); - } - - // Access the internal getting and setting methods based on argument count. - function value ( ) { - return this[0][ !arguments.length ? 'vGet' : 'vSet' ].apply(this[0], arguments); - } - - // Override the .val() method. Test every element. Is it a slider? Go to - // the slider value handling. No? Use the standard method. - // Note how $.fn.val expects 'this' to be an instance of $. For convenience, - // the above 'value' function does too. - $.fn.val = function ( arg ) { - - // this === instanceof $ - - function valMethod( a ){ - return a.hasClass(Classes[0]) ? value : $val; + if ( !target.nodeName ) { + throw new Error('noUiSlider.create requires a single element.'); } - // If no value is passed, this is 'get'. - if ( !arguments.length ) { - var first = $(this[0]); - return valMethod(first).call(first); - } - - var isFunction = $.isFunction(arg); - - // Return the set so it remains chainable. Make sure not to break - // jQuery's .val(function( index, value ){}) signature. - return this.each(function( i ){ + // Test the options and create the slider environment; + var options = testOptions( originalOptions, target ), + slider = closure( target, options ); - var val = arg, $t = $(this); + // Use the public value method to set the start values. + slider.set(options.start); - if ( isFunction ) { - val = arg.call(this, i, $t.val()); - } - - valMethod($t).call($t, val); - }); - }; - -// Extend jQuery/Zepto with the noUiSlider method. - $.fn.noUiSlider = function ( options, rebuildFlag ) { - - switch ( options ) { - case 'step': return this[0].getCurrentStep(); - case 'options': return this[0].getOriginalOptions(); - } + target.noUiSlider = slider; + } - return ( rebuildFlag ? rebuild : initialize ).call(this, options); + // Use an object instead of a function for future expansibility; + return { + create: initialize }; diff --git a/src/js/intro.js b/src/js/intro.js new file mode 100644 index 00000000..9149643b --- /dev/null +++ b/src/js/intro.js @@ -0,0 +1,24 @@ +/*jslint browser: true */ +/*jslint white: true */ + +(function (factory) { + + if ( typeof define === 'function' && define.amd ) { + + // AMD. Register as an anonymous module. + define([], factory); + + } else if ( typeof exports === 'object' ) { + + // Node/CommonJS + module.exports = factory(require('jquery')); + + } else { + + // Browser globals + window.noUiSlider = factory(); + } + +}(function( ){ + + 'use strict'; diff --git a/src/js/options.js b/src/js/options.js index 54e3bc9a..06982c12 100644 --- a/src/js/options.js +++ b/src/js/options.js @@ -11,7 +11,6 @@ or true when everything is OK. It can also modify the option object, to make sure all values can be correctly looped elsewhere. */ - /** @const */ var defaultFormatter = { 'to': function( value ){ return value.toFixed(2); }, 'from': Number }; @@ -30,7 +29,7 @@ function testRange ( parsed, entry ) { // Filter incorrect input. - if ( typeof entry !== 'object' || $.isArray(entry) ) { + if ( typeof entry !== 'object' || Array.isArray(entry) ) { throw new Error("noUiSlider: 'range' is not an object."); } @@ -48,7 +47,7 @@ // Validate input. Values aren't tested, as the public .val method // will always provide a valid location. - if ( !$.isArray( entry ) || !entry.length || entry.length > 2 ) { + if ( !Array.isArray( entry ) || !entry.length || entry.length > 2 ) { throw new Error("noUiSlider: 'start' option is incorrect."); } @@ -215,18 +214,26 @@ 'format': { r: false, t: testFormat } }; - // Set defaults where applicable. - options = $.extend({ + var defaults = { 'connect': false, 'direction': 'ltr', 'behaviour': 'tap', 'orientation': 'horizontal' - }, options); + }; + + // Set defaults where applicable. + Object.keys(defaults).forEach(function ( name ) { + if ( options[name] === undefined ) { + options[name] = defaults[name]; + } + }); // Run all options through a testing mechanism to ensure correct // input. It should be noted that options might get modified to // be handled properly. E.g. wrapping integers in arrays. - $.each( tests, function( name, test ){ + Object.keys(tests).forEach(function( name ){ + + var test = tests[name]; // If the option isn't set, but it is required, throw an error. if ( options[name] === undefined ) { @@ -241,6 +248,9 @@ test.t( parsed, options[name] ); }); + // Forward pips options + parsed.pips = options.pips; + // Pre-define the styles. parsed.style = parsed.ort ? 'top' : 'left'; diff --git a/src/js/outro.js b/src/js/outro.js new file mode 100644 index 00000000..57d3e482 --- /dev/null +++ b/src/js/outro.js @@ -0,0 +1 @@ +})); \ No newline at end of file diff --git a/src/js/pips.js b/src/js/pips.js index 2302a52d..b16625c0 100644 --- a/src/js/pips.js +++ b/src/js/pips.js @@ -1,8 +1,9 @@ - function getGroup ( $Spectrum, mode, values, stepped ) { + + function getGroup ( mode, values, stepped ) { // Use the range. if ( mode === 'range' || mode === 'steps' ) { - return $Spectrum.xVal; + return scope_Spectrum.xVal; } if ( mode === 'count' ) { @@ -22,8 +23,8 @@ if ( mode === 'positions' ) { // Map all percentages to on-range values. - return $.map(values, function( value ){ - return $Spectrum.fromStepping( stepped ? $Spectrum.getStep( value ) : value ); + return values.map(function( value ){ + return scope_Spectrum.fromStepping( stepped ? scope_Spectrum.getStep( value ) : value ); }); } @@ -32,10 +33,10 @@ // If the value must be stepped, it needs to be converted to a percentage first. if ( stepped ) { - return $.map(values, function( value ){ + return values.map(function( value ){ // Convert to percentage, apply step, return to value. - return $Spectrum.fromStepping( $Spectrum.getStep( $Spectrum.toStepping( value ) ) ); + return scope_Spectrum.fromStepping( scope_Spectrum.getStep( scope_Spectrum.toStepping( value ) ) ); }); } @@ -45,12 +46,12 @@ } } - function generateSpread ( $Spectrum, density, mode, group ) { + function generateSpread ( density, mode, group ) { - var originalSpectrumDirection = $Spectrum.direction, + var originalSpectrumDirection = scope_Spectrum.direction, indexes = {}, - firstInRange = $Spectrum.xVal[0], - lastInRange = $Spectrum.xVal[$Spectrum.xVal.length-1], + firstInRange = scope_Spectrum.xVal[0], + lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length-1], ignoreFirst = false, ignoreLast = false, prevPct = 0; @@ -58,7 +59,7 @@ // This function loops the spectrum in an ltr linear fashion, // while the toStepping method is direction aware. Trick it into // believing it is ltr. - $Spectrum.direction = 0; + scope_Spectrum.direction = 0; // Create a copy of the group, sort it and filter away all duplicates. group = unique(group.slice().sort(function(a, b){ return a - b; })); @@ -75,11 +76,11 @@ ignoreLast = true; } - $.each(group, function ( index ) { + group.forEach(function ( current, index ) { // Get the current step and the lower + upper positions. var step, i, q, - low = group[index], + low = current, high = group[index+1], newPct, pctDifference, pctPos, type, steps, realSteps, stepsize; @@ -87,7 +88,7 @@ // When using 'steps' mode, use the provided steps. // Otherwise, we'll step on to the next subrange. if ( mode === 'steps' ) { - step = $Spectrum.xNumSteps[ index ]; + step = scope_Spectrum.xNumSteps[ index ]; } // Default to a 'full' step. @@ -106,7 +107,7 @@ // Get the percentage value for the current step, // calculate the size for the subrange. - newPct = $Spectrum.toStepping( i ); + newPct = scope_Spectrum.toStepping( i ); pctDifference = newPct - prevPct; steps = pctDifference / density; @@ -131,7 +132,7 @@ } // Determine the point type. - type = ($.inArray(i, group) > -1) ? 1 : ( mode === 'steps' ? 2 : 0 ); + type = (group.indexOf(i) > -1) ? 1 : ( mode === 'steps' ? 2 : 0 ); // Enforce the 'ignoreFirst' option by overwriting the type for 0. if ( !index && ignoreFirst ) { @@ -149,17 +150,18 @@ }); // Reset the spectrum. - $Spectrum.direction = originalSpectrumDirection; + scope_Spectrum.direction = originalSpectrumDirection; return indexes; } - function addMarking ( CSSstyle, orientation, direction, spread, filterFunc, formatter ) { + function addMarking ( spread, filterFunc, formatter ) { - var style = ['horizontal', 'vertical'][orientation], - element = $('
'); + var style = ['horizontal', 'vertical'][options.ort], + element = document.createElement('div'); - element.addClass('noUi-pips noUi-pips-'+style); + addClass(element, 'noUi-pips'); + addClass(element, 'noUi-pips-' + style); function getSize( type, value ){ return [ '-normal', '-large', '-sub' ][type]; @@ -169,12 +171,12 @@ return 'class="' + source + ' ' + source + '-' + style + ' ' + source + getSize(values[1], values[0]) + - '" style="' + CSSstyle + ': ' + offset + '%"'; + '" style="' + options.style + ': ' + offset + '%"'; } function addSpread ( offset, values ){ - if ( direction ) { + if ( scope_Spectrum.direction ) { offset = 100 - offset; } @@ -182,44 +184,38 @@ values[1] = (values[1] && filterFunc) ? filterFunc(values[0], values[1]) : values[1]; // Add a marker for every point - element.append('
'); + element.innerHTML += '
'; // Values are only appended for points marked '1' or '2'. if ( values[1] ) { - element.append('
' + formatter.to(values[0]) + '
'); + element.innerHTML += '
' + formatter.to(values[0]) + '
'; } } // Append all points. - $.each(spread, addSpread); + Object.keys(spread).forEach(function(a){ + addSpread(a, spread[a]); + }); return element; } - $.fn.noUiSlider_pips = function ( grid ) { + function pips ( grid ) { var mode = grid.mode, density = grid.density || 1, filter = grid.filter || false, values = grid.values || false, + stepped = grid.stepped || false, + group = getGroup( mode, values, stepped ), + spread = generateSpread( density, mode, group ), format = grid.format || { to: Math.round - }, - stepped = grid.stepped || false; - - return this.each(function(){ - - var info = this.getInfo(), - group = getGroup( info[0], mode, values, stepped ), - spread = generateSpread( info[0], density, mode, group ); - - return $(this).append(addMarking( - info[1], - info[2], - info[0].direction, - spread, - filter, - format - )); - }); - }; + }; + + return scope_Target.appendChild(addMarking( + spread, + filter, + format + )); + } diff --git a/src/js/scope.js b/src/js/scope.js index 1e5b0e31..b2d72282 100644 --- a/src/js/scope.js +++ b/src/js/scope.js @@ -2,16 +2,16 @@ // Test suggested values and apply margin, step. function setHandle ( handle, to, noLimitOption ) { - var trigger = handle[0] !== $Handles[0][0] ? 1 : 0, - lowerMargin = $Locations[0] + options.margin, - upperMargin = $Locations[1] - options.margin, - lowerLimit = $Locations[0] + options.limit, - upperLimit = $Locations[1] - options.limit; + var trigger = handle !== scope_Handles[0] ? 1 : 0, + lowerMargin = scope_Locations[0] + options.margin, + upperMargin = scope_Locations[1] - options.margin, + lowerLimit = scope_Locations[0] + options.limit, + upperLimit = scope_Locations[1] - options.limit; // For sliders with multiple handles, // limit movement to the other handle. // Apply the margin option by adding it to the handle positions. - if ( $Handles.length > 1 ) { + if ( scope_Handles.length > 1 ) { to = trigger ? Math.max( to, lowerMargin ) : Math.min( to, upperMargin ); } @@ -19,37 +19,40 @@ // maximum distance from another. Limit must be > 0, as otherwise // handles would be unmoveable. 'noLimitOption' is set to 'false' // for the .val() method, except for pass 4/4. - if ( noLimitOption !== false && options.limit && $Handles.length > 1 ) { + if ( noLimitOption !== false && options.limit && scope_Handles.length > 1 ) { to = trigger ? Math.min ( to, lowerLimit ) : Math.max( to, upperLimit ); } // Handle the step option. - to = $Spectrum.getStep( to ); + to = scope_Spectrum.getStep( to ); // Limit to 0/100 for .val input, trim anything beyond 7 digits, as // JavaScript has some issues in its floating point implementation. to = limit(parseFloat(to.toFixed(7))); // Return false if handle can't move. - if ( to === $Locations[trigger] ) { + if ( to === scope_Locations[trigger] ) { return false; } // Set the handle to the new position. - handle.css( options.style, to + '%' ); + handle.style[options.style] = to + '%'; // Force proper handle stacking - if ( handle.is(':first-child') ) { - handle.toggleClass(Classes[17], to > 50 ); + if ( !handle.previousSibling ) { + removeClass(handle, Classes[17]); + if ( to > 50 ) { + addClass(handle, Classes[17]); + } } // Update locations. - $Locations[trigger] = to; + scope_Locations[trigger] = to; // Convert the value to the slider stepping/range. - $Values[trigger] = $Spectrum.fromStepping( to ); + scope_Values[trigger] = scope_Spectrum.fromStepping( to ); - linkUpdate(triggerPos[trigger]); + fireEvent('update', trigger); return true; } @@ -87,9 +90,8 @@ // Request an update for all links if the value was invalid. // Do so too if setting the handle fails. - if ( to === false || isNaN(to) || setHandle( $Handles[trigger], $Spectrum.toStepping( to ), i === (3 - options.dir) ) === false ) { - - linkUpdate(triggerPos[trigger]); + if ( to === false || isNaN(to) || setHandle( scope_Handles[trigger], scope_Spectrum.toStepping( to ), i === (3 - options.dir) ) === false ) { + fireEvent('update', trigger); } } } @@ -98,12 +100,7 @@ // Set the slider value. function valueSet ( input ) { - // LibLink: don't accept new values when currently emitting changes. - if ( $Target[0].LinkIsEmitting ) { - return this; - } - - var count, values = asArray( input ); + var count, values = asArray( input ), i; // The RTL settings is implemented by reversing the front-end, // internal mechanisms are the same. @@ -112,14 +109,13 @@ } // Animation is optional. - // Make sure the initial values where set before using animated - // placement. (no report, unit testing); - if ( options.animate && $Locations[0] !== -1 ) { - addClassFor( $Target, Classes[14], 300 ); + // Make sure the initial values where set before using animated placement. + if ( options.animate && scope_Locations[0] !== -1 ) { + addClassFor( scope_Target, Classes[14], 300 ); } // Determine how often to set the handles. - count = $Handles.length > 1 ? 3 : 1; + count = scope_Handles.length > 1 ? 3 : 1; if ( values.length === 1 ) { count = 1; @@ -127,11 +123,10 @@ setValues ( count, values ); - // Fire the 'set' event. As of noUiSlider 7, - // this is no longer optional. - fireEvents(['set']); - - return this; + // Fire the 'set' event for both handles. + for ( i = 0; i < scope_Handles.length; i++ ) { + fireEvent('set', i); + } } // Get the slider value. @@ -141,33 +136,20 @@ // Get the value from all handles. for ( i = 0; i < options.handles; i += 1 ){ - retour[i] = options.format.to( $Values[i] ); + retour[i] = options.format.to( scope_Values[i] ); } return inSliderOrder( retour ); } - // Destroy the slider and unbind all events. - function destroyTarget ( ) { - - // Unbind events on the slider, remove all classes and child elements. - $(this).off(namespace) - .removeClass(Classes.join(' ')) - .empty(); - - delete this.LinkUpdate; - delete this.LinkConfirm; - delete this.LinkDefaultFormatter; - delete this.LinkDefaultFlag; - delete this.reappend; - delete this.vGet; - delete this.vSet; - delete this.getCurrentStep; - delete this.getInfo; - delete this.destroy; - - // Return the original options from the closure. - return originalOptions; + // Removes classes from the root and empties it. + function destroy ( ) { + Classes.forEach(function(cls){ + if ( !cls ) { return; } // Ignore empty classes + removeClass(scope_Target, cls); + }); + scope_Target.innerHTML = ''; + delete scope_Target.noUiSlider; } // Get the current step size for the slider. @@ -175,16 +157,16 @@ // Check all locations, map them to their stepping point. // Get the step point, then find it in the input list. - var retour = $.map($Locations, function( location, index ){ + var retour = scope_Locations.map(function( location, index ){ - var step = $Spectrum.getApplicableStep( location ), + var step = scope_Spectrum.getApplicableStep( location ), // As per #391, the comparison for the decrement step can have some rounding issues. // Round the value to the precision used in the step. stepDecimals = countDecimals(String(step[2])), // Get the current numeric value - value = $Values[index], + value = scope_Values[index], // To move the slider 'one step up', the current step value needs to be added. // Use null if we are at the maximum slider value. @@ -198,53 +180,70 @@ // previous step. Return null if the slider is at its minimum value. decrement = location === 0 ? null : (prev >= step[1]) ? step[2] : (step[0] || false); - return [[decrement, increment]]; + return [decrement, increment]; }); // Return values in the proper order. return inSliderOrder( retour ); } - // Get the original set of options. - function getOriginalOptions ( ) { - return originalOptions; + // Attach an event to this slider, possibly including a namespace + function bindEvent ( namespacedEvent, callback ) { + scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || []; + scope_Events[namespacedEvent].push(callback); + + // If the event bound is 'update,' fire it immediately for all handles. + if ( namespacedEvent.split('.')[0] === 'update' ) { + scope_Handles.forEach(function(a, index){ + fireEvent('update', index); + }); + } } + // Undo attachment of event + function removeEvent ( namespacedEvent ) { + + var event = namespacedEvent.split('.')[0], + namespace = namespacedEvent.substring(event.length); + + Object.keys(scope_Events).forEach(function( bind ){ + + var tEvent = bind.split('.')[0], + tNamespace = bind.substring(tEvent.length); + + if ( (!event || event === tEvent) && (!namespace || namespace === tNamespace) ) { + delete scope_Events[bind]; + } + }); + } -// Initialize slider // Throw an error if the slider was already initialized. - if ( $Target.hasClass(Classes[0]) ) { + if ( scope_Target.noUiSlider ) { throw new Error('Slider was already initialized.'); } + // Create the base element, initialise HTML and set classes. // Add handles and links. - $Base = addSlider( options.dir, options.ort, $Target ); - $Handles = addHandles( options.handles, options.dir, $Base ); + scope_Base = addSlider( options.dir, options.ort, scope_Target ); + scope_Handles = addHandles( options.handles, options.dir, scope_Base ); // Set the connect classes. - addConnection ( options.connect, $Target, $Handles ); + addConnection ( options.connect, scope_Target, scope_Handles ); // Attach user events. events( options.events ); -// Methods - - target.vSet = valueSet; - target.vGet = valueGet; - target.destroy = destroyTarget; - - target.getCurrentStep = getCurrentStep; - target.getOriginalOptions = getOriginalOptions; + if ( options.pips ) { + pips(options.pips); + } - target.getInfo = function(){ - return [ - $Spectrum, - options.style, - options.ort - ]; + return { + destroy: destroy, + steps: getCurrentStep, + on: bindEvent, + off: removeEvent, + get: valueGet, + set: valueSet }; - - // Use the public value method to set the start values. - $Target.val( options.start ); diff --git a/src/js/scope_events.js b/src/js/scope_events.js index e9a43ba7..07d3f8bc 100644 --- a/src/js/scope_events.js +++ b/src/js/scope_events.js @@ -3,133 +3,174 @@ function attach ( events, element, callback, data ) { // This function can be used to 'filter' events to the slider. + // element is a node, not a nodeList - // Add the noUiSlider namespace to all events. - events = events.replace( /\s/g, namespace + ' ' ) + namespace; + var method = function ( e ){ - // Bind a closure on the target. - return element.on( events, function( e ){ - - // jQuery and Zepto (1) handle unset attributes differently, - // but always falsy; #208 - if ( !!$Target.attr('disabled') ) { + if ( scope_Target.hasAttribute('disabled') ) { return false; } // Stop if an active 'tap' transition is taking place. - if ( $Target.hasClass( Classes[14] ) ) { + if ( hasClass(scope_Target, Classes[14]) ) { return false; } e = fixEvent(e); + + // Ignore right or middle clicks on start #454 + if ( events === actions.start && e.buttons !== undefined && e.buttons !== 1 ) { + return false; + } + e.calcPoint = e.points[ options.ort ]; // Call the event handler with the event [ and additional data ]. callback ( e, data ); + + }, methods = []; + + // Bind a closure on the target for every event type. + events.split(' ').forEach(function( eventName ){ + element.addEventListener(eventName, method, false); + methods.push([eventName, method]); }); + + return methods; } // Handle movement on document for handle and range drag. function move ( event, data ) { - var handles = data.handles || $Handles, positions, state = false, + var handles = data.handles || scope_Handles, positions, state = false, proposal = ((event.calcPoint - data.start) * 100) / baseSize(), - h = handles[0][0] !== $Handles[0][0] ? 1 : 0; + handleNumber = handles[0] === scope_Handles[0] ? 0 : 1; // Calculate relative positions for the handles. positions = getPositions( proposal, data.positions, handles.length > 1); - state = setHandle ( handles[0], positions[h], handles.length === 1 ); + state = setHandle ( handles[0], positions[handleNumber], handles.length === 1 ); if ( handles.length > 1 ) { - state = setHandle ( handles[1], positions[h?0:1], false ) || state; - } - // Fire the 'slide' event if any handle moved. - if ( state ) { - fireEvents(['slide']); + state = setHandle ( handles[1], positions[handleNumber?0:1], false ) || state; + + if ( state ) { + // fire for both handles + for ( i = 0; i < data.handles.length; i++ ) { + fireEvent('slide', i); + } + } + } else if ( state ) { + // Fire for a single handle + fireEvent('slide', handleNumber); } } // Unbind move events on document, call callbacks. - function end ( event ) { + function end ( event, data ) { // The handle is no longer active, so remove the class. - $('.' + Classes[15]).removeClass(Classes[15]); + var active = scope_Base.getElementsByClassName(Classes[15]), + handleNumber = data.handles[0] === scope_Handles[0] ? 0 : 1; + + if ( active.length ) { + removeClass(active[0], Classes[15]); + } // Remove cursor styles and text-selection events bound to the body. if ( event.cursor ) { - $('body').css('cursor', '').off( namespace ); + document.body.style.cursor = ''; + document.body.removeEventListener('selectstart', document.body.noUiListener); } + var d = document.documentElement; + // Unbind the move and end events, which are added on 'start'. - doc.off( namespace ); + d.noUiListeners.forEach(function( c ) { + d.removeEventListener(c[0], c[1]); + }); // Remove dragging class. - $Target.removeClass(Classes[12]); + removeClass(scope_Target, Classes[12]); // Fire the change and set events. - fireEvents(['set', 'change']); + fireEvent('set', handleNumber); + fireEvent('change', handleNumber); } // Bind move events on document. function start ( event, data ) { + var d = document.documentElement; + // Mark the handle as 'active' so it can be styled. - if( data.handles.length === 1 ) { - data.handles[0].children().addClass(Classes[15]); + if ( data.handles.length === 1 ) { + addClass(data.handles[0].children[0], Classes[15]); + + // Support 'disabled' handles + if ( data.handles[0].hasAttribute('disabled') ) { + return false; + } } // A drag should never propagate up to the 'tap' event. event.stopPropagation(); - // Attach the move event. - attach ( actions.move, doc, move, { + // Attach the move and end events. + var moveEvent = attach(actions.move, d, move, { start: event.calcPoint, handles: data.handles, positions: [ - $Locations[0], - $Locations[$Handles.length - 1] + scope_Locations[0], + scope_Locations[scope_Handles.length - 1] ] + }), endEvent = attach(actions.end, d, end, { + handles: data.handles }); - // Unbind all movement when the drag ends. - attach ( actions.end, doc, end, null ); + d.noUiListeners = moveEvent.concat(endEvent); // Text selection isn't an issue on touch devices, // so adding cursor styles can be skipped. if ( event.cursor ) { // Prevent the 'I' cursor and extend the range-drag cursor. - $('body').css('cursor', $(event.target).css('cursor')); + document.body.style.cursor = getComputedStyle(event.target).cursor; // Mark the target with a dragging state. - if ( $Handles.length > 1 ) { - $Target.addClass(Classes[12]); + if ( scope_Handles.length > 1 ) { + addClass(scope_Target, Classes[12]); } + var f = function(){ + return false; + }; + + document.body.noUiListener = f; + // Prevent text selection when dragging the handles. - $('body').on('selectstart' + namespace, false); + document.body.addEventListener('selectstart', f, false); } } // Move closest handle to tapped location. function tap ( event ) { - var location = event.calcPoint, total = 0, to; + var location = event.calcPoint, total = 0, handleNumber, to; // The tap event shouldn't propagate up and cause 'edge' to run. event.stopPropagation(); // Add up the handle offsets. - $.each( $Handles, function(){ - total += this.offset()[ options.style ]; + scope_Handles.forEach(function(a){ + total += offset(a)[ options.style ]; }); // Find the handle closest to the tapped position. - total = ( location < total/2 || $Handles.length === 1 ) ? 0 : 1; + handleNumber = ( location < total/2 || scope_Handles.length === 1 ) ? 0 : 1; - location -= $Base.offset()[ options.style ]; + location -= offset(scope_Base)[ options.style ]; // Calculate the new position. to = ( location * 100 ) / baseSize(); @@ -137,17 +178,24 @@ if ( !options.events.snap ) { // Flag the slider as it is now in a transitional state. // Transition takes 300 ms, so re-enable the slider afterwards. - addClassFor( $Target, Classes[14], 300 ); + addClassFor( scope_Target, Classes[14], 300 ); + } + + // Support 'disabled' handles + if ( scope_Handles[handleNumber].hasAttribute('disabled') ) { + return false; } // Find the closest handle and calculate the tapped point. // The set handle to the new position. - setHandle( $Handles[total], to ); + setHandle( scope_Handles[handleNumber], to ); - fireEvents(['slide', 'set', 'change']); + fireEvent('slide', handleNumber); + fireEvent('set', handleNumber); + fireEvent('change', handleNumber); if ( options.events.snap ) { - start(event, { handles: [$Handles[total]] }); + start(event, { handles: [scope_Handles[total]] }); } } @@ -159,12 +207,12 @@ // Attach the standard drag event to the handles. if ( !behaviour.fixed ) { - for ( i = 0; i < $Handles.length; i += 1 ) { + for ( i = 0; i < scope_Handles.length; i += 1 ) { // These events are only bound to the visual handle // element, not the 'real' origin element. - attach ( actions.start, $Handles[i].children(), start, { - handles: [ $Handles[i] ] + attach ( actions.start, scope_Handles[i].children[0], start, { + handles: [ scope_Handles[i] ] }); } } @@ -172,26 +220,29 @@ // Attach the tap event to the slider base. if ( behaviour.tap ) { - attach ( actions.start, $Base, tap, { - handles: $Handles + attach ( actions.start, scope_Base, tap, { + handles: scope_Handles }); } // Make the range dragable. if ( behaviour.drag ){ - drag = $Base.find( '.' + Classes[7] ).addClass( Classes[10] ); + drag = [scope_Base.getElementsByClassName( Classes[7] )[0]]; + addClass(drag[0], Classes[10]); // 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 ( behaviour.fixed ) { - drag = drag.add($Base.children().not( drag ).children()); + drag.push(scope_Handles[(drag[0] === scope_Handles[0] ? 1 : 0)].children[0]); } - attach ( actions.start, drag, start, { - handles: $Handles + drag.forEach(function( element ) { + attach ( actions.start, element, start, { + handles: scope_Handles + }); }); } } diff --git a/src/js/scope_helpers.js b/src/js/scope_helpers.js index 54bc8e83..a656e970 100644 --- a/src/js/scope_helpers.js +++ b/src/js/scope_helpers.js @@ -1,21 +1,28 @@ -// Helpers // Shorthand for base dimensions. function baseSize ( ) { - return $Base[['width', 'height'][options.ort]](); + return scope_Base['offset' + ['Width', 'Height'][options.ort]]; } // External event handling - function fireEvents ( events ) { + function fireEvent ( event, handleNumber ) { - // Use the external api to get the values. - // Wrap the values in an array, as .trigger takes - // only one additional argument. - var index, values = [ $Target.val() ]; - - for ( index = 0; index < events.length; index += 1 ){ - $Target.trigger(events[index], values); + if ( handleNumber !== undefined ) { + handleNumber = Math.abs(handleNumber - options.dir); } + + Object.keys(scope_Events).forEach(function( targetEvent ) { + + var eventType = targetEvent.split('.')[0]; + + if ( event === eventType ) { + scope_Events[targetEvent].forEach(function( callback ) { + // .reverse is in place + // Return values as array, so arg_1[arg_2] is always valid. + callback( asArray(valueGet()), handleNumber, inSliderOrder(Array.prototype.slice.call(scope_Values)) ); + }); + } + }); } // Returns the input array, respecting the slider direction configuration. diff --git a/src/js/scope_link.js b/src/js/scope_link.js deleted file mode 100644 index df9d07fd..00000000 --- a/src/js/scope_link.js +++ /dev/null @@ -1,65 +0,0 @@ -// libLink integration - - // Create a new function which calls .val on input change. - function createChangeHandler ( trigger ) { - return function ( ignore, value ){ - // Determine which array position to 'null' based on 'trigger'. - $Target.val( [ trigger ? null : value, trigger ? value : null ], true ); - }; - } - - // Called by libLink when it wants a set of links updated. - function linkUpdate ( flag ) { - - var trigger = $.inArray(flag, triggerPos); - - // The API might not have been set yet. - if ( $Target[0].linkAPI && $Target[0].linkAPI[flag] ) { - $Target[0].linkAPI[flag].change( - $Values[trigger], - $Handles[trigger].children(), - $Target - ); - } - } - - // Called by libLink to append an element to the slider. - function linkConfirm ( flag, element ) { - - // Find the trigger for the passed flag. - var trigger = $.inArray(flag, triggerPos); - - // If set, append the element to the handle it belongs to. - if ( element ) { - element.appendTo( $Handles[trigger].children() ); - } - - // The public API is reversed for rtl sliders, so the changeHandler - // should not be aware of the inverted trigger positions. - // On rtl slider with one handle, 'lower' should be used. - if ( options.dir && options.handles > 1 ) { - trigger = trigger === 1 ? 0 : 1; - } - - return createChangeHandler( trigger ); - } - - // Place elements back on the slider. - function reAppendLink ( ) { - - var i, flag; - - // The API keeps a list of elements: we can re-append them on rebuild. - for ( i = 0; i < triggerPos.length; i += 1 ) { - if ( this.linkAPI && this.linkAPI[(flag = triggerPos[i])] ) { - this.linkAPI[flag].reconfirm(flag); - } - } - } - - target.LinkUpdate = linkUpdate; - target.LinkConfirm = linkConfirm; - target.LinkDefaultFormatter = options.format; - target.LinkDefaultFlag = 'lower'; - - target.reappend = reAppendLink; diff --git a/src/js/scope_start.js b/src/js/scope_start.js index 7e05ae37..d5f8dfc5 100644 --- a/src/js/scope_start.js +++ b/src/js/scope_start.js @@ -1,19 +1,11 @@ -function closure ( target, options, originalOptions ){ -// Internal variables +function closure ( target, options ){ - // All variables local to 'closure' are marked $. - var $Target = $(target), - $Locations = [-1, -1], - $Base, - $Handles, - $Spectrum = options.spectrum, - $Values = [], - // libLink. For rtl sliders, 'lower' and 'upper' should not be inverted - // for one-handle sliders, so trim 'upper' it that case. - triggerPos = ['lower', 'upper'].slice(0, options.handles); - - // Invert the libLink connection for rtl sliders. - if ( options.dir ) { - triggerPos.reverse(); - } + // All variables local to 'closure' are prefixed with 'scope_' + var scope_Target = target, + scope_Locations = [-1, -1], + scope_Base, + scope_Handles, + scope_Spectrum = options.spectrum, + scope_Values = [], + scope_Events = {}; diff --git a/src/js/structure.js b/src/js/structure.js index b58c1be9..f2840a38 100644 --- a/src/js/structure.js +++ b/src/js/structure.js @@ -1,4 +1,3 @@ -// Class handling // Delimit proposed values for handle positions. function getPositions ( a, b, delimit ) { @@ -23,9 +22,6 @@ return [c,d]; } - -// Event handling - // Provide a clean event with standardized offset values. function fixEvent ( e ) { @@ -36,22 +32,16 @@ // 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; + 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'. @@ -60,42 +50,34 @@ } 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; } event.points = [x, y]; - event.cursor = mouse; + event.cursor = mouse || pointer; // Fix #435 return event; } - -// DOM additions - // Append a handle to the base. function addHandle ( direction, index ) { - var handle = $('
').addClass( Classes[2] ), + var origin = document.createElement('div'), + handle = document.createElement('div'), additions = [ '-lower', '-upper' ]; if ( direction ) { additions.reverse(); } - handle.children().addClass( - Classes[3] + " " + Classes[3]+additions[index] - ); + addClass(handle, Classes[3]); + addClass(handle, Classes[3] + additions[index]); - return handle; + addClass(origin, Classes[2]); + origin.appendChild(handle); + + return origin; } // Add the proper connection classes. @@ -106,14 +88,14 @@ // segments listed in the class list, to allow easy // renaming and provide a minor compression benefit. switch ( connect ) { - case 1: target.addClass( Classes[7] ); - handles[0].addClass( Classes[6] ); + case 1: addClass(target, Classes[7]); + addClass(handles[0], Classes[6]); break; - case 3: handles[1].addClass( Classes[6] ); + case 3: addClass(handles[1], Classes[6]); /* falls through */ - case 2: handles[0].addClass( Classes[7] ); + case 2: addClass(handles[0], Classes[7]); /* falls through */ - case 0: target.addClass(Classes[6]); + case 0: addClass(target, Classes[6]); break; } } @@ -127,7 +109,7 @@ for ( index = 0; index < nrHandles; index += 1 ) { // Keep a list of all added handles. - handles.push( addHandle( direction, index ).appendTo(base) ); + handles.push( base.appendChild(addHandle( direction, index )) ); } return handles; @@ -137,11 +119,12 @@ function addSlider ( direction, orientation, target ) { // Apply classes and data to the target. - target.addClass([ - Classes[0], - Classes[8 + direction], - Classes[4 + orientation] - ].join(' ')); - - return $('
').appendTo(target).addClass( Classes[1] ); + addClass(target, Classes[0]); + addClass(target, Classes[8 + direction]); + addClass(target, Classes[4 + orientation]); + + var div = document.createElement('div'); + addClass(div, Classes[1]); + target.appendChild(div); + return div; } diff --git a/src/jquery.nouislider.css b/src/nouislider.css similarity index 95% rename from src/jquery.nouislider.css rename to src/nouislider.css index ca948d88..d07b87f6 100644 --- a/src/jquery.nouislider.css +++ b/src/nouislider.css @@ -21,6 +21,7 @@ width: 100%; height: 100%; position: relative; + z-index: 1; /* Fix 401 */ } .noUi-origin { position: absolute; @@ -38,11 +39,6 @@ its values is > 50%. */ z-index: 10; } -.noUi-stacking + .noUi-origin { -/* Fix stacking order in IE7, which incorrectly - creates a new context for the origins. */ - *z-index: -1; -} .noUi-state-tap .noUi-origin { -webkit-transition: left 0.3s, top 0.3s; transition: left 0.3s, top 0.3s; @@ -160,6 +156,7 @@ [disabled] .noUi-connect { background: #B8B8B8; } +[disabled].noUi-origin, [disabled] .noUi-handle { cursor: not-allowed; } diff --git a/src/jquery.nouislider.pips.css b/src/nouislider.pips.css similarity index 100% rename from src/jquery.nouislider.pips.css rename to src/nouislider.pips.css diff --git a/submodules/libLink b/submodules/libLink deleted file mode 160000 index e6a1ddf4..00000000 --- a/submodules/libLink +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e6a1ddf4bd411e9f793db80c8692314783d28200 diff --git a/submodules/wNumb b/submodules/wNumb deleted file mode 160000 index 71e844f6..00000000 --- a/submodules/wNumb +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 71e844f61362adf43d1a339cd2747834119189e8 diff --git a/tests/addon_pips.js b/tests/addon_pips.js index d6ea967a..374f6053 100644 --- a/tests/addon_pips.js +++ b/tests/addon_pips.js @@ -3,168 +3,150 @@ return value%1000 ? 2 : 1; } - function test_slider( first ){ + function test_slider( pips, first ){ - Q.html('\ -
\ - '); + Q.innerHTML = '
'; + var slider = Q.getElementsByClassName('slider')[0]; - return Q.find("#slider").noUiSlider({ + noUiSlider.create(slider, { range: { 'min': [ (first || 0) ], '10%': [ 500, 500 ], '50%': [ 4000, 1000 ], 'max': [ 10000 ] }, - start: 0 - }) + start: 0, + pips: pips + }); + + return slider; } // RANGE - test( "Range", function(){ + QUnit.test( "Range", function( assert ){ - var slider = test_slider(); - - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'range', density: 3, - format: wNumb({ - decimals: 2 - }) + format: { + to: function( value ){ + return value.toFixed(2); + } + } }); - ok( Q.find('.noUi-pips'), 'Pips where created' ); + assert.ok( Q.getElementsByClassName('noUi-pips').length, 'Pips where created' ); + + var markers = Q.getElementsByClassName('noUi-marker'); + assert.ok( markers.length >= 32 && markers.length <= 34, 'Density of 1/3 was applied' ); - var markers = Q.find('.noUi-marker'); - ok( markers.length >= 32 && markers.length <= 34, 'Density of 1/3 was applied' ); - // Test formatter - equal( Q.find('.noUi-value').first().text(), '0.00' ); + assert.equal( Q.getElementsByClassName('noUi-value')[0].innerHTML, '0.00' ); }); - test( "Steps", function(){ + QUnit.test( "Steps", function( assert ){ - var slider = test_slider(); - - // STEPS - - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'steps', density: 2, filter: filter500 }); - var markers = Q.find('.noUi-marker').length; - ok( markers >= 49 && markers <= 51, 'Density of 1/2 was applied' ); - - }); + // STEPS - test( "Positions", function(){ + var markers = Q.getElementsByClassName('noUi-marker').length; + assert.ok( markers >= 49 && markers <= 51, 'Density of 1/2 was applied' ); - var slider = test_slider(); + }); - // POSITIONS + QUnit.test( "Positions", function( assert ){ - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'positions', values: [0,25,50,75,100] }); - equal( Q.find('.noUi-marker-large').length, 5, 'Large markers added for all values' ); - equal( Q.find('.noUi-value').length, 5 ); + // POSITIONS + + assert.equal( Q.getElementsByClassName('noUi-marker-large').length, 5, 'Large markers added for all values' ); + assert.equal( Q.getElementsByClassName('noUi-value').length, 5 ); var pos = []; - Q.find('.noUi-value').each(function(){ - pos.push(parseInt(this.style.left)); + Array.prototype.forEach.call(Q.getElementsByClassName('noUi-value'), function( el ){ + pos.push(parseInt(el.style.left)); }); - deepEqual(pos, [0,25,50,75,100], 'Values placed on proper positions'); + assert.deepEqual(pos, [0,25,50,75,100], 'Values placed on proper positions'); }); - test( "Positions, stepped", function(){ + QUnit.test( "Positions, stepped", function( assert ){ expect(0); // TODO - var slider = test_slider(); - - // POSITIONS (STEPPED) - - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'positions', values: [0,25,50,75,100], stepped: true }); + // POSITIONS (STEPPED) }); - test( "Count", function(){ - - var slider = test_slider(); - - // COUNT + QUnit.test( "Count", function( assert ){ - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'count', values: 8 }); - equal( Q.find('.noUi-value').length, 8, 'Placed requested number of values' ); + // COUNT + + assert.equal( Q.getElementsByClassName('noUi-value').length, 8, 'Placed requested number of values' ); var pos2 = []; - Q.find('.noUi-value').each(function(){ - pos2.push(parseInt(this.style.left)); + Array.prototype.forEach.call(Q.getElementsByClassName('noUi-value'), function( el ){ + pos2.push(parseInt(el.style.left)); }); - deepEqual(pos2, [0, Math.floor((100/7)*1), Math.floor((100/7)*2), Math.floor((100/7)*3), Math.floor((100/7)*4), Math.floor((100/7)*5), Math.floor((100/7)*6), 100], 'Values spread evenly'); + assert.deepEqual(pos2, [0, Math.floor((100/7)*1), Math.floor((100/7)*2), Math.floor((100/7)*3), Math.floor((100/7)*4), Math.floor((100/7)*5), Math.floor((100/7)*6), 100], 'Values spread evenly'); }); - test( "Count, stepped", function(){ + QUnit.test( "Count, stepped", function( assert ){ expect(0); // TODO - var slider = test_slider(); - - // COUNT (STEPPED) - - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'count', values: 8, stepped: true }); - }); // VALUES - test( "Values", function(){ + QUnit.test( "Values", function( assert ){ // #357 - var slider = test_slider( 1 ); - - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'values', values: [50, 552, 750, 940, 5000, 6080, 9000] - }); - - equal( Q.find('.noUi-value').length, 7, 'Placed requested number of values' ); + }, 1 ); + assert.equal( Q.getElementsByClassName('noUi-value').length, 7, 'Placed requested number of values' ); }); // VALUES (STEPPED) - test( "Values, stepped", function(){ - - var slider = test_slider(); + QUnit.test( "Values, stepped", function( assert ){ - slider.noUiSlider_pips({ + var slider = test_slider({ mode: 'values', values: [50, 552, 750, 940, 5000, 6080, 9000], stepped: true }); - equal( Q.find('.noUi-value').length, 6, 'Removed duplicate in step' ); - + assert.equal( Q.getElementsByClassName('noUi-value').length, 6, 'Removed duplicate in step' ); }); diff --git a/tests/blanket.min.js b/tests/blanket.min.js new file mode 100644 index 00000000..b5ce8aaf --- /dev/null +++ b/tests/blanket.min.js @@ -0,0 +1,39 @@ +/*! blanket - v1.1.5 */ +"undefined"!=typeof QUnit&&(QUnit.config.autostart=!1),function(a){/* + Copyright (C) 2013 Ariya Hidayat + Copyright (C) 2013 Thaddee Tyl + Copyright (C) 2013 Mathias Bynens + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Mathias Bynens + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +!function(b,c){"use strict";"function"==typeof a&&a.amd?a(["exports"],c):c("undefined"!=typeof exports?exports:b.esprima={})}(this,function(a){"use strict";function b(a,b){if(!a)throw new Error("ASSERT: "+b)}function c(a){return a>=48&&57>=a}function d(a){return"0123456789abcdefABCDEF".indexOf(a)>=0}function e(a){return"01234567".indexOf(a)>=0}function f(a){return 32===a||9===a||11===a||12===a||160===a||a>=5760&&[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].indexOf(a)>=0}function g(a){return 10===a||13===a||8232===a||8233===a}function h(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a||92===a||a>=128&&ec.NonAsciiIdentifierStart.test(String.fromCharCode(a))}function i(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a||a>=48&&57>=a||92===a||a>=128&&ec.NonAsciiIdentifierPart.test(String.fromCharCode(a))}function j(a){switch(a){case"class":case"enum":case"export":case"extends":case"import":case"super":return!0;default:return!1}}function k(a){switch(a){case"implements":case"interface":case"package":case"private":case"protected":case"public":case"static":case"yield":case"let":return!0;default:return!1}}function l(a){return"eval"===a||"arguments"===a}function m(a){if(hc&&k(a))return!0;switch(a.length){case 2:return"if"===a||"in"===a||"do"===a;case 3:return"var"===a||"for"===a||"new"===a||"try"===a||"let"===a;case 4:return"this"===a||"else"===a||"case"===a||"void"===a||"with"===a||"enum"===a;case 5:return"while"===a||"break"===a||"catch"===a||"throw"===a||"const"===a||"yield"===a||"class"===a||"super"===a;case 6:return"return"===a||"typeof"===a||"delete"===a||"switch"===a||"export"===a||"import"===a;case 7:return"default"===a||"finally"===a||"extends"===a;case 8:return"function"===a||"continue"===a||"debugger"===a;case 10:return"instanceof"===a;default:return!1}}function n(a,c,d,e,f){var g;b("number"==typeof d,"Comment must have valid position"),oc.lastCommentStart>=d||(oc.lastCommentStart=d,g={type:a,value:c},pc.range&&(g.range=[d,e]),pc.loc&&(g.loc=f),pc.comments.push(g),pc.attachComment&&(pc.leadingComments.push(g),pc.trailingComments.push(g)))}function o(a){var b,c,d,e;for(b=ic-a,c={start:{line:jc,column:ic-kc-a}};lc>ic;)if(d=gc.charCodeAt(ic),++ic,g(d))return pc.comments&&(e=gc.slice(b+a,ic-1),c.end={line:jc,column:ic-kc-1},n("Line",e,b,ic-1,c)),13===d&&10===gc.charCodeAt(ic)&&++ic,++jc,void(kc=ic);pc.comments&&(e=gc.slice(b+a,ic),c.end={line:jc,column:ic-kc},n("Line",e,b,ic,c))}function p(){var a,b,c,d;for(pc.comments&&(a=ic-2,b={start:{line:jc,column:ic-kc-2}});lc>ic;)if(c=gc.charCodeAt(ic),g(c))13===c&&10===gc.charCodeAt(ic+1)&&++ic,++jc,++ic,kc=ic,ic>=lc&&O({},dc.UnexpectedToken,"ILLEGAL");else if(42===c){if(47===gc.charCodeAt(ic+1))return++ic,++ic,void(pc.comments&&(d=gc.slice(a+2,ic-2),b.end={line:jc,column:ic-kc},n("Block",d,a,ic,b)));++ic}else++ic;O({},dc.UnexpectedToken,"ILLEGAL")}function q(){var a,b;for(b=0===ic;lc>ic;)if(a=gc.charCodeAt(ic),f(a))++ic;else if(g(a))++ic,13===a&&10===gc.charCodeAt(ic)&&++ic,++jc,kc=ic,b=!0;else if(47===a)if(a=gc.charCodeAt(ic+1),47===a)++ic,++ic,o(2),b=!0;else{if(42!==a)break;++ic,++ic,p()}else if(b&&45===a){if(45!==gc.charCodeAt(ic+1)||62!==gc.charCodeAt(ic+2))break;ic+=3,o(3)}else{if(60!==a)break;if("!--"!==gc.slice(ic+1,ic+4))break;++ic,++ic,++ic,++ic,o(4)}}function r(a){var b,c,e,f=0;for(c="u"===a?4:2,b=0;c>b;++b){if(!(lc>ic&&d(gc[ic])))return"";e=gc[ic++],f=16*f+"0123456789abcdef".indexOf(e.toLowerCase())}return String.fromCharCode(f)}function s(){var a,b;for(a=gc.charCodeAt(ic++),b=String.fromCharCode(a),92===a&&(117!==gc.charCodeAt(ic)&&O({},dc.UnexpectedToken,"ILLEGAL"),++ic,a=r("u"),a&&"\\"!==a&&h(a.charCodeAt(0))||O({},dc.UnexpectedToken,"ILLEGAL"),b=a);lc>ic&&(a=gc.charCodeAt(ic),i(a));)++ic,b+=String.fromCharCode(a),92===a&&(b=b.substr(0,b.length-1),117!==gc.charCodeAt(ic)&&O({},dc.UnexpectedToken,"ILLEGAL"),++ic,a=r("u"),a&&"\\"!==a&&i(a.charCodeAt(0))||O({},dc.UnexpectedToken,"ILLEGAL"),b+=a);return b}function t(){var a,b;for(a=ic++;lc>ic;){if(b=gc.charCodeAt(ic),92===b)return ic=a,s();if(!i(b))break;++ic}return gc.slice(a,ic)}function u(){var a,b,c;return a=ic,b=92===gc.charCodeAt(ic)?s():t(),c=1===b.length?$b.Identifier:m(b)?$b.Keyword:"null"===b?$b.NullLiteral:"true"===b||"false"===b?$b.BooleanLiteral:$b.Identifier,{type:c,value:b,lineNumber:jc,lineStart:kc,start:a,end:ic}}function v(){var a,b,c,d,e=ic,f=gc.charCodeAt(ic),g=gc[ic];switch(f){case 46:case 40:case 41:case 59:case 44:case 123:case 125:case 91:case 93:case 58:case 63:case 126:return++ic,pc.tokenize&&(40===f?pc.openParenToken=pc.tokens.length:123===f&&(pc.openCurlyToken=pc.tokens.length)),{type:$b.Punctuator,value:String.fromCharCode(f),lineNumber:jc,lineStart:kc,start:e,end:ic};default:if(a=gc.charCodeAt(ic+1),61===a)switch(f){case 43:case 45:case 47:case 60:case 62:case 94:case 124:case 37:case 38:case 42:return ic+=2,{type:$b.Punctuator,value:String.fromCharCode(f)+String.fromCharCode(a),lineNumber:jc,lineStart:kc,start:e,end:ic};case 33:case 61:return ic+=2,61===gc.charCodeAt(ic)&&++ic,{type:$b.Punctuator,value:gc.slice(e,ic),lineNumber:jc,lineStart:kc,start:e,end:ic}}}return d=gc.substr(ic,4),">>>="===d?(ic+=4,{type:$b.Punctuator,value:d,lineNumber:jc,lineStart:kc,start:e,end:ic}):(c=d.substr(0,3),">>>"===c||"<<="===c||">>="===c?(ic+=3,{type:$b.Punctuator,value:c,lineNumber:jc,lineStart:kc,start:e,end:ic}):(b=c.substr(0,2),g===b[1]&&"+-<>&|".indexOf(g)>=0||"=>"===b?(ic+=2,{type:$b.Punctuator,value:b,lineNumber:jc,lineStart:kc,start:e,end:ic}):"<>=!+-*%&|^/".indexOf(g)>=0?(++ic,{type:$b.Punctuator,value:g,lineNumber:jc,lineStart:kc,start:e,end:ic}):void O({},dc.UnexpectedToken,"ILLEGAL")))}function w(a){for(var b="";lc>ic&&d(gc[ic]);)b+=gc[ic++];return 0===b.length&&O({},dc.UnexpectedToken,"ILLEGAL"),h(gc.charCodeAt(ic))&&O({},dc.UnexpectedToken,"ILLEGAL"),{type:$b.NumericLiteral,value:parseInt("0x"+b,16),lineNumber:jc,lineStart:kc,start:a,end:ic}}function x(a){for(var b="0"+gc[ic++];lc>ic&&e(gc[ic]);)b+=gc[ic++];return(h(gc.charCodeAt(ic))||c(gc.charCodeAt(ic)))&&O({},dc.UnexpectedToken,"ILLEGAL"),{type:$b.NumericLiteral,value:parseInt(b,8),octal:!0,lineNumber:jc,lineStart:kc,start:a,end:ic}}function y(){var a,d,f;if(f=gc[ic],b(c(f.charCodeAt(0))||"."===f,"Numeric literal must start with a decimal digit or a decimal point"),d=ic,a="","."!==f){if(a=gc[ic++],f=gc[ic],"0"===a){if("x"===f||"X"===f)return++ic,w(d);if(e(f))return x(d);f&&c(f.charCodeAt(0))&&O({},dc.UnexpectedToken,"ILLEGAL")}for(;c(gc.charCodeAt(ic));)a+=gc[ic++];f=gc[ic]}if("."===f){for(a+=gc[ic++];c(gc.charCodeAt(ic));)a+=gc[ic++];f=gc[ic]}if("e"===f||"E"===f)if(a+=gc[ic++],f=gc[ic],("+"===f||"-"===f)&&(a+=gc[ic++]),c(gc.charCodeAt(ic)))for(;c(gc.charCodeAt(ic));)a+=gc[ic++];else O({},dc.UnexpectedToken,"ILLEGAL");return h(gc.charCodeAt(ic))&&O({},dc.UnexpectedToken,"ILLEGAL"),{type:$b.NumericLiteral,value:parseFloat(a),lineNumber:jc,lineStart:kc,start:d,end:ic}}function z(){var a,c,d,f,h,i,j,k,l="",m=!1;for(j=jc,k=kc,a=gc[ic],b("'"===a||'"'===a,"String literal must starts with a quote"),c=ic,++ic;lc>ic;){if(d=gc[ic++],d===a){a="";break}if("\\"===d)if(d=gc[ic++],d&&g(d.charCodeAt(0)))++jc,"\r"===d&&"\n"===gc[ic]&&++ic,kc=ic;else switch(d){case"u":case"x":i=ic,h=r(d),h?l+=h:(ic=i,l+=d);break;case"n":l+="\n";break;case"r":l+="\r";break;case"t":l+=" ";break;case"b":l+="\b";break;case"f":l+="\f";break;case"v":l+=" ";break;default:e(d)?(f="01234567".indexOf(d),0!==f&&(m=!0),lc>ic&&e(gc[ic])&&(m=!0,f=8*f+"01234567".indexOf(gc[ic++]),"0123".indexOf(d)>=0&&lc>ic&&e(gc[ic])&&(f=8*f+"01234567".indexOf(gc[ic++]))),l+=String.fromCharCode(f)):l+=d}else{if(g(d.charCodeAt(0)))break;l+=d}}return""!==a&&O({},dc.UnexpectedToken,"ILLEGAL"),{type:$b.StringLiteral,value:l,octal:m,startLineNumber:j,startLineStart:k,lineNumber:jc,lineStart:kc,start:c,end:ic}}function A(a,b){var c;try{c=new RegExp(a,b)}catch(d){O({},dc.InvalidRegExp)}return c}function B(){var a,c,d,e,f;for(a=gc[ic],b("/"===a,"Regular expression literal must start with a slash"),c=gc[ic++],d=!1,e=!1;lc>ic;)if(a=gc[ic++],c+=a,"\\"===a)a=gc[ic++],g(a.charCodeAt(0))&&O({},dc.UnterminatedRegExp),c+=a;else if(g(a.charCodeAt(0)))O({},dc.UnterminatedRegExp);else if(d)"]"===a&&(d=!1);else{if("/"===a){e=!0;break}"["===a&&(d=!0)}return e||O({},dc.UnterminatedRegExp),f=c.substr(1,c.length-2),{value:f,literal:c}}function C(){var a,b,c,d;for(b="",c="";lc>ic&&(a=gc[ic],i(a.charCodeAt(0)));)if(++ic,"\\"===a&&lc>ic)if(a=gc[ic],"u"===a){if(++ic,d=ic,a=r("u"))for(c+=a,b+="\\u";ic>d;++d)b+=gc[d];else ic=d,c+="u",b+="\\u";P({},dc.UnexpectedToken,"ILLEGAL")}else b+="\\",P({},dc.UnexpectedToken,"ILLEGAL");else c+=a,b+=a;return{value:c,literal:b}}function D(){var a,b,c,d;return nc=null,q(),a=ic,b=B(),c=C(),d=A(b.value,c.value),pc.tokenize?{type:$b.RegularExpression,value:d,lineNumber:jc,lineStart:kc,start:a,end:ic}:{literal:b.literal+c.literal,value:d,start:a,end:ic}}function E(){var a,b,c,d;return q(),a=ic,b={start:{line:jc,column:ic-kc}},c=D(),b.end={line:jc,column:ic-kc},pc.tokenize||(pc.tokens.length>0&&(d=pc.tokens[pc.tokens.length-1],d.range[0]===a&&"Punctuator"===d.type&&("/"===d.value||"/="===d.value)&&pc.tokens.pop()),pc.tokens.push({type:"RegularExpression",value:c.literal,range:[a,ic],loc:b})),c}function F(a){return a.type===$b.Identifier||a.type===$b.Keyword||a.type===$b.BooleanLiteral||a.type===$b.NullLiteral}function G(){var a,b;if(a=pc.tokens[pc.tokens.length-1],!a)return E();if("Punctuator"===a.type){if("]"===a.value)return v();if(")"===a.value)return b=pc.tokens[pc.openParenToken-1],!b||"Keyword"!==b.type||"if"!==b.value&&"while"!==b.value&&"for"!==b.value&&"with"!==b.value?v():E();if("}"===a.value){if(pc.tokens[pc.openCurlyToken-3]&&"Keyword"===pc.tokens[pc.openCurlyToken-3].type){if(b=pc.tokens[pc.openCurlyToken-4],!b)return v()}else{if(!pc.tokens[pc.openCurlyToken-4]||"Keyword"!==pc.tokens[pc.openCurlyToken-4].type)return v();if(b=pc.tokens[pc.openCurlyToken-5],!b)return E()}return ac.indexOf(b.value)>=0?v():E()}return E()}return"Keyword"===a.type?E():v()}function H(){var a;return q(),ic>=lc?{type:$b.EOF,lineNumber:jc,lineStart:kc,start:ic,end:ic}:(a=gc.charCodeAt(ic),h(a)?u():40===a||41===a||59===a?v():39===a||34===a?z():46===a?c(gc.charCodeAt(ic+1))?y():v():c(a)?y():pc.tokenize&&47===a?G():v())}function I(){var a,b,c;return q(),a={start:{line:jc,column:ic-kc}},b=H(),a.end={line:jc,column:ic-kc},b.type!==$b.EOF&&(c=gc.slice(b.start,b.end),pc.tokens.push({type:_b[b.type],value:c,range:[b.start,b.end],loc:a})),b}function J(){var a;return a=nc,ic=a.end,jc=a.lineNumber,kc=a.lineStart,nc="undefined"!=typeof pc.tokens?I():H(),ic=a.end,jc=a.lineNumber,kc=a.lineStart,a}function K(){var a,b,c;a=ic,b=jc,c=kc,nc="undefined"!=typeof pc.tokens?I():H(),ic=a,jc=b,kc=c}function L(a,b){this.line=a,this.column=b}function M(a,b,c,d){this.start=new L(a,b),this.end=new L(c,d)}function N(){var a,b,c,d;return a=ic,b=jc,c=kc,q(),d=jc!==b,ic=a,jc=b,kc=c,d}function O(a,c){var d,e=Array.prototype.slice.call(arguments,2),f=c.replace(/%(\d)/g,function(a,c){return b(c>="===a||">>>="===a||"&="===a||"^="===a||"|="===a)}function W(){var a;return 59===gc.charCodeAt(ic)||T(";")?void J():(a=jc,q(),void(jc===a&&(nc.type===$b.EOF||T("}")||Q(nc))))}function X(a){return a.type===bc.Identifier||a.type===bc.MemberExpression}function Y(){var a,b=[];for(a=nc,R("[");!T("]");)T(",")?(J(),b.push(null)):(b.push(pb()),T("]")||R(","));return J(),mc.markEnd(mc.createArrayExpression(b),a)}function Z(a,b){var c,d,e;return c=hc,e=nc,d=Qb(),b&&hc&&l(a[0].name)&&P(b,dc.StrictParamName),hc=c,mc.markEnd(mc.createFunctionExpression(null,a,[],d),e)}function $(){var a,b;return b=nc,a=J(),a.type===$b.StringLiteral||a.type===$b.NumericLiteral?(hc&&a.octal&&P(a,dc.StrictOctalLiteral),mc.markEnd(mc.createLiteral(a),b)):mc.markEnd(mc.createIdentifier(a.value),b)}function _(){var a,b,c,d,e,f;return a=nc,f=nc,a.type===$b.Identifier?(c=$(),"get"!==a.value||T(":")?"set"!==a.value||T(":")?(R(":"),d=pb(),mc.markEnd(mc.createProperty("init",c,d),f)):(b=$(),R("("),a=nc,a.type!==$b.Identifier?(R(")"),P(a,dc.UnexpectedToken,a.value),d=Z([])):(e=[tb()],R(")"),d=Z(e,a)),mc.markEnd(mc.createProperty("set",b,d),f)):(b=$(),R("("),R(")"),d=Z([]),mc.markEnd(mc.createProperty("get",b,d),f))):a.type!==$b.EOF&&a.type!==$b.Punctuator?(b=$(),R(":"),d=pb(),mc.markEnd(mc.createProperty("init",b,d),f)):void Q(a)}function ab(){var a,b,c,d,e,f=[],g={},h=String;for(e=nc,R("{");!T("}");)a=_(),b=a.key.type===bc.Identifier?a.key.name:h(a.key.value),d="init"===a.kind?cc.Data:"get"===a.kind?cc.Get:cc.Set,c="$"+b,Object.prototype.hasOwnProperty.call(g,c)?(g[c]===cc.Data?hc&&d===cc.Data?P({},dc.StrictDuplicateProperty):d!==cc.Data&&P({},dc.AccessorDataProperty):d===cc.Data?P({},dc.AccessorDataProperty):g[c]&d&&P({},dc.AccessorGetSet),g[c]|=d):g[c]=d,f.push(a),T("}")||R(",");return R("}"),mc.markEnd(mc.createObjectExpression(f),e)}function bb(){var a;return R("("),a=qb(),R(")"),a}function cb(){var a,b,c,d;if(T("("))return bb();if(T("["))return Y();if(T("{"))return ab();if(a=nc.type,d=nc,a===$b.Identifier)c=mc.createIdentifier(J().value);else if(a===$b.StringLiteral||a===$b.NumericLiteral)hc&&nc.octal&&P(nc,dc.StrictOctalLiteral),c=mc.createLiteral(J());else if(a===$b.Keyword){if(U("function"))return Tb();U("this")?(J(),c=mc.createThisExpression()):Q(J())}else a===$b.BooleanLiteral?(b=J(),b.value="true"===b.value,c=mc.createLiteral(b)):a===$b.NullLiteral?(b=J(),b.value=null,c=mc.createLiteral(b)):T("/")||T("/=")?(c=mc.createLiteral("undefined"!=typeof pc.tokens?E():D()),K()):Q(J());return mc.markEnd(c,d)}function db(){var a=[];if(R("("),!T(")"))for(;lc>ic&&(a.push(pb()),!T(")"));)R(",");return R(")"),a}function eb(){var a,b;return b=nc,a=J(),F(a)||Q(a),mc.markEnd(mc.createIdentifier(a.value),b)}function fb(){return R("."),eb()}function gb(){var a;return R("["),a=qb(),R("]"),a}function hb(){var a,b,c;return c=nc,S("new"),a=jb(),b=T("(")?db():[],mc.markEnd(mc.createNewExpression(a,b),c)}function ib(){var a,b,c,d,e;for(e=nc,a=oc.allowIn,oc.allowIn=!0,b=U("new")?hb():cb(),oc.allowIn=a;;){if(T("."))d=fb(),b=mc.createMemberExpression(".",b,d);else if(T("("))c=db(),b=mc.createCallExpression(b,c);else{if(!T("["))break;d=gb(),b=mc.createMemberExpression("[",b,d)}mc.markEnd(b,e)}return b}function jb(){var a,b,c,d;for(d=nc,a=oc.allowIn,b=U("new")?hb():cb(),oc.allowIn=a;T(".")||T("[");)T("[")?(c=gb(),b=mc.createMemberExpression("[",b,c)):(c=fb(),b=mc.createMemberExpression(".",b,c)),mc.markEnd(b,d);return b}function kb(){var a,b,c=nc;return a=ib(),nc.type===$b.Punctuator&&(!T("++")&&!T("--")||N()||(hc&&a.type===bc.Identifier&&l(a.name)&&P({},dc.StrictLHSPostfix),X(a)||P({},dc.InvalidLHSInAssignment),b=J(),a=mc.markEnd(mc.createPostfixExpression(b.value,a),c))),a}function lb(){var a,b,c;return nc.type!==$b.Punctuator&&nc.type!==$b.Keyword?b=kb():T("++")||T("--")?(c=nc,a=J(),b=lb(),hc&&b.type===bc.Identifier&&l(b.name)&&P({},dc.StrictLHSPrefix),X(b)||P({},dc.InvalidLHSInAssignment),b=mc.createUnaryExpression(a.value,b),b=mc.markEnd(b,c)):T("+")||T("-")||T("~")||T("!")?(c=nc,a=J(),b=lb(),b=mc.createUnaryExpression(a.value,b),b=mc.markEnd(b,c)):U("delete")||U("void")||U("typeof")?(c=nc,a=J(),b=lb(),b=mc.createUnaryExpression(a.value,b),b=mc.markEnd(b,c),hc&&"delete"===b.operator&&b.argument.type===bc.Identifier&&P({},dc.StrictDelete)):b=kb(),b}function mb(a,b){var c=0;if(a.type!==$b.Punctuator&&a.type!==$b.Keyword)return 0;switch(a.value){case"||":c=1;break;case"&&":c=2;break;case"|":c=3;break;case"^":c=4;break;case"&":c=5;break;case"==":case"!=":case"===":case"!==":c=6;break;case"<":case">":case"<=":case">=":case"instanceof":c=7;break;case"in":c=b?7:0;break;case"<<":case">>":case">>>":c=8;break;case"+":case"-":c=9;break;case"*":case"/":case"%":c=11}return c}function nb(){var a,b,c,d,e,f,g,h,i,j;if(a=nc,i=lb(),d=nc,e=mb(d,oc.allowIn),0===e)return i;for(d.prec=e,J(),b=[a,nc],g=lb(),f=[i,d,g];(e=mb(nc,oc.allowIn))>0;){for(;f.length>2&&e<=f[f.length-2].prec;)g=f.pop(),h=f.pop().value,i=f.pop(),c=mc.createBinaryExpression(h,i,g),b.pop(),a=b[b.length-1],mc.markEnd(c,a),f.push(c);d=J(),d.prec=e,f.push(d),b.push(nc),c=lb(),f.push(c)}for(j=f.length-1,c=f[j],b.pop();j>1;)c=mc.createBinaryExpression(f[j-1].value,f[j-2],c),j-=2,a=b.pop(),mc.markEnd(c,a);return c}function ob(){var a,b,c,d,e;return e=nc,a=nb(),T("?")&&(J(),b=oc.allowIn,oc.allowIn=!0,c=pb(),oc.allowIn=b,R(":"),d=pb(),a=mc.createConditionalExpression(a,c,d),mc.markEnd(a,e)),a}function pb(){var a,b,c,d,e;return a=nc,e=nc,d=b=ob(),V()&&(X(b)||P({},dc.InvalidLHSInAssignment),hc&&b.type===bc.Identifier&&l(b.name)&&P(a,dc.StrictLHSAssignment),a=J(),c=pb(),d=mc.markEnd(mc.createAssignmentExpression(a.value,b,c),e)),d}function qb(){var a,b=nc;if(a=pb(),T(",")){for(a=mc.createSequenceExpression([a]);lc>ic&&T(",");)J(),a.expressions.push(pb());mc.markEnd(a,b)}return a}function rb(){for(var a,b=[];lc>ic&&!T("}")&&(a=Ub(),"undefined"!=typeof a);)b.push(a);return b}function sb(){var a,b;return b=nc,R("{"),a=rb(),R("}"),mc.markEnd(mc.createBlockStatement(a),b)}function tb(){var a,b;return b=nc,a=J(),a.type!==$b.Identifier&&Q(a),mc.markEnd(mc.createIdentifier(a.value),b)}function ub(a){var b,c,d=null;return c=nc,b=tb(),hc&&l(b.name)&&P({},dc.StrictVarName),"const"===a?(R("="),d=pb()):T("=")&&(J(),d=pb()),mc.markEnd(mc.createVariableDeclarator(b,d),c)}function vb(a){var b=[];do{if(b.push(ub(a)),!T(","))break;J()}while(lc>ic);return b}function wb(){var a;return S("var"),a=vb(),W(),mc.createVariableDeclaration(a,"var")}function xb(a){var b,c;return c=nc,S(a),b=vb(a),W(),mc.markEnd(mc.createVariableDeclaration(b,a),c)}function yb(){return R(";"),mc.createEmptyStatement()}function zb(){var a=qb();return W(),mc.createExpressionStatement(a)}function Ab(){var a,b,c;return S("if"),R("("),a=qb(),R(")"),b=Pb(),U("else")?(J(),c=Pb()):c=null,mc.createIfStatement(a,b,c)}function Bb(){var a,b,c;return S("do"),c=oc.inIteration,oc.inIteration=!0,a=Pb(),oc.inIteration=c,S("while"),R("("),b=qb(),R(")"),T(";")&&J(),mc.createDoWhileStatement(a,b)}function Cb(){var a,b,c;return S("while"),R("("),a=qb(),R(")"),c=oc.inIteration,oc.inIteration=!0,b=Pb(),oc.inIteration=c,mc.createWhileStatement(a,b)}function Db(){var a,b,c;return c=nc,a=J(),b=vb(),mc.markEnd(mc.createVariableDeclaration(b,a.value),c)}function Eb(){var a,b,c,d,e,f,g;return a=b=c=null,S("for"),R("("),T(";")?J():(U("var")||U("let")?(oc.allowIn=!1,a=Db(),oc.allowIn=!0,1===a.declarations.length&&U("in")&&(J(),d=a,e=qb(),a=null)):(oc.allowIn=!1,a=qb(),oc.allowIn=!0,U("in")&&(X(a)||P({},dc.InvalidLHSInForIn),J(),d=a,e=qb(),a=null)),"undefined"==typeof d&&R(";")),"undefined"==typeof d&&(T(";")||(b=qb()),R(";"),T(")")||(c=qb())),R(")"),g=oc.inIteration,oc.inIteration=!0,f=Pb(),oc.inIteration=g,"undefined"==typeof d?mc.createForStatement(a,b,c,f):mc.createForInStatement(d,e,f)}function Fb(){var a,b=null;return S("continue"),59===gc.charCodeAt(ic)?(J(),oc.inIteration||O({},dc.IllegalContinue),mc.createContinueStatement(null)):N()?(oc.inIteration||O({},dc.IllegalContinue),mc.createContinueStatement(null)):(nc.type===$b.Identifier&&(b=tb(),a="$"+b.name,Object.prototype.hasOwnProperty.call(oc.labelSet,a)||O({},dc.UnknownLabel,b.name)),W(),null!==b||oc.inIteration||O({},dc.IllegalContinue),mc.createContinueStatement(b))}function Gb(){var a,b=null;return S("break"),59===gc.charCodeAt(ic)?(J(),oc.inIteration||oc.inSwitch||O({},dc.IllegalBreak),mc.createBreakStatement(null)):N()?(oc.inIteration||oc.inSwitch||O({},dc.IllegalBreak),mc.createBreakStatement(null)):(nc.type===$b.Identifier&&(b=tb(),a="$"+b.name,Object.prototype.hasOwnProperty.call(oc.labelSet,a)||O({},dc.UnknownLabel,b.name)),W(),null!==b||oc.inIteration||oc.inSwitch||O({},dc.IllegalBreak),mc.createBreakStatement(b))}function Hb(){var a=null;return S("return"),oc.inFunctionBody||P({},dc.IllegalReturn),32===gc.charCodeAt(ic)&&h(gc.charCodeAt(ic+1))?(a=qb(),W(),mc.createReturnStatement(a)):N()?mc.createReturnStatement(null):(T(";")||T("}")||nc.type===$b.EOF||(a=qb()),W(),mc.createReturnStatement(a))}function Ib(){var a,b;return hc&&(q(),P({},dc.StrictModeWith)),S("with"),R("("),a=qb(),R(")"),b=Pb(),mc.createWithStatement(a,b)}function Jb(){var a,b,c,d=[];for(c=nc,U("default")?(J(),a=null):(S("case"),a=qb()),R(":");lc>ic&&!(T("}")||U("default")||U("case"));)b=Pb(),d.push(b);return mc.markEnd(mc.createSwitchCase(a,d),c)}function Kb(){var a,b,c,d,e;if(S("switch"),R("("),a=qb(),R(")"),R("{"),b=[],T("}"))return J(),mc.createSwitchStatement(a,b);for(d=oc.inSwitch,oc.inSwitch=!0,e=!1;lc>ic&&!T("}");)c=Jb(),null===c.test&&(e&&O({},dc.MultipleDefaultsInSwitch),e=!0),b.push(c);return oc.inSwitch=d,R("}"),mc.createSwitchStatement(a,b)}function Lb(){var a;return S("throw"),N()&&O({},dc.NewlineAfterThrow),a=qb(),W(),mc.createThrowStatement(a)}function Mb(){var a,b,c;return c=nc,S("catch"),R("("),T(")")&&Q(nc),a=tb(),hc&&l(a.name)&&P({},dc.StrictCatchVariable),R(")"),b=sb(),mc.markEnd(mc.createCatchClause(a,b),c)}function Nb(){var a,b=[],c=null;return S("try"),a=sb(),U("catch")&&b.push(Mb()),U("finally")&&(J(),c=sb()),0!==b.length||c||O({},dc.NoCatchOrFinally),mc.createTryStatement(a,[],b,c)}function Ob(){return S("debugger"),W(),mc.createDebuggerStatement()}function Pb(){var a,b,c,d,e=nc.type;if(e===$b.EOF&&Q(nc),e===$b.Punctuator&&"{"===nc.value)return sb();if(d=nc,e===$b.Punctuator)switch(nc.value){case";":return mc.markEnd(yb(),d);case"(":return mc.markEnd(zb(),d)}if(e===$b.Keyword)switch(nc.value){case"break":return mc.markEnd(Gb(),d);case"continue":return mc.markEnd(Fb(),d);case"debugger":return mc.markEnd(Ob(),d);case"do":return mc.markEnd(Bb(),d);case"for":return mc.markEnd(Eb(),d);case"function":return mc.markEnd(Sb(),d);case"if":return mc.markEnd(Ab(),d);case"return":return mc.markEnd(Hb(),d);case"switch":return mc.markEnd(Kb(),d);case"throw":return mc.markEnd(Lb(),d);case"try":return mc.markEnd(Nb(),d);case"var":return mc.markEnd(wb(),d);case"while":return mc.markEnd(Cb(),d);case"with":return mc.markEnd(Ib(),d)}return a=qb(),a.type===bc.Identifier&&T(":")?(J(),c="$"+a.name,Object.prototype.hasOwnProperty.call(oc.labelSet,c)&&O({},dc.Redeclaration,"Label",a.name),oc.labelSet[c]=!0,b=Pb(),delete oc.labelSet[c],mc.markEnd(mc.createLabeledStatement(a,b),d)):(W(),mc.markEnd(mc.createExpressionStatement(a),d))}function Qb(){var a,b,c,d,e,f,g,h,i,j=[];for(i=nc,R("{");lc>ic&&nc.type===$b.StringLiteral&&(b=nc,a=Ub(),j.push(a),a.expression.type===bc.Literal);)c=gc.slice(b.start+1,b.end-1),"use strict"===c?(hc=!0,d&&P(d,dc.StrictOctalLiteral)):!d&&b.octal&&(d=b);for(e=oc.labelSet,f=oc.inIteration,g=oc.inSwitch,h=oc.inFunctionBody,oc.labelSet={},oc.inIteration=!1,oc.inSwitch=!1,oc.inFunctionBody=!0;lc>ic&&!T("}")&&(a=Ub(),"undefined"!=typeof a);)j.push(a);return R("}"),oc.labelSet=e,oc.inIteration=f,oc.inSwitch=g,oc.inFunctionBody=h,mc.markEnd(mc.createBlockStatement(j),i)}function Rb(a){var b,c,d,e,f,g,h=[];if(R("("),!T(")"))for(e={};lc>ic&&(c=nc,b=tb(),f="$"+c.value,hc?(l(c.value)&&(d=c,g=dc.StrictParamName),Object.prototype.hasOwnProperty.call(e,f)&&(d=c,g=dc.StrictParamDupe)):a||(l(c.value)?(a=c,g=dc.StrictParamName):k(c.value)?(a=c,g=dc.StrictReservedWord):Object.prototype.hasOwnProperty.call(e,f)&&(a=c,g=dc.StrictParamDupe)),h.push(b),e[f]=!0,!T(")"));)R(",");return R(")"),{params:h,stricted:d,firstRestricted:a,message:g}}function Sb(){var a,b,c,d,e,f,g,h,i,j=[];return i=nc,S("function"),c=nc,a=tb(),hc?l(c.value)&&P(c,dc.StrictFunctionName):l(c.value)?(f=c,g=dc.StrictFunctionName):k(c.value)&&(f=c,g=dc.StrictReservedWord),e=Rb(f),j=e.params,d=e.stricted,f=e.firstRestricted,e.message&&(g=e.message),h=hc,b=Qb(),hc&&f&&O(f,g),hc&&d&&P(d,g),hc=h,mc.markEnd(mc.createFunctionDeclaration(a,j,[],b),i)}function Tb(){var a,b,c,d,e,f,g,h,i=null,j=[];return h=nc,S("function"),T("(")||(a=nc,i=tb(),hc?l(a.value)&&P(a,dc.StrictFunctionName):l(a.value)?(c=a,d=dc.StrictFunctionName):k(a.value)&&(c=a,d=dc.StrictReservedWord)),e=Rb(c),j=e.params,b=e.stricted,c=e.firstRestricted,e.message&&(d=e.message),g=hc,f=Qb(),hc&&c&&O(c,d),hc&&b&&P(b,d),hc=g,mc.markEnd(mc.createFunctionExpression(i,j,[],f),h)}function Ub(){if(nc.type===$b.Keyword)switch(nc.value){case"const":case"let":return xb(nc.value);case"function":return Sb();default:return Pb()}return nc.type!==$b.EOF?Pb():void 0}function Vb(){for(var a,b,c,d,e=[];lc>ic&&(b=nc,b.type===$b.StringLiteral)&&(a=Ub(),e.push(a),a.expression.type===bc.Literal);)c=gc.slice(b.start+1,b.end-1),"use strict"===c?(hc=!0,d&&P(d,dc.StrictOctalLiteral)):!d&&b.octal&&(d=b);for(;lc>ic&&(a=Ub(),"undefined"!=typeof a);)e.push(a);return e}function Wb(){var a,b;return q(),K(),b=nc,hc=!1,a=Vb(),mc.markEnd(mc.createProgram(a),b)}function Xb(){var a,b,c,d=[];for(a=0;a0?1:0,kc=0,lc=gc.length,nc=null,oc={allowIn:!0,labelSet:{},inFunctionBody:!1,inIteration:!1,inSwitch:!1,lastCommentStart:-1},pc={},b=b||{},b.tokens=!0,pc.tokens=[],pc.tokenize=!0,pc.openParenToken=-1,pc.openCurlyToken=-1,pc.range="boolean"==typeof b.range&&b.range,pc.loc="boolean"==typeof b.loc&&b.loc,"boolean"==typeof b.comment&&b.comment&&(pc.comments=[]),"boolean"==typeof b.tolerant&&b.tolerant&&(pc.errors=[]);try{if(K(),nc.type===$b.EOF)return pc.tokens;for(d=J();nc.type!==$b.EOF;)try{d=J()}catch(f){if(d=nc,pc.errors){pc.errors.push(f);break}throw f}Xb(),e=pc.tokens,"undefined"!=typeof pc.comments&&(e.comments=pc.comments),"undefined"!=typeof pc.errors&&(e.errors=pc.errors)}catch(g){throw g}finally{pc={}}return e}function Zb(a,b){var c,d;d=String,"string"==typeof a||a instanceof String||(a=d(a)),mc=fc,gc=a,ic=0,jc=gc.length>0?1:0,kc=0,lc=gc.length,nc=null,oc={allowIn:!0,labelSet:{},inFunctionBody:!1,inIteration:!1,inSwitch:!1,lastCommentStart:-1},pc={},"undefined"!=typeof b&&(pc.range="boolean"==typeof b.range&&b.range,pc.loc="boolean"==typeof b.loc&&b.loc,pc.attachComment="boolean"==typeof b.attachComment&&b.attachComment,pc.loc&&null!==b.source&&void 0!==b.source&&(pc.source=d(b.source)),"boolean"==typeof b.tokens&&b.tokens&&(pc.tokens=[]),"boolean"==typeof b.comment&&b.comment&&(pc.comments=[]),"boolean"==typeof b.tolerant&&b.tolerant&&(pc.errors=[]),pc.attachComment&&(pc.range=!0,pc.comments=[],pc.bottomRightStack=[],pc.trailingComments=[],pc.leadingComments=[]));try{c=Wb(),"undefined"!=typeof pc.comments&&(c.comments=pc.comments),"undefined"!=typeof pc.tokens&&(Xb(),c.tokens=pc.tokens),"undefined"!=typeof pc.errors&&(c.errors=pc.errors)}catch(e){throw e}finally{pc={}}return c}var $b,_b,ac,bc,cc,dc,ec,fc,gc,hc,ic,jc,kc,lc,mc,nc,oc,pc;$b={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8,RegularExpression:9},_b={},_b[$b.BooleanLiteral]="Boolean",_b[$b.EOF]="",_b[$b.Identifier]="Identifier",_b[$b.Keyword]="Keyword",_b[$b.NullLiteral]="Null",_b[$b.NumericLiteral]="Numeric",_b[$b.Punctuator]="Punctuator",_b[$b.StringLiteral]="String",_b[$b.RegularExpression]="RegularExpression",ac=["(","{","[","in","typeof","instanceof","new","return","case","delete","throw","void","=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","&=","|=","^=",",","+","-","*","/","%","++","--","<<",">>",">>>","&","|","^","!","~","&&","||","?",":","===","==",">=","<=","<",">","!=","!=="],bc={AssignmentExpression:"AssignmentExpression",ArrayExpression:"ArrayExpression",BlockStatement:"BlockStatement",BinaryExpression:"BinaryExpression",BreakStatement:"BreakStatement",CallExpression:"CallExpression",CatchClause:"CatchClause",ConditionalExpression:"ConditionalExpression",ContinueStatement:"ContinueStatement",DoWhileStatement:"DoWhileStatement",DebuggerStatement:"DebuggerStatement",EmptyStatement:"EmptyStatement",ExpressionStatement:"ExpressionStatement",ForStatement:"ForStatement",ForInStatement:"ForInStatement",FunctionDeclaration:"FunctionDeclaration",FunctionExpression:"FunctionExpression",Identifier:"Identifier",IfStatement:"IfStatement",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",NewExpression:"NewExpression",ObjectExpression:"ObjectExpression",Program:"Program",Property:"Property",ReturnStatement:"ReturnStatement",SequenceExpression:"SequenceExpression",SwitchStatement:"SwitchStatement",SwitchCase:"SwitchCase",ThisExpression:"ThisExpression",ThrowStatement:"ThrowStatement",TryStatement:"TryStatement",UnaryExpression:"UnaryExpression",UpdateExpression:"UpdateExpression",VariableDeclaration:"VariableDeclaration",VariableDeclarator:"VariableDeclarator",WhileStatement:"WhileStatement",WithStatement:"WithStatement"},cc={Data:1,Get:2,Set:4},dc={UnexpectedToken:"Unexpected token %0",UnexpectedNumber:"Unexpected number",UnexpectedString:"Unexpected string",UnexpectedIdentifier:"Unexpected identifier",UnexpectedReserved:"Unexpected reserved word",UnexpectedEOS:"Unexpected end of input",NewlineAfterThrow:"Illegal newline after throw",InvalidRegExp:"Invalid regular expression",UnterminatedRegExp:"Invalid regular expression: missing /",InvalidLHSInAssignment:"Invalid left-hand side in assignment",InvalidLHSInForIn:"Invalid left-hand side in for-in",MultipleDefaultsInSwitch:"More than one default clause in switch statement",NoCatchOrFinally:"Missing catch or finally after try",UnknownLabel:"Undefined label '%0'",Redeclaration:"%0 '%1' has already been declared",IllegalContinue:"Illegal continue statement",IllegalBreak:"Illegal break statement",IllegalReturn:"Illegal return statement",StrictModeWith:"Strict mode code may not include a with statement",StrictCatchVariable:"Catch variable may not be eval or arguments in strict mode",StrictVarName:"Variable name may not be eval or arguments in strict mode",StrictParamName:"Parameter name eval or arguments is not allowed in strict mode",StrictParamDupe:"Strict mode function may not have duplicate parameter names",StrictFunctionName:"Function name may not be eval or arguments in strict mode",StrictOctalLiteral:"Octal literals are not allowed in strict mode.",StrictDelete:"Delete of an unqualified identifier in strict mode.",StrictDuplicateProperty:"Duplicate data property in object literal not allowed in strict mode",AccessorDataProperty:"Object literal may not have data and accessor property with the same name",AccessorGetSet:"Object literal may not have multiple get/set accessors with the same name",StrictLHSAssignment:"Assignment to eval or arguments is not allowed in strict mode",StrictLHSPostfix:"Postfix increment/decrement may not have eval or arguments operand in strict mode",StrictLHSPrefix:"Prefix increment/decrement may not have eval or arguments operand in strict mode",StrictReservedWord:"Use of future reserved word in strict mode"},ec={NonAsciiIdentifierStart:new RegExp("[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]"),NonAsciiIdentifierPart:new RegExp("[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]")},fc={name:"SyntaxTree",processComment:function(a){var b,c; +if(!(a.type===bc.Program&&a.body.length>0)){for(pc.trailingComments.length>0?pc.trailingComments[0].range[0]>=a.range[1]?(c=pc.trailingComments,pc.trailingComments=[]):pc.trailingComments.length=0:pc.bottomRightStack.length>0&&pc.bottomRightStack[pc.bottomRightStack.length-1].trailingComments&&pc.bottomRightStack[pc.bottomRightStack.length-1].trailingComments[0].range[0]>=a.range[1]&&(c=pc.bottomRightStack[pc.bottomRightStack.length-1].trailingComments,delete pc.bottomRightStack[pc.bottomRightStack.length-1].trailingComments);pc.bottomRightStack.length>0&&pc.bottomRightStack[pc.bottomRightStack.length-1].range[0]>=a.range[0];)b=pc.bottomRightStack.pop();b?b.leadingComments&&b.leadingComments[b.leadingComments.length-1].range[1]<=a.range[0]&&(a.leadingComments=b.leadingComments,delete b.leadingComments):pc.leadingComments.length>0&&pc.leadingComments[pc.leadingComments.length-1].range[1]<=a.range[0]&&(a.leadingComments=pc.leadingComments,pc.leadingComments=[]),c&&(a.trailingComments=c),pc.bottomRightStack.push(a)}},markEnd:function(a,b){return pc.range&&(a.range=[b.start,ic]),pc.loc&&(a.loc=new M(void 0===b.startLineNumber?b.lineNumber:b.startLineNumber,b.start-(void 0===b.startLineStart?b.lineStart:b.startLineStart),jc,ic-kc),this.postProcess(a)),pc.attachComment&&this.processComment(a),a},postProcess:function(a){return pc.source&&(a.loc.source=pc.source),a},createArrayExpression:function(a){return{type:bc.ArrayExpression,elements:a}},createAssignmentExpression:function(a,b,c){return{type:bc.AssignmentExpression,operator:a,left:b,right:c}},createBinaryExpression:function(a,b,c){var d="||"===a||"&&"===a?bc.LogicalExpression:bc.BinaryExpression;return{type:d,operator:a,left:b,right:c}},createBlockStatement:function(a){return{type:bc.BlockStatement,body:a}},createBreakStatement:function(a){return{type:bc.BreakStatement,label:a}},createCallExpression:function(a,b){return{type:bc.CallExpression,callee:a,arguments:b}},createCatchClause:function(a,b){return{type:bc.CatchClause,param:a,body:b}},createConditionalExpression:function(a,b,c){return{type:bc.ConditionalExpression,test:a,consequent:b,alternate:c}},createContinueStatement:function(a){return{type:bc.ContinueStatement,label:a}},createDebuggerStatement:function(){return{type:bc.DebuggerStatement}},createDoWhileStatement:function(a,b){return{type:bc.DoWhileStatement,body:a,test:b}},createEmptyStatement:function(){return{type:bc.EmptyStatement}},createExpressionStatement:function(a){return{type:bc.ExpressionStatement,expression:a}},createForStatement:function(a,b,c,d){return{type:bc.ForStatement,init:a,test:b,update:c,body:d}},createForInStatement:function(a,b,c){return{type:bc.ForInStatement,left:a,right:b,body:c,each:!1}},createFunctionDeclaration:function(a,b,c,d){return{type:bc.FunctionDeclaration,id:a,params:b,defaults:c,body:d,rest:null,generator:!1,expression:!1}},createFunctionExpression:function(a,b,c,d){return{type:bc.FunctionExpression,id:a,params:b,defaults:c,body:d,rest:null,generator:!1,expression:!1}},createIdentifier:function(a){return{type:bc.Identifier,name:a}},createIfStatement:function(a,b,c){return{type:bc.IfStatement,test:a,consequent:b,alternate:c}},createLabeledStatement:function(a,b){return{type:bc.LabeledStatement,label:a,body:b}},createLiteral:function(a){return{type:bc.Literal,value:a.value,raw:gc.slice(a.start,a.end)}},createMemberExpression:function(a,b,c){return{type:bc.MemberExpression,computed:"["===a,object:b,property:c}},createNewExpression:function(a,b){return{type:bc.NewExpression,callee:a,arguments:b}},createObjectExpression:function(a){return{type:bc.ObjectExpression,properties:a}},createPostfixExpression:function(a,b){return{type:bc.UpdateExpression,operator:a,argument:b,prefix:!1}},createProgram:function(a){return{type:bc.Program,body:a}},createProperty:function(a,b,c){return{type:bc.Property,key:b,value:c,kind:a}},createReturnStatement:function(a){return{type:bc.ReturnStatement,argument:a}},createSequenceExpression:function(a){return{type:bc.SequenceExpression,expressions:a}},createSwitchCase:function(a,b){return{type:bc.SwitchCase,test:a,consequent:b}},createSwitchStatement:function(a,b){return{type:bc.SwitchStatement,discriminant:a,cases:b}},createThisExpression:function(){return{type:bc.ThisExpression}},createThrowStatement:function(a){return{type:bc.ThrowStatement,argument:a}},createTryStatement:function(a,b,c,d){return{type:bc.TryStatement,block:a,guardedHandlers:b,handlers:c,finalizer:d}},createUnaryExpression:function(a,b){return"++"===a||"--"===a?{type:bc.UpdateExpression,operator:a,argument:b,prefix:!0}:{type:bc.UnaryExpression,operator:a,argument:b,prefix:!0}},createVariableDeclaration:function(a,b){return{type:bc.VariableDeclaration,declarations:a,kind:b}},createVariableDeclarator:function(a,b){return{type:bc.VariableDeclarator,id:a,init:b}},createWhileStatement:function(a,b){return{type:bc.WhileStatement,test:a,body:b}},createWithStatement:function(a,b){return{type:bc.WithStatement,object:a,body:b}}},a.version="1.2.2",a.tokenize=Yb,a.parse=Zb,a.Syntax=function(){var a,b={};"function"==typeof Object.create&&(b=Object.create(null));for(a in bc)bc.hasOwnProperty(a)&&(b[a]=bc[a]);return"function"==typeof Object.freeze&&Object.freeze(b),b}()})}(null),/*! + * falafel (c) James Halliday / MIT License + * https://github.com/substack/node-falafel + */ +function(a,b){function c(a,b,c){function d(b){c[a.range[0]]=b;for(var d=a.range[0]+1;dparseInt(b,10)}).forEach(function(b){e+=f+"['"+a+"']["+b+"]=0;\n"}),c&&_blanket._branchingArraySetup.sort(function(a,b){return a.line>b.line}).sort(function(a,b){return a.column>b.column}).forEach(function(b){b.file===a&&(e+="if (typeof "+f+"['"+a+"'].branchData["+b.line+"] === 'undefined'){\n",e+=f+"['"+a+"'].branchData["+b.line+"]=[];\n",e+="}",e+=f+"['"+a+"'].branchData["+b.line+"]["+b.column+"] = [];\n",e+=f+"['"+a+"'].branchData["+b.line+"]["+b.column+"].consequent = "+JSON.stringify(b.consequent)+";\n",e+=f+"['"+a+"'].branchData["+b.line+"]["+b.column+"].alternate = "+JSON.stringify(b.alternate)+";\n")}),e+="}"},_blockifyIf:function(a){if(c.indexOf(a.type)>-1){var b=a.consequent||a.body,d=a.alternate;d&&"BlockStatement"!==d.type&&d.update("{\n"+d.source()+"}\n"),b&&"BlockStatement"!==b.type&&b.update("{\n"+b.source()+"}\n")}},_trackBranch:function(a,b){var c=a.loc.start.line,d=a.loc.start.column;_blanket._branchingArraySetup.push({line:c,column:d,file:b,consequent:a.consequent.loc,alternate:a.alternate.loc});var e="_$branchFcn('"+b+"',"+c+","+d+","+a.test.source()+")?"+a.consequent.source()+":"+a.alternate.source();a.update(e)},_addTracking:function(a){var c=_blanket.getCovVar();return function(d){if(_blanket._blockifyIf(d),b.indexOf(d.type)>-1&&"LabeledStatement"!==d.parent.type){if(_blanket._checkDefs(d,a),"VariableDeclaration"===d.type&&("ForStatement"===d.parent.type||"ForInStatement"===d.parent.type))return;if(!d.loc||!d.loc.start)throw new Error("The instrumenter encountered a node with no location: "+Object.keys(d));d.update(c+"['"+a+"']["+d.loc.start.line+"]++;\n"+d.source()),_blanket._trackingArraySetup.push(d.loc.start.line)}else _blanket.options("branchTracking")&&"ConditionalExpression"===d.type&&_blanket._trackBranch(d,a)}},_checkDefs:function(a,b){if(inBrowser){if("VariableDeclaration"===a.type&&a.declarations&&a.declarations.forEach(function(c){if("window"===c.id.name)throw new Error("Instrumentation error, you cannot redefine the 'window' variable in "+b+":"+a.loc.start.line)}),"FunctionDeclaration"===a.type&&a.params&&a.params.forEach(function(c){if("window"===c.name)throw new Error("Instrumentation error, you cannot redefine the 'window' variable in "+b+":"+a.loc.start.line)}),"ExpressionStatement"===a.type&&a.expression&&a.expression.left&&a.expression.left.object&&a.expression.left.property&&a.expression.left.object.name+"."+a.expression.left.property.name===_blanket.getCovVar())throw new Error("Instrumentation error, you cannot redefine the coverage variable in "+b+":"+a.loc.start.line)}else if("ExpressionStatement"===a.type&&a.expression&&a.expression.left&&!a.expression.left.object&&!a.expression.left.property&&a.expression.left.name===_blanket.getCovVar())throw new Error("Instrumentation error, you cannot redefine the coverage variable in "+b+":"+a.loc.start.line)},setupCoverage:function(){e.instrumentation="blanket",e.stats={suites:0,tests:0,passes:0,pending:0,failures:0,start:new Date}},_checkIfSetup:function(){if(!e.stats)throw new Error("You must call blanket.setupCoverage() first.")},onTestStart:function(){_blanket.options("debug")&&console.log("BLANKET-Test event started"),this._checkIfSetup(),e.stats.tests++,e.stats.pending++},onTestDone:function(a,b){this._checkIfSetup(),b===a?e.stats.passes++:e.stats.failures++,e.stats.pending--},onModuleStart:function(){this._checkIfSetup(),e.stats.suites++},onTestsDone:function(){_blanket.options("debug")&&console.log("BLANKET-Test event done"),this._checkIfSetup(),e.stats.end=new Date,inBrowser?this.report(e):(_blanket.options("branchTracking")||delete(inBrowser?window:global)[_blanket.getCovVar()].branchFcn,this.options("reporter").call(this,e))}}}(),function(a){var b=a.options;a.extend({outstandingRequireFiles:[],options:function(c,d){var e={};if("string"!=typeof c)b(c),e=c;else{if("undefined"==typeof d)return b(c);b(c,d),e[c]=d}e.adapter&&a._loadFile(e.adapter),e.loader&&a._loadFile(e.loader)},requiringFile:function(b,c){"undefined"==typeof b?a.outstandingRequireFiles=[]:"undefined"==typeof c?a.outstandingRequireFiles.push(b):a.outstandingRequireFiles.splice(a.outstandingRequireFiles.indexOf(b),1)},requireFilesLoaded:function(){return 0===a.outstandingRequireFiles.length},showManualLoader:function(){if(!document.getElementById("blanketLoaderDialog")){var a="
";a+=" 
",a+="
",a+="
",a+="Error: Blanket.js encountered a cross origin request error while instrumenting the source files. ",a+="

This is likely caused by the source files being referenced locally (using the file:// protocol). ",a+="

Some solutions include starting Chrome with special flags, running a server locally, or using a browser without these CORS restrictions (Safari).",a+="
","undefined"!=typeof FileReader&&(a+="
Or, try the experimental loader. When prompted, simply click on the directory containing all the source files you want covered.",a+="Start Loader",a+=""),a+="
Close",a+="
",a+="
";var b=".blanketDialogWrapper {";b+="display:block;",b+="position:fixed;",b+="z-index:40001; }",b+=".blanketDialogOverlay {",b+="position:fixed;",b+="width:100%;",b+="height:100%;",b+="background-color:black;",b+="opacity:.5; ",b+="-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)'; ",b+="filter:alpha(opacity=50); ",b+="z-index:40001; }",b+=".blanketDialogVerticalOffset { ",b+="position:fixed;",b+="top:30%;",b+="width:100%;",b+="z-index:40002; }",b+=".blanketDialogBox { ",b+="width:405px; ",b+="position:relative;",b+="margin:0 auto;",b+="background-color:white;",b+="padding:10px;",b+="border:1px solid black; }";var c=document.createElement("style");c.innerHTML=b,document.head.appendChild(c);var d=document.createElement("div");d.id="blanketLoaderDialog",d.className="blanketDialogWrapper",d.innerHTML=a,document.body.insertBefore(d,document.body.firstChild)}},manualFileLoader:function(a){function b(a){var b=new FileReader;b.onload=g,b.readAsText(a)}var c=Array.prototype.slice;a=c.call(a).filter(function(a){return""!==a.type});var d=a.length-1,e=0,f={};sessionStorage.blanketSessionLoader&&(f=JSON.parse(sessionStorage.blanketSessionLoader));var g=function(c){var g=c.currentTarget.result,h=a[e],i=h.webkitRelativePath&&""!==h.webkitRelativePath?h.webkitRelativePath:h.name;f[i]=g,e++,e===d?(sessionStorage.setItem("blanketSessionLoader",JSON.stringify(f)),document.location.reload()):b(a[e])};b(a[e])},_loadFile:function(b){if("undefined"!=typeof b){var c=new XMLHttpRequest;c.open("GET",b,!1),c.send(),a._addScript(c.responseText)}},_addScript:function(a){var b=document.createElement("script");b.type="text/javascript",b.text=a,(document.body||document.getElementsByTagName("head")[0]).appendChild(b)},hasAdapter:function(){return null!==a.options("adapter")},report:function(b){document.getElementById("blanketLoaderDialog")||(a.blanketSession=null),b.files=window._$blanket;blanket.options("commonJS")?blanket._commonjs.require:window.require;if(!b.files||!Object.keys(b.files).length)return void(a.options("debug")&&console.log("BLANKET-Reporting No files were instrumented."));if("undefined"!=typeof b.files.branchFcn&&delete b.files.branchFcn,"string"==typeof a.options("reporter"))a._loadFile(a.options("reporter")),a.customReporter(b,a.options("reporter_options"));else if("function"==typeof a.options("reporter"))a.options("reporter")(b,a.options("reporter_options"));else{if("function"!=typeof a.defaultReporter)throw new Error("no reporter defined.");a.defaultReporter(b,a.options("reporter_options"))}},_bindStartTestRunner:function(a,b){a?a(b):window.addEventListener("load",b,!1)},_loadSourceFiles:function(b){blanket.options("commonJS")?blanket._commonjs.require:window.require;a.options("debug")&&console.log("BLANKET-Collecting page scripts");var c=a.utils.collectPageScripts();if(0===c.length)b();else{sessionStorage.blanketSessionLoader&&(a.blanketSession=JSON.parse(sessionStorage.blanketSessionLoader)),c.forEach(function(b){a.utils.cache[b]={loaded:!1}});var d=-1;a.utils.loadAll(function(a){return a?"undefined"!=typeof c[d+1]:(d++,d>=c.length?null:c[d])},b)}},beforeStartTestRunner:function(b){b=b||{},b.checkRequirejs="undefined"==typeof b.checkRequirejs?!0:b.checkRequirejs,b.callback=b.callback||function(){},b.coverage="undefined"==typeof b.coverage?!0:b.coverage,b.coverage?a._bindStartTestRunner(b.bindEvent,function(){a._loadSourceFiles(function(){var c=function(){return b.condition?b.condition():a.requireFilesLoaded()},d=function(){if(c()){a.options("debug")&&console.log("BLANKET-All files loaded, init start test runner callback.");var e=a.options("testReadyCallback");e?"function"==typeof e?e(b.callback):"string"==typeof e&&(a._addScript(e),b.callback()):b.callback()}else setTimeout(d,13)};d()})}):b.callback()},utils:{qualifyURL:function(a){var b=document.createElement("a");return b.href=a,b.href}}})}(blanket),blanket.defaultReporter=function(a){function b(a){var b=document.getElementById(a);b.style.display="block"===b.style.display?"none":"block"}function c(a){return a.replace(/\&/g,"&").replace(//g,">").replace(/\"/g,""").replace(/\'/g,"'")}function d(a,b){var c=b?0:1;return"undefined"==typeof a||null===typeof a||"undefined"==typeof a[c]?!1:a[c].length>0}function e(a,b,f,g,h){var i="",j="";if(q.length>0)if(i+="",q[0][0].end.line===h){if(i+=c(b.slice(0,q[0][0].end.column))+"",b=b.slice(q[0][0].end.column),q.shift(),q.length>0)if(i+="",q[0][0].end.line===h){if(i+=c(b.slice(0,q[0][0].end.column))+"",b=b.slice(q[0][0].end.column),q.shift(),!f)return{src:i+c(b),cols:f}}else{if(!f)return{src:i+c(b)+"",cols:f};j=""}else if(!f)return{src:i+c(b),cols:f}}else{if(!f)return{src:i+c(b)+"",cols:f};j=""}var k=f[a],l=k.consequent;if(l.start.line>h)q.unshift([k.alternate,k]),q.unshift([l,k]),b=c(b);else{var m="";if(i+=c(b.slice(0,l.start.column-g))+m,f.length>a+1&&f[a+1].consequent.start.line===h&&f[a+1].consequent.start.column-g";var o=k.alternate;if(o.start.line>h)i+=c(b.slice(l.end.column-g)),q.unshift([o,k]);else{if(i+=c(b.slice(l.end.column-g,o.start.column-g)),m="",i+=m,f.length>a+1&&f[a+1].consequent.start.line===h&&f[a+1].consequent.start.column-g",i+=c(b.slice(o.end.column-g)),b=i}}return{src:b+j,cols:f}}var f="#blanket-main {margin:2px;background:#EEE;color:#333;clear:both;font-family:'Helvetica Neue Light', 'HelveticaNeue-Light', 'Helvetica Neue', Calibri, Helvetica, Arial, sans-serif; font-size:17px;} #blanket-main a {color:#333;text-decoration:none;} #blanket-main a:hover {text-decoration:underline;} .blanket {margin:0;padding:5px;clear:both;border-bottom: 1px solid #FFFFFF;} .bl-error {color:red;}.bl-success {color:#5E7D00;} .bl-file{width:auto;} .bl-cl{float:left;} .blanket div.rs {margin-left:50px; width:150px; float:right} .bl-nb {padding-right:10px;} #blanket-main a.bl-logo {color: #EB1764;cursor: pointer;font-weight: bold;text-decoration: none} .bl-source{ overflow-x:scroll; background-color: #FFFFFF; border: 1px solid #CBCBCB; color: #363636; margin: 25px 20px; width: 80%;} .bl-source div{white-space: pre;font-family: monospace;} .bl-source > div > span:first-child{background-color: #EAEAEA;color: #949494;display: inline-block;padding: 0 10px;text-align: center;width: 30px;} .bl-source .miss{background-color:#e6c3c7} .bl-source span.branchWarning{color:#000;background-color:yellow;} .bl-source span.branchOkay{color:#000;background-color:transparent;}",g=60,h=document.head,i=0,j=document.body,k=Object.keys(a.files).some(function(b){return"undefined"!=typeof a.files[b].branchData}),l="
results
Coverage (%)
Covered/Total Smts.
"+(k?"
Covered/Total Branches
":"")+"
",m="
{{fileNumber}}.{{file}}
{{percentage}} %
{{numberCovered}}/{{totalSmts}}
"+(k?"
{{passedBranches}}/{{totalBranches}}
":"")+"
";grandTotalTemplate="
{{rowTitle}}
{{percentage}} %
{{numberCovered}}/{{totalSmts}}
"+(k?"
{{passedBranches}}/{{totalBranches}}
":"")+"
";var n=document.createElement("script");n.type="text/javascript",n.text=b.toString().replace("function "+b.name,"function blanket_toggleSource"),j.appendChild(n);var o=function(a,b){return Math.round(a/b*100*100)/100},p=function(a,b,c){var d=document.createElement(a);d.innerHTML=c,b.appendChild(d)},q=[],r=function(a){return"undefined"!=typeof a},s=a.files,t={totalSmts:0,numberOfFilesCovered:0,passedBranches:0,totalBranches:0,moduleTotalStatements:{},moduleTotalCoveredStatements:{},moduleTotalBranches:{},moduleTotalCoveredBranches:{}},u=_blanket.options("modulePattern"),v=u?new RegExp(u):null;for(var w in s)if(s.hasOwnProperty(w)){i++;var x,y=s[w],z=0,A=0,B=[];for(x=0;x0||"undefined"!=typeof y.branchData)if("undefined"!=typeof y.branchData[x+1]){var D=y.branchData[x+1].filter(r),E=0;C=e(E,C,D,0,x+1).src}else C=q.length?e(0,C,null,0,x+1).src:c(C);else C=c(C);var F="";y[x+1]?(A+=1,z+=1,F="hit"):0===y[x+1]&&(z++,F="miss"),B[x+1]="
"+(x+1)+""+C+"
"}t.totalSmts+=z,t.numberOfFilesCovered+=A;var G=0,H=0;if("undefined"!=typeof y.branchData)for(var I=0;I0&&"undefined"!=typeof y.branchData[I][J][1]&&y.branchData[I][J][1].length>0&&H++);if(t.passedBranches+=H,t.totalBranches+=G,v){var K=w.match(v)[1];t.moduleTotalStatements.hasOwnProperty(K)||(t.moduleTotalStatements[K]=0,t.moduleTotalCoveredStatements[K]=0),t.moduleTotalStatements[K]+=z,t.moduleTotalCoveredStatements[K]+=A,t.moduleTotalBranches.hasOwnProperty(K)||(t.moduleTotalBranches[K]=0,t.moduleTotalCoveredBranches[K]=0),t.moduleTotalBranches[K]+=G,t.moduleTotalCoveredBranches[K]+=H}var L=o(A,z),M=m.replace("{{file}}",w).replace("{{percentage}}",L).replace("{{numberCovered}}",A).replace(/\{\{fileNumber\}\}/g,i).replace("{{totalSmts}}",z).replace("{{totalBranches}}",G).replace("{{passedBranches}}",H).replace("{{source}}",B.join(" "));M=g>L?M.replace("{{statusclass}}","bl-error"):M.replace("{{statusclass}}","bl-success"),l+=M}var N=function(a,b,c,d,e){var f=o(b,a),h=g>f?"bl-error":"bl-success",i=e?"Total for module: "+e:"Global total",j=grandTotalTemplate.replace("{{rowTitle}}",i).replace("{{percentage}}",f).replace("{{numberCovered}}",b).replace("{{totalSmts}}",a).replace("{{passedBranches}}",d).replace("{{totalBranches}}",c).replace("{{statusclass}}",h);l+=j};if(v)for(var O in t.moduleTotalStatements)if(t.moduleTotalStatements.hasOwnProperty(O)){var P=t.moduleTotalStatements[O],Q=t.moduleTotalCoveredStatements[O],R=t.moduleTotalBranches[O],S=t.moduleTotalCoveredBranches[O];N(P,Q,R,S,O)}N(t.totalSmts,t.numberOfFilesCovered,t.totalBranches,t.passedBranches,null),l+="
",p("style",h,f),document.getElementById("blanket-main")?document.getElementById("blanket-main").innerHTML=l.slice(23,-6):p("div",j,l)},function(){var a={},b=Array.prototype.slice,c=b.call(document.scripts);b.call(c[c.length-1].attributes).forEach(function(b){if("data-cover-only"===b.nodeName&&(a.filter=b.nodeValue),"data-cover-never"===b.nodeName&&(a.antifilter=b.nodeValue),"data-cover-reporter"===b.nodeName&&(a.reporter=b.nodeValue),"data-cover-adapter"===b.nodeName&&(a.adapter=b.nodeValue),"data-cover-loader"===b.nodeName&&(a.loader=b.nodeValue),"data-cover-timeout"===b.nodeName&&(a.timeout=b.nodeValue),"data-cover-modulepattern"===b.nodeName&&(a.modulePattern=b.nodeValue),"data-cover-reporter-options"===b.nodeName)try{a.reporter_options=JSON.parse(b.nodeValue)}catch(c){if(blanket.options("debug"))throw new Error("Invalid reporter options. Must be a valid stringified JSON object.")}if("data-cover-testReadyCallback"===b.nodeName&&(a.testReadyCallback=b.nodeValue),"data-cover-customVariable"===b.nodeName&&(a.customVariable=b.nodeValue),"data-cover-flags"===b.nodeName){var d=" "+b.nodeValue+" ";d.indexOf(" ignoreError ")>-1&&(a.ignoreScriptError=!0),d.indexOf(" autoStart ")>-1&&(a.autoStart=!0),d.indexOf(" ignoreCors ")>-1&&(a.ignoreCors=!0),d.indexOf(" branchTracking ")>-1&&(a.branchTracking=!0),d.indexOf(" sourceURL ")>-1&&(a.sourceURL=!0),d.indexOf(" debug ")>-1&&(a.debug=!0),d.indexOf(" engineOnly ")>-1&&(a.engineOnly=!0),d.indexOf(" commonJS ")>-1&&(a.commonJS=!0),d.indexOf(" instrumentCache ")>-1&&(a.instrumentCache=!0)}}),blanket.options(a),"undefined"!=typeof requirejs&&blanket.options("existingRequireJS",!0),blanket.options("commonJS")&&(blanket._commonjs={})}(),function(a){a.extend({utils:{normalizeBackslashes:function(a){return a.replace(/\\/g,"/")},matchPatternAttribute:function(b,c){if("string"==typeof c){if(0===c.indexOf("[")){var d=c.slice(1,c.length-1).split(",");return d.some(function(c){return a.utils.matchPatternAttribute(b,a.utils.normalizeBackslashes(c.slice(1,-1)))})}if(0===c.indexOf("//")){var e=c.slice(2,c.lastIndexOf("/")),f=c.slice(c.lastIndexOf("/")+1),g=new RegExp(e,f);return g.test(b)}return 0===c.indexOf("#")?window[c.slice(1)].call(window,b):b.indexOf(a.utils.normalizeBackslashes(c))>-1}return c instanceof Array?c.some(function(c){return a.utils.matchPatternAttribute(b,c)}):c instanceof RegExp?c.test(b):"function"==typeof c?c.call(window,b):void 0},blanketEval:function(b){a._addScript(b)},collectPageScripts:function(){var b=Array.prototype.slice,c=(b.call(document.scripts),[]),d=[],e=a.options("filter");if(null!=e){var f=a.options("antifilter");c=b.call(document.scripts).filter(function(c){return 1===b.call(c.attributes).filter(function(b){return"src"===b.nodeName&&a.utils.matchPatternAttribute(b.nodeValue,e)&&("undefined"==typeof f||!a.utils.matchPatternAttribute(b.nodeValue,f))}).length})}else c=b.call(document.querySelectorAll("script[data-cover]"));return d=c.map(function(c){return a.utils.qualifyURL(b.call(c.attributes).filter(function(a){return"src"===a.nodeName})[0].nodeValue)}),e||a.options("filter","['"+d.join("','")+"']"),d},loadAll:function(b,c){var d=b(),e=a.utils.scriptIsLoaded(d,a.utils.ifOrdered,b,c);if(a.utils.cache[d]&&a.utils.cache[d].loaded)e();else{var f=function(){a.options("debug")&&console.log("BLANKET-Mark script:"+d+", as loaded and move to next script."),e()},g=function(b){a.options("debug")&&console.log("BLANKET-File loading finished"),"undefined"!=typeof b&&(a.options("debug")&&console.log("BLANKET-Add file to DOM."),a._addScript(b)),f()};a.utils.attachScript({url:d},function(b){a.utils.processFile(b,d,g,g)})}},attachScript:function(b,c){var d=a.options("timeout")||3e3;setTimeout(function(){if(!a.utils.cache[b.url].loaded)throw new Error("error loading source script")},d),a.utils.getFile(b.url,c,function(){throw new Error("error loading source script")})},ifOrdered:function(b,c){var d=b(!0);d?a.utils.loadAll(b,c):c(new Error("Error in loading chain."))},scriptIsLoaded:function(b,c,d,e){return a.options("debug")&&console.log("BLANKET-Returning function"),function(){a.options("debug")&&console.log("BLANKET-Marking file as loaded: "+b),a.utils.cache[b].loaded=!0,a.utils.allLoaded()?(a.options("debug")&&console.log("BLANKET-All files loaded"),e()):c&&(a.options("debug")&&console.log("BLANKET-Load next file."),c(d,e))}},cache:{},allLoaded:function(){for(var b=Object.keys(a.utils.cache),c=0;cb;b+=1){c=progIds[b];try{new ActiveXObject(c);break}catch(d){}}this.createXhr=function(){return new a(c)}}},craeteXhr:function(){throw new Error("cacheXhrConstructor is supposed to overwrite this function.")},getFile:function(b,c,d,e){var f=!1;if(a.blanketSession)for(var g=Object.keys(a.blanketSession),h=0;h-1)return c(a.blanketSession[i]),void(f=!0)}if(!f){var j=a.utils.createXhr();j.open("GET",b,!0),e&&e(j,b),j.onreadystatechange=function(){var a,e;4===j.readyState&&(a=j.status,a>399&&600>a?(e=new Error(b+" HTTP status: "+a),e.xhr=j,d(e)):c(j.responseText))};try{j.send(null)}catch(k){if(!k.code||101!==k.code&&1012!==k.code||a.options("ignoreCors")!==!1)throw k;a.showManualLoader()}}}}}),function(){var b=(blanket.options("commonJS")?blanket._commonjs.require:window.require,blanket.options("commonJS")?blanket._commonjs.requirejs:window.requirejs);!a.options("engineOnly")&&a.options("existingRequireJS")&&(a.utils.oldloader=b.load,b.load=function(b,c,d){a.requiringFile(d),a.utils.getFile(d,function(e){a.utils.processFile(e,d,function(){b.completeLoad(c)},function(){a.utils.oldloader(b,c,d)})},function(b){throw a.requiringFile(),b})}),a.utils.cacheXhrConstructor()}()}(blanket),function(){if("undefined"!=typeof QUnit){var a=function(){return window.QUnit.config.queue.length>0&&blanket.noConflict().requireFilesLoaded()};QUnit.config.urlConfig[0].tooltip?(QUnit.config.urlConfig.push({id:"coverage",label:"Enable coverage",tooltip:"Enable code coverage."}),QUnit.urlParams.coverage||blanket.options("autoStart")?(QUnit.begin(function(){blanket.noConflict().setupCoverage()}),QUnit.done(function(){blanket.noConflict().onTestsDone()}),QUnit.moduleStart(function(){blanket.noConflict().onModuleStart()}),QUnit.testStart(function(){blanket.noConflict().onTestStart()}),QUnit.testDone(function(a){blanket.noConflict().onTestDone(a.total,a.passed)}),blanket.noConflict().beforeStartTestRunner({condition:a,callback:function(){(!blanket.options("existingRequireJS")||blanket.options("autoStart"))&&QUnit.start()}})):(blanket.options("existingRequireJS")&&(requirejs.load=_blanket.utils.oldloader),blanket.noConflict().beforeStartTestRunner({condition:a,callback:function(){(!blanket.options("existingRequireJS")||blanket.options("autoStart"))&&QUnit.start()},coverage:!1}))):(QUnit.begin=function(){blanket.noConflict().setupCoverage()},QUnit.done=function(){blanket.noConflict().onTestsDone()},QUnit.moduleStart=function(){blanket.noConflict().onModuleStart()},QUnit.testStart=function(){blanket.noConflict().onTestStart()},QUnit.testDone=function(a){blanket.noConflict().onTestDone(a.total,a.passed)},blanket.beforeStartTestRunner({condition:a,callback:QUnit.start}))}}(); diff --git a/tests/general_val.js b/tests/general_val.js deleted file mode 100644 index d771a69a..00000000 --- a/tests/general_val.js +++ /dev/null @@ -1,52 +0,0 @@ - - test( "Make sure .val() behaviour didn't change.", function(){ - - Q.html('\ - \ - \ - \ -
\ - '); - - var one = $("#one"); - var two = $("#two"); - var three = $("#three"); - - var slider = $("#simpleslider").noUiSlider({ - range: { min: 20, max: 120 }, - start: 30 - }); - - one.val(35); - equal(one.val(), 35); - - one.val(35); - equal(one.val(), 35); - - two.val( 40 ); - equal(two.val(), 40); - - slider.add(one).val(90); - - equal(slider.val(), '90.00'); - equal(one.val(), 90); - - Q.find("input").val(60); - - equal(one.val(), 60); - equal(two.val(), 60); - equal(three.val(), 60); - - three.val(50); - - ok(one[0] === one.val(10)[0]); - ok(two[0] === two.val(20)[0]); - - var expectedValues = ['10', '20', '50']; - - Q.find("input").val(function(index, value){ - equal(value, expectedValues[index]); - }); - - ok(one.val(undefined)[0] === one[0]); - }); diff --git a/tests/link_basic.js b/tests/link_basic.js deleted file mode 100644 index 5c7b028c..00000000 --- a/tests/link_basic.js +++ /dev/null @@ -1,90 +0,0 @@ - - test( "Link implementation", function(){ - - $.fn.customMethod = function(val){ - this.html(val); - }; - - Q.html('\ -
\ - \ -
\ -
\ - '); - - var slider = $('.slider'), input = $("#input-field"), div1 = $('#div-field1'), div2 = $('#div-field2'); - - throws(function(){ - - slider.Link().to('throws'); - - }, 'Can\'t link before slider.'); - - slider.noUiSlider({ - start: [ 0, 20 ], - connect: true, - step: 10, - range: { - 'min': -30, - 'max': 30 - }, - format: TEST_ROUND_FORMAT - }); - - deepEqual(slider.val(), ['0', '20']); - - slider.Link().to(input); - - equal(input.val(), '0', 'Slider value is written to input'); - - input.val(60).change(); - equal(input.val(), '20', 'Value was parsed and limited to handle max.'); - deepEqual(slider.val(), ['20', '20']); - - slider.val([null, 30]); - deepEqual(slider.val(), ['20', '30']); - - input.val(60).change(); - equal(input.val(), '30', 'Value was parsed and limited to slider max.'); - - input.val(23).change(); - input.val('Run, Forrest!').change(); - equal(input.val(), '20', 'Slider ignored invalid value and reset input.'); - - slider.Link(false); - slider.val([-20, 10]) - - equal(input.val(), '20', 'Input ignored the slider'); - - input.val(-20).change(); - deepEqual(slider.val(), ['-20', '10'], 'Input didn\t affect slider.'); - - slider.Link('upper').to(div1, 'customMethod'); - - equal(div1.html(), '10', 'HTML was set'); - - slider.Link('upper').to(div2, function( value, handle, sliderInstance ){ - - equal(value, 10, "Value as expected."); - - ok(handle.hasClass("noUi-handle"), "Handle is a handle."); - ok(sliderInstance.hasClass("noUi-target"), "Slider is a slider."); - ok(div2[0] === this[0], "Element is scope of call and $."); - ok(slider[0] === sliderInstance[0], "Slider argument is slider."); - - $(this).Link(false); - }); - - equal(div2.html(), '', 'Element wasn\t altered.'); - - slider.Link().to(function( value, handle, sliderInstance ){ - - equal(value, -20, "Value as expected."); - - ok(handle.hasClass("noUi-handle-lower"), "Handle is a handle."); - ok(sliderInstance.hasClass("noUi-target"), "Slider is a slider."); - ok(sliderInstance[0] === this[0], "Slider is scope of call and $."); - - $(this).Link(false); - }); - }); diff --git a/tests/link_multiple.js b/tests/link_multiple.js deleted file mode 100644 index 8643a9c3..00000000 --- a/tests/link_multiple.js +++ /dev/null @@ -1,40 +0,0 @@ - - test( "Generation of named inputs", function(){ - - Q.html('\ -
\ -
\ -
\ -
\ -
\ - '); - - Q.find('.slider').noUiSlider({ - start: [ 20, 80 ], - range: { - 'min': [ 0 ], - 'max': [ 100 ] - } - }); - - Q.find('.slider').Link('lower').to('input-lower'); - Q.find('.slider').Link('upper').to('input-upper'); - - $("#slidera").val([50, 61]); - $("#sliderb").val([51, 62]); - $("#sliderc").val([52, 63]); - - var inputs = Q.find('input'); - - equal( inputs.length, 6, "Generated all inputs" ); - - equal( $(inputs[0]).val(), '50.00' ); - equal( $(inputs[1]).val(), '61.00' ); - equal( $(inputs[2]).val(), '51.00' ); - equal( $(inputs[3]).val(), '62.00' ); - equal( $(inputs[4]).val(), '52.00' ); - equal( $(inputs[5]).val(), '63.00' ); - - equal(Q.find('[name="input-lower"]').length, 3); - - }); diff --git a/tests/link_rtl.js b/tests/link_rtl.js deleted file mode 100644 index e9b0c6ec..00000000 --- a/tests/link_rtl.js +++ /dev/null @@ -1,25 +0,0 @@ - - test( "Test rtl link integration", function(){ - - Q.html('\ -
\ -
\ - \ -
\ - '); - - var slider = Q.find('#slider'), input = Q.find('#write'); - - slider.noUiSlider({ - range: { min: 0, max: 15 }, - direction: 'rtl', - orientation: 'vertical', - start: 5 - }).Link('lower').to(input); - - equal(input.val(), '5.00'); - - input.val('8').change(); - - equal(input.val(), '8.00'); - }); diff --git a/tests/link_select.js b/tests/link_select.js deleted file mode 100644 index 9ec5fd67..00000000 --- a/tests/link_select.js +++ /dev/null @@ -1,32 +0,0 @@ - - test( "Testing select elements", function(){ - - Q.html('\ -
\ - \ - '); - - var select = $('#select'); - - for( var i = -20; i <= 40; i++ ){ - select.append( - '' - ); - } - - $('.slider').noUiSlider({ - start: [ 10, 30 ], - connect: true, - range: { - 'min': -20, - 'max': 40 - } - }); - - $('.slider').Link('lower').to(select, null, TEST_ROUND_FORMAT); - - select.val( 40 ).change(); - - equal( select.val(), '30', 'Select was reset properly.' ); - - }); diff --git a/tests/link_update.js b/tests/link_update.js deleted file mode 100644 index c54b750c..00000000 --- a/tests/link_update.js +++ /dev/null @@ -1,68 +0,0 @@ - - test( "Test re-append of inline elements", function(){ - - Q.html('\ -
\ -
\ - \ -
\ - '); - - var slider = Q.find('.slider'), input = Q.find('#input-element'); - - slider.noUiSlider({ - start: [50, 70], - direction: 'rtl', - range: { - 'min': [ 0 ], - 'max': [ 100 ] - } - }); - - slider.Link().to('input-lower'); - slider.Link('upper').to(input); - - equal(input.val(), '70.00'); - equal(Q.find('[name="input-lower"]').length, 1); - equal(Q.find('[name="input-lower"]').val(), '50.00'); - - slider.Link(false); - equal(Q.find('[name="input-lower"]').length, 0, 'input was removed.'); - - slider[0].destroy(); - - throws(function(){ - slider.Link().to('input-throws'); - }, 'No slider to link to.'); - - slider.noUiSlider({ - start: [30, 40], - range: { - 'min': [ 0 ], - 'max': [ 150 ] - } - }); - - equal(input.val(), '70.00', 'Input didn\t change.'); - input.val(30).change(); - - deepEqual(slider.val(), ['30.00', '40.00'], 'Slider didn\'t change.'); - - slider.Link('lower').to('input-new'); - slider.Link('upper').to('-inline-'); - - equal(Q.find('[name="input-new"]').length, 1); - equal(Q.find('.noUi-handle > div').length, 1, 'Inline element was appended'); - equal(Q.find('.noUi-handle > div').html(), '40.00'); - - slider.noUiSlider({ - start: [40, 90], - direction: 'rtl' - }, true); - - equal(Q.find('.noUi-handle > div').html(), '90.00', 'Element is still there, with new value.'); - - equal(Q.find('[name="input-new"]').length, 1, 'Input was re-appended'); - equal(Q.find('[name="input-new"]').val(), '40.00', 'Value was set.'); - - }); diff --git a/tests/slider.html b/tests/slider.html index d868927e..08e871b5 100644 --- a/tests/slider.html +++ b/tests/slider.html @@ -15,13 +15,12 @@ - + + + + - - - - @@ -31,7 +30,8 @@
- - + - - - - - - - - - - + + - + diff --git a/tests/slider_binding.js b/tests/slider_binding.js new file mode 100644 index 00000000..2625bbc3 --- /dev/null +++ b/tests/slider_binding.js @@ -0,0 +1,84 @@ + + QUnit.test( "Binding", function( assert ){ + + assert.expect(10); + + Q.innerHTML = '
'; + + var sliders = Q.getElementsByClassName('slider'), + slider = sliders[0]; + + noUiSlider.create(slider, { + start: [ 2, 5 ], + range: { + 'min': 0, + 'max': 10 + } + }); + + var count = 0; + + // Fires on bind, for every handle (2+2) + slider.noUiSlider.on('update', function( values, handle ){ + assert.deepEqual(values, ['2.00', '5.00']); + assert.ok(count++ === handle); + }); + + slider.noUiSlider.off('update'); + count = 0; + + slider.noUiSlider.on('set', function( values, handle ){ + assert.deepEqual(values, ['1.00', '6.00']); + assert.ok(count++ === handle); + }); + + // Setting a value triggers 'set' for each handle (2+2) + slider.noUiSlider.set([1,6]); + + slider.noUiSlider.off('set'); + + // Run set again, 'set' shouldn't fire now. + slider.noUiSlider.set([1,9]); + + count = 0; + + // Fires once on click (1) + slider.noUiSlider.on('set.namespace', function( values, handle ){ + assert.ok(true); + }); + + // Fires once on click (1) + slider.noUiSlider.on('change.namespace', function( values, handle ){ + assert.ok(true); + }); + + document.body.addEventListener('mousedown', function(e){ + console.log(e.clientX, e.clientY); + }); + + function offset ( el ) { + var rect = el.getBoundingClientRect() + return { + top: rect.top + document.body.scrollTop, + left: rect.left + document.body.scrollLeft + }; + } + + var origin = slider.getElementsByClassName('noUi-origin')[1], + clickEvent = new MouseEvent('mousedown', { + bubbles: true, + cancelable: true, + view: window, + buttons: 1, + clientX: offset(slider).left + 100, + clientY: offset(slider).top + 8 + }); + + console.log(offset(slider)); + origin.dispatchEvent(clickEvent); + + slider.noUiSlider.off('.namespace'); + + // Doesn't trigger 'set' again + slider.noUiSlider.set([5, 7]); + }); diff --git a/tests/slider_errors.js b/tests/slider_errors.js new file mode 100644 index 00000000..057843d0 --- /dev/null +++ b/tests/slider_errors.js @@ -0,0 +1,105 @@ + + QUnit.test( "Errors", function( assert ){ + + Q.innerHTML = '
'; + + var sliders = Q.getElementsByClassName('slider'), + slider = sliders[0]; + + assert.throws(function(){ + noUiSlider.create(sliders, { + start: [ 5 ], + range: { + 'min': 0, + 'max': 10 + } + }); + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: [ 5 ], + range: { + 'min': 0, + 'max': 'nope.' + } + }); + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: [ 5 ], + step: 'u', + range: { + 'min': 0, + 'max': 10 + } + }); + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: [ 5 ], + range: { + 'min': 0 + } + }); + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: [ 5 ], + range: 'Over 9000!!!' + }); + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: [ 1, 2, 3 ], + range: { + 'min': 0, + 'max': 10 + } + }); + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: [ 1 ], + range: { + 'min': 0, + 'max': 10 + }, + animate: 3 + }); + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: [ 1 ], + range: { + 'min': 0, + 'max': 10 + }, + connect: true + }); + }); + + noUiSlider.create(slider, { + start: 1, + range: { + 'min': 0, + 'max': 10 + } + }); + + assert.throws(function(){ + noUiSlider.create(slider, { + start: 10, + range: { + 'min': 0, + 'max': 10 + } + }); + }); + }); diff --git a/tests/slider_events.js b/tests/slider_events.js deleted file mode 100644 index 75de2b46..00000000 --- a/tests/slider_events.js +++ /dev/null @@ -1,109 +0,0 @@ - - test( "Triggering events", function(){ - - Q.html('
'); - - var slider = Q.find('.slider'); - - slider.width(302); // Border of 2 pixels - - slider.noUiSlider({ - start: [ 0, 100 ], - connect: true, - range: { - 'min': [ 0 ], - 'max': [ 300 ] - } - }); - - equal(slider.find('.noUi-base').length, 1); - equal(slider.find('.noUi-base').width(), 300, 'Testable width') - - var handles = slider.find('.noUi-handle'); - - ok( !slider.hasClass('noUi-state-tap'), 'No transition on value set' ); - - slider.on('slide', function( event, values ){ - deepEqual( values, ['30.00', '100.00'], "Slide event has proper parameters." ); - slider.off('slide') - }); - - handles.first().trigger($.Event('mousedown', { - clientX: 10, - clientY: 0 - })); - - $(document).trigger($.Event('mousemove', { - clientX: 40, - clientY: 0 - })); - - $(document).trigger('mouseup'); - - - - - slider.on('set', function( event, values ){ - deepEqual( values, ['30.00', '249.00']); - slider.off('set') - }); - - handles.last().trigger($.Event('mousedown', { - clientX: 50, - clientY: 0 - })); - - $(document).trigger($.Event('mousemove', { - clientX: 100, - clientY: 0 - })); - - equal(handles.last().parent()[0].style.left, '50%', 'Proper half-way left offset.'); - - $(document).trigger($.Event('mousemove', { - clientX: 199, - clientY: 0 - })); - - $(document).trigger('mouseup'); - - deepEqual(slider.val(), ['30.00', '249.00'], 'Value has changed.'); - - - slider.val([10, 20]); - - ok( slider.hasClass('noUi-state-tap'), 'Animating class has been applied.' ); - - - QUnit.asyncTest( "Testing after animation", function(){ - - setTimeout(function() { - - QUnit.start(); - - ok( !slider.hasClass('noUi-state-tap'), 'Animation class is removed properly.' ); - - slider.on('change', function( event, values ){ - deepEqual( values, ['10.00', '10.00'], "Slide event has proper parameters." ); - slider.off('slide') - }); - - deepEqual( slider.val(), ['10.00', '20.00'] ); - - handles.last().trigger($.Event('mousedown', { - clientX: 1000, - clientY: 0 - })); - - $(document).trigger($.Event('mousemove', { - clientX: 980, - clientY: 0 - })); - - $(document).trigger('mouseup'); - - deepEqual( slider.val(), ['10.00', '10.00'], "Slider didn't cross." ); - - }, 350); - }); - }); diff --git a/tests/slider_get-step.js b/tests/slider_get-step.js index 6a4336c9..02ac11ee 100644 --- a/tests/slider_get-step.js +++ b/tests/slider_get-step.js @@ -1,33 +1,42 @@ - test( "Step API", function(){ + QUnit.test( "Step API", function( assert ){ function matchStep ( slider, value, steps ) { - slider.val(value); - deepEqual(slider.noUiSlider('step')[0], steps); + slider.noUiSlider.set(value); + assert.deepEqual(slider.noUiSlider.steps()[0], steps); } - Q.html('\ -
\ -
\ -
\ - '); + function matchStepBoth ( slider, value, steps ) { + slider.noUiSlider.set(value); + assert.deepEqual(slider.noUiSlider.steps(), steps); + } + + Q.innerHTML = '\ +
\ +
\ +
\ +
\ + '; - var slider1 = Q.find('.slider1'), slider2 = Q.find('.slider2'), slider3 = Q.find('.slider3'); + var slider1 = document.getElementById('slider1'), + slider2 = document.getElementById('slider2'), + slider3 = document.getElementById('slider3'), + slider4 = document.getElementById('slider4'); // Issue #391 - slider1.noUiSlider({ + noUiSlider.create(slider1, { range: { min: 1.1, max: 2 }, start: [ 1.2 ], step: 0.1 }); - matchStep(slider1, 1.1, [null, 0.1]); - matchStep(slider1, 1.2, [0.1, 0.1]); - matchStep(slider1, 1.9, [0.1, 0.1]); - matchStep(slider1, 2, [0.1, null]); + matchStep(slider1, 1.1, [null, 0.1]); // 1 + matchStep(slider1, 1.2, [0.1, 0.1]); // 2 + matchStep(slider1, 1.9, [0.1, 0.1]); // 3 + matchStep(slider1, 2, [0.1, null]); // 4 // Mixed steps - slider2.noUiSlider({ + noUiSlider.create(slider2, { start: 40, step: 10, range: { @@ -38,20 +47,20 @@ } }); - matchStep(slider2, 0, [null, 10]); - matchStep(slider2, 10, [10, 10]); - matchStep(slider2, 40, [10, 10]); - matchStep(slider2, 190, [10, 10]); - matchStep(slider2, 300, [10, 100]); - matchStep(slider2, 400, [100, 100]); - matchStep(slider2, 700, [100, 100]); - matchStep(slider2, 800, [100, 50]); - matchStep(slider2, 850, [50, 50]); - matchStep(slider2, 950, [50, 50]); - matchStep(slider2, 1000, [50, null]); + matchStep(slider2, 0, [null, 10]); // 5 + matchStep(slider2, 10, [10, 10]); // 6 + matchStep(slider2, 40, [10, 10]); // 7 + matchStep(slider2, 190, [10, 10]); // 8 + matchStep(slider2, 300, [10, 100]); // 9 + matchStep(slider2, 400, [100, 100]); // 10 + matchStep(slider2, 700, [100, 100]); // 11 + matchStep(slider2, 800, [100, 50]); // 12 + matchStep(slider2, 850, [50, 50]); // 13 + matchStep(slider2, 950, [50, 50]); // 14 + matchStep(slider2, 1000, [50, null]); // 15 // Small and 0 step - slider3.noUiSlider({ + noUiSlider.create(slider3, { start: 0.3, range: { 'min': 0, @@ -60,10 +69,39 @@ } }); - matchStep(slider3, 0, [null, false]); - matchStep(slider3, 0.9999, [false, false]); - matchStep(slider3, 1, [false, 0.0008]); - matchStep(slider3, 1.0008, [0.0008, 0.0008]); - matchStep(slider3, 1.2, [0.0008, 0.0008]); - matchStep(slider3, 1.3, [0.0008, null]); + matchStep(slider3, 0, [null, false]); // 16 + matchStep(slider3, 0.9999, [false, false]); // 17 + matchStep(slider3, 1, [false, 0.0008]); // 18 + matchStep(slider3, 1.0008, [0.0008, 0.0008]); //19 + matchStep(slider3, 1.2, [0.0008, 0.0008]); // 20 + matchStep(slider3, 1.3, [0.0008, null]); // 21 + + // two handles + noUiSlider.create(slider4, { + start: [0.3, 0.9], + range: { + 'min': 0, + '50%': [ 1, 6 ], + '70%': [ 8, 3 ], + 'max': 18 + } + }); + + matchStepBoth(slider4, [0, 18], [[null, false], [3, null]]); // 22 + assert.deepEqual(slider4.noUiSlider.get(), ['0.00', '18.00']); // 23 + + matchStepBoth(slider4, [5, 9], [[6, 6], [6, 3]]); // 24 + assert.deepEqual(slider4.noUiSlider.get(), ['7.00', '8.00']); // 25 + + matchStepBoth(slider4, [1, 16], [[false, 6], [3, 3]]); // 26 + assert.deepEqual(slider4.noUiSlider.get(), ['1.00', '17.00']); // 27 + + matchStepBoth(slider4, [1.0008, 8], [[false, 6], [6, 3]]); // 28 + assert.deepEqual(slider4.noUiSlider.get(), ['1.00', '8.00']); // 29 + + matchStepBoth(slider4, [1.2, 16.458], [[false, 6], [3, 3]]); // 30 + assert.deepEqual(slider4.noUiSlider.get(), ['1.00', '17.00']); // 31 + + matchStepBoth(slider4, [1.3, 8], [[false, 6], [6, 3]]); // 32 + assert.deepEqual(slider4.noUiSlider.get(), ['1.00', '8.00']); // 33 }); diff --git a/tests/slider_limit.js b/tests/slider_limit.js index 9cc6651e..2e2e31ca 100644 --- a/tests/slider_limit.js +++ b/tests/slider_limit.js @@ -1,33 +1,37 @@ - test( "Limit option", function(){ + QUnit.test( "Limit option", function( assert ){ - Q.html('\ -
\ - '); + Q.innerHTML = '
'; - var slider = Q.find('.slider'); - - slider.noUiSlider({ + var settings = { start: [ 50, 100 ], limit: 30, range: { 'min': 30, 'max': 986 } - }); + }; + + var slider = Q.getElementsByClassName('slider')[0]; + + noUiSlider.create(slider, settings); + + assert.deepEqual( slider.noUiSlider.get(), ['50.00', '80.00'], 'Limit applied on init.' ); + + slider.noUiSlider.set( [ null, 600 ] ); + assert.deepEqual( slider.noUiSlider.get(), ['50.00', '80.00'], 'Handle can\'t leave limit.' ); + + slider.noUiSlider.set( [ 150, 600 ] ); + assert.deepEqual( slider.noUiSlider.get(), ['150.00', '180.00'], 'Multiple set limit.' ); - deepEqual( slider.val(), ['50.00', '80.00'], 'Limit applied on init.' ); + // Rebuild with new settings; + settings.direction = 'rtl'; + slider.noUiSlider.destroy(); - slider.val( [ null, 600 ] ); - deepEqual( slider.val(), ['50.00', '80.00'], 'Handle can\'t leave limit.' ); - - slider.val( [ 150, 600 ] ); - deepEqual( slider.val(), ['150.00', '180.00'], 'Multiple set limit.' ); + noUiSlider.create(slider, settings); - slider.noUiSlider({ direction: 'rtl' }, true); - - deepEqual( slider.val(), ['150.00', '180.00'], 'Re-init rtl keeps value.' ); + assert.deepEqual( slider.noUiSlider.get(), ['50.00', '80.00'], 'RTL correct value.' ); - slider.val( [ 120, 240 ] ); - deepEqual( slider.val(), ['120.00', '150.00'], 'RTL set.' ); + slider.noUiSlider.set( [ 120, 240 ] ); + assert.deepEqual( slider.noUiSlider.get(), ['120.00', '150.00'], 'RTL set.' ); }); diff --git a/tests/slider_non-linear-rtl.js b/tests/slider_non-linear-rtl.js index a0dc2498..563d6dab 100644 --- a/tests/slider_non-linear-rtl.js +++ b/tests/slider_non-linear-rtl.js @@ -1,15 +1,15 @@ - test( "Testing ltr and rtl non-linear", function(){ + QUnit.test( "Testing ltr and rtl non-linear", function( assert ){ - Q.html('\ + Q.innerHTML = '\
\
\ - '); + '; - var sliderRTL = $('.sliderRTL'); - var sliderLTR = $('.sliderLTR'); + var sliderRTL = Q.getElementsByClassName('sliderRTL')[0]; + var sliderLTR = Q.getElementsByClassName('sliderLTR')[0]; - sliderRTL.noUiSlider({ + noUiSlider.create(sliderRTL, { range: { 'min': 0, '30%': 5, @@ -21,7 +21,7 @@ format: TEST_ROUND_FORMAT }); - sliderLTR.noUiSlider({ + noUiSlider.create(sliderLTR, { range: { 'min': 0, '30%': 5, @@ -32,18 +32,18 @@ format: TEST_ROUND_FORMAT }); - equal(sliderRTL.val(), '40', 'Start stepping on rtl works'); - equal(sliderLTR.val(), '40', 'Start stepping on ltr works'); + equal(sliderRTL.noUiSlider.get(), '40', 'Start stepping on rtl works'); + equal(sliderLTR.noUiSlider.get(), '40', 'Start stepping on ltr works'); - sliderRTL.val(42); - sliderLTR.val(42); + sliderRTL.noUiSlider.set(42); + sliderLTR.noUiSlider.set(42); - equal(sliderRTL.val(), '40', 'RTL slider stepped by 10 in upper half.'); - equal(sliderLTR.val(), '40', 'LTR slider stepped by 10 in upper half.'); + equal(sliderRTL.noUiSlider.get(), '40', 'RTL slider stepped by 10 in upper half.'); + equal(sliderLTR.noUiSlider.get(), '40', 'LTR slider stepped by 10 in upper half.'); - sliderRTL.val(6); - sliderLTR.val(6); + sliderRTL.noUiSlider.set(6); + sliderLTR.noUiSlider.set(6); - equal(sliderRTL.val(), '6', 'RTL slider didn\'t step in lower half.'); - equal(sliderLTR.val(), '6', 'LTR slider didn\'t step in lower half.'); + equal(sliderRTL.noUiSlider.get(), '6', 'RTL slider didn\'t step in lower half.'); + equal(sliderLTR.noUiSlider.get(), '6', 'LTR slider didn\'t step in lower half.'); }); diff --git a/tests/slider_none.js b/tests/slider_none.js deleted file mode 100644 index 6b228a08..00000000 --- a/tests/slider_none.js +++ /dev/null @@ -1,12 +0,0 @@ - - test( "No slider", function(){ - - Q.html(''); - - var slider = Q.find('.slider'), is = slider.noUiSlider({ - range: { min: 0, max: 20 }, - start: [ 12 ], - }); - - equal(is, slider); - }); diff --git a/tests/slider_rtl.js b/tests/slider_rtl.js index 17839d34..08277464 100644 --- a/tests/slider_rtl.js +++ b/tests/slider_rtl.js @@ -1,13 +1,12 @@ - test( "RTL slider multiple value set.", function(){ + QUnit.test( "RTL slider multiple value set.", function( assert ){ - Q.html('\ -
\ -
\ - '); + Q.innerHTML = '
'; - var slider = $("#slider").noUiSlider({ - range: {min: 0.201, max: 1}, + var slider = Q.getElementsByClassName('slider')[0]; + + noUiSlider.create(slider, { + range: { min: 0.201, max: 1 }, step: 0.01, start: 0.401, direction: "rtl", @@ -20,35 +19,11 @@ } }); - equal(slider.val(), 0.4); - - slider.val(0.201, true); - equal(slider.val(), 0.2); - - slider.val(0.201, true); - equal(slider.val(), 0.2); - - - var slider2 = $("#slider2").noUiSlider({ - range: { - 'min': 0, - 'max': 50 - }, - start: [10, 40], - behaviour: 'tap', - connect: true, - direction : 'rtl' - }); - - deepEqual(slider2.val(), ["10.00", "40.00"], "Proper start handling in RTL."); - - slider2.val([20,30]); - deepEqual(slider2.val(), ["20.00", "30.00"]); - - slider2.val([40,45]); - deepEqual(slider2.val(), ["40.00", "45.00"], "RTL slider overstepped properly."); + equal(slider.noUiSlider.get(), 0.4); - slider2.val([30,35]); - deepEqual(slider2.val(), ["30.00", "35.00"], "RTL slider understepped properly."); + slider.noUiSlider.set(0.201); + equal(slider.noUiSlider.get(), 0.2); + slider.noUiSlider.set(0.201); + equal(slider.noUiSlider.get(), 0.2); }); diff --git a/tests/slider_rtl2.js b/tests/slider_rtl2.js new file mode 100644 index 00000000..0d9ea47a --- /dev/null +++ b/tests/slider_rtl2.js @@ -0,0 +1,30 @@ + + QUnit.test( "RTL slider 2", function( assert ){ + + Q.innerHTML = '
'; + + var slider = Q.getElementsByClassName('slider')[0]; + + noUiSlider.create(slider, { + range: { + 'min': 0, + 'max': 50 + }, + start: [10, 40], + behaviour: 'tap', + connect: true, + direction : 'rtl' + }); + + assert.deepEqual(slider.noUiSlider.get(), ["10.00", "40.00"], "Proper start handling in RTL."); + + slider.noUiSlider.set([20,30]); + assert.deepEqual(slider.noUiSlider.get(), ["20.00", "30.00"]); + + slider.noUiSlider.set([40,45]); + assert.deepEqual(slider.noUiSlider.get(), ["40.00", "45.00"], "RTL slider overstepped properly."); + + slider.noUiSlider.set([30,35]); + assert.deepEqual(slider.noUiSlider.get(), ["30.00", "35.00"], "RTL slider understepped properly."); + + }); diff --git a/tests/slider_setting-getting.js b/tests/slider_setting-getting.js index f040cf1a..e0a3f02e 100644 --- a/tests/slider_setting-getting.js +++ b/tests/slider_setting-getting.js @@ -1,11 +1,11 @@ - test( "Value setting/getting", function(){ + QUnit.test( "Value setting/getting", function( assert ){ - Q.html('\ -
\ - '); + Q.innerHTML = '
'; - var slider = $('#slider').noUiSlider({ + var slider = Q.getElementsByClassName('slider')[0]; + + noUiSlider.create(slider, { range: { min: -30, max: 1080 }, start: [ 0, 10 ], behaviour: 'drag', @@ -18,35 +18,35 @@ } }); - deepEqual(slider.val(), ["0.0", "10.0"]); + assert.deepEqual(slider.noUiSlider.get(), ["0.0", "10.0"]); - slider.val([-10, 80]); - deepEqual(slider.val(), ["-10.0", "80.0"]); + slider.noUiSlider.set([-10, 80]); + assert.deepEqual(slider.noUiSlider.get(), ["-10.0", "80.0"]); - slider.val(5); - deepEqual(slider.val(), ["5.0", "80.0"]); + slider.noUiSlider.set(5); + assert.deepEqual(slider.noUiSlider.get(), ["5.0", "80.0"]); - slider.val([10, 980.51]); - deepEqual(slider.val(), ["10.0", "980.5"]); + slider.noUiSlider.set([10, 980.51]); + assert.deepEqual(slider.noUiSlider.get(), ["10.0", "980.5"]); - slider.val([null]); - deepEqual(slider.val(), ["10.0", "980.5"]); + slider.noUiSlider.set([null]); + assert.deepEqual(slider.noUiSlider.get(), ["10.0", "980.5"]); - slider.val([null, 80]); + slider.noUiSlider.set([null, 80]); - slider.val([10.6]); - deepEqual(slider.val(), ["10.6", "80.0"]); + slider.noUiSlider.set([10.6]); + assert.deepEqual(slider.noUiSlider.get(), ["10.6", "80.0"]); - slider.val([null, 10.6]); - deepEqual(slider.val(), ["10.6", "10.6"]); + slider.noUiSlider.set([null, 10.6]); + assert.deepEqual(slider.noUiSlider.get(), ["10.6", "10.6"]); - slider.val([30, null]); - deepEqual(slider.val(), ["10.6", "10.6"]); + slider.noUiSlider.set([30, null]); + assert.deepEqual(slider.noUiSlider.get(), ["10.6", "10.6"]); - slider.val(null); - deepEqual(slider.val(), ["10.6", "10.6"]); + slider.noUiSlider.set(null); + assert.deepEqual(slider.noUiSlider.get(), ["10.6", "10.6"]); - slider.val(false); - deepEqual(slider.val(), ["10.6", "10.6"]); + slider.noUiSlider.set(false); + assert.deepEqual(slider.noUiSlider.get(), ["10.6", "10.6"]); }); diff --git a/tests/slider_step.js b/tests/slider_step.js index 6d860405..3dc2f6b4 100644 --- a/tests/slider_step.js +++ b/tests/slider_step.js @@ -1,27 +1,25 @@ - test( "Testing handling of odd-numbered steps", function(){ + QUnit.test( "Testing handling of odd-numbered steps", function( assert ){ - Q.html('\ -
\ - '); + Q.innerHTML = '
'; - var slider = $('.slider'); + var slider = Q.getElementsByClassName('slider')[0]; - slider.noUiSlider({ + noUiSlider.create(slider, { range: { min: 3, max: 106 }, start: [ 20, 50 ], step: 10, format: TEST_ROUND_FORMAT }); - deepEqual( slider.val(), ['23', '53'] ); + assert.deepEqual( slider.noUiSlider.get(), ['23', '53'] ); - slider.val([50, 106]); - deepEqual( slider.val(), ['53', '106'], 'Slider reached edge outside from step.' ); + slider.noUiSlider.set([50, 106]); + assert.deepEqual( slider.noUiSlider.get(), ['53', '106'], 'Slider reached edge outside from step.' ); - slider.val([71, 105]); - deepEqual( slider.val(), ['73', '103'], 'Slider steps back into stepping with lower points as origin.' ); + slider.noUiSlider.set([71, 105]); + assert.deepEqual( slider.noUiSlider.get(), ['73', '103'], 'Slider steps back into stepping with lower points as origin.' ); - slider.val([71, 101]); - deepEqual( slider.val(), ['73', '103'] ); + slider.noUiSlider.set([71, 101]); + assert.deepEqual( slider.noUiSlider.get(), ['73', '103'] ); }); diff --git a/tests/slider_unordered.js b/tests/slider_unordered.js index 34d9b0bb..9efb287f 100644 --- a/tests/slider_unordered.js +++ b/tests/slider_unordered.js @@ -1,27 +1,30 @@ - test( "Unordered slider range", function(){ + QUnit.test( "Unordered slider range", function( assert ){ - Q.html('\ -
\ - '); + Q.innerHTML = '
'; - var slider = Q.find('.slider'); + var slider = Q.getElementsByClassName('slider')[0]; - slider.noUiSlider({ + noUiSlider.create(slider, { + start: [ 12 ], + format: TEST_ROUND_FORMAT, range: { '50%': 16, 'min': 11, '10%': 12, 'max': 20 - }, - start: [ 12 ], - format: TEST_ROUND_FORMAT + } }); - equal(slider.val(11).val(), 11); - equal(slider.find('.noUi-origin')[0].style.left, '0%'); - equal(slider.val(12).val(), 12); - equal(slider.find('.noUi-origin')[0].style.left, '10%'); - equal(slider.val(16).val(), 16); - equal(slider.find('.noUi-origin')[0].style.left, '50%'); + slider.noUiSlider.set(11); + equal(slider.noUiSlider.get(), 11); + equal(slider.getElementsByClassName('noUi-origin')[0].style.left, '0%'); + + slider.noUiSlider.set(12); + equal(slider.noUiSlider.get(), 12); + equal(slider.getElementsByClassName('noUi-origin')[0].style.left, '10%'); + + slider.noUiSlider.set(16); + equal(slider.noUiSlider.get(), 16); + equal(slider.getElementsByClassName('noUi-origin')[0].style.left, '50%'); }); diff --git a/tests/slider_update.js b/tests/slider_update.js index 67f78ae4..1a02f66c 100644 --- a/tests/slider_update.js +++ b/tests/slider_update.js @@ -1,63 +1,51 @@ - test( "Testing update method", function(){ + QUnit.test( "Testing update method", function( assert ){ - Q.html('\ + Q.innerHTML = '\
\ - \ - '); + '; - var slider = $('.slider'); + var slider = Q.getElementsByClassName('slider')[0]; - slider.noUiSlider({ + noUiSlider.create(slider, { range: { min: 20, max: 140 }, start: 50, format: TEST_ROUND_FORMAT }); - deepEqual(slider.val(), '50'); + assert.deepEqual(slider.noUiSlider.get(), '50'); - slider[0].destroy(); + slider.noUiSlider.destroy(); - ok(slider.is(':empty'), 'Slider was cleared'); + equal(slider.innerHTML, '', 'Slider was cleared'); - equal ( slider.val(), '', 'Slider has no value' ); - - slider.noUiSlider({ + var settings = { range: { min: 30, max: 70 }, start: [ 30, 60 ], format: TEST_ROUND_FORMAT - }); - - deepEqual(slider.val(), ['30', '60']); - - slider.val(70); - deepEqual(slider.val(), ['60', '60']); + }; - slider.val(40); - deepEqual(slider.val(), ['40', '60']); + noUiSlider.create(slider, settings); - equal ( slider.find('.noUi-connect').length, 0, 'Slider uses no connection' ); + assert.deepEqual(slider.noUiSlider.get(), ['30', '60']); - slider.noUiSlider({ - connect: true - }, true); + slider.noUiSlider.set(70); + assert.deepEqual(slider.noUiSlider.get(), ['60', '60']); - equal ( slider.find('.noUi-connect').length, 1, 'Slider now connects' ); + slider.noUiSlider.set(40); + assert.deepEqual(slider.noUiSlider.get(), ['40', '60']); - deepEqual(slider.val(), ['40', '60'], 'Value was unchanged'); + equal ( slider.getElementsByClassName('noUi-connect').length, 0, 'Slider uses no connection' ); - slider.val([30,50]); - deepEqual(slider.val(), ['30', '50'], 'Can still set slider'); + settings.connect = true; + slider.noUiSlider.destroy(); - slider[0].destroy(); + noUiSlider.create(slider, settings); - ok ( !slider[0].destroy, 'destroy method removed itself'); - - slider.noUiSlider({ - start: 30, - range: { min: 80, max: 1000 } - }, true); + equal ( slider.getElementsByClassName('noUi-connect').length, 1, 'Slider now connects' ); - equal(slider.val(), '80.00', 'Slider was build, ignoring the rebuild flag.'); + assert.deepEqual(slider.noUiSlider.get(), ['30', '60'], 'Value was unchanged'); + slider.noUiSlider.set([30,50]); + assert.deepEqual(slider.noUiSlider.get(), ['30', '50'], 'Can still set slider'); }); diff --git a/tests/slider_values.js b/tests/slider_values.js index 1d9d019c..b91a66b9 100644 --- a/tests/slider_values.js +++ b/tests/slider_values.js @@ -1,26 +1,24 @@ - test( "Values", function(){ + QUnit.test( "Values", function( assert ){ - Q.html('\ -
\ - '); + Q.innerHTML = '
'; - var slider = $('.slider'); + var slider = Q.getElementsByClassName('slider')[0]; - slider.noUiSlider({ + noUiSlider.create(slider, { start: [ 50, 100 ], connect: true, + format: TEST_ROUND_FORMAT, range: { 'min': 30, 'max': 986 - }, - format: TEST_ROUND_FORMAT + } }); - deepEqual( slider.val(), ['50', '100'], 'Values where set' ); + assert.deepEqual( slider.noUiSlider.get(), ['50', '100'], 'Values where set' ); - slider.val( [ 150, 600 ] ); + slider.noUiSlider.set( [ 150, 600 ] ); - deepEqual( slider.val(), ['150', '600'], 'Slider correctly overstepped limits.' ); + assert.deepEqual( slider.noUiSlider.get(), ['150', '600'], 'Slider correctly overstepped limits.' ); }); diff --git a/tests/wnumb_basic.js b/tests/wnumb_basic.js deleted file mode 100644 index 4acfa0b3..00000000 --- a/tests/wnumb_basic.js +++ /dev/null @@ -1,66 +0,0 @@ - - test( "Serialization and formatting options", function(){ - - Q.html('\ -
\ - \ - \ - \ - '); - - $("#slider").noUiSlider({ - start: [ 0, 0.002 ], - connect: true, - behaviour: 'drag', - range: { - 'min': [ 0.001 ], - 'max': [ 0.003 ] - }, - format: wNumb({ - decimals: 5 - }) - }); - - $("#slider").Link('lower').to('-inline-
', function( value, handle, slider ){ - ok( $("#slider")[0] === slider[0] ); - ok( handle.hasClass('noUi-handle') ); - }, wNumb({ - decimals: 6, - prefix: '#', - negativeBefore: '!', - negative: '' - })); - - $("#slider").Link('lower').to($("#inputChange"), null, wNumb({ - mark: '.', - thousand: ',', - prefix: '$', - postfix: ' p.p.', - decimals: 3, - negativeBefore: '-', - negative: '', - encoder: function( a ){ - return a * 1E7; - }, - decoder: function( a ){ - return a / 1E7; - } - })); - - $("#slider").Link('upper').to($("#inputVal"), 'val'); - - $("#inputChange").val( "15000" ).trigger('change'); - - equal( $("#inputChange").val(), "$15,000.000 p.p.", "Testing interpretation of improper data" ); - - $("#inputVal").val( 3 ); - - equal( $("#inputVal").val(), "3" ); - - $("#inputVal").trigger("change"); - - equal ( $("#inputVal").val(), "3", "Input doesn't respond to change events." ); - - deepEqual( $("#slider").val(), ["0.00150", "0.00200"] ); - - });