I can see lots of similarities between JavaScript and Perl. Both are languages that are often written by people with no real programming experience, just to get a job done - usually involving web sites. A lot of the code in each isn’t written from scratch, but starts by taking some other code that almost does what you want, and hacking it around until it does do what you want. And, as a result, a lot of the code that exists in both languages is really ugly, clumsy, and contains lots of special case code and lots of subtle bugs. Which the next person to adapt the script hacks around until it does what they want. And so on.

But beneath it all, both are actually very powerful languages, which can be well written, clean, expressive, and well factored.

And whilst I’m perfectly at home writing Perl like that, my JavaScript skills are still rather lacking.

So, I was playing around with Object Oriented JavaScript over the holidays. I found a good example at ChunkySoup, but I still wasn’t entirely happy with the results.

The code for the test page is still a little uglier, and more repetitive than I’d like. In particular, each link on the page still needs to explicitly set up its
own handling code for the image rollovers etc.:

<div id="link1"><a href="DSCB1428.jpg"
onmouseover="elements[0].handleMouseOver()"
onmouseout="elements[0].handleMouseOut()" onclick="return
elements[0].handleClick()">1</a></div>
<div id="link2"><a href="DSCN4337.jpg"
onmouseover="elements[1].handleMouseOver()"
onmouseout="elements[1].handleMouseOut()" onclick="return
elements[1].handleClick()">2</a></div>

<div id="link3"><a href="DSCN4358.jpg"
onmouseover="elements[2].handleMouseOver()"
onmouseout="elements[2].handleMouseOut()" onclick="return
elements[2].handleClick()">3</a></div>
<div id="link4"><a href="DSCN4373.jpg"
onmouseover="elements[3].handleMouseOver()"
onmouseout="elements[3].handleMouseOut()" onclick="return
elements[3].handleClick()">4</a></div>
<div id="link5"><a href="DSCN1509.jpg"
onmouseover="elements[4].handleMouseOver()"
onmouseout="elements[4].handleMouseOut()" onclick="return
elements[4].handleClick()">5</a></div>

And setting up the JavaScript that gets called onLoad is a little repititive too:


var elements = new Array();
var thumbnailID = "thumbnail"; // this is universal for the page
var emptyimg = "blank.gif"; // this is universal for the page
var photoID = "bigimage"; // this is universal for the page

function initpage() {
  elements[0] = new csnPhotoNavObject(new
csnPhotoObject(thumbnailID,emptyimg,"DSCN1428tn.jpg",photoID,"DSCN1428.jpg"));
  elements[1] = new csnPhotoNavObject(new
csnPhotoObject(thumbnailID,emptyimg,"DSCN4337tn.jpg",photoID,"DSCN4337.jpg"));
  elements[2] = new csnPhotoNavObject(new
csnPhotoObject(thumbnailID,emptyimg,"DSCN4358tn.jpg",photoID,"DSCN4358.jpg"));
  elements[3] = new csnPhotoNavObject(new
csnPhotoObject(thumbnailID,emptyimg,"DSCN4373tn.jpg",photoID,"DSCN4373.jpg"));
  elements[4] = new csnPhotoNavObject(new
csnPhotoObject(thumbnailID,emptyimg,"DSCN1509tn.jpg",photoID,"DSCN1509.jpg"));
}

So, I figured it should be possible to abstract some of that away further too. The JavaScript should be able to dynamically alter the DOM and set up all the event handles. Then the links could just be set up as:


<a id="link1" href="DSCN1428.jpg">1</a>
<a id="link2" href="DSCN4337.jpg">2</a>
<a id="link3" href="DSCN4358.jpg">3</a>
<a id="link4" href="DSCN4373.jpg">4</a>
<a id="link5" href="DSCN1509.jpg">5</a>

And at the start of the page, I’d just want to associate images with each link:


function initpage() {
  addImage("link1", "DSCN1428.jpg", "DSCN1428tn.jpg");
  addImage("link2", "DSCN4337.jpg", "DSCN4337tn.jpg");
  addImage("link3", "DSCN4358.jpg", "DSCN4358tn.jpg");
  addImage("link4", "DSCN4373.jpg", "DSCN4373tn.jpg");
  addImage("link5", "DSCN1509.jpg", "DSCN1509tn.jpg");
}

The addImage JavaScript would then find the image element with the id of the first parameter, associate an onclick() with the second element, and a rollover() with the third.

After a lot of playing around I ended up with a nice abstract JavaScript addImage function that does just this:


function addImage(id, img, thumb) {
  var pno = new csnPhotoNavObject(new csnPhotoObject("thumbnail","blank.gif",thumb,"bigimage",img));
  var img = document.getElementById(id);
  img.onmouseover = function() { pno.handleMouseOver(); };
  img.onmouseout  = function() { pno.handleMouseOut(); };
  img.onclick     = function() { return pno.handleClick(); };
}

What I don’t like about this though, is the need to set up the anonymous closures. (Of course, before this I didn’t even know I could actually do that in JavaScript!). I can’t see why I can’t just say:


  img.onmouseover = pno.handleMouseOver;
  img.onmouseout  = pno.handleMouseOut;

The onmouseover and onmouseout need to be assigned a function. But if I give them the foreign object function directly, then something later gets confused. Whereas if I give it an anonymous function that just calls that other function, everything works just fine.

I don’t know if I’m doing something wrong. Or if there’s some strange JavaScript language issues I don’t know about yet. Or what.

Anyone any suggestions?

Comments

Leave a Reply