//***********************************************************************************************************************************/
// DynBox Class
// Author: mydiscog.com
// Date: October 2009
// License: Creative Commons Attribution 3.0 License (http://creativecommons.org/licenses/by/3.0/)
//
// Credit: 	DynBox is a ajax-content-only adaptation of Lytebox (written by Markus F. Hay, see http://www.dolem.com/lytebox/)
// 			DynBox will only show dynamic ajax content in the lightbox (no images, no slideshows, no iframe content...)
// 			LyteBox was itself derived from the Lightbox class (v2.02) that was written by Lokesh Dhakar (http://huddletogether.com/projects/lightbox2/)
//***********************************************************************************************************************************/

// constants
gbDebug = false;

// default options
var gaDynBoxDefaultOptions = {
	fxDuration : 0.2,
	onClose : null // Close button action
}

// class DynBox: overlay div, with dynamic ajax content
var DynBox = Class.create({
	oOverlay : null, // overlay behind the box
	oDialog : null, // container to show/hide with all decoration elements
	oContainer : null, // ajax final content container
	oContainerOut : null, // outer container with border.. the one to resize
	oSpinner: null, // spinner
	oTemplate:null, // is the size of opening dialog is known in advance ?
	responseText:null, // ajax response
	options : null, // options given on init merged with default
	doc : null, // main document
	isFrame : false, // are we inside a frame?
	ie : false,
	ie7 : false,
	
	// init
	initialize : function(options){
		var bOk = true;
		// init
		try{
			// merge options
			this.options = Object.extend(Object.extend({ }, gaDynBoxDefaultOptions), options || { });
			// is frame ?
			if (window.parent.frames[window.name] && (parent.document.getElementsByTagName('frameset').length <= 0)) {
				this.isFrame = true;
				this.lytebox = "window.parent." + window.name + ".myDynBox";
				this.doc = parent.document;
			} else {
				this.isFrame = false;
				this.lytebox = "myDynBox";
				this.doc = document;
			}
			
			// ie ?
			/*@cc_on
				/*@if (@_jscript)
					this.ie = (document.all && !window.opera) ? true : false;
				/*@else @*/
					this.ie = false;
				/*@end
			@*/
			this.ie7 = (this.ie && window.XMLHttpRequest);			
		}
		catch(e){
			bOk = false;
			this.handleEx(e);
		}

		// add all graphical elements, the overlay and the box
		this.DynBoxBuildBox();
		
		// pimp all links needing DynBox
		this.DynBoxUpdate();

		// return
		return bOk;
	},
	
	// add overlay and box
	DynBoxBuildBox : function(){
		var objBody = this.doc.getElementsByTagName("body").item(0);
		
		if (this.doc.getElementById('lbOverlay')) {
			objBody.removeChild(this.doc.getElementById("lbOverlay"));
			objBody.removeChild(this.doc.getElementById("lbMain"));
		}
		
		var objOverlay = this.doc.createElement("div");
			objOverlay.setAttribute('id','lbOverlay');
			objOverlay.setAttribute((this.ie ? 'className' : 'class'), this.theme);
			if ((this.ie && !this.ie7) || (this.ie7 && this.doc.compatMode == 'BackCompat')) {
				objOverlay.style.position = 'absolute';
			}
			objOverlay.style.display = 'none';
			objBody.appendChild(objOverlay);
						
		var objLytebox = this.doc.createElement("div");
			objLytebox.setAttribute('id','lbMain');
			objLytebox.style.display = 'none';
			objBody.appendChild(objLytebox);
			
		var objOuterContainer = this.doc.createElement("div");
			objOuterContainer.setAttribute('id','lbOuterContainer');
			objOuterContainer.setAttribute((this.ie ? 'className' : 'class'), this.theme);
						
		var objImageContainer = this.doc.createElement("div");
			objImageContainer.setAttribute('id','lbImageContainer');
			objOuterContainer.appendChild(objImageContainer);
			
		var objLoading = this.doc.createElement("div");
			objLoading.setAttribute('id','lbLoading');
			objOuterContainer.appendChild(objLoading);

		var oCloseButton = this.doc.createElement("div");
			oCloseButton.setAttribute('id','lbCloseButton');
			oCloseButton.setAttribute((this.ie ? 'className' : 'class'), this.theme);
			objOuterContainer.appendChild(oCloseButton);
			objLytebox.appendChild(objOuterContainer);

		
		// direct obj properties	
		this.oOverlay = $(objOverlay);
		this.oDialog = $(objLytebox);
		this.oContainerOut = $(objOuterContainer);
		this.oContainer = $(objImageContainer);
		this.oSpinner = $(objLoading);
		
		// close events
		$(oCloseButton).observe('click', function(){myDynBox.DynBoxClose();return false;});
		this.oOverlay.observe('click', function(){myDynBox.DynBoxClose();return false;});
		this.oDialog.onclick = function(e) {
			var e = e;
			if (!e) {
				if (window.parent.frames[window.name] && (parent.document.getElementsByTagName('frameset').length <= 0)) {
					e = window.parent.window.event;
				} else {
					e = window.event;
				}
			}
			var id = (e.target ? e.target.id : e.srcElement.id);
			if (id == 'lbMain') { myDynBox.DynBoxClose(); return false; }
		}
		
	},
	
	// find all elements to switch (class="dynbox") in the container and pimp them with DynBox events
	DynBoxUpdate : function(){
		// find all links thats needs dynbox
		$$('[rel="dynbox"]').each(function(elem){
			elem.stopObserving('click');
			elem.observe('click', function(){myDynBox.DynBoxOpen(elem);});
		}.bind(this));
	},
	
	// open the dialog and show content
	DynBoxOpen :function(elem){
		// position
		var pageSize = this.getPageSize();
		this.oOverlay.style.height = pageSize[1] + "px";
		this.oDialog.style.top = (this.getPageScroll() + (pageSize[3] / 15)) + "px";
		
		// show dialog + spinner
		this.oOverlay.show();
		this.oDialog.show();
		this.oSpinner.show();

		// load content
		this.DynBoxLoadContent(elem);
	},
	
	// close the dialog
	DynBoxClose :function(){
		if (this.options.onClose){
			// call just once. so we reset 
			var tmpOnClose = this.options.onClose;
			this.options.onClose = null;
			tmpOnClose();
		}
		else{
			// reset starting dimensions
			this.oContainerOut.setStyle('width:200px;height:200px;');
			this.oContainer.style.width = null;
			this.oContainer.style.height = null;
			this.oContainer.update('reset');

			this.oOverlay.hide();
			this.oDialog.hide();
		}
	},
	
	DynBoxLoadContent : function(elem){
		// semaphore
		if (this.bAjaxRunning){
			return false;
		}
		this.bAjaxRunning = true;
		
		// load page requested in _href (_href and not href will avoid a click on that link to open a new page before DynBox has initialized)
		var bOk = true;
		var sUrl = elem.readAttribute('_href');
		var sTpl = elem.readAttribute('tpl');
		var sRev = elem.readAttribute('rev');
		// sizes in rev are higher priority than tpl
		if (sRev){
			this.oTemplate = eval('(' + sRev + ')');
		}else{
			// size is fixed, we read in it "tpl" attribute, then in global arrays of sizes
			this.oTemplate = sTpl ? gaLyteboxDialogTemplates[sTpl] : null;
		}
		
		// hide content before loading
		this.oContainer.hide();
		
		// ajax load
		if (bOk){
			try{
				new Ajax.Request(sUrl,{
					method:'get',
					onSuccess: function(transport){
						this.responseText = null;
						// if the size is not fixed, we update content first to get size (we are still hidden here)
						if (!this.oTemplate){
							this.oContainer.update(transport.responseText);
						}else{
							// we keep to update content when resizing is finished (flash can use 100% then from inside the box...:)
							this.responseText = transport.responseText;							
							transport.responseText = null;
						}

						// resize container (getDimensions includes the padding)
						var oSize = this.oTemplate ? this.oTemplate : this.oContainer.getDimensions();
						this.oContainer.setStyle('width:' + (oSize.width) + 'px;height:' + (oSize.height) + 'px;');
						
						// resize container Out (with padding)
						oSize.width+=20;
						oSize.height+=20;
						
						// fx or not ?
						if (this.options.fxDuration>0){
							// fx : morph containerOut (20 is 2x10 padding)
							this.oContainerOut.morph('width:' + (oSize.width) + 'px;height:' + (oSize.height) + 'px;', {
								duration:this.options.fxDuration, 
								afterFinish:function(){
									// if size was fixed, we update content only now
									if (this.oTemplate){
										this.oContainer.update(this.responseText).show();
									}
									this.oContainer.show();
									try{this.oContainer.down('.focus').focus();}catch(e){};
									this.oSpinner.hide();
									this.bAjaxRunning = false;
								}.bind(this)
							});
						}
						else{
							// no fx : we size directly and show (20 is 2x10 padding)
							this.oContainerOut.setStyle('width:' + (oSize.width) + 'px;height:' + (oSize.height) + 'px;');
							if (this.oTemplate){
								this.oContainer.update(this.responseText);
							}
							this.oContainer.show();
							try{this.oContainer.down('.focus').focus();}catch(e){};
							this.oSpinner.hide();
							this.bAjaxRunning = false;
						}

						
					}.bind(this)
				});
			}
			catch(e){
				// semaphore off
				this.bAjaxRunning = false;
				// error
				bOk = false;
				this.dynHandleEx(e, 'DynBoxLoadContent');
			}
		}
		
		return bOk
	},
	
	getPageScroll : function() {
		if (this.pageYOffset) {
			return this.isFrame ? parent.pageYOffset : this.pageYOffset;
		} else if (this.doc.documentElement && this.doc.documentElement.scrollTop){
			return this.doc.documentElement.scrollTop;
		} else if (document.body) {
			return this.doc.body.scrollTop;
		}
	},
	
	getPageSize :function() {	
		var xScroll, yScroll, windowWidth, windowHeight;
		if (window.innerHeight && window.scrollMaxY) {
			xScroll = this.doc.scrollWidth;
			yScroll = (this.isFrame ? parent.innerHeight : self.innerHeight) + (this.isFrame ? parent.scrollMaxY : self.scrollMaxY);
		} else if (this.doc.body.scrollHeight > this.doc.body.offsetHeight){
			xScroll = this.doc.body.scrollWidth;
			yScroll = this.doc.body.scrollHeight;
		} else {
			xScroll = this.doc.getElementsByTagName("html").item(0).offsetWidth;
			yScroll = this.doc.getElementsByTagName("html").item(0).offsetHeight;
			xScroll = (xScroll < this.doc.body.offsetWidth) ? this.doc.body.offsetWidth : xScroll;
			yScroll = (yScroll < this.doc.body.offsetHeight) ? this.doc.body.offsetHeight : yScroll;
		}
		if (self.innerHeight) {
			windowWidth = (this.isFrame) ? parent.innerWidth : self.innerWidth;
			windowHeight = (this.isFrame) ? parent.innerHeight : self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) {
			windowWidth = this.doc.documentElement.clientWidth;
			windowHeight = this.doc.documentElement.clientHeight;
		} else if (document.body) {
			windowWidth = this.doc.getElementsByTagName("html").item(0).clientWidth;
			windowHeight = this.doc.getElementsByTagName("html").item(0).clientHeight;
			windowWidth = (windowWidth == 0) ? this.doc.body.clientWidth : windowWidth;
			windowHeight = (windowHeight == 0) ? this.doc.body.clientHeight : windowHeight;
		}
		var pageHeight = (yScroll < windowHeight) ? windowHeight : yScroll;
		var pageWidth = (xScroll < windowWidth) ? windowWidth : xScroll;
		return new Array(pageWidth, pageHeight, windowWidth, windowHeight);
	},
	
	
	// handle exceptions
	handleEx : function(e, sContext){
		var sError =  e.message;
		if (gbDebug){
			sContext = sContext ? ' (' + sContext + ') ' : '';
			alert("Exception" + sContext + ":\n" + sError);
		}
	},
	
	/* public function */
	// show spinner
	showSpinner : function(){
		this.oContainer.hide();
		this.oSpinner.show();
	},
	
	// hide spinner
	hideSpinner : function(){
		this.oContainer.show();
		this.oSpinner.hide();
	},
	
	// find all elements to switch (class="dynbox") in the page and pimp them with DynBox events
	update : function(){
		this.DynBoxUpdate();
	},
	
	// close the dialog
	close :function(){
		this.DynBoxClose();
	}	
});


/* Create a Dynbox ready to use when this script is included */
myDynBox = null;
document.observe("dom:loaded", function() {
	myDynBox = new DynBox();
});
