diff options
author | Jörn Zaefferer <joern.zaefferer@gmail.com> | 2010-02-02 14:04:50 +0000 |
---|---|---|
committer | Jörn Zaefferer <joern.zaefferer@gmail.com> | 2010-02-02 14:04:50 +0000 |
commit | df391a998fe3af2fe950e7c07921f70c02e8d541 (patch) | |
tree | 7b958e3bbb46ae91ca43591305deb5269e71b7ff | |
parent | d549ba6d43072f65c56159a136ad4c077d859d36 (diff) | |
download | jquery-ui-df391a998fe3af2fe950e7c07921f70c02e8d541.tar.gz jquery-ui-df391a998fe3af2fe950e7c07921f70c02e8d541.zip |
Fix for #5120 - create menu only once and return that element from the widget method, put ui-autocomplete class on menu
-rw-r--r-- | tests/unit/autocomplete/autocomplete_events.js | 10 | ||||
-rw-r--r-- | tests/unit/autocomplete/autocomplete_methods.js | 3 | ||||
-rw-r--r-- | tests/unit/autocomplete/autocomplete_options.js | 8 | ||||
-rw-r--r-- | themes/base/ui.autocomplete.css | 4 | ||||
-rw-r--r-- | ui/jquery.ui.autocomplete.js | 102 |
5 files changed, 64 insertions, 63 deletions
diff --git a/tests/unit/autocomplete/autocomplete_events.js b/tests/unit/autocomplete/autocomplete_events.js index 88df16528..3bbcafdf2 100644 --- a/tests/unit/autocomplete/autocomplete_events.js +++ b/tests/unit/autocomplete/autocomplete_events.js @@ -24,7 +24,7 @@ test("all events", function() { }, close: function(event) { same(event.type, "autocompleteclose"); - same( $(".ui-menu").length, 1 ); + same( $(".ui-menu:visible").length, 1 ); }, select: function(event, ui) { same(event.type, "autocompleteselect"); @@ -32,13 +32,13 @@ test("all events", function() { }, change: function(event) { same(event.type, "autocompletechange"); - same( $(".ui-menu").length, 0 ); + same( $(".ui-menu:visible").length, 0 ); } }); stop(); ac.val("ja").keydown(); setTimeout(function() { - same( $(".ui-menu").length, 1 ); + same( $(".ui-menu:visible").length, 1 ); ac.simulate("keydown", { keyCode: $.ui.keyCode.DOWN }); ac.simulate("keydown", { keyCode: $.ui.keyCode.ENTER }); start(); @@ -66,10 +66,10 @@ test("cancel search", function() { stop(); ac.val("ja").keydown(); setTimeout(function() { - same( $(".ui-menu").length, 0 ); + same( $(".ui-menu:visible").length, 0 ); ac.val("java").keydown(); setTimeout(function() { - same( $(".ui-menu").length, 1 ); + same( $(".ui-menu:visible").length, 1 ); same( $(".ui-menu .ui-menu-item").length, 2 ); start(); }, 50); diff --git a/tests/unit/autocomplete/autocomplete_methods.js b/tests/unit/autocomplete/autocomplete_methods.js index 3ad93844c..44e74cb69 100644 --- a/tests/unit/autocomplete/autocomplete_methods.js +++ b/tests/unit/autocomplete/autocomplete_methods.js @@ -9,7 +9,8 @@ module("autocomplete: methods"); test("destroy", function() { var beforeHtml = $("#autocomplete").parent().html(); var afterHtml = $("#autocomplete").autocomplete().autocomplete("destroy").parent().html(); - same( beforeHtml, afterHtml ); + // TODO can't use same, as that would insert the markup unescaped into the test results, screwing up other tests + ok( beforeHtml == afterHtml ); }) var data = ["c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "pearl"]; diff --git a/tests/unit/autocomplete/autocomplete_options.js b/tests/unit/autocomplete/autocomplete_options.js index 5a3a7d732..bd07ab7eb 100644 --- a/tests/unit/autocomplete/autocomplete_options.js +++ b/tests/unit/autocomplete/autocomplete_options.js @@ -71,12 +71,12 @@ test("delay", function() { }); ac.val("ja").keydown(); - same( $(".ui-menu").length, 0 ); + same( $(".ui-menu:visible").length, 0 ); // wait half a second for the default delay to open the menu stop(); setTimeout(function() { - same( $(".ui-menu").length, 1 ); + same( $(".ui-menu:visible").length, 1 ); ac.autocomplete("destroy"); start(); }, 100); @@ -87,11 +87,11 @@ test("minLength", function() { source: data }); ac.autocomplete("search", ""); - same( $(".ui-menu").length, 0, "blank not enough for minLength: 1" ); + same( $(".ui-menu:visible").length, 0, "blank not enough for minLength: 1" ); ac.autocomplete("option", "minLength", 0); ac.autocomplete("search", ""); - same( $(".ui-menu").length, 1, "blank enough for minLength: 0" ); + same( $(".ui-menu:visible").length, 1, "blank enough for minLength: 0" ); ac.autocomplete("destroy"); }); diff --git a/themes/base/ui.autocomplete.css b/themes/base/ui.autocomplete.css index f42a05a4c..03ad7d007 100644 --- a/themes/base/ui.autocomplete.css +++ b/themes/base/ui.autocomplete.css @@ -1,10 +1,10 @@ /* Autocomplete ----------------------------------*/ -.ui-autocomplete-menu { position: absolute; cursor: default; } +.ui-autocomplete { position: absolute; cursor: default; } .ui-autocomplete-loading { background: white url('images/ui-anim.basic.16x16.gif') right center no-repeat; } /* workarounds */ -* html .ui-autocomplete-menu { width:1px; } /* without this, the menu expands to 100% in IE6 */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ /* Menu ----------------------------------*/ diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 932485ebc..f326fd903 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -21,7 +21,6 @@ $.widget( "ui.autocomplete", { _create: function() { var self = this; this.element - .addClass( "ui-autocomplete" ) .attr( "autocomplete", "off" ) // TODO verify these actually work as intended .attr({ @@ -92,6 +91,44 @@ $.widget( "ui.autocomplete", { this.response = function() { return self._response.apply( self, arguments ); }; + this.menu = $("<ul/>") + .addClass( "ui-autocomplete" ) + .appendTo( this.element.parent() ) + .menu({ + focus: function( event, ui ) { + var item = ui.item.data( "item.autocomplete" ); + if ( false !== self._trigger( "focus", null, { item: item } ) ) { + // use value to match what will end up in the input + self.element.val( item.value ); + } + }, + selected: function( event, ui ) { + var item = ui.item.data( "item.autocomplete" ); + if ( false !== self._trigger( "select", event, { item: item } ) ) { + self.element.val( item.value ); + } + self.close( event ); + self.previous = self.element.val(); + // only trigger when focus was lost (click on menu) + if ( self.element[0] != document.activeElement ) { + self.element.focus(); + } + } + }) + .zIndex( this.element.zIndex() + 1 ) + // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 + .css({ top: 0, left: 0 }) + .position({ + my: "left top", + at: "left bottom", + of: this.element, + collision: "none" + }) + .hide() + .data( "menu" ); + if ( $.fn.bgiframe ) { + menu.element.bgiframe(); + } }, destroy: function() { @@ -170,10 +207,9 @@ $.widget( "ui.autocomplete", { close: function( event ) { clearTimeout( this.closing ); - if ( this.menu ) { + if ( this.menu.element.is(":visible") ) { this._trigger( "close", event ); - this.menu.element.remove(); - this.menu = null; + this.menu.element.hide(); } if ( this.previous != this.element.val() ) { this._trigger( "change", event ); @@ -200,59 +236,19 @@ $.widget( "ui.autocomplete", { }, _suggest: function( items ) { - if (this.menu) { - this.menu.element.remove(); - } - var self = this, - ul = $( "<ul></ul>" ), - parent = this.element.parent(); - + this.menu.element.empty(); + var ul = this.menu.element; $.each( items, function( index, item ) { $( "<li></li>" ) .data( "item.autocomplete", item ) .append( "<a>" + item.label + "</a>" ) .appendTo( ul ); }); - this.menu = ul - .addClass( "ui-autocomplete-menu" ) - .appendTo( parent ) - .menu({ - focus: function( event, ui ) { - var item = ui.item.data( "item.autocomplete" ); - if ( false !== self._trigger( "focus", null, { item: item } ) ) { - // use value to match what will end up in the input - self.element.val( item.value ); - } - }, - selected: function( event, ui ) { - var item = ui.item.data( "item.autocomplete" ); - if ( false !== self._trigger( "select", event, { item: item } ) ) { - self.element.val( item.value ); - } - self.close( event ); - self.previous = self.element.val(); - // only trigger when focus was lost (click on menu) - if ( self.element[0] != document.activeElement ) { - self.element.focus(); - } - } - }) - .zIndex( this.element.zIndex() + 1 ) - // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 - .css({ top: 0, left: 0 }) - .position({ - my: "left top", - at: "left bottom", - of: this.element, - collision: "none" - }) - .data( "menu" ); + this.menu.refresh(); + this.menu.element.show(); if ( ul.width() <= this.element.width() ) { ul.width( this.element.width() ); } - if ( $.fn.bgiframe ) { - ul.bgiframe(); - } }, _move: function( direction, event ) { @@ -270,8 +266,7 @@ $.widget( "ui.autocomplete", { }, widget: function() { - // return empty jQuery object when menu isn't initialized yet - return this.menu ? this.menu.element : $([]); + return this.menu.element; } }); @@ -316,7 +311,12 @@ $.widget("ui.menu", { e.preventDefault(); self.select(); }); - var items = this.element.children("li") + this.refresh(); + }, + + refresh: function() { + // don't refresh list items that are already adapted + var items = this.element.children("li:not(.ui-menu-item)") .addClass("ui-menu-item") .attr("role", "menuitem"); |