Now that you’ve constructed some simple JavaScript code to read form elements and do a calculation in response to a button submission event, you’re ready to wire up a form to use XHR to access the flickrgeo.php
server-side proxy. That is, you’ll let the user fill in new values and do the form submission by JavaScript. Once the user hits Go!, the script returns a URL to use flickrgeo.php
to search for geotagged photos. We’ll build up the example in three steps:
Translate the form parameters into a query to flickrgeo.php
.
Use XHR to do the request to flickrgeo.php
and display the resulting JSON response.
Translate that JSON into HTML for display.
Let’s start with the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>flickrgeo.1.html</title> <meta ?http-?equiv="Content-Type" content="text/html;charset=utf-8" /> </head> <body> <script type="text/javascript"> //<![CDATA[ function get_pictures() { /* We're aiming for the following: flickrgeo.php?tags=flower&lat0=-90&lon0=-180&lat1=90&lon1=180&page=1&per_page=10&o_format=json */ } //]]> </script> <form action="#" onsubmit="get_pictures(); return false;"> <label>Search for photos with the following tag:</label> <input type="text" size="20" name="tag" value="flower" /> <label> located at: lat0,lon0,lat1,lon1:</label> <input type="text" size="10" name="lat0" value="-90.0" /> <input type="text" size="10" name="lon0" value="-180.0" /> <input type="text" size="10" name="lat1" value="90.0" /> <input type="text" size="10" name="lon1" value="180.0" /> <label>at page</label> <input type="text" size="4" name="page" value="1" /> <label>with</label> <input type="text" size="3" name="per_page" value="1" /> <label> per page.</label> <button type="submit">Go!</button> </form> <div id="pics"></div> </body> </html>
Your goal is to figure out how to fill in get_pictues()
to translate the input parameters from the form into a URL of the correct form. Here’s one possible approach:[139]
<script type="text/javascript"> //<![CDATA[ function get_pictures() { // flickrgeo.php?tags=flower&lat0=-90&lon0=-180&lat1=90&lon1=180&page=1&per_page // =10&o_format=json var s = ""; f = document.forms[0].getElementsByTagName('input'); // get all input fields for (i = 0; i < f.length; i++) if (i < f.length - 1) { s = s + f[i].name + "=" + escape(f[i].value) + "&"; } else { s = s + f[i].name + "=" + escape(f[i].value); } var url = "flickrgeo.php?" + s + "&o_format=json"; document.getElementById('pics').innerHTML = "<a href=" + url + ">URL</a>"; } //]]> </script>
The get_pictures
function iterates through all the
<input>
tags in the form, extracting the name and value of each
tag, out of which to create a URL (with parameters) to flickrgeo.php
. This
URL is an HTTP GET
request for JSON-formatted results for the given
parameters.
The next step is to actually grab the JSON that is available at the URL. Using what you learned earlier (in the section “What Happens with XHR and Direct API Calls”), let’s use the YUI Connection Manager to call flickrgeo.php
and display the raw JSON:[140]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>flickrgeo.2.html</title> <meta ?http-?equiv="Content-Type" content="text/html;charset=utf-8" /> <script type="text/javascript" src="/lib/yui/build/yahoo/yahoo.js"></script> <script type="text/javascript" src="/lib/yui/build/event/event.js"></script> <script type="text/javascript" src="/lib/yui/build/connection/connection.js"> </script> </head> <body> <script type="text/javascript"> //<![CDATA[ var handleSuccess = function(o){ div = document.getElementById('pics'); div.innerHTML = ""; // blank out the div if(o.responseText !== undefined){ div.innerHTML += "Server response: " + o.responseText + "<br/>"; } } var handleFailure = function(o){ if(o.responseText !== undefined){ alert("failure"); } } var callback = { success:handleSuccess, failure: handleFailure, argument: {} }; function get_pictures() { // flickrgeo.php?tags=flower&lat0=-90&lon0=-180&lat1=90&lon1=180&page=1&per_page // =10&o_format=json var s = ""; f = document.forms[0].getElementsByTagName('input'); // get all input fields for (i = 0; i < f.length; i++) if (i < f.length - 1) { s = s + f[i].name + "=" + escape(f[i].value) + "&"; } else { s = s + f[i].name + "=" + escape(f[i].value); } var url = "flickrgeo.php?" + s + "&o_format=json"; var request = YAHOO.util.Connect.asyncRequest('GET', url, callback); } //]]> </script> <form action="#" onsubmit="get_pictures(); return false;"> <label>Search for photos with the following tag:</label> <input type="text" size="20" name="tags" value="flower" /> <label> located at: lat0,lon0,lat1,lon1:</label> <input type="text" size="10" name="lat0" value="-90.0" /> <input type="text" size="10" name="lon0" value="-180.0" /> <input type="text" size="10" name="lat1" value="90.0" /> <input type="text" size="10" name="lon1" value="180.0" /> <label>at page</label><input type="text" size="4" name="page" value="1" /> <label>with</label> <input type="text" size="3" name="per_page" value="1" /><label> per page.</label> <button type="submit">Go!</button> </form> <div id="pics"></div> </body> </html>
Note what was added:
<script>
elements to include the relevant parts of the Yahoo! UI Library to enable the use of the Connection Manager.
The definition of callback functions (handleSuccess
and handleFailure
), which are referenced by the callback
object, to handle successful and failed calls, respectively, to flickrgeo.php
. If the call is successful, the JSON output from flickrgeo.php
is written into the <div id="pics"></div>
.
A call to the Yahoo! Connection Manager in the line var request = YAHOO.util.Connect.?a
syncRequest('GET', url, callback);
. Remember that an HTTP GET
request is made to url
and the HTTP response is fed to the functions contained in the callback
object.
The next step is to convert the JSON input to HTML so that you can use it to display the photos. Note how you can use eval()
to convert the JSON coming back from Flickr to a JavaScript object because you trust the source of this JSON. An alternative to eval()
is JSON stringify()
.[141]
Here’s some code:[142]
<body> <script type="text/javascript"> //<![CDATA[ function rspToHTML(rsp) { var s = ""; // http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstb].jpg // http://www.flickr.com/photos/{user-id}/{photo-id} s = "total number is: " + rsp.photos.photo.length + "<br/>"; for (var i=0; i < rsp.photos.photo.length; i++) { photo = rsp.photos.photo[i]; t_url = "http://farm" + photo.farm + ".static.flickr.com/" + photo.server + "/" + photo.id + "_" + photo.secret + "_" + "t.jpg"; p_url = "http://www.flickr.com/photos/" + photo.owner + "/" + photo.id; s += '<a href="' + p_url + '">' + '<img alt="'+ photo.title + '"src="' + t_url + '"/>' + '</a>'; } return s; } var handleSuccess = function(o){ div = document.getElementById('pics'); div.innerHTML = ""; // blank out the div if(o.responseText !== undefined){ div.innerHTML += "Server response: " + o.responseText + "<br/>"; //let's deposit the response in a global variable //so that we can look at it via the shell. window.response = o.responseText; window.rsp = eval('(' + o.responseText + ')'); div.innerHTML = rspToHTML(window.rsp); } } var handleFailure = function(o){ ... } var callback = { ... }; function get_pictures() { ... } //]]> </script> <form action="#" onsubmit="get_pictures(); return false;"> ... </form> <div id="pics"></div> </body>
You now have a client-side form that uses XHR to query the Flickr API, get back results in JSON, convert the JSON to HTML, and insert that HTML into the page—without a page reload (see Figure 10-1). The next steps are to integrate these results with Google Maps—the work of the next section.
Figure 10.1. Results of flickrgeo.3.html
. Geotagged photos are displayed as HTML in response to the XHR request.