Tuesday, August 7, 2007

A Simple Geonames And Google Maps Mashup

Geonames is an opensource database of location data available under the creative commons license. Geonames provides web service APIs that can be used in your web applications. The database and some sourcecode are available for download as well.

I was playing around with the Geonames webservice APIs yesterday. I had done some playing with Google maps APIs and had this small map display in my blog where I could display different places. The geonames webservices interested me and I thought why not link them up together. So here is the result...

The following geonames APIs interested me:
  1. Get the list of contries tagged in the database with postcodes
  2. Search place based on postcode
  3. Search place based on latitude and longitude
  4. Search place based on place name
The APIs are available both as REST style APIs giving out XML and as well as JSON webservices giving out javascript objects. First I tried out the REST APIs using XMLHttpObject with AJAX. But since Geonames does not provide any XMLHttpObject supported scripts to be included from their site, I could run it only from a local html file and couldn't link it to the Google map on my blog (cross scripting!).

The JSON API migration was pretty straightforward, thanks to the helper javascript Geonames provides. You can see the result on the sidebar. Search using any thing - country and postcode, place name, latitude and longitude. If results are found, the result is populated in the boxes and the map moves to the place found!

There is a lot more at Geonames than what I could use till now in half a day. Entities are also classified by type, have details of altitude, population, and I think more that I haven't explored till now. The webservice has not been available all the time, though I don't know whether it is Geonames or my ISP.

You can try out the mashup on my sidebar. If you like it, you can include it on your site as well! Just add a link back to my article. ;)

Here is how to do it:
  1. Get a Google Maps API license from Google for your website
  2. Include the following code in the head of your template. Modify the initial position by setting the latitude and longitude in the call to setCenter method. This script has code to initialize Google Map and a method to set the map center point to a particular location with a marker. I commented out the info window display because I have very little space on my sidebar. If you are using this in a bigger form, you may enable it.

    <!--
    Google Maps code
    -->
    <script src='http://maps.google.com/maps?file=api&amp;v=2&key=ABQIAAAAmdqXgjznr4hS5v-Mm6h6sBSIOc1eR8fDsLa0r7-yKhCQJ6WduxSX8llV7pUW-Nv47K3n48VUeC47tg' type='text/javascript'/>
    <script type='text/javascript'>
    //<![CDATA[
    var mapobj;
    function load() {
    if (GBrowserIsCompatible()) {
    mapobj = new GMap2(document.getElementById("map"), {mapTypes:[G_HYBRID_MAP,G_SATELLITE_MAP]});
    mapobj.addControl(new GSmallMapControl());
    mapobj.addControl(new GMapTypeControl());
    // Change the lat and lng to the place you like!
    mapobj.setCenter(new GLatLng(12.966667, 77.583333), 12);
    mapobj.setMapType(G_HYBRID_MAP);
    }
    }

    function moveMap(lat, lng, zoom, txt) {
    mapobj.clearOverlays();
    var pt = new GLatLng(lat, lng);
    mapobj.panTo(pt);
    mapobj.setZoom(zoom);
    var marker = new GMarker(pt);
    /*
    GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(txt);
    });
    */
    mapobj.addOverlay(marker);
    }
    //]]>
    </script>
  3. Change the body tag of your template to one looking like the following:

    <body onload='load()' onunload='GUnload()'>

    This is to let Google initialize the map when your page loads.

  4. Create a new HTML widget and paste the following code into it:

    <script src="http://www.geonames.org/export/geonamesData.js" type="text/javascript"></script>
    <script src="http://www.geonames.org/export/jsr_class.js" type="text/javascript"></script>

    <script language="Javascript">
    var pcodesearched;
    var lngsearched;
    var latsearched;
    var placesearched;
    var resdiv;

    function doJSON(url) {
    // Create a new script object
    aObj = new JSONscriptRequest(url);
    // Build the script tag
    aObj.buildScriptTag();
    // Execute (add) the script tag
    aObj.addScriptTag();
    }

    function placeNameSearchCallback(jData) {
    if (jData == null) {
    document.getElementById(resdiv).innerHTML = '<small>Search failed for ' + placesearched + '</small>';
    return;
    }
    geonames = jData.geonames;
    document.getElementById(resdiv).innerHTML = '<small>' + geonames.length + ' results for ' + placesearched + '</small>';
    if(geonames.length > 0) {
    var pname=geonames[0].name;
    if(null != geonames[0].adminName1) pname += (', '+geonames[0].adminName1);
    var pcodegot="";
    var latgot=geonames[0].lat;
    var lnggot=geonames[0].lng;
    var cntrygot=geonames[0].countryCode;
    document.getElementById(resdiv).innerHTML += '<small><br/>Place: '+pname+'<br/>Country: '+cntrygot+'<br/>Latitude: ' + latgot + '<br/>Longitude: ' + lnggot + '</small>';
    populateResult('', pname, latgot, lnggot, cntrygot);
    }
    }

    function doPlaceNameSearch(divname, placename) {
    resdiv = divname;
    placesearched = placename;
    document.getElementById(divname).innerHTML = '<small>Searching ' + placename + '</small>';
    doJSON("http://ws.geonames.org/searchJSON?q="+placename+"&amp;maxRows=10"+'&callback=placeNameSearchCallback');
    }

    function latLngSearchCallback(jData) {
    if (jData == null) {
    document.getElementById(resdiv).innerHTML = '<small>Search failed for lat:' + latsearched + ' and lng:' + lngsearched + '</small>';
    return;
    }
    geonames = jData.geonames;
    document.getElementById(resdiv).innerHTML = '<small>' + geonames.length + ' results for lat:' + latsearched + ' and lng:' + lngsearched + '</small>';
    if(geonames.length > 0) {
    var pname=geonames[0].name;
    if(null != geonames[0].adminName1) pname += (', '+geonames[0].adminName1);
    var pcodegot="";
    var latgot=geonames[0].lat;
    var lnggot=geonames[0].lng;
    var cntrygot=geonames[0].countryCode;
    document.getElementById(resdiv).innerHTML += '<small><br/>Place: '+pname+'<br/>Country: '+cntrygot+'<br/>Latitude: ' + latgot + '<br/>Longitude: ' + lnggot + '</small>';
    populateResult('', pname, latgot, lnggot, cntrygot);
    }
    }

    function doLatLngSearch(divname, lat, lng) {
    resdiv = divname;
    latsearched = lat;
    lngsearched = lng;
    document.getElementById(divname).innerHTML = '<small>Searching lat:' + lat + ' and lng:' + lng + '</small>';
    doJSON("http://ws.geonames.org/findNearbyPlaceNameJSON?lat="+lat+"&lng="+lng+'&callback=latLngSearchCallback');
    }

    // this function will be called by our JSON callback
    // the parameter jData will contain an array with postalcode objects
    function postalCodeSearchCallback(jData) {
    if (jData == null) {
    document.getElementById(resdiv).innerHTML = '<small>Search failed for '+pcodesearched+' in '+document.getElementById('postcodecountry').value + '</small>';
    return;
    }
    postalcodes = jData.postalCodes;
    document.getElementById(resdiv).innerHTML = '<small>' + postalcodes.length + ' results for '+pcodesearched+' in '+document.getElementById('postcodecountry').value + '</small>';
    if(postalcodes.length > 0) {
    for(iIndex=0; iIndex < postalcodes.length; iIndex++) {
    var thisplace = postalcodes[iIndex];
    var pname=thisplace.placeName;
    if(null != thisplace.adminName1) pname += (', '+thisplace.adminName1);
    var pcodegot=thisplace.postalCode;
    var cntrygot=thisplace.countryCode;
    var latgot=thisplace.lat;
    var lnggot=thisplace.lng;
    if(pcodegot == pcodesearched) break;
    }
    document.getElementById(resdiv).innerHTML += '<small><br/>Best match: '+pname+' ('+pcodegot+')<br/>Latitude:'+latgot+'<br/>Longitude:'+lnggot+'</small>';
    populateResult(pcodegot, pname, latgot, lnggot, cntrygot);
    //alert("name:"+pname+" pcode:"+pcodegot+" lat:"+lat+" lng:"+lng);
    }
    }

    function doPostalCodeSearch(divname, pcode, cntry) {
    resdiv = divname;
    pcodesearched = pcode;
    document.getElementById(divname).innerHTML = '<small>Searching ' + pcode + ' in ' + cntry + '</small>';
    doJSON("http://ws.geonames.org/findNearbyPostalCodesJSON?postalcode="+pcode+"&country="+cntry+'&callback=postalCodeSearchCallback');
    }


    function createCountryCodeSelBox(divname) {
    document.getElementById(divname).innerHTML = '<small>Getting country codes...</small>';

    document.getElementById(divname).innerHTML = '<small>Search in:</small><select id="postcodecountry" width="220px" name="postcodecountry" style="width: 220px; font-size: 10px;"><option value="AD">Andorra (AD100 - AD700)</option><option value="AS">American Samoa (96799 - 96799)</option><option value="AT">Austria (1010 - 9991)</option><option value="AU">Australia (0200 - 9726)</option><option value="BE">Belgium (1000 - 9992)</option><option value="BG">Bulgaria (1000 - 9974)</option><option value="CA">Canada (A0A - Y1A)</option><option value="CH">Switzerland (1000 - 9658)</option><option value="CZ">Czech Republic (100 00 - 798 62)</option><option value="DE">Germany (01067 - 99998)</option><option value="DK">Denmark (0800 - 9990)</option><option value="ES">Spain (01001 - 52080)</option><option value="FI">Finland (00002 - 99999)</option><option value="FO">Faroe Islands (100 - 970)</option><option value="FR">France (01000 - 98000)</option><option value="GB">United Kingdom (AB1 - ZE3)</option><option value="GL">Greenland (3900 - 3985)</option><option value="GP">Guadeloupe (97100 - 97180)</option><option value="GR">Greece (200 01 - 859 00)</option><option value="GU">Guam (96910 - 96932)</option><option value="GY">Guyana (97312 - 97360)</option><option value="HR">Croatia (10000 - 53296)</option><option value="HU">Hungary (1011 - 9985)</option><option value="IN">India (110001 - 855126)</option><option value="IS">Iceland (101 - 902)</option><option value="IT">Italy (00010 - 98168)</option><option value="LI">Liechtenstein (9485 - 9498)</option><option value="LK">Sri Lanka ( * - 96167)</option><option value="LU">Luxembourg (L-1009 - L-9999)</option><option value="MC">Monaco (98000 - 98000)</option><option value="MH">Marshall Islands (96960 - 96970)</option><option value="MP">Northern Mariana Islands (96950 - 96952)</option><option value="MQ">Martinique (97213 - 97290)</option><option value="MX">Mexico (01000 - 99998)</option><option value="NL">Netherlands (1000 - 9999)</option><option value="NO">Norway (0001 - 9991)</option><option value="NZ">New Zealand (1001 - 9758)</option><option value="PK">Pakistan (10010 - 97320)</option><option value="PL">Poland (00-001 - 99-440)</option><option value="PM">Saint Pierre and Miquelon (97501 - 97502)</option><option value="PR">Puerto Rico (00601 - 00988)</option><option value="PT">Portugal (1000-001 - 9980-999)</option><option value="RE">Reunion (97400 - 97490)</option><option value="SE">Sweden (10005 - 98499)</option><option value="SI">Slovenia (1000 - 9600)</option><option value="SK">Slovakia (010 01 - 992 01)</option><option value="SM">San Marino (47890 - 47899)</option><option value="TH">Thailand (10100 - 96220)</option><option value="TR">Turkey (01010 - 81910)</option><option value="US">United States (00210 - 99950)</option><option value="VA">Vatican (00120 - 00120)</option><option value="VI">U.S. Virgin Islands (00801 - 00851)</option><option value="YT">Mayotte (97600 - 97640)</option><option value="ZA">South Africa (0002 - 9992)</option></select>';

    document.getElementById('postcodecountry').value = geonamesUserIpCountryCode;
    }

    function populateResult(postalcodeval, placenameval, latval, lngval, country) {
    document.getElementById('postcode').value = postalcodeval;
    document.getElementById('place').value = placenameval;
    document.getElementById('lat').value = latval;
    document.getElementById('lng').value = lngval;
    document.getElementById('postcodecountry').value = country;
    moveMap(latval, lngval, 13, placenameval);
    }
    </script>
    <div id="map" style="width: 220px; height: 220px"/></div>
    <div style="background: #e6e6e6; border: 1px solid #cccccc;">
    <div id="cntrydiv" class="resstyle">
    </div>
    <table border="0">
    <tr>
    <td><small>post code:</small></td>
    <td><input id="postcode" name="postcode" size="18" type="text" style="font-size: 10px;"/><input style="font-size: 10px;" value=">" onclick="srchres=doPostalCodeSearch('mapres', document.getElementById('postcode').value,document.getElementById('postcodecountry').value);" type="button"/></td>
    </tr>
    <tr>
    <td><small>place:</small></td>
    <td><input id="place" name="place" size="18" type="text" style="font-size: 10px;"/><input style="font-size: 10px;" value=">" onclick="srchres=doPlaceNameSearch('mapres', document.getElementById('place').value);" type="button"/></td>
    </tr>
    <tr>
    <td><small>lat:</small></td>
    <td><input id="lat" name="lat" size="18" type="text" style="font-size: 10px;"/><input style="font-size: 10px;" value=">" onclick="srchres=doLatLngSearch('mapres', document.getElementById('lat').value,document.getElementById('lng').value);" type="button"/></td>
    </tr>
    <tr>
    <td><small>lng:</small></td>
    <td><input id="lng" name="lng" size="18" type="text" style="font-size: 10px;"/><input style="font-size: 10px;" value=">" onclick="srchres=doLatLngSearch('mapres', document.getElementById('lat').value,document.getElementById('lng').value);" type="button"/></td>
    </tr>
    </table>
    </div>
    <div id="mapres" style="font-size: 10px; border: 1px solid #cccccc;">
    </div>
    <div style="font-size: 8px; background: #e6e6e6; border: 1px solid #cccccc; text-align: right;">
    powered by <a href="http://www.geonames.org/" alt="geonames">geonames</a>
    </div>
    <script language="javascript">
    createCountryCodeSelBox('cntrydiv');
    </script>

    This has the Google Map div element, the JSON code for Geonames and the geonames search text boxes. I created the country select box by getting a list of countries from Geonames webservice postalCodeCountryInfo. Unfortunately postalCodeCountryInfo is not available in JSON format so I couldn't use it directly on the page.


You can also check out the standalone code using XMLHttpObject. Save the code below into an HTML file and open it with your browser.

<html>
<head>
<script language="Javascript">
function getXMLHTTP() {
var xmlhttp=false;
if (!xmlhttp && (typeof(XMLHttpRequest) != 'undefined')) {
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
xmlhttp=false;
}
}
if (!xmlhttp && window.createRequest) {
try {
xmlhttp = window.createRequest();
} catch (e) {
xmlhttp=false;
}
}
return xmlhttp;
}

function doPlaceNameSearch(divname, placename) {
xmlhttp = getXMLHTTP();
document.getElementById(divname).innerHTML = 'Searching ' + placename;
var url = "http://ws.geonames.org/search?q="+placename+"&amp;maxRows=10";
//alert(url);
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
res = xmlhttp.responseXML.documentElement;
//alert(res);
geonames = res.getElementsByTagName('geoname');
document.getElementById(divname).innerHTML = geonames.length + ' results for ' + placename;
if(geonames.length > 0) {
var nl = geonames.item(0).childNodes;
var pname="";
var pcodegot="";
var latgot="";
var lnggot="";
var cntrygot="";
var distance="";

for(jIndex=0; jIndex < nl.length; jIndex++) {
var nd = nl.item(jIndex);
if(nd.nodeName == "name") pname = nd.firstChild.data;
else if(nd.nodeName == "countryCode") cntrygot = nd.firstChild.data;
else if(nd.nodeName == "lat") latgot = nd.firstChild.data;
else if(nd.nodeName == "lng") lnggot = nd.firstChild.data;
}
document.getElementById(divname).innerHTML += '<br/>Place: '+pname+'<br/>Country: '+cntrygot+'<br/>Latitude: ' + latgot + '<br/>Longitude: ' + lnggot;
populateResult('', pname, latgot, lnggot, cntrygot);
}
}
}
xmlhttp.send(null);
}

function doLatLngSearch(divname, lat, lng) {
xmlhttp = getXMLHTTP();
document.getElementById(divname).innerHTML = 'Searching lat:' + lat + ' and lng:' + lng;
var url = "http://ws.geonames.org/findNearbyPlaceName?lat="+lat+"&lng="+lng;
//alert(url);
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
res = xmlhttp.responseXML.documentElement;
//alert(res);
geonames = res.getElementsByTagName('geoname');
document.getElementById(divname).innerHTML = geonames.length + ' results for lat:' + lat + ' and lng:' + lng;
if(geonames.length > 0) {
var nl = geonames.item(0).childNodes;
var pname="";
var pcodegot="";
var latgot="";
var lnggot="";
var cntrygot="";
var distance="";

for(jIndex=0; jIndex < nl.length; jIndex++) {
var nd = nl.item(jIndex);
if(nd.nodeName == "name") pname = nd.firstChild.data;
else if(nd.nodeName == "countryCode") cntrygot = nd.firstChild.data;
else if(nd.nodeName == "lat") latgot = nd.firstChild.data;
else if(nd.nodeName == "lng") lnggot = nd.firstChild.data;
else if(nd.nodeName == "distance") distance = nd.firstChild.data;
}
document.getElementById(divname).innerHTML += '<br/>Place: '+pname+'<br/>Country: '+cntrygot+'<br/>Latitude: ' + latgot + '<br/>Longitude: ' + lnggot + '<br/>Distance: ' + distance;
populateResult('', pname, latgot, lnggot, cntrygot);
}
}
}
xmlhttp.send(null);
}

function doPostalCodeSearch(divname, pcode, cntry) {
xmlhttp = getXMLHTTP();
document.getElementById(divname).innerHTML = 'Searching ' + pcode + ' in ' + cntry;
var url = "http://ws.geonames.org/findNearbyPostalCodes?postalcode="+pcode+"&country="+cntry;
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
res = xmlhttp.responseXML.documentElement;
//alert(res);
codes = res.getElementsByTagName('code');
//alert(codes);
//alert(codes.length);
document.getElementById(divname).innerHTML = codes.length + ' results for ' + pcode + ' in ' + cntry;
if(codes.length > 0) {
for(iIndex=0; iIndex < codes.length; iIndex++) {
var thisplace = codes.item(iIndex);
var nl = thisplace.childNodes;
var pname="";
var pcodegot="";
var latgot="";
var lnggot="";
for(jIndex=0; jIndex < nl.length; jIndex++) {
var nd = nl.item(jIndex);
if(nd.nodeName == "name") pname = nd.firstChild.data;
else if(nd.nodeName == "postalcode") pcodegot = nd.firstChild.data;
else if(nd.nodeName == "lat") latgot = nd.firstChild.data;
else if(nd.nodeName == "lng") lnggot = nd.firstChild.data;
}
if(pcodegot == pcode) break;
}
document.getElementById(divname).innerHTML += '<br/>Best match: '+pname+'('+pcodegot+')<br/>Latitude:'+latgot+'<br/>Longitude:'+lnggot;
populateResult(pcodegot, pname, latgot, lnggot, cntry);
//alert("name:"+pname+" pcode:"+pcodegot+" lat:"+lat+" lng:"+lng);
}
}
}
xmlhttp.send(null);
}


function createCountryCodeSelBox(divname) {
xmlhttp = getXMLHTTP();
document.getElementById(divname).innerHTML = 'Getting country codes...';
var url = "http://ws.geonames.org/postalCodeCountryInfo?";
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
res = xmlhttp.responseXML.documentElement;
countries = res.getElementsByTagName('country');
var totalCountries = countries.length;
//alert(totalCountries);
var optstr = "";

for(iIndex=0; iIndex < totalCountries; iIndex++) {
var country = countries.item(iIndex);
var nl = country.childNodes;
var cname="";
var ccode="";
var mincode="";
var maxcode="";
for(jIndex=0; jIndex < nl.length; jIndex++) {
var nd = nl.item(jIndex);
if(nd.nodeName == "countryCode") ccode = nd.firstChild.data;
else if(nd.nodeName == "countryName") cname = nd.firstChild.data;
else if(nd.nodeName == "minPostalCode") mincode = nd.firstChild.data;
else if(nd.nodeName == "maxPostalCode") maxcode = nd.firstChild.data;
}
optstr += "<option value='"+ccode+"'>"+cname+" ("+mincode+" - "+maxcode+")"+"</option>";
}
document.getElementById(divname).innerHTML = 'Search in: <select id="postcodecountry" name="postcodecountry">'+optstr+'</select>';
document.getElementById('postcodecountry').value = "IN";
alert(optstr);
document.getElementById('debug').innerHTML = '<pre>'+escape(optstr)+'</pre>';
//document.getElementById('debug').innerHTML = 'Hello';
}
}
xmlhttp.send(null);
}
var srchres;
function populateResult(srchres) {
if(null != srchres) {
document.getElementById('postcode').value = srchres.postalcode;
document.getElementById('place').value = srchres.placename;
document.getElementById('lat').value = srchres.lat;
document.getElementById('lng').value = srchres.lng;
}
}
function populateResult(postalcodeval, placenameval, latval, lngval, country) {
document.getElementById('postcode').value = postalcodeval;
document.getElementById('place').value = placenameval;
document.getElementById('lat').value = latval;
document.getElementById('lng').value = lngval;
document.getElementById('postcodecountry').value = country;
}
</script>
</head>
<body>
<div id="cntrydiv">
</div>
postal code: <input name="postcode" id="postcode" type="text" size="10"/>
<input type="button" value=">" onclick="srchres=doPostalCodeSearch('mapres', document.getElementById('postcode').value,document.getElementById('postcodecountry').value);"/>
<br/>
place: <input name="place" id="place" type="text" size="20"/> <input type="button" value=">" onclick="srchres=doPlaceNameSearch('mapres', document.getElementById('place').value);"/><br/>
lat: <input name="lat" id="lat" type="text" size="20"/> <input type="button" value=">" onclick="srchres=doLatLngSearch('mapres', document.getElementById('lat').value,document.getElementById('lng').value);"/><br/>
lng: <input name="lng" id="lng" type="text" size="20"/> <input type="button" value=">" onclick="srchres=doLatLngSearch('mapres', document.getElementById('lat').value,document.getElementById('lng').value);"/><br/>
<div id="mapres">
</div>
<div id="debug">
Test
</div>
<script language="javascript">
createCountryCodeSelBox('cntrydiv');
</script>
</body>
</html>


There is also this standalone code using JSON below.

<html>
<head>
<script type="text/javascript" src="http://www.geonames.org/export/geonamesData.js"></script>
<script type="text/javascript" src="http://www.geonames.org/export/jsr_class.js"></script>

<script language="Javascript">
var pcodesearched;
var lngsearched;
var latsearched;
var placesearched;
var resdiv;

function doJSON(url) {
// Create a new script object
aObj = new JSONscriptRequest(url);
// Build the script tag
aObj.buildScriptTag();
// Execute (add) the script tag
aObj.addScriptTag();
}

function placeNameSearchCallback(jData) {
if (jData == null) {
document.getElementById(resdiv).innerHTML = 'Search failed for ' + placesearched;
return;
}
geonames = jData.geonames;
document.getElementById(resdiv).innerHTML = geonames.length + ' results for ' + placesearched;
if(geonames.length > 0) {
var pname=geonames[0].name;
if(null != geonames[0].adminName1) pname += (', '+geonames[0].adminName1);
var pcodegot="";
var latgot=geonames[0].lat;
var lnggot=geonames[0].lng;
var cntrygot=geonames[0].countryCode;
document.getElementById(resdiv).innerHTML += '<br/>Place: '+pname+'<br/>Country: '+cntrygot+'<br/>Latitude: ' + latgot + '<br/>Longitude: ' + lnggot;
populateResult('', pname, latgot, lnggot, cntrygot);
}
}

function doPlaceNameSearch(divname, placename) {
resdiv = divname;
placesearched = placename;
document.getElementById(divname).innerHTML = 'Searching ' + placename;
doJSON("http://ws.geonames.org/searchJSON?q="+placename+"&amp;maxRows=10"+'&callback=placeNameSearchCallback');
}

function latLngSearchCallback(jData) {
if (jData == null) {
document.getElementById(resdiv).innerHTML = 'Search failed for lat:' + latsearched + ' and lng:' + lngsearched;
return;
}
geonames = jData.geonames;
document.getElementById(resdiv).innerHTML = geonames.length + ' results for lat:' + latsearched + ' and lng:' + lngsearched;
if(geonames.length > 0) {
var pname=geonames[0].name;
if(null != geonames[0].adminName1) pname += (', '+geonames[0].adminName1);
var pcodegot="";
var latgot=geonames[0].lat;
var lnggot=geonames[0].lng;
var cntrygot=geonames[0].countryCode;
document.getElementById(resdiv).innerHTML += '<br/>Place: '+pname+'<br/>Country: '+cntrygot+'<br/>Latitude: ' + latgot + '<br/>Longitude: ' + lnggot;
populateResult('', pname, latgot, lnggot, cntrygot);
}
}

function doLatLngSearch(divname, lat, lng) {
resdiv = divname;
latsearched = lat;
lngsearched = lng;
document.getElementById(divname).innerHTML = 'Searching lat:' + lat + ' and lng:' + lng;
doJSON("http://ws.geonames.org/findNearbyPlaceNameJSON?lat="+lat+"&lng="+lng+'&callback=latLngSearchCallback');
}

// this function will be called by our JSON callback
// the parameter jData will contain an array with postalcode objects
function postalCodeSearchCallback(jData) {
if (jData == null) {
document.getElementById(resdiv).innerHTML = 'Search failed for '+pcodesearched+' in '+document.getElementById('postcodecountry').value;
return;
}
postalcodes = jData.postalCodes;
document.getElementById(resdiv).innerHTML = postalcodes.length + ' results for '+pcodesearched+' in '+document.getElementById('postcodecountry').value;
if(postalcodes.length > 0) {
for(iIndex=0; iIndex < postalcodes.length; iIndex++) {
var thisplace = postalcodes[iIndex];
var pname=thisplace.placeName;
if(null != thisplace.adminName1) pname += (', '+thisplace.adminName1);
var pcodegot=thisplace.postalCode;
var cntrygot=thisplace.countryCode;
var latgot=thisplace.lat;
var lnggot=thisplace.lng;
if(pcodegot == pcodesearched) break;
}
document.getElementById(resdiv).innerHTML += '<br/>Best match: '+pname+' ('+pcodegot+')<br/>Latitude:'+latgot+'<br/>Longitude:'+lnggot;
populateResult(pcodegot, pname, latgot, lnggot, cntrygot);
//alert("name:"+pname+" pcode:"+pcodegot+" lat:"+lat+" lng:"+lng);
}
}

function doPostalCodeSearch(divname, pcode, cntry) {
resdiv = divname;
pcodesearched = pcode;
document.getElementById(divname).innerHTML = 'Searching ' + pcode + ' in ' + cntry;
doJSON("http://ws.geonames.org/findNearbyPostalCodesJSON?postalcode="+pcode+"&country="+cntry+'&callback=postalCodeSearchCallback');
}


function createCountryCodeSelBox(divname) {
document.getElementById(divname).innerHTML = 'Getting country codes...';

document.getElementById(divname).innerHTML = 'Search in: <select id="postcodecountry" name="postcodecountry"><option value="AD">Andorra (AD100 - AD700)</option><option value="AS">American Samoa (96799 - 96799)</option><option value="AT">Austria (1010 - 9991)</option><option value="AU">Australia (0200 - 9726)</option><option value="BE">Belgium (1000 - 9992)</option><option value="BG">Bulgaria (1000 - 9974)</option><option value="CA">Canada (A0A - Y1A)</option><option value="CH">Switzerland (1000 - 9658)</option><option value="CZ">Czech Republic (100 00 - 798 62)</option><option value="DE">Germany (01067 - 99998)</option><option value="DK">Denmark (0800 - 9990)</option><option value="ES">Spain (01001 - 52080)</option><option value="FI">Finland (00002 - 99999)</option><option value="FO">Faroe Islands (100 - 970)</option><option value="FR">France (01000 - 98000)</option><option value="GB">United Kingdom (AB1 - ZE3)</option><option value="GL">Greenland (3900 - 3985)</option><option value="GP">Guadeloupe (97100 - 97180)</option><option value="GR">Greece (200 01 - 859 00)</option><option value="GU">Guam (96910 - 96932)</option><option value="GY">Guyana (97312 - 97360)</option><option value="HR">Croatia (10000 - 53296)</option><option value="HU">Hungary (1011 - 9985)</option><option value="IN">India (110001 - 855126)</option><option value="IS">Iceland (101 - 902)</option><option value="IT">Italy (00010 - 98168)</option><option value="LI">Liechtenstein (9485 - 9498)</option><option value="LK">Sri Lanka ( * - 96167)</option><option value="LU">Luxembourg (L-1009 - L-9999)</option><option value="MC">Monaco (98000 - 98000)</option><option value="MH">Marshall Islands (96960 - 96970)</option><option value="MP">Northern Mariana Islands (96950 - 96952)</option><option value="MQ">Martinique (97213 - 97290)</option><option value="MX">Mexico (01000 - 99998)</option><option value="NL">Netherlands (1000 - 9999)</option><option value="NO">Norway (0001 - 9991)</option><option value="NZ">New Zealand (1001 - 9758)</option><option value="PK">Pakistan (10010 - 97320)</option><option value="PL">Poland (00-001 - 99-440)</option><option value="PM">Saint Pierre and Miquelon (97501 - 97502)</option><option value="PR">Puerto Rico (00601 - 00988)</option><option value="PT">Portugal (1000-001 - 9980-999)</option><option value="RE">Reunion (97400 - 97490)</option><option value="SE">Sweden (10005 - 98499)</option><option value="SI">Slovenia (1000 - 9600)</option><option value="SK">Slovakia (010 01 - 992 01)</option><option value="SM">San Marino (47890 - 47899)</option><option value="TH">Thailand (10100 - 96220)</option><option value="TR">Turkey (01010 - 81910)</option><option value="US">United States (00210 - 99950)</option><option value="VA">Vatican (00120 - 00120)</option><option value="VI">U.S. Virgin Islands (00801 - 00851)</option><option value="YT">Mayotte (97600 - 97640)</option><option value="ZA">South Africa (0002 - 9992)</option></select>';

document.getElementById('postcodecountry').value = geonamesUserIpCountryCode;
}

function populateResult(postalcodeval, placenameval, latval, lngval, country) {
document.getElementById('postcode').value = postalcodeval;
document.getElementById('place').value = placenameval;
document.getElementById('lat').value = latval;
document.getElementById('lng').value = lngval;
document.getElementById('postcodecountry').value = country;
}
</script>
</head>
<body>
<div id="cntrydiv">
</div>
postal code: <input name="postcode" id="postcode" type="text" size="10"/>
<input type="button" value=">" onclick="srchres=doPostalCodeSearch('mapres', document.getElementById('postcode').value,document.getElementById('postcodecountry').value);"/>
<br/>
place: <input name="place" id="place" type="text" size="20"/> <input type="button" value=">" onclick="srchres=doPlaceNameSearch('mapres', document.getElementById('place').value);"/><br/>
lat: <input name="lat" id="lat" type="text" size="20"/> <input type="button" value=">" onclick="srchres=doLatLngSearch('mapres', document.getElementById('lat').value,document.getElementById('lng').value);"/><br/>
lng: <input name="lng" id="lng" type="text" size="20"/> <input type="button" value=">" onclick="srchres=doLatLngSearch('mapres', document.getElementById('lat').value,document.getElementById('lng').value);"/><br/>
<div id="mapres">
</div>
<script language="javascript">
createCountryCodeSelBox('cntrydiv');
</script>
</body>
</html>

No comments: