Geo!Suggest
Geo!Suggest = Yahoo Geocoding API + AJAXSource Code::./yahoo.geocode.php
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  
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