/**
 * CHIP Javascript Library Version 0.0.1
 * Prototype and Scriptaculous Extensions
 *
 * @version $Id: chiplib.js 14909 2008-02-28 10:30:48Z djungowski $
 * 
 * @author mtrinczer
 * @author djungowski
 */

Element.addMethods({
	/**
	 * Inserts Elements before, after or inside an element
	 */
	inject: function(element, el, where) {
		element = $(element);
		var el = $(el);
		switch (where){
			case "before": $(el.parentNode).insertBefore(element, el); break;
			case "after":
				if (!el.next()) $(el.parentNode).appendChild(element);
				else $(el.parentNode).insertBefore(element, el.next());
			break;
			case "inside": el.appendChild(element);
		}
		return element;
	},
	
	/**
	 * Property: injectBefore
	 * Inserts the Element before the passed element.
	 *
	 * Parameters:
	 * el - a string representing the element to be injected in (myElementId, or div), or an element reference.
	 * If you pass div or another tag, the element will be created.
	 */
	injectBefore: function(element, el) {
		element = $(element);
		return element.inject(el, 'before');
	},
	
	/**
	 * Property: injectAfter
	 * Same as <Element.injectBefore>, but inserts the element after.
	 */
	injectAfter: function(element, el) {
		element = $(element);
		return element.inject(el, 'after');
	},
	
	/**
	 * Property: injectInside
	 * Same as <Element.injectBefore>, but inserts the element inside.
	 */
	injectInside: function(element, el) {
		element = $(element);
		return element.inject(el, 'inside');
	},
	
	/**
	 * Property: clone
	 * Clones the Element and returns the cloned one.
	 *
	 * Parameters:
	 * @param newId		Change the ID of the cloned element
	 * @param contents	boolean, when true the Element is cloned with childNodes, default true
	 *
	 * Returns:
	 * the cloned element
	 * 
	 * Examples:
	 * >var clone = $('myElement').clone().injectAfter('myElement');
	 * >//clones the Element and append the clone after the Element.
	 *
	 * >var clone = $('div4').clone('div6').injectAfter('div1');
	 * >//clones the Element, changes its id and appends it after the element div1
	 */
	clone: function(element, newId, contents) {
		element = $(element);
		var el = element.cloneNode(contents !== false);
		if (typeof newId != 'undefined' && typeof newId != false) {
			el.id = newId;
		}
		return $(el);
	},
	
	/**
	 * Uses the Scriptaculous appear effect to show or hide a DOM Element
	 * 
	 * Example:
	 *  > $('myElement').fade();
	 * Example 2:
	 * var spanElements = document.getElementsByTagName('span');
	 * > $('myElement').fade({hideId: 'elementOfIdtoHide', hideClass: 'className', hideElements: spanElements});
	 */
	fade: function(element, options) {
		element = $(element);
		var hideDomElements = [];
		
		// Get options
		if(typeof options == 'object') {
			// Id of a DOM Element to hide
			if (typeof options.hideId != 'undefined') {
				hideDomElements.push($(options.hideId));
			}
			// Class name of DOM Element(s) to hide
			if (typeof options.hideClass != 'undefined') {
				var classElements = getElementsByClass(options.hideClass);
				for (var i in classElements) {
					hideDomElements.push(classElements[i]);
				}
			}
			// DomElements to hide, must be ArrayObject (like hideDomElements)
			if (typeof options.hideElements == 'object') {
				for (var i in options.hideElements) {
					hideDomElements.push(options.hideElements[i]);
				}
			}
		}
		// Is the element visible or not?
		var isVisible = element.visible();
		// Show the element, if it is not visible
		if (!isVisible) {
			for (var i in hideDomElements) {
				// Make sure, that the element is really an object
				if (typeof hideDomElements[i] == 'object') {
					// Fix: Getting the object again
					var domElement = $(hideDomElements[i]);
					domElement.hide();
				}
			}
			// Try to fade in, if not successful use show() function to show
			try {
				Effect.toggle(element, 'appear', {duration: 0.5});
			} catch(e) {
				element.show();
			}
		// Hide the element, if it is visible
		} else {
			// Try to fade out, if not successful use hide() function to show
			try {
				Effect.toggle(element, 'appear', {duration: 0.5});
			} catch(e) {
				element.hide();
			}
		}
		return element;
	},
	
	/**
	 * Uses the Scriptaculous BlindUp/BlindDown effect to fold a DOM Element up or down
	 * 
	 * Example 1:
	 *  > $('myElement').fold();
	 * Example 2:
	 * > $('myElement').fold({duration: 5});
	 */
	fold: function(element, options) {
		element = $(element);
		var foldDuration = "0.2";
		// Get options
		if(typeof options == 'object') {
			if (typeof options.duration != 'undefined') {
				foldDuration = options.duration;
			}
		}
		var isVisible = element.visible();
		if (isVisible) {
			try {
				Effect.BlindUp(element, {duration: foldDuration});
			} catch (e) {
				element.hide();
			}
		} else {
			try {
				Effect.BlindDown(element, {duration: foldDuration});
			} catch (e) {
				element.show();
			}
		}
	},
	
	/**
	 * Get elements by a given classname
	 *
	 * @param object element
	 * @param string className
	 * @return array
	 */
	getElementsByClass: function(element, className){
		return getElementsByClass(className, element);
	}
});

/**
 * Get elements by a given classname (contains workarounds
 * various browsers)
 * this function is not in the document scope since konqueror
 * could not handle that
 *
 * @param string className
 * @param object parentElement
 * @return array
 */
getElementsByClass = function(className, parentElement){
	try {
		//konqueror workaround: try with the parentElement first
		//and in case of failure: without
		try {
			var elements = $$('.' + className, parentElement);
		} catch (e1) {
			var elements = $$('.' + className);
		}
	} catch (e) {
		//safari workaraound: only the (deprecated)
		//getElementsByClassName() is available
		var elements = document.getElementsByClassName(className, parentElement);
	}
	return elements;
}