diff --git a/tests/unit/slider/slider_options.js b/tests/unit/slider/slider_options.js index cc36923b3..b9a766539 100644 --- a/tests/unit/slider/slider_options.js +++ b/tests/unit/slider/slider_options.js @@ -88,17 +88,50 @@ test("range", function() { ok(false, "missing test - untested code is broken code."); }); +//spec: http://wiki.jqueryui.com/Slider#specs +// value option/method: the value option is not restricted by min/max/step. +// What is returned by the value method is restricted by min (>=), max (<=), and step (even multiple) test("step", function() { var el = $('
').slider({ - step: 10 + min: 0, + value: 0, + step: 10, + max: 100, }); - equals( el.slider("value"), 0 ) + equals( el.slider("value"), 0 ); + el.slider("value", 1); + equals( el.slider("value"), 0 ); + + el.slider("value", 9); equals( el.slider("value"), 10 ); - el.slider("value", 10); - equals( el.slider("value"), 10 ); + el.slider("value", 11); + equals( el.slider("value"), 10 ); + + el.slider("value", 19); equals( el.slider("value"), 20 ); + +el = $('
').slider({ + min: 0, + value: 0, + step: 20, + max: 100, + }); + el.slider("value", 0); + + el.slider("option", "value", 1); + equals( el.slider("value"), 0 ); + + el.slider("option", "value", 9); + equals( el.slider("value"), 0 ); + + el.slider("option", "value", 11); + equals( el.slider("value"), 20 ); + + el.slider("option", "value", 19); + equals( el.slider("value"), 20 ); + el.slider('destroy'); }); diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js index 185fe809c..dd79cb730 100644 --- a/ui/jquery.ui.slider.js +++ b/ui/jquery.ui.slider.js @@ -340,17 +340,9 @@ $.widget("ui.slider", $.ui.mouse, { percentMouse = 1 - percentMouse; var valueTotal = this._valueMax() - this._valueMin(), - valueMouse = percentMouse * valueTotal, - valueMouseModStep = valueMouse % this.options.step, - normValue = this._valueMin() + valueMouse - valueMouseModStep; - - if (valueMouseModStep > (this.options.step / 2)) - normValue += this.options.step; - - // Since JavaScript has problems with large floats, round - // the final value to 5 digits after the decimal point (see #4124) - return parseFloat(normValue.toFixed(5)); + valueMouse = percentMouse * valueTotal; + return this._trimAlignValue(valueMouse); }, _start: function(event, index) { @@ -440,7 +432,7 @@ $.widget("ui.slider", $.ui.mouse, { value: function(newValue) { if (arguments.length) { - this.options.value = this._trimValue(newValue); + this.options.value = this._trimAlignValue(newValue); this._refreshValue(); this._change(null, 0); } @@ -452,7 +444,7 @@ $.widget("ui.slider", $.ui.mouse, { values: function(index, newValue) { if (arguments.length > 1) { - this.options.values[index] = this._trimValue(newValue); + this.options.values[index] = this._trimAlignValue(newValue); this._refreshValue(); this._change(null, index); } @@ -461,7 +453,7 @@ $.widget("ui.slider", $.ui.mouse, { if ($.isArray(arguments[0])) { var vals = this.options.values, newValues = arguments[0]; for (var i = 0, l = vals.length; i < l; i++) { - vals[i] = this._trimValue(newValues[i]); + vals[i] = this._trimAlignValue(newValues[i]); this._change(null, i); } this._refreshValue(); @@ -528,9 +520,9 @@ $.widget("ui.slider", $.ui.mouse, { _value: function() { //internal value getter - // _value() returns value trimmed by min and max + // _value() returns value trimmed by min and max, aligned by step var val = this.options.value; - val = this._trimValue(val); + val = this._trimAlignValue(val); return val; }, @@ -542,7 +534,7 @@ $.widget("ui.slider", $.ui.mouse, { if (arguments.length) { var val = this.options.values[index]; - val = this._trimValue(val); + val = this._trimAlignValue(val); return val; } else { @@ -550,7 +542,7 @@ $.widget("ui.slider", $.ui.mouse, { // this copy gets trimmed by min and max and then returned var vals = this.options.values.slice(); for (var i = 0, l = vals.length; i < l; i++) { - vals[i] = this._trimValue(vals[i]); + vals[i] = this._trimAlignValue(vals[i]); } return vals; @@ -558,14 +550,25 @@ $.widget("ui.slider", $.ui.mouse, { }, - _trimValue: function(val) { + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue: function(val) { if (val < this._valueMin()) { return this._valueMin(); } if (val > this._valueMax()) { return this._valueMax(); } - return val; + var step = this.options.step, + valModStep = val % step, + alignValue = this._valueMin() + val - valModStep; + + if (valModStep >= (step / 2)) { + alignValue += step; + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat(alignValue.toFixed(5)); }, _valueMin: function() {