
/*
##############################################################################################
#   $Source: /home/cvs/clientside/cvsroot/jstools/lib/lib.jst_regex.js,v $
#   $Author: stephenc $
#   $Revision: 1.7 $
#   $Date: 2004/02/26 08:30:57 $
##############################################################################################
*/

bbcjs.regex =
{
	not_empty		: /^.+$/,

	numeric			: /^\d+$/,
	postcode		: /^[a-z]{1,2}\d{1,2}[a-z]? ?\d{1}[a-z]{2}$/i,
	postcode_partial: /^[a-z]{1,2}\d{1,2}[a-z]?( ?\d{1}[a-z]{2})?$/i,
	email			: /^[\w\d\._-]+@[\w\d-\.]+\.\w{2,3}(\.\w{2,5})?$/,
	string			: /^[a-zA-Z\-\'_ \?]+$/,
	age				: /^1?\d{1,2}$/,
	date			: /^(\d{1,2}[\-|\/]\d{1,2}[\-|\/]\d{4})$/,
	currency		: /^[\$\£]?\d+(\.\d{2})?$/
}



/*
##############################################################################################
#   $Source: /home/cvs/clientside/cvsroot/jstools/lib/lib.jst_string.js,v $
#   $Author: stephenc $
#   $Revision: 1.5 $
#   $Date: 2004/08/24 11:25:12 $
##############################################################################################
*/

bbcjs.lib.string = {};

/**
 * Takes a uniform object and converts this to a name-value paired string, using the delimiters passed as args 2,3
 *
 * @param {object} o The object to be referenced when building the string.
 * @param {string} pd The pair delimiter, default is "&"
 * @param {string} vd The value delimiter, default is "="
 *
 * @returns A string in the format of (for example): name1=val1&name2=val2&...&nameN=valN
 *
 * @author Stephen Calcott
 */
bbcjs.lib.string.obj2string = function (o, pd, vd)
{
	//Have name1=val1&name2=val2 as defaults
	if (typeof(pd)=="undefined") pd = "&";
	if (typeof(vd)=="undefined") vd = "=";

	var str = "", i, t="", cnt = 0;
	if (typeof(o)=="object")
	{
		for (i in o)
		{
			cnt++;
			if (typeof(o[i])=="object" && ((o[i].constructor==Object) || (o[i].constructor==Array) ))
			{
				t += i + vd + escape(bbcjs.lib.string.obj2string(o[i], pd, vd)) + pd;
			}
			else if (typeof(o[i])!="object")
			{
				t += i + vd + o[i] + pd;
			}
		}
		str = t.substring(0, t.length-1);
	}
	else bbcjs.trace("obj2string expected typeof object, not "+typeof(o),1);

	if (cnt==0) str = "_{}";

	return str;
}

/**
 * Takes a name-value paired string, returns an object that is built from this by splitting on args 2,3
 *
 * @param {object} str The string to be analysed and split.
 * @param {string} pd The pair delimiter, default is "&"
 * @param {string} vd The value delimiter, default is "="
 *
 * @returns A single-level nested object with the values found in the name-val pairs.
 *
 * @author Stephen Calcott
 */
bbcjs.lib.string.string2obj = function (str, pd, vd)
{
	//Have name1=val1&name2=val2 as defaults
	if (typeof(pd)=="undefined") pd = "&";
	if (typeof(vd)=="undefined") vd = "=";

	var pairs = str.split(pd);
	var i, j, o={}, pair=[], t;

	for (i=0; i<pairs.length; i++)
	{
		pair = pairs[i].split(vd);
		if (pair.length==2)
		{
			t = unescape(pair[1]);
			if (t.indexOf(vd)!=-1)
			{
				o[pair[0]] = bbcjs.lib.string.string2obj(t, pd, vd);
			}
			else
			{
				if (!isNaN(parseInt(pair[0]))) pair[0] = parseInt(pair[0]);
				if (unescape(pair[1])!="_{}") o[pair[0]] = pair[1];
				else o[pair[0]] = {};
			}
		}
		else bbcjs.trace("WARNING: string2obj:: '"+pairs[i]+"' is not a proper name-val pair (using '"+pd+"' and '"+vd+"')",5);
	}
	return o;
}
/*
##############################################################################################
#   $Source: /home/cvs/clientside/cvsroot/jstools/mod/mod.jst_forms.js,v $
#   $Author: stephenc $
#   $Revision: 1.26 $
#   $Date: 2004/08/24 11:27:23 $
##############################################################################################
*/

bbcjs.trace('<b><font color="green">jst_forms.js</font> was included.</b>',2);

//Initialise the forms object.
bbcjs.forms = new bbcjs.Module("forms", 1, "$Revision: 1.26 $", "$Date: 2004/08/24 11:27:23 $");
bbcjs.forms.required	= {};
bbcjs.forms.req_err		= {};
bbcjs.forms.valErrorMsg = "Please enter all required information correctly.";

//One stop shop form validation:
bbcjs.forms.validate = function (f)
{
	bbcjs.trace('<hr /><b>bbcjs.forms.validate('+f.name+')</b>...',2);

	//Default return value is to return true to the system.
	var retval = true, errorElement = " ", errorMsg = bbcjs.forms.valErrorMsg, val = "", i;

	//Loop through all elements defined in the required object, as these are the ones needed.
	for (i in bbcjs.forms.required)
	{
		bbcjs.trace("Checking element: <b>"+i+"</b>", 3);

		//If we have a more complex validation to do (eg range) do so...
		if ( (typeof(bbcjs.forms.required[i])=="object") && (typeof(bbcjs.forms.required[i].type)!="undefined") )
		{
			bbcjs.trace("&nbsp;&nbsp;Checking <b>"+bbcjs.forms.required[f[i].name].type+"</b> element",3);
			if (!bbcjs.forms.validateComplex(f[i]))
			{
				val = bbcjs.forms.getValue(f[i]);
				retval = false;
			}
		}
		else
		{
			//Get the value of the elemnt from getValue
			val = bbcjs.forms.getValue(f[i]);
			if (val) val = val.toString();

			bbcjs.trace("getValue returned element of type <b>"+typeof(val)+"</b>", 5);

			//If we have an element which returned an array, just check that at least one was selected
			if (typeof(val)=="object")
			{
				if (val.length==0) retval = false;
			}
			else //just use regex
			{
				if (typeof(val)=="string") val = val.replace(/[\r|\n]/g, "");
				if (typeof(val)=="undefined" || (!val.match(bbcjs.forms.required[i])) )
				{
					retval = false;
				}
			}
		}
		if (!retval)
		{
			//If we've not validated, set error message and break.
			bbcjs.trace("&nbsp;&nbsp;Element does not validate! Value: "+val+"",3);
			bbcjs.trace("&nbsp;&nbsp;&nbsp;&nbsp;Requires: "+bbcjs.forms.required[i],4);
			errorElement = i;
			break;
		}
	}

	if (!retval)
	{
		//If the element that failed validation has a bespoke error message, use it.
		if (typeof(bbcjs.forms.req_err[errorElement])!="undefined")	errorMsg = bbcjs.forms.req_err[errorElement];
		
		// Added by benr - 4/5/04
		// Only attempt to move the focus if the form element is not a hidden element
		// Attempting to move the focus to hidden elements throws an exception
		if (f[errorElement].type != "hidden") {
			if (typeof(f[errorElement].focus)!="undefined") f[errorElement].focus();
		}
		
		alert(errorMsg);
	}

	//Debugging - set text colour to red or green dependent on return value.
	var jst_fret_col = retval ? 'green' : 'red';
	bbcjs.trace('<b>bbcjs.forms.validate</b> is returning <font color=\''+jst_fret_col+'\'><b>'+retval+'</b></font><hr />',2);

	return retval;
}


//Returns the value of the radio button that is checked in a group (fe)
bbcjs.forms.getRadioValue = function(fe)
{
	var retval, i;
	for (i=0; i<fe.length; i++)
	{
		if (fe[i].checked) retval = fe[i].value;
	}
	bbcjs.trace("getRadioValue is returning <b>"+retval+"</b>",5);
	return retval;
}

//Returns an array of all of the elements checked in a checkbox group
bbcjs.forms.getCheckboxValues = function(fe)
{
	var retval = [], i;
	if (typeof(fe.length)!="undefined")
	{
		for (i=0; i<fe.length; i++)
		{
			if (fe[i].checked)
			{
				retval[retval.length] = fe[i].value;
			}
		}
	}
	else if (fe.checked) retval[0] = fe.value;
	else retval[0] = "";

	bbcjs.trace("getCheckboxValues is returning <b>"+retval+"</b>",5);
	return retval;
}

//Returns an array OR a value of a select-multi / select box.
bbcjs.forms.getSelectValue = bbcjs.forms.getSelectValues = function(sb)
{
	var retval, i;

	if (sb.type == "select-multiple")
	{
		retval = [];
		for (i=0; i<sb.options.length; i++)
		{
			if (sb.options[i].selected && (sb.options[i].value!=""))
			{
				retval[retval.length] = sb.options[i].value;
			}
		}
	}
	else retval = sb.options[sb.selectedIndex].value;

	bbcjs.trace("getSelectValues is returning <b>"+retval+"</b>",5);
	return retval;
}

//Provides extended functionality for comparisons above regex's.
bbcjs.forms.validateComplex = function(fe)
{
	var retval;
	bbcjs.trace("validateComplex called...", 3);

	switch (bbcjs.forms.required[fe.name].type)
	{
		case "range" : retval = bbcjs.forms.required[fe.name].contains(fe.value); break;
		default : retval = true;
	}
	bbcjs.trace("validateComplex is returning <b>'"+retval+"'</b>",4);
	return retval;
}


//generic function to get a value of any form element.
bbcjs.forms.getValue = function(fe)
{
	var typestring, t = "";

	if (typeof(fe)!="object")
	{
		bbcjs.trace("Error - getValue expects type: form element, not '"+typeof(fe)+"'.",1);
		return false;
	}

	//Set type of element, if type isn't defined, try to get from 0th element
	if (typeof(fe.type)!="undefined") typestring = fe.type;
	else if (typeof(fe.length)!="undefined") typestring = fe[0].type;

	bbcjs.trace("<b>getValue()</b>, checking item of type <b>"+typestring+"</b>",4);

	//switch on type...
	switch (typestring)
	{
		case "radio" :
				t = bbcjs.forms.getRadioValue(fe);
				break;

		case "checkbox"	:
				t = bbcjs.forms.getCheckboxValues(fe);
				break;
		
		case "select-one" :
				t = bbcjs.forms.getSelectValue(fe);
				break;

		case "select-multiple" :
				t = bbcjs.forms.getSelectValues(fe);
				break;

		default :
				t = fe.value;
				break;
	}
	bbcjs.trace("getValue is returning <b>'"+t+"'</b>",4);
	return t;
}


// Function:	bbcjs.forms.setValue (fe, str)
// Desc:	Set the value of a form element and update the user interface for radio buttons and check boxes
bbcjs.forms.setValue = function (fe)
{

	var str = arguments[1], i;
	
	bbcjs.trace('setValue function', 3);
	bbcjs.trace(fe.type, 3);

	if (fe.length>0 && fe.type != 'select-one' && fe.type != 'select-multiple')	// if the element is radio or check boxes
	{
		bbcjs.trace('setValue for radio or checkbox', 3);
		for (i=0; i<fe.length; i++)
		{
			if (fe[i].value == str){
				fe[i].checked = true;
			} else {
				fe[i].checked = false;
			}
		}
	}
	// Added by benr
	else if (fe.type == 'select-one') // if the element is a single select list
	{
		bbcjs.trace('setValue for select-one', 3);
		for (i=0;i<fe.length;i++) 
		{
			if (fe[i].value == str) 
			{
				fe.selectedIndex = i;
				break;
			}
		} 
	}
	else if (fe.type == 'select-multiple') // if the element is a multiple select list
	{
		bbcjs.trace('setValue for select-multiple', 3);
		for (i=0;i<fe.length;i++) 
		{
			for (var j=1; j<arguments.length; j++) 
			{
				if (fe.options[i].value == arguments[j]) 
				{
					fe.options[i].selected = true;
					break;
				}
			}
		} 
	}
	else
	{
		bbcjs.trace('setValue for other', 3);
		fe.value = str; 
	}
}

// Function:	bbcjs.forms.form2object
// Desc:	Returns an object that contains the result of doing a getValue on each element.
bbcjs.forms.form2object = function (f)
{
	var o = new Object();
	var t = "", i;
	bbcjs.trace("form2object called on form named: '"+f.name+"'", 3);

	//Loop through each form element and assign value to object "o"...
	for (i=0; i<f.elements.length; i++)
	{
		if (f[i].name) //only asign objects that can be referenced
		{
			if ( (f[i].type == "checkbox") | (f[i].type == "radio") ) t = bbcjs.forms.getValue(f[f[i].name]);
			else if (f[i].type != "submit") t = bbcjs.forms.getValue(f[i]);
			else t = "";

			if (!(t)) t = ""; //for non-checked radios
			o[f[i].name] = t;
		}
	}
	bbcjs.trace("form2object returned: "+bbcjs.obj2list(o), 5);
	return o;
}

// Function:	bbcjs.forms.form2cookie
// Desc:	Automatically converts form values into a cookie representation... is useful for page-to-page tracking.
//			Also requires the cookie module to be loaded
bbcjs.forms.form2cookie = function (f, name, exp, pth, dmn)
{
	var retval = false, t = {}, c = {}, i=0;
	if (bbcjs.cookies)
	{
		bbcjs.trace("form2cookie:: '"+f.name+"' -&gt; '"+name+"'",3);

		t = bbcjs.forms.form2object(f);
		
		//We need to ammend to a cookie instead of overwriting it... Thus we use cookieData...
		if (bbcjs.cookies.cookieData[name])
		{
			c = bbcjs.cookies.cookieData[name];
			for (i in t) c[i] = t[i];
			t = c;
		}
		
		retval = bbcjs.cookies.setCookie(name, t, exp, pth, dmn);
	}
	else bbcjs.trace("form2cookie:: Could not find cookie module! Please include jst_cookies.",1);
	return retval;
}