var TextUtil = new Object();
var EventUtil = new Object;

var sUserAgent = navigator.userAgent;
var fAppVersion = parseFloat(navigator.appVersion);

// specify the (columnar) locations for each input parameter
var doclinkAt = 0;
var vinminAt = 1;
var vinmaxAt = 2;
var noofoutputsAt = 3;
var vout1At = 4;
var vout2At = 5;
var vout3At = 6;
var vout4At = 7;
var vout5At = 8;
var vout6At = 9;
var totpowerAt = 10;
var topologyAt = 11;
var productfamilyAt = 12;
var productAt = 13;
var schematicAt = 14;
var rdklinkAt = 15;
var gerberAt = 16;
var isolatedAt = 17;
var cvccAt = 18;

var bisolated = false;
var bcvcc = false;
var bvinmin = false;
var bvinmax = false;
var bnoofoutputs = false;
var bvout1 = false;
var bvout2 = false;
var bvout3 = false;
var bvout4 = false;
var bvout5 = false;
var bvout6 = false;
var btotpower = false;
var btopology = false;
var bproductfamily = false;

var vinminlow = 0;
var vinmaxlow = 0;
var vout1low = 0;
var vout2low = 0;
var vout3low = 0;
var vout4low = 0;
var vout5low = 0;
var vout6low = 0;
var totpowerlow = 0;

var vinminhigh = 0;
var vinmaxhigh = 0;
var vout1high = 0;
var vout2high = 0;
var vout3high = 0;
var vout4high = 0;
var vout5high = 0;
var vout6high = 0;
var totpowerhigh = 0;


//baseURI this is used for specifying the correct path for all the files available for download
//var baseURI = "http://www.powerint.com/";
var baseURI = "/sites/default/files/";

//XML file name that we were called with
var xml_file = "";

//there are 6 rows on top that do not have the data; the next row is where the data starts
var dataStartsAt = 7;

//this flag allows us to code things so that every other row will be shaded
var shaded = false;

//import the data from the xml file
function importXML(fn)
{

	xml_file = fn;
	
	if (document.implementation && document.implementation.createDocument)
	{
		xmlDoc = document.implementation.createDocument("", "", null);
		xmlDoc.onload = createTable;
	}
	else if (window.ActiveXObject)
	{
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.onreadystatechange = function () {if (xmlDoc.readyState == 4) createTable()};
 	}
	else
	{
		alert('Your browser can\'t handle this script');
		return;
	}

	// delete the table if it exists
	var table = document.getElementById('tablehead');
	//total number of rows in the table
	var iRows = (table.rows.length - 1);	

	//for each row
	for (i=iRows; i >= dataStartsAt; i--) {
			table.deleteRow(i);
	}
	

	xmlDoc.load(fn);
	
}



//create the table that will be inserted into the document
function createTable()
{

	//set this so that the rows are properly shaded
	shaded = false;

	//these are used to control display of message indicating no matches found
	//hide the message for now
	document.getElementById('loading').style.display="block";
	document.getElementById('nothing').style.display="none";	
	var matches = 0;
	
	var x = xmlDoc.getElementsByTagName('PIItems');
	var iCols = x[0].childNodes.length;
	//number of data rows
	var iRows = x.length;
	var tmp = document.getElementById('tablehead_tbody');
	for (i=0;i<x.length;i++) 
	{
		if (!(bisolated || bcvcc || bvinmin || bvinmax || bvout1 || bvout2 ||  bvout3 || bvout4 || bvout5 || bvout6 ||btotpower || bnoofoutputs || btopology || bproductfamily)) {
			tmp.appendChild(addRow(x[i]));
		}
		else {
			if (fullFilterX(x[i])) {
				tmp.appendChild(addRow(x[i]));
				matches++;
			}
		}
	}

	//if any search criteria was specified and no matches found, display message
	document.getElementById('loading').style.display="none";
	if (bisolated || bcvcc || bvinmin || bvinmax || bvout1 || bvout2 ||  bvout3 || bvout4 || bvout5 || bvout6 ||btotpower || bnoofoutputs || btopology || bproductfamily) {
		if (matches == 0) {
			document.getElementById('nothing').style.display="block";	
		}
	}	
}


function addRow(x) 
{

	//create a row
	var row = document.createElement('TR');
	//specify the class name for the row
	if (shaded) {
		row.className = 'texttablerow_shaded';
		shaded = false;
	}
	else {
		row.className = 'texttablerow';
		shaded = true;
	}
	for (j=0;j<x.childNodes.length;j++)
	{
		if (x.childNodes[j].nodeType != 1) continue;
		//add a cell
		var container = document.createElement('td');
		//if there is a value for tha tcell
		if (x.childNodes[j].firstChild != null) {
			var val1 = x.childNodes[j].firstChild.nodeValue;
			switch (j) {
				case productfamilyAt: {
					//productFamily contains the link to the downloadable .pdf file
					//if it is an image, then the cell should be centred
					container.setAttribute("align", "center");
					var theData = document.createElement('a');

					var temp_001 = val1.indexOf('~') + 1;
					var temp_002 = val1.substring(temp_001);
					var temp_003 = val1.substring(0, (temp_001 - 1));
					theData.href = baseURI + temp_002;
					theData.setAttribute("target", "_blank");
					var tn1 = document.createTextNode(temp_003);
					theData.appendChild(tn1);
						}
					break;
				case schematicAt: {
					//schematic column contains the link to the downloadable schematic file
					container.setAttribute("align", "center");
					var theData = document.createElement('a');
					theData.href = baseURI + val1;
					theData.setAttribute("target", "_blank");
					var tn = document.createElement("img");
					tn.setAttribute("src", "/sites/all/themes/power_v1/img/icons/schematic.gif");
					//tn.setAttribute("style", "border:none;");
					tn.setAttribute("border", "0");
					theData.appendChild(tn);
					}
					break;
				case doclinkAt: {
					//doclink contains the link to the downloadable .pdf file
					//container.setAttribute("align", "center");

					var bcec = false;
					if (val1.substring(val1.length - 1) == 'Y') {
						bcec = true;
					}
					
					//Strip the "/Y" or "/N" of the end first
					val1 = val1.substring(0, val1.length - 2);
					var theData = document.createElement('a');
					theData.href = baseURI + val1;
					// added this to make the docs open in new windows - ckw
					theData.setAttribute("target", "_blank");
					
					//search for the last "/" in the string
					var startAt = val1.lastIndexOf('/') + 1;
					//search for the . - the .pdf - in the string
					var endAt = val1.lastIndexOf('.');
					//we need everything in between that, except...
					var useMe = val1.substring(startAt, endAt);
					//alert(useMe);
					//strip the "CN" off of the name if it's there
					if (useMe.substring(useMe.length-2) == "CN") {
						useMe = useMe.substring(0, useMe.length-2);
					}

					//find the first digit
					for (s=0; s < useMe.length;s++)
						{
							//find the first digit in the string
							if (!(isNaN(parseInt(useMe.substring(s, (s + 1)))))) {
								break;
							}
						}
					useMe = useMe.substring(0, s).toUpperCase() + '-' + useMe.substring(s);
					var tn = document.createTextNode(useMe);
					theData.appendChild(tn);

					if (bcec) {
						var tn1a = document.createElement('br');
						theData.appendChild(tn1a);
						var tn2 = document.createElement("img");
						tn2.setAttribute("src", "/sites/all/themes/power_v1/img/icons/cec.gif");
						tn2.setAttribute("style", "border:none;");
						tn2.setAttribute("border", "0");
						theData.appendChild(tn2);
					}

					}
					break;
				case rdklinkAt: {
						if (val1.length > 1) {  // there's always at least a " " in the tag
							// set the url
							var theData = document.createElement('a');
							theData.href = baseURI + val1;
							theData.setAttribute("target", "_blank");
							
							// construct the text for the link
							// grab the first 3 characters after the "#" - either DAK or RDK
							var startAt = val1.indexOf("#") + 1;
							var useMe = val1.substring(startAt, startAt+3).toUpperCase() + '-';
							// get the number that follows and construct the whole string
							useMe = useMe + val1.substring(startAt+3, val1.length);
							var tn = document.createTextNode(useMe);
							theData.appendChild(tn);
						}
						else {
							var theData = document.createTextNode(".");
						}
					}
					break;
				case gerberAt: {
						//gerber contains the link to the downloadable .zip file
						//container.setAttribute("align", "center");
						//if (trim(val1).length > 0) {
						if (val1.replace(/^\s+|\s+$/g,"").length > 0) {
							var theData = document.createElement('a');
							theData.href = baseURI + val1;
							var tn = document.createElement("img");
							tn.setAttribute("src", "/sites/all/themes/power_v1/img/icons/zip.gif");
							//tn.setAttribute("style", "border:none;");
							tn.setAttribute("border", "0");
							theData.appendChild(tn);
						}
						else {
							var theData = document.createTextNode(".");
						}
					}
					break;
				default: {
						//else add it as a regular text node
						if (val1.replace(/^\s+|\s+$/g,"").length > 0) {
							var theData = document.createTextNode(val1);
						}
						else {
							var theData = document.createTextNode(".");
						}
						//alert(j + ', ' + theData);
					}
					break;
			}
		}
		else {
			//the data is null, just create a cell with no data
			var theData = document.createTextNode(".");
		}
		//append the data
		container.appendChild(theData);
		//append the cell
		row.appendChild(container);
	}
	//append the row
	//tmp.appendChild(row);
	return row;
}





var VInMin = -1000;
var VInMax = 1000;
var VOut1Min = VOut2Min = VOut3Min = VOut4Min = VOut5Min = VOut6Min = -1000;
var VOut1Max = VOut2Max = VOut3Max = VOut4Max = VOut5Max = VOut6Max = 1000;
var TotPowerMin = 0;
var TotPowerMax = 1000;

function checkLimits(oTextbox) {

	/** bisolated = false;
	bcvcc = false;
	bvinmin = false;
	bvinmax = false;
	bnoofoutputs = false;
	bvout1 = false;
	bvout2 = false;
	bvout3 = false;
	bvout4 = false;
	bvout5 = false;
	bvout6 = false;
	btotpower = false;
	btopology = false;
	bproductfamily = false; **/


	switch (oTextbox.name) {
		case "rbIsolated": {
			if ((document.formname1.rbIsolated[0].checked) || (document.formname1.rbIsolated[1].checked) || (document.formname1.rbIsolated[2].checked)) {
					bisolated = true;
				}
			}
			break;
		case "rbCVCC": {
			if ((document.formname1.rbCVCC[0].checked) || (document.formname1.rbCVCC[1].checked) || (document.formname1.rbCVCC[2].checked)) {
					bcvcc = true;
				}
			}
			break;
		case "tbVInMin": {
				//if we have a number
				bvinmin = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						/** if (Number(oTextbox.value) < VInMin) {
							Number(oTextbox.value) = VInMin;
						}
						if (Number(oTextbox.value) > VInMax) {
							Number(oTextbox.value) = VInMax;
						} **/
						bvinmin = true;
						// Initial implementation had these backwards - ckw
						// vinminlow = Math.abs(Number(oTextbox.value) * 0.95);
						// vinminhigh = VInMax;
						
						// Choose everything below, plus those 5% above - ckw
						vinminlow = VInMin;
						vinminhigh = Math.abs(Number(oTextbox.value) * 1.05);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "tbVInMax": {
				//if we have a number
				bvinmax = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						bvinmax = true;
						// Initial implementation had these backwards - ckw
						// vinmaxlow = 0;
						// vinmaxhigh = Math.abs(Number(oTextbox.value) * 1.05);
						
						// Choose everything below, plus those 5% above - ckw
						vinmaxlow = Math.abs(Number(oTextbox.value) * 0.95);
						vinmaxhigh = VInMax;
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "lstNoOfOutputs": {
				bnoofoutputs = true;
			};
			break;
		case "tbVOut1": {
				//if we have a number
				bvout1 = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						bvout1 = true;
						vout1low = Math.abs(Number(oTextbox.value) * 0.9);
						vout1high = Math.abs(Number(oTextbox.value) * 1.1);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "tbVOut2": {
				//if we have a number
				bvout2 = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						bvout2 = true;
						vout2low = Math.abs(Number(oTextbox.value) * 0.9);
						vout2high = Math.abs(Number(oTextbox.value) * 1.1);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "tbVOut3": {
				//if we have a number
				bvout3 = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						bvout3 = true;
						vout3low = Math.abs(Number(oTextbox.value) * 0.9);
						vout3high = Math.abs(Number(oTextbox.value) * 1.1);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "tbVOut4": {
				//if we have a number
				bvout4 = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						bvout4 = true;
						vout4low = Math.abs(Number(oTextbox.value) * 0.9);
						vout4high = Math.abs(Number(oTextbox.value) * 1.1);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "tbVOut5": {
				//if we have a number
				bvout5 = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						bvout5 = true;
						vout5low = Math.abs(Number(oTextbox.value) * 0.9);
						vout5high = Math.abs(Number(oTextbox.value) * 1.1);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "tbVOut6": {
				//if we have a number
				bvout6 = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						bvout6 = true;
						vout6low = Math.abs(Number(oTextbox.value) * 0.9);
						vout6high = Math.abs(Number(oTextbox.value) * 1.1);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "tbTotPower": {
				//if we have a number
				btotpower = false;
				if (!isNaN(oTextbox.value)) {
					if (Number(oTextbox.value) != 0) {
						btotpower = true;
						totpowerlow = Math.abs(Number(oTextbox.value) * 0.9);
						totpowerhigh = Math.abs(Number(oTextbox.value) * 1.5);
					}
				}
				else {
					alert("Please enter a numerical value.");
					oTextbox.value = '';
				}
			};
			break;
		case "lstTopology": {
				btopology = true;
			};
			break;
		case "lstProductFamily": {
				bproductfamily = true;
			};
			break;
	}

	importXML(xml_file);
	
}







//this function filters out the rows in the table
//get the input text box for which this function is called
//find the (columnar) position of that input text box
//now follow the logic to delete the rows
function fullFilterX(x) {

	var	bKeep1 = true;
	var	bKeep2 = true;
	var	bKeep3 = true;
	var temp_001 = 0;
	
	
	// to filter the data based on whether the row fits the "Isolated" specification
	//first get the value that we have to compare the row data against
	for (var i=0; i < document.formname1.rbIsolated.length; i++)
	{
		if (document.formname1.rbIsolated[i].checked)
		{
			var rb_isolated = document.formname1.rbIsolated[i].value;
		}
	}


	for (var i=0; i < document.formname1.rbCVCC.length; i++)
	{
		if (document.formname1.rbCVCC[i].checked)
		{
			var rb_cvcc = document.formname1.rbCVCC[i].value;
		}
	}


	var lst_noofoutputs = document.formname1.lstNoOfOutputs.value;
	var lst_productfamily = document.formname1.lstProductFamily.value;
	var lst_topology = document.formname1.lstTopology.value;
	
		
		
	
		//all along that we go, right from the first condition, bKeep1 / 2 / 3 should be true
		// if a condition is not met, then it is immediately set to false
		// bKeep2 is somewhat different, because it is implemented as an "OR" condition
		
		// if we have to filter the data based on whether the row fits the "Isolated" specification
		if ((bisolated) && (rb_isolated != 'B')) {
			// the row data should not be null
			if (x.childNodes[isolatedAt].firstChild.nodeValue != null) {
				// if the value matches, then keep the row
				if (x.childNodes[isolatedAt].firstChild.nodeValue != rb_isolated) {
					bKeep1 = false;
				}
			}
		}


		if (bcvcc) {
			// the row data should not be null
			if (x.childNodes[cvccAt].firstChild.nodeValue != null) {
				// if the value matches, then keep the row
				if (x.childNodes[cvccAt].firstChild.nodeValue != rb_cvcc) {
					bKeep1 = false;
				}
			}
		}


		// check if the input specs fit the range
		if (bKeep1 && bvinmin) {
			temp_001 = Math.abs(Number(x.childNodes[vinminAt].firstChild.nodeValue));
			if (!((temp_001 >= vinminlow) && (temp_001 <= vinminhigh))) {
				bKeep1 = false;
			}
		}
		
		if (bKeep1 && bvinmax) {
			temp_001 = Math.abs(Number(x.childNodes[vinmaxAt].firstChild.nodeValue));
			if (!((temp_001 >= vinmaxlow) && (temp_001 <= vinmaxhigh))) {
				bKeep1 = false;
			}
		}
		

		// check if the row needs ot be kept based on the value of no of outputs
		// keep the row if no of outputs is not specified
		if (bKeep1 && (lst_noofoutputs != "")) {
			// keep the row if the value is null - benefit of doubt theory
			if (x.childNodes[noofoutputsAt].firstChild.nodeValue != null) {
				// keep the row if the values match
				if (x.childNodes[noofoutputsAt].firstChild.nodeValue != lst_noofoutputs) {
					// else set the row for deletion
					bKeep1 = false;
				}
			}
		}
		



		if (bKeep1) {

			//check if the output 1 requirement is met by any one of the 6 outputs available
			if (bvout1) {
				bKeep2 = checkVOutX(x, vout1low, vout1high);
			}

			// check if output 2 requirement meets any one of the 6 outputs available -- this should be done only if bKeep1 and bKeep2 is false
			// if either one of them is true, then we do not need to do this since the record has already been selected
			// same for requirement 3, 4, 5, and 6
			if (bvout2 && bKeep2) {
				bKeep2 = checkVOutX(x, vout2low, vout2high);
			}
			if (bvout3 && bKeep2) {
				bKeep2 = checkVOutX(x, vout3low, vout3high);
			}
			if (bvout4 && bKeep2) {
				bKeep2 = checkVOutX(x, vout4low, vout4high);
			}
			if (bvout5 && bKeep2) {
				bKeep2 = checkVOutX(x, vout5low, vout5high);
			}
			if (bvout6 && bKeep2) {
				bKeep2 = checkVOutX(x, vout6low, vout6high);
			}

			if (bKeep2) {
				//if this record was not selected because of either of the previous conditions,
				//then let's check if it will be selected due to power requirements
				if (btotpower) {
					temp_001 = Math.abs(Number(x.childNodes[totpowerAt].firstChild.nodeValue));
					if (!((temp_001 >= totpowerlow) && (temp_001 <= totpowerhigh))) {
						bKeep3 = false;
					}
				}


				// check if the row needs ot be kept based on the value of product family
				if (lst_productfamily != "") {
					if (x.childNodes[productfamilyAt].firstChild.nodeValue != null) {

						var temp_100 = x.childNodes[productfamilyAt].firstChild.nodeValue;
						var temp_101 = temp_100.indexOf('~');
						var temp_102 = temp_100.substring(0, temp_101);
						
						//if (x.childNodes[productfamilyAt].innerText != lst_productfamily) {
						if (temp_102 != lst_productfamily) {
							bKeep3 = false;
						}
					}
				}


				// check if the row needs ot be kept based on the value of topology
				if (lst_topology != "") {
					if (x.childNodes[topologyAt].firstChild.nodeValue != null) {
						if (x.childNodes[topologyAt].firstChild.nodeValue != lst_topology) {
							bKeep3 = false;
						}
					}
				}
			}
		}

	return (bKeep1 && bKeep2 && bKeep3);

}

// check VOutx - if it is within the range
// or if any of the other VOuty is within the range, then we select the row, else delete it
function checkVOutX(x, valLow, valHigh) {

	var inRange = false;
	var temp_002 = 0;
	
	temp_002 = Math.abs(Number(x.childNodes[vout1At].firstChild.nodeValue));
	if ((temp_002 >= valLow) && (temp_002 <= valHigh)) {
		inRange = true;
	}

	temp_002 = Math.abs(Number(x.childNodes[vout2At].firstChild.nodeValue));
	if (!(inRange)) {
		if ((temp_002 >= valLow) && (temp_002 <= valHigh)) {
			inRange = true;
		}
	}

	temp_002 = Math.abs(Number(x.childNodes[vout3At].firstChild.nodeValue));
	if (!(inRange)) {
		if ((temp_002 >= valLow) && (temp_002 <= valHigh)) {
			inRange = true;
		}
	}

	temp_002 = Math.abs(Number(x.childNodes[vout4At].firstChild.nodeValue));
	if (!(inRange)) {
		if ((temp_002 >= valLow) && (temp_002 <= valHigh)) {
			inRange = true;
		}
	}

	temp_002 = Math.abs(Number(x.childNodes[vout5At].firstChild.nodeValue));
	if (!(inRange)) {
		if ((temp_002 >= valLow) && (temp_002 <= valHigh)) {
			inRange = true;
		}
	}

	temp_002 = Math.abs(Number(x.childNodes[vout6At].firstChild.nodeValue));
	if (!(inRange)) {
		if ((temp_002 >= valLow) && (temp_002 <= valHigh)) {
			inRange = true;
		}
	}
	
	return inRange;

}




function trim(stringToTrim) {
	return stringToTrim.replace(/^\s+|\s+$/g,"");
}
function ltrim(stringToTrim) {
	return stringToTrim.replace(/^\s+/,"");
}
function rtrim(stringToTrim) {
	return stringToTrim.replace(/\s+$/,"");
}




//in a text box, block specified characters
TextUtil.blockChars = function (oTextbox, oEvent) {
	oEvent = EventUtil.formatEvent(oEvent);
	var sInvalidChars = oTextbox.getAttribute("invalidchars");
	var sChar = String.fromCharCode(oEvent.charCode);
	var bIsValidChar = sInvalidChars.indexOf(sChar) == -1;
	return bIsValidChar || oEvent.ctrlKey;
};

//in a text box, allow specified characters
TextUtil.allowChars = function (oTextbox, oEvent) {
	//alert(oEvent.isChar + ', ' + oEvent.keyCode + ', ' + oEvent.charCode);
	oEvent = EventUtil.formatEvent(oEvent);
	var sValidChars = oTextbox.getAttribute("validchars");
	if (window.event) { //if we are in IE
		var sChar = String.fromCharCode(oEvent.charCode);
		var bIsValidChar = sValidChars.indexOf(sChar) > -1;
		if (oEvent.keyCode == 13) {
			checkLimits(oTextbox);
			return true;
		}
	}
	else { //firefox deals with this differently
		if (oEvent.keyCode == 0) {
			var sChar = String.fromCharCode(oEvent.charCode);
			var bIsValidChar = sValidChars.indexOf(sChar) > -1;
		}
		else {
			if (oEvent.keyCode == 13) {
				checkLimits(oTextbox);
			}
			var bIsValidChar = true;
		}
	}
	return bIsValidChar || oEvent.ctrlKey;
};

function noNumbers(e) {
	var keynum
	var keychar
	var numcheck

	if(window.event) // IE
	{
	keynum = e.keyCode
	}
	else if(e.which) // Netscape/Firefox/Opera
	{
	keynum = e.which
	}
	keychar = String.fromCharCode(keynum)
	numcheck = /\d/
	return !numcheck.test(keychar)
}

function numbersOnly(e) {
	var keynum
	var keychar
	var numcheck

	if(window.event) // IE
	{
	keynum = e.keyCode
	}
	else if(e.which) // Netscape/Firefox/Opera
	{
	keynum = e.which
	}
	keychar = String.fromCharCode(keynum)
	numcheck = /[0-9]/;
	return numcheck.test(keychar)
}

EventUtil.addEventHandler = function (oTarget, sEventType, fnHandler) {
	if (oTarget.addEventListener) { //for DOM-compliant browsers
		oTarget.addEventListener(sEventType, fnHandler, false);
	} 
	else if (oTarget.attachEvent) { //for IE
		oTarget.attachEvent("on" + sEventType, fnHandler);
	} 
	else { //for all others
		oTarget["on" + sEventType] = fnHandler;
	}
};

EventUtil.removeEventHandler = function (oTarget, sEventType, fnHandler) {
	if (oTarget.removeEventListener) { //for DOM-compliant browsers
		oTarget.removeEventListener(sEventType, fnHandler, false);
	} 
	else if (oTarget.detachEvent) { //for IE
		oTarget.detachEvent("on" + sEventType, fnHandler);
	} 
	else { //for all others
		oTarget["on" + sEventType] = null;
	}
};

EventUtil.formatEvent = function (oEvent) {
	if (isIE && isWin) {
		oEvent.charCode = (oEvent.type == "keypress") ? oEvent.keyCode : 0;
		oEvent.eventPhase = 2;
		oEvent.isChar = (oEvent.charCode > 0);
		oEvent.pageX = oEvent.clientX + document.body.scrollLeft;
		oEvent.pageY = oEvent.clientY + document.body.scrollTop;
		oEvent.preventDefault = function () {
			this.returnValue = false;
		};
		if (oEvent.type == "mouseout") {
			oEvent.relatedTarget = oEvent.toElement;
		} 
		else if (oEvent.type == "mouseover") {
			oEvent.relatedTarget = oEvent.fromElement;
		}
		oEvent.stopPropagation = function () {
			this.cancelBubble = true;
		};
		oEvent.target = oEvent.srcElement;
		oEvent.time = (new Date).getTime();
	}
	return oEvent;
}


EventUtil.getEvent = function() {
	if (window.event) {
		return this.formatEvent(window.event);
	}
	else {
		return EventUtil.getEvent.caller.arguments[0];
	}
};


function compareVersions(sVersion1, sVersion2) {
	var aVersion1 = sVersion1.split(".");
	var aVersion2 = sVersion2.split(".");
	if (aVersion1.length > aVersion2.length) {
		for (var i=0; i < aVersion1.length - aVersion2.length; i++) {
			aVersion2.push("0");
		}
	} 
	else if (aVersion1.length < aVersion2.length) {
		for (var i=0; i < aVersion2.length - aVersion1.length; i++) {
			aVersion1.push("0");
		}
	}
	for (var i=0; i < aVersion1.length; i++) {
		if (aVersion1[i] < aVersion2[i]) {
			return -1;
		} 
		else if (aVersion1[i] > aVersion2[i]) {
			return 1;
		}
	}
	return 0;
}

var isOpera = sUserAgent.indexOf("Opera") > -1;
var isMinOpera4 = isMinOpera5 = isMinOpera6 = isMinOpera7 = isMinOpera7_5 = false;
if (isOpera) {
	var fOperaVersion;
	if(navigator.appName == "Opera") {
		fOperaVersion = fAppVersion;
	} 
	else {
		var reOperaVersion = new RegExp("Opera (\\d+\\.\\d+)");
		reOperaVersion.test(sUserAgent);
		fOperaVersion = parseFloat(RegExp["$1"]);
	}
	isMinOpera4 = fOperaVersion >= 4;
	isMinOpera5 = fOperaVersion >= 5;
	isMinOpera6 = fOperaVersion >= 6;
	isMinOpera7 = fOperaVersion >= 7;
	isMinOpera7_5 = fOperaVersion >= 7.5;
}

var isKHTML = sUserAgent.indexOf("KHTML") > -1 || sUserAgent.indexOf("Konqueror") > -1 || sUserAgent.indexOf("AppleWebKit") > -1;
var isMinSafari1 = isMinSafari1_2 = false;
var isMinKonq2_2 = isMinKonq3 = isMinKonq3_1 = isMinKonq3_2 = false;
if (isKHTML) {
	isSafari = sUserAgent.indexOf("AppleWebKit") > -1;
	isKonq = sUserAgent.indexOf("Konqueror") > -1;
	if (isSafari) {
		var reAppleWebKit = new RegExp("AppleWebKit\\/(\\d+(?:\\.\\d*)?)");
		reAppleWebKit.test(sUserAgent);
		var fAppleWebKitVersion = parseFloat(RegExp["$1"]);
		isMinSafari1 = fAppleWebKitVersion >= 85;
		isMinSafari1_2 = fAppleWebKitVersion >= 124;
	}
	else if (isKonq) {
		var reKonq = new RegExp("Konqueror\\/(\\d+(?:\\.\\d+(?:\\.\\d)?)?)");
		reKonq.test(sUserAgent);
		isMinKonq2_2 = compareVersions(RegExp["$1"], "2.2") >= 0;
		isMinKonq3 = compareVersions(RegExp["$1"], "3.0") >= 0;
		isMinKonq3_1 = compareVersions(RegExp["$1"], "3.1") >= 0;
		isMinKonq3_2 = compareVersions(RegExp["$1"], "3.2") >= 0;
	}
}

var isIE = sUserAgent.indexOf("compatible") > -1 && sUserAgent.indexOf("MSIE") > -1 && !isOpera;
var isMinIE4 = isMinIE5 = isMinIE5_5 = isMinIE6 = false;
if (isIE) {
	var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
	reIE.test(sUserAgent);
	var fIEVersion = parseFloat(RegExp["$1"]);
	isMinIE4 = fIEVersion >= 4;
	isMinIE5 = fIEVersion >= 5;
	isMinIE5_5 = fIEVersion >= 5.5;
	isMinIE6 = fIEVersion >= 6.0;
}

var isMoz = sUserAgent.indexOf("Gecko") > -1 && !isKHTML;
var isMinMoz1 = sMinMoz1_4 = isMinMoz1_5 = false;
if (isMoz) {
	var reMoz = new RegExp("rv:(\\d+\\.\\d+(?:\\.\\d+)?)");
	reMoz.test(sUserAgent);
	isMinMoz1 = compareVersions(RegExp["$1"], "1.0") >= 0;
	isMinMoz1_4 = compareVersions(RegExp["$1"], "1.4") >= 0;
	isMinMoz1_5 = compareVersions(RegExp["$1"], "1.5") >= 0;
}

var isNS4 = !isIE && !isOpera && !isMoz && !isKHTML && (sUserAgent.indexOf("Mozilla") == 0) && (navigator.appName == "Netscape") && (fAppVersion >= 4.0 && fAppVersion < 5.0);
var isMinNS4 = isMinNS4_5 = isMinNS4_7 = isMinNS4_8 = false;
if (isNS4) {
	isMinNS4 = true;
	isMinNS4_5 = fAppVersion >= 4.5;
	isMinNS4_7 = fAppVersion >= 4.7;
	isMinNS4_8 = fAppVersion >= 4.8;
}


var isWin = (navigator.platform == "Win32") || (navigator.platform == "Windows");
var isMac = (navigator.platform == "Mac68K") || (navigator.platform == "MacPPC") || (navigator.platform == "Macintosh");
var isUnix = (navigator.platform == "X11") && !isWin && !isMac;
var isWin95 = isWin98 = isWinNT4 = isWin2K = isWinME = isWinXP = false;
if (isWin) {
isWin95 = sUserAgent.indexOf("Win95") > -1 || sUserAgent.indexOf("Windows 95") > -1;
isWin98 = sUserAgent.indexOf("Win98") > -1 || sUserAgent.indexOf("Windows 98") > -1;
isWinME = sUserAgent.indexOf("Win 9x 4.90") > -1 || sUserAgent.indexOf("Windows ME") > -1;
isWin2K = sUserAgent.indexOf("Windows NT 5.0") > -1 || sUserAgent.indexOf("Windows 2000") > -1;
isWinXP = sUserAgent.indexOf("Windows NT 5.1") > -1 || sUserAgent.indexOf("Windows XP") > -1;
isWinNT4 = sUserAgent.indexOf("WinNT") > -1 || sUserAgent.indexOf("Windows NT") > -1 || sUserAgent.indexOf("WinNT4.0") > -1 || sUserAgent.indexOf("Windows NT 4.0") > -1 && (!isWinME && !isWin2K && !isWinXP);
}

var isMac68K = isMacPPC = false;
if (isMac) {
	isMac68K = sUserAgent.indexOf("Mac_68000") > -1 || sUserAgent.indexOf("68K") > -1;
	isMacPPC = sUserAgent.indexOf("Mac_PowerPC") > -1 || sUserAgent.indexOf("PPC") > -1;
}

var isSunOS = isMinSunOS4 = isMinSunOS5 = isMinSunOS5_5 = false;
var reSunOS = new RegExp("SunOS (\\d+\\.\\d+(?:\\.\\d+)?)");
if (isUnix) {
	isSunOS = sUserAgent.indexOf("SunOS") > -1;
	if (isSunOS) {
		var reSunOS = new RegExp("SunOS (\\d+\\.\\d+(?:\\.\\d+)?)");
		reSunOS.test(sUserAgent);
		isMinSunOS4 = compareVersions(RegExp["$1"], "4.0") >= 0;
		isMinSunOS5 = compareVersions(RegExp["$1"], "5.0") >= 0;
		isMinSunOS5_5 = compareVersions(RegExp["$1"], "5.5") >= 0;
	}
}
