/**
 *	PortabilityKit is a class dependent on Prototype library capable to abilities
 *	currently missing in Prototype (1.6).
 */
var PortabilityKit = {
	
	/**
	 * Extends viewport functionality
	 */
	Viewport: {
		
		/**
		 * Returns the inner width of the window regarding the scroll bars
		 */
		getInnerWidth: function () {
			return window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth;
		},
		
		/**
		 * Returns the inner height of the window regarding the scroll bars
		 */
		getInnerHeight: function () {
			return window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
		},
		
		/**
		 * Returns the inner dimensions of the window regarding the scroll bars as
		 * a hash with the fields 'width' and 'height'.
		 */
		getInnerDimensions: function () {
			return {
				'width'  : this.getInnerWidth(),
				'height' : this.getInnerHeight()
			};
		},
		
		/**
		 * Returns the inner width of the window without regarding the scroll bars
		 */
		getWidth: function () {
			return Math.max(
				Math.max(document.body.scrollWidth, document.documentElement.scrollWidth),
				Math.max(document.body.offsetWidth, document.documentElement.offsetWidth),
				Math.max(document.body.clientWidth, document.documentElement.clientWidth));
		},
		
		/**
		 * Returns the inner height of the window without regarding the scroll bars
		 */
		getHeight: function () {
			return Math.max(
				Math.max(document.body.scrollHeight, document.documentElement.scrollHeight),
				Math.max(document.body.offsetHeight, document.documentElement.offsetHeight),
				Math.max(document.body.clientHeight, document.documentElement.clientHeight));
		},
		
		/**
		 * Returns the inner dimensions of the window without regarding the scroll
		 * bars as a hash with the fields 'width' and 'height'.
		 */
		getDimensions: function () {
			return {
				'width'  : this.getWidth(),
				'height' : this.getHeight()
			};
		},
		
		/**
		 * Returns the x-scroll-bar's position of the page
		 */
		getLeftOffset: function () {
			return window.pageXOffset                  || 
			       document.documentElement.scrollLeft || 
			       document.body.scrollLeft;
		},
		
		/**
		 * Returns the y-scroll-bar's position of the page
		 */
		getTopOffset: function () {
			return window.pageYOffset                 || 
			       document.documentElement.scrollTop || 
			       document.body.scrollTop;
		},
		
		/**
		 * Returns the scroll bars' positions as a hash with the fields 'left' and
		 * 'top'
		 */
		getOffsets: function () {
			return {
				'left' : this.getLeftOffset(),
				'top'  : this.getTopOffset()
			};
		}
		
	},
	
	Element: {
		
		getWidth: function (elem) {
			return parseInt(elem.getStyle('width').replace(/\D+/, ''));
		},
		
		getHeight: function (elem) {
			return parseInt(elem.getStyle('height').replace(/\D+/, ''));
		},
		
		getDimensions: function (elem) {
			return {
				'width'  : this.getWidth(elem),
				'height' : this.getHeight(elem)
			};
		},
		
		getLocationLeft: function (elem) {
			return parseInt(elem.getStyle('marginLeft').replace(/\D+/, ''));
		},
		getLocationTop: function (elem) {
			return parseInt(elem.getStyle('marginTop').replace(/\D+/, ''));
		},
		
		getLocation: function (elem) {
			return {
				'left' : this.getLocationLeft(elem),
				'top'  : this.getLocationTop(elem)
			};
		},
		
		getBounds: function (elem) {
			return {
				'width'  : this.getWidth(elem),
				'height' : this.getHeight(elem),
				'left'   : this.getLocationLeft(elem),
				'right'  : this.getLocationTop(elem)
			};
		},
		
		setWidth: function (elem, width) {
			elem.setStyle({
				'width' : width
			});
		},
		
		setHeight: function (elem, height) {
			elem.setStyle({
				'height' : height
			});
		},
		
		setDimensions: function (elem, width, height) {
			if (typeof width == 'object') {
				this.setDimensions(elem, width.width, width.height);
			}
			else {
				elem.setStyle({
					'width'  : width,
					'height' : height
				});
			}
		},
		
		setLocationLeft: function (elem, left) {
			elem.setStyle({
				marginLeft : left
			});
		},
		
		setLocationTop: function (elem, top) {
			elem.setStyle({
				marginTop : top
			});
		},
		
		setLocation: function (elem, left, top) {
			elem.setStyle({
				marginLeft : left,
				marginTop  : top
			});
		},
		
		setBounds: function (elem, width, height, left, top) {
			if (typeof width == 'object') {
				this.setBounds(elem, width.width, width.height, left, top);
			}
			else {
				elem.setStyle({
					'width'    : width,
					'height'   : height,
					marginLeft : left,
					marginTop  : top
				});	
			}
		}
		
	},
	
	Document: {
		
		getElementsByClassName: function (name) {
			var elements = new Array();
			
			var findElementsByClassName = function (className, child, arr) {
				if (undefined != child.className && null != child.className && child.className == className) {
					arr.push(child);
				}

				for (var i = 0; i < child.childNodes.length; ++i) {
					findElementsByClassName(className, child.childNodes[i], arr);
				}
			}
			
			findElementsByClassName(name, document, elements);

			return elements;
		}
		
	}
	
};
