/*
 *   Extend Element Object. All methods return 
 *   original element unless otherwise stated.
 */
Element.addMethods({
	/* Is this DOM element in the DOM at all? */
	exists: function(element) {
		return present(element);
	},
	/* Extracts element from Parent node, removes parent and replaces element in place of parent. Returns element */
	extract: function(element) {
		var extractedElement = element.firstDescendant();
		var inner = element.contents();
		element.replace(inner);
		return extractedElement;
	},
	/* Moves Element into new Parent. Returns transported element */
	transport: function(element, destination) {
		element = $(element);
		$(destination).insert({ bottom: element });
		return element;
	},
	/* Switches position of element and previous sibling (if exists) */
	ascend: function(element) {
		element = $(element);
		var previous = element.previousSiblings().first();
		if (previous != undefined) {
			previous.insert({ before: element });
			return element;
		}
		return false;
	},
	/* Switches position of element and next sibling (if exists) */
	descend: function(element) {
		element = $(element);
		var next = element.nextSiblings().first();
		if (next != undefined) {
			next.insert({ after: element });
			return element;
		}
		return false;
	},
	/* Moves element to be first sibling */
	makeFirstChild: function(element) {
		element = $(element);
		element.up().insert({top:element});
		return element;
	},
	/* Moves element to be first sibling */
	makeLastChild: function(element) {
		element = $(element);
		element.up().insert({bottom:element});
		return element;
	},
	/* Moves element out of parent into BODY tag */
	orphanize: function(element) {
		element = $(element);
		$$('body').first().insert({ bottom: element });
		return element;
	},
	/* Make Clone of Element. Returns CLONE */
	clone: function(element, setID) {
		var clone = new Element(element.tagName);
		$A(element.attributes).each(function(attribute) { 
			if ( attribute.name != 'style' ) {
				clone[attribute.name] = attribute.value;
			}
		});		
		clone.setStyle(element.getStyles());
		clone.id = setID || element.id + '_clone';
		clone.update(element.contents());
		return clone; 
	},
	/* Return HTML Contents of Element */
	contents: function(element) {
		return $(element).innerHTML;
	},
	insertContents: function(element, contents) {
		element = $(element);
		var c = element.contents();
		c += contents;
		return element.update(c);
	},
	/* Remove all elements matching CSS selector. Returns nothing */
	removeAll: function(cssSelector) {
		$$(cssSelector).each(function(e) { 
			e.remove();
		});
	},
	/* Detect whether $target is not a descendant of $element | returns True|False */
	outside: function(target, element) {
		element = $(element);
		return ($(target).descendantOf(element)) ? false: true;
	},
	/* Opposite of above */
	inside: function(target, element) {
		return (this.outside(element, target)) ? false : true;
	},
	/* Set Width of Element */
	setWidth: function(element, width) {
		element = $(element);
		element.setStyle({ width: width });
		return $(element);
	},
	/* Set Height of Element */
	setHeight: function(element, height) {
		element = $(element);
		element.setStyle({ height: height });
		return $(element);
	},
	removeClassNames: function(element) {
		element = $(element);
		element.className = "";
		return element;
	},
	safeRemove: function(element) {
		element = $(element);
		if (present(element)) element.remove();
		else return false;
	},
	/* Place element in center of viewport */
	centerize: function(element) {
		element = $(element);
		var elementDimensions = element.getDimensions();
		var centerX = (document.viewport.getDimensions().width / 2 - elementDimensions.width / 2);
		var centerY = (document.viewport.getDimensions().height / 2 - elementDimensions.height / 2);
		element.setStyle({
			position: 'absolute',
			top: Math.floor(centerY) + 'px',
			left: Math.floor(centerX) + 'px'
		});
		return element;
	},
	/* Position an element (absolutely) in the center of another */
	centerizeWithin: function(element, container) {
		element = $(element);
		container = $(container);
		var elementDims = element.getDimensions();
		var containerDims = container.getDimensions();
		var containerPos = container.positionedOffset();
		var centerX = (containerDims.width / 2 - elementDims.width / 2);
		var centerY = (containerDims.height / 2 - elementDims.height / 2);
		element.setStyle({ position: 'absolute', top: Math.floor(centerY) + 'px', left: Math.floor(centerX) + 'px' });
		return element;
	},
	/* Position an element (absolutely) topographically above another element */
	cover: function(element, container) {
		element = $(element);
		container = $(container);

		var elementDims = element.getDimensions();
		var containerDims = container.getDimensions();
		var containerPos = container.cumulativeOffset();
		var centerX = containerDims.width / 2 - elementDims.width / 2;
		var centerY = containerDims.height / 2 - elementDims.height / 2;

		var parent = container.getOffsetParent();
		element.setStyle( { top: containerPos.top + 'px', left: containerPos.left + 'px', width: containerDims.width +'px', height: containerDims.height +'px' } );
		return element;
	},
	/* Recalibrate centerization if scaled */
	recenterizeCover: function(element, activate) { 
		if (activate == 0) return false;
		element = $(element);
		element.setStyle({ 
			width: element.up().getWidth()+'px', 
			height: element.up().getHeight()+'px',
			top: element.up().positionedOffset().top+'px',
			left: element.up().positionedOffset().left+'px'
		});
		element.down().centerizeWithin(element);
		
	},
	/* Insert element */ 
	paste: function(element, parent) {
		element = $(element);
		$(parent).insert({bottom:element});
		return $(element);
	},
	/* FORM.ELEMENT: enter will submit form (or perform callback) */
	invokeEnterSubmit: function(input, defaultValue, callbackFunction) {
		input = $(input);
		input.observe('keyup', function(event) {
			if (input.value == "" || input.value == defaultValue) return false;
			if (event.keyCode == 13) {
				callbackFunction();
			}
		});
	},


	insertLoadingBars: function(element, disposition) {
		disposition = disposition || 'insert';
		Element.removeAll("#temp_bars");
		var element = $(element);
		
		if (disposition == 'insert') {
			var nuDiv = new Element('div', { id: 'temp_bars' }).update($('loadbars').contents()).setStyle({marginTop: '15px', textAlign: 'center' });
		} else {
			var nuDiv = new Element('span', { id: 'temp_bars' }).update($('loadbars').contents()).setStyle({marginLeft: '15px'});
		}
		
		element.insert({after: nuDiv});
		return nuDiv;
	},
	destroyLoadingBars: function(element) {
		var element = $(element);
		$('temp_bars').remove();
		return element;
	}
});

/*
 *   Extend String Object
 */
Object.extend(String.prototype, {
	/* Is this string a properly formatted e-mail address? */
	isValidEmail: function() {
		return (this.match(/^[\w.-]+@[-\w.]+\.[\w+]{2,3}$/)) ? this : false;
	},
	/* Wrap string within a set of HTML tags - does NOT extend DOM */
	enclose: function(tag){
		return "<"+ tag +">"+ this +"</"+ tag +">";
	}
});

/*
 *   Extend Array Object
 */
Object.extend(Array.prototype, {
	empty: function() {
		return this.size() > 0 ? false : true;
	},
	recursivelySetStyle: function(style) {
		this.each(function(e){ e.setStyle(style); });
	}
});


