///////////////////////////////////////////////////////////////////////////////
// Form and user data manipulation facilities
// Sam Briesemeister (c) 2008
// This is currently NOT licensed under GPL or any other Open Source license. 
// Distribution of this code is prohibited except by permission of the author.
///////////////////////////////////////////////////////////////////////////////

// Data structure
var Form = new Object();
Form.Field = new Object();

// Color to shade fields not matching their patterns
Form.highlightInvalid = 'yellow'; 

////////////////////////////////////////////////////////////////////////////////
////////////////////* Supporting Functions *////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

Form.Field.getValue = function(e){ 
	// This is adapted from the AJAX form submission tool. Further revision is necessary.
	var t, i, v = '';
//	breakpoint(function(e){return eval(e);}); // used for debugging.
	switch(e.type){
		case 'checkbox': v = (e.checked) ? 'on' : false; break;
		case 'radio': v = (e.checked) ? e.value : false; break;
		case 'select-multiple': 
			v = new Array();
			if(e.selectedIndex < 0) return '';
			for(i = 0; i < e.options.length; i++){
				if(e.options[i].selected) v[v.length] = e.options[i].value;
			}
			break;
		case 'select-one':
			if(e.selectedIndex < 0) return null;
			v = e.options[e.selectedIndex].value;
			break;
		default: v = e.value.toString();  
	}
	
//	if(typeof(v) == 'string' && v == '') return null;
	return v;
}
///////////////////////////////////////////////////////////////////////////////
//////////////////////* Form validation *//////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Form.Validate = function(form, highlight, errMessage){
	// Scan fields for the 'pattern' attribute, handle as RegExp
	var i, allFieldsValid = true; // start by assuming true.
	if(typeof(highlight) != 'boolean') highlight = true;
	if(typeof(errMessage) != 'string') 
		errMessage = "One or more fields contain errors. Please correct " + ((highlight)?'the highlighted fields':'them') + " to proceed.";
	for(i = 0; i < form.elements.length; i++){
		allFieldsValid = Form.Field.checkValidity(form.elements.item(i), highlight) && allFieldsValid;
	}
	if(allFieldsValid != true) alert(errMessage);
	return allFieldsValid;
}

Form.Field.checkValidity = function(field, highlight){
	if(highlight) return this.Highlight(field, this.isValid(field));
	else return this.isValid(field);
}

Form.Field.Highlight = function(field, valid){
	field.style.backgroundColor = (valid) ? '' : Form.highlightInvalid;
	return valid;
}

Form.Field.isValid = function(field, pattern){
	if(field.disabled || !this.hasPattern(field)) return true;
	if(typeof(pattern) != 'function' && typeof(pattern) != 'object'){
		pattern = new RegExp(field.getAttribute('pattern'));
	}

	var d = field.getAttribute('debug'), v = this.getValue(field), b = true;

	if(v === 'false' || (!v && typeof(v) != 'string')) return false;
	if(typeof(v) == 'null') return false;
	
	b = this.checkPattern(v, pattern);
	

	if(d) 
		alert('[dbg] ['+field.name+']'
			+ '\npattern: ' + pattern 
			+ '\nvalue: ' + v.toString() 
			+ '\nmatch: ' + b
			);

	return b;
}

Form.Field.checkPattern = function(v, pattern){
	if(typeof(v) != 'string'){
		var i, b = true;
		for(i = 0; i < v.length; i++){
			if(typeof(v[i]) != 'string') return null; // Panic if it's not an array of strings.
			b = b && this.inArray(v[i], v[i].match(pattern));
		}
		return b;
	}else return this.inArray(v, v.match(pattern));
}


Form.Field.inArray = function(v, arr){
	var i;
	for(i in arr){
		if(arr[i] === v) return true;
	}
	return false;
}


Form.Field.hasPattern = function(e){
	// IE6 does not support the DOM standard 'hasAttribute' function. (yay MS! /sarcasm)
	return ((e.hasAttribute) ? e.hasAttribute('pattern') : (e.getAttribute('pattern') != null));
}

///////////////////////////////////////////////////////////////////////////////
////////////////////////* Query building */////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

Form.Query = function(form, validate){
	// Compile the provided data into a query string (usually used in AJAX)
	if(validate === true && !this.Validate(form, true)) return false;
	
	var i, v, q = '';
	for(i = 0; i < form.elements.length; i++){
		if(typeof(form.elements[i].name) != 'string') continue;
		if(form.elements[i].name == '') continue;
		v = this.Field.QueryString(form.elements[i]);
		if(v) q+= v;
	}
	return q;
}

Form.Field.QueryString = function(field){
	if(typeof(field) != 'object') return null;
	var s = '', v = this.getValue(field); if(!v) return null;

	if(typeof(v) == 'string' || typeof(v) == 'number'){
		s = (escape(field.name)+'='+escape(v)+'&');
	}else{
		var i, n = escape(field.name);
		for(i = 0; i < v.length; i ++){
			s += n + '=' + escape(v[i]) + '&';
		}
	}
	return s;
}

