Opened 9 years ago

Closed 8 years ago

#6666 closed enhancement (fixed)

Autocomplete: keyboard-autorepeat on Firefox and paste event

Reported by: brotherli Owned by:
Priority: minor Milestone: 1.8.13
Component: ui.autocomplete Version: 1.8.6
Keywords: Cc:
Blocked by: Blocking:

Description

Keyboard-autorepeat (when holding down a key) doesn't fire keydown events in Firefox. This is desirable when holding down the cursor (up/down) keys to quickly move through the suggestions list and when pressing backspace until the input field is empty. In the latter case Firefox doesn't hide the suggestions list.

To make the behavior of the autocomplete widget consistent on all browsers (at least) the cursor and the backspace keys should be processed in the keypress event handler on Mozilla browsers.

Also pasting content to the input field using the mouse or the context menu doesn't trigger an update of the autocompleter. An event listener to 'paste' events could be added.

Change History (8)

comment:1 Changed 9 years ago by brotherli

Since I'm not familiar with Git I'm attaching a diff against version 1.8.6 to fix the above mentioned issues.

--- jquery.ui.autocomplete.js.1.8.6	2010-11-02 12:49:44.000000000 +0100
+++ jquery.ui.autocomplete.js	2010-11-18 11:09:52.000000000 +0100
@@ -55,12 +55,14 @@
 					self._move( "nextPage", event );
 					break;
 				case keyCode.UP:
-					self._move( "previous", event );
+					if (!$.browser.mozilla)
+						self._move( "previous", event );
 					// prevent moving cursor to beginning of text field in some browsers
 					event.preventDefault();
 					break;
 				case keyCode.DOWN:
-					self._move( "next", event );
+					if (!$.browser.mozilla)
+						self._move( "next", event );
 					// prevent moving cursor to end of text field in some browsers
 					event.preventDefault();
 					break;
@@ -85,15 +87,7 @@
 					self.close( event );
 					break;
 				default:
-					// keypress is triggered before the input value is changed
-					clearTimeout( self.searching );
-					self.searching = setTimeout(function() {
-						// only search if the value has changed
-						if ( self.term != self.element.val() ) {
-							self.selectedItem = null;
-							self.search( null, event );
-						}
-					}, self.options.delay );
+					self.triggerSearch( event );
 					break;
 				}
 			})
@@ -102,6 +96,24 @@
 					suppressKeyPress = false;
 					event.preventDefault();
 				}
+				// handle certain keys here because keyboard-autorepeat doesn't fire keydown events on Mozilla browsers
+				else if ($.browser.mozilla) {
+					var keyCode = $.ui.keyCode;
+					switch( event.keyCode ) {
+					case keyCode.UP:
+						self._move( "previous", event );
+						break;
+					case keyCode.DOWN:
+						self._move( "next", event );
+						break;
+					case keyCode.BACKSPACE:
+						self.triggerSearch( event );
+						break;
+					}
+				}
+			})
+			.bind( "paste.autocomplete", function ( event ) {
+				self.triggerSearch( event );
 			})
 			.bind( "focus.autocomplete", function() {
 				if ( self.options.disabled ) {
@@ -257,6 +269,19 @@
 		}
 	},
 
+	triggerSearch: function( event ) {
+		// keypress is triggered before th einput value is changed
+		var self = this;
+		clearTimeout( this.searching );
+		this.searching = setTimeout(function() {
+			// only search if the value has changed
+			if ( self.term != self.element.val() ) {
+				self.selectedItem = null;
+				self.search( null, event );
+			}
+		}, this.options.delay );
+	},
+
 	search: function( value, event ) {
 		value = value != null ? value : this.element.val();

comment:2 Changed 9 years ago by Scott González

Milestone: TBD1.9
Status: newopen

Sorry, but we can't accept any patches that contain browser checks.

comment:3 Changed 9 years ago by brotherli

So what's the preferred solution to get around behavioral differences between browsers? Ignore them?

comment:4 Changed 9 years ago by Scott González

Either find something that works in all browsers or find a way to detect that you're going to have a problem. You can check out jQuery.support for a slew of detection code. If you need more help, please use the forums.

Last edited 9 years ago by Scott González (previous) (diff)

comment:5 Changed 9 years ago by brotherli

OK, here's a revised version of my patch without browser detection. Feel free to find a better solution, I just thought this might help...

--- jquery.ui.autocomplete.js.1.8.6	2010-11-02 12:49:44.000000000 +0100
+++ jquery.ui.autocomplete.js	2010-11-18 14:13:38.000000000 +0100
@@ -50,17 +50,21 @@
 				switch( event.keyCode ) {
 				case keyCode.PAGE_UP:
 					self._move( "previousPage", event );
+					suppressKeyPress = true;
 					break;
 				case keyCode.PAGE_DOWN:
 					self._move( "nextPage", event );
+					suppressKeyPress = true;
 					break;
 				case keyCode.UP:
 					self._move( "previous", event );
+					suppressKeyPress = true;
 					// prevent moving cursor to beginning of text field in some browsers
 					event.preventDefault();
 					break;
 				case keyCode.DOWN:
 					self._move( "next", event );
+					suppressKeyPress = true;
 					// prevent moving cursor to end of text field in some browsers
 					event.preventDefault();
 					break;
@@ -85,15 +89,7 @@
 					self.close( event );
 					break;
 				default:
-					// keypress is triggered before the input value is changed
-					clearTimeout( self.searching );
-					self.searching = setTimeout(function() {
-						// only search if the value has changed
-						if ( self.term != self.element.val() ) {
-							self.selectedItem = null;
-							self.search( null, event );
-						}
-					}, self.options.delay );
+					self.triggerSearch( event );
 					break;
 				}
 			})
@@ -101,8 +97,32 @@
 				if ( suppressKeyPress ) {
 					suppressKeyPress = false;
 					event.preventDefault();
+					return;
+				}
+
+				// handle certain keys here because keyboard-autorepeat doesn't fire keydown events on all browsers
+				var keyCode = $.ui.keyCode;
+				switch( event.keyCode ) {
+				case keyCode.PAGE_UP:
+					self._move( "previousPage", event );
+					break;
+				case keyCode.PAGE_DOWN:
+					self._move( "nextPage", event );
+					break;
+				case keyCode.UP:
+					self._move( "previous", event );
+					break;
+				case keyCode.DOWN:
+					self._move( "next", event );
+					break;
+				case keyCode.BACKSPACE:
+					self.triggerSearch( event );
+					break;
 				}
 			})
+			.bind( "paste.autocomplete", function ( event ) {
+				self.triggerSearch( event );
+			})
 			.bind( "focus.autocomplete", function() {
 				if ( self.options.disabled ) {
 					return;
@@ -257,6 +277,19 @@
 		}
 	},
 
+	triggerSearch: function( event ) {
+		// keypress is triggered before the input value is changed
+		var self = this;
+		clearTimeout( this.searching );
+		this.searching = setTimeout(function() {
+			// only search if the value has changed
+			if ( self.term != self.element.val() ) {
+				self.selectedItem = null;
+				self.search( null, event );
+			}
+		}, this.options.delay );
+	},
+
 	search: function( value, event ) {
 		value = value != null ? value : this.element.val();

comment:6 Changed 9 years ago by Jörn Zaefferer

Related to #7269 - that one fixes the up/down/page_up/page_down repeating, but doesn't handle repeating backspace or paste event.

comment:8 Changed 8 years ago by Scott González

Milestone: 1.91.8.13
Resolution: fixed
Status: openclosed

Closing fixed for the key repeating. Paste will be handled separately (they're unrelated). See #8062.

Note: See TracTickets for help on using tickets.