﻿GScript=Object.extend({
	DynamicContent: null
}, window.GScript || {});

var DynamicContent=Class.create({
	prefixContent: null,
	prefixLoading: null,
	
	targetLayerCode: [],
	
	defaultLoadingCSSClass: 'dynamicContent_loadDefault',
	defaultEncoding: 'utf-8',
	defaultAppearDuration: 0.8,

	clickListener : null,

	initialize: function(){
		if(!this.clickListener){
			this.prefixContent = this.layerID();
			this.prefixLoading = this.layerID();
			
			this.clickListener = (function(event){
				var param = this.getParam(Event.element(event), 'dynamicContent', true);
		        if(param != null){
		        	event.stop();
		        	this.update(param);
		        }
			}).bind(this);
			document.observe('click', this.clickListener);
		}
	},
	
	destory: function(){
		document.stopObserving('click', this.clickListener);
		this.clickListner = null;
	},
	
	call: function(param, trigger){
		this.update(this.constructArrayParam(param, $(trigger) == null ? "" : ($(trigger).readAttribute("href") == null ? "" : $(trigger).readAttribute("href"))));
	},
	
	//---------------------------------------------------------------------------------------------------------
	// PRIVATE FUNCTION SECTION. SHOULD NOT BE CALLED OUTSIDE
	//---------------------------------------------------------------------------------------------------------
	
	getParam: function(trigger, keyword, propagation){
		if(propagation){
			var param = this.getParam(trigger, keyword, false);
			if(param){
				return param;
			}
			else{
				var trigger = trigger.ancestors();
				for(var i=0; i<trigger.length; i++){
					param = this.getParam(trigger[i], keyword, false);
					if(param){
						return param;
					}
				}
				return null;
			}
	 	}
	 	else{
			var param = trigger.readAttribute(keyword);
			return param == null || param.empty() ? null : this.constructArrayParam(param, trigger.readAttribute("href") == null ? "" : trigger.readAttribute("href"));
		}
	},
	 
	constructArrayParam: function(param, source){
		return Try.these(
			(function(){
				var paramArray = "<script>[" + param + "]</script>";
				paramArray = paramArray.evalScripts()[0];
				
				var date = (new Date()).getTime();
				var random = Math.round(Math.random() * 100000);

				for(var i=0; i<paramArray.length; i++){
					paramArray[i].random = random;
					paramArray[i].lastActionTime = date;

					paramArray[i].source = paramArray[i].source == null ? source : paramArray[i].source;
					paramArray[i].encoding = paramArray[i].encoding || this.defaultEncoding;
					paramArray[i].appear = paramArray[i].appear == null ? this.defaultAppearDuration : paramArray[i].appear;
					paramArray[i].effect = paramArray[i].effect == null ? "fade" : paramArray[i].effect.toLowerCase();
					paramArray[i].container = paramArray[i].container == null || paramArray[i].container.toLowerCase() != 'iframe' ? "layer" : paramArray[i].container.toLowerCase();
					paramArray[i].canAppendInfoToURL = paramArray[i].canAppendInfoToURL != "false" && paramArray[i].canAppendInfoToURL != false	? true : false;
					paramArray[i].setRelative = paramArray[i].setRelative != "false" && paramArray[i].canAppendInfoToURL != false	? true : false;
					
					// reformat the URL to solve the AJAX cache problem
					if(paramArray[i].source.toLowerCase() != '__fade__' && paramArray[i].canAppendInfoToURL && 
					   !Utility.isImgLink(paramArray[i].source) && !Utility.isFlashLink(paramArray[i].source)){
						paramArray[i].source = paramArray[i].source.indexOf("?") < 0 ? paramArray[i].source + "?lastClickTime=" + date + "_" + random : paramArray[i].source + "&lastClickTime=" + date + "_" + random;
					}
					
					// reformat the source link based on the form data
					if($(paramArray[i].formName) != null){
						options = $(paramArray[i].formName).serialize();
						if(paramArray[i].source.indexOf("?") > 0){
							paramArray[i].source += "&" + options;
						}
						else{
							paramArray[i].source += "?" + options;
						}
					}
				}
				return paramArray;
			}).bind(this)
		) || null;
	},
	
	//---------------------------------------------------------------------------------------------------------
	// MAJOR PROCESS FOR FADING
	//---------------------------------------------------------------------------------------------------------
	
	update: function(paramArray){
		if(paramArray != null){
			var loadingSource = [];
			for(var i=0; i<paramArray.length; i++){
				// run the beginning script
				this.evalScript(paramArray[i].beginScript);
				
				// fade out the layer. no need to display anything and no need for AJAX request.
				if(paramArray[i].source.toLowerCase() == '__fade__'){
					this.fadeProcess(paramArray[i]);
				}
				else{
					if(!paramArray[i].source.empty()){
						var loaded = false;
						for(var k=0; k<loadingSource.length; k++){
							if(loadingSource[k] == (paramArray[i].source + "#" + paramArray[i].encoding)){
								loaded = true;
								break;
							}
						}
						if(!loaded){
							loadingSource.push(paramArray[i].source + "#" + paramArray[i].encoding);
							this.loadSource(paramArray[i].source, paramArray[i].encoding, paramArray);
						}
					}
				}
			} // end for
		}
	},

	/**
	 * Fade out the current content
	 */
	fadeProcess: function(param){
		var isFirstClick = this.targetLayerCode[param.target] == null;
		this.targetLayerCode[param.target] = this.targetCode(param);

		// no effect is applying on this layer now
		if(isFirstClick){
			this.createLayer(param);
		}
		else{
			Utility.stopSetSize(param.target);
		}

		$(param.target).setStyle({height: $(param.target).getStyle('height'), width: $(param.target).getStyle('width')});
		$(this.prefixContent + param.target).setStyle({'position': 'absolute'});
		
		if($(this.prefixLoading + param.target).visible()){
			$(this.prefixLoading + param.target).setStyle({height: $(this.prefixLoading + param.target).getStyle('height'), width: $(this.prefixLoading + param.target).getStyle('width')});
		}
		
		if(Utility.getBrowser()=="IE" && Utility.getBrowserVersion() >= 8){
			var childs = $(this.prefixContent+ param.target).childElements();
			for(var i=0; i<childs.length; i++){
				Utility.setOpacity(childs[i].identify(), {duration: param.appear, to: 0});
			}
		}

		Utility.setOpacity(this.prefixContent + param.target, {duration: param.appear, to: 0});
		Utility.setOpacity(this.prefixLoading + param.target, {duration: param.appear, to: 0});

		setTimeout((function(){
			if(this.targetLayerCode[param.target] == this.targetCode(param)){
				var dimension = [];
				dimension.width = param.width == null ? '0px' : param.width;
				dimension.height = param.height == null ? '0px' : param.height;

				$(this.prefixLoading + param.target).setStyle({width: '100%', height: '100%'});
				$(this.prefixLoading + param.target).writeAttribute('effect', 'fade');
				Utility.setSize(param.target, {width: dimension.width, height: dimension.height, duration: param.appear});
				setTimeout((function(){
					if(this.targetLayerCode[param.target] == this.targetCode(param)){
						$(this.prefixContent + param.target).update();
						$(this.prefixContent + param.target).setStyle({width: 'auto', height: 'auto'});
						$(this.prefixContent + param.target).setStyle({'position': 'relative'});

						this.targetLayerCode[param.target] = null;
						this.evalScript(param.endScript);
					}				
				}).bind(this), param.appear * 1000);
			}
		}).bind(this), param.appear * 1000);
	},
	

	/**
	 * load the source, and set the target(s) to the source element
	 */
	loadSource: function(source, encoding, paramArray){
		var numOfAjaxCall=0, numOfIFrameCall=0, numOfUpdate=0;
		for(var i=0; i<paramArray.length; i++){
			if(paramArray[i].source == source){
				var isFirstClick = this.targetLayerCode[paramArray[i].target] == null;
				this.targetLayerCode[paramArray[i].target] = this.targetCode(paramArray[i]);
				
				// fix the height and width of the target layer
				Utility.stopSetSize(paramArray[i].target);
				var width = $(paramArray[i].target).getStyle('width');
				var height = $(paramArray[i].target).getStyle('height');
				$(paramArray[i].target).setStyle({height: height, width: width});

				// no effect is applying on this layer now
				if(isFirstClick){
					this.createLayer(paramArray[i]);
					$(this.prefixContent + paramArray[i].target).setStyle({'position': 'absolute', width: width, height: height});

					// left corner 
					if(paramArray[i].effect == 'leftcorner'){
						var effect = paramArray[i].effect;
						$(this.prefixLoading + paramArray[i].target).setStyle({width: '0px', height: '0px'});
						$(this.prefixLoading + paramArray[i].target).setOpacity(1);
					}

					// top
					else if(paramArray[i].effect == 'top'){
						var effect = paramArray[i].effect;
						$(this.prefixLoading + paramArray[i].target).setStyle({width: width, height: '0px'});
						$(this.prefixLoading + paramArray[i].target).setOpacity(1);
					}

					// left
					else if(paramArray[i].effect == 'left'){
						var effect = paramArray[i].effect;
						$(this.prefixLoading + paramArray[i].target).setStyle({width: '0px', height: height});
						$(this.prefixLoading + paramArray[i].target).setOpacity(1);
					}

					// fade by default
					else{
						var effect = 'fade';
						$(this.prefixLoading + paramArray[i].target).setOpacity(0);
						$(this.prefixLoading + paramArray[i].target).setStyle({width: width, height: height});
					}
					
					$(this.prefixLoading + paramArray[i].target).writeAttribute('effect', effect);
					$(this.prefixLoading + paramArray[i].target).show();
				}
				
				// stop any size effect
				else{
					var effect = $(this.prefixLoading + paramArray[i].target).readAttribute('effect');
				}
				
				paramArray[i].loadingEffectBeginTime = (new Date()).getTime();
				
				Utility.setOpacity(this.prefixLoading + paramArray[i].target, {duration: paramArray[i].appear, to: 1});
				if(effect == 'leftcorner'){
					if($(this.prefixLoading + paramArray[i].target).getStyle('width') != '100%'){
						Utility.setSize(this.prefixLoading + paramArray[i].target, {width: width, height:  height, duration: paramArray[i].appear});
					}
				}
				
				else if(effect == 'top'){
					if($(this.prefixLoading + paramArray[i].target).getStyle('width') != '100%'){
						Utility.setSize(this.prefixLoading + paramArray[i].target, {width: width, height: height, duration: paramArray[i].appear});
					}
				}
				
				else if(effect == 'left'){
					if($(this.prefixLoading + paramArray[i].target).getStyle('width') != '100%'){
						Utility.setSize(this.prefixLoading + paramArray[i].target, {width: width, height: height, duration: paramArray[i].appear});
					}
				}
				
				numOfUpdate++;
				
				if(paramArray[i].container == 'iframe'){
					numOfIFrameCall++;
				}
				else{
					numOfAjaxCall++;
				}
			} // end if 
		} // end for i
		var requestTime = (new Date()).getTime();
		
		if(numOfAjaxCall > 0){
			if(Utility.isImgLink(source)){
				this.loadHiddenContent(source, paramArray, numOfAjaxCall, '<img src="' + source + '" border="0" />', 'img', 'layer');
			}
		
			else if(Utility.isFlashLink(source)){
				this.loadHiddenContent(source, paramArray, numOfAjaxCall, '<iframe marginwidth="0" marginheight="0" frameborder="0" scrolling="no" style="overflow-y: hidden; overflow-x: hidden; margin: 0px; "></iframe>', 'iframe', 'layer');
			}
			
			else if(Utility.isMovieLink(source)){
				this.loadHiddenContent(source, paramArray, numOfAjaxCall, '<iframe marginwidth="0" marginheight="0" frameborder="0" scrolling="no" style="overflow-y: hidden; overflow-x: hidden; margin: 0px; "></iframe>', 'iframe', 'layer');
			}
			
			else{
				new Ajax.Request(source, {
					method: 'get',
					encoding: encoding,
					onSuccess: (function(response){
						if(response.status == 0){
							this.loadHiddenContent(source, paramArray, numOfAjaxCall, '<div style="position: relative; width: 300px"><b>Request Error:</b><br /><br />Possible reasons: You request a page not in your own domain or the URL is wrong.</div>', 'ajax', 'layer');
						}
						else{
							this.loadHiddenContent(source, paramArray, numOfAjaxCall, response.responseText, 'ajax', 'layer');
						}
					}).bind(this),
					onFailure: (function(response){
						this.loadHiddenContent(source, paramArray, numOfAjaxCall, '<div style="position: relative; width: 300px"><b>Request Failure:</b><br /><br />Possible reasons: You request a page not in your own domain or the URL is wrong.</div>', 'ajax', 'layer');
					}).bind(this),
					onException: (function(response){
						this.loadHiddenContent(source, paramArray, numOfAjaxCall, '<div style="position: relative; width: 300px"><b>Request Exception:</b><br /><br />Possible reasons: You request a page not in your own domain or the URL is wrong.</div>', 'ajax', 'layer');
					}).bind(this)
				});
			}
		}
		
		if(numOfIFrameCall > 0){
			this.loadHiddenContent(source, paramArray, numOfIFrameCall, '<iframe marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" style="margin: 0px"></iframe>', 'iframe', 'iframe');
		}
	},

	loadHiddenContent: function(source, paramArray, numToUpdate, content, contentType, container){
		var tmpLayer = this.layerID();
		$$('body')[0].appendChild(Builder.node('div', {id: tmpLayer, style:'display: none; position:absolute; top:0px; left:0px;'}));
		$(tmpLayer).update(content);
		
		new PeriodicalExecuter((function(pe){
			var currentTime = (new Date()).getTime();
			for(var i=0; i<paramArray.length; i++){
				if(paramArray[i].source == source && !paramArray[i].executed && paramArray[i].container == container){
					if(currentTime > (paramArray[i].appear * 1000 + paramArray[i].loadingEffectBeginTime)){
						// notify it is updated
						paramArray[i].executed = true;
						
						// ensure we got the target one
						if(this.targetLayerCode[paramArray[i].target] == this.targetCode(paramArray[i])){
							// we simply load the layer immediately because it is in iframe
							if(contentType == 'iframe'){
								this.resizeAndShow(content, paramArray[i], contentType);
							}
							
							// paramArray[i].element means which element from the source to be loaded. null means the whole page
							else if(paramArray[i].element == null || contentType == 'img'){
								this.checkAllImageLoaded($(tmpLayer).innerHTML, paramArray[i], contentType);
							}
							
							// check which element to be loaded
							else{
								var descendants = Element.descendants($(tmpLayer));
								var found = false;
								for(var j=0; j<descendants.length; j++){
									if(descendants[j].identify() == paramArray[i].element){
										this.checkAllImageLoaded(descendants[j], paramArray[i], contentType);
										found = true;
										break;
									}
								} // end for j
								
								if(!found){
									this.resizeAndShow("<b>Error:</b><br /><br />The requested element is not found.", paramArray[i], contentType);
								}
							}
						}
						
						if(--numToUpdate == 0){
							pe.stop();
							$(tmpLayer).remove();
						}
					}
				}
			}
		}).bind(this), 0.2);
	},
	
	resizeAndShow: function(content, param, contentType){
		if(this.targetLayerCode[param.target] == this.targetCode(param)){
			$(this.prefixContent + param.target).hide();
			$(this.prefixContent + param.target).setOpacity(0);
			$(this.prefixContent + param.target).setStyle({'position': 'absolute'});
			
			$(this.prefixContent + param.target).update(content);

			var dimension = [];
			var haveToSetRelative = false;
		
			if(contentType == 'img'){
				$(this.prefixContent + param.target).show();
				
				if(param.width){
					dimension.width = param.width;
					$(this.prefixContent + param.target).childElements()[0].setStyle({width: dimension.width});
				}
				else{
					dimension.width = $(this.prefixContent + param.target).childElements()[0].width + 'px';
				}
				
				if(param.height){
					dimension.height = param.height;
					$(this.prefixContent + param.target).childElements()[0].setStyle({height: dimension.height});
				}
				else{
					dimension.height = $(this.prefixContent + param.target).childElements()[0].height + 'px';
				}
				
				$(this.prefixContent + param.target).setStyle({width: dimension.width, height: dimension.height});
			}

			else if(contentType == 'iframe'){
				dimension.width = param.width ? param.width : '800px';
				dimension.height = param.height ? param.height : '600px';

				$(this.prefixContent + param.target).childElements()[0].setStyle({width: dimension.width});
				$(this.prefixContent + param.target).childElements()[0].setStyle({height: dimension.height});
				
				if(param.scroll){
					$(this.prefixContent + paramArray[i].target).childElements()[0].writeAttribute('scrolling', param.scroll);
				}
				$(this.prefixContent + param.target).childElements()[0].src = param.source;
				$(this.prefixContent + param.target).setStyle({width: 'auto', height: 'auto'});
			}
				
			else{
				haveToSetRelative = true;

				if(param.width){
					$(this.prefixContent + param.target).setStyle({width: param.width});
				}
				else{
					$(this.prefixContent + param.target).setStyle({width: 'auto'});
				}
				if(param.height){
					$(this.prefixContent + param.target).setStyle({height: param.height});
				}
				else{
					$(this.prefixContent + param.target).setStyle({height: 'auto'});
				}
				$(this.prefixContent + param.target).show();
				dimension.width = $(this.prefixContent + param.target).getStyle('width');
				dimension.height = $(this.prefixContent + param.target).getStyle('height');


				$(this.prefixContent + param.target).hide();
			}

			$(this.prefixLoading + param.target).setStyle({width: '100%', height: '100%'});
			Utility.setSize(param.target, {width: dimension.width, height: dimension.height, duration: param.appear});
			
			new PeriodicalExecuter((function(pe){
				if(Utility.setSizeState(param.target) == "finished"){
					pe.stop();
					if(this.targetLayerCode[param.target] == this.targetCode(param)){
						$(this.prefixLoading + param.target).setStyle({width: $(param.target).getStyle('width'), height: $(param.target).getStyle('height')});

						$(this.prefixContent + param.target).setOpacity(1);
						$(this.prefixContent + param.target).show();
						
						// corner effect
						if(param.effect == 'leftcorner'){
							$(this.prefixLoading + param.target).writeAttribute('effect', 'leftcorner');
							var dimension = $(param.target).getDimensions();
							$(this.prefixLoading + param.target).setStyle({width: dimension.width + 'px', height: dimension.height + 'px'});
							Utility.setSize(this.prefixLoading + param.target, {width: '0px', height: '0px', duration: param.appear});
						}
								
						else if(param.effect == 'top'){
							$(this.prefixLoading + param.target).writeAttribute('effect', 'top');
							var dimension = $(param.target).getDimensions();
							$(this.prefixLoading + param.target).setStyle({width: dimension.width + 'px', height: dimension.height + 'px'});
							Utility.setSize(this.prefixLoading + param.target, {width: dimension.width + 'px', height: '0px', duration: param.appear});
						}
								
						else if(param.effect == 'left'){
							$(this.prefixLoading + param.target).writeAttribute('effect', 'left');
							var dimension = $(param.target).getDimensions();
							$(this.prefixLoading + param.target).setStyle({width: dimension.width + 'px', height: dimension.height + 'px'});
							Utility.setSize(this.prefixLoading + param.target, {width: '0px', height: dimension.height + 'px', duration: param.appear});
						}
								
						// fade effect
						else{
							$(this.prefixLoading + param.target).writeAttribute('effect', 'fade');
							Utility.setOpacity(this.prefixLoading + param.target, {duration: param.appear , to: 0, hide: true});
						}
						
						setTimeout((function(){
							if(this.targetLayerCode[param.target] == this.targetCode(param)){
							
								if(param.setRelative && haveToSetRelative){
									$(this.prefixContent + param.target).setStyle({'position': 'relative'});
									$(param.target).setStyle({width: 'auto', height: 'auto'});
									$(param.target).setOpacity(1);
								}
								
								this.targetLayerCode[param.target] = null;
								this.evalScript(param.endScript);
							}
						}).bind(this), param.appear * 1000);
					}
				}

			}).bind(this), 0.2);

		}

	},
	
	//---------------------------------------------------------------------------------------------------------
	// SOME UTILITY FUNCTIONS -- USUALLY MUST BE CORRECT
	//---------------------------------------------------------------------------------------------------------
	
	createLayer: function(param){
		if(!$(this.prefixContent + param.target)){
			$(param.target).update(
				'<div id="' + this.prefixContent + param.target + '" style="position:relative; top: 0px; left: 0px;">' + $(param.target).innerHTML + '</div>' +
				'<div id="' + this.prefixLoading + param.target + '" style="display: none; position:absolute; top: 0px; left: 0px; width: 0px; height: 0px;"></div>'
			);
		}
		else{
			var classNames = $A($(this.prefixLoading + param.target).classNames());
			for(var i=0; i<classNames.length; i++){
				$(this.prefixLoading + param.target).removeClassName(classNames[i]);	
			}
		}
		
		if(param.className){
			$(this.prefixLoading + param.target).addClassName(param.className);
		}
		else{
			$(this.prefixLoading + param.target).addClassName(this.defaultLoadingCSSClass);	
		}
	},
	
	targetCode: function(param){
		return param.source + "#" + param.element + "#" + param.random + "#" + param.lastActionTime;
	},
	
	layerID: function(){
		return "s" + (new Date()).getTime() + "_" + Math.round(Math.random() * 10000000);
	},
	
	evalScript: function(script){
		if(script != null){
			Try.these((function(){
				eval(script);
			}).bind(this));
		}
	},
	
	checkAllImageLoaded: function(layerOrContent, param, contentType){
		var tmpLayer = this.layerID();
		$$('body')[0].appendChild(Builder.node('div', {id: tmpLayer, style:'display: none; position:absolute; top:0px; left:0px;'}));
		$(tmpLayer).update(layerOrContent);
		var trial = 0, maxTrial = 150;
		new PeriodicalExecuter((function(pe){
			if(Utility.isAllImgLoaded($(tmpLayer)) || ++trial == maxTrial){
				pe.stop();
				
				this.resizeAndShow($(tmpLayer).innerHTML, param, contentType);
				$(tmpLayer).remove();
			}
		}).bind(this), 0.2);
	}
	
});

if($$('body')[0]){
	if(!GScript.DynamicContent){
		GScript.DynamicContent = new DynamicContent();
	}
}
else{
	document.observe('dom:loaded', function(){
		if(!GScript.DynamicContent){
			GScript.DynamicContent = new DynamicContent();
		}
	});
}

