Geo!Suggest


Geo!Suggest = Yahoo Geocoding API + AJAX

Source Code::./yahoo.geocode.php


[LineNum : OFF]  [Download]

1 <?php
2
/** 
3 * Geo!Suggest
4
5 * @package Geo!Suggest
6 * @version 1.0
7
8 * This is a main Geo!Suggest script - it used to render user interface.
9 * The main responsibility for this script is communication with service.yahoo.geocode.php through the AJAX calls
10 * fetching geocoding results and dynamical user interface creating.
11
12 * History 
13 * 11/12/2005 A. Bidochko 
14 * - Created. 
15 */
16
?>
17

18 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
19
20 <html>
21 <head>
22   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
23   <meta name="title" content="Geo!Suggest" />
24   <meta name="description" content="Geo!Suggest - Yahoo Geocoder's AJAX Interface" />
25   <meta name="keywords" content="Yahoo, Geocoding, MapBuilder.net" />
26   <meta name="author" content="Andrew Bidochko" />
27   <title>Geo!Suggest</title>
28 <style type="text/css">
29    #MapBuilderIW { width: 200px; height: 200px;}
30 </style>
31
32 <script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=2.0&appid=mapbuilder.net"></script>
33
34 <script type="text/javascript">
35 // Global storage for Location objects
36 var MBLocations = new Array();
37
38 // Storage for map object
39 var map;
40
41 // MapBuilder.net: Location Definition Class
42 function MBLocation (Latitude, Longitude, Address, City, State, Zip, Country) {
43   this.Latitude = Latitude;
44   this.Longitude = Longitude;
45   this.Address = Address;
46   this.City = City;
47   this.State = State;
48   this.Zip = Zip;
49   this.Country = Country;
50
51   // Create well formatted location address
52   this.GetAddress = function() {
53     var addressItem = ''; 
54
55     if (this.Address != '') {
56        addressItem = this.Address;
57     }
58     if (this.City != '') {
59        addressItem = (addressItem=='') ? this.City : addressItem + ", " + this.City;
60     }
61     if (this != '') {
62        addressItem = (addressItem=='') ? this.State : addressItem + ", " + this.State;
63     }
64     if (this.Zip != '') {
65        addressItem = (addressItem=='') ? this.Zip : addressItem + ", " + this.Zip;
66     }
67     if (this.Country != '') {
68        addressItem = (addressItem=='') ? this.Country : addressItem + ", " + this.Country;
69     }
70
71     return addressItem;
72   }
73 }
74
75 // global flag
76 var isIE = false;
77
78 // global request and XML document objects
79 var req;
80
81 // retrieve XML document (reusable generic function);
82 // parameter is URL string (relative or complete) to
83 // an .xml file whose Content-Type is a valid XML
84 // type, such as text/xml; XML source must be from
85 // same domain as HTML file
86 function loadXMLDoc(url) {
87   // branch for native XMLHttpRequest object
88   if (window.XMLHttpRequest) {
89     req = new XMLHttpRequest();
90     req.onreadystatechange = processReqChange;
91     req.open("GET", url, true);
92     req.send(null);
93   // branch for IE/Windows ActiveX version
94   } 
95   else if (window.ActiveXObject) {
96     isIE = true;
97     req = new ActiveXObject("Microsoft.XMLHTTP");
98     if (req) {
99       req.onreadystatechange = processReqChange;
100       req.open("GET", url, true);
101       req.send();
102     }
103   }
104 }
105
106 // handle onreadystatechange event of req object
107 function processReqChange() {
108   // only if req shows "loaded"
109   if (req.readyState == 4) {
110     // only if "OK"
111     if (req.status == 200) {
112       clearAll();
113       buildGeoSuggestList();
114       // Enable address
115       document.LocationSearchForm.LocationSearch.removeAttribute("readonly");
116     } 
117     else {
118       alert("There was a problem retrieving the XML data:\n" +
119           req.statusText);
120       // Enable address
121       document.LocationSearchForm.LocationSearch.removeAttribute("readonly");
122     }
123   }
124 }
125
126
127 // Retrieve text of an XML document element, including elements using namespaces
128 function getElementTextNS(prefix, local, parentElem, index) {
129   var result = "";
130   if (prefix && isIE) {
131     // IE/Windows way of handling namespaces
132     result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
133   } 
134   else {
135     // the namespace versions of this method 
136     // (getElementsByTagNameNS()) operate
137     // differently in Safari and Mozilla, but both
138     // return value with just local name, provided 
139     // there aren't conflicts with non-namespace element
140     // names
141     result = parentElem.getElementsByTagName(local)[index];
142   }
143   if (result) {
144     // get text, accounting for possible
145     // whitespace (carriage return) text nodes 
146     if (result.childNodes.length > 1) {
147         return result.childNodes[1].nodeValue;
148     } else {
149         if (result.firstChild == null) return ''; 
150         return result.firstChild.nodeValue;            
151     }
152   } 
153   else {
154     return "n/a";
155   }
156 }
157
158 // Remove all previuos results from the screen
159 function clearAll() {
160   clearSelect("GeoSuggestList");
161   document.getElementById('searchInfo').innerHTML = '';
162 }
163
164 // Empty select list content
165 function clearSelect(select_name) {
166   var select = document.getElementById(select_name);
167   while (select.length > 0) {
168     select.remove(0);
169   }
170 }
171
172 // Add item to select element 
173 function appendToSelect(select, value, content) {
174   var opt;
175   opt = document.createElement("option");
176   opt.value = value;
177   opt.appendChild(content);
178   select.appendChild(opt);
179 }
180
181 // Fill Loactions select list with items from the XML document
182 function buildGeoSuggestList() {
183   //Remove all markers from map
184   map.removeMarkersAll();
185   
186   document.getElementById('searchInfo').style.display = 'block';
187   //document.getElementById("searchInfo").style.visibility = 'visible';
188   
189   var select = document.getElementById("GeoSuggestList");
190   var errors = req.responseXML.getElementsByTagName("Error");
191   // Do we have Error in xml?
192   if (errors.length > 0) {
193     document.getElementById('searchInfo').innerHTML = "<span style=\"color:red\">Yahoo returned the following error: " + 
194       getElementTextNS("", "Message", errors[0], 0) + 
195       "</span>";
196     document.getElementById('GeoResults').style.display = 'none';
197     document.getElementById("GeoSuggest").style.display = 'none';
198     return;
199   }
200
201   var items = req.responseXML.getElementsByTagName("Result");
202   
203   /* Get precision attibutes.
204   * Looks like yahoo return the same 'precision' attribute for multiple "Result" element
205   */
206   var precision = items[0].getAttribute('precision');
207
208   // loop through <Result > elements, and add each nested to the "Suggest" drop down
209   for (var i = 0; i < items.length; i++) {
210     // Craete location object and store it in the array
211     MBLocations[i] = new MBLocation
212     (
213       getElementTextNS("", "Latitude", items[i], 0),
214       getElementTextNS("", "Longitude", items[i], 0),
215       getElementTextNS("", "Address", items[i], 0),
216       getElementTextNS("", "City", items[i], 0),
217       getElementTextNS("", "State", items[i], 0),
218       getElementTextNS("", "Zip", items[i], 0),
219       getElementTextNS("", "Country", items[i], 0)
220     );
221     //Add node to the drop down
222     appendToSelect(select, i, document.createTextNode(MBLocations[i].GetAddress()));
223   }
224   
225   // Dump geocoding results
226   // Show first available result
227   DumpGeoInfo('0');
228   
229   // Do we have some suggestions from Yahoo?
230   if (items.length > 1) {
231     document.getElementById('searchInfo').innerHTML = 'Yahoo suggest you to select the most suitable geocoding result:';
232     document.getElementById("GeoSuggest").style.display = 'block';
233   }
234   else {
235     document.getElementById('searchInfo').style.display = 'none';
236     document.getElementById("GeoSuggest").style.display = 'none';
237   }
238 }
239
240 // AJAX call to make geocoding
241 function GeoCode(address) {
242   if (trim(address)=='') {
243     alert ("Please, specify address for geocoding.")
244     return;
245   }
246
247   document.LocationSearchForm.LocationSearch.setAttribute("readonly","readonly");
248   document.getElementById('searchInfo').innerHTML = 'Searching...';
249
250   loadXMLDoc("service.yahoo.geocode.php?address=" + encode(address));
251 }
252
253 // Show geo information received from Yahoo for the given ID of MBLocation object
254 function DumpGeoInfo(id) {
255   document.getElementById("GeoResults").innerHTML = 
256   "<b>Geocode Result</b><br \>" +
257   "Latitude: " + MBLocations[id].Latitude  + "<br \>" +
258   "Longitude: " + MBLocations[id].Longitude + "<br \>" +
259   "Address: " + MBLocations[id].Address + "<br \>" +
260   "City: " + MBLocations[id].City + "<br \>" +
261   "State: " + MBLocations[id].State + "<br \>" +
262   "Zip: " + MBLocations[id].Zip + "<br \>" +
263   "Country: " + MBLocations[id].Country;
264   
265   document.getElementById("GeoResults").style.visibility = 'visible';
266   
267   // Center Map and show marker
268   showMarker(MBLocations[id].Latitude, MBLocations[id].Longitude, '3', "x", document.getElementById("GeoResults").innerHTML);
269 }
270
271 // Get address, put it on the form and geocode
272 function ForceGeoCode(address) {
273   document.LocationSearchForm.LocationSearch.value = address;
274   GeoCode(address);
275 }
276
277 // encode the things to pass back and forth
278 // the escape() method in Javascript is deprecated -- should use encodeURIComponent if available
279 function encode( uri ) {
280   if (encodeURIComponent) {
281     return encodeURIComponent(uri);
282   }
283
284   if (escape) {
285     return escape(uri);
286   }
287 }
288
289 function onLoad() {
290   // Create a map object
291   map = new  YMap(document.getElementById('mapContainer'));
292   // Add a slider zoom control
293   map.addZoomShort();
294   
295   var Text = "First Test";
296   // Create a lat/lon object
297   var myPoint = new YGeoPoint(30.244047, -97.747175); 
298   // Display the map centered on a latitude and longitude
299   map.drawZoomAndCenter(myPoint, 3);
300 }
301
302 function trim(str)
303 {
304   return str.replace(/^\s*|\s*$/g,"");
305 }
306
307 // Show marker with label and text for mouse click event
308 function showMarker(Latitude, Longitude, Zoom, Label, Text) {
309   // Create a lat/lon object
310   var myPoint = new YGeoPoint(parseFloat(Latitude), parseFloat(Longitude)); 
311   // Display the map centered on a latitude and longitude
312   map.drawZoomAndCenter(myPoint, Zoom);
313   // Create a marker positioned at a lat/lon
314   var marker = new YMarker(myPoint);
315   // Add a label to the marker
316   marker.addLabel("<blink>"+Label+"</blink>");
317   // Call onSmartWinEvent when the user clicks on the marker
318   YEvent.Capture(marker, EventsList.MouseClick, 
319     function onSmartWinEvent() {
320       marker.openSmartWindow("<div id=\"MapBuilderIW\">"+Text+"</div>");
321     } 
322   );
323   // Display the marker
324   map.addOverlay(marker);
325 }
326
327 </script>
328
329 </head>
330
331 <body onload="onLoad();">
332 <h1>Geo!Suggest - Yahoo Geocoder's AJAX Interface</h1>
333 <div style="margin-right:15px;"> 
334   <form id="LocationSearchForm" name="LocationSearchForm" method="post" onsubmit="GeoCode(document.LocationSearchForm.LocationSearch.value); return false;">
335     <input class="text" id="LocationSearch" name="LocationSearch" size="40" value="Sunnyvale" type="text">
336     &#032; 
337     <input value="Search" type="button" class="frmButton" onclick="GeoCode(document.LocationSearchForm.LocationSearch.value);">
338   </form>
339   <div id="searchInfo"></div>
340   <div id="GeoSuggest" style="display:none"> 
341     <select id="GeoSuggestList" size="1" onchange="DumpGeoInfo(this.options[this.selectedIndex].value)">
342       <option value="">Yahoo Suggest</option>
343     </select>
344   </div>
345   <div id="GeoResults" style="visibility:hidden"> </div>
346   <div id="mapContainer" style="width: 350px; height: 300px; margin-top:20px;"></div>
347   <div id="devinfo">
348     Developmet: <br />
349     <a href="http://www.mapbuilder.net">Andrew Bidochko</a> 
350   </div>
351 </div>
352 </body>
353 </html>
354