Archive for the ‘Coding’ Category

Error message FAIL

August 18, 2008 - 12:10 am No Comments

The other day while on a bus in Brisbane, I witnessed a classic error message FAIL:

Modem FAILED


On a more serious note, error handling and the display of error messages in software development is an often discussed usability topic.  Errors occur for all sorts of reasons – user-generated, hardware failures, invalid data, and of course software bugs.  But how much do you let the end-user know that the software has failed?  Well, I believe it depends on the type of error, the impact of the error and who your audience is.

Clearly in this case letting the end-user (i.e. the general population driving by) know that the modem had failed was not useful at all.  What would an end-user be able to do with that knowledge?  Nothing.  They can’t fix it nor would they care to.  Showing them that message is pointless and makes the manufacturers of the mobile street display look stupid.  SOMEONE ought to know about the failure but in this case that someone is certainly not the end-user.

Another concern with display error messages such as the one I witnessed the other day is that it gives those malicious souls out there who thrive on breaking other people’s software a better idea of what will make the software break.

Personally, I’m a fan of generating more than one type of error message upon software failure and audience.  If the end-user is likely to be the general population (i.e. website users), then you should look at what caused the software to fail.  If you’re allowing users to generate errors by entering invalid data into a form, then you should probably let the user know that they entered some invalid data and that they should try entering something valid next time.  However, if you’ve coded restrictions into the software so that they should never be able to enter invalid data but somehow they do anyway, then you may be a victim of a hacker’s attack.  In this case, you do not want to admit that they have almost just broken your site because if you do you’ll only be encouraging them to try again and you may have just given them the extra information they needed to totally own your site.  Instead, the message you display to the end-user should be a friendly and generic/vague one, something along the lines of ‘Oops!  Your request returned no results.  Please try again later or contact support.’.  That way, the hacker will be none the wiser or at least they won’t think that their last input came so close to pulling your site down.  The same error should be logged somewhere on the system (event log, log file, database error log…) with a much more specific error message.  If it’s a critical error then perhaps it should even be emailed or sms’ed to an administrator automatically.

I guess the moral of the story is that it really doesn’t matter that you’ve handled all the potential errors in your code.  What really matters is how you’ve handled them, in particular, who you’ve alerted and what information you’ve given them.  Telling the world that the last input caused an integer overflow is probably not the best way to keep hackers out and users in!  If you’re a developer, think carefully about every line of code you write and if that line can raise an exception then make sure you know what to do when it happens.

Enabling & Disabling ASP.NET radio buttons using code-behind and JavaScript

June 19, 2008 - 12:35 am 2 Comments

I have just come across a strange problem when trying to disable some radio buttons on a web page using .NET and JavaScript. It seems to work well in Firefox but not IE, what a surprise!

The situation:

I have two sets of radio buttons – two RadioButtonList controls. The first set needs to control the second set – that is, when one of the radio buttons in the first set is selected, the other RadioButtonList control should be enabled, and when the other of the radio buttons in the first RadioButtonList control is selected, the second RadioButtonList control should be disabled.

In my code-behind, I had an event handler for the first RadioButtonList control to check if the selected index had changed. If so, check the value of the first RadioButtonList control and if it’s say equal to 1, then set the Enabled property of the second RadioButtonList control to false. Otherwise, set the Enabled property to true.

Obviously this alone doesn’t fix the problem unless the first RadioButtonList control is set to AutoPostBack = True. I needed some code on the client side to do this when while the user wasn’t posting the page back.

The code to disable some radio buttons is simple:

[-]?View Code JAVASCRIPT
1
2
3
4
var secondRadioButtons = document.form1.secondRadioButtonList;
for(var i=0; i<secondRadioButtons.length;i++ ){
    document.form1.secondRadioButtons[i].disabled = false;
}

The problem:

When you wire all this up, it works fine in Firefox… But does it work in IE? No, of course not. So why not? I found that when I first loaded the page, the radio buttons were enabled / disabled as they should have been. Clicking on the first set of radio buttons was disabling / enabling the second RadioButtonList control as it should have. But as soon as I posted the page back (the page had a button that submitted a form and displayed some results), the second RadioButtonList control was completely disabled and no matter which of the first radio buttons I selected, I couldn’t re-enable it. I stuck some debug code in my JavaScript only to find that it was running correctly and firing when it should. As far as I could tell, the JavaScript was setting disabled = false (as above) on all of the radio buttons in the second RadioButtonList control, but they were still disabled. Why!?

I took a look at the source code for the page and noticed something that I thought might have been causing the problem I was experiencing. Basically, browsers renders an asp:RadioButtonList control like this:

1
2
3
4
5
6
<span id="secondRadioButtonList">
<input id="secondRadioButtonList_0" name="secondRadioButtonList" value="1" type="radio" />
    <label for="secondRadioButtonList_0">First radio button</label>
<input id="secondRadioButtonList_1" name="secondRadioButtonList" value="2" type="radio" />
    <label for="secondRadioButtonList_1">Second radio button</label>
</span>

If you disable a RadioButtonList in your code-behind, the same asp:RadioButtonList control will be rendered like this:

1
2
3
4
5
6
7
8
<span id="secondRadioButtonList" disabled="disabled">
    <span disabled="disabled">
<input id="secondRadioButtonList_0" name="secondRadioButtonList" value="1" disabled="disabled" type="radio" />
        <label for="secondRadioButtonList_0">First radio button</label>
<input id="secondRadioButtonList_1" name="secondRadioButtonList" value="2" disabled="disabled" type="radio" />
        <label for="secondRadioButtonList_1">Second radio button</label>
    </span>
</span>

This is precisely why I don’t like asp controls – they look nice in the html that you write yet when they render out to the browser, they’re filled with extra stuff like these two spans.

Anyway, the problem were these spans – obviously even though I was setting ‘disabled = true’ on all the radio buttons inside my asp:RadioButtonList control, there were a couple of spans around the radio buttons that were also disabled causing my radio buttons to appear disabled regardless of their individual status.

The solution:

My solution to this was to simply remove the code-behind that I had written to enable or disable the RadioButtonList control on the server side. My JavaScript is all I really need.

However, if you desperately want or need to have some server-side code also disabling your radio buttons, you should do so like this:

1
secondRadioButtonList.InputAttributes.Add(”disabled”, “disabled”);

rather than

1
secondRadioButtonList.Enabled = false;

Code for GPS Tracking with Google Maps & AJAX

March 15, 2008 - 4:42 pm No Comments

Over the past few months, my article on GPS Tracking with Google Maps & AJAX has received many hits and attracted a multitude of comments requesting that the code for it be made available. I apologize for the delay but I’ve been away on holiday and far away from my trusted laptop. Now that things are somewhat back to normal and I can spend hour upon hour on my laptop again, here is the code that so many of you have asked for. I hope it makes sense and that it helps you all with what you’re trying to achieve. Obviously I haven’t posted the entire HTML and PHP coz it’s not all relevant to the GPS plotting but I hope what I have posted gives ya’ll a general idea on how to solve this particular problem. I’m sure there are many different ways to do this but this was just one way that I tried.Please feel free to ask questions and I’ll try to answer as best as I can! :)

...

Within the head section of the page that contains the gps tracking map:

[-]?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<script language="JavaScript">
 
function setTimer() {
   window.setTimeout("show_data();",5000);
}
 
function show_data(){
   //Append the id (just a simple count) to the requestURL
   var requestURL = "http://www.sitename.com/getGpsPoints.php";
   var count = document.getElementById("counter").value;
   count = parseInt(count, 10);
   var queries = "?id=" + count;
   var url = requestURL + queries;
 
   //Increment the hidden counter variable
   document.getElementById("counter").value = count+1; 
 
   var request = GXmlHttp.create();
   request.open("GET", url, true);
 
   request.onreadystatechange = function() {
      if (request.readyState == 4) {
         var xmlDoc = request.responseXML;
         var markers = xmlDoc.documentElement.getElementsByTagName("marker");
 
         for (var i = 0; i < markers.length; i++) {
            var point = new GPoint(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));
 
            // Draw the MapMarker
            var mapMarker = new GMarker(point);
            map.addOverlay(mapMarker);
         }
 
         // Recenter the map
         map.centerAtLatLng(point); 
      }
   }
 
   request.send(null);
 
   //Reset the timer so that the page keeps refreshing itself
   setTimer();
}
 
</script>

Within the body section of the page that contains the gps tracking map, right at the bottom just before the /body tag:

[-]?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
<script language="JavaScript">
   var query = window.location.pathname;
   if (query == "/mapping/gps-tracking-with-google-maps--ajax") {
      var map = new GMap(document.getElementById("map"));
      mapSetup();
      setTimer();
   }
</script>

Separate PHP script that queries your database to retrieve the GPS points to plot:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
    header ("content-type: text/xml");
 
    $link = mysql_connect ("localhost", "username", "password");
    if (!$link) {
        die('Could not connect: ' . mysql_error());
    }
 
    mysql_select_db ("dbname");
 
    //If no search string is passed, then we can't search
    if(empty($_GET["id"])) {
        echo " ";
    } else {
        //Remove whitespace from beginning x%x% end of passed search.
        $search = trim($_GET["id"]);
 
        //Query the DB and store the result in a variable
        $query = mysql_query("SELECT * FROM gps WHERE id=".$search);
 
        //If no rows are found...
        if(mysql_num_rows($query) == 0) {
            echo " ";
        } else {
            //Stick the returned rows into a handy array for easy use
            $row = mysql_fetch_array($query) or die(mysql_error()); 
 
            //Write out XML using values returned by the query
            echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><markers><marker lat=\"".$row["lat"]."\" lng=\"".$row["lng"]."\" /></markers>";
        }
    }
 
    mysql_close($link);
?>

Textpattern plugins and Facebook apps

August 12, 2007 - 5:37 pm 1 Comment

Since Chris and I have become addicted to Facebook, we decided it would be cool to have a plugin for our respective blogging engines (Chris uses WordPress, I use Textpattern) that would update our Facebook accounts’ mini-feeds when we posted something on our blogs. Thus we both set off on our epic missions to create Facebook applications and WordPress / Textpattern plugins that would support this behaviour.

Here I’ll relate my experience with my Textpattern plugin. I’ll leave Chris to talk about his experience with WordPress.

So yeah, basically, my experience was a nightmare.

This was my first attempt ever at writing a Textpattern plugin so I am by no means an expert at this. It took me a while to figure out how to compile my php code so that I could deploy it to my Textpattern instance on my web server. Then it took me another while to figure out how to hook into Textpattern ‘events’. I must say, the documentation for this is really poor and I found myself trawling through the Textpattern source to figure out what functions did what. Not pretty. The best (and only) sites I found that helped me somewhat were this article on threshold state and this Textpattern source repository.

When I finally figured out how to call the ‘register_callback’ functions and that I had to use ‘article’ as the event I wanted to register my own events against, I was able to get stuck into it.

My next challenge was how to add a checkbox to the ‘write’ tab of the admin screens. I wanted a checkbox that when checked, would essentially call my code to notify my facebook account of my post. If it wasn’t checked, it wouldn’t notify facebook. However, adding a checkbox and positioning it where ever I want in the flow of elements on the page was NOT an easy task. Below is a sample of the code I had to use to get this to work:

1
2
3
4
5
6
7
8
9
10
function mdt_event_insert_checkbox($buffer) {
   $fb_notify = graf('<small><label for="notify_facebook">'.
      checkbox("notify_facebook", '1', '1', '', 'notify_facebook').
      'Notify Facebook?</label>&nbsp;');
 
   $find = '<input type="submit"';
   $replace = $fb_notify.$find;
 
   return str_replace($find, $replace, $buffer);
}

NASTY! I had to find the ‘Save’ button, then replace the HTML with my new HTML that includes the checkbox. OMG.

Anyway, I finally got that working (see screenshot below).

Next I needed to grab the title of the new post, the friendly-url to the article on my site and the excerpt of the new article. This again was no easy task. The following code seems to do the trick:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function current_url() {
   return 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}
 
function get_latest_post() {
   include_once txpath.'/publish/taghandlers.php';
 
   // get the latest article posted
   $rs = safe_row("ID, Title, Excerpt", 'textpattern', "1=1 ORDER BY LastMod DESC LIMIT 0,1");
 
   $title = ' has blogged: ' . urlencode(stripslashes(urldecode('<a href="' . permlinkurl_id($rs['ID']) . '">'))) . substr($rs['Title'], 0, 45) . '</a>';
   $msg = substr($rs['Excerpt'], 0, 180);
   $url = current_url();
 
   if (strtolower($step) == "publish") {
   $url = $url . "?event=article";
 
   } elseif (strtolower($step) == "edit") {
      $url = $url . "?event=articlex%x%step=editx%x%ID=" . $rs['ID'];
   }
}

So now the tricky part – how to connect to Facebook, log in as myself and call the Facebook API function that updates my ‘mini-feed’ with some content. I first attempted this by embedding the Facebook API into the Textpattern plugin so that the integration would be completely seamless. This, however, was difficult on many levels. First of all, I couldn’t get the Facebook API to compile into my Textpattern plugin. The php compiler would tell me that certain server variables weren’t defined, etc etc. I did iron out all those error messages and warnings eventually though and finally got the code to compile. However, I later realized that this was never going to be a feasible solution because in order for this to work, my Facebook developers’ API key and secret key would need to be hard-coded into the Textpattern plugin and if I were ever to make this Textpattern plugin public (which I intend to do), I would be sharing my API and secret keys, something I don’t necessarily want to do. Doh! So I had to change my thinking somewhat.

The solution to this was to basically write the Facebook part of the plugin as a totally separate web application and have the Textpattern plugin call this web app, passing through to it the title, url and excerpt in the form of a query string. This method lets the Facebook web application handle all the Facebook functionality (logging in and authenticating, remembering you once you’re logged in, calling the appropriate API functions, etc etc) and the Textpattern plugin basically doesn’t need to know anything about Facebook.

What a mission.

However, it all seems to be working now and I’ve used it once already. Those of you who are on Facebook and have added me as a friend will be able to see little posts on my mini-feed (on my profile page) saying “Annie has blogged…” with a link through to this article. Very cool :) When I am comfortable that things are working as intended and I tidy things up enough to make my Textpattern plugin publicly available, I’ll put it up on my here somewhere for people to grab.

Phew

An example Prolog program

April 9, 2007 - 3:27 pm No Comments

Way back at university (like, 3 years ago), I did a couple of papers that covered Prolog. Unlike most procedural top-down programming languages that us software developers are used to using, Prolog is a logic programming language. A typical Prolog program consists of facts, rules and queries. Although I don’t have a Prolog interpreter on my machine at the moment, we used SICStus Prolog on NetBSD at university.

Speaking of SICStus Prolog – apparently it now has integrated support for developing web based applications using a new module called PrologBeans. Using this module, SICStus Prolog can be called from a Java-based application server. Awesome!!

Anyway, for those interested in what Prolog looks like, below is an old assignment that I submitted for a course on Artificial Intelligence. If I remember correctly, the assignment was for us to simulate a robot cleaning dishes. We were asked to implement all the facts and rules, in Prolog, for such a robot. When the robot encounters dirty dishes, it is supposed to clean them. If it encounters wet dishes, it is meant to dry them.

When the program is run with an initial state, the output is a list of steps that the robot would take according to the prolog rules written in the program.

Below is the code for this program.



%-*-prolog-*-
% operator(-Op, -Pre, -Del, -Add)
% operator definitions
% Pre is a list of state preconditions
% After Op is applied
% Del gets deleted from state
% Add gets added to state


operator(putDirtyDishFromBench(X), pre: [dirty(X), at(X,bench)], del: [at(X,bench)], add: [at(X,sink)]).


operator(putDirtyDishFromDrainer(X), pre: [dirty(X), at(X,drainer)], del: [at(X,drainer)], add: [at(X,sink)]).


operator(putDryDishInSink(X), pre: [dry(X), at(X,drainer)], del: [dry(X), at(X,drainer)], add: [cleanButWet(X), at(X,sink)]).


operator(putDryDishInCupboardFromDrainer(X), pre: [dry(X), at(X,drainer)], del: [at(X,drainer)], add: [at(X,cupboard)]).


operator(putDryDishInCupboardFromBench(X), pre: [dry(X), at(X,bench)], del: [at(X,bench)], add: [at(X,cupboard)]).


operator(putCleanButWetDishFromSink(X), pre: [cleanButWet(X), at(X,sink)], del: [at(X,sink)], add: [at(X,drainer)]).


operator(putCleanButWetDishFromBench(X), pre: [cleanButWet(X), at(X,bench)], del: [at(X,bench)], add: [at(X,drainer)]).


operator(pickUpTool(X,Y), pre: [holding(X)], del: [holding(X)], add: [holding(Y)]).


operator(processInSink(X), pre: [dirty(X), at(X, sink), holding(dishbrush)], del: [dirty(X)], add: [cleanButWet(X)]).


operator(processInDrainer(X), pre: [cleanButWet(X), at(X, drainer), holding(teatowel)], del: [cleanButWet(X)], add: [dry(X)]).


% instantiate(?Operator)
% Makes Operator ground (including its pre, del and add lists)


instantiate(putDirtyDishFromBench(X)) :- dish(X).
instantiate(putDirtyDishFromDrainer(X)) :- dish(X).
instantiate(putDryDishInSink(X)) :- dish(X).
instantiate(putDryDishInCupboardFromDrainer(X)) :- dish(X).
instantiate(putDryDishInCupboardFromBench(X)) :- dish(X).
instantiate(putCleanButWetDishFromSink(X)) :- dish(X).
instantiate(putCleanButWetDishFromBench(X)) :- dish(X).
instantiate(pickUpTool(X,Y)) :- tool(X), tool(Y), X\==Y.
instantiate(processInSink(X)) :- dish(X).
instantiate(processInDrainer(X)) :- dish(X).


% dish(?Object)
% Object is a dish
dish(dish1).
dish(dish2).
dish(dish3).
dish(dish4).
dish(dish5).


% tool(?Object)
% Object is a tool
tool(dishbrush).
tool(teatowel).
tool(nothing).


% location(?Object)
% Object is a location
location(bench).
location(sink).
location(drainer).
location(cupboard).

An example of how to use this prolog program:


TESTDISHES1:


testdishes1 :- goal_stack_plan([at(dish1, bench), dirty(dish1), holding(nothing)], [at(dish1, cupboard), dry(dish1)], Plan, FinalState, []).

And the plan found by the program when TESTDISHES1 is run:


PLAN FOUND FOR TESTDISHES1:


====================================
Plan to achieve [at(dish1,cupboard),dry(dish1)]
Starting at [at(dish1,bench),dirty(dish1),holding(nothing)] putDirtyDishFromBench(dish1) pickUpTool(nothing,teatowel) pickUpTool(teatowel,dishbrush) processInSink(dish1) putCleanButWetDishFromSink(dish1) pickUpTool(dishbrush,teatowel) processInDrainer(dish1) putDryDishInCupboardFromDrainer(dish1)
Ending in state: [holding(teatowel),dry(dish1),at(dish1,cupboard)]
====================================
yes | ?-

If this looks like something you might wanna have a go with, try looking at this tutorial.

I’ve been quoted… about VB.NET

April 3, 2007 - 5:06 am 1 Comment

This morning one of my fellow developers sent me a link to this article on Rowan Simpson’s (formerly the Software Development team lead at Trade Me, now heading up the Trade Me Products team) blog.

How exciting!! I’m famous!! :)

But seriously, writing code in VB.NET just frustrates me and that email I sent our dev group was one of a few instances (perhaps one of the more curious ones) where VB.NET just doesn’t seem to rate next to C#. I mean, the recent introduction of the using statement… come on! C# has had this for aaaaaaaaaaaages. And the fact that operator overloading has only JUST been introduced to VB.NET – again, C# has has this for ages. And language support for unsigned types (UInteger, ULong, and UShort) has again, only just been introduced in .NET 2 for dear ol’ VB.NET. I’m sure I was using unsigned types about 8 years ago at university (ok, so that might have been in Java, but still?!!?).

However, what frustrates me the most about VB.NET is probably the fact that I feel like I’m writing an essay in English when coding… Brackets are good! Semi-colons are good! And sticking to the OOP terminology that many programmers out there have learnt to love over the years must be good!

Oh well, better get back to my screeds of VB.NET – we have an early deploy tomorrow morning wooohoooo!!!

IE Conditional CSS Comments

March 28, 2007 - 6:58 pm No Comments

I know this has blogged about many times over, but I recently came across this really handy CSS hack (yes, I think this qualifies as a hack) specifically for styling sites in IE.

Basically, only Internet Explorer (5 and onwards) on Windows can read these ‘comments’. Therefore, any CSS styles written within them are only interpreted and applied by IE. And better yet – you can write ‘if’ statements within these comments so that your CSS styles are only applied to particular versions of IE.

Pretty handy huh?

Here’s a quick example:



<!--[if gt IE 5]> table#content { width: 100%; !important; }
<![endif]-->

Here are the different ‘if’ operators:


<!--[if IE]> This comment applies to all versions of IE from 5 to 7.
<![endif]-->


<!--[if IE 6]> This comment applies to version 6 of IE.
<![endif]-->


<!--[if lt IE 6]> This comment applies to versions of IE less than version 6.
<![endif]-->


<!--[if lte IE 6]> This comment applies to versions of IE less than or equal to version 6.
<![endif]-->


<!--[if gt IE 6]> This comment applies to versions of IE greater than version 6.
<![endif]-->


<!--[if gte IE 6]> This comment applies to versions of IE greater than or equal to version 6.
<![endif]-->

There are a couple of gotchas you should be aware of before you use this great little hack.

  • Only IE on Windows will interpret these comments. Read: this hack will not work for IE on a Mac. If you need to style something for IE on a Mac, think about checking for the user agent using whatever script you’re programming in, if you’re using one at all, and including styles based on that instead.
  • Conditional statements just use the normal HTML comments and therefore can only be used in HTML pages. Read: this hack won’t work when written in a CSS file.

    I know the pain web designers and developers go through trying to get their sites to look the same in all browsers (trust me, I know!) so it might be quite tempting to use this hack all over your code. But keep in mind that this is just a hack and you should try to find more standards compliant ways of styling your sites using CSS that works well in all browsers (or at least that are important to you).

Send MSN messages programmatically

March 18, 2007 - 5:07 pm No Comments
I’m sure there is a need out there to send messages to MSN programmatically. So I’m gonna find out how plausible it is and whether I can find a use for it myself :)

I recently came across a simple PHP class for sending MSN messages called sendMsg written by FanaticLive. Below is a form that uses this class to send a message from the ‘sender’ to the ‘recipient’ that you enter.

In order for this process to work, the specified recipient must have the sender in their MSN contact list (approved or not) and the recipient must be online. If you don’t want to enter your email and password into this form (and I totally understand if you don’t) then try using the test user. Only thing is you’ll have to temporarily add the test user – msn.tester@mindtrip.co.nz – to your contact list on MSN.

So go on, try it… you know you want to :)

Now I have to come up with a cool idea for why I might actually want to programmatically send MSN messages… hmm….
Update: Looks like some cunning spammers have decided to use this form to send spam out, not that it’s working. So HA spammers, take that. I’ve logged all your IP addresses and the fact that none of your spam got through. Anyway, I’m not impressed, spammers suck. So thanks to them, I’m taking this form down. If anyone wants to see the code for it, just leave me a message and I’ll send it to you.

GPS Tracking with Google Maps & AJAX

August 25, 2005 - 10:45 am 17 Comments

“Real-Time” tracking of GPS locations on a web site is actually quite hard to achieve. In order to see a dot moving around on an online map, the page would need to be constantly refreshing itself. The refresh would initiate a request back to the server where server-side code would grab the new coordinates of the GPS unit out of a database, redraw the map with a dot on it, and send the whole image back to the user’s browser. Whether the refreshing is caused by the page itself or a hidden iframe on the page somewhere, a full roundtrip to the server every few seconds would soon become super annoying, even if it did mean the user got to see a neat dot ‘seemingly’ moving around on a map.

So how do we get around this? Ideally, we would just want to redraw the ‘dot’, not the whole map and definitely not the whole page. Can this be done? Yes! How? Using AJAX.

No, AJAX isn’t a cleaning product. And believe it or not it isn’t even a new technology. AJAX stands for “Asynchronous JavaScript and XML” and is described by WikiPedia as:

A term describing a web development technique for creating interactive web applications using a combination of:

*HTML (or XHTML) and CSS for presenting information *The Document Object Model manipulated through JavaScript to dynamically display and interact with the information presented *The XMLHttpRequest object to exchange data asynchronously with the web server. (XML is commonly used, although any text format will work, including preformatted HTML, plain text, and JSON)

AJAX essentially allows calls to be made to the server without the user ‘noticing’. The call itself does not cause the page to refresh at all. The developer can make the page do whatever they wish with the response from the server. Most often developers will manipulate the page’s appearance using JavaScript, the DOM and CSS.

So how can AJAX be applied to online mapping? Well, using AJAX we can make ‘asynchronous’ calls to some server-side logic that can grab the newest position of the GPS unit out of a database. The coordinates can then be passed back to our page in an XML string. Client-side JavaScript in our page will interpret the XML and create a ‘img’ element that looks like a dot, using CSS to place it at the correct pixel location on the map.

Since I don’t have a real GPS unit to test this with, I have populated a database table with some fake GPS coordinates. To date I’ve tried this using MapInfo’s MapXtreme 2004 (ASP.NET in C#, plenty of JavaScript, CSS and a horrible little Access DB) which worked a treat. I’ve also tried it using a Google Map which you can see below. (If the dot has stopped moving, refresh the page using Ctrl+F5 – I only have about 10 points in my fake GPS unit db table.)

 

If anyone wants to see my code, please see this article.