﻿/* 
================================================

Author: Ayoosh Joshi.
Creation Date: 15th March 2009.
Purpose: Common Browser functionality Library.
Copyright ©: QuadLabs Technologies Ltd. All Rights Reserved.

================================================
*/


/************************/
/*** Browser Sniffer ***/

function BrowserSniffer()
{
	function GetUserAgent()
	{
		// IE: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
		// FF: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5
		// OP: Opera/9.63 (Windows NT 5.1; U; en) Presto/2.1.1
		// SF: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16
		// CR: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.53 Safari/525.19,
		var ua = navigator.userAgent;
		return ua.toLowerCase();
	}

	this.GetBrowserType = function()
	{
	  //debugger
		var retVal = null;
		if (window.ActiveXObject)	// Internet Explorer
			retVal = "ie";
		else if (document.implementation && document.implementation.createDocument)	// FF/CR/SF/OP
		{
			retVal = (GetUserAgent().indexOf("webkit") > -1) ? "cr" : "ff";
		}
//		else if (window.ActiveXObject)	// Internet Explorer
//			retVal = "ie";
		else if (document.layers) // NetScape
			retVal = "ns";
		else
			retVal = null;
			
		return retVal;
	}
}
	


/***********************/
/*** Element related ***/
/*** Class DOM ***/

function DOM()
{
	// bType property.
	var bType;
	
	// Constructor Logic.
	bType = new BrowserSniffer().GetBrowserType();

	
	this.$ = function(elementIDs)
	{
		var el;
		
		// If an array of element names is passed.
		if (arguments.length > 1) 
		{
			var elements = [];
			var length = arguments.length;
			for (var i = 0; i < length; i++)
			{
				// Call this function recursively for each passed parameter.
				elements.push(this.$(arguments[i]));
			}
			return elements;
		}
		
		// If a single element name is passed.
		if (isString(elementIDs))
		{
			el = document.getElementById(elementIDs);
		}
		
		// If the element was not found, try replacing the '$' with '_' and searching.
		if ((!ObjectExists(el)) && (bType != "ie"))
		{
			el = elementIDs.replace(/[\$]/g, '_');
			el = document.getElementById(elementIDs);
		}
		return el;
	}
	
	this.$Name = function(elementNames, tagName)
	{
		var el;
		
		// If an array of element names is passed.
		if (arguments.length > 1) 
		{
			var elements = [];
			var length = arguments.length;
			for (var i = 0; i < length; i++)
			{
				// Call this function recursively for each passed parameter.
				elements.push(this.$Name(arguments[i]));
			}
			return elements;
		}
		
		// If a single element name is passed.
		if (isString(elementNames))
		{
			el = document.getElementsByName(elementNames);
		}
		
		// If the element still was not found.
		if ((el.length == 0) && (bType == "ie"))
		{
			var names = getElementNameWithSeparator(elementNames, false, "_");
			el = document.getElementsByName(names);
		}
		
		return el;
	}

	// Retreive an element's innertext.
	this.GetElementInnerText = function(elementName)
	{
		var value = null;
		var element = (isString(elementName)) ? this.$(elementName) : elementName;
		if (ObjectExists(element))
		{
			
			switch(bType)
			{
				case "ie":
					value = element.innerText;
					break;
				default:
					value = element.textContent;
					break;
			}
		}
		return value;
	}

	// Set an element's innertext.
	this.SetElementInnerText = function(elementName, text)
	{
		var value = null;
		var element = (isString(elementName)) ? this.$(elementName) : elementName;
		if (ObjectExists(element) && isString(text))
		{
			switch(bType)
			{
				case "ie":
					element.innerText = text;
					break;
				default:
					element.textContent = text;
					break;
			}
		}
		return value;
	}


	this.InsertTableRow = function(htmlTable, index)
	{
		var newRow = null;
		var table = (isString(htmlTable)) ? this.$(htmlTable) : htmlTable;
		index = (isNumber(index)) ? index : table.rows.length;
		
		if (ObjectExists(table))
		{
			switch(bType)
			{
				case "ie":
					newRow = table.insertRow(index);
					break;
				default:
					newRow = table.insertRow(index);
					break;
			}
		}
		return newRow;
	}


	this.InsertTableCell = function(htmlTableRow, index)
	{
		var newCell;
		var tableRow = (isString(htmlTableRow)) ? this.$(htmlTableRow) : htmlTableRow;
		index = (isNumber(index)) ? index : tableRow.cells.length;
		
		if (ObjectExists(tableRow))
		{
			switch(bType)
			{
				case "ie":
					newCell = tableRow.insertCell(index);
					break;
				default:
					newCell = tableRow.insertCell(index);
					break;
			}
		}
		return newCell;
	}

	
	this.FindPosition = function(element)
	{
		var currLeft = currTop = 0;
		if(element.offsetParent)
		{
			do 
			{
				currLeft += element.offsetLeft;
				currTop += element.offsetTop;
				if(!element.offsetParent)
					break;
	      
			} while (element = element.offsetParent)
		}
		else if(element.x)
		{
			currLeft += element.x;
			currTop += element.y;
		}
		return {"left" : currLeft, "top" : currTop};
	}	

}



/*********************/
/*** Event related ***/

function DOMEvents()
{
	// bType property.
	var bType;
	
	// Constructor Logic.
	bType = new BrowserSniffer().GetBrowserType();

	// Retrieve a reference to the current event raised in the Window.
	this.GetRaisedEvent = function(e)
	{
		var evt = (window.event) ? event : e;
		if (!evt)
			evt = window.event;
		
		return evt;
	}
}


/*******************/
/*** XML Related ***/

function XML()
{
	// bType property.
	var bType;
	var that = this;
	
	// Constructor Logic.
	bType = new BrowserSniffer().GetBrowserType();
	
	this.HasXML = function(xmlDocument)
	{
		if (ObjectExists(xmlDocument))
		{
			var hasXml = false;
			switch(bType)
			{
				case "ie":
					hasXml = (xmlDocument.xml != "") ? true : false;
					break;
				default:
					var docEl = GetDocumentElement(xmlDocument);
					hasXml = ((docEl != null) && (docEl.childNodes.length > 0) && (docEl.textContent != "")) ? true : false;
					break;		
			}
			return hasXml;
		}
		else
			return false;
	}
	
	
	this.GetXML = function(xmlDocument)
	{
		if (ObjectExists(xmlDocument))
		{
			var xml;
			switch(bType)
			{
				case "ie":
					xml = xmlDocument.xml;
					break;
				default:
					var xs = new XMLSerializer();
					xml = xs.serializeToString(xmlDocument);
					break;
			}
			return xml;
		}
		else
			return "";
	}

	
	this.LoadXMLString = function(xmlString)
	{
		if (ObjectExists(xmlString) && isString(xmlString))
		{
			var xDoc;
			switch(bType)
			{
				case "ie":
					xDoc =  GetMSDOMDocument("DOMDocument");
					xDoc.async = false;
					SetDocumentProperties(xDoc, "SelectionLanguage", "XPath");
					SetDocumentProperties(xDoc, "NewParser", true);
					SetDocumentProperties(xDoc, "ValidateOnParse", false);
					xDoc.loadXML(xmlString);
					break;
				default:
					var dp = new DOMParser();
					xDoc = dp.parseFromString(xmlString, "text/xml");
					break;
			}
			return xDoc;
		}
		else
			return null;
	}

	// Retrieve an XMLDocument object.
	this.LoadXMLFile = function(filePath)
	{
		if (ObjectExists(filePath) && isString(filePath))
		{
			var xDoc = null;
			switch(bType)
			{
				case "ie": // IE
					xDoc = GetMSDOMDocument("DOMDocument");
					xDoc.async = false;
					SetDocumentProperties(xDoc, "SelectionLanguage", "XPath");
					SetDocumentProperties(xDoc, "NewParser", true);
					SetDocumentProperties(xDoc, "ValidateOnParse", false);
					xDoc.load(filePath);	
					break;
				case "cr": // Google Chrome
					var xmlHttp = new window.XMLHttpRequest();
					xmlHttp.open("GET", filePath, false);
					xmlHttp.send(null);
					xDoc = xmlHttp.responseXML.documentElement;
					break;
				default:  // FF and compliant browsers
					xDoc = document.implementation.createDocument("", "", null);
					xDoc.async = false;
					xDoc.load(filePath)
					break;
			}
			return xDoc;
		}
		else
			return null;
	}
	
	this.AppendNode = function(xmlNode, node)
	{
		if (ObjectExists(xmlNode) && ObjectExists(node))
		{
			switch(bType)
			{
				case "cr":
					var xDoc = GetOwnerDocument(xmlNode)
					var nodeToImport = xDoc.importNode(node, true);
					xmlNode.appendChild(nodeToImport);
					break;
				default:
					xmlNode.appendChild(node);
					break;
			}
		}
	} 
	
	function SetDocumentProperties(document, propertyName, propertyValue)
	{
		try
		{
			if ((propertyName in document) || (document.getProperty(propertyName) != "undefined"))
				document.setProperty(propertyName, propertyValue);
		}
		catch(ex)
		{
			// Do nothing.
		}
	}

	// Retrieves an XML document based on the version of MSXML installed.
	function GetMSDOMDocument(docType)
	{
		var xmlDoc = null;
		try {
			if (xmlDoc = new ActiveXObject("MSXML2." + docType + ".6.0"))						//ver 6
				return xmlDoc;
		}
		catch(e) {
			try {
				if (xmlDoc = new ActiveXObject("MSXML2." + docType + ".5.0"))					//ver 5
					return xmlDoc;
			}
			catch(e) {
				try {
					if (xmlDoc = new ActiveXObject("MSXML2." + docType + ".3.0"))				//ver 3
						return xmlDoc;
				}
				catch(e) {
					try {
						if (xmlDoc = new ActiveXObject("MSXML2." + docType + ".4.0"))			//ver 4
							return xmlDoc;
					}
					catch(e) {
						try {
							if (xmlDoc = new ActiveXObject("MSXML2." + docType))						//ver 3
								return xmlDoc;
						}
						catch(e) {
							try {
								if (xmlDoc = new ActiveXObject("MSXML." + docType))						//ver 2.x
									return xmlDoc;
							}
							catch(e) {
								switch (docType)
								{
									case "DOMDocument":
										if (xmlDoc = new ActiveXObject("Microsoft.XMLDOM"))				//ver 2
											return xmlDoc;
										break;
									case "XSLTemplate":
										if (xmlDoc = new ActiveXObject("Microsoft.XSLTemplate"))	//ver 2
											return xmlDoc;
										break;
								}
							}
						}
					}
				}
			}
		}
	}
	
	/*** END XML Related ***/
	
	/*** XPath Related ***/
	
	this.SelectNodeValue = function(xmlDocument, xPathString)
	{
		if (ObjectExists(xmlDocument) && isString(xPathString))
		{
			var node, value;
			switch(bType)
			{
				case "ie":
					node = xmlDocument.documentElement.selectSingleNode(xPathString);
					value = (node != null) ? node.text : null;
					break;
				default:
					var xpe = new XPathEvaluator();
					var docEl = GetDocumentElement(xmlDocument);
					var nsResolver = xpe.createNSResolver(docEl);
					var results = xpe.evaluate(xPathString, docEl, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null);		
					node = results.singleNodeValue;
					value = (node != null) ? node.textContent : null;
					break;
			}
			return value;
		}
		else
			return null;
	}
	
	
	this.SelectNode = function(xmlDocument, xPathString)
	{
		if (ObjectExists(xmlDocument) && isString(xPathString))
		{
			var node, value;
			switch(bType)
			{
				case "ie":
					node = xmlDocument.documentElement.selectSingleNode(xPathString);
					break;
				default:
					var xpe = new XPathEvaluator();
					var docEl = GetDocumentElement(xmlDocument);
					var nsResolver = xpe.createNSResolver(docEl);
					var results = xpe.evaluate(xPathString, docEl, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null);		
					node = results.singleNodeValue;
					break;
			}
			return node;
		}
		else
			return null;
	}
	
	
	this.SelectNodes = function(xmlDocument, xPathString, xPathResultType)
	{
		if (ObjectExists(xmlDocument) && isString(xPathString))
		{
			var nodeSet;

			switch(bType)
			{
				case "ie":
					nodeSet = xmlDocument.documentElement.selectNodes(xPathString)
					break;
				default:
					if (!ObjectExists(xPathResultType))
					{
						xPathResultType = XPathResult.ANY_TYPE;
					}
					var xpe = new XPathEvaluator();
					var docEl = GetDocumentElement(xmlDocument);
					var nsResolver = xpe.createNSResolver(docEl);
					nodeSet = xpe.evaluate(xPathString, docEl, nsResolver, xPathResultType, null);
					break;
			}
			return nodeSet;
		}
		else
			return null;
	}
	
	
	function GetDocumentElement(xmlDocument)
	{
		if (ObjectExists(xmlDocument))
		{
			if (ObjectExists(xmlDocument.documentElement))
				return xmlDocument.documentElement;
			else
				return xmlDocument.ownerDocument.documentElement;
		}
		else
			return null;
	}
	
	
	function GetOwnerDocument(xmlNode)
	{
		if (ObjectExists(xmlNode))
		{
			if (ObjectExists(xmlNode.documentElement))
				return xmlNode;
			else
				return xmlNode.ownerDocument;
		}
		else
			return null;
	}
	
	
	this.GetNodeCount = function(xmlDocument, xPathString)
	{
		if (ObjectExists(xmlDocument) && isString(xPathString))
		{
			var len;
			var nodeSet;
			switch(bType)
			{
				case "ie":
					nodeSet = this.SelectNodes(xmlDocument, xPathString);
					len = (nodeSet != null) ? nodeSet.length : null;
					break;
				default:
					nodeSet = this.SelectNodes(xmlDocument, xPathString, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE);
					len = (nodeSet != null) ? nodeSet.snapshotLength : null;		
					break;
			}
			return len;
		}
		else
			return null;
	}
	
	
	this.GetNodeValue = function(nodeSet, nodeIndex)
	{
		var thisNode = this.GetNode(nodeSet, nodeIndex);
		var value = null;
		if (ObjectExists(nodeSet) && isNumber(nodeIndex))
		{
			switch(bType)
			{
				case "ie":
					value = (thisNode != null) ? thisNode.text : "";
					break;
				default:
					value = (thisNode != null) ? thisNode.textContent : "";
					break;
			}
		}
		return value;
	}
	
	this.SetNodeValue = function(xmlNode, value)
	{
		if (ObjectExists(xmlNode) && isString(value))
		{
			switch(bType)
			{
				case "ie":
					xmlNode.text = value;
					break;
				default:
					xmlNode.textContent = value;
					break;
			}
			return true;
		}
		else
			return false;
	}
	
	this.GetNodeSetCount = function(nodeSet)
	{
		if (ObjectExists(nodeSet))
		{
			var len;
			switch(bType)
			{
				case "ie":
					len = nodeSet.length;
					break;
				default:
					len = (nodeSet.resultType == 6) ? nodeSet.snapshotLength : CountNodes(nodeSet);
					break;
			}
			return len;
		}
		else
			return 0;
	}
	
	function CountNodes(nodeSet)
	{
		var ctr = 0;
		while (nodeSet.iterateNext() != null)
		{
			ctr++;
		}
		return ctr;
	}
	
	this.GetNode = function(nodeSet, nodeIndex)
	{
		var node = null;
		if (ObjectExists(nodeSet) && isNumber(nodeIndex))
		{
			switch(bType)
			{
				case "ie":
					node = (nodeSet[nodeIndex] != null) ? nodeSet[nodeIndex] : null;
					break;
				default:
					if (nodeSet.resultType == 6)
						node = (nodeSet.snapshotItem(nodeIndex) != null) ? nodeSet.snapshotItem(nodeIndex) : null;
					else if (nodeSet.resultType == 4)
						node = nodeSet.iterateNext();
					break;
			}
		}
		return node;
	}
	
	/*** END XPath Related ***/
	
	/*** XSLT Related ***/
	
	function GetXSLTProcessor(xslFilePath)
	{
	//debugger
		var proc = null;
		var xDoc = null;
		switch(bType)
		{
			case "ie":
				var xslt = GetMSDOMDocument("XSLTemplate");
				var xslDoc = GetMSDOMDocument("FreeThreadedDOMDocument");
				xslDoc.async = false;	
				xslDoc.resolveExternals = true;
				SetDocumentProperties(xslDoc, "AllowXsltScript", true);
				xslDoc.load(xslFilePath);

				xslt.stylesheet = xslDoc;
				proc = xslt.createProcessor();
				break;
			default:
				var xslDoc = that.LoadXMLFile(xslFilePath);
				proc = new XSLTProcessor();
				proc.importStylesheet(xslDoc);
				break;
		}
		return proc;
	}
	
	this.XSLTransform = function(xmlFilePath, xslFilePath, outputMethod)
	{
		var inputXmlDoc;
		
		// Only load the XML into an XmlDocument if a string has been provided.
		if (isString(xmlFilePath))
		{
			inputXmlDoc = this.LoadXMLFile(xmlFilePath);
		}
		else
		{
			inputXmlDoc = xmlFilePath;
		}
		var proc = GetXSLTProcessor(xslFilePath, bType);

		if (params.length > 0)
		{
			paramArray = XSLParamArray.apply({}, params);
		}

		if ((ObjectExists(paramArray)) && (paramArray.length > 0))
		{
			for (var i in paramArray.items)
			{
				if (bType == "ie")
					proc.addParameter(i, paramArray.items[i]);
				else
					proc.setParameter(null, i, paramArray.items[i]);
			}
			
			// Clear the paramArray object.
			paramArray = null;
			params = [];
		}
		var op;
		if (bType == "ie")
		{
			proc.input = inputXmlDoc;
			proc.transform();
			while (proc.readyState != 4) {};
			op = proc.output;
		}
		else
		{
			if (outputMethod == "html")
			{
				var ownerDoc = document.implementation.createDocument("", "", null);
				//var frag1 = proc.transformToFragment(inputXmlDoc, document);
				var frag = proc.transformToFragment(inputXmlDoc, ownerDoc);
				var xs = new XMLSerializer();
				op = xs.serializeToString(frag);
			}
			else if (outputMethod == "xml")
			{
				var xDoc = proc.transformToDocument(inputXmlDoc);
				var xs = new XMLSerializer();
				op = xs.serializeToString(xDoc);
			}
		}
		return op;		
	}
	
	var params = new Array();
	var paramArray = null;
	
	this.AddParameter = function(paramName, paramValue)
	{
		params.push(paramName);
		params.push(paramValue);
	}
	
	
	this.AddParameterArray = function()
	{
		paramArray = XSLParamArray.apply({}, arguments);
	}
	
	this.GetParameters = function()
	{
		return XSLParamArray.apply({}, params);
	}
	
	function XSLParamArray()
	{
		// Length property.
		this.length = 0;
		// Items property.
		this.items = new Array();
		//var args = Array.prototype.slice.call(arguments);
		
		// Constructor logic (fill items and set length)
		for (var i = 0; i < arguments.length; i += 2)
		{
			if (typeof(arguments[i + 1]) != "undefined") 
			{
				this.items[arguments[i]] = arguments[i + 1];
				this.length++;
			}
		}
		return this;
	}
	
	/*** END XSLT Related ***/
	
}

/********************/
/*** AJAX Related ***/

function Ajax()
{
}	
	// Retrieve the XMLHTTP object.
Ajax.prototype.GetXmlHttpObject = function()
{
	var ajax = null;
	if (window.XMLHttpRequest)
	{
		// If IE7, Mozilla, Safari, and so on: Use native object
		ajax = new XMLHttpRequest();
	}
	else
	{
		if (window.ActiveXObject)
		{
			 // ...otherwise, use the ActiveX control for IE5.x and IE6
			 ajax = new ActiveXObject('MSXML2.XMLHTTP.3.0');
		}
	}
	return ajax;
}


// Retrieves the Response Text from within a passed XmlHttp object.
Ajax.prototype.GetResponseText = function(xmlHttp)
{
	var responseTxt = "";
	var bType = new BrowserSniffer().GetBrowserType();
	switch(bType)
	{
		case "ie":
			responseTxt = xmlHttp.responseXML.lastChild.text;
			break;
		default:
			responseTxt = xmlHttp.responseXML.lastChild.textContent;
			break;
	}
	return responseTxt;
}


function ObjectExists(obj)
{
	if (obj == null)
		return false;
	else
	{
		if (typeof(obj) == "undefined")
			return false;
		else
			//if (obj == "")
				//return false;
			//else
				return true;
	}
}

function isFunction(obj) 
{
	return (typeof(obj) == "function");
}

function isString(obj) 
{
	return (typeof(obj) == "string");
}

function isNumber(obj) 
{
	return (typeof(obj) == "number");
}

