jQuery.event.fix (v19)

Revision 19 of this benchmark created on


Preparation HTML

<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script>
(function ($) {
	// http://bitovi.com/blog/2012/04/faster-jquery-event-fix.html
	// https://gist.github.com/2377196
	// IE 8 has Object.defineProperty but it only defines DOM Nodes. According to
	// http://kangax.github.com/es5-compat-table/#define-property-ie-note
	// All browser that have Object.defineProperties also support Object.defineProperty properly
	if (Object.defineProperties) {
		var
		// Use defineProperty on an object to set the value and return it
		set = function (obj, prop, val) {
			if (val !== undefined) {
				Object.defineProperty(obj, prop, {
					value: val
				});
			}
			return val;
		},
			// special converters
			special = {
				pageX: function (original) {
					if (!original) {
						return;
					}

					var eventDoc = this.target.ownerDocument || document,
					doc = eventDoc.documentElement,
					body = eventDoc.body;
					return original.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
				},
				pageY: function (original) {
					if (!original) {
						return;
					}

					var eventDoc = this.target.ownerDocument || document,
					    doc = eventDoc.documentElement,
					    body = eventDoc.body;
					return original.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
				},
				relatedTarget: function (original) {
					if (!original) {
						return;
					}

					return original.fromElement === this.target ? original.toElement : original.fromElement;
				},
				metaKey: function (originalEvent) {
					if (!originalEvent) {
						return;
					}
					return originalEvent.ctrlKey;
				},
				which: function (original) {
					if (!original) {
						return;
					}

					return original.charCode != null ? original.charCode : original.keyCode;
				}
			};

		// Get all properties that should be mapped
		$.each($.event.keyHooks.props.concat($.event.mouseHooks.props).concat($.event.props), function (i, prop) {
			if (prop !== "target") {
				(function () {
					Object.defineProperty($.Event.prototype, prop, {
						get: function () {
							// get the original value, undefined when there is no original event
							var originalValue = this.originalEvent && this.originalEvent[prop];
							// overwrite getter lookup
							return this['_' + prop] !== undefined ? this['_' + prop] : set(this, prop,
								// if we have a special function and no value
								special[prop] && originalValue === undefined ?
									// call the special function
									special[prop].call(this, this.originalEvent) :
									// use the original value
									originalValue);
						},
						set: function (newValue) {
							// Set the property with underscore prefix
							this['_' + prop] = newValue;
						}
					});
				})();
			}
		});

		$.event.fastFix = function(event) {
			if (event[$.expando]) {
				return event;
			}
			// Create a jQuery event with at minimum a target and type set
			var originalEvent = event;

			event = $.Event(originalEvent);

			event.target = originalEvent.target;
			// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
			if (!event.target) {
				event.target = originalEvent.srcElement || document;
			}

			// Target should not be a text node (#504, Safari)
			if (event.target.nodeType === 3) {
				event.target = event.target.parentNode;
			}

			return event;
		};
	}

	return $;
})(jQuery);

var makeClick = function(){

        
        var event;

        try {
                event = document.createEvent('MouseEvents');
                event.initMouseEvent("click", true, true, null, null, 100, 100, 100, 100, false, false, false, false, 0, null);
        } catch (e) {
                try {
                        event = document.createEvent("Events");
                } catch (e2) {
                        event = document.createEvent("UIEvents");
                } finally {
                        event.initEvent("click", true, true);
                }
        }
        //element.dispatchEvent(event)
        return event;
}
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
existing fix
var ev = $.event.fix( makeClick() )
ev.pageX
ev.pageY
ev.pageX
ev.pageY
ev.pageX
ev.pageY
ev.pageX
ev.pageY
ready
fast fix
var ev = $.event.fastFix( makeClick() )
ev.pageX
ev.pageY
ev.pageX
ev.pageY
ev.pageX
ev.pageY
ev.pageX
ev.pageY
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.