Faster Click Events on Mobile Webkit

Matteo Spinelli has coded a wonderful script to remove the 300ms delay from onClick events that occur on mobile versions of webkit. The reason for this delay is that the browser is waiting to see if you are actually performing a double tap. In most situations there is no need to handle double clicks and it is preferred to have a snappy user interface.

I recommend reading the article first, it can be found at: Remove onclick delay on webkit

The script did have a small disadvantage in my opinion, the default behavior like scrolling, pinching, panning, etc. was not functioning anymore on the elements where the script was used. I made a small alteration to the script so that this is working again and still have the fast clicks. The code can be found below.

function NoClickDelay(el) {
	if ('ontouchstart' in window) {
		this.element = typeof el === "object" ? el : document.getElementById(el);
		this.element.addEventListener('touchstart', this, false);
		this.element.addEventListener('click', this, true);
	}
}

NoClickDelay.prototype = {
	handleEvent: function(e) {
		this[e.type](e);
	},

	touchstart: function(e) {
		this.moved = false;

		this.theTarget = document.elementFromPoint(e.targetTouches[0].clientX, e.targetTouches[0].clientY);
		if (this.theTarget.nodeType == 3) this.theTarget = theTarget.parentNode;
		this.theTarget.className += " pressed";

		this.element.addEventListener('touchmove', this, false);
		this.element.addEventListener('touchend', this, false);
	},

	touchmove: function(e) {
		this.moved = true;
		this.theTarget.className = this.theTarget.className.replace(/ ?pressed/gi, '');
	},

	touchend: function(e) {
		e.preventDefault();
		
		this.element.removeEventListener('touchmove', this, false);
		this.element.removeEventListener('touchend', this, false);

		if (!this.moved && this.theTarget) {
			this.theTarget.className = this.theTarget.className.replace(/ ?pressed/gi, '');
			var theEvent = document.createEvent('MouseEvents');
			theEvent.initEvent('click', true, true);
			this.theTarget.dispatchEvent(theEvent);
		}

		this.theTarget = undefined;
	},

	click: function(e) {
		if (this.theTarget === undefined) {
			e.stopImmediatePropagation();
			e.preventDefault();
		}
	}
};
comments powered by Disqus