The problem

What happens is that if the user clicks anything in the document that you plan to assign an event handler to before your JavaScript files have loaded and have run, the web browser will run the default action for that element. This could, for instance, be a link element, resulting in the user being taken to another page, where you instead had meant to prevent that and get some information loaded dynamically via AJAX or something.

The solution, in theory

Recently, I have been discussing and working on this with my colleague David Billskog, and the proposed solution is to have a JavaScript block included in the head of the document (inline or included) where you make sure to catch all click events in the page. Then, you would want to filter those to make sure they were only on an element that you know you actually are going to apply your own event handler to.

And, finally, when the page has loaded/your event handlers have been assigned, you want to remove the previously assigned click catcher, iterate over all the elements that got clicked before that, and now trigger a true click event on them to trigger both their natural and applied events’ behavior.

The solution, in practice

Therefore, David and I started our work separately, me on a solution not needing any JavaScript library and he on a version based on jQuery (but could easily be adapted to any other JavaScript library). I’ll present my solution, the clickCatcher, below.

The clickCatcher is using a few handy script functions as its base:

addEvent to assign a click event to the document without overriding any other potentially assigned click handlers.

removeEvent to remove the above assigned event, so it doesn’t continue to catch click once the page has loaded.

fireEvent to fire a click event on all elements that were clicked before the JavaScript files had loaded.

The clickCatcher is wrapped in an anonymous self-invoking function, not to mess with the global scope of the web page and to create its own scope. This code can optionally also expose the clickCatcher object itself, if you want it accessible from elsewhere. It appends a click event handler to the document, and stores each click in an array if the element being clicked (or any of its parent elements) has the class catch (as in Link).

Once the page has loaded, you can have this called automatically, or you can trigger it manually by calling clickCatcher.callClicks();

The complete code, with the addEvent, removeEvent and fireEvent methods included, looks like this:

Code updated to “good ol'” event branching, because it’s all that’s needed for this scenario.

The setTimeout trick

However, no matter if the triggering of the execution of the clicks is from within the clickCatcher object or called manually, you want to make sure this is the last one being called, i.e. when all events have been applied. An interesting result from David’s research is that you can control the call stack by using setTimeout and setting the time to 0, thus putting it last in the stack compared to other load event handlers of the exact same.

What this means is that if you, for instance, use addEvent to call something when the window has loaded, you could control it like this (probably only safe if they are in the same script block/JavaScript file – any feedback here is appreciated!):

A jQuery option

I mentioned before that David has been working on a jQuery version, which means that jQuery has to be included before you call it, but you can all include all other JavaScript files at the end of the document. He presents his approach and findings in clickCatcher with jQuery.

Feedback?

From our testing this seems to be a good and solid way to catch clicks before your JavaScript files have loaded, and still having the performance advantage of having them included at the bottom of the document. If you have any findings, addendum or similar, please let us know!

I don't know what to think of this; it feels awkward having to add additional code to work around a problem caused by an attempt to improve performance. In my opinion this is a tell-tale sign that you took your efforts for improving performance too far and that you should reconsider adding those functions that are necessary for the page to function as intended in javascript-enabled browsers back into the head-section.

Another problem I have with this solution is the fact that clicking something on the page and the click being queued leaves the user without any visible pointer that something should happen but is waiting for some script to be loaded. Ofcourse this could be remedied by f.i. placing a throbber over or nearby the clicked item, but that will mean even more code and complexity.

Last I wouldn't recommend using Resigs' addEvent because it has several problems (John doesn't even recommend it himself there). Besides the problem with relying on function decompilation testing for MSIE's proprietary method first is i.m.o. the wrong order.

1) It totally depends on the web page you are using it in. However, compared to loading a JavaScript library and one or more other dependencies, especially since you never know which files will apply event handlers to the page, I personally find it to be a quick and small solution to catching the clicks.

2. I agree, however if the delay between actual click and loading of JavaScript files and applying of event handling, there are some other performance issues as well with the web site.

Adding a throbber or something isn't that bad, though. Just append an element to the document and position it next to the click or at a fixed position, and could easily be added to this script.

3. It's a valid point, and just the first one I took for its small size – feel free to replace it with anyone of your liking.

My concern is when there is a javascript error (and that does happen sometimes no matter how hard we try), you are left with a page that is unusable instead of a page that degrades into traditional interaction.