Onclick JavaScript parameters

5 August 2004

23 comments

A Blue Perspective: Onclick JavaScript parameters

Unobtrusive JavaScript requires that you don't place JavaScript calls directly in HTML code. So, when you want to place an onclick handler on an anchor tag, instead of typing:

<a id="link" href="page.htm" onclick="popUp();">link</a>

You should instead assign the handler via the DOM:

document.getElementById("link").onclick = popUp;

This is all great and keeps my code nice and clean, but what happens when I want to supply arguments to the method?

If I have a whole series of pop-up images and I need to know their dimensions, how do I get these to the pop-up function? I could hardcode them into the JavaScript method – create a list of variables corresponding to the images' dimensions and somehow find the right one when the method is invoked – but this means there's a double maintenance issue when I change/remove/add any of the links. Another option is to include the dimensions as part of the HTML code, as one of the link's attributes, like, say ... "rel"? But there's no attribute that really matches the information we're looking for, and misusing an attribute would displace the information that's actually meant to go in there. The solution I came up with for my portfolio was to place the dimensions inside the href.

If we treat the dimensions like a piece of form data we can encode them much as they would be in a URL. In my case, I referenced image files – JPEGs and GIFs – that, without JavaScript, would display normally as images. However, the URL also includes dimensions encoded like CGI parameters:

<a href="example.jpg?js_width=400&js_height=300">link</a>

When an onclick handler is added to that link, the method called when the link is clicked has access to the link's href attribute using this.href. To read the parameters, it's just a simple matter of parsing the parameter string:

var parameterString = this.href.replace(/.*\?(.*)/, "$1");
var parameterTokens = parameterString.split("&");
var parameterList = new Array();

for (i = 0; i < parameterTokens.length; i++)
{
var parameterName = parameterTokens[i].replace(/(.*)=.*/, "$1");
var parameterValue = parameterTokens[i].replace(/.*=(.*)/, "$1");

parameterList[parameterName] = parameterValue;
}

theWidth = parameterList("js_width");

Although there's still an uncomfortable dependence on the HTML code, overall I find this to be a much cleaner and easier way to maintain any variables that need to be used by onclick methods for anchor tags.

Categories

, , ,

Comments

  1. 1/23

    bryan commented on 5 August 2004 @ 02:57

    I like the idea, but some "at-a-glance" examples would be great.

  2. 2/23

    Jennifer Grucza commented on 5 August 2004 @ 05:42

    I don't know, I'd be inclined just to leave the onclick attributes in the HTML. Sometimes I think it's ok to go with simplicity over "correctness".

  3. 3/23

    Jennifer Grucza commented on 5 August 2004 @ 05:44

    Good solution, though, for those that are concerned with correctness. :)

  4. 4/23

    TaQ commented on 5 August 2004 @ 06:03

    Seems that to map a function with parameters you need to map a function with no parameters calling that other one. I was checking some stuff here and seems that the object model really need a pointer to a no parameters function there.
    As Jennifer says, simplicity can be better on this case. :-)

  5. 5/23

    Jonathan Snook commented on 5 August 2004 @ 06:38

    To lessen the reliance on HTML, you could always give the link an id and then using a javascript array, match the id to an entry in the array. Not sure that one method is any better or worse than the other. :)

  6. 6/23

    TaQ commented on 5 August 2004 @ 07:25

    If you want to deal with img dimensions:

    HTML code:
    <img src="x.png" onclick="getattrs(this);">

    JavaScript code:
    function getattrs(e){
    alert("width:"+e.width+" height:"+e.height);
    }

    Inside the JavaScript code you can fire a pop-up based on those values.

  7. 7/23

    Micah Goulart commented on 5 August 2004 @ 07:37

    Another thing you could do is use inline properties such as <a href="example.jpg" _width="100" _height="200"> etc

    I like your method though. It's Dreamweaver-friendly and still works if someone has JavaScript disabled.

    I've worked a lot on doing JavaScript without inline scripting. I even created a custom library that loads up objects based on ID on window.onload so <div id="myDiv"> become _myDiv for scripting. and xHtml.myDiv = { onclick : alert } gets applied to it onload.

    For a practical example see http://www.ingenial.com/applied/GalleryStats/

  8. 8/23

    The Man in Blue commented on 5 August 2004 @ 12:37

    Jonathan: JavaScript variables are what I mentioned in the article, and what I wanted to avoid. When you add a pop-up to the HTML, you also then have to edit the JavaScript, and ensure that the IDs match, etc.

    TaQ: the img tag wouldn't exist in the HTML code, as the link goes to the larger image. Hence, you wouldn't be able to get its dimensions.

    Micah: inserting custom attributes would invalidate the code. If you were supplying your own DTD it'd be OK, but not for XHTML.

  9. 9/23

    Simon proctor commented on 5 August 2004 @ 19:30

    A few months ago I was working on a site redesign, mostly the back end scripts but I also wrote a chunk of the Javascript. I used this trick then for certain user requested pop ups.

    The link below has a virtual tour link that demonstrates it.

    http://www.s1homes.com/2004070709383238.html

  10. 10/23

    Richard@Home commented on 5 August 2004 @ 21:41

    How about this alternative?
    http://richardathome.no-ip.com/examples/img_popup/

    View the source - its pretty straight forward.

    My method means you don't have to hard code any image dimentions.

  11. 11/23

    Unearthed Ruminator commented on 5 August 2004 @ 22:54

    Very nice RIchard - I was going to point to http://www.alistapart.com/articles/popuplinks/ but I like yours.

  12. 12/23

    Mark Wubben commented on 5 August 2004 @ 23:48

    Actually there is a bug in the code you posted here:

    var parameterList = new Array();

    // .....

    parameterList(parameterName) = parameterValue;

    You are calling *function* parameterList, while parameterList is an *array*. You should use square brackets:

    parameterList[parameterName] = parameterValue;

    Actually by using square brackets you set a *property* on parameterList, not an array element. Therefore parameterList could simply be an object:

    var parameterList = {}; // {} is an object literal, it is the same as new Object();

    Aside from this, good solution. It would be even better if you'd use the parameters on the serverside when showing the image.

    (Ed: fixed)

  13. 13/23

    TaQ commented on 6 August 2004 @ 00:04

    This can works also:
    http://beam.to/taq/autopopup.html

  14. 14/23

    TaQ commented on 6 August 2004 @ 00:09

    If don't works, try
    http://200.211.78.140/taq/autopopup.html
    F@$@$g redirection services with inner frames and popups ... :-(

  15. 15/23

    Richard@Home commented on 6 August 2004 @ 03:51

    Just a quick note: I've jotted down some notes on the script I mentioned above: http://richardathome.no-ip.com/index.php?article_id=309

    Let me know what you think :-)

  16. 16/23

    Matt Brubeck commented on 13 August 2004 @ 05:50

    "document.getElementById("link").onclick = popUp;

    This is all great and keeps my code nice and clean, but what happens when I want to supply arguments to the method?"

    Then you should use a closure:

    document.getElementById("link").onclick = function() { popUp(300, 400, "foobar"); }

    Simon Willison has made good use of closures for dynamically adding (instead of replacing) event handlers:

    http://simon.incutio.com/archive/2004/05/26/addLoadEvent

  17. 17/23

    TaQ commented on 13 August 2004 @ 06:52

    Wow, cool! The closure stuff is perfect. Will test here. :-)

  18. 18/23

    The Man in Blue commented on 13 August 2004 @ 13:44

    Using a closure you still end up with image dimensions in your JavaScript, and therefore requires you to edit 2 files when you add another element.

  19. 19/23

    Seth commented on 20 August 2004 @ 13:35

    Similiar to your original idea of adding pararemeters to the href, but I feel better about it...

    Why not add these parameters to the href's title attribute. You can also include a known character for easy parsing of the diminsions.

    example

    <a id="link" href="page.htm" title="Image of something :300x400">link</a>


  20. 20/23

    The Man in Blue commented on 20 August 2004 @ 13:52

    I considered putting the arguments in the title, but figured that that would be too visible to the user, and would also affect audio browsers.

    Parameters are traditionally passed via the URL, so it seems logical to use it for the purposes here.

  21. 21/23

    Már Örlygsson commented on 14 October 2004 @ 10:13

    You might like this solution - it's *very* clean:

    Unobtrusive Popup Windows
    http://mar.anomy.net/entry/2004/02/09/12.17.47/

    check it out :-)

  22. 22/23

    Fred commented on 8 January 2005 @ 07:20

    It seems well, but it is possible to do such things completely different. When it is called unobtrusive javascript so why to use a popup when you can createElement div. See my example here. No popup and no javascript links inside xhtml code. Just one line code to replace raw jpg links into something like favelet links which will create positioned div with image info and so on http://xy.wz.cz/habendorf/

  23. 23/23

    Ryan S. White commented on 13 February 2005 @ 05:19

    Good solution. I am using it for a page where I am using an options button which when clicked opens a window with coloured squares. I am using variables on teh coloured squares page to record which square the user last clicked, and my main page scans the variables on the coloured squares page every millisecond and updates the background colour accordingly. The problem is, if the coloured square window is closed, it causes an error message on the main page, because the page it is trying to scan no longer exists. I found a partial solution to this using flags, but using your solution I have been able to fully amend all the problems.

  24. Leave your own comment

    Comments have been turned off on this entry to foil the demons from the lower pits of Spamzalot.

    If you've got some vitriol that just has to be spat, then contact me.

Follow me on Twitter

To hear smaller but more regular stuff from me, follow @themaninblue.

Monthly Archives

Popular Entries

My Book: Simply JavaScript

Simply JavaScript

Simply JavaScript is an enjoyable and easy-to-follow guide for beginners as they begin their journey into JavaScript. Separated into 9 logical chapters, it will take you all the way from the basics of the JavaScript language through to DOM manipulation and Ajax.

Step-by-step examples, rich illustrations and humourous commentary will teach you the right way to code JavaScript in both an unobtrusive and an accessible manner.

RSS feed