var DOM = {

  transitionEvents:['transitionend','webkitTransitionEnd','MSTransitionEnd','oTransitionEnd'],

	getElementsByClassName: function(className, element) {
		if (element.getElementsByClassName === undefined) {
			return List.select(element.getElementsByTagName('*'), function(descendant) {
				return DOM.hasClass(descendant, className);
			});
		}
		return element.getElementsByClassName(className);
	},

	hasClass: function(element, needle) {
		if (element.classList === undefined) {
			return (element.className === needle
				|| element.className.indexOf(' ' + needle + ' ') !== -1
				|| new RegExp(' ' + needle + '$').test(element.className)
				|| new RegExp('^' + needle + ' ').test(element.className)
			);
		}
		return element.classList.contains(needle);
	},

	addClass: function(element, className) {
		if (element.classList === undefined) {
      if (!DOM.hasClass(element, className)) {
				element.className = element.className + ' ' + className;
			}
      return null;
		}
		return element.classList.add(className);
	},

	removeClass: function(element, className) {
		if (element.classList === undefined) {
			var index = element.className.indexOf(className);
			if (index !== -1) {
				element.className = element.className.substr(0, index - 1) + element.className.substr(index + className.length);
			}
      return null;
		}
		return element.classList.remove(className);
	},

	setMouseOverClassName: function(DOMElement, className) {
		if (className === undefined) {
			className  = 'mouseover';
		}
		DOM.addEventListener(DOMElement, 'mouseover', function(e) {
			DOM.addClass(DOMElement, className);
		});
		DOM.addEventListener(DOMElement, 'mouseout', function(e) {
			DOM.removeClass(DOMElement, className);
		});
	},

	getFirstChild: function(element) {
		if (element.firstElementChild === undefined) {
			if (element.childNodes.length > 0) {
				if (element.childNodes[0].nodeType === 1) {
					return element.childNodes[0];
				}
				return element.childNodes[1];
			}
			return null;
		}
		return element.firstElementChild;
	},

	getPreviousElement: function(DOMElement) {
		if (DOMElement.previousElementSibling !== undefined) {
			return DOMElement.previousElementSibling;
		}
		else {
			var previous = DOMElement.previousSibling;
                        return previous.nodeType === 1 ? previous : previous.previousSibling;
		}
	},

	getNextElement: function(DOMElement) {
		if (DOMElement.nextElementSibling !== undefined) {
			return DOMElement.nextElementSibling;
		}
		else {
			var next = DOMElement.nextSibling;
                        return next.nodeType === 1 ? next : next.nextSibling;
		}
	},

	getNextElements: function(element, filters) {
		var elements = [];
		var sibling = DOM.getNextElement(element);
		while (sibling) {
			elements.push(sibling);
			sibling = DOM.getNextElement(sibling);
		}
		return DOM.filterList(elements, filters);
	},

	getChildren: function(element, filters) {
		var children = element.children !== undefined ? element.children : List.select(element.childNodes, function(child, index) { return child.nodeType === 1; });
                return DOM.filterList(children, filters);
	},

	getSiblings: function(element, filters) {
		return List.select(DOM.getChildren(element.parentNode, filters), function(sibling) { return sibling != element; });
	},

	filterList: function(list, filters) {
		if (typeof(filters) === 'object') {
			var filterFuncs = [];
			if (filters.tagName !== undefined) {
				filterFuncs.push(function(element) { return element.nodeName === filters.tagName.toUpperCase(); });
			}
			if (filters.className !== undefined) {
				filterFuncs.push(function(element) { return DOM.hasClass(element, filters.className); });
			}
			List.walk(filterFuncs, function(func) {
				list = List.select(list, func);
			});
		}
		return list;
	},

	getVerticalScroll: function() {
		var scrollY;
		if (window.scrollY !== undefined) {
			scrollY = window.scrollY;
		}
		else {
			var documentElement = document.documentElement || document.body.parentNode;
			scrollY = typeof(documentElement.scrollTop) === 'number' ? documentElement.scrollTop : document.body.scrollTop;
		}
		return scrollY;
	},

	getWindowDimensions: function() {
		var width = 0;
		var height = 0;
		if (typeof(window.innerWidth) === 'number') {
			width = window.innerWidth;
			height = window.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientWidth) {
			width = document.documentElement.clientWidth;
			height = document.documentElement.clientHeight;
		}
		else if (document.body && document.body.clientWidth) {
			width = document.body.clientWidth;
			height = document.body.clientHeight;
		}
		return { width:width, height:height };
	},

	addEventListener: function(element, event, callback, preventDefault) {
		var onevent = 'on' + event;
		var func;
		if (preventDefault === true) {
			func = function(e) {
				if (e.preventDefault !== undefined) {
					e.preventDefault();
					callback(e);
					return false;
				}
			};
		}
		else {
			func = callback;
		}
		if (element.addEventListener !== undefined) {
			return element.addEventListener(event, func, false);
		}
		else if (element.attachEvent !== undefined) {
			return element.attachEvent(onevent, func);
		}
		else {
			element[onevent] = func;
		}
	},

	removeEventListener: function(element, event, callback) {
		var onevent = 'on' + event;
		if (element.removeEventListener !== undefined) {
			return element.removeEventListener(event, callback);
		}
		else if (element.detachEvent !== undefined) {
			return element.detachEvent(onevent, callback);
		}
		else {
			element[onevent] = null;
		}
	},

  removeElement: function(element) {
    if (element.parentNode) {
      element.parentNode.removeChild(element);
    }
  },

	onSvgLoad: function(objectElement, callback) {
		var intervalID = setInterval(function() {
			if (objectElement.contentDocument) {
				clearInterval(intervalID);
				callback(objectElement.contentDocument);
			}
		}, 16);
	},

	/*
	setMouseEnterAndLeave: function(element, onMouseEnter, onMouseLeave) {
		if (element.attachEvent !== undefined) {
			element.attachEvent('onmouseenter', onMouseEnter);
			element.attachEvent('onmouseleave', onMouseLeave);
		}
		else {
			var hasMouseEntered = false;
			var isMouseOver = false;
			DOM.addEventListener(element, 'mouseover', function(e) {
				isMouseOver = true;
				if (hasMouseEntered === false) {
					onMouseEnter(e);
					hasMouseEntered = true;
				}
			});
			//var leaveFunction
			DOM.addEventListener(element, 'mouseout', function(e) {
				isMouseOver = false;
				if (hasMouseEntered === true) {
					onMouseLeave(e);
					hasMouseEntered = false;
				}
			});
			List.walk(element.getElementsByTagName('*'), function(descendant) {
				DOM.addEventListener(descendant, 'mouseover', function(e) {
					isMouseOver = true;
					if (mouseHasEntered) {
						e.stopPropagation();
					}
				});
				DOM.addEventListener(descendant, 'mouseout', function(e) {
					isMouseOver = false;
					e.stopPropagation();
				});
			});
			//DOM.removeEventListener(
		}
	},
	*/
	getMousePosition: function(e) {
		var position = { x: -1, y: -1 };
		if (e.pageX || e.pageY) {
			position.x = e.pageX;
			position.y = e.pageY;
		}
		else if (e.clientX || e.clientY) {
			position.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			position.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		}
		return position;
	},

	onTransitionEnd: function(element, eventHandler) {
		var onTransitionEnd = function(e) {
      List.walk(DOM.transitionEvents, function(eventName) {
        element.removeEventListener(eventName, onTransitionEnd);
      });
      eventHandler(element);
    };
    List.walk(DOM.transitionEvents, function(eventName) {
      element.addEventListener(eventName, onTransitionEnd, false);
    });
	}
}

