/*;

vers. 1.1: now you can define sorttypes
*/

function QxcSortTable (sPathToJs,ObjectName,tableID) 
{		
	//public proberties
	this.HeadAClassName="";
	this.HeadImgNoSrc=false;
	this.HeadImgDownSrc=false;
	this.HeadImgUpSrc=false;
	this.UseHeadImg=true;
	this.NoHeaderLinks= new Array();
	//<+1.1
	this.SortTypes= new Array();
	//+>
	//private proberties
	this.ObjectName=ObjectName;
	this.tableID=tableID;
	this.oTable;
	this.oTabHead=false;
	this.oTabBody=false;
	this.oArrHeadTds;
	this.oArrBodyTrTd;
	this.oArrBodyTr;
	this.iArrSortDirection;
	this.oArrHeadImg;
	this.sPathToJs=sPathToJs;
	
	
	this.Init = function ()
	{
		
		if(!this.HeadImgNoSrc)
		{
			this.HeadImgNoSrc=sPathToJs+"/img/no.gif";
		}

		if(!this.HeadImgDownSrc)
		{
			this.HeadImgDownSrc=sPathToJs+"/img/down.gif";
		}

		if(!this.HeadImgUpSrc)
		{
			this.HeadImgUpSrc=sPathToJs+"/img/up.gif";
		}
		this.initTable(this.tableID);

	}
	
	
	this.initTable = function (tableID)
	{
		
		this.oTable= document.getElementById(this.tableID);
		
		this.oTabHead=this.oTable.getElementsByTagName("thead");
		this.oTabBody=this.oTable.getElementsByTagName("tbody");
		
		if(this.oTabHead.length==0)
		{
			alert("Table Header nicht gefunden.");
			return false;
		}
		else
		{
			this.oTabHead=this.oTabHead[0];
		}
		
		if(this.oTabBody.length==0)
		{
			alert("Table Body nicht gefunden.");
			return false;
		}
		else
		{
			this.oTabBody=this.oTabBody[0];
		}
		
		this.oHeadTr=this.oTabHead.getElementsByTagName("tr");

		if(this.oHeadTr.length==0)
		{
			alert("TR im Table Head nicht gefunden.");
			return false;
		}
		else
		{
			this.oHeadTr=this.oHeadTr[0];
		}
		
		this.oArrHeadTds=this.oHeadTr.getElementsByTagName("td");
		
		
		if(this.oArrHeadTds.length==0)
		{
			alert("keine TD im Table Header gefunden.");
			return false;
			
		}
		else
		{
			//Das Array f�r die Directions initieren
			this.iArrSortDirection = new Array();
			for(i=0;i<this.oArrHeadTds.length;i++)
			{
				this.iArrSortDirection[i]=0;
				
				//<+1.1
				if(this.SortTypes[i]!="string" && this.SortTypes[i]!="date" && this.SortTypes[i]!="money")
				{
					this.SortTypes[i]=="string";
				}				
				//+>
			}
		}
		
		
		return this.ModifyHeader();
		
	}
	
	this.ModifyHeader = function ()
	{
		this.oArrHeadImg = new Array();
		for(i=0;i<this.oArrHeadTds.length;i++)
		{
			bIsHeader=true;
			for(iNoHeader=0;iNoHeader<this.NoHeaderLinks.length;iNoHeader++)
			{
				
				if(this.NoHeaderLinks[iNoHeader]==i)
				{
					bIsHeader=false;
					break;
				}
			}
			
			if(bIsHeader)
			{
				sLinkText="<a id='"+this.ObjectName+"qxcSortTableHeaderA"+i+"' class='"+this.HeadAClassName+"' href='javascript:"+this.ObjectName+".Sort("+i+")'>";				
				sLinkText+=this.oArrHeadTds[i].innerHTML;
				if(this.UseHeadImg)
				{
					sLinkText+="<img id='"+this.ObjectName+"qxcSortTableHeaderImg"+i+"' border='0' src='"+this.HeadImgNoSrc+"'/></a>";
					this.oArrHeadTds[i].innerHTML=sLinkText;
					this.oArrHeadImg[i] = document.getElementById(this.ObjectName+"qxcSortTableHeaderImg"+i);
				}
				else
				{
					this.oArrHeadTds[i].innerHTML=sLinkText;
					sLinkText+="</a>";			
				}
			}
			
			
		}
		
		return true;
	}
	
	this.ReadBody = function()
	{
		this.oArrBodyTr= new Array();
		this.oArrBodyTr=this.oTabBody.getElementsByTagName("tr");
		
		this.oArrBodyTrTd= new Array();
		
		for(i=0;i<this.oArrBodyTr.length;i++)
		{
			
			this.oArrBodyTrTd[i]=this.oArrBodyTr[i].getElementsByTagName("td");
		}
		
		
		
		return true;
	}
	
	this.Sort = function (SortIndex)
	{
		//<+1.1: get SortType
		var sSortType=this.SortTypes[SortIndex];
		//+>
		if(!this.ReadBody())
		{
			alert("Fehler beim lesen des Table Bodys");
			return false;
		}
		
		//Den zu sortierenden text in ein Array schrieben
		sArrSortText = new Array();
		
		
		for(i=0;i<this.oArrBodyTrTd.length;i++)
		{
			sSortText=this.oArrBodyTrTd[i][SortIndex].innerHTML;
			sArrSortText.push(sSortText);
		}
		
		
		//Das Array des zu sortierenden Textes sortieren und die Indexes speichern
		if(this.iArrSortDirection[SortIndex]==0)
		{
			iArrSortIndexes=this.SortArrayToIdxArr(sArrSortText,0,sSortType);	
			this.iArrSortDirection[SortIndex]=1;
			if(this.UseHeadImg)
			{
				for(i=0;i<this.oArrHeadImg.length;i++)
				{
					if(i==SortIndex)
					{
						this.oArrHeadImg[i].src=this.HeadImgDownSrc;
					}
					else
					{
						this.oArrHeadImg[i].src=this.HeadImgNoSrc;
					}
				}
			}
		}
		else
		{
			iArrSortIndexes=this.SortArrayToIdxArr(sArrSortText,1,sSortType);
			this.iArrSortDirection[SortIndex]=0;
			if(this.UseHeadImg)
			{
				for(i=0;i<this.oArrHeadImg.length;i++)
				{
					if(i==SortIndex)
					{
						this.oArrHeadImg[i].src=this.HeadImgUpSrc;
					}
					else
					{
						this.oArrHeadImg[i].src=this.HeadImgNoSrc;
					}
				}
			}
		}
		
		//Mit dem nun sortierten Indexes den TBody neu schreiben
		if(!this.WriteTBody(iArrSortIndexes))
		{
			alert("Fehler beim schreiben des Table Bodys");
			return false;
		}
	}
	
	this.WriteTBody = function (iArrTrSortedIndexes)
	{
		//Anhand der �bergebenen Indexes die TR in TBody neu schreiben
		oNewTabBody=document.createElement("TBody");
		
                //erste Zeile einfügen (=letzte Zeile)
                
                oNewTr=this.oArrBodyTr[0].cloneNode(true);
                oNewTabBody.appendChild(oNewTr);

			
		for(i=0;i<iArrTrSortedIndexes.length;i++)
		{
                        oLastTr=oNewTr;
			oNewTr=this.oArrBodyTr[iArrTrSortedIndexes[i]].cloneNode(true);


                        oNewTabBody.insertBefore(oNewTr,oLastTr);
		}
		
		//this.oTabBody.removeNode(true);


                this.oTable.removeChild(this.oTabBody);

		this.oTable.appendChild(oNewTabBody);
		this.oTabBody=oNewTabBody;
		
		return true;
	}

	//<x1.1: new parameter sSortType	
	this.SortArrayToIdxArr = function (arrToSort,iSortDirection,sSortType)
	//x>
	{
		iArrSortedFinal= new Array();
		sArrSortedFinal= new Array();
		
		
		/*
		Alle Elemente des Array welches sortiert werden soll durchlaufen und im neuen Array sArrSortedFinal 
		einordnen. Jedes mal wenn der String in sArrSortedFinal eingeordnet wird, wird auch der Index in iArrSortedFinal
		eingeordnet.
		*/
		for(i=0;i<arrToSort.length;i++)
		{
			bIsInsert=false;
			for(j=0;j<sArrSortedFinal.length;j++)
			{
				//F�r jedes bereits sortiertes Element pr�fen, ob das aktuelle Element gem�� der Direction einorderbar ist
				//<x1.1
				if(sSortType=="string")
				{
					iSortResult=this.Sort2Strings(arrToSort[i],sArrSortedFinal[j]);
				}
				else if(sSortType=="date")
				{
					iSortResult=this.Sort2Dates(arrToSort[i],sArrSortedFinal[j]);				
				}
				else if(sSortType=="money")
				{
					iSortResult=this.Sort2Moneys(arrToSort[i],sArrSortedFinal[j]);				
				}
				else
				{
					iSortResult=this.Sort2Strings(arrToSort[i],sArrSortedFinal[j]);				
				}
				//x>
				if((iSortResult==0 && iSortDirection==0) || (iSortResult==1 && iSortDirection==1))
				{
					//Das aktuelle Element ist gleich oder kleiner als das aktuelle bereits eingeordente Element
					//Das bereits geordnete Array an dieser Stelle splitten
					
					sArrStart=sArrSortedFinal.slice(0,j);	
					sArrEnd=sArrSortedFinal.slice(j);
					
					iArrStart=iArrSortedFinal.slice(0,j);	
					iArrEnd=iArrSortedFinal.slice(j);
					
					//Das aktuelle Element dem 1. Teil der gesplitteten Arrays anh�ngen
					sArrStart.push(arrToSort[i]);
					iArrStart.push(i);
					
					//Arrays wieder zusammenf�gen
					sArrSortedFinal=sArrStart.concat(sArrEnd);
					iArrSortedFinal=iArrStart.concat(iArrEnd);
					
					//markieren das das Element eingef�gt wurde
					bIsInsert=true;
					
					//Die innere Schleife verlassen.
					break;
				}
			}
			
			if(!bIsInsert)
			{
				//noch nicht eingef�gt -> am Ende einf�gen
				sArrSortedFinal.push(arrToSort[i]);
				iArrSortedFinal.push(i);
			}
		}
		return iArrSortedFinal;
	}

	//<+1.1
	this.Sort2Moneys = function (String1,String2)
	{
		//Ret Code
		//0: String1 ist kleiner
		//1: String2 ist kleiner
		//2: String sind gleich
		String1=this.clearTags(String1);
		String2=this.clearTags(String2);
		
		String1=String1.toLowerCase();
		String2=String2.toLowerCase();
		
		//Wenn beide String gleich sind, dann sofort Code 2 zur�ckgeben.
		if(String1==String2)
		{
			return 2;
		}
		
		//Strings von hinten durchsuchen. Erste nicht Zahl ist dezimalsztrich au�er einem Leerzeichen.
		var k=String1.length-1;
		var startFloat=false;
		var sFinalString="";
		var sCommaChar="";
		while(k>0)
		{
			isCharInt=(String1.charCodeAt(k)>47 && String1.charCodeAt(k)<58);
			
			//wenn keine Zahl
			if(!isCharInt)
			{
				if(startFloat)
				{
					//Aufzeichnung bereits gestartet
					if(sCommaChar=="")
					{
						//noch kein Comma gesetzt ->setzen
						sCommaChar=String1.charCodeAt(k);
						sFinalString=","+sFinalString;
					}
				}
			}
			else
			{
				if(!startFloat)
				{
					//Aufzeichnung noch nicht gestartet ->starten
					startFloat=true;
				}
				sFinalString=String1.charAt(k)+sFinalString;
			}

			k--;
		}
		var fMoney1= parseFloat(sFinalString);

		//STRING2
		//Strings von hinten durchsuchen. Erste nicht Zahl ist dezimalsztrich au�er einem Leerzeichen.
		var k=String2.length-1;
		var startFloat=false;
		var sFinalString="";
		var sCommaChar="";
		
		while(k>0)
		{

			isCharInt=(String2.charCodeAt(k)>47 && String2.charCodeAt(k)<58);
			
			//wenn keine Zahl
			if(!isCharInt)
			{
				if(startFloat)
				{
					//Aufzeichnung bereits gestartet
					if(sCommaChar=="")
					{
						//noch kein Comma gesetzt ->setzen
						sCommaChar=String2.charCodeAt(k);
						sFinalString=","+sFinalString;
					}
				}
			}
			else
			{
				if(!startFloat)
				{
					//Aufzeichnung noch nicht gestartet ->starten
					startFloat=true;
				}
				
				sFinalString=String2.charAt(k)+sFinalString;
			}

			k--;
			
		}
		var fMoney2= parseFloat(sFinalString);
		
		//Vergleichen
		if(fMoney1<fMoney2)
		{
			return 0;
		}
		else if(fMoney2<fMoney1)
		{
			return 1;
		}
		else
		{
			return 2;
		}
	
	}
	//+>
	
	//<+1.1
	this.Sort2Dates = function (String1,String2)
	{
		//Ret Code
		//0: String1 ist kleiner
		//1: String2 ist kleiner
		//2: String sind gleich
		String1=this.clearTags(String1);
		String2=this.clearTags(String2);
		
		String1=String1.toLowerCase();
		String2=String2.toLowerCase();
		
		//Wenn beide String gleich sind, dann sofort Code 2 zur�ckgeben.
		if(String1==String2)
		{
			return 2;
		}
		
		var aDate1=String1.split(".");
		var aDate2=String2.split(".");
		
		var iDate1=Date.UTC(aDate1[2],aDate1[1],aDate1[0]);
		var iDate2=Date.UTC(aDate2[2],aDate2[1],aDate2[0]);
				
		if(iDate1<iDate2)
		{
			return 0;
		}
		else if (iDate2<iDate1)
		{
			return 1;
		}
		else
		{
			return 2;
		}
	}
	//+>
	
	this.Sort2Strings = function (String1,String2)
	{
		//Ret Code
		//0: String1 ist kleiner
		//1: String2 ist kleiner
		//2: String sind gleich
		String1=this.clearTags(String1);
		String2=this.clearTags(String2);
		
		String1=String1.toLowerCase();
		String2=String2.toLowerCase();
		
		//Wenn beide String gleich sind, dann sofort Code 2 zur�ckgeben.
		if(String1==String2)
		{
			return 2;
		}
		
		//So lange weiter z�hlen, so lange die Chars gleich sind, oder einer der beiden String keinen  Char mehr hat.
		k=0;
		while(String1.charCodeAt(k)==String2.charCodeAt(k) && !isNaN(String1.charCodeAt(k)) && !isNaN(String1.charCodeAt(k)))
		{
			k++
		}
		
		//Wenn String 1 zu Ende ist, oder der Char von String1 an Pos i kleiner ist als der CHar von String2 an Pos i, dann ist String1 kleiner
		if(isNaN(String1.charCodeAt(k)) || String1.charCodeAt(k)<String2.charCodeAt(k))
		{
			return 0;
		}
		else
		{
			//String 2 ist kleiner
			return 1;
		}
		
		
	}
	
	this.clearTags = function (sString)
	{
		bIsInnerTag=false;
		sFinalString="";
		for (iChar=0;iChar<sString.length;iChar++)
		{
			cCurChar=sString.charAt(iChar);
			
			if(bIsInnerTag)
			{
				if(cCurChar=='>')
				{
					bIsInnerTag=false;
				}
			}
			else
			{
				if(cCurChar=='<')
				{
					bIsInnerTag=true;
				}
				else
				{
					sFinalString+=cCurChar;
				}
			}
		}
		return sFinalString;
	}
	
	
	
}	
