Fast, NonObtrusive Way to Capture Click Events Before Loading JS Library

Many JavaScript developers are learning to optimize their webpages by moving JavaScript includes to the bottom of the HTML document, just before the closing of the body tag. In addition, most developers believe in separation of implementation from design, so all JavaScript event handlers will be inside those included JavaScript files, instead of being written (or attached) directly in the HTML. What this creates is a window of time, depending on how long it takes for the JavaScript to load, when the HTML is viewable to the end-user, but none of the JavaScript event callbacks are available. While there are many techniques available to mitigate this issue, none completely solve this problem, without breaking the "separation of implementation from design" rule. Today I will show you a simple JavaScript file to be included as the last element inside the head tag that will capture and queue click events until the page is loaded, then execute those clicks once the JavaScript is ready.

Example 1: EventCapture

(function() {
	var _addEventListener = null,
		_eventQueue = [];

	var _isLibraryEventModuleLoaded = function() {return window.YAHOO && YAHOO.util && YAHOO.util.Event;};

	// standard compliant browser
	if (window.addEventListener) {
		_addEventListener = function(el, eType, fn) {el.addEventListener(eType, fn, false);};
	// IE
	else if (window.attachEvent) {
		_addEventListener = function(el, eType, fn) {el.attachEvent(on + eType, fn, false);};

	// if we cannot detect the event management system, then dont bother continuing
	if (_addEventListener) {
		var _handleClick = function(e) {_eventQueue.push(e);};
		_addEventListener(document, click, _handleClick);

		var _handleOnloadEvent = function() {
			if (_isLibraryEventModuleLoaded() && YAHOO.util.Event.simulateClick) {
				YAHOO.util.Event.removeListener(document, click, _handleClick);
				var j = _eventQueue.length;

				for (var i = 0; i < j; i += 1) {
					var targ = YAHOO.util.Event.getTarget(_eventQueue[i]);

					if (targ) {
			else {
				setTimeout(_handleOnloadEvent, 250);

		_addEventListener(window, load, _handleOnloadEvent);

The EventCapture system first uses rudimentary event handler detection to determine which event handling system is available, terminating if none are available. It then uses the event handler to attach two event listeners: one to capture all click events on the document, queuing event event into a list, and the other to execute onload. The onload event fires code to check that both "YAHOO.util.Event" and the simulateClick method from "YUI-EXT-MVC" are available. If you use another library, replace these checks and method calls with your JavaScript librarys equivalent. Next, the callback removes the click handler from document, as the included JavaScript should how be handling these events, and iterates through each of the cached events. The target element is found for each event and then a click event is simulated, executing all user clicks before the page loaded. The setTimeout will be needed if YAHOO (or your library) is dynamically loaded, as the onload event will fire, before the library is completely loaded.

I have included a demo page, which pulls in a lot of external JavaScript to slow down the page load, so you can click on the button several times before the page loads, then watch all your actions execute when the page finishes. Although, this system is fast and robust, it is not perfect. There are several drawbacks to this system that would benefit from innovation:

1) Since the EventCapture system doesnt stop queuing until the page is loaded, any click event attached before then, could possibly fire twice (when the user clicks, and then again when the page loads). This can be prevented by ensuring that all click event handlers are not attached until after the page loads.

2) To the end user the page appears unresponsive. Although, their clicks are captured, the event callback isnt available until the page loads, so there may be a delay (especially on DSL or dialup). To mitigate this, I sometimes apply a class to any click node, which changes its color or hides it (this class will need to be removed before simulateClick is called). This gives the user some tangible feedback until the proper event callback is ready.