//alert ("load text-utils.js");

/* AJAX AND XML TEXT FUNCTIONS */

// Ajax status update
function updateStatus(el, readyState) {
	
	var message = document.getElementById(el);
	
	if (readyState == 1) {
		replaceText(message, "Connection Initialised");
		
	} else if (readyState == 2) {
		replaceText(message, "Response in progress");
		
	} else if (readyState == 3) {
		replaceText(message, "Getting server response");
		
	} else if (readyState == 4) {
		replaceText(message, "Data ready");
	}
}

function getXmlById(xmlID) {
	var xmlDoc = request.responseXML;
	return xmlDoc.getElementsByTagName(xmlID)[0];
}

// Page update from returned XML
function updatePageFromXml(params) {

	updateStatus('message', request.readyState);
	
	if (request.readyState == 4) {
		if (request.status == 200) {
			
			var xmlDoc = request.responseXML;
			
			if (xmlDoc != null) {
				
				// html layouts
				while (params.length > 0) {
					var obj = params.shift();
					var el = document.getElementById(obj.html);
					var xmlNode = xmlDoc.getElementsByTagName(obj.xml)[0];
					replaceHtmlFromXml (el, xmlNode);
				}
				
				// xml vars
				var xmlVars = xmlDoc.getElementsByTagName('vars')[0];
				if (xmlVars != null) setVarsFromXml(xmlVars);

				return true;
			
			} else if (request.responseText == 'session time out') {
				sessionTimeOut(); // from login-functions.js
				return false;

			} else {
				updateStatusMessage(request.responseText, 'error');
				return false;
			}
			
		} else {

			var message = request.getResponseHeader("Status");
			
			alert ("message = " + message);
			
			if ((message.length == null) || (message.length <= 0)) {
				updateStatusMessage("Error! Request status is " + request.status, 'error');
				//alert("Error! Request status is " + request.status);
				return false;
				
			} else {
				updateStatusMessage(message, 'error');
				//alert (message);
				return false;
			}
		}
	}
}

// set global vars
var vars = {};
function setVarsFromXml(xmlVars) {
	for (var i = 0; i < xmlVars.childNodes.length; i++) {
		var varName = xmlVars.childNodes[i].nodeName;
		var varValue = xmlVars.childNodes[i].childNodes[0].nodeValue;
		vars[varName] = varValue;
	}
}


/* BASIC TEXT TO DOM FUNCTIONS */

function replaceText(el, text) {
	if (el != null) {
		clearText(el);
		var newNode = document.createTextNode(text);
		el.appendChild(newNode);
	}
}

function clearText(el) {
	if (el != null) {
		if (el.childNodes) {
			for (var i = el.childNodes.length - 1; i >= 0; i--) {
				var childNode = el.childNodes[i];
				el.removeChild(childNode);
			}
		}
	}
}

function getText(el) {
	var text = "";
	if (el != null) {
		if (el.childNodes) {
			for (var i = 0; i < el.childNodes.length; i++) {
				var childNode = el.childNodes[i];
				if (childNode.nodeValue != null) {
					text = text + childNode.nodeValue;
				}
			}
		}
	}
	return text;
}


/* HTML STRING TO DOM FUNCTIONS */

function replaceHtml(el, html) {
	if (el != null) {
		clearText(el);
		addHtml(el, html);
	}
}

function addHtml(el, html) {
	if (el != null) {
		var pattern = new RegExp('(<.*?>)|([^<>]*)', 'g');
		var obj = new Object();
		obj.html = html.match(pattern);
		appendHtml(el, obj);
	}
}

function updateHtmlFromString (elString, htmlString) {
	var el = document.getElementById(elString);
	replaceHtml(el, htmlString);
}

function appendHtml(el, obj) {

	// regular expressions for identifying types of html tags and content
	var openPattern = new RegExp('^<[^\/\!].*?>$');
	var selfClosePattern = new RegExp('^<.*?\/>$');
	var closePattern = new RegExp('^<\/.*?>$');
	var commentPattern = new RegExp('^<\!--.*?-->$');
	var contentPattern = new RegExp('^[^<>]*$');
	
	// loop through the array of html tags until there are none left
	while (obj.html.length > 0) {

		// remove the first entry from the array of html
		html = obj.html.shift();
		html = cleanString(html);
		
		// opening tag (and self-closing)
		if (html.search(openPattern) >= 0) {
			
			// set the 'isSelfClosing' tag (tags like <br /> and <img src=.... />)
			if (html.search(selfClosePattern) >= 0) var isSelfClosing = true;
			else var isSelfClosing = false;

			// find the tag name
			var tagPattern = new RegExp('[^<> ]+');
			var nodeName = html.match(tagPattern)[0];
			
			// and create a new document element and add it to the element submitted to this function
			var newNode = document.createElement(nodeName);
			el.appendChild(newNode);
			
			// extract the tag's attributes (the regex below gets the tag info with a leading space)
			var attributePattern = new RegExp('(?= )(.*?\".*?\")', 'g');
			//var attributePattern = new RegExp('([^ ]*?\".*?\")', 'g');
			var attributes = html.match(attributePattern);
			
			// if the tag has any attributes then set them in the document element
			if (attributes) {
				for (var i = 0; i < attributes.length; i++) {
					var attributeName = attributes[i].substring(1, attributes[i].indexOf("="));
					var attributeValue = html_entity_decode(attributes[i].substring(attributes[i].indexOf("\"") + 1, attributes[i].lastIndexOf("\"")));
					appendAttribute(newNode, attributeName, attributeValue);
				}
			}
			
			// if the tag is not self closing then create a sub-instance of this function with the remaining html
			// so that any nested content or tags are added to the node that has just been created
			if (!isSelfClosing) appendHtml(newNode, obj);
		
		// closing tag
		} else if (html.search(closePattern) >= 0) {

			// break out of the while loop - effectively exiting this sub-instance of the function
			// and returning to the parent instance
			break;
		
		// comment
		} else if (html.search(commentPattern) >= 0) {

			while (html.indexOf("<\!--") > -1) html = html.replace("<\!--", "");
			while (html.indexOf("-->") > -1) html = html.replace("-->", "");
			var newNode = document.createComment(html);
			el.appendChild(newNode);

		// content
		} else if (html.search(contentPattern) >= 0) {
			
			var newNode = document.createTextNode(html);
			el.appendChild(newNode);
		}
	}
	// go back to the top of the while loop
}


/* XML DOM TO BROWSER DOM FUNCTIONS */

function replaceHtmlFromXml (el, xmlNode) {
	
	if (el != null) {
		clearText(el);
		addHtmlFromXml(el, xmlNode);
	}
}

function addHtmlFromXml (el, xmlNode) {
	
	if (el != null) {
		appendHtmlFromXml(el, xmlNode);
	}
}

function appendHtmlFromXml(el, xmlNode) {

	var iLength = xmlNode.childNodes.length;
	
	if (iLength == undefined) alert ("xmlNode.childNodes.length = undefined : xmlNode.nodeName = " + xmlNode.nodeName);
	
	for (var i = 0; i < iLength; i++) {
		
		if (xmlNode.childNodes[i].nodeType == 1) { 			// ELEMENT_NODE

			//alert ("element node : name = " + xmlNode.childNodes[i].nodeName);
			var newNode = document.createElement(xmlNode.childNodes[i].nodeName);
			
			// element attributes
			var jLength = xmlNode.childNodes[i].attributes.length;

			for (var j = 0; j < jLength; j++) {
				var attributeName = xmlNode.childNodes[i].attributes[j].nodeName;
				var attributeValue = html_entity_decode(xmlNode.childNodes[i].attributes[j].nodeValue);
				appendAttribute(newNode, attributeName, attributeValue);
			}
			
			el.appendChild(newNode);
			appendHtmlFromXml(newNode, xmlNode.childNodes[i]);
			
		} else if (xmlNode.childNodes[i].nodeType == 2) { 	// ATTRIBUTE_NODE
			// uses element.attributes property instead
			//alert ("attribute node");
			
		} else if (xmlNode.childNodes[i].nodeType == 3) { 	// TEXT_NODE
		
			//alert ("text node : value = " + xmlNode.childNodes[i].nodeValue);
			var newNode = document.createTextNode(xmlNode.childNodes[i].nodeValue);
			el.appendChild(newNode);
			
		} else if (xmlNode.childNodes[i].nodeType == 4) { 	// CDATA_SECTION_NODE
		} else if (xmlNode.childNodes[i].nodeType == 5) { 	// ENTITY_REFERENCE_NODE
		} else if (xmlNode.childNodes[i].nodeType == 6) { 	// ENTITY_NODE
		} else if (xmlNode.childNodes[i].nodeType == 7) { 	// PROCESSING_INSTRUCTION_NODE
		} else if (xmlNode.childNodes[i].nodeType == 8) { 	// COMMENT_NODE
			
			//alert ("comment node : value = " + xmlNode.childNodes[i].nodeValue);
			var newNode = document.createComment(html_entity_decode(xmlNode.childNodes[i].nodeValue));
			el.appendChild(newNode);
			
		} else if (xmlNode.childNodes[i].nodeType == 9) { 	// DOCUMENT_NODE
		} else if (xmlNode.childNodes[i].nodeType == 10) { 	// DOCUMENT_TYPE_NODE
		} else if (xmlNode.childNodes[i].nodeType == 11) { 	// DOCUMENT_FRAGMENT_NODE
		} else if (xmlNode.childNodes[i].nodeType == 12) { 	// NOTATION_NODE
		}
	}
}

function appendAttribute(el, name, value) {

	// css class
	if (name == 'class') {
		el.className = value;
		
	// css styles
	} else if (name == 'style') {
		while (value.search('; ') > -1) value = value.replace('; ', ';');
		var array = value.split(';');
		var styles = [];
		while (array.length > 0) styles.push(array.shift().split(':'));
		for (var key in styles) if (styles[key].length > 1) el.style[styles[key][0]] = styles[key][1];
	
	
	// event listeners (onclick)
	} else if (name.toLowerCase() == 'onclick') {
		el.setAttribute('onClickFunction', value);
		el.onclick = function() {
			// evaluate function string
			var str = this.getAttribute('onClickFunction');
			if (str.indexOf(':') > -1) str = str.substring(str.indexOf(':') + 1);
			eval(str);
		}
		
	// event listeners (onkeyup)
	} else if (name.toLowerCase() == 'onkeyup') {
		el.setAttribute('onKeyUpFunction', value);
		el.onkeyup = function() {
			// evaluate function string
			var str = this.getAttribute('onKeyUpFunction');
			if (str.indexOf(':') > -1) str = str.substring(str.indexOf(':') + 1);
			eval(str);
		}
		
	// event listeners (onkeypress)
	} else if (name.toLowerCase() == 'onkeypress') {
		el.setAttribute('onKeyPressFunction', value);
		el.onkeyup = function() {
			// evaluate function string
			var str = this.getAttribute('onKeyPressFunction');
			if (str.indexOf(':') > -1) str = str.substring(str.indexOf(':') + 1);
			eval(str);
		}
		
	// event listeners (onmouseover)
	} else if (name.toLowerCase() == 'onmouseover') {
		el.setAttribute('onMouseOverFunction', value);
		el.onmouseover = function() {
			// evaluate function string
			var str = this.getAttribute('onMouseOverFunction');
			if (str.indexOf(':') > -1) str = str.substring(str.indexOf(':') + 1);
			eval(str);
		}
		
	// event listeners (onmouseout)
	} else if (name.toLowerCase() == 'onmouseout') {
		el.setAttribute('onMouseOutFunction', value);
		el.onmouseout = function() {
			// evaluate function string
			var str = this.getAttribute('onMouseOutFunction');
			if (str.indexOf(':') > -1) str = str.substring(str.indexOf(':') + 1);
			eval(str);
		}

	// other
	} else {
		el.setAttribute(name, value);
	}

}

function performFunctionFromString(string) {
					
		// e.g. attributeValue = javascript:updateCalendarDetail('!domID!', !totalEl!, 'calendardetail', '!functionString!');

		// evaluate function string
		if (string.indexOf(':') > -1) functionString = string.substring(string.indexOf(':') + 1);
		else functionString = string;
		eval(functionString);
}

function html_entity_decode(string) {
  while (string.indexOf("&gt;") > -1) string = string.replace("&gt;",">");
  while (string.indexOf("&lt;") > -1) string = string.replace("&lt;","<");
  while (string.indexOf("&amp;") > -1) string = string.replace("&amp;","&");
  while (string.indexOf("&quot;") > -1) string = string.replace("&quot;","\"");
  //string = string.replace("&gt;",">");
  //string = string.replace("&lt;","<");
  //string = string.replace("&amp;","&");
  //string = string.replace("&quot;","\"");
  return string;
}

function cleanString(string) {
	while (string.indexOf("\n") > -1) string = string.replace("\n", "");
	while (string.indexOf("\r") > -1) string = string.replace("\r", "");
	while (string.indexOf("\t") > -1) string = string.replace("\t", "");
	return string;
}
