/* ----------------------- generic cross-broswer functions ----------------------- */ 

// function to add event listener regardless of browser 
// el is the DOM element, 
// eType is the event type, 
// fn is the function to execute and uC is the propogation type - true to propogate, false to not
function addEvent(el, eType, fn, uC) {
	
	if (el.addEventListener) {
		el.addEventListener(eType, fn, uC);
	}
	// IE Specific
	else if (el.attachEvent) {
		el.attachEvent('on' + eType, fn);
	}
	else {
		el['on' + eType] = fn;
	}
}

// stop default event - do not submit form
function stopDefaultEvent(e) {
	if (e && e.preventDefault) {
		e.preventDefault();
	}	
	// IE Specific
	else if (window.event && (window.event.returnValue == null)) {
		window.event.returnValue = false;
	}
}

function stopEventBubble(e) {		
    if (e && e.stopPropogation) {
        e.stopPropogation();
    }
    // IE Specific
    else if (window.event && window.event.cancelBubble) {
	window.event.cancelBubble = true;
    }
}

// access the object that triggered an event function
function getEventObject(e) {
	var eventObject;
	if (e.target) {
		eventObject = e.target;
		return eventObject;
	}
	else if (e.srcElement) {
		eventObject = e.srcElement;
		return eventObject;			
	}
	else if (window.event) {
		eventObject = window.event;
		return eventObject;	
	}
}

// function kindly donated by quirks mode
function getElementsByTagNames(list,obj) {
	if (!obj) var obj = document;
	var tagNames = list.split(',');
	var resultArray = new Array();
	for (var i=0;i<tagNames.length;i++) {
		var tags = obj.getElementsByTagName(tagNames[i]);
		for (var j=0;j<tags.length;j++) {
			resultArray.push(tags[j]);
		}
	}
	var testNode = resultArray[0];
	if (!testNode) return [];
	if (testNode.sourceIndex) {
		resultArray.sort(function (a,b) {
				return a.sourceIndex - b.sourceIndex;
		});
	}
	else if (testNode.compareDocumentPosition) {
		resultArray.sort(function (a,b) {
				return 3 - (a.compareDocumentPosition(b) & 6);
		});
	}
	return resultArray;
}

/* ----------------------- page setup variable and functions ----------------------- */ 

// global variables
// create global array
var formArray = new Array();
// create constants for test type array
var TEXT_CHECK = 0;
var EMAIL_CHECK = 1;
var NUMBER_CHECK = 2;
var DATE_CHECK = 3;

var errorID = 0;

// setField function to add field set-up information to field array
// field type, with type test array holding a constant(s), 
// is required, is to have an onblur event added, form id for which form to add the event
function setField(field, testTypes, isRequired, setOnBlur, formID) {
	tempFieldArray = new Array();
	var y = 0;
	tempFieldArray[y] = field;
	y++;
	tempFieldArray[y] = testTypes.slice(0, testTypes.length);
	y++;
	tempFieldArray[y] = isRequired;
	y++;
	tempFieldArray[y] = setOnBlur;
	y++;
	tempFieldArray[y] = formID;
	formArray[formArray.length] = tempFieldArray;
}

// MUST be in the following format:
			
// testTypeArray = [TEST_TYPE_ONE, TEST_TYPE_TWO, ...];
// where:
// TEST_TYPE_X is equal to one of the global constant variables
	
// setField('name', testTypeArray, isRequired, setOnBlur, 'form');
// where:
// 'name' is the value of <input> attribute "name" in HTML', 
// testTypeArray - must NOT be changed 
// isRequired (boolean) -whether the field must be entered (true) by the user or not (false)
// setOnBlur (boolean) - whether the field is to have an onblur event (true) or not (false)
// 'form' is the HTML id of the form that contains this field
function setFormArray() {
	//delcare testType array
	testTypeArray = new Array();
	// first form set-up
	testTypeArray = [TEXT_CHECK];
	setField('name', testTypeArray, true, true, 'repository-form');	
	testTypeArray = [EMAIL_CHECK];
	setField('email', testTypeArray, true, true, 'repository-form');
}

function go() {
	setFormArray();
	addBlurEvent();
	addSubmitEvent();
}

/* ----------------------- add event functions ----------------------- */ 

// onblur events
function addBlurEvent() {
	// get elements by tag name <form>
	var theForms = document.getElementsByTagName('form');
	// loop through form elements
	for(x = 0; x < theForms.length; x++) {
		// get elements by tag name - <input>
		var theInputs = theForms[x].getElementsByTagName('input');
		// loop thought all  <input> & <textarea> elements
		for(var y = 0; y < theInputs.length; y++) {
			// loop through all of formArray
			for(var z = 0; z < formArray.length; z++ ) {
				// if the global array value is have onblur event added 
				// and if the <input> & <textarea> tag's attribute "name" is equal to global array value
				if(formArray[z][3] && theInputs[y].name == formArray[z][0] && formArray[z][4] == theForms[x].getAttribute('id')) {	
					// add blur event, set the function to run onblur
					addEvent(theInputs[y], 'blur', processFormOnBlur, false);
				}
			}
		}
	}
}

// onsubmit events
function addSubmitEvent() {
	// get elements by tag name <form>
	var theForms = document.getElementsByTagName('form');
	// loop through forms
	for(var x = 0; x < theForms.length; x++) {
		// add onsubmit event & set function to run to check form when submitted
		addEvent(theForms[x], 'submit', processFormOnSubmit, false);
	}
}	

/* ----------------------- form field processing functions ----------------------- */ 

// function to check form field value when user clicks or tabs out of field
// needs to also handle text areas
function processFormOnBlur(e) {
	// get event object
	var eventObject = getEventObject(e);
	var eventValue  = eventObject.name;
	// get elements by tag name <form>
	var theForms = document.getElementsByTagName('form');
	// loop through form elements
	for(x = 0; x < theForms.length; x++) {
		// get elements by tag name - <input> & <textarea>
		var theInputs = getElementsByTagNames('input,select,textarea', theForms[x]);
		// loop thought all  <input> & <textarea> elements
		for(var y = 0; y < theInputs.length; y++) {
			// loop through all of formArray
			for(var z = 0; z < formArray.length; z++ ) {
				if(eventValue == formArray[z][0] && eventObject == theInputs[y]  && formArray[z][4] == theForms[x].getAttribute('id')) {	
					// get test types
					var testTypes = formArray[z][1];
					// run selectCheck function - pass test types & currentElement
					selectCheck(testTypes, eventObject, formArray[z][2], e);
					return;
				}
			}
		}
	}
}

// function to check form ALL field values when submitted
// needs to also handle text areas
function processFormOnSubmit(e) {
	// get event object
	var eventObject = getEventObject(e);
	var theID = eventObject.getAttribute('id');
	// get form by id
	var theForm = document.getElementById(theID);
	// get inputs within forms
	var theInputs = getElementsByTagNames('input,select,textarea', theForm);
	// loop through inputs
	for(var x = 0; x < theInputs.length; x++) {
		// if input is equal to eventObject values
		// loop through global array
		for(var y = 0; y < formArray.length; y++) {
			// if form id and name is equal to values in global array
			if(formArray[y][4] == theID && formArray[y][0] == theInputs[x].name && formArray[y][3]) {
				// get test types
				var testTypes = formArray[y][1];
				// run selectCheck function
				selectCheck(testTypes, theInputs[x], formArray[y][2], e);
			}
		}
	}
}

// function in which a switch statement runs the relevant error checking function
function selectCheck(testTypeArray, currentElement, isRequired, theEvent) {
	// loop through test types
	for(var x = 0; x < testTypeArray.length; x++) {
		var theTest = testTypeArray[x];
		switch(theTest) {
			case 0: 
				// if check finds error
				if(checkText(currentElement.value, isRequired)) {	
					errorText = 'Your name is required';
					addError(errorText, currentElement);
					stopDefaultEvent(theEvent);
					break;
				}	
				// else no error
				removeError(currentElement);	
				break;
			case 1:
				// if check finds error
				if(checkEmail(currentElement.value, isRequired)) {
					errorText = 'Please enter a valid email';
					addError(errorText, currentElement);
					stopDefaultEvent(theEvent);
					break;
				}
				// else no error
				removeError(currentElement);
				break;
			default:
				alert('default');
				break;
		}
	}
}

/* ----------------------- error checking functions ----------------------- */ 

// check txt field
function checkText(txt, isRequired) {
	var theText = txt;
	// if required
	if(isRequired) {
		// if not entered
		if(txt == null || txt == '' || txt == 'undefined') {
			// error
			// return
			return true;
		}
	}
	return false;
}

// check email
function checkEmail(email, isRequired) {
	// if required
	if(isRequired) {
		// if not entered
		if(email == null || email == '' || email == 'undefined') {
			// error
			// return
			return true;
		}
	}
	// validate
	var at = email.indexOf('@');
	var dot = email.lastIndexOf('.');
	if(at < 1 || dot - at < 3 || email.length - dot < 2 ) {
		return true;
	}
	// all ok
	return false;
}

/* ----------------------- error message functions ----------------------- */ 

// add error to page
function addError(theErrorTxt, currentElement) {
	// if error has been added to page (check by id)	
	if(currentElement.nextSibling.nextSibling.className == 'error-msg-span') {
		// change error message??
		return;
	}
	//else
	else {
		//create new clone of currentElement
		currentElement.style.borderColor = '#B20000';
		
		var errorElement = new Object;
		errorElement = currentElement.cloneNode(true);
		
		// creat new <div>
		/*var errorDIV = document.createElement('div');
		// set class to div for styling
		errorDIV.className = 'error-msg-div';		*/
		// creat new <span>
		var errorSPAN = document.createElement('span');
		// set class to span for styling
		errorSPAN.className = 'error-msg-span';
		// create new text node with error message
		errorTxt = document.createTextNode(theErrorTxt);

		theSpan = currentElement.parentNode.lastChild;

		// add <div> to page, replacing moving currentElement
		/*currentElement.parentNode.appendChild(errorDIV, currentElement);
		errorDIV.parentNode.insertBefore(errorDIV, currentElement);*/
		
		// move input inside div
		/*errorDIV.appendChild(currentElement);*/
		// move span inside div
		/*errorDIV.appendChild(theSpan);*/
		// add text node to <span>
		errorSPAN.appendChild(errorTxt);
		currentElement.parentNode.insertBefore(errorSPAN, currentElement.nextSibling.nextSibling);
		// add error span to div
		/*errorDIV.appendChild(errorSPAN);*/
	}
}

// remove error from page
// currentElement is set during the event process functions
// currentElement is used to identify the correct form and field to remove the error from
function removeError(currentElement) {
	// if error message does NOT exist on page
	if(!currentElement.nextSibling.nextSibling.className == 'error-msg-span') {
		// do nothing
		return;
	}
	// if error message DOES exist on page
	else if(currentElement.nextSibling.nextSibling.className == 'error-msg-span') {
		// remove error from page
		currentElement.style.borderColor = '#CCCCCC';
		var errorElement = currentElement.nextSibling;				
		currentElement.parentNode.removeChild(errorElement.nextSibling);
	}	
}
