Arne Sommer


Geo::Postcodes::Ajax - A Tutorial in how to set up an Ajax service for the Geo::Postcodes::* modules.


This document uses the fictious country Utopia (with country code 'U2'), and the rest of this document will refer to the non-existent module Geo::Postcodes::U2.

The files described in this tutorial are available in the eg/ directory of the distribution.


Only the relevant parts of the html code in the file index.html is shown here:

 01 <script type="text/javascript" src="postcodecheck.js"></script>

Put this line somehere in the beginning of the file, so that the ajax code is available for the code.

 02 <form name='one' onSubmit="return false;">

The form does not need a name for the ajax code to work, but it does not hurt. The 'onSubmit'-code prevents the form from beeing submitted, as we would like to keep the html page - and let the ajax-code do changes in-line.

 03   Address:  <input name="address" value="Something or other"><br>

This is not used by the example, but is there to make it more real.

 04   Postcode: <input id="postcode_u2"

We have dropped naming this and the following element, as there are no program to receive the submitted form. Do give them a name-attribute if the form is meant for submission (and use the same name as the ID).

It does not matter what id we give these elements, byt they must be unique for the html document. (The naming structure used in this example makes it easy to add forms for several languages in the same html document.)

 05           onBlur='get_location("location_u2", "u2", "postcode_u2");'

When the postcode field looses the focus, the location is computed automatically by this call. The first argument is the ID of the location field, which is showing the updated location information. The second argument is the name of the country module, as used to build up the name of the cgi-program that the ajax-code calls; in this case 'location_u2.cgi'. The third argument is the ID of the postcode field, where the ajax-code gets hold of the postcode.

 06           onFocus='clear_it("location_u2");'

The location field is cleared whenever the poscode field gets the focus, as a visual hint that we are changing it - and the shown location would not be correct anyway.

 07           maxlength=4 size=4><br>

Utoipian postcodes are no longer than four characters, so we prevent the user from typing in longer strings.

 08   Location:  <span id="location_u2" style="color:red;"></span>

The style is just to make the location stand out.

 09 </form>


The file postcodecheck.js:

 01 function clear_it (dest)
 02 {
 03   document.getElementById(dest).innerHTML = "";
 04 }

 This function is used to clear the location field for us, when the postcode
 field gets the docus.

 05 function get_location (dest, country, code)

The 'dest' variable is the ID of the location field, where the postal location is written (and is the destination of the call). The 'country' variable is the name of the country class the postcode belongings to. The 'code' varaiable is the ID of the postcode field, where the postcode is taken from.

 06 {

 07   var postcode = document.getElementById(code).value;

Get the postcode.

 08   var httpreq  = getHTTPObject();

Ajax magic. This procedure is included in this file, but ius not shown here as it is exactly as in the ajax documentation. (See the file eg/postcodecheck.js in the distribution of the core module for the code.)

 09   var url      = "location_" + country + ".cgi?postcode=" + postcode;

Build up the url of the cgi program to call. This ensures that we can have programs for different countries, as it would not be a good idea to mix them all togetehr into one huge program.

 10"GET", url, true);

This will execute the cgi program.

 11   httpreq.onreadystatechange = function ()
 12   {
 13     if (httpreq.readyState == 4)
 14     {
 15       document.getElementById(dest).innerHTML = httpreq.responseText;

Put the returned text from the cgi call into the location element.

 16     }
 17     return true;
 18   }
 19   httpreq.send(null);
 20 }


The file location_u2.cgi:

 01 #! /usr/bin/perl
 02 use strict;
 03 use Geo::Postcodes::U2 0.30;
 04 use HTML::Entities ();
 05 use CGI ();

 06 print CGI::header(), CGI::start_html('-');

 07 if (CGI::param())
 08 {
 09   my $postcode = CGI::param('postcode');

Check that the program was given the '?postcode=xxxx' argument.

 10   if (!Geo::Postcodes::U2::legal($postcode))
 11   {
 12     print "<em>Illegal postcode</em>";
 13   }
 14   elsif (!Geo::Postcodes::U2::valid($postcode))
 15   {
 16     print "<em>Postcode not in use</em>";
 17   }

Give an error message that is as helpful as possible.

 18   else
 19   {
 20     print HTML::Entities::encode(Geo::Postcodes::U2::location_of($postcode));
 21   }

If the postcode is valid, we return the location. The encode call transforms any 8-bit (non us-ascii) characters (as the danish and norwegian 'æ', 'ø' and 'å') to html character codes, as they would otherwise get scrambled (as we chose to send the location string in hmtl instead of xml).

 22 }

 23 print CGI::end_html(), "\n";


  1. Copy the three files index.html, location_u2.cgi and postcodecheck.js (available in the eg/ directory of the distribution) to a directory on a web server, and make sure that execution of cgi-scrips are allowed there.

  2. Choose a country module to use (as 'U2' is fictious), e.g. Geo::Postcodes::NO. Install this module, if not already done. Rename the file location_u2.cgi to <location_no.cgi>.

  3. Swap all occurences of the string 'u2' in the two files index.html and location_u2.cgi with 'no'.

  4. Open the index file in a web browser.


There are several things that can be done to this ajax example:

  1. Use the CPAN module CGI::Ajax instead of my javascript code. This will probably also fix the compatibility problem with Internet Explorer.

  2. Speed it up considerably by setting it up as a mod_perl handler.


The tutorial perldoc Geo::Postcodes::Tutorial or man Geo::Postcodes::Tutorial, and the documentation for the individual country modules; e.g. perldoc Geo::Postcodes::NO or man Geo::Postcodes::NO.


Copyright (C) 2006 by Arne Sommer -

This library is free software; you can redistribute them and/or modify it under the same terms as Perl itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 163:

Non-ASCII character seen before =encoding in ''æ','. Assuming ISO8859-1