Skip to content

Commit dd0a436

Browse files
committed
Spinner: Trigger change event when the value is changed programmatically.
1 parent bea9933 commit dd0a436

File tree

1 file changed

+61
-26
lines changed

1 file changed

+61
-26
lines changed

ui/jquery.ui.spinner.js

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@
1313
*/
1414
(function( $ ) {
1515

16+
function modifier( fn ) {
17+
return function() {
18+
var previous = this.options.value;
19+
fn.apply( this, arguments );
20+
this._format();
21+
this._aria();
22+
if ( previous !== this.options.value ) {
23+
this._trigger( "change" );
24+
}
25+
};
26+
}
27+
1628
$.widget( "ui.spinner", {
1729
version: "@VERSION",
1830
defaultElement: "<input>",
@@ -33,7 +45,7 @@ $.widget( "ui.spinner", {
3345
},
3446

3547
_create: function() {
36-
this.value( this.options.value );
48+
this._value( this.options.value );
3749
this._draw();
3850
this._mousewheel();
3951
this._aria();
@@ -73,18 +85,19 @@ $.widget( "ui.spinner", {
7385
keyup: "_stop",
7486
focus: function() {
7587
uiSpinner.addClass( "ui-state-active" );
76-
this.previous = this.options.value;
88+
this.previous = this.element.val();
7789
},
7890
blur: function( event ) {
7991
// don't clear invalid values on blur
80-
var value = this.element.val(),
81-
parsed = this._parse( value );
82-
this.option( "value", parsed );
83-
if ( parsed === null ) {
92+
var value = this.element.val();
93+
this._value( value );
94+
if ( this.element.val() === "" ) {
8495
this.element.val( value );
8596
}
8697
uiSpinner.removeClass( "ui-state-active" );
87-
if ( this.previous !== this.options.value ) {
98+
// TODO: what should trigger change?
99+
// element.val() or options.value?
100+
if ( this.previous !== this.element.val() ) {
88101
this._trigger( "change", event );
89102
}
90103
}
@@ -151,7 +164,7 @@ $.widget( "ui.spinner", {
151164
this._repeat( null, -options.page, event );
152165
return true;
153166
case keyCode.ENTER:
154-
this.value( this.element.val() );
167+
this._value( this.element.val() );
155168
}
156169

157170
return false;
@@ -241,7 +254,7 @@ $.widget( "ui.spinner", {
241254
newVal = this._trimValue( newVal );
242255

243256
if ( this._trigger( "spin", event, { value: newVal } ) !== false) {
244-
this.value( newVal );
257+
this._value( newVal );
245258
this.counter++;
246259
}
247260
},
@@ -273,10 +286,12 @@ $.widget( "ui.spinner", {
273286
},
274287

275288
_setOption: function( key, value ) {
276-
if ( key === "value") {
277-
value = this._trimValue( this._parse(value) );
289+
if ( key === "value" ) {
290+
return this._setOptionValue( value );
278291
}
279292

293+
this._super( "_setOption", key, value );
294+
280295
if ( key === "disabled" ) {
281296
if ( value ) {
282297
this.element.prop( "disabled", true );
@@ -286,17 +301,24 @@ $.widget( "ui.spinner", {
286301
this.buttons.button( "enable" );
287302
}
288303
}
304+
},
289305

290-
this._super( "_setOption", key, value );
306+
_setOptionValue: function( value ) {
307+
var previous = this.options.value;
308+
this._value( value );
309+
if ( previous !== this.options.value ) {
310+
this._trigger( "change" );
311+
}
291312
},
292313

293-
_setOptions: function( options ) {
314+
_setOptions: modifier(function( options ) {
294315
this._super( "_setOptions", options );
295-
if ( "value" in options || "numberFormat" in options ) {
296-
this._format( this.options.value );
297-
}
316+
317+
// handle any options that might cause value to change, e.g., min
318+
this._value( this._trimValue( this.options.value ) );
319+
this._format();
298320
this._aria();
299-
},
321+
}),
300322

301323
_aria: function() {
302324
this.element.attr({
@@ -313,10 +335,17 @@ $.widget( "ui.spinner", {
313335
return isNaN( val ) ? null : val;
314336
},
315337

316-
_format: function( num ) {
338+
_format: function() {
339+
var num = this.options.value;
317340
this.element.val( $.global && this.options.numberFormat ? $.global.format( num, this.options.numberFormat ) : num );
318341
},
319342

343+
// update the value without triggering change
344+
_value: function( value ) {
345+
this.options.value = this._trimValue( this._parse(value) );
346+
this._format();
347+
},
348+
320349
destroy: function() {
321350
this.element
322351
.removeClass( "ui-spinner-input" )
@@ -330,21 +359,27 @@ $.widget( "ui.spinner", {
330359
this.uiSpinner.replaceWith( this.element );
331360
},
332361

333-
stepUp: function( steps ) {
362+
stepUp: modifier(function( steps ) {
363+
this._stepUp( steps );
364+
}),
365+
_stepUp: function( steps ) {
334366
this._spin( (steps || 1) * this.options.step );
335367
},
336368

337-
stepDown: function( steps ) {
369+
stepDown: modifier(function( steps ) {
370+
this._stepDown( steps );
371+
}),
372+
_stepDown: function( steps ) {
338373
this._spin( (steps || 1) * -this.options.step );
339374
},
340375

341-
pageUp: function( pages ) {
342-
this.stepUp( (pages || 1) * this.options.page );
343-
},
376+
pageUp: modifier(function( pages ) {
377+
this._stepUp( (pages || 1) * this.options.page );
378+
}),
344379

345-
pageDown: function( pages ) {
346-
this.stepDown( (pages || 1) * this.options.page );
347-
},
380+
pageDown: modifier(function( pages ) {
381+
this._stepDown( (pages || 1) * this.options.page );
382+
}),
348383

349384
value: function( newVal ) {
350385
if ( !arguments.length ) {

0 commit comments

Comments
 (0)