Skip to content

Commit 5ffd3ab

Browse files
committed
Align slider value to step. Fixes #5471 - value not aligned to step when set programatically
1 parent ab1f806 commit 5ffd3ab

File tree

2 files changed

+59
-23
lines changed

2 files changed

+59
-23
lines changed

tests/unit/slider/slider_options.js

+37-4
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,50 @@ test("range", function() {
8888
ok(false, "missing test - untested code is broken code.");
8989
});
9090

91+
//spec: http://wiki.jqueryui.com/Slider#specs
92+
// value option/method: the value option is not restricted by min/max/step.
93+
// What is returned by the value method is restricted by min (>=), max (<=), and step (even multiple)
9194
test("step", function() {
9295
var el = $('<div></div>').slider({
93-
step: 10
96+
min: 0,
97+
value: 0,
98+
step: 10,
99+
max: 100,
94100
});
95-
equals( el.slider("value"), 0 )
101+
equals( el.slider("value"), 0 );
102+
96103
el.slider("value", 1);
104+
equals( el.slider("value"), 0 );
105+
106+
el.slider("value", 9);
97107
equals( el.slider("value"), 10 );
98-
el.slider("value", 10);
99-
equals( el.slider("value"), 10 );
108+
100109
el.slider("value", 11);
110+
equals( el.slider("value"), 10 );
111+
112+
el.slider("value", 19);
101113
equals( el.slider("value"), 20 );
114+
115+
el = $('<div></div>').slider({
116+
min: 0,
117+
value: 0,
118+
step: 20,
119+
max: 100,
120+
});
121+
el.slider("value", 0);
122+
123+
el.slider("option", "value", 1);
124+
equals( el.slider("value"), 0 );
125+
126+
el.slider("option", "value", 9);
127+
equals( el.slider("value"), 0 );
128+
129+
el.slider("option", "value", 11);
130+
equals( el.slider("value"), 20 );
131+
132+
el.slider("option", "value", 19);
133+
equals( el.slider("value"), 20 );
134+
102135
el.slider('destroy');
103136
});
104137

ui/jquery.ui.slider.js

+22-19
Original file line numberDiff line numberDiff line change
@@ -340,17 +340,9 @@ $.widget("ui.slider", $.ui.mouse, {
340340
percentMouse = 1 - percentMouse;
341341

342342
var valueTotal = this._valueMax() - this._valueMin(),
343-
valueMouse = percentMouse * valueTotal,
344-
valueMouseModStep = valueMouse % this.options.step,
345-
normValue = this._valueMin() + valueMouse - valueMouseModStep;
346-
347-
if (valueMouseModStep > (this.options.step / 2))
348-
normValue += this.options.step;
349-
350-
// Since JavaScript has problems with large floats, round
351-
// the final value to 5 digits after the decimal point (see #4124)
352-
return parseFloat(normValue.toFixed(5));
343+
valueMouse = percentMouse * valueTotal;
353344

345+
return this._trimAlignValue(valueMouse);
354346
},
355347

356348
_start: function(event, index) {
@@ -440,7 +432,7 @@ $.widget("ui.slider", $.ui.mouse, {
440432
value: function(newValue) {
441433

442434
if (arguments.length) {
443-
this.options.value = this._trimValue(newValue);
435+
this.options.value = this._trimAlignValue(newValue);
444436
this._refreshValue();
445437
this._change(null, 0);
446438
}
@@ -452,7 +444,7 @@ $.widget("ui.slider", $.ui.mouse, {
452444
values: function(index, newValue) {
453445

454446
if (arguments.length > 1) {
455-
this.options.values[index] = this._trimValue(newValue);
447+
this.options.values[index] = this._trimAlignValue(newValue);
456448
this._refreshValue();
457449
this._change(null, index);
458450
}
@@ -461,7 +453,7 @@ $.widget("ui.slider", $.ui.mouse, {
461453
if ($.isArray(arguments[0])) {
462454
var vals = this.options.values, newValues = arguments[0];
463455
for (var i = 0, l = vals.length; i < l; i++) {
464-
vals[i] = this._trimValue(newValues[i]);
456+
vals[i] = this._trimAlignValue(newValues[i]);
465457
this._change(null, i);
466458
}
467459
this._refreshValue();
@@ -528,9 +520,9 @@ $.widget("ui.slider", $.ui.mouse, {
528520

529521
_value: function() {
530522
//internal value getter
531-
// _value() returns value trimmed by min and max
523+
// _value() returns value trimmed by min and max, aligned by step
532524
var val = this.options.value;
533-
val = this._trimValue(val);
525+
val = this._trimAlignValue(val);
534526

535527
return val;
536528
},
@@ -542,30 +534,41 @@ $.widget("ui.slider", $.ui.mouse, {
542534

543535
if (arguments.length) {
544536
var val = this.options.values[index];
545-
val = this._trimValue(val);
537+
val = this._trimAlignValue(val);
546538

547539
return val;
548540
} else {
549541
// .slice() creates a copy of the array
550542
// this copy gets trimmed by min and max and then returned
551543
var vals = this.options.values.slice();
552544
for (var i = 0, l = vals.length; i < l; i++) {
553-
vals[i] = this._trimValue(vals[i]);
545+
vals[i] = this._trimAlignValue(vals[i]);
554546
}
555547

556548
return vals;
557549
}
558550

559551
},
560552

561-
_trimValue: function(val) {
553+
// returns the step-aligned value that val is closest to, between (inclusive) min and max
554+
_trimAlignValue: function(val) {
562555
if (val < this._valueMin()) {
563556
return this._valueMin();
564557
}
565558
if (val > this._valueMax()) {
566559
return this._valueMax();
567560
}
568-
return val;
561+
var step = this.options.step,
562+
valModStep = val % step,
563+
alignValue = this._valueMin() + val - valModStep;
564+
565+
if (valModStep >= (step / 2)) {
566+
alignValue += step;
567+
}
568+
569+
// Since JavaScript has problems with large floats, round
570+
// the final value to 5 digits after the decimal point (see #4124)
571+
return parseFloat(alignValue.toFixed(5));
569572
},
570573

571574
_valueMin: function() {

0 commit comments

Comments
 (0)