diff --git a/tests/unit/autocomplete/autocomplete_events.js b/tests/unit/autocomplete/autocomplete_events.js index 7b51ec4c08c..bd3d8b0d7af 100644 --- a/tests/unit/autocomplete/autocomplete_events.js +++ b/tests/unit/autocomplete/autocomplete_events.js @@ -176,4 +176,86 @@ asyncTest( "blur during remote search", function() { ac.val( "ro" ).keydown(); }); +asyncTest( "With an input pressing up causes the menu to be shown", function() { + arrowsActivateOpensMenuTest( "#autocomplete", true, true ); +}); + +asyncTest( "With an input pressing down causes the menu to be shown", function() { + arrowsActivateOpensMenuTest( "#autocomplete", false, true ); +}); + +asyncTest( "With a textarea pressing up doesn't cause the menu to be shown", function() { + arrowsActivateOpensMenuTest( "#autocomplete-textarea", true, false ); +}); + +asyncTest( "With a textarea pressing down doesn't cause the menu to be shown", function() { + arrowsActivateOpensMenuTest( "#autocomplete-textarea", false, false ); +}); + +asyncTest( "With a contenteditable pressing up doesn't cause the menu to be shown", function() { + arrowsActivateOpensMenuTest( "#autocomplete-contenteditable", true, false ); +}); + +asyncTest( "With a contenteditable pressing down doesn't cause the menu to be shown", function() { + arrowsActivateOpensMenuTest( "#autocomplete-contenteditable", false, false ); +}); + +function arrowsActivateOpensMenuTest( id, isKeyUp, isMenuVisible ) { + expect( 3 ); + var element = $( id ).autocomplete({ + source: data, + delay: 0, + minLength: 0 + }); + menu = element.autocomplete( "widget" ); + ok( menu.is( ":hidden" ), "menu is hidden to start with" ); + element.simulate( "keydown", { keyCode: ( isKeyUp ? $.ui.keyCode.UP : $.ui.keyCode.DOWN ) } ); + + setTimeout(function() { + equal( menu.is( ":visible" ), isMenuVisible, "menu is visible after delay" ); + equal( menu.find( "a.ui-state-focus" ).text(), "", "nothing should be initially selected" ); + start(); + }, 50 ); +} + +test( "Pressing up selects the previous search item when active with input", function() { + searchUpDownSelectsItemTest( "#autocomplete", true, "" ); +}); + +test( "Pressing down selects the next search item when active with input", function() { + searchUpDownSelectsItemTest( "#autocomplete", false, "JavaScript" ); +}); + +test( "Pressing up selects the previous search item when active with textarea", function() { + searchUpDownSelectsItemTest( "#autocomplete-textarea", true, "" ); +}); + +test( "Pressing down selects the next search item when active with textarea", function() { + searchUpDownSelectsItemTest( "#autocomplete-textarea", false, "JavaScript" ); +}); + +test( "Pressing up selects the previous search item when active with contenteditable", function() { + searchUpDownSelectsItemTest( "#autocomplete-contenteditable", true, "" ); +}); + +test( "Pressing down selects the next search item when active with contenteditable", function() { + searchUpDownSelectsItemTest( "#autocomplete-contenteditable", false, "JavaScript" ); +}); + +function searchUpDownSelectsItemTest( id, isKeyUp, itemThatShouldBeSelected ) { + expect( 2 ); + var element = $( id ).autocomplete({ + source: data, + autoFocus: true, + delay: 0 + }); + menu = element.autocomplete( "widget" ); + + element.autocomplete( "search", "a" ); + + equal( menu.find( "a.ui-state-focus" ).text(), "Java", "Java should be initially selected" ); + element.simulate( "keydown", { keyCode: ( isKeyUp ? $.ui.keyCode.UP : $.ui.keyCode.DOWN ) } ); + equal( menu.find( "a.ui-state-focus" ).text(), itemThatShouldBeSelected, "Check you've selected the expected value." ); +} + }( jQuery ) ); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index dbda2058ed8..0658f456a89 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -92,15 +92,11 @@ $.widget( "ui.autocomplete", { break; case keyCode.UP: suppressKeyPress = true; - self._move( "previous", event ); - // prevent moving cursor to beginning of text field in some browsers - event.preventDefault(); + self._keyEvent( "previous", event ); break; case keyCode.DOWN: suppressKeyPress = true; - self._move( "next", event ); - // prevent moving cursor to end of text field in some browsers - event.preventDefault(); + self._keyEvent( "next", event ); break; case keyCode.ENTER: case keyCode.NUMPAD_ENTER: @@ -151,14 +147,10 @@ $.widget( "ui.autocomplete", { self._move( "nextPage", event ); break; case keyCode.UP: - self._move( "previous", event ); - // prevent moving cursor to beginning of text field in some browsers - event.preventDefault(); + self._keyEvent( "previous", event ); break; case keyCode.DOWN: - self._move( "next", event ); - // prevent moving cursor to end of text field in some browsers - event.preventDefault(); + self._keyEvent( "next", event ); break; } }) @@ -495,6 +487,16 @@ $.widget( "ui.autocomplete", { _value: function( value ) { return this.valueMethod.apply( this.element, arguments ); + }, + + _keyEvent: function( keyEvent, event ) { + var target = $( event.target ); + if ( this.menu.activeMenu.is( ":visible" ) || !target.is( "textarea" ) && (typeof target.attr( "contenteditable" ) === "undefined" || target.attr( "contenteditable" ) === false )) { + this._move( keyEvent, event ); + + // prevents moving cursor to beginning/end of the text field in some browsers + event.preventDefault(); + } } });