/**
 * Events, helper class to work with events.
 * Code largely based on Peter Nederlof's work, mainly cause he first
 * showed me how to do this and our coding styles are almost identical.
 *
 * v1.0.060628.080701
 * @author Martin Reurings - http://www.windgazer.nl/
 * @credits Peter Nederlof - http://www.xs4all.nl/~pnederlof/
 * @class
 */

var Events = {
	safRE:/safari/i,
	aRE:/^a$/i,
	/**
	 * Attaches an event to an element. Uses DOM methods when available, but
	 * falls back to onXXXX handlers when needed.
	 *
	 * @param {Element} element The element to which to attach the event
	 * @param {String} type The type of event to handle, without the 'on' i.e. mouseover.
	 * @param {Function} handler The event-handler method.
	 * @return EventWrapper
	 */
	attach:function(element, type, handler) {
		var result = null;
		if (element.addEventListener) result = element.addEventListener(type, handler, false);
		else if(element.attachEvent) result = element.attachEvent('on' + type, handler);
		else element['on' + type] = handler;
		return {type:type, handler:handler, element:element, result:result}; //return JSON object which contains all the relevant bits
	},
	/**
	 * Detaches an event that has been attached using Events.attach. Makes
	 * use of DOM methods with a fallback to onXXX handlers.
	 * If you didn't store the EventWrapper but have the correct set of data
	 * just pass the data on with the following syntax:
	 * Events.detach({type:String, handler:function, element:Element});
	 * @param {EventWrapper} eventWrapper An object containing all related data to an eventhandler.
	 */
	detach:function(eventWrapper) {
		var element = eventWrapper.element;
		if (element.removeEventListener) element.removeEventListener(eventWrapper.type, eventWrapper.handler, false);
		else if(element.detachEvent) element.detachEvent('on' + eventWrapper.type, eventWrapper.handler);
		else element['on' + eventWrapper.type] = null;
	},
	/**
	 * Cancels an event using DOM methods, returns false. Preferable when
	 * you want to cancel events return the result of this function from your
	 * handler, this will encertain to some degree that onXXX handlers will
	 * also cancel the default action.
	 * On Safari this method will overwrite the onClick method of a link to
	 * return false before setting back it's original onClick method. This
	 * is because the DOM methods do not work on Safari even though they
	 * exist.
	 *
	 * @param {Event} event The event you want to cancel.
	 * @return false
	 */
	cancel:function(event) {
		try {
			event.preventDefault();
		} catch (e) {
			event.returnValue = false;
		}
		try {
			event.stopPropagation();
		} catch (e) {
			event.cancelBubble = true;
		}
		if (Events.safRE.test(navigator.userAgent)) {
			var target = event.target;
			if (target.nodeName == "#text") target = target.parentNode;
		 	if (Events.aRE.test(target.nodeName)) {
		 		target.onclick = function() {
					return false;
				};
			}
		} return false;
	}
};
