Monday, May 23, 2005

Google's fusion initiative...

So Google have finally announced what we've all known for sometime, that they are attempting to pull together all their disparate "products" under one roof in what they are describing as the "fusion initiative". A fancy name for what is basically making Google into a portal.

I suppose that it is good they are taking their time over this, but so far I am not impressed with the results. My problem is partly caused by their tactic of placing all new features into overly long Betas. I now have a GMail account, which I monitor through the Windows notifier and the Firefox plugin, depending on where I am. I can now also monitor this through their new "fusion" homepage, but only if I remember to go there. It doesn't help that I cannot seem to reset the Google Homepage button in the Google IE Toolbar to point to anything except the homepage.

When setting up my personlised Google homepage it didn't pick up any of my settings from my personlised Google News page that I set up the other week, very annoying. Finally, if I try to load my personlised Google homepage from the domain I get re-routed to the domain. All very patchy.

In each case Google has launched something that I find incredibly useful, but I have to remember how to access each of these things. Perform the special mouse gesture while standing on one leg....okay, not quite that bad, but you get the idea.

I think the "fusion initiative" is fantastic and long overdue, and completely predictable. But they have their work cut out for them to pull back together all the different initiatives launched to date into one cohesive whole. I wish them luck.

Saturday, May 21, 2005

Space geekery...

I am a geek in many ways, I am a computer geek, a Sci-Fi geek, a film geek. I have been this way for many years, but longer than all of these I have been a space geek. The thought of everything that is out there, how much we don't know, how much we do and how we found it out always amazes me.

One of the best things about being a space geek is that it sits quite happily with my other geek obsessions. Space exploration is a very technical endeavor and the Internet has been a boon to us space geeks for getting all the latest information, even seeing space exploration as it happens.

People in my office know that if there is a big space event happening during working hours they will probably be able to stand behind me and watch it. We all saw SpaceShipOne's historic flights into space, all three of them. We sat around and watched as the Genesis probe crashed into the desert.

Such visual images of space exploration, whether good or bad, still captivate me, they always have. I remember the first time I saw Viking images from the surface of Mars, especially the ones where you could see Martian frost! I doubt many people could forget the pictures of Earth rise from the surface of the moon. These images still manage to give me butterflies.

The most recent one is perhaps the most geeky one to date. Few people that I have shown this too get quite why it makes me geek out, and it is hard to explain. But I figured that the people who read this blog would instinctively get it. Over the last few months Nasa seems to have been on a Mars hardware hunt. Spotting various Mars landers from orbit, they think they have spotted the doomed Mars Polar Lander.

Cool though those images are, it is another one that amazed me. It is the first clear(ish) picture of a man made probe in orbit of another planet. It is a picture of the Mars Odyssey probe taken from the Mars Global Surveyor. It's not a great image, but damn does it put a big smile on my face.


Monday, May 16, 2005

I am seeing our code through new eyes... fact they are the eyes of our new developer who started today. I had forgotten how educational it is to listen to someone completely new talk about your code. Someone who has no emotional attachment to it. Someone who has not put blood, sweat and tears into it (honestly each of those at least once over the last 5 years). Someone who obviously doesn't care as much as me....sorry getting carried away there.

But it is true that if you spend as long as we have creating something you do begin to get attached to it. I was in an all day meeting with clients last week, we took them out for lunch. On the walk to Franco's (wonderful pasta place near here) she apologised to me, saying that she knew she could be "picky and awkward". After a moments reflection on this I apologised back to her about being too defensive, remarking that the system she had been commenting on was something that I often though of as my "baby" for want of a better term.

Since starting here in mid 2000 I have seen the code grow from a mere 8 classes to the behemoth that it is now. I lived through the delivery pains of the "Mango" version. The joys of seeing the "Papaya" version in all its' refactored glory. The long nights coaxing the first Swing management console "Guava" out of the door and the horror of starting again from scratch for the "Tangerine" version.

It is often said that most software is no good till at least the third version. Depending on how you count we are there now, and looking back I am amazed and very happy at where we are with the software. I could sit back and bask in the shining light of Open Harmonise.....thank God we have a new developer to point out its' problems and where it could be better.

Wednesday, May 11, 2005

Lessons Learned #5: Cross-browser Javascript and CSS

Unlike previous "Lessons Learned" articles this one will describe my current project and list some of the little annoyances that I have had to solve. I mentioned in my last post that this project was to build a web based administration system for Open Harmonise that mirrored the Java Swing version as closely as possible. Obviously the Java Swing version was pretty dynamic in nature so this project was going to require a lot of Javascript and funky CSS which would have to work in both of our target browsers (Internet Explorer and Mozilla/Firefox).

I have to admit, that when starting out I really did not think the project would be successful. The Java Swing version of the client includes many custom components to allow the management of complex information. The layout includes Outlook style tabs, a highly customised table view and a tabbed form that is built on the fly from data definitions. These form elements are not simple either, for example a text field is made up of the following components;

  • text of the field name.
  • button to open a help text window.
  • valid/invalid icon (updated in real time, also impacting a similar icon on the tab).
  • the text entry field itself.
  • a counter which counts down how many characters you have left based on the data definition. This counter turns amber when you get close to the maximum length and red when you go over it.
That is just one of the simple types of form field, we also support number (with or without floating point), date (with or without time) and boolean. Then there are the complex types including vocabulary lookups, relationships to other resources in the CMS and finally compound properties (nested fields like address). Each field in the form can have a min and max number of occurrences and therefore needs to have plus and minus buttons for adding and removing extra fields.

I have ranted on a bit, but you can see why I was a little worried about building this and supporting it in html's request response model. But this was my task so I forged on. Overall it has been nice to discover that building these types of web application is a lot easier now than in days gone by. The latest versions of IE and Firefox interoperate quite well, but there have been many points where I have had to stop and scratch my head for a while. The following are my experiences and solutions, if for any of these you know that I am just being stupid and that there are much easier ways of doing these then please leave a comment.

1) Dynamically adding dynamic content.


There are several approaches to adding content to a html page, the easiest of these is to append to the "innerHTML" attribute of an element. In Internet Explorer this doesn't work for forms as any information people have already input to form elements will be lost. Instead you must construct your new elements as html DOM objects and use the "appendChild" method. While this works fine for simple things life becomes complex in Internet Explorer with some special (for want of another word) attributes. These attributes include;

  • name on form elements
  • value on form elements
  • class
  • name on iframes
  • all Javascript event handlers such as onchange and onclick
The problem with these is that Internet Explorer treats them as plain DOM attributes and does not do the special processing that each requires. The worst offender for these is the Javascript event handlers, they are not parsed by the Javascript engine so they are not actually set as listeners to the events.


For most of these it is a simple mater of using the relevant Javascript attribute for the object, such as doing;'NAME' ;

instead of;

element.setAttribute('name', 'NAME');

However things get a little more complex where the Javascript event handlers are concerned. For these you must again set the relevant Javascript attribute for the object, but you must set it to the method pointer rather than a string. E.g.

inputElement.onchange = elementChangeMethod;

instead of;

inputElement.setAttribute('onchange', 'elementChangeMethod(PARAM1, PARAM2)');

One thing that should be obvious from this is that when having to use the method pointer you cannot provide any parameters to the method. When mocking the interface up in static HTML I was mostly passing "this" into these methods, which is still accessible, but not as a parameter, from a method called using the method pointer. So the rule is to remember that if you are going have to insert a new version of some html that has Javascript event attributes on it, ensure that those methods only deal with the "this" context object and use no other parameters.

2) & in links and window.location


Because this is a very dynamic html web application there are many points where I use Javascript to either load a page into a frame/main window or insert an IFRAME in the page. Something that foxed me for quite a while was the fact that "window.location.replace" was working in IE but not in Firefox (and that Firefox was not showing any errors), I would just get a blank page.


The solution was embarrassingly simple, but not obvious at all. IE allows you to put "& amp" into the URL for "window.location.replace" and Firefox does not. Mostly this is hard to spot as Firefox doesn't complain, it just shows a blank page.

3) Submitting a form and using window.location


I replicated the Java Swing toolbar as a series of buttons in a frame across the top of the page. These submit various forms in other frames to accomplish their tasks. These forms may be visible to the user, for example the "Save Resource" button submits the main visible data entry form. Some are not, the "New Resource" button submits a hidden form. To keep life simple, these forms submit to a page that performs the action and then I redirect the frame back to the previous page which is now in a new state because of the action. However the changes were not happening.


After quite a while of fiddling it appeared that the "window.location.replace" was happening before the "form.submit" commands in the Javascript, even though they were in the other order in the source. The evil hacky solution was to put the "window.location.replace" into a delay of a second to allow the "form.submit" to happen, truly horrible but it does work.

4) Comparing the value of a html DOM attribute to a string


In many places I am allowing the user to move values from a list into a "select" field. The field has the "multiple" attribute set to "true" so that it appears as a list instead of a drop down, but I want everything in it to be submitted. So I wrote a small Javascript function to find all the elements with a tag name of "SELECT" and a "multiple" attribute with a value of "true". This is a very simple DOM navigating script, so imagine my surprise when it found the elements with the right name but would never match on the attribute value.


The html DOM method "getAttribute('ATT_NAME')" returns a "DOMString" object not a "String" object, therefore you cannot do a simple comparison. In the end I did the following;

var attrubuteValue = element.getAttribute('ATT_NAME');
var sValue = '' + attrubuteValue;
if(sValue == 'STRING_TO_COMPARE') {

I am guessing that I could have compared against the DOMString's "toString()" method, but I was a bit fecked off by the time I thought of that and so haven't gone back in to fix it. But you get the idea. Again, no warnings or errors to be seen.

5) Dynamically inserted IFrame not findable by name


Inserting an "IFRAME" element using Javascript works fine, until you come to try and find it by its' name in the "frames[]" array. The name doesn't appear to be available.


Another bit of a hack, I found it by comparing the location instead.


So those were the most annoying issues, and the ones that I can remember while writing this. Although these did cause me major headaches, again I must say that the process of building this site has not been anywhere near as bad as I thought it would be. There is a resurgence in the art of building web "applications" instead of websites. Most of this has been the interest surrounding Google's efforts in this area and the fantastic results that can be gained from using asynchronous calls with XMLHttpRequest objects. Of course I would have loved to build this site in that way, but it was a bit too much of a risk given the time and budget allowed. Still I did create the layout structure to allow us to begin replacing various parts in this way over time.

Finally, please to do let me know if I am wrong in anything I have said here. I really do want to find the best way of fixing these issues, and I must thank the Mozilla/Firefox teams for supporting all the non-standard IE ways of doing things so that I could build truly cross-browser Javascript.