if(typeof LITHIUM == "undefined") { var LITHIUM={}; };
if(typeof LITHIUM.Dom == "undefined") { LITHIUM.Dom={}; };

LITHIUM.Dom.CLICK = "click";
LITHIUM.Dom.MOUSEOVER = "mouseover";

LITHIUM.Dialog = Class.create({
	initialize: function(element, url, windowName, options, className) {		
		this.element = element;
		this.originalUrl = url;
		this.url = url;
		this.windowName = windowName;
		this.className = className || false;
		this.options = options || "width=300,height=400,scrollbars=yes,resizable=yes";		
		if(this.className != false) {
			this.element = $(this.element).down("." + className);
		}		
		$(this.element).addClassName("dialog-link");
		this.beforeOpenMethod = false;
		Event.observe(this.element, 'click', this.openWindow.bind(this));	
	},
	openWindow: function(event) {
		Event.stop(event);		
		if (this.beforeOpenMethod != false) {
			this.beforeOpenMethod(this);
		}
		if (this.url != false) {
			//LIA-8696
			//When a component is re-rendered via Ajax, its id comes back with a '-' rather than a '_' as its delimiter;
			//IE doesn't like an '-' in a window name passed to window.open[!]; hence, if that delimiter is in place, we replace
			//it with the non-ajax-rendered delimiter, and all is well. Considered handling this server-side, but this
			//seems like a client-side quirk, and thus can be addressed here as such.
			var formattedName = this.windowName.gsub(" ", "");
			formattedName = formattedName.replace('-', '_');
			window.open(this.url, formattedName, this.options.toString());
		}		
	},
	setBeforeOpenMethod: function(method) {
		this.beforeOpenMethod = method;
	}
});

LITHIUM.Warning = Class.create({
	initialize: function(error) {
		alert(error);
	}
});

/**
 * This code is used to mimic the core tapestry JS that hides all elements with the CSS class of "t-invisible" then removes
 * the class name. This enables us to then do a Element#show() and Element#hide() as needed through JS and not have the 
 * element intially show up during page load.
 */
document.observe("dom:loaded", function() {
	$$(".t-invisible").invoke("hide").invoke("removeClassName", "t-invisible");			
});

LITHIUM.CustomEvent = {
	register:function(element, triggerEvent, fireEvent, eventContext) {
		var element = $(element);
		Event.observe(element, triggerEvent, function(event) {						
			var customEvent = element.fire(fireEvent, eventContext);
			if (customEvent.stopped) { 
				event.stop();
			}
		});		
	}
} 

LITHIUM.Toggle = Class.create({
	initialize:function(switchElement, toggleElement) {
		this.toggleElement = $(toggleElement)		
		if ($F(switchElement) !== "on") {
			this.toggleElement.hide();
		}
		this.toggleElement.removeClassName("hidden");		
		Event.observe(switchElement, "click", function(event) {
			$(toggleElement).toggle();
		})
	}
});

/**
 * The methods Element#getOffsetParent and Element#viewportOffset cause a bug in IE7.  Updating these methods
 * per the patch listed here: http://dev.rubyonrails.org/attachment/ticket/11473/getOffsetParent_viewportOffset_fix.diff.
 * TODO: This should be removed once prototype 1.6.0.3 is released.
 */
Element.addMethods({ 
	getOffsetParent: function(element) { 
		element = $(element);   
	 	var op = element.offsetParent, body = document.body, docEl = document.documentElement;   
	 		 
	 	/* IE with strict doctype may try to return documentElement as offsetParent   
	 	   on relatively positioned elements, we will return body instead */   
	 	if (op && op !== docEl) return $(op);   
	 	if (op === docEl || element === docEl || element === body) return $(body);   
	 	      
	 	while ((element = element.parentNode) && element !== body)   
			if (Element.getStyle(element, 'position') != 'static') 
				return $(element); 
		 
	 	return $(body); 
	}, 
	
  viewportOffset: function(forElement) {
    forElement = $(forElement);
    var element = forElement, valueT = 0, valueL = 0
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent == document.body &&
        Element.getStyle(element, 'position') == 'absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      
    } while ((element = element.getOffsetParent()) != document.body);

    return Element._returnOffset(valueL, valueT);
  }
});

/**
 * A JavaScript object that manages triggering an open and close function after a configurable timeout.
 *
 * @author Adam Ayres
 * @date 09/18/2008
 *
 * @param element The id or element to apply the delayed toggle to
 * @param options A object literal that contains the following options:
 *		@param openFunction The function that gets fired when the openEvent occurs after the openDelayMs time period.
 *		@param closeFunction The function that gets fired when the closeEvent occurs after the closeDelayMs time period.
 *		@param openDelayMs The amount of time to wait before triggering the openFunction.
 *		@param closeDelayMs The amount of time to wait before triggering the closeFunction.
 *		@param openEvent The dom event to observe on the specified element that triggers the open timer to start.
 *		@param closeEvent The dom event to observe on the specified element that triggers the close timer to start.
 */
LITHIUM.DelayToggle = Class.create({
	initialize: function(element, options) {
		this.element = $(element);
		//Setup options
		this.options = {
			openFunction: function(item) { item.show() },
			closeFunction: function(item) { item.hide() },
			openDelayMs: 500,
			closeDelayMs: 100,
			openEvent: "mouseover",
			closeEvent: "mouseout"
		}
		Object.extend(this.options, options || {});		
		
		//Initialize state
		this.enabled = false;
		this.timeout = false;
		
		//Apply event listeners		
		if (this.openEvent != false) {			
			Event.observe(this.element, this.options.openEvent, this.delayedOpen.bindAsEventListener(this));	
		}	
		if (this.closeEvent != false) {
			Event.observe(this.element, this.options.closeEvent, this.delayedClose.bindAsEventListener(this));	
		}		
	},	
	delayedOpen: function(event) {
		clearTimeout(this.timeout);
		if (this.enabled == false) {			
			this.timeout = setTimeout(function(){
				this.enabled = true;						
				this.options.openFunction(this.element);
			}.bind(this),this.options.openDelayMs);	
		}
	},
	delayedClose: function(event) {			
		if (this.enabled == false) {
			clearTimeout(this.timeout);	
		} else {
			this.timeout = setTimeout(function(){
				this.enabled = false;
				this.options.closeFunction(this.element);
			}.bind(this),this.options.closeDelayMs);			
		}        		
	}
});

LITHIUM.Cookie = {	
	/**
	 * Create a cookie
	 * @param {String} name Name of cookie
	 * @param {String} value value of cookie
	 * @param {int} days Nmuber ofdays  
	 */
	createCookie: function(name,value,days) {
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else {
			var expires = "";
		}
		return document.cookie = name+"="+value+expires+"; path=/";
	},
	/**
	 * Read a cookie
	 */
	readCookie: function(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return null;
	},
	/**
	 * Erase a cookie
	 */
	eraseCookie: function(name) {
		this.createCookie(name,"",-1);
	}
}
	