Geo!Suggest


Geo!Suggest = Yahoo Geocoding API + AJAX

Source Code::./yahoo.geocode.php


[LineNum : ON]  [Download]

<?php
/** 
* Geo!Suggest

* @package Geo!Suggest
* @version 1.0

* This is a main Geo!Suggest script - it used to render user interface.
* The main responsibility for this script is communication with service.yahoo.geocode.php through the AJAX calls
* fetching geocoding results and dynamical user interface creating.

* History 
* 11/12/2005 A. Bidochko 
* - Created. 
*/
?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <meta name="title" content="Geo!Suggest" />
  <meta name="description" content="Geo!Suggest - Yahoo Geocoder's AJAX Interface" />
  <meta name="keywords" content="Yahoo, Geocoding, MapBuilder.net" />
  <meta name="author" content="Andrew Bidochko" />
  <title>Geo!Suggest</title>
<style type="text/css">
   #MapBuilderIW { width: 200px; height: 200px;}
</style>

<script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=2.0&appid=mapbuilder.net"></script>

<script type="text/javascript">
// Global storage for Location objects
var MBLocations = new Array();

// Storage for map object
var map;

// MapBuilder.net: Location Definition Class
function MBLocation (Latitude, Longitude, Address, City, State, Zip, Country) {
  this.Latitude = Latitude;
  this.Longitude = Longitude;
  this.Address = Address;
  this.City = City;
  this.State = State;
  this.Zip = Zip;
  this.Country = Country;

  // Create well formatted location address
  this.GetAddress = function() {
    var addressItem = ''; 

    if (this.Address != '') {
       addressItem = this.Address;
    }
    if (this.City != '') {
       addressItem = (addressItem=='') ? this.City : addressItem + ", " + this.City;
    }
    if (this != '') {
       addressItem = (addressItem=='') ? this.State : addressItem + ", " + this.State;
    }
    if (this.Zip != '') {
       addressItem = (addressItem=='') ? this.Zip : addressItem + ", " + this.Zip;
    }
    if (this.Country != '') {
       addressItem = (addressItem=='') ? this.Country : addressItem + ", " + this.Country;
    }

    return addressItem;
  }
}

// global flag
var isIE = false;

// global request and XML document objects
var req;

// retrieve XML document (reusable generic function);
// parameter is URL string (relative or complete) to
// an .xml file whose Content-Type is a valid XML
// type, such as text/xml; XML source must be from
// same domain as HTML file
function loadXMLDoc(url) {
  // branch for native XMLHttpRequest object
  if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    req.onreadystatechange = processReqChange;
    req.open("GET", url, true);
    req.send(null);
  // branch for IE/Windows ActiveX version
  } 
  else if (window.ActiveXObject) {
    isIE = true;
    req = new ActiveXObject("Microsoft.XMLHTTP");
    if (req) {
      req.onreadystatechange = processReqChange;
      req.open("GET", url, true);
      req.send();
    }
  }
}

// handle onreadystatechange event of req object
function processReqChange() {
  // only if req shows "loaded"
  if (req.readyState == 4) {
    // only if "OK"
    if (req.status == 200) {
      clearAll();
      buildGeoSuggestList();
      // Enable address
      document.LocationSearchForm.LocationSearch.removeAttribute("readonly");
    } 
    else {
      alert("There was a problem retrieving the XML data:\n" +
          req.statusText);
      // Enable address
      document.LocationSearchForm.LocationSearch.removeAttribute("readonly");
    }
  }
}


// Retrieve text of an XML document element, including elements using namespaces
function getElementTextNS(prefix, local, parentElem, index) {
  var result = "";
  if (prefix && isIE) {
    // IE/Windows way of handling namespaces
    result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
  } 
  else {
    // the namespace versions of this method 
    // (getElementsByTagNameNS()) operate
    // differently in Safari and Mozilla, but both
    // return value with just local name, provided 
    // there aren't conflicts with non-namespace element
    // names
    result = parentElem.getElementsByTagName(local)[index];
  }
  if (result) {
    // get text, accounting for possible
    // whitespace (carriage return) text nodes 
    if (result.childNodes.length > 1) {
        return result.childNodes[1].nodeValue;
    } else {
        if (result.firstChild == null) return ''; 
        return result.firstChild.nodeValue;            
    }
  } 
  else {
    return "n/a";
  }
}

// Remove all previuos results from the screen
function clearAll() {
  clearSelect("GeoSuggestList");
  document.getElementById('searchInfo').innerHTML = '';
}

// Empty select list content
function clearSelect(select_name) {
  var select = document.getElementById(select_name);
  while (select.length > 0) {
    select.remove(0);
  }
}

// Add item to select element 
function appendToSelect(select, value, content) {
  var opt;
  opt = document.createElement("option");
  opt.value = value;
  opt.appendChild(content);
  select.appendChild(opt);
}

// Fill Loactions select list with items from the XML document
function buildGeoSuggestList() {
  //Remove all markers from map
  map.removeMarkersAll();
  
  document.getElementById('searchInfo').style.display = 'block';
  //document.getElementById("searchInfo").style.visibility = 'visible';
  
  var select = document.getElementById("GeoSuggestList");
  var errors = req.responseXML.getElementsByTagName("Error");
  // Do we have Error in xml?
  if (errors.length > 0) {
    document.getElementById('searchInfo').innerHTML = "<span style=\"color:red\">Yahoo returned the following error: " + 
      getElementTextNS("", "Message", errors[0], 0) + 
      "</span>";
    document.getElementById('GeoResults').style.display = 'none';
    document.getElementById("GeoSuggest").style.display = 'none';
    return;
  }

  var items = req.responseXML.getElementsByTagName("Result");
  
  /* Get precision attibutes.
  * Looks like yahoo return the same 'precision' attribute for multiple "Result" element
  */
  var precision = items[0].getAttribute('precision');

  // loop through <Result > elements, and add each nested to the "Suggest" drop down
  for (var i = 0; i < items.length; i++) {
    // Craete location object and store it in the array
    MBLocations[i] = new MBLocation
    (
      getElementTextNS("", "Latitude", items[i], 0),
      getElementTextNS("", "Longitude", items[i], 0),
      getElementTextNS("", "Address", items[i], 0),
      getElementTextNS("", "City", items[i], 0),
      getElementTextNS("", "State", items[i], 0),
      getElementTextNS("", "Zip", items[i], 0),
      getElementTextNS("", "Country", items[i], 0)
    );
    //Add node to the drop down
    appendToSelect(select, i, document.createTextNode(MBLocations[i].GetAddress()));
  }
  
  // Dump geocoding results
  // Show first available result
  DumpGeoInfo('0');
  
  // Do we have some suggestions from Yahoo?
  if (items.length > 1) {
    document.getElementById('searchInfo').innerHTML = 'Yahoo suggest you to select the most suitable geocoding result:';
    document.getElementById("GeoSuggest").style.display = 'block';
  }
  else {
    document.getElementById('searchInfo').style.display = 'none';
    document.getElementById("GeoSuggest").style.display = 'none';
  }
}

// AJAX call to make geocoding
function GeoCode(address) {
  if (trim(address)=='') {
    alert ("Please, specify address for geocoding.")
    return;
  }

  document.LocationSearchForm.LocationSearch.setAttribute("readonly","readonly");
  document.getElementById('searchInfo').innerHTML = 'Searching...';

  loadXMLDoc("service.yahoo.geocode.php?address=" + encode(address));
}

// Show geo information received from Yahoo for the given ID of MBLocation object
function DumpGeoInfo(id) {
  document.getElementById("GeoResults").innerHTML = 
  "<b>Geocode Result</b><br \>" +
  "Latitude: " + MBLocations[id].Latitude  + "<br \>" +
  "Longitude: " + MBLocations[id].Longitude + "<br \>" +
  "Address: " + MBLocations[id].Address + "<br \>" +
  "City: " + MBLocations[id].City + "<br \>" +
  "State: " + MBLocations[id].State + "<br \>" +
  "Zip: " + MBLocations[id].Zip + "<br \>" +
  "Country: " + MBLocations[id].Country;
  
  document.getElementById("GeoResults").style.visibility = 'visible';
  
  // Center Map and show marker
  showMarker(MBLocations[id].Latitude, MBLocations[id].Longitude, '3', "x", document.getElementById("GeoResults").innerHTML);
}

// Get address, put it on the form and geocode
function ForceGeoCode(address) {
  document.LocationSearchForm.LocationSearch.value = address;
  GeoCode(address);
}

// encode the things to pass back and forth
// the escape() method in Javascript is deprecated -- should use encodeURIComponent if available
function encode( uri ) {
  if (encodeURIComponent) {
    return encodeURIComponent(uri);
  }

  if (escape) {
    return escape(uri);
  }
}

function onLoad() {
  // Create a map object
  map = new  YMap(document.getElementById('mapContainer'));
  // Add a slider zoom control
  map.addZoomShort();
  
  var Text = "First Test";
  // Create a lat/lon object
  var myPoint = new YGeoPoint(30.244047, -97.747175); 
  // Display the map centered on a latitude and longitude
  map.drawZoomAndCenter(myPoint, 3);
}

function trim(str)
{
  return str.replace(/^\s*|\s*$/g,"");
}

// Show marker with label and text for mouse click event
function showMarker(Latitude, Longitude, Zoom, Label, Text) {
  // Create a lat/lon object
  var myPoint = new YGeoPoint(parseFloat(Latitude), parseFloat(Longitude)); 
  // Display the map centered on a latitude and longitude
  map.drawZoomAndCenter(myPoint, Zoom);
  // Create a marker positioned at a lat/lon
  var marker = new YMarker(myPoint);
  // Add a label to the marker
  marker.addLabel("<blink>"+Label+"</blink>");
  // Call onSmartWinEvent when the user clicks on the marker
  YEvent.Capture(marker, EventsList.MouseClick, 
    function onSmartWinEvent() {
      marker.openSmartWindow("<div id=\"MapBuilderIW\">"+Text+"</div>");
    } 
  );
  // Display the marker
  map.addOverlay(marker);
}

</script>

</head>

<body onload="onLoad();">
<h1>Geo!Suggest - Yahoo Geocoder's AJAX Interface</h1>
<div style="margin-right:15px;"> 
  <form id="LocationSearchForm" name="LocationSearchForm" method="post" onsubmit="GeoCode(document.LocationSearchForm.LocationSearch.value); return false;">
    <input class="text" id="LocationSearch" name="LocationSearch" size="40" value="Sunnyvale" type="text">
    &#032; 
    <input value="Search" type="button" class="frmButton" onclick="GeoCode(document.LocationSearchForm.LocationSearch.value);">
  </form>
  <div id="searchInfo"></div>
  <div id="GeoSuggest" style="display:none"> 
    <select id="GeoSuggestList" size="1" onchange="DumpGeoInfo(this.options[this.selectedIndex].value)">
      <option value="">Yahoo Suggest</option>
    </select>
  </div>
  <div id="GeoResults" style="visibility:hidden"> </div>
  <div id="mapContainer" style="width: 350px; height: 300px; margin-top:20px;"></div>
  <div id="devinfo">
    Developmet: <br />
    <a href="http://www.mapbuilder.net">Andrew Bidochko</a> 
  </div>
</div>
</body>
</html>