jQuery Autocomplete Using XML as Data Source
Update: fixed broken links for demo and zip.
Introduction
The following article will describe how to use an XML file as a Data Source for the jQuery Autocomplete plugin.
The jQuery Autocomplete Plugin documentation is lacking on examples, or details, on how to use an XML file as the data source. So this is my attempt to provide a simple example of how to use XML with the Autocomplete Plugin.
The plugin can take an array of strings, so we need to develop code to read the XML file into memory and parse its contents into an array of strings. Once we have an array of strings, we can assign that array to the autocomplete plugin and attach that to a text field in our form. The following will step through that process.
Demo
First things first. Here is a link to the demo.
Example Code
Below is the full code used for this article.
<!DOCTYPE html>
<html>
<head>
<title>jQuery Autocomplete: XML as data source</title>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.js"></script>
<script>
$(document).ready(function() {
var myArr = [];
$.ajax({
type: "GET",
url: "states.xml", // change to full path of file on server
dataType: "xml",
success: parseXml,
complete: setupAC,
failure: function(data) {
alert("XML File could not be found");
}
});
function parseXml(xml)
{
//find every query value
$(xml).find("state").each(function()
{
myArr.push($(this).attr("label"));
});
}
function setupAC() {
$("input#searchBox").autocomplete({
source: myArr,
minLength: 1,
select: function(event, ui) {
$("input#searchBox").val(ui.item.value);
$("#searchForm").submit();
}
});
}
});
</script>
</head>
<body style="font-size:62.5%;">
<form name="search_form" id="searchForm" method="GET" action="search_results.html">
<label for="searchBox">Keyword Search</label>
<input type="text" id="searchBox" name="searchString" />
<button name="searchKeyword" id="searchKeyword">Sumbit</button>
</form>
</body>
</html>
jQuery Library Includes
The following libraries and css are used for this example:
- jQuery UI CSS – http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css
- jQuery Minified JS - http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js
- jQuery UI JS – http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.js
XML File
The XML file used for this example is very basic. It consists of a parent element labeled states and child elements labeled state for each item that can be suggested as a search option.
<?xml version="1.0" encoding="UTF-8"?> <states> <state label="Alabama" value="AL" country="US" /> <state label="Alaska" value="AK" country="US" /> <state label="Arkansas" value="AR" country="US" /> <state label="Arizona" value="AZ" country="US" /> <state label="California" value="CA" country="US" /> <state label="Colorado" value="CO" country="US" /> <state label="Connecticut" value="CT" country="US" /> ...
The Form
The following is the form used in this example:
<form name="search_form" id="searchForm" method="GET" action="search_results.html"> <label for="searchBox">Keyword Search</label> <input type="text" id="searchBox" name="searchString" /> <button name="searchKeyword" id="searchKeyword">Sumbit</button> </form>
Important features of the form
- The form has an id of
searchForm. This will be used later to submit the form when selecting a result in the search suggestion list. - Text Input field has an id of
searchBox. This will be used to add autocomplete functionality to this form field.
Open XML file for parsing
In order for the form to display suggested search options, the XML file needs to be opened and parsed into memory. To do this, an ajax call is needed once the HTML document is ready.
$.ajax({
type: "GET",
url: "states.xml", // change to full path of file on server
dataType: "xml",
success: parseXml,
complete: setupAC,
error: function() {
alert("XML File could not be found");
}
});
Explanation
- If XML file is loaded succesfully,
parseXMLfunction is called. Which will, as you guessed, parse the XML file into an array of strings. - Once the
ajaxrequest is completed, assign the autocomplete plugin to thesearchBoxfield via thesetupACfunction. - If the
ajaxcall fails to find the XML file, an alert prompt will display; notifying you that the file cannot be found. This method works great for an example, but a more elegant error method should be developed for a production version.
Note: be sure to change the url variable to the full path of file on your sever.
Parse XML
The following code will parse the XML opened through the ajax call above.
function parseXml(xml)
{
//find every query value
$(xml).find("state").each(function()
{
myArr.push($(this).attr("label"));
});
}
This function finds all elements named state and adds the label attribute of that element to the myArr variable, which is of type Array.
Once this function is complete, myArr will be populated with possible search suggestion strings.
Adding Autocomplete Functionality
In order to add autocomplete functionality, we need to add the jQuery plugin features to an input text field.
After the ajax call is complete, the setupAC function is then called which will configure the autocomplete feature.
function setupAC() {
$("input#searchBox").autocomplete({
source: myArr,
minLength: 3,
select: function(event, ui) {
$("input#searchBox").val(ui.item.value);
$("#searchForm").submit();
}
});
}
Explanation
source: myArrassigns the array of strings parsed from our XML file as the data source- A minimum of 3 characters must be entered before suggested search options will display (
minLengthvalue). This can be changed to work for your solution. - The
selectoption will replace the text in the input field with the search suggestion selected item. This is needed so that the form will submit with the search term within the form properties. Otherwise, the form would submit with a blanksearchBoxvalue if a selection is made from the search suggestion dropdown. - Lastly,
$("#searchForm").submit()submits the form.
Limitations
One major limitation I’ve found with this plugin is the option to limit the suggestion menu result set. For example, it would be great to have the option to display a maximum of 10 suggestions matching the user’s search criteria. This example doesn’t have this problem, but imagine if your data source had thousands of strings and more than 50 of them had the characters “add” somewhere in the string. The suggestion dropdown would be too long to see all those results on the screen without scrolling.
Download Example
Here is a zip file containing all example files for this article. Feel free to reuse for your needs
I welcome comments or suggestions. All code is free to use as you see fit. No licensing here.
Thank you very much for this, it's a really nice explanation of everything. But the links, to the demo and .zip file, don't work. It would be really nice to have those two thing available too.
@zidar. Thank you for pointing out that the links were broken. This has now been fixed. Please let me know if you experience any other issues. Happy coding!
Great tutorial! Got it to work right away. Just have one question. How would you go about showing the autocomplete like: "Alabama, AL, USA".
Would be awesome if you could give me a hint!
@Homanp.
Option 1:
You could modify the parseXML function that is included in the demo's index.html. This could be accomplished by combining the label, value, and country properties for each state xml element into one. Look at the "$(xml).find("state").each(function()" portion of the code.
Here is an example:
function parseXml(xml)
{
//find every query value
$(xml).find("state").each(function()
{
// this variable combines the label, value, and country properties into a single string
// which will be added to the search array.
var thisItem = $(this).attr("label") + ', ' + $(this).attr("value") + ', ' + $(this).attr("country");
myArr.push(thisItem);
});
}
Option 2:
If you don't want to mess with the JavaScript, you could modify the label (since the JavaScript is already adding this attribute to the jQuery search string) in the XML file for each state property.
For example:
<state label="Alabama, AL, US" />
Change each state property in the XML file accordingly.
I hope that helps. Please let me know if you have any further questions.
hi
first thank you for this nice explanation.I am very new to jquery and ajax i have small issue that is i want the XML to change based in user input.
how can i changed the code so that everytime new xml is loaded from the server based on user input.
What i am trying to do is everytime user inputs something asp file file will be called which will generate XML.
How can i change the code to meet the requirements.
thanks
@ryman.
I'm not following what you are trying to accomplish. Could you provide a more in depth explanation?
Thank you.
Hey, thanks so much for sharing this.
How would I show the full details (as in option 1 in your last response), but actually use only the state to populate the form field ?
Thanks
Sol
@Sol.
This can be accomplished by modifying the autocomplete function associated with the input searchBox inside of the setupAC function. Take the string (ui.item.value) sent into that function and split the string (for example: Alabama, AL, USA) into a new string variable. Then you can assign that new variable to the input#searchBox's value.
Here is an example of the modified setupAC function, which places the full name of a state into the form field. Note: I've only tested this in Firefox.
function setupAC() {
$("input#searchBox").autocomplete({
source: myArr,
minLength: 1,
select: function(event, ui) {
var stateStr = ui.item.value.substring(0,ui.item.value.indexOf(',')); // adds the full state name to stateStr
$("input#searchBox").val(stateStr); // substitute ui.item.value for stateStr
$("#searchForm").submit();
}
});
}
});
If you wanted to break out the string manipulation into multiple steps for more clarity you could do this:
var wholeStr = ui.item.value;
var stateStr = wholeStr.substring(0,wholeStr.indexOf(','));
$("input#searchBox").val(ui.item.value);
I hope that helps. Please let me know if you have any further questions.
Hi
Here's how I did it:
All the labels show in the search box, but only Brand is populated on click through.
`
function parseXml(xml)
{
//find every query value
$(xml).find("airport").each(function()
{
//you are going to create an array of objects
var thisItem = {};
thisItem['label'] = $(this).attr("label") + ' ' + $(this).attr("colour") + ', ' + $(this).attr("size") + ' (' + $(this).attr("brand")+ ') ';
thisItem['value'] = $(this).attr("brand");
myArr.push(thisItem);
});
}
`
@Sol,
Very nice. that works much better than what I suggested. Glad you found a good solution!
Works perfectly!
Thanks!
Great stuff… I've mangled everything to suit my own "Plans for World Domination" (admit it, we've all got one!)…
But I've hit one teeny snag!
How do I stop the "autocomplete" bit from submitting the form as soon as it's filled in (by selecting a result in the dropdown)?
I've got a couple of other fields for people to enter, so I'd like them to have to press the "submit" button.
@Harvey,
Looking at the demo provided, disabling the $(#searchForm").submit() line from the setupAC function should prevent the form submitting by selecting a result in the dropdown. To do this, remove or comment line 39 in index.html from the demo (download provided above).
Here is an example:
function setupAC() {
$("input#searchBox").autocomplete({
source: myArr,
minLength: 1,
select: function(event, ui) {
$("input#searchBox").val(ui.item.value);
// $("#searchForm").submit(); <—- this line submits the form when selecting a result from the dropdown
}
});
Thanks, Ryan… Everything is working beautifully now.
This is only my second venture into jQuery, and the code and phrases are a bit different to what I'm used to; so I appreciate the help…
you are welcome, Harvey. Happy to help. Best of luck in your jQuery adventures.
Does anyone know who to limit the number of results?
@Jung,
I don't see an option to limit the number of results in the documentation.
However, to paraphrase from the AutoComplete documentation; a possible solution might be to change the minLength value to something higher than one. This will increase the minimum number of characters a user has to type before the Autocomplete activates. Zero is useful for local data with just a few items. But the value should be increased when there are a lot of items, where a single character would match a few thousand items.
I hope that helps.
Hi John,
Thank you so much for this wonderfully explained code.
i have a question, it would be great if you could help me.
On my page i have a table that uses an xml page. Artists and albums. When you click on the artist name an image on the right and side and some relevant content change according to the artist. I was wondering is there in a possibilities in being able to alter the code so it picks up my already functioning table. So if i type an artist in search box it will auto complete it and also i will be able to click and choose the artists which will then change the content on the page?
@Mak,
Without seeing your code or an example, I can only speak hypothetically about how to get your functionality added to this autocomplete example.
You should be able to add your function inside the setupAC function from the example above. If you add a hook to your existing code after line 37 from the demo, you should be able to leverage the functionality you've already built.
For example:
function setupAC() {
$("input#searchBox").autocomplete({
source: myArr,
minLength: 1,
select: function(event, ui) {
$("input#searchBox").val(ui.item.value);
// ADD YOUR FUNCTION HERE
//$("#searchForm").submit(); <- probably want to remove this line so that form does not submit
}
});
}
I would be happy to look into this further if you can provide an example…
Thank you.
Hi John, It works like a charm. But if I include the javascript in a separate file. It's not working.
I put the code in the below file and call it from my jsp like this and it won't work. Do you have any idea ?
<script type="text/javascript" src="js/pkval.js"></script>
@Jain,
Without seeing your server setup or have knowledge of source code, my guess is that other javascript code is interferring or the path is wrong on the .js file you are trying to include.
I hope that helps.
Thanks for tips on using XML sources, it is nice for newbies like myself. I am wondering about expanding the functionality so that when the visitor selects their state/province the code would populate both the state input and a separate country input..
@Tom,
This is definitely possible with a little tweaking of the example code. Here is one way of populating two input fields based on the autocomplete selection:
Step 1:
Add an additional input field with id of "country" in your form.
Step 2:
Modify the parseXML function as found below:
function parseXml(xml)
{
//find every query value
$(xml).find("state").each(function()
{
var thisItem = {};
thisItem['label'] = $(this).attr("label");
thisItem['country'] = $(this).attr("country");
myArr.push(thisItem);
});
}
Step 3:
Modify the setupAC function as found below:
function setupAC() {
$("input#searchBox").autocomplete({
source: myArr,
minLength: 1,
select: function(event, ui) {
$("input#searchBox").val(ui.item.label);
$("input#country").val(ui.item.country);
}
});
}
I hope that helps. Best of luck on your jQuery endeavors!
That worked like a charm. Thank you kindly.
Now I need to see if I can use what I learned from your example and merge it with data from the geonames.org db, to create an autocompleter triggered off the city name, that would also subsequently fill in both the state and the country inputs.
@John, I was able to resolve the issue. The issue was with the order in javascript import
Thanks,
Jain
Hi! Can you modify the code to make the matching start from the beginning? I've tried various solution but I couldn't make it work. I would love to see a working solution.
@anais,
I'm not sure what you mean. I'm happy to help if you could elaborate on what functionality you would like to see.
The demo shows the autocomplete matching start when one character is entered. Is that what you are looking for?
Hallo,
Nice one, thank you
But how to make the result work?
And not only "This page will contain search results…"
Can you give me please simple sample?
Thank you so much.
@wiyono,
The demo sends a GET variable called searchString to the search_results.html page (search_results.html?searchString=Ohio).
You could use this GET variable to do any processing you would need based on what the searchString variable contains (either from using the autocomplete functionality or entering text into the input box).
For example, in PHP, you could access the GET variable like this: $_GET['searchString'].
I hope that helps. Please let me know if yo have any further questions.
great job thanks a lot…