A picture of me taking it easy

I'm currently on parental leave till September. During that time, I will not read any e-mail or blog comments.

Until I'm back, please read through my archives, take a look at my code/applications and check out my pictures.

Have a great summer, and a splendid winter to you aussies and kiwis! :-)

AJAX Suggestions - a new JavaScript library for you

Published on Monday, April 9th, 2007

Updated April 10th with a couple of features per comment suggestions

Ok, I’ve added a couple of features and settings based on the comments I’ve got. The additional settings are:

hideResultsOnDocumentClick
If a click on the document should hide the results list.
itemInsertValueSetFocusToInput
If the focus should be set to the input element, once an item has updated the input element’s value (by initially having the itemInsertValueIntoInputClassName CSS class).
hideResultsWhenInsertValueIsSelected
If the results list should be hidden when the input element’s value is updated.

Another additional feature is that if you use the arrow keys to navigate the results list, arrow up from the first item as well as arrow down from the last, will set the focus back to the input element.

Updated April 11th

Changed the license to a Creative Commons Deed.

Updated April 13th

I got an e-mail with the suggestion to turn off the web browser autocompletion feature of the inout element. I think it was a good idea, so I have now added it as a setting:

turnAutoCompleteOff : true

When most people need some kind of intellectual challenge, they do crosswords, sudokus, IQ tests, read up on philosophy or something similar. Me? I write some JavaScript. :-)

The thing is, though, that my small hobby scripts soon turn into something I think will be useful for other people, so I feel a strong urge to share it. Branded by having web developing as a living, after the initial rush and the proof of concept phase, more “sexy” matters come into my mind: scalability, performance, cross browser and cross platform support etc…

Anyway, once I’ve spent way too much time on that (and since I want to be a good father and husband, we’re talking late nights; basically, anytime when I seem to be the only person in the entire world awake), sooner or later I reach I time when I’m ready to share. Luckily, for my sanity, that time is now.

Background

I think that for me, as well as many other web developers, the spark was lit when I saw Google Suggest for the first time. Since then, I’ve wanted to (re-)create that JavaScript since I think it’s a perfect example of good progressive enhancement; helping the end user, but it’s nothing vital that the whole web site depends on.

I was kind of hoping that a project would turn up where this was asked for, but it never came (at least not yet), so I had to give in and create the script in my free time. The good thing with that, however, is that I own the script and can bring it to any project I seem fit. I just hate leaving my “script babies” behind. :-)

The script and the concept

The result of my efforts is AJAX Suggestions!

The general idea is that, as soon as you type a couple of characters into an input element, a JavaScript makes an AJAX call to the server, which performs a search and returns the results/suggestions and displays them adjacent to the input element. The user can then click on, or navigate through the results with the keyboard, and choose the item they prefer.

I’ve also added some functionality to use this to do a look-up of the value in the input element, and when one of the results are chosen, it replaces the value in the input element with the value of the result. This can be useful, for instance, in a web-based e-mail application where you want to auto-complete recipients. No doubt, many will want to tweak this for their specific needs, and that’s just fine. My advice, however, is to override the methods in an external JavaScript file, in case I update the core AJAX Suggestions JavaScript file.

Implementation

The script looks for elements that have the CSS class AJAX-suggestion and then another CSS class, like URL-the-actual-URL, where you should replace the-actual-URL with your desired URL for the AJAX call. The HTML code can look something like this:

<input type="text" class="AJAX-suggestion URL-AJAX-demo.php">

Important to note is that AJAX Suggestions supports multiple elements in the same web page, who can also use different URLs for their AJAX calls. The same element is used for presenting the results, so it will only show you the results/suggestions for the latest search.

A library, in two versions

I’ve created two versions of this script. One that is completely stand-alone, and will automatically work as soon as it’s included into a web page (given that the element/-s contain the desired CSS classes, of course.)

The other one is written based on DOMAssistant, which means that is slightly smaller (and leaner, according to my taste).

License and copyright

AJAX Suggestions is released under a Creative Commons Deed license. Basically, it means that it’s free to use and improve, and that the JavaScript files keep their reference to its creator. Like this:


/*
	AJAX Suggestions is developed by Robert Nyman, http://www.robertnyman.com, and it is released according to the
	Creative Commons Deed license (http://creativecommons.org/licenses/GPL/2.0/)
	For more information, please see http://www.robertnyman.com/ajax-suggestions
*/

Where to go from here

Go to the AJAX Suggestions mini web site, where you can see a demo of AJAX Suggestions or read through the implementation page to find about all the available settings.

You can also directly download the stand-alone JavaScript file (10 KB) or the DOMAssistant-based JavaScript file (7 KB) and start playing! :-)

Note: remember to call the init() method of the ajaxSuggestions object, with the approach you find suitable, when using the DOMAssistant version.

A thanks to PPK

In the darkest hour of developing this, I was eating candy till I felt sick and drinking about one glass of water a minute out of pure exasperation. At that time, one certain person’s work with the ins and outs of the abort method really saved the day.

So, Peter-Paul Koch, thank you for your superb XMLHTTP notes: abort() and Mozilla bug article.

 

PS. You can also see it in use for the search input element of this very web site. :-) DS.

24 comments

  • Emil Stenström
    April 10th, 2007 at 6:53

    One small thing I’d like to change:

    1) When I tab through the links I first have to go through all the links in the right menu. Is this because you add the dropdown to the bottom? I’d rather tab directly to it from the input (tested in Firefox).

    3) When I press enter on one of the list items the value gets copied, but I’d like to submit that word, so shifting focus to the input after that would be preferable. Enter #1 - fills the input, Enter #2 - submits that input contents. Tabbing backwards to the input again is just too cumbersome. Perhaps “close” all suggestions too?

    2) One of your examples uses the bold tag ;)

  • Robert Nyman - author
    April 10th, 2007 at 7:58

    Emil,

    1. The idea (although I might reconsider this) is to not hijack the tab at all, but instead use the down arrow to set focus to the results list (the same approach as Google uses).

    2. Most definitely! And it’s there since it’s valid, and also because there’s a vast difference between the b and the strong element. Semantics, young padawan, semantics. ;-)

    3. That is a very good suggestion. My thinking was that you might want to add more than one, and therefore kept the focus in the results list but that’s something I might have to revise.

  • Jeroen Mulder
    April 10th, 2007 at 9:47

    Haha, that is awesome. Last thursday I spend all day writing this in Javascript. Could have used this to get a good idea how to approach the problem. Some functionality I added:

    - Closing the suggestion list when clicking elsewhere
    - Highlighting of matched search term (see Yahoo!’s Auto Complete Design Pattern)
    - As well as the suggestion mentioned above.

    Difference for me is that I give suggestions to a very consistent set of data. So, I only send a xmlHttpRequest for the first character, store the results and then filter that list for the following characters, until it detects a new word.

  • Robert Nyman - author
    April 10th, 2007 at 9:56

    Jeroen,

    Right, missed to reply to Emil’s point about close the suggestions. That’s not functionality added through this library, but something each and everyone can implement in the reply they choose to deliver.

    When it comes to clicking: I though about adding a click to the document to hide it, but refrained from it for some reason. Maybe I should add it, it’s not a big thing to do.

    Not to sure about the higlighting. To me, highlighting means that the element has focus, and you can press enter to choose it, arrow down, to choose the one below etc. To me, this is not combinable with keeping the focus in the input element to be able to continue typing.

    However, a suggestion is to use another color for the first item in the returned results, and then, if desired, add functionality in a custom method to remove it.

    I guess the most common usage is to do a search for each character. What I do here, though, is that I cache requests/replies, so I never look up the same term twice.

  • Jeroen Mulder
    April 10th, 2007 at 10:08

    My bad. I didn’t explain the highlighting carefully. I agree the highlighting of the closest matching result is not a good idea. What I meant and what the pattern also suggests is to visually distinguish the matched search term in the suggestion list.

    For example, when you search for: ‘java’, the suggestion list looks like:

    - javascript
    - javabeans
    - javalicious

    Ah, I didn’t see the caching. Forgive me, I should have looked better at the actual code. It’s still early and I shouldn’t be commenting ;-)

  • Robert Nyman - author
    April 10th, 2007 at 10:16

    Jeroen,

    Ah, sorry, I didn’t read carefully enough. That’s a good idea about highlighting, but definitely something I would completely leave to the result generating logic.

    A downside with that, though, is that when doing a search here in my web site, it returns the title of the post matching the search criteria. This means that the post contains the search term, but, most likely, the post title doesn’t so the highlighting is in vain.

  • Kenneth Sundqvist
    April 10th, 2007 at 16:48

    One essential thing to point out, is that there is no easy way to gain focus of the input again when you’ve arrow-key’ed yourself on to the suggestions (only through tabbing, I believe.)

    A ‘Close this list/these suggestions’ selection isn’t very intuitive, so I suggest that when you arrow-key yourself off the list (going up when at the top, and down when at the bottom) sets focus to the input again. This is how Firefox works (don’t know about other browsers,) and It feels very intuitive.

  • Robert Nyman - author
    April 10th, 2007 at 21:32

    Kenneth,

    That’s a great idea! I’ve added it to the script.

  • Paul irish
    April 11th, 2007 at 2:28

    Actually a CC license is not meant for software. (read about it in their FAQ!) This is a good alternative: http://creativecommons.org/licenses/GPL/2.0/

  • Pat
    April 11th, 2007 at 9:22

    Robert, I have to admit something, the parts in your blog that contain AJAX, was generally skipped by me. But.. I’m tired, I love your blog, and I just ate so much chocolate left from Easter I’m feeling sick :( So.. what better remedy than to read what you’re up to today :)

    Thanks for sharing your “background” info, ’cause now I understand (a bit) what you’re up to those late nights. Funny is I’ve seen those drop down suggestions on other sites too, and wondered “how the heck do they do that?”

    When I have more time, I’m going to try to read the rest of your JS entries. Although I also admit, I’ve never really coded much in JS.. only whatever was necessary I guess.

    Thanks for your hard work!

  • Robert Nyman - author
    April 11th, 2007 at 11:30

    Paul,

    Thanks for pointing that out! I had missed that, but now I have changed the license to the one you suggested.

    Pat,

    Ah, that’s just fine. I’m very well aware that not everything I write is interesting to everyone. As long as write something that makes you come back, I’m happy. :-)

    And thanks for reading!

  • Lionel Petitiaux
    June 11th, 2007 at 11:55

    Robert,

    first of all, thanks for all your effort!

    Just wanted to comment on something I came across while testing your AJAX Suggestions library in IE7.

    When you click on a suggestion item in IE7, the entire URL is copied into the input field. For instance, if you click the bottom suggestion item in the demo on your site (’Click/press Enter on this, and it will add that value to the input element.‘) the IE7 input field value is ‘www.robertnyman.com/ajax-suggestions/robertn;’ while the same action in Firefox will result in the desired ‘robertn;’

    Any thoughts on this are greatly appreciated.

    All the best,

    Lionel.

  • Robert Nyman - author
    June 11th, 2007 at 22:24

    Lionel,

    Hmm…
    I haven’t access to IE 7 to test right now, but I guess it’s IE 7 that automatically adds the entire domain path to the href attribute, unless it’s preceded by something like a #.

    My recommendation is to either use a full path or one with a #. Another option is to tweak the insertValueIntoField method of the ajaxSuggestions object to trim out unwanted parts.

  • Erik
    November 8th, 2007 at 6:08

    To avoid the IE7 thing you could probably just stick the value you want in an attribute that HTML doesn’t do anything with. “value” would be a good choice.

    Anyhow, this is pretty nifty. I had to tweak it a little to get it to recognize textareas as well as input, but after that it worked quite excellently.

  • Robert Nyman - author
    November 8th, 2007 at 10:12

    Erik,

    Yes, that might be a good approach to it.
    Good that it worked out for you tweaking it with textarea elements!

  • Erik
    November 14th, 2007 at 0:01

    Now that I look at it again (I’m having to rewrite my code to take full advantage of this,) there are several options that would be better set per-element with custom attributes. The query URL would probably be better as query_url=”", for example.

  • Robert Nyman - author
    November 14th, 2007 at 12:27

    Erik,

    Personally, I don’t condole of custom attributes, since its invalid HTML code and there’s really no way to guarantee how it will work cross-browser and cross-platform.

  • Erik
    November 15th, 2007 at 8:05

    You have a point. I hadn’t thought of that.

  • KK AW
    December 30th, 2007 at 16:14

    Robert,

    I tried running you demo (index.html) with IE7 and it gives me an error on line 147 - Access is denied.

    “this.xmlHttp.onreadystatechange = this.getResults;”

    It works as expected in Firefox.

    Anything I have missed?

  • Robert Nyman - author
    December 30th, 2007 at 19:45

    KK AW,

    To make sure AJAX calls work in IE, it has to be run on a server (IIS, Apache etc). Just opening files locally and trying to make AJAX requests in IE will just give you an error.

  • KK AW
    December 31st, 2007 at 0:57

    Thanks. I will try that.

    Happy New Year 2008.

  • Daniel
    January 28th, 2008 at 1:12

    Hi… i like this wonderful AJAX SUGESSTIONS script. Works fine and looks quite nice.

    BUT: in the Moment i try to load prototype.js on the same page, i will get errors in IE and Suggestions does not work any longer.
    Error message e.g. “‘this.elements.length’ is null or no object”. Any ideas how to work with it?

    Daniel

  • Robert Nyman - author
    January 28th, 2008 at 8:48

    Daniel,

    I’ve never used Prototype, but my guess is that they implement something which affect elements, thus it might result in unexpected behavior of some parts.

  • tenshi13
    July 11th, 2008 at 4:52

    Would like to ask, is it me with PHP on my win box, on my IE6,
    that after i select an item it returns values in URL form, that i need to unescape it?
    Or everyone’s getting values in the same format?

    Real cool script! Thank you very much!!!

Share your thoughts:

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong> . If you want to display code examples, please remember to write &lt; for < and &gt; for >.

Comment preview

All the proceeds from ad clicks will go to charity. However, if you like to give something directly to charity yourself, I recommend choosing from the listed ones below.

  • Save the Children
  • Red Cross
  • Cancer Research UK
  • WWF

Top results