/**
 * @author 	Pascal Noordink
 * @version 12-11-2008
 */
 var poGridInstance = null;
 
 /**
 * Als de body geladen is dan het `PioenPartners_JS_Grid` object aan het
 * grid koppelen. 
 */
laOnloadActions.push(
	function() {
 		// Instantie van de grid maken.
 		PioenPartners_JS_Grid.initGrid("PPGrid");
	}
);

 var PioenPartners_JS_Grid = {
 	_lnSorted : 0,
 
 	/**
 	 * Maak een instantie van het Grid en geef het Grid een standaard ordening.
 	 *
 	 * @param	lcGrid
 	 * @return	void
 	 */
 	initGrid : function(lcGrid) { 	
 		// Grid element opvragen.
 		var loGrid		= document.getElementById(lcGrid);
 		var loBody 		= document.getElementById(lcGrid + "Body");
 		var loHeader	= document.getElementById(lcGrid + "Header");

 		// Gegevens uit het grid mogen niet geselecteerd worden.
 		this._disableSelect(loBody);
 		this._disableSelect(loHeader);

	 	// De body van het grid resizen. (Dit kan niet in CSS)
	 	if(loGrid.style.width.indexOf("%") == -1) {
	 		loBody.style.height = (parseInt(loGrid.style.height) - 21) + "px"; 
	 		loBody.style.width  = (parseInt(loGrid.style.width)) + "px";
	 	} else {
	 		loBody.style.height = (parseInt(loGrid.style.height) - 21) + "px";
	 		loBody.style.width  = (parseInt(loGrid.style.width)) + "%";	 		
	 	}

 		// Instantie van de `PioenPartners_JS_Grid` class in een globable variabele
 		// opslaan. Bij het uitvoeren van functies op het grid kan de instantie
 		// gebruikt worden. Deze is op dat punt namelijk niet meer bekend.
 		poGridInstance = this; 		
 		
 		// Lege textNodes verwijderen om problemen met FireFox te voorkomen.
		this._cleanNodes(loGrid) 		
 		
		// De eerste regel selecteren.
		var loRow = loHeader.getElementsByTagName("div")[0];
		
		// Alle kolommen van het grid doorlopen en deze sorteerbaar maken.
		for(var lnI = 0; lnI < loRow.getElementsByTagName("div").length; lnI++) {
			var loColumn = loRow.getElementsByTagName("div")[lnI];
			
			// Een `onclick` event toevoegen aan de header. Als er op de header
			// wordt geklikt dan wordt de functie `doSort` voor de desbetreffende
			// kolom uitgevoerd.
			loColumn.onclick = new Function("document.getElementById('"+ lcGrid +"Wait').style.visibility = 'visible'; setTimeout(\"PioenPartners_JS_Grid.doSort('"+ lcGrid +"', "+ lnI +");\", 100);");
			
			// Standaard is geen enkele kolom geordend. In de functie `doSort`
			// wordt een kolom gekozen om op te ordenen.
			loColumn.className = 'OrderNone';
		} 

 		// Even en oneven regels tekenen.
 		this._showLines(loBody);		
 	},
 	
 	/**
 	 * De regels ordenen op inhoud. Tevens de weergave van de header wijzigen
 	 * als een sorteer volgorde wordt gewijzigd.
 	 *
 	 * @param	lcGrid
 	 * @param	lnIndex
 	 * @return	void
 	 */ 	
 	doSort : function(lcGrid, lnIndex) {
 		// Grid element opvragen.
 		var loBody 		= document.getElementById(lcGrid + "Body");
 		var loHeader	= document.getElementById(lcGrid + "Header");

		// Div tonen om te laten zien dat het grid bijgewerkt wordt.
		document.getElementById(lcGrid +"Wait").style.visibility = "visible";

 		// De kolom die wordt gesorteerd opslaan in de variabele `_lnSorted`
 		// zodat de sorteer functie er nog bij kan.
 		this._lnSorted = lnIndex;

 		// De gekozen kolom opvragen.
 		var loRow 		= loHeader.getElementsByTagName("div")[0];
		var loColumn	= loRow.getElementsByTagName("div")[lnIndex];
		
		// Als de gekozen kolom al een order heeft dan omdraaien, als dat niet
		// het geval is dan beginnen met ASC.
		var lcOrder = 'ASC';
		
		switch(loColumn.className) {
			case 'OrderASC':
				loColumn.className  = 'OrderDESC';
				lcOrder				= 'DESC'
				break;
				
			case 'OrderDESC':
				loColumn.className = 'OrderASC';
				break;
				
			case 'OrderNone':
				loColumn.className = 'OrderASC';
				break;
		}
		
		// Alle andere kolommen mogen geen order meer bevatten. Tevens dient
		// het uiterlijk te worden gewijzigd door de css class naam te wijzigen.
		for(lnI = 0; lnI < loRow.getElementsByTagName("div").length; lnI++) {
			if(lnI != lnIndex) {
				loRow.getElementsByTagName("div")[lnI].className = 'OrderNone';
			}
		}
		
		// Alle rows doorlopen en deze in een array opslaan, als er straks wordt
		// geordend opnieuw opbouwen. 
		var laRows = new Array();
		
		for(var lnI = 0; lnI < loBody.getElementsByTagName("div").length; lnI++) {
			if(loBody.getElementsByTagName("div")[lnI].className != "PPGridColumn") {
				laRows.push(loBody.getElementsByTagName("div")[lnI]);
			}
		}
	
		// Initieel String.
		var lcType = "String";

		for(var lnI = 0; lnI < laRows.length; lnI++) {
			var luValue = this._getColumnValue(laRows[lnI].childNodes[lnIndex]);

			if(luValue.length != 0) {
				if(luValue.match(/[0-9]{2}-[0-9]{2}-[0-9]{4}/)) {
					lcType = "Date";
				} else if(!isNaN(luValue)) {
					lcType = "Numeric";
				} else {
					lcType = "String";
				}
				
				// Type is gevonden dus stoppen.
				lnI = laRows.length;					
			}
		}

		// Alle rows ordenen met de functie `_doSort.......`.
		if(lcType == "Date") {
			laRows.sort(this._doSortDate);
		} else if(lcType == "Numeric") {
			laRows.sort(this._doSortNumeric);
		} else {
			laRows.sort(this._doSortString);
		}

		// Als de order op DESC staat dan de array omdraaien.
		if(lcOrder == 'DESC') {
			laRows.reverse();
		}

		// Alle geordende rows weer toevoegen aan de grid.
		for(var lnI = 0; lnI < laRows.length; lnI++) {
			loBody.appendChild(laRows[lnI]);
		}

		// Het ordenen is gereed dus de melding kan weer weg worden gehaald.
		document.getElementById(lcGrid +"Wait").style.visibility = "hidden";

 		// Even en oneven regels tekenen.
 		this._showLines(loBody);				
 	},
 	
 	/**
 	 * Sorteer functie die wordt aangeroepen vanuit de functie `doSort`. Als de
 	 * methode `sort` op een array wordt uitgevoerd dan wordt deze functie 
 	 * aangeroepen.
 	 * De functie vergelijkt 2 waarden met elkaar en geeft dan.
 	 *	. -1 terug als A voor B ligt.
 	 *	. 0 terug als de waardes gelijk zijn. 	 
 	 *	. 1 terug als B voor A ligt. 
 	 *
 	 * @param	loRowA
 	 * @param	loRowB
 	 * @return	Integer
 	 */ 	 	
 	_doSortDate : function(loRowA, loRowB) {
 		// De waarden van regel A vergelijken met regel B.
		var lcValueA = poGridInstance._getColumnValue(loRowA.childNodes[poGridInstance._lnSorted]).toLowerCase();
		var lcValueB = poGridInstance._getColumnValue(loRowB.childNodes[poGridInstance._lnSorted]).toLowerCase();

		// De opgegeven datums omschrijven naar het formaat: `jjjjmmdd`.
		var lnValueA = lcValueA.substr(6, 4) +"-"+ lcValueA.substr(3, 2) +"-"+ lcValueA.substr(0, 2);
		var lnValueB = lcValueB.substr(6, 4) +"-"+ lcValueB.substr(3, 2) +"-"+ lcValueB.substr(0, 2);
			
		// Als de waardes overeenkomen dan `0` retourneren.
		if (lnValueA == lnValueB) {
			return 0;
		}
		
		// Als de waarde van A voor de waarde van B ligt dan `-1` retourneren.
		if (lnValueA < lnValueB) {
			return -1;
		}
		
		// Als de waarde van B voor de waarde van A ligt dan `1` retourneren.
		return 1;		
 	}, 	
 	
 	/**
 	 * Sorteer functie die wordt aangeroepen vanuit de functie `doSort`. Als de
 	 * methode `sort` op een array wordt uitgevoerd dan wordt deze functie 
 	 * aangeroepen.
 	 * De functie vergelijkt 2 waarden met elkaar en geeft dan.
 	 *	. -1 terug als A voor B ligt.
 	 *	. 0 terug als de waardes gelijk zijn. 	 
 	 *	. 1 terug als B voor A ligt. 
 	 *
 	 * @param	loRowA
 	 * @param	loRowB
 	 * @return	Integer
 	 */ 	 	
 	_doSortNumeric : function(loRowA, loRowB) {
 		// De waarden van regel A vergelijken met regel B.
		var lnValueA = parseFloat(poGridInstance._getColumnValue(loRowA.childNodes[poGridInstance._lnSorted]));
		var lnValueB = parseFloat(poGridInstance._getColumnValue(loRowB.childNodes[poGridInstance._lnSorted]));

		// Als de waardes overeenkomen dan `0` retourneren.
		if (lnValueA == lnValueB) {
			return 0;
		}
		
		// Als de waarde van A voor de waarde van B ligt dan `-1` retourneren.
		if (lnValueA < lnValueB) {
			return -1;
		}
		
		// Als de waarde van B voor de waarde van A ligt dan `1` retourneren.
		return 1;		
 	}, 	 	
 	
 	/**
 	 * Sorteer functie die wordt aangeroepen vanuit de functie `doSort`. Als de
 	 * methode `sort` op een array wordt uitgevoerd dan wordt deze functie 
 	 * aangeroepen.
 	 * De functie vergelijkt 2 waarden met elkaar en geeft dan.
 	 *	. -1 terug als A voor B ligt.
 	 *	. 0 terug als de waardes gelijk zijn. 	 
 	 *	. 1 terug als B voor A ligt. 
 	 *
 	 * @param	loRowA
 	 * @param	loRowB
 	 * @return	Integer
 	 */ 	
 	_doSortString : function(loRowA, loRowB) {
 		// De waarden van regel A vergelijken met regel B.
		var lcValueA = poGridInstance._getColumnValue(loRowA.childNodes[poGridInstance._lnSorted]).toLowerCase();
		var lcValueB = poGridInstance._getColumnValue(loRowB.childNodes[poGridInstance._lnSorted]).toLowerCase();

		// Als de waardes overeenkomen dan `0` retourneren.
		if (lcValueA == lcValueB) {
			return 0;
		}
		
		// Als de waarde van A voor de waarde van B ligt dan `-1` retourneren.
		if (lcValueA < lcValueB) {
			return -1;
		}
		
		// Als de waarde van B voor de waarde van A ligt dan `1` retourneren.
		return 1;		
 	},
 	
 	/**
 	 * De waarde uit een opgegeven kolom opvragen.
 	 *
 	 * @param	loColumn
 	 * @return	Undefined
 	 */ 	
 	 _getColumnValue : function(loColumn) {
 	 	// Initieel leeg.
 	 	var luValue = "";
 	 	
		// Alle kinderen van de opgegeven kolom doorlopen.
		var laChildren = loColumn.childNodes;

		for(var lnI = 0; lnI < laChildren.length; lnI++) {
			if(laChildren[lnI].tagName != "DIV") {
				if(laChildren[lnI].nodeValue.length != 0) {
					luValue = laChildren[lnI].nodeValue;
				}
			} else {
				luValue = this._getColumnValue(laChildren[lnI].childNodes);
			}			
		}
 	 
		// Waarde retourneren.
		return luValue; 	 	
 	 },
 	 
	/**
	 * Opschonen van het DOM (Data Object Model).
	 * textNodes vallen binnen de set van Childnodes in FireFox.
	 * Binnen IE worden ze genegeerd, om de verwerking hetzelfde te houden
	 * worden de textNodes verwijdert als deze leeg zijn.
	 *
	 * @param	loNode
	 */
	_cleanNodes : function(loNode) {
		// Alle kinderen opvragen.
		var loExpr = /\S/;
		
		for(var lnI = 0; lnI < loNode.childNodes.length; lnI++) {
			var loChildNode = loNode.childNodes[lnI];
			
			// Als de node een textnode is en leeg is dan verwijderen.
			if(loChildNode.nodeType == 3 && 
			   !loExpr.test(loChildNode.nodeValue)) {
				loNode.removeChild(loNode.childNodes[lnI]);
			
				lnI--;
			}
			
			// Als de node kinderen kan hebben dan deze ook opschonen.
			if (loChildNode.nodeType == 1) {
				this._cleanNodes(loChildNode);
			}
		}
	},
 	
 	/**
 	 * Even en oneven regels een andere kleur geven. Tevens regels waar met de muis
 	 * overheen wordt bewogen een andere kleur geven.
 	 *
 	 * @param	loBody
 	 * @return	void
 	 */ 	
 	_showLines : function(loBody) {
 		// Alle regels doorlopen. 
 		var lnRows = 0;
 		 
 		for(var lnI = 0; lnI < loBody.getElementsByTagName("div").length; lnI++) {
			if(loBody.getElementsByTagName("div")[lnI].className != "PPGridColumn") {
	 			// Even krijgt de class naam `Even`.
	 			// Oneven krijgt de class naam `Odd`.
				if((lnRows % 2) == 0) {
					loBody.getElementsByTagName("div")[lnI].className = 'Even';
				} else {
					loBody.getElementsByTagName("div")[lnI].className = 'Odd';
				}
				
				lnRows++;
			}
 		}
 		
		// Alle rows krijgen een onmouseover en onmouseout event toegewezen 
		// voor het tonen van een andere kleur als er met de muis over de
		// regel wordt bewogen.
		for(lnI = 0; lnI < loBody.getElementsByTagName("div").length; lnI++) {
			loRow = loBody.getElementsByTagName("div")[lnI];
			
			if(loRow.className != "PPGridColumn") {
				// Als de muis over de regel wordt bewogen dan de className 
				// veranderen in `Hover`.
				loRow.onmouseover = function() {
					this.className = 'Hover';
				}
				
				// Als de muis van de regel af wordt bewogen dan de className
				// veranderen in het origineel.
				loRow.classOld = loRow.className;
							
				loRow.onmouseout = function(e) {
					this.className = this.classOld;				
				} 
			}
		} 	 		
 	},
 	
 	/**
 	 * De mogelijkheid voor de gebruiker om tekst te selecteren onmogelijk maken
 	 * voor het opgegeven object.
 	 *
 	 * @param	loElement
 	 * @return	void
 	 */ 	
 	_disableSelect : function(loElement) {
 		// Functie toevoegen die wordt getriggered als er met de muis tekst
 		// wordt geselecteerd.
 		loElement.onselectstart = function() {
        	return false;
    	};
    	
    	// Voor alle browsers zorgen dat de tekst niet geselecteerd kan worden.
    	loElement.unselectable 			= "on";
    	loElement.style.MozUserSelect 	= "none";
    	loElement.style.cursor 			= "default";
 	}
 };
