• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[JavaScript] capturing Event Handler für IE

Dormilich

New member
Hallo,

ich habe mir einen Event Listener zusammengebaut, der auch die Event-capture-Phase im IE bewerkstelligen soll, nur fehlt mir leider ein IE (bzw. mehrere), um den Code richtig zu testen.

Danke schon mal im Voraus.

Testseite

Code:
PHP:
// based upon an addEvent() implementation from Tino Zijdel
// http://therealcrisp.xs4all.nl/upload/addEvent2.html
var Events = (function ()
{
	/**
	 * workaround for Array.lastIndexOf()
	 *
	 * @param (mixed) val          value to search for
	 * @param (Array) arr          array to search in
	 * @return (int)               array index of val or -1
	 */
	function array_search(val, arr) 
	{
		var i = arr.length;
		while (i--) { 
			if (arr[i] && arr[i] === val) {
				break;
			} 
		}
		return i;
	}

	/**
	 * build the array of elements to loop through in capturing phase
	 *
	 * @param (Node) elem          element from which to search up
	 * @return (Array)             list of elements starting with input
	 *                             element until top node
	 */
	function getParents(elem)
	{
		var p = [elem];
		while (elem.parentNode) {
			elem = elem.parentNode;
			p.push(elem);
		}
		return p;
	}

	/**
	 * workaround for Function.call()
	 *
	 * @param (Function) Fn        function reference
	 * @param (Node)               node on which the handler is to execute
	 * @param (Event)              current event object
	 * @return (mixed)             return value of the function Fn
	 */
	function callHandler(Fn, obj, evt)
	{
		var retValue = true;
		
		if (Function.call) {
			retValue = Fn.call(obj, evt);
		} 
		else {
			try { 
				obj.__fn = Fn;
				retValue = obj.__fn(evt);
				delete obj.__fn; 
			} 
			catch (f) { 
				obj.__fn = null; 
			}
		}
		return retValue;
	}

	/**
	 * function that executes events according to DOM
	 *
	 * @param (mixed) e            Event object, if passed
	 * @return (bool)              combined return value of bubble handlers
	 */
	function IEHandler(e)
	{
		// if no Event object is passed (IE)
		e = e || window.event;
		// add .stopPropagation()
		if (!e.stopPropagation) {
			e.stopPropagation = function () 
			{
				this.cancelEvent  = true;
				this.cancelBubble = true;
			}
		}
		    // get Event Target
		var base      = e.target || e.srcElement,
			// get Event Type
			evTypeRef = '__' + e.type, 
			// return values for bubbling handlers
			retValue  = true, 
			i, j, l, elem, chain, evPhase;
		
		// execute only once
		if (base == this) {
			// get elements for capturing
			chain = getParents(base);
			for (i = chain.length; i--;) {
				elem = chain[i];
				// if there are functions attached
				// to execute in capturing context
				if (elem[evTypeRef] && elem[evTypeRef].capture) {
					evPhase = elem[evTypeRef].capture;
					// execute each function
					for (j = 0, l = evPhase.length; j < l; j++) {
						if (evPhase[j]) {
							// exit on stopPropagation()
							if (e.cancelEvent === true) {
								return null;
							}
							// there can be no value returned due to the
							// executing element of this loop is the Event 
							// target and not the element the handler
							// executes on.
							callHandler(evPhase[j], elem, e);
						}
					}
				}
			}
		}
		// if there are functions attached to execute in bubbling context
		if (this[evTypeRef] && this[evTypeRef].bubble) {
			evPhase = this[evTypeRef].bubble;
			for (j = 0, l = evPhase.length; j < l; j++) {
				if (evPhase[j]) {
					// this time we're in the correct element context so we can
					// safely return something
					retValue = callHandler(evPhase[j], this, e) && retValue;
				}
			}
		}
		return retValue;
	}
	
	/**
	 * return interface
	 *
	 * @public add
	 * @public remove
	 */
	return {
		add : function (obj, evType, fn, useCapture) 
		{
			if (fn != Function) {
				throw new TypeError("Function expected!");
			}
			// make useCapture a Boolean
			useCapture = !!useCapture;
			
			// W3C
			if (obj.addEventListener) {
				obj.addEventListener(evType, fn, useCapture);
			} 
			else {
				var evTypeRef = '__' + evType,
					phase     = useCapture ? "capture" : "bubble";
				
				// create ".__event" property
				if (!obj[evTypeRef]) {
					obj[evTypeRef] = {};
				}
				// search in ".__event.bubble"/".__event.capture"
				// if function is already registered
				if (obj[evTypeRef][phase]) {
					if (array_search(fn, obj[evTypeRef][phase]) > -1) {
						return;
					}
				}
				// create ".__event.bubble"/".__event.capture" property
				else {
					obj[evTypeRef][phase] = [];
					if (!useCapture && obj['on' + evType] && obj['on' + evType] != IEHandler) {
						// add any previous function assigned to .onevent
						obj[evTypeRef][phase][0] = obj['on' + evType];
					}
				}
				// add function to stack
				obj[evTypeRef][phase].push(fn);
				// set "global" handler
				obj['on' + evType] = IEHandler;
			}
		},

		remove : function (obj, evType, fn, useCapture) 
		{
			useCapture = !!useCapture;
			
			if (obj.removeEventListener) {
				obj.removeEventListener(evType, fn, useCapture);
			} 
			else {
				var evTypeRef = '__' + evType,
					phase     = useCapture ? "capture" : "bubble",
					evPhase, i;
				
				if (obj[evTypeRef] && obj[evTypeRef][phase]) {
					evPhase = obj[evTypeRef][phase];
					i = array_search(fn, evPhase);
					if (i > -1) {
						try {
							delete evPhase[i];
						} 
						catch (e) {
							evPhase[i] = null;
						}
					}
				}
			}
		}
	}
})();
 
Zuletzt bearbeitet:
hatte ich auch mal implementiert hatte soweit auch funktioniert nur hatte es einen kleinen Bug. Testen kann ich's nicht hab immo kein IE.
 
Bei mir kommen die Alerts so wie vorgeschrieben (IE 8.0.6001.18702),
mit einigen Sekundenbruchteilen dazwischen (Sanduhr).

Frohe Pfingsten
 
Zurück
Oben