Datepicker Tests: Fix IE tests by accounting for async nature of focus/blur and by correctly not double focusing a programmatically focused date picker.

A partial fix was implemented to resolve #6694, and this commit completes the fix so we can programmatically focus a date picker without focus being fired twice.(cherry picked from commit 1c1b64fcf0)
This commit is contained in:
Mike Sherov 2013-04-07 14:16:31 -04:00 committed by Scott González
parent 5bcf0bf50b
commit 2879b3ac25
3 changed files with 89 additions and 79 deletions

View File

@ -87,56 +87,53 @@ test("change", function() {
equal($.datepicker._defaults.showOn, "focus", "Retain default showOn"); equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
}); });
asyncTest("invocation", function() { asyncTest( "invocation", function() {
expect( 29 ); expect( 29 );
var button, image, var button, image,
inp = TestHelpers.datepicker.init("#inp"), inp = TestHelpers.datepicker.init( "#inp" ),
dp = $("#ui-datepicker-div"), dp = $( "#ui-datepicker-div" ),
body = $("body"); body = $( "body" );
function step1() { function step1() {
// On focus // On focus
button = inp.siblings("button"); button = inp.siblings( "button" );
ok(button.length === 0, "Focus - button absent"); ok( button.length === 0, "Focus - button absent" );
image = inp.siblings("img"); image = inp.siblings( "img" );
ok(image.length === 0, "Focus - image absent"); ok( image.length === 0, "Focus - image absent" );
inp[0].focus();
setTimeout(function() { inp.one( "focus", function() {
ok(dp.is(":visible"), "Focus - rendered on focus"); ok( dp.is( ":visible" ), "Focus - rendered on focus" );
inp.simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE}); inp.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
ok(!dp.is(":visible"), "Focus - hidden on exit"); ok( !dp.is( ":visible" ), "Focus - hidden on exit" );
inp[0].blur();
setTimeout(function() { TestHelpers.datepicker.onBlurThenFocus( inp, function() {
inp[0].focus(); ok( dp.is( ":visible" ), "Focus - rendered on focus" );
setTimeout(function() { body.simulate( "mousedown", {} );
ok(dp.is(":visible"), "Focus - rendered on focus"); ok( !dp.is( ":visible" ), "Focus - hidden on external click" );
body.simulate("mousedown", {}); inp.datepicker( "hide" ).datepicker( "destroy" );
ok(!dp.is(":visible"), "Focus - hidden on external click");
inp.datepicker("hide").datepicker("destroy");
step2(); step2();
}); });
}); })[ 0 ].focus();
});
} }
function step2() { function step2() {
// On button // On button
inp = TestHelpers.datepicker.init("#inp", {showOn: "button", buttonText: "Popup"}); inp = TestHelpers.datepicker.init( "#inp", { showOn: "button", buttonText: "Popup" } );
ok(!dp.is(":visible"), "Button - initially hidden"); ok( !dp.is( ":visible" ), "Button - initially hidden" );
button = inp.siblings("button"); button = inp.siblings( "button" );
image = inp.siblings("img"); image = inp.siblings( "img" );
ok(button.length === 1, "Button - button present"); ok( button.length === 1, "Button - button present" );
ok(image.length === 0, "Button - image absent"); ok( image.length === 0, "Button - image absent" );
equal(button.text(), "Popup", "Button - button text"); equal( button.text(), "Popup", "Button - button text" );
inp[0].focus();
setTimeout(function() { TestHelpers.datepicker.onBlurThenFocus( inp, function() {
ok(!dp.is(":visible"), "Button - not rendered on focus"); ok( !dp.is( ":visible" ), "Button - not rendered on focus" );
button.click(); button.click();
ok(dp.is(":visible"), "Button - rendered on button click"); ok( dp.is( ":visible" ), "Button - rendered on button click" );
button.click(); button.click();
ok(!dp.is(":visible"), "Button - hidden on second button click"); ok( !dp.is( ":visible" ), "Button - hidden on second button click" );
inp.datepicker("hide").datepicker("destroy"); inp.datepicker( "hide" ).datepicker( "destroy" );
step3(); step3();
}); });
@ -144,23 +141,27 @@ asyncTest("invocation", function() {
function step3() { function step3() {
// On image button // On image button
inp = TestHelpers.datepicker.init("#inp", {showOn: "button", buttonImageOnly: true, inp = TestHelpers.datepicker.init( "#inp", {
buttonImage: "images/calendar.gif", buttonText: "Cal"}); showOn: "button",
ok(!dp.is(":visible"), "Image button - initially hidden"); buttonImageOnly: true,
button = inp.siblings("button"); buttonImage: "images/calendar.gif",
ok(button.length === 0, "Image button - button absent"); buttonText: "Cal"
image = inp.siblings("img"); });
ok(image.length === 1, "Image button - image present"); ok( !dp.is( ":visible" ), "Image button - initially hidden" );
equal(image.attr("src"), "images/calendar.gif", "Image button - image source"); button = inp.siblings( "button" );
equal(image.attr("title"), "Cal", "Image button - image text"); ok( button.length === 0, "Image button - button absent" );
inp[0].focus(); image = inp.siblings( "img" );
setTimeout(function() { ok( image.length === 1, "Image button - image present" );
ok(!dp.is(":visible"), "Image button - not rendered on focus"); equal( image.attr( "src" ), "images/calendar.gif", "Image button - image source" );
equal( image.attr( "title" ), "Cal", "Image button - image text" );
TestHelpers.datepicker.onBlurThenFocus( inp, function() {
ok( !dp.is( ":visible" ), "Image button - not rendered on focus" );
image.click(); image.click();
ok(dp.is(":visible"), "Image button - rendered on image click"); ok( dp.is( ":visible" ), "Image button - rendered on image click" );
image.click(); image.click();
ok(!dp.is(":visible"), "Image button - hidden on second image click"); ok( !dp.is( ":visible" ), "Image button - hidden on second image click" );
inp.datepicker("hide").datepicker("destroy"); inp.datepicker( "hide" ).datepicker( "destroy" );
step4(); step4();
}); });
@ -168,30 +169,27 @@ asyncTest("invocation", function() {
function step4() { function step4() {
// On both // On both
inp = TestHelpers.datepicker.init("#inp", {showOn: "both", buttonImage: "images/calendar.gif"}); inp = TestHelpers.datepicker.init( "#inp", { showOn: "both", buttonImage: "images/calendar.gif"} );
ok(!dp.is(":visible"), "Both - initially hidden"); ok( !dp.is( ":visible" ), "Both - initially hidden" );
button = inp.siblings("button"); button = inp.siblings( "button" );
ok(button.length === 1, "Both - button present"); ok( button.length === 1, "Both - button present" );
image = inp.siblings("img"); image = inp.siblings( "img" );
ok(image.length === 0, "Both - image absent"); ok( image.length === 0, "Both - image absent" );
image = button.children("img"); image = button.children( "img" );
ok(image.length === 1, "Both - button image present"); ok( image.length === 1, "Both - button image present" );
inp[0].blur();
setTimeout(function() { TestHelpers.datepicker.onBlurThenFocus( inp, function() {
inp[0].focus(); ok( dp.is( ":visible" ), "Both - rendered on focus" );
setTimeout(function() { body.simulate( "mousedown", {} );
ok(dp.is(":visible"), "Both - rendered on focus"); ok( !dp.is( ":visible" ), "Both - hidden on external click" );
body.simulate("mousedown", {});
ok(!dp.is(":visible"), "Both - hidden on external click");
button.click(); button.click();
ok(dp.is(":visible"), "Both - rendered on button click"); ok( dp.is( ":visible" ), "Both - rendered on button click" );
button.click(); button.click();
ok(!dp.is(":visible"), "Both - hidden on second button click"); ok( !dp.is( ":visible" ), "Both - hidden on second button click" );
inp.datepicker("hide").datepicker("destroy"); inp.datepicker( "hide" ).datepicker( "destroy" );
start(); start();
}); });
});
} }
step1(); step1();

View File

@ -18,5 +18,12 @@ TestHelpers.datepicker = {
$.datepicker.setDefaults($.datepicker.regional[""]); $.datepicker.setDefaults($.datepicker.regional[""]);
return $(id).datepicker($.extend({showAnim: ""}, options || {})); return $(id).datepicker($.extend({showAnim: ""}, options || {}));
}, },
onBlurThenFocus: function( element, callback ) {
element.one( "blur", function(){
element.one( "focus", function(){
callback();
})[ 0 ].focus();
})[ 0 ].blur();
},
PROP_NAME: "datepicker" PROP_NAME: "datepicker"
}; };

View File

@ -752,9 +752,10 @@ $.extend(Datepicker.prototype, {
inst.dpDiv[showAnim || "show"](showAnim ? duration : null); inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
} }
if (inst.input.is(":visible") && !inst.input.is(":disabled")) { if ( $.datepicker._shouldFocusInput( inst ) ) {
inst.input.focus(); inst.input.focus();
} }
$.datepicker._curInst = inst; $.datepicker._curInst = inst;
} }
}, },
@ -781,10 +782,7 @@ $.extend(Datepicker.prototype, {
inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
"Class"]("ui-datepicker-rtl"); "Class"]("ui-datepicker-rtl");
// #6694 - don't focus the input if it's already focused if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
// this breaks the change event in IE
if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
inst.input.is(":visible") && !inst.input.is(":disabled") && inst.input[0] !== document.activeElement) {
inst.input.focus(); inst.input.focus();
} }
@ -801,6 +799,13 @@ $.extend(Datepicker.prototype, {
} }
}, },
// #6694 - don't focus the input if it's already focused
// this breaks the change event in IE
// Support: IE and jQuery <1.9
_shouldFocusInput: function( inst ) {
return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
},
/* Check positioning to remain on screen. */ /* Check positioning to remain on screen. */
_checkOffset: function(inst, offset, isFixed) { _checkOffset: function(inst, offset, isFixed) {
var dpWidth = inst.dpDiv.outerWidth(), var dpWidth = inst.dpDiv.outerWidth(),