Skip to content

Commit 1c1b64f

Browse files
committed
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.
1 parent 58d9130 commit 1c1b64f

File tree

3 files changed

+89
-79
lines changed

3 files changed

+89
-79
lines changed

tests/unit/datepicker/datepicker_options.js

Lines changed: 72 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -87,110 +87,108 @@ test("change", function() {
8787
equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
8888
});
8989

90-
asyncTest("invocation", function() {
90+
asyncTest( "invocation", function() {
9191
expect( 29 );
9292
var button, image,
93-
inp = TestHelpers.datepicker.init("#inp"),
94-
dp = $("#ui-datepicker-div"),
95-
body = $("body");
93+
inp = TestHelpers.datepicker.init( "#inp" ),
94+
dp = $( "#ui-datepicker-div" ),
95+
body = $( "body" );
9696

9797
function step1() {
9898
// On focus
99-
button = inp.siblings("button");
100-
ok(button.length === 0, "Focus - button absent");
101-
image = inp.siblings("img");
102-
ok(image.length === 0, "Focus - image absent");
103-
inp[0].focus();
104-
setTimeout(function() {
105-
ok(dp.is(":visible"), "Focus - rendered on focus");
106-
inp.simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
107-
ok(!dp.is(":visible"), "Focus - hidden on exit");
108-
inp[0].blur();
109-
setTimeout(function() {
110-
inp[0].focus();
111-
setTimeout(function() {
112-
ok(dp.is(":visible"), "Focus - rendered on focus");
113-
body.simulate("mousedown", {});
114-
ok(!dp.is(":visible"), "Focus - hidden on external click");
115-
inp.datepicker("hide").datepicker("destroy");
99+
button = inp.siblings( "button" );
100+
ok( button.length === 0, "Focus - button absent" );
101+
image = inp.siblings( "img" );
102+
ok( image.length === 0, "Focus - image absent" );
103+
104+
inp.one( "focus", function() {
105+
ok( dp.is( ":visible" ), "Focus - rendered on focus" );
106+
inp.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
107+
ok( !dp.is( ":visible" ), "Focus - hidden on exit" );
116108

117-
step2();
118-
});
109+
TestHelpers.datepicker.onBlurThenFocus( inp, function() {
110+
ok( dp.is( ":visible" ), "Focus - rendered on focus" );
111+
body.simulate( "mousedown", {} );
112+
ok( !dp.is( ":visible" ), "Focus - hidden on external click" );
113+
inp.datepicker( "hide" ).datepicker( "destroy" );
114+
115+
step2();
119116
});
120-
});
117+
})[ 0 ].focus();
121118
}
122119

123120
function step2() {
124121
// On button
125-
inp = TestHelpers.datepicker.init("#inp", {showOn: "button", buttonText: "Popup"});
126-
ok(!dp.is(":visible"), "Button - initially hidden");
127-
button = inp.siblings("button");
128-
image = inp.siblings("img");
129-
ok(button.length === 1, "Button - button present");
130-
ok(image.length === 0, "Button - image absent");
131-
equal(button.text(), "Popup", "Button - button text");
132-
inp[0].focus();
133-
setTimeout(function() {
134-
ok(!dp.is(":visible"), "Button - not rendered on focus");
122+
inp = TestHelpers.datepicker.init( "#inp", { showOn: "button", buttonText: "Popup" } );
123+
ok( !dp.is( ":visible" ), "Button - initially hidden" );
124+
button = inp.siblings( "button" );
125+
image = inp.siblings( "img" );
126+
ok( button.length === 1, "Button - button present" );
127+
ok( image.length === 0, "Button - image absent" );
128+
equal( button.text(), "Popup", "Button - button text" );
129+
130+
TestHelpers.datepicker.onBlurThenFocus( inp, function() {
131+
ok( !dp.is( ":visible" ), "Button - not rendered on focus" );
135132
button.click();
136-
ok(dp.is(":visible"), "Button - rendered on button click");
133+
ok( dp.is( ":visible" ), "Button - rendered on button click" );
137134
button.click();
138-
ok(!dp.is(":visible"), "Button - hidden on second button click");
139-
inp.datepicker("hide").datepicker("destroy");
135+
ok( !dp.is( ":visible" ), "Button - hidden on second button click" );
136+
inp.datepicker( "hide" ).datepicker( "destroy" );
140137

141138
step3();
142139
});
143140
}
144141

145142
function step3() {
146143
// On image button
147-
inp = TestHelpers.datepicker.init("#inp", {showOn: "button", buttonImageOnly: true,
148-
buttonImage: "images/calendar.gif", buttonText: "Cal"});
149-
ok(!dp.is(":visible"), "Image button - initially hidden");
150-
button = inp.siblings("button");
151-
ok(button.length === 0, "Image button - button absent");
152-
image = inp.siblings("img");
153-
ok(image.length === 1, "Image button - image present");
154-
equal(image.attr("src"), "images/calendar.gif", "Image button - image source");
155-
equal(image.attr("title"), "Cal", "Image button - image text");
156-
inp[0].focus();
157-
setTimeout(function() {
158-
ok(!dp.is(":visible"), "Image button - not rendered on focus");
144+
inp = TestHelpers.datepicker.init( "#inp", {
145+
showOn: "button",
146+
buttonImageOnly: true,
147+
buttonImage: "images/calendar.gif",
148+
buttonText: "Cal"
149+
});
150+
ok( !dp.is( ":visible" ), "Image button - initially hidden" );
151+
button = inp.siblings( "button" );
152+
ok( button.length === 0, "Image button - button absent" );
153+
image = inp.siblings( "img" );
154+
ok( image.length === 1, "Image button - image present" );
155+
equal( image.attr( "src" ), "images/calendar.gif", "Image button - image source" );
156+
equal( image.attr( "title" ), "Cal", "Image button - image text" );
157+
158+
TestHelpers.datepicker.onBlurThenFocus( inp, function() {
159+
ok( !dp.is( ":visible" ), "Image button - not rendered on focus" );
159160
image.click();
160-
ok(dp.is(":visible"), "Image button - rendered on image click");
161+
ok( dp.is( ":visible" ), "Image button - rendered on image click" );
161162
image.click();
162-
ok(!dp.is(":visible"), "Image button - hidden on second image click");
163-
inp.datepicker("hide").datepicker("destroy");
163+
ok( !dp.is( ":visible" ), "Image button - hidden on second image click" );
164+
inp.datepicker( "hide" ).datepicker( "destroy" );
164165

165166
step4();
166167
});
167168
}
168169

169170
function step4() {
170171
// On both
171-
inp = TestHelpers.datepicker.init("#inp", {showOn: "both", buttonImage: "images/calendar.gif"});
172-
ok(!dp.is(":visible"), "Both - initially hidden");
173-
button = inp.siblings("button");
174-
ok(button.length === 1, "Both - button present");
175-
image = inp.siblings("img");
176-
ok(image.length === 0, "Both - image absent");
177-
image = button.children("img");
178-
ok(image.length === 1, "Both - button image present");
179-
inp[0].blur();
180-
setTimeout(function() {
181-
inp[0].focus();
182-
setTimeout(function() {
183-
ok(dp.is(":visible"), "Both - rendered on focus");
184-
body.simulate("mousedown", {});
185-
ok(!dp.is(":visible"), "Both - hidden on external click");
186-
button.click();
187-
ok(dp.is(":visible"), "Both - rendered on button click");
188-
button.click();
189-
ok(!dp.is(":visible"), "Both - hidden on second button click");
190-
inp.datepicker("hide").datepicker("destroy");
172+
inp = TestHelpers.datepicker.init( "#inp", { showOn: "both", buttonImage: "images/calendar.gif"} );
173+
ok( !dp.is( ":visible" ), "Both - initially hidden" );
174+
button = inp.siblings( "button" );
175+
ok( button.length === 1, "Both - button present" );
176+
image = inp.siblings( "img" );
177+
ok( image.length === 0, "Both - image absent" );
178+
image = button.children( "img" );
179+
ok( image.length === 1, "Both - button image present" );
191180

192-
start();
193-
});
181+
TestHelpers.datepicker.onBlurThenFocus( inp, function() {
182+
ok( dp.is( ":visible" ), "Both - rendered on focus" );
183+
body.simulate( "mousedown", {} );
184+
ok( !dp.is( ":visible" ), "Both - hidden on external click" );
185+
button.click();
186+
ok( dp.is( ":visible" ), "Both - rendered on button click" );
187+
button.click();
188+
ok( !dp.is( ":visible" ), "Both - hidden on second button click" );
189+
inp.datepicker( "hide" ).datepicker( "destroy" );
190+
191+
start();
194192
});
195193
}
196194

tests/unit/datepicker/datepicker_test_helpers.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,12 @@ TestHelpers.datepicker = {
1818
$.datepicker.setDefaults($.datepicker.regional[""]);
1919
return $(id).datepicker($.extend({showAnim: ""}, options || {}));
2020
},
21+
onBlurThenFocus: function( element, callback ) {
22+
element.one( "blur", function(){
23+
element.one( "focus", function(){
24+
callback();
25+
})[ 0 ].focus();
26+
})[ 0 ].blur();
27+
},
2128
PROP_NAME: "datepicker"
2229
};

ui/jquery.ui.datepicker.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -774,9 +774,10 @@ $.extend(Datepicker.prototype, {
774774
inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
775775
}
776776

777-
if (inst.input.is(":visible") && !inst.input.is(":disabled")) {
777+
if ( $.datepicker._shouldFocusInput( inst ) ) {
778778
inst.input.focus();
779779
}
780+
780781
$.datepicker._curInst = inst;
781782
}
782783
},
@@ -803,10 +804,7 @@ $.extend(Datepicker.prototype, {
803804
inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
804805
"Class"]("ui-datepicker-rtl");
805806

806-
// #6694 - don't focus the input if it's already focused
807-
// this breaks the change event in IE
808-
if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
809-
inst.input.is(":visible") && !inst.input.is(":disabled") && inst.input[0] !== document.activeElement) {
807+
if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
810808
inst.input.focus();
811809
}
812810

@@ -823,6 +821,13 @@ $.extend(Datepicker.prototype, {
823821
}
824822
},
825823

824+
// #6694 - don't focus the input if it's already focused
825+
// this breaks the change event in IE
826+
// Support: IE and jQuery <1.9
827+
_shouldFocusInput: function( inst ) {
828+
return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
829+
},
830+
826831
/* Check positioning to remain on screen. */
827832
_checkOffset: function(inst, offset, isFixed) {
828833
var dpWidth = inst.dpDiv.outerWidth(),

0 commit comments

Comments
 (0)