Skip to content
Permalink
Browse files

Spinner: Handle async focus events in IE. Fixes incorrect detection o…

…f changes.
  • Loading branch information
scottgonzalez committed May 10, 2012
1 parent ab4d8b7 commit d393c8b4cb26ec34878c22202da6ba9393e0094d
Showing with 90 additions and 48 deletions.
  1. +51 −45 tests/unit/spinner/spinner_events.js
  2. +39 −3 ui/jquery.ui.spinner.js
@@ -121,7 +121,7 @@ test( "stop", function() {
element.spinner( "value", 999 );
});

test( "change", function() {
asyncTest( "change", function() {
expect( 14 );
var element = $( "#spin" ).spinner();

@@ -174,50 +174,56 @@ test( "change", function() {
shouldChange( false, "button up, before blur" );
element.spinner( "widget" ).find( ".ui-spinner-up" ).mousedown().mouseup();
shouldChange( true, "blur after button up" );
element.blur();

shouldChange( false, "button down, before blur" );
element.spinner( "widget" ).find( ".ui-spinner-down" ).mousedown().mouseup();
shouldChange( true, "blur after button down" );
element.blur();

shouldChange( false, "many buttons, same final value, before blur" );
element.spinner( "widget" ).find( ".ui-spinner-up" ).mousedown().mouseup();
element.spinner( "widget" ).find( ".ui-spinner-up" ).mousedown().mouseup();
element.spinner( "widget" ).find( ".ui-spinner-down" ).mousedown().mouseup();
element.spinner( "widget" ).find( ".ui-spinner-down" ).mousedown().mouseup();
shouldChange( false, "blur after many buttons, same final value" );
element.blur();

shouldChange( true, "stepUp" );
element.spinner( "stepUp" );

shouldChange( true, "stepDown" );
element.spinner( "stepDown" );

shouldChange( true, "pageUp" );
element.spinner( "pageUp" );

shouldChange( true, "pageDown" );
element.spinner( "pageDown" );

shouldChange( true, "value" );
element.spinner( "value", 999 );

shouldChange( false, "value, same value" );
element.spinner( "value", 999 );

shouldChange( true, "max, value changed" );
element.spinner( "option", "max", 900 );

shouldChange( false, "max, value not changed" );
element.spinner( "option", "max", 1000 );

shouldChange( true, "min, value changed" );
element.spinner( "option", "min", 950 );

shouldChange( false, "min, value not changed" );
element.spinner( "option", "min", 200 );
setTimeout(function() {
element.blur();

shouldChange( false, "button down, before blur" );
element.spinner( "widget" ).find( ".ui-spinner-down" ).mousedown().mouseup();
shouldChange( true, "blur after button down" );
setTimeout(function() {
element.blur();

shouldChange( false, "many buttons, same final value, before blur" );
element.spinner( "widget" ).find( ".ui-spinner-up" ).mousedown().mouseup();
element.spinner( "widget" ).find( ".ui-spinner-up" ).mousedown().mouseup();
element.spinner( "widget" ).find( ".ui-spinner-down" ).mousedown().mouseup();
element.spinner( "widget" ).find( ".ui-spinner-down" ).mousedown().mouseup();
shouldChange( false, "blur after many buttons, same final value" );
element.blur();
setTimeout(function() {
shouldChange( true, "stepUp" );
element.spinner( "stepUp" );

shouldChange( true, "stepDown" );
element.spinner( "stepDown" );

shouldChange( true, "pageUp" );
element.spinner( "pageUp" );

shouldChange( true, "pageDown" );
element.spinner( "pageDown" );

shouldChange( true, "value" );
element.spinner( "value", 999 );

shouldChange( false, "value, same value" );
element.spinner( "value", 999 );

shouldChange( true, "max, value changed" );
element.spinner( "option", "max", 900 );

shouldChange( false, "max, value not changed" );
element.spinner( "option", "max", 1000 );

shouldChange( true, "min, value changed" );
element.spinner( "option", "min", 950 );

shouldChange( false, "min, value not changed" );
element.spinner( "option", "min", 200 );
start();
});
});
});
});

})( jQuery );
@@ -93,6 +93,11 @@ $.widget( "ui.spinner", {
this.previous = this.element.val();
},
blur: function( event ) {
if ( this.cancelBlur ) {
delete this.cancelBlur;
return;
}

this._refresh();
this.uiSpinner.removeClass( "ui-state-active" );
if ( this.previous !== this.element.val() ) {
@@ -117,11 +122,42 @@ $.widget( "ui.spinner", {
event.preventDefault();
},
"mousedown .ui-spinner-button": function( event ) {
var previous;

// We never want the buttons to have focus; whenever the user is
// interacting with the spinner, the focus should be on the input.
// If the input is focused then this.previous is properly set from
// when the input first received focus. If the input is not focused
// then we need to set this.previous based on the value before spinning.
previous = this.element[0] === this.document[0].activeElement ?
this.previous : this.element.val();
function checkFocus() {
var isActive = this.element[0] === this.document[0].activeElement;
if ( !isActive ) {
this.element.focus();
this.previous = previous;
// support: IE
// IE sets focus asynchronously, so we need to check if focus
// moved off of the input because the user clicked on the button.
this._delay(function() {
this.previous = previous;
});
}
}

// ensure focus is on (or stays on) the text field
event.preventDefault();
if ( this.document[0].activeElement !== this.element[ 0 ] ) {
this.element.focus();
}
checkFocus.call( this );

// support: IE
// IE doesn't prevent moving focus even with event.preventDefault()
// so we set a flag to know when we should ignore the blur event
// and check (again) if focus moved off of the input.
this.cancelBlur = true;
this._delay(function() {
delete this.cancelBlur;
checkFocus.call( this );
});

if ( this._start( event ) === false ) {
return;

0 comments on commit d393c8b

Please sign in to comment.
You can’t perform that action at this time.