// JavaScript Document

// jQuery extension to read and use jSon Comments (by A.C.)
jQuery.fn.extend({
  getJsonComment: function(){
	var code=jQuery(this).children("code.jsonComment");
	var par=null;
	if (code.length>0){
		code=code.get(0).innerHTML
			.replace("<!--","")
			.replace("-->","");
		par=eval("(" + code + ")");
	}
	return par||false;
	}
});



/*
 * In-Field Label jQuery Plugin
 * @version 0.1
 */
(function($){$.InFieldLabels=function(label,field,options){var base=this;base.$label=$(label);base.$field=$(field);base.$label.data("InFieldLabels",base);base.showing=true;base.init=function(){base.options=$.extend({},$.InFieldLabels.defaultOptions,options);base.$label.css('position','absolute');var fieldPosition=base.$field.position();base.$label.css({'left':fieldPosition.left,'top':fieldPosition.top}).addClass(base.options.labelClass);if(base.$field.val()!=""){base.$label.hide();base.showing=false;};base.$field.focus(function(){base.fadeOnFocus();}).blur(function(){base.checkForEmpty(true);}).bind('keydown.infieldlabel',function(e){base.hideOnChange(e);}).change(function(e){base.checkForEmpty();}).bind('onPropertyChange',function(){base.checkForEmpty();});};base.fadeOnFocus=function(){if(base.showing){base.setOpacity(base.options.fadeOpacity);};};base.setOpacity=function(opacity){base.$label.stop().animate({opacity:opacity},base.options.fadeDuration);base.showing=(opacity>0.0);};base.checkForEmpty=function(blur){if(base.$field.val()==""){base.prepForShow();base.setOpacity(blur?1.0:base.options.fadeOpacity);}else{base.setOpacity(0.0);};};base.prepForShow=function(e){if(!base.showing){base.$label.css({opacity:0.0}).show();base.$field.bind('keydown.infieldlabel',function(e){base.hideOnChange(e);});};};base.hideOnChange=function(e){if((e.keyCode==16)||(e.keyCode==9))return;if(base.showing){base.$label.hide();base.showing=false;};base.$field.unbind('keydown.infieldlabel');};base.init();};$.InFieldLabels.defaultOptions={fadeOpacity:0.5,fadeDuration:300,labelClass:'infield'};$.fn.inFieldLabels=function(options){return this.each(function(){var for_attr=$(this).attr('for');if(!for_attr)return;var $field=$("input#"+for_attr+"[type='text'],"+"input#"+for_attr+"[type='password'],"+"textarea#"+for_attr);if($field.length==0)return;(new $.InFieldLabels(this,$field[0],options));});};})(jQuery);



$(window).load(function(){
	//loading the widget css file containing the background images.
	$("<link />")
		.appendTo('head')
		.attr({rel:"stylesheet", type:"text/css", href:"includes/css/textPanelImages.css"});
})
						
$(document).ready(function(){	
		
	//inFieldLabels plugin init
	if ( !($.browser.msie && $.browser.version<7)){		// filtering out IE 6
		var tmpObj=$("label.inField");
		tmpObj.inFieldLabels(
				{
					fadeOpacity: 0.4, // Once a field has focus, how transparent should the label be
					fadeDuration: 300, // How long should it take to animate from 1.0 opacity to the fadeOpacity
					labelClass: 'infield' // Class to be applied to label when positioned over form field	
				}
			);
	}
	
	//widget handler init (must be exec. after inFieldLabels init)
	isat.init();	
		
});


// this is the the page logic holding object
var isat={
	language:"en",																		//TODO: define all the available languages
	imgPath:"includes/images/",															//path to the flags folder
	lightBoxBg:$("<div id='lightBoxBg'></div>").attr("tabIndex",0).appendTo("body"),	//creating the BG
	textPanel:$("#isatPhone_textPanel"),												//pointer to the widget
	closeBtn:$("#isatPhone_textPanel .isat_closeBtn"),									//the widget close button
	submitBtn:$("#isatPhone_textPanel div.buttonBar button"),
	countriesCodes:null,																//js object holding the international phone codes
	countriesFlags:null,																//js object holding extra countries info
	
	autoValidation:false,		//boolean used to run the validation process against a single field when the its blur event is fired. This is turned on on submit
	
	//creating the alert box
	messageBox:{
		callback:null,
		html:$("<div id='isatPhone_messageBox'><a class='isat_closeBtn' href='#close' title='Close'><span>Close</span></a><div><span class='icon' /><span class='title' /><span class='text' /></div></div>").appendTo("body")
	},
	
	init:function(){
		isat.textPanel.css({display:"none","opacity":1}).get(0).style.filter="";
		
		//PE_defaultValue
		$(".PE_defaultValue").blur(function(){
			var $this=$(this);
			if ($this.attr("value").length==0) {$this.attr("value",$this.attr("title"));};
		});
		
		//handling the close button click event
		isat.closeBtn.click(function(){
			isat.form.close();
			return false;
		});
		
		//moving the focus to the first available anchor
		isat.lightBoxBg.focus(function(){
			var a=isat.textPanel.find("a").eq(0);
			if (a.is(":visible")){
				a.focus();
			}else{
				isat.messageBox.html.find("a").get(0).focus();
			}			
		});
		
		//messageBox closing function
		isat.messageBox.html.find("a").click(function(){	

			if (isat.messageBox.callback){ 
				isat.messageBox.callback();
				isat.messageBox.callback=null;
			}
			isat.messageBox.html.hide(0);
			return false;
		});
		
		//handling the form events
		isat.textPanel.find("form")
			.submit(isat.form.onSubmit)
			
			//setting the "show validation error" on focus behaviour
			.find("input, textarea")
				.focus(function(){
					var $this=$(this),
					$validationP=$("#isatPhone_validationMsg"),
					params=$(this.parentNode).getJsonComment(),																//reading the validation rule
					validationMsg=isat.dict.validationMessages[isat.language][$this.data("validationResult")||params.type];		//getting the validation message html
					
					//console.log($this.data("validationResult") + " -- " + params.type)					
					
					$this.hasClass("error")?
						$validationP.addClass("alert"):
						$validationP.removeClass("alert");
						

					$validationP
						.empty()
						.append($(validationMsg));
						
					if (validationMsg) {$validationP.fadeIn(300)};
				})
				.blur(function(){
					//revalidate the field on blur if autoValidation is true
					if (isat.autoValidation){
						isat.validateField(this);
					}
					//clearing and hiding the validation message
					$("#isatPhone_validationMsg").hide(0).empty();					
				});
		
		
		//setting up the max length checker function
		var fields=isat.textPanel.find("#message, #reply_email, #reply_phone"),
			counter=isat.textPanel.find("p.chCounter strong");		
		//this is the actual function
		var checker=function(){
			var tot=0;
			fields.each(function(index,item){
				var $item=$(item);
				tot+=$item.attr("value").length;
				
				if ($item.attr("id")!="message"){
					tot+=($item.attr("value").length>0)?1:0;
				}
				
			});
			counter.text(tot);
			counter.toggleClass("error",tot>160);		
		};
	
		//assigning the event handler
		fields.keyup(checker);
		
		//let's run it now!
		checker();
		
		
		//The world countries and their codes/flags		
		var ajaxParams={
				type:"GET",
				dataType:"json",
				url:"includes/json/countriesData.txt",
				success:function(data){
					isat.countriesFlags=data;
				}
			};
		
		$.ajax(ajaxParams);
		
		ajaxParams={
				type:"GET",
				dataType:"json",
				url:"includes/json/countriesCodes.txt",
				success:function(data){
					isat.countriesCodes=data;
				}
			};
		
		$.ajax(ajaxParams);			
		
		
		
		$(".PE_phoneOrEmail")
			.before("<span class='phoneOrEmail' />")
			.keyup(codeLookUp)	
			.click(codeLookUp)	
			.change(codeLookUp);
		
		
		//local function
		function codeLookUp(){
			var $this=$(this),
				cCode=$this.attr("value"),
				firstCh=cCode.substring(0,1),				
				$phoneEmail=$this.prev(".phoneOrEmail"),				
				width=$this.data("originalWidth")||$this.innerWidth(),
				currentMatch=$this.data("currentMatch")||"",				
				cName="",
				country={pos:-100};
				
			//cheking if the user input is a country code
			for(var x=cCode.length;x>0;x--){
				cName=isat.countriesCodes[cCode.substring(0,x)];
				if(cName){
					country=isat.countriesFlags[cName]||{pos:-100,code:"empty"};
					break;
				}
			}		
			
			
			if(!$this.data("originalWidth")) {$this.data("originalWidth",width)}
			
			//$phoneEmail.stop();
			
			if(cName){	
				//making a note of the currentMatch
				$this.data("currentMatch",cCode);
				
				$phoneEmail
					//.css({"background-position":"2px " + (-country.pos*21+6) + "px"})
					.css({"backgroundImage":"url(" + isat.imgPath + country.code + ".png)"})
					.show();					
				$this					
					.css({
						"padding-left":"30px",
						"width":width-30
					})
			}else{								
				//if the typed code exists in the countries table...
				if(currentMatch){
					//check if the code is contained in the current number
					if (currentMatch.length>cCode.length){
						$this.data("currentMatch",null);					
					}else{				
						//is the user typing an email address??							
						if(cCode.length>0 && firstCh!="+" && firstCh!="0"){
							$phoneEmail
								//.css({"background-position":"2px bottom"})
								.css({"backgroundImage":"url(" + isat.imgPath + "email" + ".png)"})
								.css({"background-position":"0px 4px"})
								.show();					
							$this					
								.css({
									"padding-left":"30px",
									"width":width-30
								});
							return false;
						}
						
						//if you are here then the user is typing an already recognised international number
						return false;
					}
				}
				
				//is the user typing an email address??				
				if(cCode.length>0 && firstCh!="+" && firstCh!="0"){
					$phoneEmail
						//.css({"background-position":"2px bottom"})
						.css({"backgroundImage":"url(" + isat.imgPath + "email" + ".png)"})
						.css({"background-position":"0px  4px"})
						.show();					
					$this					
						.css({
							"padding-left":"30px",
							"width":width-30
						});		
						
					$phoneEmail.attr("title","e-mail address");
					$this.attr("title","e-mail address");						
					
					return false;
				}				
				
				
				$phoneEmail.hide();
				
				$this					
					.css({						
						"padding-left":"2px",
						"width":width-2
					});									
			}
			
			$phoneEmail.attr("title",cName);
			$this.attr("title",cName);			
		}	
	},
	
	alert:function(msg,callback){
		if (callback) {isat.messageBox.callback=callback};
		isat.messageBox.html
			.fadeIn(100,function(){isat.messageBox.html.find("a").focus()})
			.find("div").attr("className","error")
			.find(".text").text(msg.message).end()
			.find(".title").text(msg.title);		
	},
	
	inform:function(msg,callback){
		if (callback){isat.messageBox.callback=callback};
		isat.messageBox.html
			.fadeIn(100,function(){isat.messageBox.html.find("a").focus()})
			.find("div").attr("className","")
			.find(".text").text(msg.message).end()
			.find(".title").text(msg.title);
	},
	
	form:{
		show:function(){			
			//showing the BG
			isat.lightBoxBg.fadeTo(600,0.6);			
			
			//showing the textPanel
			isat.textPanel
				.css("top",((isat.lightBoxBg.innerHeight() - isat.textPanel.outerHeight())/2))
				.show(0);
				//.find("input").get(0).focus();				
			
		},
		close:function(){			
			
			isat.autoValidation=false;			
			
			isat.textPanel.find("input[type='text'],textarea")
				.focus()
				.removeClass("error")
				.val("")
				.data("validationResult",null)
				.blur();	//showing the labels
			
			//resetting the char. counter
			isat.textPanel.find("p.chCounter strong")
				.attr("className","")
				.text("0");
				
			$("#isatPhone_validationMsg").text("").hide(0);				
			
			isat.textPanel.find("span.phoneOrEmail").css({"display":"none"});
			
			isat.lightBoxBg.fadeOut(400);
			isat.textPanel.hide(0);				
				
			
		},
		onSubmit:function(e){
			e.preventDefault();	
			
			//enabling input validation on blur
			isat.autoValidation=true;

			//validating the form
			var $form=$(this),
				doSubmit=true;							
			
			//cycling through the form elements
			$.each($form.find("input, textarea"),function(index,item){														  
				if(!isat.validateField(item)){doSubmit=false};
			});							
				
			if (doSubmit){		//everything is fine, let's submit the form			
			
				isat.submitBtn.attr("disabled",true);
				
				$("#isatPhone_validationMsg").text("").hide(0);
				
				isat.submitBtn
					.addClass("sending")
					.find(".caption").text("sending..");
				
				var postObj=$form.serializeArray(),
					ajaxParams={
						type:"POST",
						data:postObj,
						dataType:"json",
						url:$form.attr("action"),
						success:isat.form.onResponse,
						error:isat.form.onServerError,
						complete:function(){
							isat.submitBtn
								.removeClass("sending")
								.attr("disabled",false)
								.find(".caption").text("Send");								
						}
					};
					
				//simulating a bit of delay in getting the response back from the server
				setTimeout(function(){$.ajax(ajaxParams)},3000);
			}else{
				// moving the focus to the first invalid inputbox
				isat.closeBtn.focus();
				$form.find(".error, .error input").not("p.error").get(0).focus();
			}			
			
			return false;
		},
		onResponse:function(data){
			isat.textPanel.hide(0);
			switch (data.code){
				case 0:
					isat.inform(
						{
							title:data.msg.title,
							message:data.msg.body
						},
						isat.form.close
					);
				break;
				
				default:
					isat.alert(
						{
							title:data.msg.title,
							message:data.msg.body
						},
						isat.form.close
					);
				break;
			}
		},
		onServerError:function(err,textStatus, errorThrown){
			isat.textPanel.hide(0);
			isat.alert(
				{title:isat.dict.serverError[isat.language],message:textStatus || errorThrown.message},
				isat.form.close
			);
		}
	},
	
	validateField:function(inputObj){
		//returns true/false and sets the className and the error message for the passed inputObj
		var $this=$(inputObj),	
			rule=$this.closest("p").getJsonComment(),
			validationResult=isat.isValid($this,rule);
		
		//clearing the obj props
		$this
			.removeClass("error")
			.data("validationResult",null)
			.closest("p")				//used by the checkbox
				.removeClass("error");
		
		//this is the "alternative" field
		var alt=$this.closest("p").getJsonComment().alt,
			$alt=$(alt),
			altRule=$alt.closest("p").getJsonComment();
			
		if (alt){	//if alt exists...
			if (!(validationResult===true)){	
					//if the alternative field is valid then just skip to the next check
				if(isat.isValid($alt,altRule)===true){					
					return true;
				}
			}else{
				//if this field is valid, then so is the alternative
				$alt
					.removeClass("error")
					.data("validationResult",null)
					.attr("value","")
					.blur()
					.closest("p")				//used by the checkbox
						.removeClass("error")								
			}
		}
		
		//setting the validation result (used to display the feedback message properly)
		$this.data("validationResult",validationResult);
		
		if (!(validationResult===true)){
			if($this.attr("type")=="checkbox"){
				$this.closest("p").addClass("error");
			}else{
				$this.addClass("error");
			}			
			return false;	
		}
		
		return true		
	},
	
	isValid:function($this,rule){
		//this function returns true or one of the following: minLen,email,isatPhone,internationalMobile
		var fieldValue=$this.attr("value");
			
		if ($this.attr("type")=="checkbox"){
			if (!$this.attr("checked")){fieldValue=""};
		}
		
		
		if (!rule){return true} // if it has no rules to follow then skip to the next item																
		
		rule.minLen=rule.minLen||0;
		rule.maxLen=rule.maxLen||999999999;
		rule.minVal=rule.minVal||-999999999;
		rule.maxVal=rule.maxVal||999999999;				
	
		//input length check
		if(fieldValue.length<rule.minLen){return "minLen"};
		if(fieldValue.length>rule.maxLen){return "maxLen"};

		// apply the rules set
		switch (rule.type){
			case "any":
				// nothing to do. This "case" is here only for consistency
			break;
		
			case "email":													
				if (fieldValue.length>0){
					//var pattern=/^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+\.([a-zA-Z])+([a-zA-Z])+/;
					var pattern=/^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$/;
					if(!pattern.test(fieldValue)){return "email"};
				}
			break;
			
			case "isatPhone":													
				if (fieldValue.length>0){

					var pattern=/^([+]|00)87077\d{7}$/;
					/*
					Validates an Inmarsat Mobile Number
					Matches			0087077xxxxxxx | +87077xxxxxxx
					*/
					if(!pattern.test(fieldValue)) return "isatPhone";
				}
			break;			
			
			case "satSms":
				if (fieldValue.length>0){
					if ((fieldValue.length + $(rule.linkedField).attr("value").length)>160){return "satSms"}
				}
			break;
			
			case "internationalMobile":													
				if (fieldValue.length>0){

					var pattern=/^[+][^0]\d{8,14}$/;
					/*
					Matches			+xxxxxxxx[xxxx]
					*/
					if(!pattern.test(fieldValue)) return "internationalMobile";
				}
			break;	
			
			case "userContact":
				if (fieldValue.length>0){
					//rough input type check
					var firstCh=fieldValue.substring(0,1);
					if(firstCh=="+" || firstCh=="0"){
						//could be a mobile number, let's check its validity						
						return isat.isValid($this,{type:"internationalMobile"})
					}else{						
						//could be an email address, let's see if it contains at least "@"
						if(fieldValue.indexOf("@")>1){
							return isat.isValid($this,{type:"email"})
						}else{
							return "userContact";
						}
					}
				}
			break;
		}		
		
		return true;	
	},
	
	// this object holds the html + message to give users some help
	dict:{
		validationMessages:{	
			en:{
				"minLen":"<span>This is a mandatory field!</span>",
				"satSms":"<span>Please type your message here!</span><span class='block'>NB - The email/mobile number counts as part of the 160 characters allowance</span>",
				"email":"<span>Please provide a valid email address</span>",
				"isatPhone":"<span class='isatPhoneNumberHelp'>Inmarsat number format: <br /> +8707 XXXX...</span>",
				"internationalMobile":"<span class='isat_intMob'>International mobile format:</span>",
				"userContact":"<span>Please provide either your email address or you mobile number, the latter in international format.</span>"
			},
			it:{
				"minLen":"<span>Campo obbligatorio!</span>",
				"satSms":"<span>Inserisci qui il tuo messaggio!</span><span class='block'>NB - La tua email/numero di telefono sono conteggiati nei 160 caratteri disponibili</span>",
				"email":"<span>Inserisci un indirizzo email valido</span>",
				"isatPhone":"<span class='isatPhoneNumberHelp'>Formato numero Inmarsat: <br /> +8707 XXXX...</span>",
				"internationalMobile":"<span class='isat_intMob'>Numero di cell. in formato internazionale:</span>",
				"userContact":"<span>Fornisci un indirizzo email o un numero di cellulare, quest'ultimo in formato internazionale.</span>"
			},
			ch:{
				"minLen":"<span>这是一个必须填写！</span>",
				"satSms":"<span>请输入您的讯息！</span><span class='block'>注： - 电子邮件/手机号码数为160个字符津贴部分</span>",
				"email":"<span>请提供一个有效的电子邮件地址</span>",
				"isatPhone":"<span class='isatPhoneNumberHelp'>国际海事卫星数字格式：</span>",
				"internationalMobile":"<span class='isat_intMob'>国际移动格式：</span>",
				"userContact":"<span>请提供您的电子邮件地址或您的手机号码，以国际标准格式后者。</span>"
			}
			// ... extend this object with other languages
		},
		
		serverError:{
			en:"Server error:",
			it:"Errore sul server:",
			ch:"服务器错误"
		}
	}
}

