/**
 * @fileoverview Library for DOM Element Handling
 * extends the prototype library by Sam Stephenson
 *
 * @author	Gaetan Lauff	<glauff@plansoft.de>
 *
 * $Id: lib.element.js 286 2007-12-13 15:30:41Z glauff $
 */
/**
 * Extend the Prototype Library 
 */
Object.extend( Element, 
{
	/**
	 * Get Element from multiple sources
	 *
	 * @param	{mixed}	src			Source from which element should be searched	Can be string or an Event Object
	 * @return	{object}			element
	 * @access	public
	 * @throws	object	Error
	 */
	getElement: function( evt )
	{
		try {
			if (evt.tagName)
				return $(evt);

			if (typeof evt == 'string')
				return $(evt);
				
			if (window.event)
			  	el = window.event.srcElement;
			else 
				if (evt.type == 'scroll')
					el = evt.currentTarget;
				else
					el = (evt.target.tagName ? evt.target : evt.target.parentNode);
		
			return $(el);
		} catch (e) {
			if (e instanceof Error)
				throw new Error('Element::getElement(): ' + e.name + ' ' + e.message);
		}
	},
	
	/**
	 * Returns the Nodedepth
	 *
	 * @param	{object} node	DOM Element
	 * @returns	Item Depth
	 * @private
	 */
	getDepth: function( node, tagName, ektype )
	{
		var depth = -1;
		
		while (node = Element.getParentElementByTagName( node, tagName)) {
			var nodetype = Element.getAttributeValue(node, 'ektype');
			
			if (nodetype != ektype )
				depth++;
			else
				break;
			
			node = node.parentNode;
		}
		
		return depth;
	},
	
	getPageOffsetTop: function( domElement )
	{
		var y;
	
		y = domElement.offsetTop;
	
		if ( domElement.offsetParent != null ) {
			y +=Element.getPageOffsetTop( domElement.offsetParent );
		}
	
		return y;
	},
	
	
	getPageOffsetLeft: function( domElement )
	{
		var x;
	
		x = domElement.offsetLeft;
		
		if ( domElement.offsetParent != null ) {
			x += Element.getPageOffsetLeft( domElement.offsetParent );
		}
	
		return x;
	},
	
	/**
	 * Creates New HTML Element
	 * @param	{string}	tagName		name of element to create
	 * @param	{string}	id		Id
	 * @param	{int}		width
	 * @param	{int}		height
	 * @param	{int}		left
	 * @param	{int}		top
	 * @return	object		HTML Element
	 * @access	public
	 */
	create: function(tagName, id, width, height, left, top)
	{
		try {
			var newElement = document.createElement(tagName);
			newElement.setAttribute( 'id', id );
			
			var width = ( width == null ) ? 100 : width;
			var height = ( height == null ) ? 25 : height;
			
			Element.setDimension( newElement, width, height );
			
			if ( left != null || top != null ) {
				newElement.style.position = "absolute";
				Element.setPosition( newElement, top, left );
			}
		
			return newElement;
		} catch (e) {
			if (e instanceof Error)
				throw new Error('Element::create(): ' + e.name + ' ' + e.message);
		}
	},
	
	/**
	 * @param	{object}	element
	 * @returns	The correct width for Internet Explorer.
	 * @access	public
	 */
	getIEWidth: function( element )
	{
		var width = parseInt(element.offsetWidth);
		var offset = 0;
		
		/**
		 * Fix the IE Box Model
		 */
		if (!is.ie5 && !is.ie5_5) {
			var offset = Element.getIEBoxWidthOffset( element );
		}
			
		return width - offset;
	},
	
	/**
	 * @param	{object}	element
	 * @returns	The correct Height for Internet Explorer.
	 * @access	public
	 */
	getIEHeight: function( element )
	{
		var height = parseInt(element.offsetHeight);
		var offset = 0;
		
		/**
		 * Fix the IE Box Model
		 */
		if (!is.ie5 && !is.ie5_5) {
			var offset = Element.getIEBoxHeightOffset( element );
		}
			
		return height - offset;
	},
	
	/**
	 * @param	{object}	element
	 * @returns the IE5 width for a DOM Element.
	 * @access	public
	 */
	getIEBoxWidthOffset: function( element )
	{
		var paddingLeft 	= Element.getStyle( element, 'padding-left' );
		var paddingRight 	= Element.getStyle( element, 'padding-right' );
		
		var borderLeft		= Element.getStyle( element, 'border-left-width' );
		var borderRight 	= Element.getStyle( element, 'border-right-width' );
		
		paddingLeft 	= (paddingLeft) ? isNaN(parseInt(paddingLeft)) ? 0 : parseInt(paddingLeft) : 0;
		paddingRight 	= (paddingRight) ? isNaN(parseInt(paddingRight)) ? 0 : parseInt(paddingRight) : 0;
		
		borderLeft 		= (borderLeft) ? isNaN(parseInt(borderLeft)) ? 0 : parseInt(borderLeft) : 0;
		borderRight 	= (borderRight) ? isNaN(parseInt(borderRight)) ? 0 : parseInt(borderRight) : 0;
	
		return borderLeft + borderRight + paddingLeft + paddingRight;
	},
	
	/**
	 * @param	{object}	element
	 * @returns The IE5 height offset for a DOM Element.
	 * @access	public
	 */
	getIEBoxHeightOffset: function( element )
	{
		var paddingTop	= Element.getStyle( element, 'padding-top' );
		var paddingBot 	= Element.getStyle( element, 'padding-bottom' );
		
		var borderTop	= Element.getStyle( element, 'border-top-width' );
		var borderBot 	= Element.getStyle( element, 'border-bottom-width' );
		
		paddingTop = (paddingTop) ? isNaN(parseInt(paddingTop)) ? 0 : parseInt(paddingTop) : 0;
		paddingBot = (paddingBot) ? isNaN(parseInt(paddingBot)) ? 0 : parseInt(paddingBot) : 0;
		
		borderTop = (borderTop) ? isNaN(parseInt(borderTop)) ? 0 : parseInt(borderTop) : 0;
		borderBot = (borderBot) ? isNaN(parseInt(borderBot)) ? 0 : parseInt(borderBot) : 0;
		
		return borderTop + borderBot + paddingTop + paddingBot;
	},

	/**
	 * Returns all elements of a given tagName nested inside the given element
	 * @param	element
	 * @param	tagName
	 * @returns	array	Array of elements
	 */
	getElementsByTagName: function( element, tagName ) 
	{
		return element.getElementsByTagName( tagName );
	},
	
	getAttributeValue: function( element, attribute, defaultValue )
	{
		var attributeValue = element.getAttribute( attribute );
	
		if (!attributeValue) {
			if ( defaultValue != null )
				return defaultValue;
				
			return false;
		}
		
		switch (attributeValue) {
			case 'true':
				attributeValue = true;
				break;
			case 'false':
				attributeValue = false;
				break;
			default:
				break;
		}
	
		return attributeValue;
	},
	
	setDimension: function( element, width, height )
	{
		try {
			var element = $(element);
		
			if (typeof width != 'string')
				width += 'px';
			
			if (typeof height != 'string')
				height += 'px';
			
			element.style.width = width;
			element.style.height = height;
		} catch(e) {
			if (e instanceof Error)
				throw new Error('Element::setDimension(): ' + e.name + ' ' + e.message);
		}
	},
	
	setPosition: function( element, top, left ) 
	{
		try {
			var element = $(element);
			
			if (typeof top != 'string')
				top += 'px';
			
			if (typeof left != 'string')
				left += 'px';
				
			element.style.top = top;
			element.style.left = left;
		} catch (e) {
			if (e instanceof Error)
				throw new Error('Element::setPosition(): ' + e.name + ' ' + e.message);
		}
	},
	
	getChildNodesByTagName: function( element, tagName )
	{
		var cNodes = [];
		var element = $(element);
		
		for (var i=0; i < element.childNodes.length; i++) {
			if (element.childNodes[i].nodeType == 1 && element.childNodes[i].tagName.toLowerCase() == tagName.toLowerCase()) {
				cNodes[cNodes.length] = element.childNodes[i];
			}
		}
				
		return cNodes;
	},
	
	getFirstChildByTagName: function( element, tagName )
	{	
		for (var i=0; i < element.childNodes.length; i++) {
			if (element.childNodes[i].nodeName.toLowerCase() == tagName.toLowerCase()) {
				return element.childNodes[i];
			}
		}
		
		return false;
	},
	
	getFirstChild: function( element )
	{
		for (var i=0; i < element.childNodes.length; i++) {
			if ( element.childNodes[i].nodeType == 1 ) {
				return element.childNodes[i];
			}
		}
		
		return false;
	},
	
	getParentAttributeValue: function(element, attribute, defaultValue)
	{
		while (element != null && element.nodeType != 9 ) {
			if (element.getAttribute( attribute ) ) {
				return element.getAttribute( attribute );
			}
			
			element = element.parentNode;
		}
		
		if ( !isEmptyValue( defaultValue ) ) {
			return defaultValue;
		}
		
		return false;
	},
	
	/**
	 * @param	{object}	element
	 * @param	{string}	tagName
	 * @param	{boolean}	checkelement	Set this to true if you want to perform a check on the given element
	 * @returns An element of a given tagName or false if there is no such element in the document tree
	 * @access	public
	 */
	getParentElementByTagName: function( element, tagName, checkelement )
	{
		var tagName = tagName.toLowerCase();
		
		if (checkelement != null && checkelement) {
			if( element.tagName.toLowerCase() == tagName.toLowerCase() ) {
				return element;
			}
		}
			
		while (element != null && element.nodeType != 9) {
	    	if (element.nodeType == 1 && element.tagName.toLowerCase() == tagName.toLowerCase()) {
	    		return element;
	    	}
	      	
	    	element = element.parentNode;
		}
		
		return false;
	},
	
	/**
	 * @param	{object}	element		DOM Element
	 * @param	{string}	tagName			tag name to search for
	 * @param	{string}	attribute		attribute to search for
	 * @param	{bool}		checkelement	If set to true the function checks also the given element
	 * @returns	The Element if found, FALSE otherwise
	 * @access	public
	 */
	getParentElementByTagNameAndAttribute: function( element, tagName, attribute, checkelement )
	{
		if (element == null) {
			var element = element.parentNode;
		}
		
		var tagName = tagName.toLowerCase();
		
		if (checkelement != null && checkelement) {
			if ( element.tagName.toLowerCase() == tagName.toLowerCase() && element.getAttribute( attribute ) ) {
				return element;
			}
		}
		
		while ( element != null && element.nodeType != 9) {
			if (element.nodeType == 1 && element.tagName.toLowerCase() == tagName.toLowerCase() && element.getAttribute( attribute ) ) {
				return element;
			}
			
			element = element.parentNode;
		}
		
		return false;
	},
	
	/**
	 * @param	{object}	element
	 * @param	{string}	nodeType
	 * @returns	An element of a given node type or false if there is no such element in the document tree
	 * @access	public
	 */
	getParentElementByNodeType: function( element, nodeType, checkelement)
	{	
		while (element != null && element.nodeType != 9) {
	    	if (element.nodeType != null && element.nodeType == nodeType) {
	    		return element;
	    	}
	      	
	    	element = element.parentNode;
		}
		
		return false;
	},
	
	getInnerText: function( element )
	{
		if (typeof(element) == "string")
			var element = $( element );
			
		if (typeof element == "undefined")
			return element;
		
		if (element.innerText)
			return element.innerText;
			
		var text 		= "";
		var childNodes 	= element.childNodes;
		var length 		= element.childNodes.length;
		
		for (var i = 0; i < length; i++) {
			switch (childNodes[i].nodeType) {
				case 1:
					text += Element.getInnerText(childNodes[i]);
					break;
				case 3:
					text += childNodes[i].nodeValue;
					break;
			}
		}
		
		return text;
	},
	
	hasChildNodesWithNodeType: function( element, nodeType )
	{
		if (nodeType == null) {
			var nodeType = 1;
		}
		
		for (var i=0; i < element.childNodes.length; i++) {
			if (element.childNodes[i].nodeType == nodeType) { 
				return true;
			}
		}
			
		return false;
	},
	
	hasChildNodesWithTagName: function( element, tagName )
	{
		for (var i=0; i < element.childNodes.length; i++) {
			if (element.childNodes[i].nodeName == tagName) {
				return true;
			}
		}
				
		return false;
	},
	
	/**
	 * Checks if an Element has a parent element with a given attribute
	 * @param	{object}	element
	 * @param	{string}	attribute	
	 * @returns	True if an element has a parent node with a given attribute
	 * @access	public
	 */
	
	hasParentWithAttribute: function( element, attribute )
	{
		while ( element != null && element.nodeType != 9 ) {
			if ( element.hasAttribute ) {
				if ( element.hasAttribute( attribute) ) {
					return true;
				}
			} else {
				if ( element.getAttribute( attribute ) != null ) {
					return true;
				}
			}
			
			element = element.parentNode;
		}
		
		return false;
	},
	
	/**
	 * Checks is an Element has a Parent Element with a specific attribute value
	 * @param	{object}	element
	 * @param	{string}	attribute
	 * @param	{string}	value
	 * @returns True if a DOM element has a parent attribute with a given attribute set to specific value, otherwise false.
	 * @access	public
	 */
	hasParentWithAttributeValue: function( element, attribute, value )
	{
		while (element != null && element.nodeType != 9) {
			attributeValue = element.getAttribute( attribute );
			
			if (attributeValue != null && attributeValue == value) {
				return true;
			}
			
			element = element.parentNode;
		}
		
		return false;
	},
	
	/**
	 * Checks if an element is a child Component of given EK Type
	 *
	 * @param	{object}	DOM Element
	 *
	 * @returns Id of parent EK Element, FALSE otherwise
	 * @access	public
	 */
	isChildOf: function( element, type )
	{
		var parentItem = element.parentNode;
		
		while(parentItem != null && parentItem.nodeType != 9) {
			if (parentItem.nodeName == 'DIV' && ( parentItem.getAttribute( 'ektype' ) == type || parentItem.getAttribute( 'ctrltype' ) == type)) {
				return parentItem.id;
			}
			
			parentItem = parentItem.parentNode;
		}
		
		return false;
	},
	
	/**
	 * Checks if an element is in a TabCtrl
	 * @param	{mixed}		element	ID or DOM Element
	 * @returns Id of Tab where the element is in, FALSE otherwise
	 * @access	public
	 */
	isInTab: function( id )
	{
		var parentItem = $(id).parentNode;
		
		while(parentItem != null && parentItem.nodeType != 9) {
			if (parentItem.nodeName == 'DIV' && parentItem.getAttribute('ctrltype') == 'tabpanel') {
				return parentItem.id;
			}
			
			parentItem = parentItem.parentNode;
		}
		
		return false;
	},
	
	/**
	 * Checks if an element is in an EasyGUI Table
	 * @param	{mixed}	element 	ID or DOM Element
	 * @returns	Id of Table where the element is in, FALSE otherwise
	 * @access	public
	 */
	isInTable: function( element )
	{
		var parentItem = $(element).parentNode;
	
		while(parentItem != null && parentItem.nodeType != 9 ) {
			if (parentItem.nodeName == 'TABLE' && parentItem.getAttribute('ektype') == 'Table') {
				return parentItem.id;
			}
			
			parentItem = parentItem.parentNode;
		}
		
		return false;
	},
	
	/**
	 * Allows select on element identified by id
	 * @param {string} element	Id of Element or element
	 * @returns	void
	 * @access	public
	 */
	allowSelect: function( element )
	{
		var element = $( element );
	
		if (element.onselectstart) {
			Event.observe( element, 'selectstart', Event.stop );
		}
	},
	
	_toggle: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = $(arguments[i]);
			
			if( element == null ) {
				return;
			}
			
			Element[Element.visible(element) ? 'hide' : 'show'](element);
		}
	},
	
	_hide: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = $(arguments[i]);
			
			if ( element == null ) {
				return;
			}
			
			if ( dialog && element ) {
				if ( dialog[arguments[i]] ) {
					dialog[element.id].hide();
					return;
				}
			}	 
			
			element.style.visibility = 'hidden';
		}
	},
	
	_show: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = $(arguments[i]);
			
			if ( element == null ) {
				return;
			}
			
			if ( dialog && element ) {
				if ( dialog[arguments[i]] ) {
					dialog[element.id].show();
					return;
				}
			} 
			
			element.style.visibility = 'visible';
		}
	}
});

if ( is.ie5_5 || is.ie5) {
	document._getElementsByTagName = document.getElementsByTagName;
	document.getElementsByTagName = function ( sTagName )
	{
		if ( sTagName == "*" ) {
			return document.all;
		} else {
			return document._getElementsByTagName( sTagName );
		}
	};
}