From 3d28bcf9934e13f028183325b21b605cbcbc6c1d Mon Sep 17 00:00:00 2001 From: Leon Gersen Date: Tue, 24 Sep 2013 19:36:32 +0200 Subject: [PATCH] Minor fixes, remove minified versions --- README.md | 66 +++++--- jquery.nouislider.css | 27 +-- jquery.nouislider.js | 344 ++++++++++++++++++++++++-------------- jquery.nouislider.min.css | 1 - jquery.nouislider.min.js | 16 -- nouislider.jquery.json | 2 +- 6 files changed, 282 insertions(+), 174 deletions(-) delete mode 100644 jquery.nouislider.min.css delete mode 100644 jquery.nouislider.min.js diff --git a/README.md b/README.md index 06d580d7..0918c4ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # noUiSlider -_Current version: 4.0.0_ +_Current version: 4.0.2_ noUiSlider is a super tiny jQuery plugin that allows you to create range sliders. It fully supports touch, and it is way(!) less bloated than the jQueryUI library. @@ -8,32 +8,60 @@ A full documentation, including examples, is available on the [noUiSlider docume Changes ------- -**Changelog for version 4:** +**Changelog for version 4.2:** +_[current patch release]_ ++ Fixed some minor CSS issues in the default theme ++ The slider will no longer force an arbitrary width or height ++ Changed source to comply to more JsLint suggestions ++ Removed compressed versions from the tracking system. They'll still be produced and provided, but they'll only be bundled in the [Github Releases Feature](https://github.com/blog/1547-release-your-software). ++ Some very small changes to internal input testing + +**Changelog for version 4:** _[current major release]_ -* Massive update overhauling the entire code style -* Better styling possibilties -* Brand new Flat theme -* Windows Phone 8 support -* Performance improvements -* New way of handling disabled sliders -* Internal option testing provides feedback on issues ++ Massive update overhauling the entire code style ++ Better styling possibilities ++ Brand new Flat theme ++ Windows Phone 8 support ++ Performance improvements ++ New way of handling disabled sliders ++ Internal option testing provides feedback on issues + +Version numbering +------------------------------ +Version numbering follows the 'Semantic versioning' style. +You'll find an excellent documentation at [Semver.org](http://semver.org/). Compression and Error checking ------------------------------ +**CSS** ([CSSMinifier](http://cssminifier.com/)) +The stylesheet is trimmed of whitespace and comments to provide a `min` version. -**CSS** -The stylesheet is compressed using: -[CSSMinifier](http://cssminifier.com/) +**JS** ([Google Closure Compiler](http://closure-compiler.appspot.com/home)) +The plugin is compressed using the Google Closure compiler, using the 'simple' optimization option. -**JS** -The plugin is compressed using the Google Closure compiler, using the 'simple' optimalization option. -[Google Closure Compiler](http://closure-compiler.appspot.com/home) -**Code** +**Code** ([JsLint](http://jslint.com/)) The plugin code is checked using JsLint, with the following options: -`/*jslint browser: true, devel: true, nomen: true, plusplus: true, unparam: true, sloppy: true, todo: true, white: true */` +``` +browser: true +devel: true +plusplus: true +unparam: true +sloppy: true +white: true +``` + +Please note that while some errors remain without these options, they are merely differences in coding style. Using `++` for example, is in my opinion very clear in a `for` loop. Some jQuery methods offer callbacks noUiSlider doesn't require, thus requiring `unparam`, and the `devel` option is required for the `console` statements. The `sloppy` option refers to a missing `"use strict"` statement, which isn't included for lack of testing. + +Known issues +------------ +There are some minor issues remaining in noUiSlider 4. It is a priority to fix these issues. -Please note that while some errors remain, these are not issues as they are merely a difference in coding style. -[JsLint](http://jslint.com/) ++ Firefox will prefer scrolling to dragging the slider on touch events. The `preventDefault()` call that prevents this in other browser seems to fail here. ++ In IE10, tapping the slider to move it will fail in with these conditions: + + The paged is zoomed; + + The slider uses the `orientation: vertical` option + + The page is scrolled, so that `scrollTop` > 0 + This issue affects both IE10 in Windows 8 and Windows Phone 8. diff --git a/jquery.nouislider.css b/jquery.nouislider.css index d4315dea..7c89a0aa 100644 --- a/jquery.nouislider.css +++ b/jquery.nouislider.css @@ -1,7 +1,7 @@ /* General CSS resets; * The target itself is not affected, allowing - * the remainder of the document to use an + * the remainder of the document to use an * alternate box-sizing model; * Support for box-sizing is wide spread: * http://caniuse.com/#search=box-sizing @@ -19,17 +19,21 @@ } /* Main slider bar; + * Standard styles no longer incorrectly force a + * width or height on the slider. */ .noUi-base { height: 40px; - width: 300px; position: relative; max-width: 100%; + max-height: 100%; border: 1px solid #bfbfbf; z-index: 1; } /* Handles + active state; + * The :after pseudo-element wont inherit + * box-sizing, so it needs to applied manually. */ .noUi-handle { background: #EEE; @@ -42,6 +46,9 @@ background: #E9E9E9; } .noUi-active:after { +-webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; content: ""; display: block; height: 100%; @@ -76,13 +83,13 @@ .noUi-z-index { z-index: 10; } - + /* Adaptations for the vertical slider; + * Some standard styles have been extended to keep + * exceptions for the vertical slider as minimal as possible. */ .noUi-vertical { - height: 300px; width: 40px; - max-height: 100%; } .noUi-vertical .noUi-origin { bottom: 0; @@ -93,11 +100,11 @@ } /* Various alternate slider states; - * Support for transition is widely available, - * Only IE7, IE8 and IE9 will ignore these rules. - * Since this is merely a progressive enhancement, - * this is no problem at all. - * http://caniuse.com/#search=transition + * Support for transition is widely available, + * Only IE7, IE8 and IE9 will ignore these rules. + * Since this is merely a progressive enhancement, + * this is no problem at all. + * http://caniuse.com/#search=transition */ .noUi-target[disabled] .noUi-base { background: #999; diff --git a/jquery.nouislider.js b/jquery.nouislider.js index c730df9c..01c4463b 100644 --- a/jquery.nouislider.js +++ b/jquery.nouislider.js @@ -1,4 +1,4 @@ -/* noUiSlider 4.0.0 */ +/* noUiSlider - refreshless.com/nouislider/ */ (function($, UNDEF){ $.fn.noUiSlider = function( options ){ @@ -33,27 +33,38 @@ ,'noUi-background' // 13 ,'noUi-z-index' // 14 ] + // Define an extendible object with base classes for the various + // structure elements in the slider. These can be extended by simply + // pushing to the array, which reduces '.addClass()' calls. ,stdCls = { base: [clsList[0], clsList[13]] ,origin: [clsList[1]] ,handle: [clsList[2]] } + // The percentage object contains some well tested math to turn values + // to and from percentages. It can be a bit strange to wrap your head + // around the individual calls, but they'll do their job with all positive + // and negative input values. ,percentage = { - to : function (range, value) { + to: function ( range, value ) { value = range[0] < 0 ? value + Math.abs(range[0]) : value - range[0]; - return (value * 100) / this._length(range); - }, - from : function (range, value) { - return (value * 100) / this._length(range); - }, - is : function (range, value) { - return ((value * this._length(range)) / 100) + range[0]; - }, - _length : function (range) { + return (value * 100) / this.len(range); + } + ,from: function ( range, value ) { + return (value * 100) / this.len(range); + } + ,is: function ( range, value ) { + return ((value * this.len(range)) / 100) + range[0]; + } + ,len: function ( range ) { return (range[0] > range[1] ? range[0] - range[1] : range[1] - range[0]); } }; + // When the browser supports MsPointerEvents, + // Don't bind touch or mouse events. The touch events are + // currently only implemented by IE(10), but they are stable + // and convenient to use. if ( window.navigator.msPointerEnabled ) { actions = { start: 'MSPointerDown' + namespace @@ -61,11 +72,14 @@ ,end: 'MSPointerUp' + namespace }; } - - function __sp ( e ) { + + // Shorthand for stopping propagation on an object. + // Calling a function prevents having to define one inline. + function stopPropagation ( e ) { e.stopPropagation(); } + // Test an array of objects, and calls them if they are a function. function call ( f, scope, args ) { $.each(f,function(i,q){ if (typeof q === "function") { @@ -73,11 +87,13 @@ } }); } - + + // Test if there is anything that should prevent an event from being + // handled, such as a disabled state of a slider moving in the 'tap' event. function blocked ( e ) { return ( e.data.base.data('target').is('[class*="noUi-state-"], [disabled]') ); } - + function fixEvent ( e, preventDefault ) { // Required (in at the very least Chrome) to prevent @@ -86,28 +102,35 @@ if( preventDefault ) { e.preventDefault(); } - + + // Filter the event to register the type, + // which can be touch, mouse or pointer. Since noUiSlider 4 + // so longer binds touch OR mouse, but rather touch AND mouse, + // offset changes need to be made on an event specific basis. var jQueryEvent = e ,touch = e.type.indexOf('touch') === 0 ,mouse = e.type.indexOf('mouse') === 0 ,pointer = e.type.indexOf('MSPointer') === 0 ,x,y; - + + // Fetch the event where jQuery didn't make any modifications. e = e.originalEvent; - + if (touch) { + // noUiSlider supports one movement at a time, for now. + // It is therefore safe to select the first 'changedTouch'. x = e.changedTouches[0].pageX; y = e.changedTouches[0].pageY; } if (mouse) { - - // Polyfill the pageXOffset and pageYOffset + + // Polyfill the pageXOffset and pageYOffset // variables for IE7 and IE8; if(window.pageXOffset === UNDEF){ window.pageXOffset = document.documentElement.scrollLeft; window.pageYOffset = document.documentElement.scrollTop; } - + x = e.clientX + window.pageXOffset; y = e.clientY + window.pageYOffset; } @@ -115,7 +138,7 @@ x = e.pageX; y = e.pageY; } - + return { pass: jQueryEvent.data, e:e, x:x, y:y, t: [touch, mouse, pointer] }; } @@ -123,18 +146,20 @@ function getPercentage( a ){ return parseFloat(this.style[a]); } - + function test ( o, set ){ - // checks is number is numerical + // Checks whether a variable is numerical. function num(e){ return !isNaN(e) && isFinite(e); } + // Checks whether a variable is a candidate to be a + // valid serialization target. function ser(r){ return ( r instanceof $ || typeof r === 'string' || r === false ); } - + /** These tests are structured with an item for every option available. Every item contains an 'r' flag, which marks a required option, and @@ -147,27 +172,45 @@ method which appends the parent object to all children. **/ var TESTS = { + /* Handles. Has default, can be 1 or 2; + */ "handles": { - r: true // has default + r: true ,t: function(o,q){ q = parseInt(q, 10); return ( q === 1 || q === 2 ); } } + /* Range. + * Must be an array of two numerical floats, + * which can't be identical. + */ ,"range": { r: true ,t: function(o,q,w){ if(q.length!==2){ return false; } + // Reset the array to floats q = [parseFloat(q[0]),parseFloat(q[1])]; + // Test if those floats are numerical if(!num(q[0])||!num(q[1])){ return false; } + // When this test is run for range, the values can't + // be identical. + if(w==="range" && q[0] === q[1]){ + return false; + } o[w]=q; return true; } } + /* Start. + * Must be an array of two numerical floats when handles = 2; + * Uses 'range' test. + * When handles = 1, a single float is also allowed. + */ ,"start": { r: true ,t: function(o,q,w){ @@ -182,6 +225,10 @@ return this.parent.range.t(o,q,w); } } + /* Connect. + * Must be true or false when handles = 2; + * Can use 'lower' and 'upper' when handles = 1. + */ ,"connect": { t: function(o,q){ return ( q === true @@ -190,21 +237,32 @@ || ( q === 'upper' && o.handles === 1)); } } + /* Connect. + * Will default to horizontal, not required. + */ ,"orientation": { t: function(o,q){ return ( q === "horizontal" || q === "vertical" ); } } + /* Margin. + * Must be a float, has a default value. + */ ,"margin": { - r: true // has default + r: true ,t: function(o,q,w){ q = parseFloat(q); o[w]=q; return num(q); } } + /* Serialization. + * Required, but has default. Resolution option can be missing, + * 'to' can't. Must be an array when using two handles, can + * be a singular value when using one handle. + */ ,"serialization": { - r: true // has default + r: true ,t: function(o,q){ if(!q.resolution){ @@ -224,32 +282,48 @@ } if(q.to){ - + if(o.handles === 1){ + // Wrap the value for one handle into an array; if(!$.isArray(q.to)){ q.to = [q.to]; } + // Write back to the options object; o.serialization.to = q.to; + // Run test for valid serialization target. return ser(q.to[0]); } return (q.to.length === 2 && ser(q.to[0]) && ser(q.to[1])); } - + + // If no 'to' option is specified, + // the serialization option is invalid. return false; - + } } + /* Slide. + * Not required. Must be a function. + */ ,"slide": { t: function(o,q){ return typeof q === "function"; } } + /* Slide. + * Not required. Tested using the 'margin' function. + */ ,"step": { t: function(o,q,w){ return this.parent.margin.t(o,q,w); } } + /* [init] + * Not an option test. Calling this method will return the + * parent object with some cross references that allow crawling + * the object upward, which normally isn't possible in Javascript. + */ ,"init": function(){ var obj = this; $.each(obj,function(i,c){ @@ -259,11 +333,11 @@ return this; } }, - - // Prepare a set of tests, by adding some internal reference + + // Prepare a set of tests, by adding some internal reference // values not available in native Javascript object implementation. a = TESTS.init(); - + // Loop all provided tests; // v is the option set, i is the index for the current test. $.each(a, function( i, v ){ @@ -271,7 +345,7 @@ // If the value is required but not set, // or if the test fails, throw an error. if((v.r && (!o[i] && o[i] !== 0)) || ((o[i] || o[i] === 0) && !v.t(o,o[i],i))){ - + // For debugging purposes it might be very useful // to know what option caused the trouble. if(console&&console.log){ @@ -281,6 +355,8 @@ "\nValue:\t\t\t", o[i] ); } + // Since 'error' will prevent further script execution, + // log the error first. $.error("Error on noUiSlider initialisation."); return false; } @@ -288,46 +364,48 @@ }); } - + function closest( value, to ){ + // Round a value to the closest 'to'. + // Used with the 'step' option. return Math.round(value / to) * to; } - + function setHandle ( handle, to, forgive ) { var nui = handle.data('nui').options // Get the array of handles from the base. // Will be undefined at initialisation. ,handles = handle.data('nui').base.data(clsList[12]) - // Get some settings from the handle + // Get some settings from the handle; ,style = handle.data('nui').style ,dec = handle.data('nui').decimals ,hLimit; - + // Ignore the call if the handle won't move anyway. if(to === handle[0].getPercentage(style)) { return false; } - - // Limit `to` to 0 - 100 + + // Limit 'to' to 0 - 100 to = to < 0 ? 0 : to > 100 ? 100 : to; - + // Handle the step option, or ignore it. if( nui.step && !forgive ){ to = closest( to, percentage.from(nui.range, nui.step)); } - + // Stop handling this call if the handle won't step to a new value. if(to === handle[0].getPercentage(style)) { return false; } - + // We're done if this is the only handle, // if the handle bounce is trusted to the user // or on initialisation when handles isn't defined yet. if( handle.siblings('.' + clsList[1]).length && !forgive && handles ){ - - // Otherwise, the handle should bounce, + + // Otherwise, the handle should bounce, // and stop at the other handle. if ( handle.data('nui').number ) { hLimit = handles[0][0].getPercentage(style) + nui.margin; @@ -336,14 +414,14 @@ hLimit = handles[1][0].getPercentage(style) - nui.margin; to = to > hLimit ? hLimit : to; } - + // Stop handling this call if the handle can't move past another. if(to === handle[0].getPercentage(style)) { return false; } - + } - + // Fix for the z-index issue where the lower handle gets stuck // below the upper one. Since this function is called for every // movement, toggleClass cannot be used. @@ -352,23 +430,23 @@ } else { handle.removeClass(clsList[14]); } - + // Set handle to new location handle.css( style , to + '%'); - + // Write the value to the serialization object. handle.data('store').val(percentage.is(nui.range, to).toFixed(dec)); return true; - + } - + function store ( handle, S ) { - + var i = handle.data('nui').number; - + if( S.to[i] instanceof $ ) { - + // Attach a change event to the supplied jQuery object, // which will just trigger the val function on the parent. // In some cases, the change event will not fire on select elements, @@ -378,18 +456,18 @@ arr[i] = $(this).val(); handle.data('nui').target.val(arr, true); }); - + } - + if ( typeof S.to[i] === "string" ) { - + // Append a new object to the noUiSlider base, // prevent change events flowing upward. return $('') - .appendTo(handle).change(__sp); - + .appendTo(handle).change(stopPropagation); + } - + if ( S.to[i] === false ) { // Create an object capable of handling all jQuery calls. @@ -400,10 +478,10 @@ // Can't just test for !a, as a might be 0. if ( a === UNDEF ) { // Either set... - return this._handle.data('nui-val'); + return this.handleElement.data('nui-val'); } // ... or return; - this._handle.data('nui-val', a); + this.handleElement.data('nui-val', a); } // The object could be mistaken for a jQuery object, // make sure that doesn't trigger any errors. @@ -411,16 +489,16 @@ return false; } // The val function needs access to the handle. - ,_handle: handle + ,handleElement: handle }; } - + } function move( event ) { // This function is called often, keep it light. - + event = fixEvent( event, true ); if(!event) { @@ -433,21 +511,22 @@ // while taking vertical sliders into account. ,proposal = event.x - event.pass.startEvent.x ,baseSize = style === 'left' ? base.width() : base.height(); - + + // This loop prevents a long ternary for the proposal variable. if(style === 'top') { proposal = event.y - event.pass.startEvent.y; } - + proposal = event.pass.position + ( ( proposal * 100 ) / baseSize ); setHandle( event.pass.handle, proposal ); // Trigger the 'slide' event, pass the target so that it is 'this'. - call( + call( [ event.pass.base.data('options').slide ] ,event.pass.base.data('target') ); - + } function end ( event ) { @@ -455,18 +534,18 @@ if ( blocked( event ) ) { return; } - + // Handle is no longer active; event.data.handle.children().removeClass(clsList[4]); - + // Unbind move and end events, to prevent // them stacking up over and over; all.off(actions.move); all.off(actions.end); $('body').off(namespace); - + event.data.base.data('target').change(); - + } function start ( event ) { @@ -476,7 +555,7 @@ if ( blocked( event ) ) { return; } - + event = fixEvent( event ); if(!event) { @@ -487,7 +566,7 @@ ,position = handle[0].getPercentage( handle.data('nui').style ); handle.children().addClass('noUi-active'); - + // Attach the move event handler, while // passing all relevant information along. all.on(actions.move, { @@ -496,42 +575,44 @@ ,base: event.pass.base ,handle: handle }, move); - + all.on(actions.end, { base: event.pass.base, handle: handle }, end); + // Prevent text selection when dragging the handles. + // This doesn't prevent the browser defaulting to the I like cursor. $('body').on('selectstart' + namespace, function(){ return false; }); - + } - + function selfEnd( event ) { - // Trigger the end handler. Supply correct data using a + // Trigger the end handler. Supply correct data using a // fake object that contains all required information; end({ data: { base: event.data.base, handle: event.data.handle } }); // Stop propagation so that the tap handler doesn't interfere; event.stopPropagation(); } - + function tap ( event ) { if ( blocked( event ) || event.data.base.find('.' + clsList[4]).length ) { return; } - + event = fixEvent( event ); // The event handler might have rejected this event. if(!event) { return; } - + // Getting variables from the event is not required, but // shortens other expressions and is far more convenient; - var i, handle, base = event.pass.base + var i, handle, hCenter, base = event.pass.base ,handles = event.pass.handles ,style = base.data('style') ,eventXY = event[style === 'left' ? 'x' : 'y'] ,baseSize = style === 'left' ? base.width() : base.height() - + // Create a standard set off offsets compensated with the // scroll distance. When required, correct for scrolling. // This is a bug, as far as I can see, in IE(10?). @@ -545,7 +626,7 @@ ,top: base.offset().top } }; - + // Loop handles and add data to the offset list. for (i = 0; i < handles.length; i++ ) { offset.handles.push({ @@ -553,15 +634,15 @@ ,top: handles[i].offset().top }); } - + // Calculate the central point between the handles; - var handleCenter = handles.length === 1 ? 0 : + hCenter = handles.length === 1 ? 0 : (( offset.handles[0][style] + offset.handles[1][style] ) / 2 ); - + // If there is just one handle, // or the lower handles in closest to the event, // select the first handle. Otherwise, pick the second. - if ( handles.length === 1 || eventXY < handleCenter ){ + if ( handles.length === 1 || eventXY < hCenter ){ handle = handles[0]; } else { handle = handles[1]; @@ -573,35 +654,35 @@ setTimeout(function(){ base.removeClass(clsList[5]); }, 300); - + // Calculate the new position for the handle and // trigger the movement. setHandle( handle ,(((eventXY - offset.base[style]) * 100) / baseSize) ); - + // Trigger the 'slide' event, pass the target so that it is 'this'. - call( + call( [ handle.data('nui').options.slide ] ,base.data('target') ); - + base.data('target').change(); } - + function create ( ) { return this.each(function( index, target ){ // Target is the wrapper that will receive all external - // scripting interaction. It has no styling and serves no + // scripting interaction. It has no styling and serves no // other function. target = $(target); target.addClass(clsList[6]); - - // Base is the internal main 'bar'. + + // Base is the internal main 'bar'. var i, style, decimals, handle ,base = $('
').appendTo(target) ,handles = [] @@ -623,7 +704,7 @@ ,margin: 0 ,orientation: "horizontal" }, options) || {}; - + // Set a default for serialization; if(!options.serialization){ options.serialization = { @@ -631,14 +712,14 @@ ,resolution : 0.01 }; } - + // Run all options through a testing mechanism to ensure correct // input. The test function will throw errors, so there is // no need to capture the result of this call. It should be noted // that options might get modified to be handled properly. E.g. // wrapping integers in arrays. test(options, target); - + // I can't type serialization any more, and it doesn't compress // very well, so shorten it. options.S = options.serialization; @@ -650,7 +731,7 @@ if( options.connect === "lower" ){ // Add some styling classes to the base; cls.base.push(clsList[9], clsList[9] + clsList[7]); - // When using the option 'Lower', there is only one + // When using the option 'Lower', there is only one // handle, and thus only one origin. cls.origin[0].push(clsList[13]); } else { @@ -661,20 +742,22 @@ // Parse the syntactic sugar that is the serialization // resolution option to a usable integer. style = options.orientation === 'vertical' ? 'top' : 'left'; - + decimals = options.S.resolution.toString().split('.'); - // Test ==, not === - decimals = decimals[0] == 1 ? 0 : decimals[1].length; - + + // Checking for a string "1", since the resolution needs + // to be cast to a string to split in on the period. + decimals = decimals[0] === "1" ? 0 : decimals[1].length; + // Add classes for horizontal and vertical sliders. - // The horizontal class is provided for completeness, + // The horizontal class is provided for completeness, // as it isn't used in the default theme. if( options.orientation === "vertical" ){ cls.base.push(clsList[10]); } else { cls.base.push(clsList[11]); } - + // Merge base classes with default; base.addClass(cls.base.join(" ")).data('target', target); @@ -688,14 +771,14 @@ handle.children().addClass(cls.handle[i].join(" ")); // These events are only bound to the visual handle element, - // not the `real` origin element. + // not the 'real' origin element. handle.children() .on(actions.start, { base: base, handle: handle }, start) .on(actions.end, { base: base, handle: handle }, selfEnd); - // Make sure every handle has access to all primary + // Make sure every handle has access to all primary // variables. Can't uses jQuery's .data( obj ) structure - // here, as `store` needs some values from the `nui` object. + // here, as 'store' needs some values from the 'nui' object. handle.data('nui', { target: target ,decimals: decimals @@ -707,11 +790,11 @@ handle ,options.S )); - + // Attach a function to the native DOM element, // since jQuery wont let me get the current value in percentages. handle[0].getPercentage = getPercentage; - + // Make handles loop-able handles.push(handle); @@ -719,20 +802,21 @@ setHandle(handle, percentage.to(options.range, options.start[i])); } - + // The base could use the handles too; base.data({ options: options ,handles: handles ,style: style }); - + + // Add a downstream reference to the target as well. target.data({ base: base ,handles: handles }); - - // The tap event. + + // The tap event. base.on(actions.end, { base: base, handles: handles }, tap); }); @@ -749,7 +833,7 @@ if(!$.isArray(args)){ args = [args]; } - + // Setting is handled properly for each slider in the data set. return this.each(function(){ @@ -759,7 +843,7 @@ if( args[i] === null ) { return; } - + // Calculate a new position for the handle. var value, current ,range = handle.data('nui').options.range @@ -767,26 +851,32 @@ range ,parseFloat(args[i]) ), - - // Set handle to new location, and make sure developer + + // Set handle to new location, and make sure developer // input is always accepted. The ignore flag indicates // input from user facing elements. result = setHandle(handle, to, (ignore === true ? false : true)); - + // If the value of the input doesn't match the slider, // reset it. if(!result){ - + + // Get the 'store' object, which can be an input element + // or a wrapper arround a 'data' call. value = handle.data('store').val(); current = percentage.is(range, handle[0].getPercentage(handle.data('nui').style) ).toFixed(handle.data('nui').decimals); - + + // Sometimes the input is changed to a value the slider + // has rejected. This can occur when using 'select' or + // 'input[type="number"]' elements. In this case, + // set the value back to the input. if(value !== current){ handle.data('store').val(current); } } - + }); }); @@ -795,7 +885,7 @@ // Or, if the function was called without arguments, // act as a 'getter'; - + var re = []; // Loop the handles, and get the value from the input diff --git a/jquery.nouislider.min.css b/jquery.nouislider.min.css deleted file mode 100644 index f6fde5bc..00000000 --- a/jquery.nouislider.min.css +++ /dev/null @@ -1 +0,0 @@ -.noUi-target *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-touch-callout:none;-ms-touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;cursor:default}.noUi-base{height:40px;width:300px;position:relative;max-width:100%;border:1px solid #bfbfbf;z-index:1}.noUi-handle{background:#EEE;height:44px;width:44px;border:1px solid #BFBFBF;margin:-3px 0 0 -23px}.noUi-active{background:#E9E9E9}.noUi-active:after{content:"";display:block;height:100%;border:1px solid #DDD}.noUi-connect{background:Teal}.noUi-background{background:#DDD}.noUi-origin{position:absolute;right:0;top:0;bottom:0;z-index:0}.noUi-origin-upper{background:inherit!important}.noUi-z-index{z-index:10}.noUi-vertical{height:300px;width:40px;max-height:100%}.noUi-vertical .noUi-origin{bottom:0;left:0}.noUi-vertical .noUi-handle{margin:-23px 0 0 -3px}.noUi-target[disabled] .noUi-base{background:#999}.noUi-target[disabled] .noUi-connect{background:#BBB}.noUi-state-tap .noUi-origin{-webkit-transition:left .3s,top .3s;transition:left .3s,top .3s} \ No newline at end of file diff --git a/jquery.nouislider.min.js b/jquery.nouislider.min.js deleted file mode 100644 index a9ec7d2c..00000000 --- a/jquery.nouislider.min.js +++ /dev/null @@ -1,16 +0,0 @@ -/** noUiSlider 4.0.0 */ -(function(f,p){f.fn.noUiSlider=function(k){function z(a){a.stopPropagation()}function v(a,c,d){f.each(a,function(a,l){"function"===typeof l&&l.call(c,d)})}function q(a){return a.data.base.data("target").is('[class*="noUi-state-"], [disabled]')}function u(a,c){c&&a.preventDefault();var d=a,h=0===a.type.indexOf("touch"),l=0===a.type.indexOf("mouse"),b=0===a.type.indexOf("MSPointer"),s,e;a=a.originalEvent;h&&(s=a.changedTouches[0].pageX,e=a.changedTouches[0].pageY);l&&(window.pageXOffset===p&&(window.pageXOffset= -document.documentElement.scrollLeft,window.pageYOffset=document.documentElement.scrollTop),s=a.clientX+window.pageXOffset,e=a.clientY+window.pageYOffset);b&&(s=a.pageX,e=a.pageY);return{pass:d.data,e:a,x:s,y:e,t:[h,l,b]}}function A(a){return parseFloat(this.style[a])}function B(a,c){function d(a){return a instanceof f||"string"===typeof a||!1===a}var h={handles:{r:!0,t:function(a,b){b=parseInt(b,10);return 1===b||2===b}},range:{r:!0,t:function(a,b,c){if(2!==b.length)return!1;b=[parseFloat(b[0]),parseFloat(b[1])]; -if(isNaN(b[0])||!isFinite(b[0])||isNaN(b[1])||!isFinite(b[1]))return!1;a[c]=b;return!0}},start:{r:!0,t:function(a,b,c){return 1===a.handles?(f.isArray(b)&&(b=b[0]),b=parseFloat(b),a.start=[b],!isNaN(b)&&isFinite(b)):this.parent.range.t(a,b,c)}},connect:{t:function(a,b){return!0===b||!1===b||"lower"===b&&1===a.handles||"upper"===b&&1===a.handles}},orientation:{t:function(a,b){return"horizontal"===b||"vertical"===b}},margin:{r:!0,t:function(a,b,c){b=parseFloat(b);a[c]=b;return!isNaN(b)&&isFinite(b)}}, -serialization:{r:!0,t:function(a,b){if(b.resolution)switch(b.resolution){case 1:case 0.1:case 0.01:case 0.001:case 1E-4:case 1E-5:break;default:return!1}else a.serialization.resolution=0.01;return b.to?1===a.handles?(f.isArray(b.to)||(b.to=[b.to]),a.serialization.to=b.to,d(b.to[0])):2===b.to.length&&d(b.to[0])&&d(b.to[1]):!1}},slide:{t:function(a,b){return"function"===typeof b}},step:{t:function(a,b,c){return this.parent.margin.t(a,b,c)}},init:function(){var a=this;f.each(a,function(b,c){c.parent= -a});delete this.init;return this}}.init();f.each(h,function(d,b){if(b.r&&!a[d]&&0!==a[d]||(a[d]||0===a[d])&&!b.t(a,a[d],d))return console&&console.log&&console.log("Slider:\t\t\t",c,"\nOption:\t\t\t",d,"\nValue:\t\t\t",a[d]),f.error("Error on noUiSlider initialisation."),!1})}function t(a,c,d){var h=a.data("nui").options,l=a.data("nui").base.data(e[12]),b=a.data("nui").style,f=a.data("nui").decimals;if(c===a[0].getPercentage(b))return!1;c=0>c?0:100d?d:c),c===a[0].getPercentage(b)))return!1;0===a.data("nui").number&&95').appendTo(a).change(z);if(!1===c.to[d])return{val:function(a){if(a===p)return this._handle.data("nui-val");this._handle.data("nui-val",a)},hasClass:function(){return!1},_handle:a}}function D(a){if(a=u(a,!0)){var c=a.pass.base,d=c.data("style"),e=a.x-a.pass.startEvent.x,c="left"===d?c.width():c.height();"top"===d&&(e=a.y-a.pass.startEvent.y); -e=a.pass.position+100*e/c;t(a.pass.handle,e);v([a.pass.base.data("options").slide],a.pass.base.data("target"))}}function w(a){q(a)||(a.data.handle.children().removeClass(e[4]),m.off(n.move),m.off(n.end),f("body").off(g),a.data.base.data("target").change())}function E(a){if(!q(a)&&(a=u(a))){var c=a.pass.handle,d=c[0].getPercentage(c.data("nui").style);c.children().addClass("noUi-active");m.on(n.move,{startEvent:a,position:d,base:a.pass.base,handle:c},D);m.on(n.end,{base:a.pass.base,handle:c},w);f("body").on("selectstart"+ -g,function(){return!1})}}function F(a){w({data:{base:a.data.base,handle:a.data.handle}});a.stopPropagation()}function G(a){if(!q(a)&&!a.data.base.find("."+e[4]).length&&(a=u(a))){var c,d,h=a.pass.base;d=a.pass.handles;var l=h.data("style"),b=a["left"===l?"x":"y"],f="left"===l?h.width():h.height(),k=a.t[2]?window.pageXOffset:0,g=[];a={left:h.offset().left-k,top:h.offset().top};for(c=0;ca[0]?c+Math.abs(a[0]):c-a[0];return 100*c/this._length(a)},from:function(a,c){return 100*c/this._length(a)},is:function(a,c){return c*this._length(a)/100+a[0]},_length:function(a){return a[0]>a[1]?a[0]-a[1]:a[1]-a[0]}};window.navigator.msPointerEnabled&&(n={start:"MSPointerDown"+g,move:"MSPointerMove"+g,end:"MSPointerUp"+g});f.fn.val=function(){return this.hasClass(e[6])?H.apply(this,arguments):I.apply(this,arguments)};return function(){return this.each(function(a, -c){c=f(c);c.addClass(e[6]);var d,h,l,b,g=f("
").appendTo(c),m=[];d=J;var p=[x.concat([e[1]+e[7]]),x.concat([e[1]+e[8]])],q=[y.concat([e[2]+e[7]]),y.concat([e[2]+e[8]])];k=f.extend({handles:2,margin:0,orientation:"horizontal"},k)||{};k.serialization||(k.serialization={to:[!1,!1],resolution:0.01});B(k,c);k.S=k.serialization;k.connect&&(p[0].push(e[9]),"lower"===k.connect?(d.push(e[9],e[9]+e[7]),p[0].push(e[13])):d.push(e[9]+e[8]));h="vertical"===k.orientation?"top":"left";l=k.S.resolution.toString().split("."); -l=1==l[0]?0:l[1].length;"vertical"===k.orientation?d.push(e[10]):d.push(e[11]);g.addClass(d.join(" ")).data("target",c);for(d=0;d
").appendTo(g),b.addClass(p[d].join(" ")),b.children().addClass(q[d].join(" ")),b.children().on(n.start,{base:g,handle:b},E).on(n.end,{base:g,handle:b},F),b.data("nui",{target:c,decimals:l,options:k,base:g,style:h,number:d}).data("store",C(b,k.S)),b[0].getPercentage=A,m.push(b),t(b,r.to(k.range,k.start[d]));g.data({options:k,handles:m, -style:h});c.data({base:g,handles:m});g.on(n.end,{base:g,handles:m},G)})}.apply(this,arguments)}})(jQuery); diff --git a/nouislider.jquery.json b/nouislider.jquery.json index 159d84f1..17e65b11 100644 --- a/nouislider.jquery.json +++ b/nouislider.jquery.json @@ -16,7 +16,7 @@ "url": "http://refreshless.com/nouislider/license.txt" } ], - "version": "4.0.0", + "version": "4.0.2", "author": { "name": "Léon Gersen", "url": "https://twitter.com/LeonGersen"