Best way to handle history autocomplete in a form?

This post is more than 2 years old.

This was an interesting question sent to me by Joel:

I have a text input that it used for a search criteria, and I only want to enable the search button when at least 5 characters have been entered. (The list of possible matches is huge, and I don't want 25,000 results returned to the browser.)

Suppose the text input is called "searchBox". With jQuery, I can do this:

$("#searchBox").keyup(function() {
$("#btnGo").button("option", "disabled", $(this).val().length < 5 );
});


(It's a jQuery UI button, which is why the syntax for enabling is different from a normal button).

Most browsers keep a form input history. So If I start to type "apple" and I've typed it before, I can just click and choose it from the list. This does not fire the keyup event. I can bind "change" also, but that only fires when the input loses focus. Any thoughts on how to bind the selection of form history to enable the button?

Apparently dealing with a browser's autocomplete isn't quite as simple as one would think. I did a quick example to prove this (and I wanted a non-jQuery UI one to test):

<html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(document).ready(function() {

$("#search").keyup(function() {
 $("#searchBtn").attr("disabled", $(this).val().length &lt; 5 );
});

}) </script> </head>

<body>

<form action="test.html" method="post"> <input type="text" name="search" id="search"> <input type="submit" value="Search" id="searchBtn" disabled="true"> </form>

If you run this (online demo here) and enter a few values, you should be able to see the "manual" approach work, but as soon as you use something from the browser's autocomplete history, it doesn't register. In my initial Google search, the first result I found suggested simply turning it off. That's doable but not exactly a solution. What about using the change handler?

$("#search").change(function() { $("#searchBtn").attr("disabled", $(this).val().length < 5 ); });

That works - but not immediately. The user has to click elsewhere to register the change. After a bit more searching I found this comment on the jQuery docs for change. The user, Robin, mentioned listening for a new HTML5, input. (This was the first time I'd heard of this. I thought I knew about all the HTML5 Form stuff. Guess I was wrong. Looks to be documented here.) I gave this a try:

<html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(document).ready(function() {

$("#search").keyup(function() {
 $("#searchBtn").attr("disabled", $(this).val().length &lt; 5 );
});



$("#search").live("input",function() {
 $("#searchBtn").attr("disabled", $(this).val().length &lt; 5 );
});

}) </script> </head>

<body>

<form action="test.html" method="post"> <input type="text" name="search" id="search"> <input type="submit" value="Search" id="searchBtn" disabled="true"> </form>

You can demo this one here. Good news! Works in Chrome. Works in Firefox. Works in - oh crap. Not IE. Since apparently IE9 doesn't support anything Form-related in HTML5. sigh At this point, I'm willing to just give up on IE and just use "change" - as I said, it doesn't work immediately, but by this point, IE users are probably used to a substandard experience. Here is the "final" template I used.

<html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(document).ready(function() {

$("#search").keyup(function() {
 $("#searchBtn").attr("disabled", $(this).val().length &lt; 5 );
});

$("#search").change(function() {
 $("#searchBtn").attr("disabled", $(this).val().length &lt; 5 );
});

$("#search").live("input",function() {
 $("#searchBtn").attr("disabled", $(this).val().length &lt; 5 );
});

}) </script> </head>

<body>

<form action="test.html" method="post"> <input type="text" name="search" id="search"> <input type="submit" value="Search" id="searchBtn" disabled="true"> </form>

You can try this demo here. So - does anyone have a nicer solution?

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Raymond Camden posted on 6/16/2011 at 6:21 PM

Yes - I'm commenting on my own blog post. ;) One idea that occurred to me - you could use a setInterval to check the field length every second. It shouldn't be too processor heavy I think to do so. It feels kinda hacky, and it would not be "instant", but it would be darn close.

Comment 2 by Raymond Camden posted on 6/16/2011 at 6:26 PM

For folks curious I uploaded a version here:

http://www.coldfusionjedi.c...

It uses a interval of 400 ms.

Comment 3 by Sam Farmer posted on 6/16/2011 at 7:46 PM

I believe you can add autocomplete="off" to the input text tag.

Comment 4 by Raymond Camden posted on 6/16/2011 at 7:46 PM

Errrr right. I said that. ;) But it's not a "solution" though.

Comment 5 by Sam Farmer posted on 6/16/2011 at 7:56 PM

Ah, my bad for not reading throughly! ;)

I'd be tempted to turn off autocomplete and provide links above for X number of recent searches.

Comment 6 by Ben B posted on 6/16/2011 at 9:14 PM

Here's a suggestion that kind of side-steps the question, but I think it accomplishes the underlying task. How about instead of disabling the submit, wait until submit and then check to see how many characters have been entered? If enough, allow submit to continue, otherwise prevent it. Granted, the experience is slightly different (wouldn't provide a visual indicator that submit is enabled) -- but pretty close.

Maybe if you did a combination of the two approaches you could cover your browser bases.

Comment 7 by Raymond Camden posted on 6/16/2011 at 9:55 PM

That's not a bad suggestion Ben.

Comment 8 by Joel Cox posted on 6/16/2011 at 11:27 PM

Thanks for all of the suggestions. Ultimately, I'm going to do an AJAX post ($.post), so they're probably won't end up being a form history anyway. I ran into this once before on a different project and thought I'd bring it up since I didn't find a good solution the first time, either.

Comment 9 by Jonathan posted on 6/17/2011 at 5:05 AM

I agree with Ben, but if you really want to think of another alternative, you can also fire the function with the onblur event from the input text box. If so, the function should be fired before the user could get the chance to press the submit button.

Comment 10 by Julian Halliwell posted on 6/18/2011 at 12:39 PM

From a UX viewpoint this wouldn't be ideal without some sort of visible explanation. Quite frustrating seeing buttons and not knowing why you can't click them.

Comment 11 by Raymond Camden posted on 6/18/2011 at 5:22 PM

Good point. My demo was pretty minimal but a real form should have had that type of explanation.

Comment 12 by Michael Wilson posted on 6/19/2011 at 9:59 AM

A solution for IE is to use the "onpropertychange" event.

$("#search").bind("propertychange change", function() {
$("#searchBtn").attr("disabled", $(this).val().length < 5 );
});

http://msdn.microsoft.com/e...

Comment 13 by Raymond Camden posted on 6/19/2011 at 6:28 PM

Michael - kick butt. That _did_ work. I can confirm it. In IE9 at least.

Comment 14 by Mark posted on 6/27/2011 at 5:30 PM

I have an alternative solution that seems to work in all browsers for auto-complete that uses the fact that the auto-complete window is considered outside the DOM in all browsers I have tested.

$(document).mouseenter(function(){
$("#searchBtn").attr("disabled", $(“#search”).val().length < 5 );

The mouse will have to move after clicking before it update for it to register being back in the document but since even the slightest mouse move will cause it to update I dont see this being a issue.

Note: The keyup function works in cases where the user chooses auto-complete option using the enter key instead of the mouse. This is becuase autocomplete updates on keydown but for mouse require a click.