// Script to render a table of cable data from an XML input file
//
// 2009-02-26	TAK	Updated to Detati programming style, add code to sort dropdowns
// 2010-03-10	TAK	Updated to support two tables, certified & verified cables
// 2010-03-12	TAK	Updated to single CSV file upload
// 2010-03-23	TAK	Updated to drop vendor column in certified table
// 2010-04-01	TAK	Updated to handle empty XML elements
// 2010-06-10	TAK	Updated to fix Safari/Chrome XML import & IE6/7 Select onChange bug
// 2010-07-19	TAK	Updated to support columns w/o select elements
// 2010-07-20	TAK	Updated to split Certified & Verified up into two different div's
// ------------------------------------------------------------------------------------------------------------------
var titleCert = 'Mellanox Certified Cables and Modules'
var titleVeri = 'Mellanox Verified Cables and Modules'
var titleOthr = 'Other Cables and Modules'
var ftrMsg = 'No Products Available For Selection'
//var divCabl = 'divCables'		// ID of the div wrapping the cable tables
var divCert = 'divCertCables'	// ID of the div wrapping the certified cables table
var divVeri = 'divVeriCables'	// ID of the div wrapping the verified cables table
var divOthr = 'divOthrCables'	// ID of the div wrapping the other cables table
var tblCert = 'tblCert'			// ID of the certified cables table
var tblVeri = 'tblVeri'			// ID of the verified cables table
var tblOthr = 'tblOthr'			// ID of the other cables table
var hdrArr = new Array()		// Array with column heading strings
var certArr = new Array()		// Array of row arrays for certified cables
var veriArr = new Array()		// Array of row arrays for verified cables
var othrArr = new Array()		// Array of row arrays for other cables
var ldArr = []
var verIE = (p = navigator.userAgent.indexOf('MSIE ')) ?
	parseFloat(navigator.userAgent.substring(p+5, navigator.userAgent.indexOf(';', p))) : false

function cables_importXML () {
	var xml = (arguments.length) ? arguments[0] : "products/cables.xml"
	importXML(xml,'cables_init')
	return
}
function importXML (oURL, oFunct, oNoRand, oDelay) {
	if (!oNoRand) {
		oURL += ((oURL.indexOf('?') + 1 ) ? '&' : '?') + (new Date()).getTime()
	}
	if (window.XMLHttpRequest) {
		ldArr.push(new XMLHttpRequest())
		var slot = ldArr.length-1
		ldArr[slot].onreadystatechange = new Function('if( ldArr['+slot+'].readyState == 4 && ldArr['+slot+'].status < 300 ) { '+oFunct+'(ldArr['+slot+'].responseXML); }')
		ldArr[slot].open('GET', oURL, true)
		ldArr[slot].send(null)
		return true
	}
	if (!navigator.__ice_version && window.ActiveXObject) {
		var activexlist = ['Microsoft.XMLHTTP','Microsoft.XMLDOM'], tho
		for (var i = 0; !tho && i<activexlist.length; i++) {
			try {
				tho = new ActiveXObject(activexlist[i])
			} catch(e) {}
		}
		if (tho) {
			ldArr.push(tho)
			var slot = ldArr.length-1
			ldArr[slot].onreadystatechange = new Function('if(ldArr['+slot+'].readyState == 4) { '+oFunct+'(ldArr['+slot+'].load?ldArr['+slot+']:ldArr['+slot+'].responseXML); }')
			if (ldArr[slot].load) {
				ldArr[slot].load(oURL)
			} else {
				ldArr[slot].open('GET', oURL, true)
				ldArr[slot].send(null)
			}
			return true
		}
	}
	if (document.createElement && document.childNodes) {
		var ifr = document.createElement('DIV')
		ifr.style.visibility = 'hidden'
		ifr.style.position = 'absolute'
		ifr.style.top = '0px'
		ifr.style.left = '0px'
		if (!window.XML_timer) {
			window.XML_timer = window.setInterval('check_XML_Load();', 100)
		}
		ifr.innerHTML = '<iframe src="' + oURL + '" name="XML_loader_' + ldArr.length + '" height="0" width="0"><\/iframe>'
		ldArr[ldArr.length] = oFunct + '|' + (oDelay ? oDelay : 1) + ''
		document.body.appendChild(ifr)
		return true
	}
	return false
}
function check_XML_Load() {
	for (var x = 0; x<ldArr.length; x++) {
		if (ldArr[x] && window.frames['XML_loader_' + x]) {
			setTimeout(ldArr[x].split('|')[0] + '(window.frames.XML_loader_' + x + '.window.document);', parseInt(ldArr[x].split('|')[1]))
			ldArr[x] = false
		}
	}
	return
}
function cables_init (xmlDoc) {
// Initialize the arrays of data
	var c, r, l, rowArr, tblFlg,
		 x = xmlDoc.getElementsByTagName('cable'),
		 rowCnt = x.length,
		 colCnt = x[0].childNodes.length,
		 vCol = -1
	for (r = 0; r<rowCnt; r++) {
		rowArr = new Array()
		tblFlg = ''
		for (c = 0; c<colCnt; c++) {
			if (x[r].childNodes[c].nodeType == 1) {
				l = x[r].childNodes[c].nodeName.replace(/-/g, ' ')
				if (l.toLowerCase()=='ga status') {
					tblFlg = x[r].childNodes[c].firstChild.nodeValue.toLowerCase()
				} else if (l.toLowerCase()=='dell' || l.toLowerCase()=='dell opn' ||
							  l.toLowerCase()=='data rate' || l.toLowerCase().substr(0,5) =='power') {
					continue
				} else {
					if (r==0) {
						if (l.toLowerCase()=='vendor') {
							vCol = hdrArr.length
						}
						hdrArr.push(l)
					}
					rowArr.push(x[r].childNodes[c].firstChild ? x[r].childNodes[c].firstChild.nodeValue : '')
				}
			}
		}
		if (tblFlg=='certified') {
			if (vCol>=0) {
				rowArr.splice(vCol, 1)
			}
			certArr.push(rowArr)
		} else if (tblFlg=='verified') {
			veriArr.push(rowArr)
		} else {
			othrArr.push(rowArr)
		}
	}
	var divCertEl = document.getElementById(divCert),
		 divVeriEl = document.getElementById(divVeri),
		 divOthrEl = document.getElementById(divOthr),
		 newEl, tblEl
	if (hdrArr.length && certArr.length) {
// Create the table of certified cables
		var tbHdArr = hdrArr.slice(0)
		if (vCol>=0) {
			tbHdArr.splice(vCol, 1)
		}
		if (tblEl = cables_createTable(titleCert, tblCert, tbHdArr, certArr)) {
			if (divCertEl) {
				divCertEl.appendChild(tblEl)
			}
		}
	}
	if (hdrArr.length && veriArr.length) {
// Create the table of verified cables
		if (tblEl = cables_createTable(titleVeri, tblVeri, hdrArr, veriArr)) {
			if (divVeriEl) {
				divVeriEl.appendChild(tblEl)
			}
		}
	}
	if (hdrArr.length && othrArr.length) {
// Create the table of other cables
		if (tblEl = cables_createTable(titleOthr, tblOthr, hdrArr, othrArr)) {
			if (divOthrEl) {
				divOthrEl.appendChild(tblEl)
			}
		}
	}
	return
}
function cables_createTable (caption, tblIdName, tblHdrArr, rowDatArr) {
// REMEMBER - hdrArr should be passed as an arg
	var c, tblEl, tblSecEl, rowHdEl, rowEl, colHdEl, colEl, selEl,
		 colCnt = tblHdrArr.length
	tblEl = document.createElement('table')
	tblEl.setAttribute('id', tblIdName)
// Create table caption
	rowEl = document.createElement('caption')
	rowEl.innerHTML = caption
	tblEl.appendChild(rowEl)
// Create table heading
	tblSecEl = document.createElement('thead')
	tblEl.appendChild(tblSecEl)

// Create header
	rowHdEl = document.createElement('tr')
	rowHdEl.setAttribute('class', 'header')
//create DropDowns
	rowEl = document.createElement('tr')
	rowEl.setAttribute('class', 'dropdown')
	for (c = 0; c<colCnt; c++) {
		colHdEl = document.createElement('td')	
		colEl = document.createElement('td')
		if (verIE && verIE<8) {
// Workaround IE Select bug
			colEl.innerHTML = cables_addHTMLOption(tblIdName, rowDatArr, c)
		} else {
			colEl.appendChild(cables_addOption(tblIdName, rowDatArr, c))

		}
// Check for any non-selectable columns
		if (tblHdrArr[c]=='Compliancy Notes') {
			colEl.innerHTML = '<p id="'+tblIdName+'_'+c+'"></p>'
		}
		colHdEl.appendChild(document.createTextNode(tblHdrArr[c]))
		rowHdEl.appendChild(colHdEl)
		rowEl.appendChild(colEl)
	}
	tblSecEl.appendChild(rowHdEl)
	tblSecEl.appendChild(rowEl)

// Add the cable data
	var r, cls, selFlg, 
		 rowCnt = rowDatArr.length
	tblSecEl = document.createElement('tbody')
	tblEl.appendChild(tblSecEl)
	for (r = 0; r<rowCnt; r++) {
		rowEl = document.createElement('tr')
		cls = ((r % 2)==0) ? 'even' : 'odd'
		for (c = 0; c<colCnt; c++) {
// Check for selection
			colEl = document.createElement('td')
			colEl.setAttribute('class', cls)
			colEl.appendChild(document.createTextNode(rowDatArr[r][c]))
			rowEl.appendChild(colEl)
		}
		tblSecEl.appendChild(rowEl)
	}
// Add a footer
	tblSecEl = document.createElement('tfoot')
	tblSecEl.style.display = 'none'
	tblEl.appendChild(tblSecEl)
	rowEl = document.createElement('tr')
	colEl = document.createElement('td')
	colEl.colSpan = tblEl.rows[0].cells.length
	colEl.setAttribute('class', 'footer')
	colEl.innerHTML = ftrMsg
	rowEl.appendChild(colEl)
	tblSecEl.appendChild(rowEl)
	return tblEl
}
function cables_addOption(tblIdName, datArr, column) {
// Collect and sort the list of column values
	var r,
		 c = parseInt(column, 10),
		 rowCnt = datArr.length,
		 selArr = new Array()
	for (r = 0; r<rowCnt; r++) {
		if (datArr[r][c].length && !selArr.in_array(datArr[r][c])) {
			selArr.push(datArr[r][c])
		}
	}
	if (!selArr.length) {
		return document.createTextNode('')
	}
	selArr.sort(naturalSort)
// Check for the length column and add the shortcuts
	if (hdrArr[column].toLowerCase()=='length') {
		selArr.unshift('Long')
		selArr.unshift('Medium')
		selArr.unshift('Short')
	}
// Put All at the top
	selArr.unshift('All')
// Create the select element
	selEl = document.createElement('select')
	selEl.setAttribute('id', tblIdName+'_'+c)
	selEl.setAttribute('name', tblIdName+'_'+hdrArr[c])
	selEl.setAttribute('class', 'all')
	selEl.setAttribute('onChange', "cables_updData(this,'"+tblIdName+"')")
// Add the options
	var opt
	for (r = 0; r<selArr.length; r++) {
		opt = new Option(selArr[r], selArr[r])
		selEl.options.add(opt)
	}
	return selEl
}
function cables_addHTMLOption(tblIdName, datArr, column) {
// Collect and sort the list of column values
	var r,
		 c = parseInt(column, 10),
		 rowCnt = datArr.length,
		 selArr = new Array()
	for (r = 0; r<rowCnt; r++) {
		if (!selArr.in_array(datArr[r][c])) {
			selArr.push(datArr[r][c])
		}
	}
	selArr.sort(naturalSort)
// Check for the length column and add the shortcuts
	if (hdrArr[column].toLowerCase()=='length') {
		selArr.unshift('Long')
		selArr.unshift('Medium')
		selArr.unshift('Short')
	}
// Put All at the top
	selArr.unshift('All')
// Create the select element
	var selHtml = '<select id="' + tblIdName + '_' + c + '" name="' + tblIdName + '_' + hdrArr[c] + '" class="all" onChange="cables_updData(this,\'' + tblIdName + '\')">'
// Add the options
	for (r = 0; r<selArr.length; r++) {
		selHtml += '<option>' + selArr[r]
	}
	selHtml += '</select>'
	return selHtml
}
function cables_updData (selObj, tblIdName) {
// Make class adjustment
	if (selObj && selObj.options.length) {
		selObj.className = (selObj.options[selObj.selectedIndex].text=='All') ? 'all' : 'select'
	}
// Get the selected columns
	var c, selId,
		 colCnt = 0,
		 selArr = new Array()		// ['1.0','All',...]
	while (selId = document.getElementById(tblIdName+'_'+colCnt)) {
		if (selId && (selId.type=='select-one' || selId.type=='select-multiple')) {
			selArr.push(selId.options[selId.selectedIndex].text)
		} else {
			selArr.push('All')
		}
		colCnt++
	}
// Update the table rows
	var cls, len, tBody, row, disp,
		 k = 0,
		 tbl = document.getElementById(tblIdName)
	for (var i = 0; i<tbl.tBodies.length; i++) {
		tBody = tbl.tBodies[i]
		for (var j = 0; j<tBody.rows.length; j++) {
			row = tBody.rows[j]
			disp = true
			for (c = 0; c<row.cells.length; c++) {
// Eval row for display
				if (hdrArr[c]=='Length') {
					len = parseFloat(row.cells[c].innerHTML)
					if ((selArr[c]=='Short' && (isNaN(len) || len>=5)) ||
						 (selArr[c]=='Medium' && (isNaN(len) || len<5 || len>=10)) ||
						 (selArr[c]=='Long' && (isNaN(len) || len<10)) ||
						 (selArr[c]!='All' && selArr[c]!='Short' && selArr[c]!='Medium' && selArr[c]!='Long' && selArr[c]!=row.cells[c].innerHTML)
						) {
						disp = false
						break
					}
				} else if (selArr[c]!='All' && selArr[c]!=row.cells[c].innerHTML) {
					disp = false
					break
				}
// Set cell background
				cls = (selArr[c]!='All') ? ((k%2) ? 'selectOdd' : 'selectEven') : (k%2) ? 'odd' : 'even'
				row.cells[c].className = cls
			}
			if (disp) {
				row.style.display = ''
				k++
			} else {
				row.style.display = 'none'
			}
		}
	}
	tbl.tFoot.style.display = (k) ? 'none' : ''
	return
}
Array.prototype.in_array = function(f) {
	var r = 0
	if (f && this.length) {
		for (var i=0; i<this.length; i++) {
			if (this[i]===f) {	// BEWARE! Strict comparison being done here!
				r = 1
				break
			}
		}
	}
	return r
}
function naturalSort (a, b) {
// setup temp-scope variables for comparison evauluation
	var x = a.toString().toLowerCase() || ''
	var y = b.toString().toLowerCase() || ''
	var nC = String.fromCharCode(0)
	var xN = x.replace(/([-]{0,1}[0-9.]{1,})/g, nC + '$1' + nC).split(nC)
	var yN = y.replace(/([-]{0,1}[0-9.]{1,})/g, nC + '$1' + nC).split(nC)
	var xD = (new Date(x)).getTime()
	var yD = (new Date(y)).getTime()
// natural sorting of dates
	if (xD && yD && xD < yD) {
		return -1
	} else if (xD && yD && xD > yD) {
		return 1
	}
// natural sorting through split numeric strings and default strings
	for (var cLoc=0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
		if ((parseFloat(xN[cLoc]) || xN[cLoc]) < (parseFloat(yN[cLoc]) || yN[cLoc])) {
			return -1
		} else if ((parseFloat(xN[cLoc]) || xN[cLoc]) > (parseFloat(yN[cLoc]) || yN[cLoc])) {
			return 1
		}
	}
	return 0
}
