Among famous Ajax applications, there are a few that stand out, such as Google Suggest (www.google.com/webhp?complete=1&hl=en). It is shown in Figure 4.6.
Figure 4.6: Google Suggest
When you enter a partial search term, as shown in the figure, Google Suggest connects, using Ajax, to the Google servers and finds possible matches to your partial search term and displays them-no page refresh needed. Clicking a hyperlink in the drop-down list opens the corresponding search page in Google.
You can create a search page yourself that connects to Google Suggest, and download JavaScript from Google Suggest to do so. You can see this example at work in Figure 4.7.
Figure 4.7: Connecting to Google Suggest with a custom page
So how can you connect to Google Suggest? Say that you’ve stored the partial search term in a variable named searchTerm. You could then connect to Google Suggest at:
http://www.google.com/complete/search?hl=en&js=true&qu=" + searchTerm;
How does Google Suggest communicate with you? It sends back JavaScript code that calls a function named sendRPCDone. Here are the parameters passed to that function:
sendRPCDone(unusedVariable, searchTerm, arrayTerm, arrayResults, unusedArray)
So what does the JavaScript call you get back from Google Suggest actually look like? If you’re searching for ajax, this is the kind of JavaScript you’ll get back from Google:
sendRPCDone(frameElement, "ajax", new Array("ajax", "ajax amsterdam", "ajax fc", "ajax ontario", "ajax grips", "ajax football club", "ajax public library", "ajax football", "ajax soccer", "ajax pickering transit"), new Array("3,840,000 results", "502,000 results", "710,000 results", "275,000 results", "8,860 results", "573,000 results", "40,500 results", "454,000 results", "437,000 results", "10,700 results"), new Array(""));
You take it from there, writing your own sendRPCDone function that displays the results sent back to you from Google Suggest.
It’s time to create google.html. The action starts when the user enters a search term in the search text field, which has the ID textField:
<body> <H1>Connecting to Google Suggest</H1> Search for <input id = "textField" type = "text" name = "textField" onkeyup = "connectGoogleSuggest(event)"> <div id = "targetDiv"><div></div></div> </body>
Note how this works. Every time a key goes up, the onkeyup event attribute calls a function named connectGoogleSuggest, which means that you can watch what users type as they type it. Every time the user types a key, the connectGoogleSuggest function is called:
function connectGoogleSuggest(keyEvent) { . . . }
You can start the connectGoogleSuggest function by creating an object that corresponds to the input text field that the user has been typing into:
function connectGoogleSuggest(keyEvent) { var input = document.getElementById("textField"); . . . }
Next, you can check whether that text field contains any text, and if not, you can clear the target <div> element, which displays the drop-down list of items from Google Suggest:
function connectGoogleSuggest(keyEvent) { var input = document.getElementById("textField"); if (input.value) { . . . } else { var targetDiv = document.getElementById("targetDiv"); targetDiv.innerHTML = "<div></div>"; } }
If, on the other hand, the input text field does contain text, you can pass that text on to the getData function to connect to Google Suggest and get suggestions. You pass a relative URL, google.php?qu= and the search term, to getData like this:
function connectGoogleSuggest(keyEvent) { var input = document.getElementById("textField"); if (input.value) { getData("google.php?qu=" + input.value); } else { var targetDiv = document.getElementById("targetDiv"); targetDiv.innerHTML = "<div></div>"; } }
The getData function creates an XMLHttpRequest object in the usual way:
function getData(dataSource) { var XMLHttpRequestObject = false; if (window.XMLHttpRequest) { XMLHttpRequestObject = new XMLHttpRequest(); } else if (window.ActiveXObject) { XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); } . . . } }
and then connects to the relative URL passed to it, which is google.php?qu= and the search term:
function getData(dataSource) { var XMLHttpRequestObject = false; if (window.XMLHttpRequest) { XMLHttpRequestObject = new XMLHttpRequest(); } else if (window.ActiveXObject) { XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); } if(XMLHttpRequestObject) { XMLHttpRequestObject.open("GET", dataSource); XMLHttpRequestObject.onreadystatechange = function() { . . . } XMLHttpRequestObject.send(null); } }
The text returned from Google Suggest will be JavaScript to execute, and you can execute that JavaScript using the eval function:
function getData(dataSource) { var XMLHttpRequestObject = false; if (window.XMLHttpRequest) { XMLHttpRequestObject = new XMLHttpRequest(); } else if (window.ActiveXObject) { XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); } if(XMLHttpRequestObject) { XMLHttpRequestObject.open("GET", dataSource); XMLHttpRequestObject.onreadystatechange = function() { if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { eval(XMLHttpRequestObject.responseText); } } XMLHttpRequestObject.send(null); } }
As you know, the JavaScript Google Suggest sends back is a call to a function named sendRPCDone, and it passes an array of search term matches and the number of such matches to call sendRPCDone with, so this is the way to start writing sendRPCDone:
function sendRPCDone(unusedVariable, searchTerm, arrayTerm, arrayResults, unusedArray) { . . . }
In this application, the results that come back from Google Suggest are displayed in a <div> element with the ID targetDiv, using an HTML table. To assemble the text that should go into that table, the sendRPCDone function creates a variable named data and starts by storing a <table> tag in the data variable:
function sendRPCDone(unusedVariable, searchTerm, arrayTerm, arrayResults, unusedArray) { var data = "<table>"; . . . }
To add the items to the table, you can loop over the arrays passed to you, adding a new table row and cell for each array item:
function sendRPCDone(unusedVariable, searchTerm, arrayTerm, arrayResults, unusedArray) { var data = "<table>"; var loopIndex; if (arrayResults.length != 0) { for (var loopIndex = 0; loopIndex < arrayResults.length; loopIndex++) { data += "<tr><td>" + . . . } } }
Each match to the search term should be a hyperlink that, when clicked, takes the user to Google, so you can format each match to the partial search term this way in the drop-down list:
function sendRPCDone(unusedVariable, searchTerm, arrayTerm, arrayResults, unusedArray) { var data = "<table>"; var loopIndex; if (arrayResults.length != 0) { for (var loopIndex = 0; loopIndex < arrayResults.length; loopIndex++) { data += "<tr><td>" + "<a href='http://www.google.com/search?q=" + arrayTerm[loopIndex] + "'>" + arrayTerm[loopIndex] + '</a></td><td>' + arrayResults[loopIndex] + "</td></tr>"; } } }
Finally, you finish the table with a </table> tag, and display the table in the <div> element, giving the impression of a drop-down list:
function sendRPCDone(unusedVariable, searchTerm, arrayTerm, arrayResults, unusedArray) { var data = "<table>"; var loopIndex; if (arrayResults.length != 0) { for (var loopIndex = 0; loopIndex < arrayResults.length; loopIndex++) { data += "<tr><td>" + "<a href='http://www.google.com/search?q=" + arrayTerm[loopIndex] + "'>" + arrayTerm[loopIndex] + '</a></td><td>' + arrayResults[loopIndex] + "</td></tr>"; } } data += "</table>"; var targetDiv = document.getElementById("targetDiv"); targetDiv.innerHTML = data; }
The target <div> element is colored light red to stand out like this in the <style> element:
<html> <head> <title>Connecting to Google Suggest</title> <style> #targetDiv { background-color: #FFAAAA; width: 40%; } </style> . . .
All that remains is the PHP script, google.php; you use this script to connect to Google Suggest. You start by putting together the URL to open, which is www.google.com/complete/search?hl=en&js=true&qu=, where you append the term to search for at the end. That term is passed to google.php as a parameter named qu, so you can recover the term to search for as $_GET["qu"] and cobble together the URL to open this way (the PHP dot operator (.) joins two strings):
http://www.google.com/complete/search?hl=en&js=true&qu=" .$_GET["qu"]
In PHP, you can open URLs as files, using the fopen function, which returns a file handle that you use to read from the URL. Note the second parameter, r, which means that you’re opening the URL for reading:
<?php $filehandle = fopen("http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"], "r"); . . . ?>
Then you can keep reading from the URL with a while loop and the feof function, which returns true when you’re at the end of a file. You want to keep looping while you’re not at the end of the file, so you use !feof (as in JavaScript, the ! operator reverses the logical sense of its operand):
<?php $filehandle = fopen("http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"], "r"); while (!feof($filehandle)){ . . . } ?>
To get data from Google Suggest and echo it back to the browser, you can use the PHP fgets function to read data and the echo function to send it back to the browser:
<?php $filehandle = fopen("http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"], "r"); while (!feof($filehandle)){ $download = fgets($filehandle); echo $download; } ?>
Finally, you close the file handle with the fclose function:
<?php $filehandle = fopen("http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"], "r"); while (!feof($filehandle)){ $download = fgets($filehandle); echo $download; } fclose($filehandle); ?>
That echoes the data sent to you from Google Suggest. But why did you need to use google.php at all? Why couldn’t you have simply accessed the URL www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"] directly from the browser, in google.html? The answer has to do with the way the browser lets you call domains in Ajax, which is coming up next.