		// Courtesy of those lovely folks at SitePoint - thanks Kev and Cam (with a few modifications ... don't know why they didn't think of them ;)

		var Core = {};

		// W3C DOM 2 Events model
		if (document.addEventListener)
		{
			Core.addEventListener = function(target, type, listener)
			{
				target.addEventListener(type, listener, false);
			};

			Core.removeEventListener = function(target, type, listener)
			{
				target.removeEventListener(type, listener, false);
			};

			Core.preventDefault = function(event)
			{
				event.preventDefault();
			};

			Core.stopPropagation = function(event)
			{
				event.stopPropagation();
			};
		}
		// Internet Explorer Events model
		else if (document.attachEvent)
		{
			Core.addEventListener = function(target, type, listener)
			{
				// prevent adding the same listener twice, since DOM 2 Events ignores
				// duplicates like this
				if (Core._findListener(target, 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(target, event);
					}
					else
					{
						target._currentListener = listener;
						target._currentListener(event)
						target._currentListener = null;
					}
				};

				// add listener2 using IE's attachEvent method
				target.attachEvent("on" + type, listener2);

				// create an object describing this listener so we can clean it up later
				var listenerRecord =
				{
					target: target,
					type: type,
					listener: listener,
					listener2: listener2
				};

				// get a reference to the window object containing target
				var targetDocument = target.document || target;
				var targetWindow = targetDocument.parentWindow;

				// create a unique ID for this listener
				var listenerId = "l" + Core._listenerCounter++;

				// store a record of this listener in the window object
				if (!targetWindow._allListeners) targetWindow._allListeners = {};
				targetWindow._allListeners[listenerId] = listenerRecord;

				// store this listener's ID in target
				if (!target._listeners) target._listeners = [];
				target._listeners[target._listeners.length] = listenerId;

				// set up Core._removeAllListeners to clean up all listeners on unload
				if (!targetWindow._unloadListenerAdded)
				{
					targetWindow._unloadListenerAdded = true;
					targetWindow.attachEvent("onunload", Core._removeAllListeners);
				}
			};

			Core.removeEventListener = function(target, type, listener)
			{
				// find out if the listener was actually added to target
				var listenerIndex = Core._findListener(target, type, listener);
				if (listenerIndex == -1) return;

				// get a reference to the window object containing target
				var targetDocument = target.document || target;
				var targetWindow = targetDocument.parentWindow;

				// obtain the record of the listener from the window object
				var listenerId = target._listeners[listenerIndex];
				var listenerRecord = targetWindow._allListeners[listenerId];

				// remove the listener, and remove its ID from target
				target.detachEvent("on" + type, listenerRecord.listener2);
				target._listeners.splice(listenerIndex, 1);

				// remove the record of the listener from the window object
				delete targetWindow._allListeners[listenerId];
			};

			Core.preventDefault = function(event)
			{
				event.returnValue = false;
			};

			Core.stopPropagation = function(event)
			{
				event.cancelBubble = true;
			};

			Core._findListener = function(target, type, listener)
			{
				// get the array of listener IDs added to target
				var listeners = target._listeners;
				if (!listeners) return -1;

				// get a reference to the window object containing target
				var targetDocument = target.document || target;
				var targetWindow = targetDocument.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 target
					var listenerId = listeners[i];

					// get the record of the listener from the window object
					var listenerRecord = targetWindow._allListeners[listenerId];

					// compare type and listener with the retrieved record
					if (listenerRecord.type == type && listenerRecord.listener == listener)
					{
						return i;
					}
				}
				return -1;
			};

			Core._removeAllListeners = function()
			{
				var targetWindow = this;

				for (id in targetWindow._allListeners)
				{
					var listenerRecord = targetWindow._allListeners[id];
					listenerRecord.target.detachEvent(
					"on" + listenerRecord.type, listenerRecord.listener2);
					delete targetWindow._allListeners[id];
				}
			};

			Core._listenerCounter = 0;
		}

		Core.addClass = function(target, theClass)
		{
			if (!Core.hasClass(target, theClass))
			{
				if (target.className == "")
				{
					target.className = theClass;
				}
				else
				{
					target.className += " " + theClass;
				}
			}
		};

		Core.addClassGlobal = function(target, theClass)
		{
			for(var i=0; i<target.length; i++) {
				Core.addClass(target[i], theClass);
			}
		}


		Core.getElementsByClassName = function(theClass)
		{
			if(arguments[1]) 
			{
				// a second argument restricts the tags searched
				// this makes IE much faster by limiting the document.all to searching for a class within a specified tag only
				var tagName = arguments[1]; 
			}
			else 
			{
				// otherwise we search 'em all
				var tagName = "*";
			}
			var elementArray = [];

			if ((document.all) && (!arguments[1]))
			{
				elementArray = document.all;
			}
			else
			{
				elementArray = document.getElementsByTagName(tagName);
			}

			var matchedArray = [];
			var pattern = new RegExp("(^| )" + theClass + "( |$)");

			for (var i = 0; i < elementArray.length; i++)
			{
				if (pattern.test(elementArray[i].className))
				{
					matchedArray[matchedArray.length] = elementArray[i];
				}
			}

			return matchedArray;
		};

		Core.hasClass = function(target, theClass)
		{
			var pattern = new RegExp("(^| )" + theClass + "( |$)");

			if (pattern.test(target.className))
			{
				return true;
			}

			return false;
		};

		Core.removeClass = function(target, theClass)
		{
			var pattern = new RegExp("(^| )" + theClass + "( |$)");

			target.className = target.className.replace(pattern, "$1");
			target.className = target.className.replace(/ $/, "");
		};

		Core.removeClassGlobal = function(target, theClass)
		{
			for(var i=0; i<target.length; i++) {
				Core.removeClass(target[i], theClass);
			}

		};

		Core.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];
		};

		Core.start = function(runnable)
		{
			Core.addEventListener(window, "load", runnable.init);
		};

