// *** regular expression tags ***

var html_tag = /(<[^>]+>)/g;
var html_content = /(>[^<]+)/g;

// *** each group of date elements is assigned a controller object ***

function date_controller(element_name){

	this.date_object = new date_object();
	
	this.date_elements = new Array();

	// *** not all forms will require full use of date and time elements ***

	this.date_elements[0] = new list_object("day",element_name,1,31,this.date_object.get_day(),1);
	this.date_elements[1] = new list_object("month",element_name,1,12,this.date_object.get_month(),1);
	this.date_elements[2] = new list_object("year",element_name,this.date_object.get_year()-1,this.date_object.get_year()+1,this.date_object.get_year(),1);
	this.date_elements[3] = new list_object("time",element_name,0,23.75,this.date_object.get_round_time(),0.25); // round time up to nearest 15 mins

}

date_controller.prototype.setup_list = function(){

	for(var date_element in this.date_elements){// initial configuration of select lists
	
		var list_element = this.date_elements[date_element]; 
	
		list_element.load_numeric_list_options(this.date_group_title);
		
	}

}

date_controller.prototype.set_date_timestamp = function(timestamp){
	
	if(timestamp != 0){
		
		this.date_object.set_timestamp(timestamp);
	
		// *** load date group elements from timestamp ***
		
		for(var date_element in this.date_elements){
			
			var list_element = this.date_elements[date_element]; 
				
			// *** in duplication mode ensure job_live date stays at the current date / time ***
				
			if(list_element.list_group == "job_live" && duplicate == false){
				
				eval("list_element.set_list_value(this.date_object.get_"+list_element.get_list_title()+"());") // set all list date elements
			
			}
			
		}
		
	}

}

date_controller.prototype.get_date_timestamp = function(){

	// *** capture date element values and return timestamp ***

	for(var date_element in this.date_elements){
	
		var list_element = this.date_elements[date_element];
		var element_value = list_element.get_list_value().toString();

		// *** month can be equal to 0 ***

		if(element_value != false || list_element.get_list_title() == "month")

			eval("this.date_object.set_"+list_element.get_list_title()+"(\""+element_value+"\");") // set all list date elements
	
	}
	
	return this.date_object.get_timestamp(); // return date elements as timestamp

}

// ****************************************************** //

var match_criteria = new Array();

match_criteria["num"] = /^[0-9\.]+$/g;
match_criteria["tel"] = /^[0-9 ]{6,12}/g;
match_criteria["tle"] = /^[0-9a-z\?,' ]+$/i;
match_criteria["txt"] = /^[0-9a-zA-Z_/\-@%&+\.,|:!?/\r/\n ]+$/i;
match_criteria["eml"] = /^[0-9a-z_\-\.]*@[0-9a-z_\-]*\.[a-z\.]*/i;
match_criteria["pwd"] = /^[0-9a-zA-Z_\-]{6,12}/g;
match_criteria["duk"] = /^[0-3][0-9][-/ ][0-1][0-9][-/ ][0-9]{4}/g; // Standard UK Date Format
match_criteria["dts"] = /^\d+$/; // Timestamp
match_criteria["hex"] = /^[#]?[0-9A-F]{6}$/i;
match_criteria["rgb"] = /^(\d{1,3}[,]?){1,3}$/;
match_criteria["cmy"] = /^([01]{1}[\.]?(\d){0,2}[,]?){4}$/;
match_criteria["nin"] = /^[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]?\d{2}?\d{2}?\d{2}?[ABCD]$/;

function form_element_object(form_element,object_type){
	
	this.object_type = object_type;
	
	this.form_element = form_element;
	
	this.element_type = (form_element.id).substring(0,3);
    this.element_require = (form_element.id).charAt(3);   
	this.element_name = (form_element.id).substring(5,(form_element.id).length);
    this.element_reference = this.element_type + this.element_require + "_" + ((this.object_type == "radio")? this.element_name.substring(0,this.element_name.length -1) : this.element_name);
	
	if(this.element_type == "dts"){
		
		// *** display date / time attributes to capture timestamp ***
		
		this.element_object = new date_controller(this.element_name);
		this.element_object.setup_list();
		
	}

    this.element_status = true;

	this.feedback = new Array();

}

form_element_object.prototype.reset_form_element = function(){

	if(this.element_require == 4){
	
		for(var check_no = 0; check_no < this.form_element.length; check_no++)
			
			this.form_element[check_no].checked = false;	
		
	}else{
		
		this.form_element.value = "";
	}		
}

form_element_object.prototype.get_form_element = function(){return this.form_element;}

form_element_object.prototype.get_status = function(){return this.element_status;}

form_element_object.prototype.get_require = function(){return this.element_require;}

form_element_object.prototype.get_type = function(){return this.element_type;}

form_element_object.prototype.get_name = function(){return this.element_name;}

form_element_object.prototype.get_value = function(){

	if(typeof(this.element_object) == "object"){
		
		this.form_element.value = this.element_object.get_date_timestamp();
		this.element_value      = this.form_element.value;
		
	}

	return this.element_value;
	
}

form_element_object.prototype.get_feedback = function(){return this.feedback.join(",");}

form_element_object.prototype.set_value = function(value){
	
	this.element_value = value;
	this.form_element.value = this.element_value;
}

form_element_object.prototype.set_status = function(status){this.element_status = status;}

form_element_object.prototype.format_element = function(){
	
	if(typeof(this.element_object) == "object")
		
		this.form_element.value = this.element_object.get_date_timestamp();

	if(this.element_name.indexOf("content_html") != -1 && html_element){
	
		// *** load html editor content ***
		
		if(typeof(html_element) == "object"){
			
			switch_mode(0); // *** ensure editor is in normal mode ***
			
			this.element_value = html_element.body.innerHTML;
			
		}
		
	}else{
	
		this.element_value = (this.object_type == "select")? get_select_value(this.form_element) : (this.object_type == "radio")? get_radio_value(this.element_reference) : this.form_element.value;	
	
	}
	
	// provide different modes for html validation
	
	// *** escape characters ***
	
	var control_element = new text_object(this.element_value,(this.element_type == "htm")? this.element_type : "txt");
		
	this.element_value = control_element.get_parsed_string();
	
	this.form_element.value = this.element_value;

}

form_element_object.prototype.set_feedback = function(msg){

    var element_list = this.element_name.split("_");
        
	this.feedback[this.feedback.length] = element_list.join(" ") + msg;
	
	this.set_status(false);

}

form_element_object.prototype.validate_element = function(){
	
	// *** for all text remove newlines ***
	
	this.feedback = new Array();
	
	this.set_status(true);

	if(this.form_element.id && typeof(parseInt(this.element_require)) == "number"){
		
		this.format_element();
		
		if(typeof(parseInt(this.element_require)) == "number" && this.element_require <= 1){
			
			var element_match = (this.element_type != "htm")? this.element_value.match(match_criteria[this.element_type]) : this.form_element.value;
			
			if(this.element_type == "pwd" && element_match != null){
	
				var password = check_element(this.element_name+"_confirm");
	
				if(password != false)
                        		
					if(this.element_value != password.value)
						
						this.set_feedback(" and confirmation do not match");
		
			}
			
			if(this.element_type == "hex")
				
				this.element_value = this.element_value.replace(/[^0-9A-F]/i,"");

            if(element_match != null){
                
				// *** restrict the size of inputted strings ***
					
				if((word_count(strip_html(this.element_value)) > ((this.object_type == "textarea")?  1000 : 100)) && this.element_type != "htm"){
				
					this.set_feedback(" is too large");  	
				
				}else{
				
					this.form_element.value = element_match;
					
				}
		
			}else{
				
				// *** reset as data is invalid ***
				
				if(this.element_require == 1) this.set_feedback("");
			
				this.form_element.value = "";

			}
			
			update_label(this.element_name,(this.element_status == false && this.element_require == 1)? 0 : 1);
		
		}
	
	}

}

function text_object(text_value,text_type){
    
	this.text_value = text_value.replace(/\r\n/gi,""); // *** remove carriage returns / newlines
    this.text_type = text_type;

	switch(this.text_type){

		case "txt":
			
			this.parse_txt();

			break;

		case "htm":
			
			this.parse_htm();
			
			break;

	}

	this.trim_string();

}

text_object.prototype.trim_string = function(){

	this.text_value = (this.text_value.replace(/^\s+/g,"")).replace(/\s+$/g,"");

}

text_object.prototype.parse_txt = function(){
	
	// *** escape ' and " - only attempt escape if not already done ***
	
	this.text_value = (this.text_value.replace(/'/g,"\'")).replace(/"/g,'\"');
	
}

text_object.prototype.parse_htm = function(){

	// *** adapt to support fully xhtml compliant content ***

	if(character_count(this.text_value) > 0){
		
		// *** adapt to enable switching between safe & development mode 15/04/2008 ***
		
		switch(basic_editor){
			
			case true:
			
				this.text_value = (this.text_value.replace(html_tag,basic_format_tag)).replace(html_content,basic_format_content); // Basic HTML
				
				break;
			
			case false:
			
				this.text_value = (this.text_value.replace(html_tag,format_tag)).replace(html_content,format_content); // Standard HTML
			
				break;
				
		}
		
	}else{
	
		this.text_value = "";
	
	}

}

text_object.prototype.get_parsed_string = function(){

	return this.text_value;

}

var tag_codes = new Array("img","br","hr");

// basic formatting has been added to combat problems with copy / pasting from Word

function basic_format_tag(tag){

	var supp_tags = /^((h1)|(h2)|(h3)|(p)|(br)|(ul)|(ol)|(li)|(u)|(em)|(strong))$/i;  // only tags supported

	var tformat = ( tag.toLowerCase() ).replace( /[^\w\/ ]/g, "" );
	var ttype   = ( tformat.indexOf(" ") != -1 )? tformat.substring( 0, tformat.indexOf( " " ) ) : tformat; // retains opening / closing brace
	var tcode   = ( ttype.replace( /[^\w]/g, "" ) ).match(supp_tags);

	return ( tcode != null )? "<" + ttype + ">" : "";
	
}

function basic_format_content(content){

	// replace all potentially dangerous characters / improve W3C compliance
	// NOTE Does note do &
	
	var char_list = new Array( "£", "'", '"', "&nbsp;" );
	var char_code_list = new Array( "&#163;", "&#39;", "&#34;", "" );
	
	for(var chars in char_list){
		content = content.replace( char_list[chars], char_code_list[chars] );
	}
	
	// strip out any remaining characters that don't match the below pattern

	var basic_contents = /[^\d\w\.\-\/&#@%:;,? ]/g;
	content = content.replace(basic_contents,"");

	return ">" + content;

}

function format_tag(tag){ 

	var xhtml_tag = "";
	var close_tag = false;
	
	// *** identify self closing tags ***
	
	for(var tag_no in tag_codes)
		
		if(tag.indexOf(tag_codes[tag_no].toUpperCase()) != -1)
			
			close_tag = true;
	
	/* 
	
		> Do not allow any space around the =
		> Add quotes where they are not already included
		> Find index of opening = , Capture tag attributes seperately 
		> Identify the opening and closing quotes, DO NOT have any quotes within quotes
		> If attrib starts with ? or & then DO NOT enclose in quotes
		> Strip out id=null or id="null"
	
	*/
	
	if(tag.indexOf("=") != -1){
		
		// *** ensure tag has attributes before validating ***
		
		var quote_status = false;
		var quote_list = new Array();
		
		for(var index = tag.indexOf("="); index <= tag.length; index++){
			
			if(tag.charAt(index) == "="){
			
				if(quote_status === true){
					
					// *** identify closing quotes ***
					
					var tag_sub = tag.substring(0,index - 1);
					
					// if an & or ? is used after the last occurrence of an = then don't add quotes
					// else find last index of a space and add a closing quote
					
					var amp_index = tag_sub.lastIndexOf("&");
					var qtm_index = tag_sub.lastIndexOf("?");
					var qut_index = (quote_list[quote_list.length-1])? quote_list[quote_list.length-1] : tag_sub.lastIndexOf("\"");

					if(amp_index > qut_index || qtm_index > qut_index){

					}else{
					
						quote_list.push(tag_sub.lastIndexOf(" "));
						
						quote_status = false;
					
					}
					 	
				}
						
				if(quote_status === false){
					
					// *** identify opening quotes ***
					
					if(tag.charAt(index + 1) != "\""){
	
						quote_list.push(index + 1);
							
						quote_status = true;
				
					}else if(tag.charAt(index + 1) == "\""){
					
						quote_status = true;
					
					}
							
				}
				
			}
			
			if(quote_status === true && index == tag.length - 1){
			
				if(tag.charAt(index-1) != "\""){

					quote_list.push(index);
					
				}
							
				quote_status = false;
				
			}
			
		}
	
	}

	
	for(var index = 0; index <= tag.length; index++){

		// *** insert quotes into tag ***

		for(var quote in quote_list){
		
			if(quote_list[quote] == index){
			
				xhtml_tag += "\"";

				break;
					
			}
			
		}

		xhtml_tag += tag.charAt(index);

	}
	
	// *** need to support use of ampersands within tag attributes ***
	
	xhtml_tag = xhtml_tag.replace(/&amp;/g,"&");

	// *** add closing tag ***
	
	return ((close_tag === true)? xhtml_tag.substring(0,xhtml_tag.length-1)+"/>" : xhtml_tag).toLowerCase();
		
}

function format_content(content){

	var html_char = /[£'"]/g;
	var backslash = /\\/g;
	
	return (content.replace(html_char,format_character)).replace(backslash,"&#92;");

}

var character_codes = new Array({"£":"&#163;","'":"&#39;","\"":"&#34;"});

function format_character(character){
	
	return character_codes[0][character];

}