/*
		global_javascript_tools.js
		JobOffice 		-Section-or-area-this-template-is-for-
			
		Author:			Rawdyn Nutting
		Date:			-DD-MM-.2004
			
		USE:			-How-is-this-template-accessed-by-the-application-eg-included-on-job_card_cfm-etc-
		TASK:			-Basic-task-this-template-performs-
		OUTPUT:			-Any-output-this-template-produces-
		PROCESS:		-Any-specialnotes_relating-to-this-template
		DOCUMENTS		-Any-documentation-on-this-template-or-its-functionality
*/




function isNumeric(test_string)
{	var is_number = true;
	var test_format = 'numeric';
	var numeric = /^-?[0-9]+$/;
	var numeric_format = '\tValid numeric format allows for only whole numbers. This means no decimal places or thousands separator.\n\n';
	var currency = /^\$?-?([0-9]{1,3}\,[0-9]{3}]*\.[0-9]{2}|[0-9]+\.[0-9]{2})$/;
	var currency_format = '\tValid currency format is;\n\tDollar sign ($)\t\tOptional\n\tThousands separator (,)\tOptional\n\tDemial Places (.00)\t\tRequired (two places)\n\n';
	var accounting = /^-?([0-9]{1,3}\,[0-9]{3}]*(\.[0-9]{2})?|[0-9]+(\.[0-9]{2})?)$/;		///^-?([0-9]{1,3}\,[0-9]{3}]*\.[0-9]{2}|[0-9]+\.[0-9]{2})$/;
	var accounting_format = '\tValid accounting format is;\n\tOptional\n\tThousands separator (,)\tOptional\n\tDemial Places (.00)\t\tRequired (two places)\n\n';
	var accounting_light = /^-?([0-9]+(\.[0-9]{2})?)$/;		
	var accounting_light_format = '\tValid accounting light format is;\n\tThousands separator (,)\tNOT ALLOWED\n\tDemial Places (.00)\t\tOptional (two places)\n\n';
	var integer_punctuated = /^(([0-9]{1,3})+(\,[0-9][0-9][0-9])*|[0-9]+)$/;		
	var integer_punctuated_format = '\tValid accounting format is;\n\tOptional\n\tThousands separator (,)\tNOT ALLOWED\n\tDemial Places (.00)';
	var decimal = /^-?[0-9]+\.?[0-9]{0,2}$/;
	var decimal_format = '\tValid decimal format is;\n\tDemial Places (.00)\t\tRequired (two places)\n\n';		
	var floating = /^-?[0-9]+\.?[0-9]*$/;
	var floating_format = '\tValid floating format is;\n\tDemial Places (.00*)\t\tAny (Zero or more places)\n\n';						
	if(arguments.length == 2 && (arguments[1] == 'currency' || arguments[1] == 'accounting' || arguments[1] == 'accounting_light' || arguments[1] == 'decimal' || arguments[1] == 'floating' || arguments[1] == 'integer_punctuated'))	// if mode passed in and is not the default one but still a valid one
		test_format = arguments[1];															// reset the mode to the one passed in						
	this_re = eval(test_format);															// define the re string to match for this validation option
	this_eg = eval(test_format+'_format');													// define the format message (if any)						
	if(this_re.test(test_string))															// if the number to test exists and passes the required RegExp test
		return true;
	else
		return false;
}

function reorder(formName,keyObj)
{	var thisForm = eval('document.'+formName);												// collect the form as an object
	var hidObj = eval('document.'+formName+'.'+keyObj.name+'_hid');								// get the hidden object for the one clicked
	var vMin = Math.min(keyObj.value,hidObj.value);											// get the minimum of the two (the key object and te hidden (original value) object
	var vMax = Math.max(keyObj.value,hidObj.value);
	var vKey = keyObj.name;
	var vDir = 1;	
	var vPrefix = vKey.substring(0,(vKey.lastIndexOf("_")+1));								// define the prefix of all key form fields in this order set (NOTE all hidden ones must be the same but have '_hid' as a suffix)

//alert('Prefix='+vPrefix+'\nKey='+vKey+'\nMin='+vMin+'\nMax='+vMax+'\nDirection='+vDir);
//alert(keyObj.value+' - '+hidObj.value);
	if(parseInt(keyObj.value) > parseInt(hidObj.value))															// if hte new value entered is greater than the old value in the hidden field
	{	vDir = -1;
	}
	
	
	if(!isNumeric(keyObj.value))
	{	alert('You must enter a number!');
		keyObj.value = hidObj.value;
	}
	else
	{	for(i=0;i<thisForm.length;i++)																																	// loop all form elements
		{	if(thisForm[i].name.substring(0,vPrefix.length) == vPrefix && thisForm[i].name.substring(thisForm[i].name.length - 4,thisForm[i].name.length) != '_hid')	// If this elements name has the target prefix and is not a hidden version of the target
			{	if(thisForm[i].value >= vMin && thisForm[i].value <= vMax && thisForm[i].name != keyObj.name)			// if this index is GTE the min and LTE the max and NOT the one being changed
				{	thisForm[i].value = parseInt(thisForm[i].value)+vDir;
					thisForm[thisForm[i].name + '_hid'].value = parseInt(thisForm[i].value);
				}
			}
		}
		hidObj.value = keyObj.value;
	}
}



/*###########################################################  FORM FIELD CHAR COUNTER  #############################################################*/


/*		Limits field to specified count and displays currentl length
		REQUIRES - text field named same as the field to be measured but with a suffix of '_counter'
		EXAMPLE
						<textarea name="seek_description" onKeyUp="count_down(this,150,'force');">#get_job.Seek_Description#</textarea>
						<input type="text" name="seek_description_counter" size="5" value="150">
*/
function count_down(obj,limit,react)
{	counter_obj = document.getElementById(obj.name+'_counter');
	clean_value = obj.value.replace(new RegExp( "\\n", "g" ),'BR');									// replace line breaks with two characters. JS counts line feeds as one where as CF counts two chgaracters
	clean_value_length = clean_value.length;																														
	template_value = obj.value.replace(new RegExp( "[^\\n]", "g" ),'c');							// buld template of just positions. eg. 'cccccccccccccccc\ncccccccc\ncccccccccccccccccc'
	template_value = template_value.replace(new RegExp( "\\n", "g" ),'BR');							// buld template of just positions. eg. 'ccccccccccccccccBRccccccccBRcccccccccccccccccc'
	
	if(limit == 0)																					// if doing a reverse counter (that counts up)
	{	counter_obj.value = clean_value_length;
	}
	else
	{	counter_obj.value = limit - clean_value_length;		
		if(react == 'force' && clean_value_length > limit)
		{	
			obj.value = obj.value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');						// trim any leading or trailing spaces.
			re_clean_value = obj.value.replace(new RegExp( "\\n", "g" ),'BR');						// replace line breaks with two characters. JS counts line feeds as one where as CF counts two chgaracters
			if(re_clean_value.length > limit)														// if after timming it is still over the limit...
			{	template_value = template_value.substring(0, limit);								// 1. Trim the template value to the limit
				trimmed_template_value = template_value.replace(new RegExp( "BR", "g" ),'B');		// 2. Convert the template value back to single character breaks
				obj.value = obj.value.substring(0, trimmed_template_value.length);					// 3. Trim the real string to this length
			}
			counter_obj.value = 0;
		}
	}
}


/*###########################################################  TEXTAREA EDITOR  #############################################################*/

// Startup variables
var theSelection = false;
var form_obj = '';
var helpbox_obj = '';
var textbox_obj = '';
function load_boxes(form_object,textbox_name)					// Form Object | Textbox Form Emelement Name | (Helpbox Form Element Name - OPTIONAL)
{	form_obj = form_object;										// localise the form object
	textbox_obj = eval(form_obj[textbox_name]);					// localise the textbox element
	if(arguments.length > 2)									// localise the help box element
		helpbox_obj = eval(form_obj[arguments[2]]);
}

// Check for Browser & Platform for PC & IE specific bits
// More details from: http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
var clientPC = navigator.userAgent.toLowerCase(); // Get client info
var clientVer = parseInt(navigator.appVersion); // Get browser version
var is_ie = ((clientPC.indexOf("msie") != -1) && (clientPC.indexOf("opera") == -1));
var is_nav = ((clientPC.indexOf('mozilla')!=-1) && (clientPC.indexOf('spoofer')==-1)
                && (clientPC.indexOf('compatible') == -1) && (clientPC.indexOf('opera')==-1)
                && (clientPC.indexOf('webtv')==-1) && (clientPC.indexOf('hotjava')==-1));
var is_moz = 0;
var is_win = ((clientPC.indexOf("win")!=-1) || (clientPC.indexOf("16bit") != -1));
var is_mac = (clientPC.indexOf("mac")!=-1);

// Helpline messages
b_help = "Bold text: <b>text</b>  (alt+b)";
i_help = "Italic text: <i>text</i>  (alt+i)";
u_help = "Underline text: <u>text</u>  (alt+u)";
l_help = "List: <list>text</list> (alt+l) -- Then insert [*] for each item required";
o_help = "Ordered list: <list=>text</list>  (alt+o) -- Then insert [*] for each item required";
p_help = "List Item: <li>Option One</li> - each item in any list needs ot be inside their own <li></li> tags";
w_help = "Insert URL: <url>http://url</url> or <url=http://url>URL text</url>  (alt+w)";
a_help = "Close all open bbCode tags";
s_help = "Font color: <color=red>text</color>  Tip: you can also use color=#FF0000";
f_help = "Font size: <size=x-small>small text</size>";
c_help = "Comment contents are hidden from display";


// Define the bbCode tags
bbcode = new Array();
bbtags = new Array('<b>','</b>','<i>','</i>','<u>','</u>','<ul>','</ul>','<ol>','</ol>','<a href="','">here</a>','<li>','</li>','<!-- ',' -->');
imageTag = false;

// Shows the help messages in the helpline window
function helpline(help)
{	helpbox_obj.value = eval(help + "_help");
}


// Replacement for arrayname.length property
function getarraysize(thearray) {
	for (i = 0; i < thearray.length; i++) {
		if ((thearray[i] == "undefined") || (thearray[i] == "") || (thearray[i] == null))
			return i;
		}
	return thearray.length;
}

// Replacement for arrayname.push(value) not implemented in IE until version 5.5
// Appends element to the array
function arraypush(thearray,value) {
	thearray[ getarraysize(thearray) ] = value;
}

// Replacement for arrayname.pop() not implemented in IE until version 5.5
// Removes and returns the last element of an array
function arraypop(thearray) {
	thearraysize = getarraysize(thearray);
	retval = thearray[thearraysize - 1];
	delete thearray[thearraysize - 1];
	return retval;
}


function bbfontstyle(bbopen, bbclose)
{	var txtarea = textbox_obj;
	if ((clientVer >= 4) && is_ie && is_win) {
		theSelection = document.selection.createRange().text;
		if (!theSelection) {
			txtarea.value += bbopen + bbclose;
			txtarea.focus();
			return;
		}
		document.selection.createRange().text = bbopen + theSelection + bbclose;
		txtarea.focus();
		return;
	}
	else if (txtarea.selectionEnd && (txtarea.selectionEnd - txtarea.selectionStart > 0))
	{	mozWrap(txtarea, bbopen, bbclose);
		return;
	}
	else
	{	txtarea.value += bbopen + bbclose;
		txtarea.focus();
	}
	storeCaret(txtarea);
}


function bbstyle(bbnumber)
{	var txtarea = textbox_obj;
	txtarea.focus();
	donotinsert = false;
	theSelection = false;
	bblast = 0;

	if (bbnumber == -1) { // Close all open tags & default button names
		while (bbcode[0]) {
			butnumber = arraypop(bbcode) - 1;
			txtarea.value += bbtags[butnumber + 1];
			//buttext = eval('form_obj.addbbcode' + butnumber + '.value');												// SEE Line 204 for same function
			//eval('form_obj.addbbcode' + butnumber + '.value ="' + buttext.substr(0,(buttext.length - 1)) + '"');		// SEE Line 205 for same function
			eval('form_obj.addbbcode'+butnumber+'.className = "button_goto_alert"');
			
		}
		txtarea.focus();
		return;
	}

	if ((clientVer >= 4) && is_ie && is_win)
	{	theSelection = document.selection.createRange().text; // Get text selection
		if (theSelection) {
			// Add tags around selection
			document.selection.createRange().text = bbtags[bbnumber] + theSelection + bbtags[bbnumber+1];
			txtarea.focus();
			theSelection = '';
			return;
		}
	}
	else if (txtarea.selectionEnd && (txtarea.selectionEnd - txtarea.selectionStart > 0))
	{	mozWrap(txtarea, bbtags[bbnumber], bbtags[bbnumber+1]);
		return;
	}

	// Find last occurance of an open tag the same as the one just clicked
	for (i = 0; i < bbcode.length; i++) {
		if (bbcode[i] == bbnumber+1) {
			bblast = i;
			donotinsert = true;
		}
	}

	if (donotinsert) 		// Close all open tags up to the one just clicked & default button names
	{	while (bbcode[bblast])
		{	butnumber = arraypop(bbcode) - 1;
			txtarea.value += bbtags[butnumber + 1];
			//buttext = eval('form_obj.addbbcode' + butnumber + '.value'); 												// to turn off asterix indicating open tag getthe value of the tag element (eg B*) (will include asterix remember)
			//eval('form_obj.addbbcode' + butnumber + '.value ="' + buttext.substr(0,(buttext.length - 1)) + '"');		// reset the value to the same minus one char
			eval('form_obj.addbbcode'+butnumber+'.className = "button_goto_alert"');
		}
		txtarea.focus();
		return;
	}
	else
	{ // Open tags
		if (imageTag && (bbnumber != 14)) 		// Close image tag before adding another
		{	txtarea.value += bbtags[15];
			lastValue = arraypop(bbcode) - 1;	// Remove the close image tag from the list
			form_obj.addbbcode14.value = "Img";	// Return button back to normal state
			imageTag = false;
		}

		// Open tag
		txtarea.value += bbtags[bbnumber];
		if ((bbnumber == 14) && (imageTag == false)) imageTag = 1; // Check to stop additional tags after an unclosed image tag
		arraypush(bbcode,bbnumber+1);
		eval('form_obj.addbbcode'+bbnumber+'.className = "button_goto_warn"');//eval('form_obj.addbbcode'+bbnumber+'.value += "*"');
		txtarea.focus();
		return;
	}
	storeCaret(txtarea);
}

function mozWrap(txtarea, open, close)
{	var selLength = txtarea.textLength;
	var selStart = txtarea.selectionStart;
	var selEnd = txtarea.selectionEnd;
	if (selEnd == 1 || selEnd == 2)
		selEnd = selLength;
	var s1 = (txtarea.value).substring(0,selStart);
	var s2 = (txtarea.value).substring(selStart, selEnd)
	var s3 = (txtarea.value).substring(selEnd, selLength);
	txtarea.value = s1 + open + s2 + close + s3;
	return;
}

// Insert at Claret position. Code from	
function storeCaret(textEl) {
	if (textEl.createTextRange) textEl.caretPos = document.selection.createRange().duplicate();
}


/*###################### PAD WITH ZERO  ##########################################################################################################*/

// Zero padding
function pad_string(pad_string, final_length)
{	var pad_with = '0';
	var padding = "";
	var pad_by = final_length-String(pad_string).length;
	var i;
	
	if(arguments.length > 2)
		pad_with = arguments[2];
	
	for (i = 0; i<pad_by; i++)
	{	padding += "0";
	}
	return padding+pad_string;
}


/**
 * Pops up a window without menubars, scrollbars or resizing in the centre of the screen
 *
 * @param URLStr String - URL to appear in window
 * @param width Numeric - width of window
 * @param height Numeric - height of window
 * @param scrollbar Boolean - display scrollbars? 'yes|no'
 * @param resizable Boolean - is the window resizable 'yes|no'
 * @return void
 */
var _popupWindow = null;
function popUpWindow(URLStr, width, height, scrollbar, resizable)
{	var xPos = ((screen.availHeight/2) - (height/2)); 
	var yPos = ((screen.availWidth/2) - (width/2));

	_popupWindow = open(URLStr, 'popUpWin', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars='+scrollbar+',resizable='+resizable+',copyhistory=yes,width='+width+',height='+height+',left='+yPos+', top='+xPos+',screenX='+yPos+',screenY='+xPos+'');
	_popupWindow.focus();
}


/**
 * Trims any trailing whitespace from either side of a string
 * Great resource is http://blog.stevenlevithan.com/archives/faster-trim-javascript
 *
 * @param str String - String to Trim
 * @return String
 */
function trim(str)
{	return ltrim(rtrim(str));
}


/**
 * Trims any trailing whitespace from the left of a string
 *
 * @param str String - String to LTrim
 * @return String
 */
function ltrim(str)
{	return str.replace(/^\s\s*/, '');
}


/**
 * Trims any trailing whitespace to the right of a string
 *
 * @param str String - String to RTrim
 * @return String
 */
function rtrim(str)
{	return str.replace(/\s\s*$/, '');
}


/**
 * Checks to see if the element has the specified class assigned to it
 *
 * @param ele Object - The element to check
 * @param cls String - The class name to check exists
 * @return Boolean
 */
function hasClass(ele,cls) {
	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}


/**
 * Adds a class to an element if it doesn't already exist
 *
 * @param ele Object - The element to add a class to
 * @param cls String - The class name to add
 * @return Boolean
 */
function addClass(ele,cls) 
{	if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}


/**
 * Removes a class from an element if it exists
 *
 * @param ele Object - The element to remove the class from
 * @param cls String - The class name to remove
 * @return Boolean
 */
function removeClass(ele,cls)
{	if (hasClass(ele,cls)) 
	{	var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
		ele.className = ele.className.replace(reg,' ');
	}
}


/**
 * Returns elements that have the classname specified.
 * 
 * @param searchClass String	The Class Name we are searching for
 * @param node Object			The Element To Get Child Elements of
 * @param tag String			Only search tags of this type
 * @return Array[Object]		Element Objects
 */
getElementsByClass = function(searchClass,node,tag)
{	var classElements = new Array();
	
	node = node || document;
	tag = tag || "*";

	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	
	for (i = 0, j = 0; i < elsLen; i++)
	{	if ( pattern.test(els[i].className) )
		{
			classElements[j] = els[i];
			j++;
		}
	}
	
	return classElements;
}
