1. |
Please enter your state:<br />
<input type="text" id="searchField" autocomplete="off" /><br />
<div id="popups"> </div>
Here's the bit of HTML that we care about. The one tricky (and non-standards compliant) part: that autocomplete attribute. It tells browsers not to do any auto-completion on this field, as we'll be handling it with the script. While it isn't part of any W3C recommendations, autocomplete, like XMLHttpRequest itself, has excellent cross-browser support.
|
2. |
document.getElementById ("searchField").onkeyup = searchSuggest;
In order to grab and process each keystroke, we need an event handler, and here's ours, set in initAll().
|
| |
3. |
xhr.onreadystatechange = setStatesArray;
xhr.open("GET", "us-states.xml", true);
xhr.send(null);
Unlike those photographs earlier in this chapter, the names of the United States aren't likely to change. We can read the XML file ( Script 15.3) in once, initialize our array, and safely assume that our list will still be valid at the end of this session.
|
4. |
if (xhr.responseXML) {
var allStates = xhr.responseXML. getElementsByTagName("item");
for (var i=0; i<allStates.length; i++) {
statesArray[i] = allStates[i]. getElementsByTagName("label") [0].firstChild;
}
}
Here's where we read that file in, looking at each item node, finding the label node inside, and then storing label's firstChildthe name of the state itself. Each of them goes into a slot in the StatesArray array.
|
5. |
var str = document.getElementById ("searchField").value;
document.getElementById ("searchField").className = "";
When you start typing in the field, you'll end up here, in the searchSuggest() event handler function. We start off by getting the value of searchField, which is whatever has been typed so far. Next, we clear that field's class attribute.
|
| |
6. |
if (str != "") {
document.getElementById("popups"). innerHTML = "";
If nothing's been entered, we don't want to do anything, so there's a check here to make sure that the user's entry has a value before we start popping up possibilities. If there's something there, we then blank out the previous list of possibilities.
|
7. |
for (var i=0; i<statesArray.length; i++) {
var thisState = statesArray[i]. nodeValue;
Now, we loop through the list of states, storing the current state we're looking at in thisState.
|
8. |
if (thisState.toLowerCase().indexOf (str.toLowerCase()) == 0) {
We want to see if what they've entered so far is part of a state namebut that alone isn't sufficient; we also have to make sure that what they've entered is at the beginning of the name. If you type in Kansas, you don't want to see a drop-down box asking if you want Arkansas or Kansas, after all. And so long as we're doing that check, we'll also force the comparison to be lowercase on both sides before checking indexOf().
If indexOf() returns 0that is, the entered string was found starting at position 1 of thisStatethen we know we have a hit.
|
| |
9. |
var tempDiv = document. createElement("div");
tempDiv.innerHTML = thisState;
tempDiv.onclick = makeChoice;
tempDiv.className = "suggestions";
document.getElementById("popups"). appendChild(tempDiv);
Because this state is a possibility, we want to add it to the list that will display. That's done by creating a temporary div, setting its innerHTML to the name of the state, adding an onclick handler and className, and then appending the whole to the popups div. Adding each state as a separate div allows us to manipulate each using JavaScript and CSS.
|
10. |
var foundCt = document. getElementById("popups"). childNodes.length;
When we've looped through all the states, we're done setting up the popupsbut how many do we have? We calculate that, the foundCt, here.
|
11. |
if (foundCt == 0) {
document.getElementById ("searchField").className = "error";
}
If foundCt is 0, they've entered something unexpected. We let them know that by setting the className to " error", which causes the entry field to display with a pale yellow background (based on a CSS style rule in Script 15.12).
|
| |
12. |
if (foundCt == 1) {
document.getElementById ("searchField").value = document.getElementById ("popups")
.firstChild. innerHTML;
document.getElementById ("popups").innerHTML = "";
}
If foundCt is one, however, we know that they've got a unique hit, so we can then put that state into the entry field. If they've typed in ca, they shouldn't have to type in lifornia also; we already know which state they want. We give them the full state by using the single div in popups to fill in the entry field, and then we blank out the popups div.
|
13. |
function makeChoice(evt) {
var thisDiv = (evt) ? evt.target : window.event.srcElement;
document.getElementById ("searchField").value = thisDiv.innerHTML;
document.getElementById ("popups").innerHTML = "";
}
Another way the user can enter a state name is to click one from the pop-up list. In that case, the makeChoice() event handler function is called. First, we figure out which state the user clicked by looking at the target of the event, and that gives us a particular div. Looking at the innerHTML for that div gives us the state name, and we put that into the entry field. And finally, we clear out the pop-up list of possibilities.
|