diff --git a/README.md b/README.md
index 80b5ea48..884757fe 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# 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://refreshless.com/nouislider/terms-of-use).
+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/).
Documentation
-------
@@ -10,13 +10,13 @@ An extensive documentation, including **examples**, **options** and **configurat
Changes
-------
-**Changelog for version 6.1.0:**
-**Compatible with 6.0.0**
+**Changelog for version 6.2.0:**
+*(Compatible with 6.0.0)*
-+ Split out value methods into [$.classVal](https://github.com/leongersen/classVal). This is **included** in the release download.
-+ `$.noUiSlider.Link` is now an alias to `$.Link`. The Link functionality has been moved into a new file. (also in the download).
-+ Several bug fixes.
-+ Added `to` and `from` to [number formatting](http://refreshless.com/nouislider/number-formatting)
++ Removed the previously added `.classVal` and replaced it with a lightweight solution.
++ Fixed a bug in non-linear stepping for RTL sliders. (#262)
++ Added checks for `min` and `max` in `range`. (#255)
++ Added the minified version in the source, so it can be managed with Bower. (#252)
**Changelog for version 6.0.0:**
@@ -30,24 +30,42 @@ Changes
Unit Testing
------------
-
-Unit tests where added with noUiSlider 6. The event testing coverage isn't 100% yet, but coverage of the `Link` is extensive. More tests will be added eventually.
+Unit tests where added with noUiSlider 6. Coverage of `$.Link` and value handling is near complete, but due to the sensitivity of events across browsers, event testing is a little lacking.
Version numbering
------------------------------
-Version numbering follows the 'Semantic versioning' style.
+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 to remove whitespace and comments to provide a `min` version.
+The plugin code is checked using ([JsLint](http://jslint.com/)). Any remaining errors and warnings are intentional.
+
+The plugin is compressed using the ([Google Closure Compiler](http://closure-compiler.appspot.com/home)). The source was adapted to facilitate the `ADVANCED_OPTIMIZATIONS` level. `$.Link` is merged into the file. On Windows, the folling BAT script can be used to run the compiler. On OS X or Linux enviroments, simply run the `java -jar` command from the command line.
+
+```bat
+@echo off
+
+:: Set all paths as variables
+set "jquery=.\externs\jquery-1.8.js"
+set "link=..\source\Link.js"
+set "source=..\source\jquery.nouislider.js"
+set "result=..\source\jquery.nouislider.min.js"
+
+:: Remove the existing file so we can be sure a new one is generated.
+if exist %result% (
+ del %result%
+)
+
+echo "Removed %result%, ready."
+
+PAUSE
-**JS** ([Google Closure Compiler](http://closure-compiler.appspot.com/home))
-The plugin is compressed using the Google Closure compiler. The source was adapted to facilitate the `ADVANCED_OPTIMIZATIONS` level.
+java -jar .\compiler\compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --externs %jquery% --warning_level VERBOSE --js %link% --js %source% --js_output_file %result%
-**Code** ([JsLint](http://jslint.com/))
-The plugin code is checked using JsLint. Any remaining errors and warnings are intentional.
+echo "Done."
+PAUSE
+```
Known issues
------------
diff --git a/bower.json b/bower.json
index cc230fa3..63aeb2f0 100644
--- a/bower.json
+++ b/bower.json
@@ -12,13 +12,11 @@
"slide"
],
"main": [
- "Link.js",
- "jquery.nouislider.js",
+ "jquery.nouislider.min.js",
"jquery.nouislider.css"
],
"dependencies": {
- "jquery": ">= 1.7.0",
- "classval": ">= 0.1.0"
+ "jquery": ">= 1.7.0"
},
"ignore": [
"**/.*",
diff --git a/jquery.nouislider.js b/jquery.nouislider.js
index 6dfd19c9..1b55831d 100644
--- a/jquery.nouislider.js
+++ b/jquery.nouislider.js
@@ -15,6 +15,9 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
// 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',
@@ -164,7 +167,10 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
function getStep ( options, value ){
var j = 1, a, b;
- while ( value >= options.xPct[j] ){
+
+ // Find the proper step for rtl sliders by search in inverse direction.
+ // Fixes issue #262.
+ while ( (options.dir ? (100 - value) : value) >= options.xPct[j] ){
j++;
}
@@ -266,6 +272,12 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
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'.");
+ }
+
// Loop all entries.
$.each( entry, function ( index, value ) {
@@ -506,15 +518,16 @@ $.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
,margin: 0
}, tests;
+ // Tests are executed in the order they are presented here.
tests = {
'step': { r: false, t: testStep },
- 'range': { r: true, t: testRange },
'start': { r: true, t: testStart },
- 'snap': { r: false, t: testSnap },
'connect': { r: true, t: testConnect },
+ 'direction': { r: true, t: testDirection },
+ 'range': { r: true, t: testRange },
+ 'snap': { r: false, t: testSnap },
'orientation': { r: false, t: testOrientation },
'margin': { r: false, t: testMargin },
- 'direction': { r: true, t: testDirection },
'behaviour': { r: true, t: testBehaviour },
'serialization': { r: true, t: testSerialization }
};
@@ -1235,6 +1248,35 @@ function closure ( target, options, originalOptions ){
});
}
+ // 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 extects 'this' to be an instance of $. For convenience,
+ // the above 'value' function does too.
+ $.fn.val = function ( ) {
+
+ // this === instanceof $
+
+ function valMethod( a ){
+ return a.hasClass(Classes[0]) ? value : $val;
+ }
+
+ var args = arguments,
+ first = $(this[0]);
+
+ if ( !arguments.length ) {
+ return valMethod(first).call(first);
+ }
+
+ // Return the set so it remains chainable
+ return this.each(function(){
+ valMethod($(this)).apply($(this), args);
+ });
+ };
// Remap the serialization constructor for legacy support.
/** @expose */
@@ -1246,7 +1288,4 @@ function closure ( target, options, originalOptions ){
return ( re ? rebuild : initialize ).call(this, options);
};
-// Attach a classbased val handler.
- $.classVal(Classes[0], 'vGet', 'vSet', false);
-
}( window['jQuery'] || window['Zepto'] ));
diff --git a/jquery.nouislider.min.js b/jquery.nouislider.min.js
new file mode 100644
index 00000000..b9a63edd
--- /dev/null
+++ b/jquery.nouislider.min.js
@@ -0,0 +1,31 @@
+/*
+
+$.Link (part of noUiSlider) - WTFPL */
+(function(c){function m(a,c,d){if((a[c]||a[d])&&a[c]===a[d])throw Error("(Link) '"+c+"' can't match '"+d+"'.'");}function r(a){void 0===a&&(a={});if("object"!==typeof a)throw Error("(Format) 'format' option must be an object.");var h={};c(u).each(function(c,n){if(void 0===a[n])h[n]=A[c];else if(typeof a[n]===typeof A[c]){if("decimals"===n&&(0>a[n]||7a&&(n=this.a("negative"),k=this.a("negativeBefore"));a=Math.abs(a).toFixed(d).toString();a=a.split(".");this.a("thousand")?(m=c(a[0]).match(/.{1,3}/g),m=c(m.join(c(this.a("thousand"))))):m=a[0];this.a("mark")&&1")[0]};k.prototype.H=function(a){this.method="val";this.j=document.createElement("input");this.j.name=a;this.j.type="hidden"};k.prototype.G=function(a){function h(a,c){return[c?null:a,c?a:null]}var d=this;this.method="val";this.target=a.on("change",function(a){d.B.val(h(c(a.target).val(),d.t),{link:d,set:!0})})};k.prototype.p=function(a,h,d,k){this.g=d;this.update=!k;if("string"===
+typeof a&&0===a.indexOf("-tooltip-"))this.K(a,h);else if("string"===typeof a&&0!==a.indexOf("-"))this.H(a);else if("function"===typeof a)this.target=!1,this.method=a;else{if(a instanceof c||c.zepto&&c.zepto.isZ(a)){if(!h){if(a.is("input, select, textarea")){this.G(a);return}h="html"}if("function"===typeof h||"string"===typeof h&&a[h]){this.method=h;this.target=a;return}}throw new RangeError("(Link) Invalid Link.");}};k.prototype.write=function(a,c,d,k){if(!this.update||!1!==k)if(this.u=a,this.F=a=
+this.format(a),"function"===typeof this.method)this.method.call(this.target[0]||d[0],a,c,d);else this.target[this.method](a,c,d)};k.prototype.q=function(a){this.g=new r(c.extend({},a,this.g instanceof r?this.g.r:this.g))};k.prototype.J=function(a){this.B=a};k.prototype.I=function(a){this.t=a};k.prototype.format=function(a){return this.g.L(a)};k.prototype.A=function(a){return this.g.w(a)};k.prototype.p.prototype=k.prototype;c.Link=k})(window.jQuery||window.Zepto);/*
+
+$.fn.noUiSlider - WTFPL - refreshless.com/nouislider/ */
+(function(c){function m(e){return"number"===typeof e&&!isNaN(e)&&isFinite(e)}function r(e){return c.isArray(e)?e:[e]}function k(e,b){e.addClass(b);setTimeout(function(){e.removeClass(b)},300)}function u(e,b){return 100*b/(e[1]-e[0])}function A(e,b){if(b>=e.d.slice(-1)[0])return 100;for(var a=1,c,f,d;b>=e.d[a];)a++;c=e.d[a-1];f=e.d[a];d=e.c[a-1];c=[c,f];return d+u(c,0>c[0]?b+Math.abs(c[0]):b-c[0])/(100/(e.c[a]-d))}function a(e,b){if(100<=b)return e.d.slice(-1)[0];for(var a=1,c,f,d;b>=e.c[a];)a++;c=
+e.d[a-1];f=e.d[a];d=e.c[a-1];c=[c,f];return 100/(e.c[a]-d)*(b-d)*(c[1]-c[0])/100+c[0]}function h(a,b){for(var c=1,g;(a.dir?100-b:b)>=a.c[c];)c++;if(a.m)return g=a.c[c-1],c=a.c[c],b-g>(c-g)/2?c:g;a.h[c-1]?(g=a.h[c-1],c=a.c[c-1]+Math.round((b-a.c[c-1])/g)*g):c=b;return c}function d(a,b){if(!m(b))throw Error("noUiSlider: 'step' is not numeric.");a.h[0]=b}function n(a,b){if("object"!==typeof b||c.isArray(b))throw Error("noUiSlider: 'range' is not an object.");if(void 0===b.min||void 0===b.max)throw Error("noUiSlider: Missing 'min' or 'max' in 'range'.");
+c.each(b,function(b,g){var d;"number"===typeof g&&(g=[g]);if(!c.isArray(g))throw Error("noUiSlider: 'range' contains invalid value.");d="min"===b?0:"max"===b?100:parseFloat(b);if(!m(d)||!m(g[0]))throw Error("noUiSlider: 'range' value isn't numeric.");a.c.push(d);a.d.push(g[0]);d?a.h.push(isNaN(g[1])?!1:g[1]):isNaN(g[1])||(a.h[0]=g[1])});c.each(a.h,function(b,c){if(!c)return!0;a.h[b]=u([a.d[b],a.d[b+1]],c)/(100/(a.c[b+1]-a.c[b]))})}function E(a,b){"number"===typeof b&&(b=[b]);if(!c.isArray(b)||!b.length||
+2").addClass(f[2]),g=["-lower","-upper"];a.dir&&g.reverse();d.children().addClass(f[3]+" "+f[3]+g[b]);return d}function Q(a,b){b.j&&(b=new c.Link({target:c(b.j).clone().appendTo(a),method:b.method,format:b.g},!0));return b}function R(a,b){var d,f=[];for(d=0;d").appendTo(b).addClass(f[1])}function V(d,b,m){function g(){return t[["width","height"][b.k]]()}function n(a){var b,c=[q.val()];for(b=0;bp&&(p=h(b,p));p=Math.max(Math.min(parseFloat(p.toFixed(7)),100),0);if(p===x[g])return 1===l.length?!1:p===H||p===k?0:!1;d.css(b.style,p+"%");d.is(":first-child")&&d.toggleClass(f[17],50