var Util = {};

// W3C DOM 2 events
if (document.addEventListener) {
    Util.addEventListener = function(element, type, listener) {
	element.addEventListener(type, listener, false);
    };
    
    Util.removeEventListener = function(element, type, listener) {
	element.removeEventListener(type, listener, false);
    };
    
    Util.preventDefault = function(event) {
	event.preventDefault();
    };
    
    Util.stopPropagation = function(event) {
	event.stopPropagation();
    };
}
// Internet Explorer events
else if (document.attachEvent) {
    Util.addEventListener = function(element, type, listener) {
        // prevent adding the same listener twice, since DOM 2 Events ignores
	// duplicates like this
        if (Util._findListener(element, type, listener) != -1) {
	    return;
	}

	// listener2 calls listener as a method of target in one of two ways,
	// depending on what this version of IE supports, and passes it the global
	// event object as an argument
	var listener2 = function() {
	    var event = window.event;

	    if (Function.prototype.call) {
		listener.call(element, event);
	    }
	    else {
		element._currentListener = listener;
		element._currentListener(event);
		element._currentListener = null;
    	    }
	};

	// add listener2 using IE's attachEvent method
	element.attachEvent("on" + type, listener2);

	// create an object describing this listener so we can clean it up later
	var listenerRecord = {
	    element: element,
	    type: type,
	    listener: listener,
	    listener2: listener2
	};

	// get a reference to the window object containing element
	var elementDocument = element.document || element;
	var elementWindow = elementDocument.parentWindow;

	// create a unique ID for this listener
	var listenerId = "l" + Util._listenerCounter++;

	// store a record of this listener in the window object
	if (!elementWindow._allListeners) {
	    elementWindow._allListeners = {};
	}
	elementWindow._allListeners[listenerId] = listenerRecord;

	// store this listener's ID in element
	if (!element._listeners) {
	    element._listeners = [];
	}
	element._listeners[element._listeners.length] = listenerId;

	// set up Util._removeAllListeners to clean up all listeners on unload
	if (!elementWindow._unloadListenerAdded) {
	    elementWindow._unloadListenerAdded = true;
	    elementWindow.attachEvent("onunload", Util._removeAllListeners);
	}
    };

    Util.removeEventListener = function(element, type, listener) {
	// find out if the listener was actually added to element
	var listenerIndex = Util._findListener(element, type, listener);
	if (listenerIndex == -1) {
	    return;
	}

	// get a reference to the window object containing element
	var elementDocument = element.document || element;
	var elementWindow = elementDocument.parentWindow;

	// obtain the record of the listener from the window object
	var listenerId = element._listeners[listenerIndex];
	var listenerRecord = elementWindow._allListeners[listenerId];

	// remove the listener, and remove its ID from element
	element.detachEvent("on" + type, listenerRecord.listener2);
	element._listeners.splice(listenerIndex, 1);

	// remove the record of the listener from the window object
	delete elementWindow._allListeners[listenerId];
    };

    Util.preventDefault = function(event) {
	event.returnValue = false;
    };
    
    Util.stopPropagation = function(event) {
	event.cancelBubble = true;
    };

    Util._findListener = function(element, type, listener) {
	// get the array of listener IDs added to element
        var listeners = element._listeners;
	if (!listeners) {
	    return -1;
	}

	// get a reference to the window object containing element
	var elementDocument = element.document || element;
	var elementWindow = elementDocument.parentWindow;

	// searching backward (to speed up onunload processing), find the listener
	for (var i = listeners.length - 1; i >= 0; i--) {
	    // get the listener's ID from element
	    var listenerId = listeners[i];

	    // get the record of the listener from the window object
	    var listenerRecord = elementWindow._allListeners[listenerId];

	    // compare type and listener with the retrieved record
	    if (listenerRecord.type == type && listenerRecord.listener == listener) {
		return i;
	    }
	}
	return -1;
    };

    Util._removeAllListeners = function() {
	var elementWindow = this;

	for (id in elementWindow._allListeners) {
	    var listenerRecord = elementWindow._allListeners[id];
    	    listenerRecord.element.detachEvent(
		"on" + listenerRecord.type, listenerRecord.listener2);
    	    delete elementWindow._allListeners[id];
	}
    };

    Util._listenerCounter = 0;
}

Util.addClass = function(element, elementClass) {
    if (!Util.hasClass(element, elementClass)) {
	if (element.className == '') {
	    element.className = elementClass;
	}
	else {
	    element.className += ' ' + elementClass;
	}
    }
};

Util.getElementsByClass = function(elementsClass) {
    var elementArray = [];

    if (document.all) {
	elementArray = document.all;
    }
    else {
	elementArray = document.getElementsByTagName("*");
    }

    var matchedArray = [];
    var pattern = new RegExp("(^| )" + elementsClass + "( |$)");

    for (var i = 0; i < elementArray.length; i++) {
	if (pattern.test(elementArray[i].className)) {
	    matchedArray[matchedArray.length] = elementArray[i];
	}
    }

    return matchedArray;
};

Util.hasClass = function(element, elementClass) {
    var pattern = new RegExp("(^| )" + elementClass + "( |$)");

    if (pattern.test(element.className)) {
	return true;
    }

    return false;
};

Util.removeClass = function(element, elementClass) {
    var pattern = new RegExp("(^| )" + elementClass + "( |$)");

    element.className = element.className.replace(pattern, "$1");
    element.className = element.className.replace(/ $/, "");
};

Util.getComputedStyle = function(element, styleProperty) {
    var computedStyle = null;

    if (typeof element.currentStyle != "undefined") {
	computedStyle = element.currentStyle;
    }
    else {
	computedStyle = document.defaultView.getComputedStyle(element, null);
    }

    return computedStyle[styleProperty];
};

Util.onload = function(initFunction) {
    Util.addEventListener(window, "load", initFunction);
};

Util.onunload = function(cleanupFunction) {
    Util.addEventListener(window, "unload", cleanupFunction);
};

Util.fixIEBackground = function() {
    try {
	document.execCommand("BackgroundImageCache", false, true);
    } catch (err) {}
}
