/*
	name			: ClassBehaviours, the javascript framework based on class-name parsing
	update			: 9.11.9
	author			: Maurice van Creij
	dependencies	: jquery.classbehaviours.js
	info			: http://www.classbehaviours.com/

    This file is part of jQuery.classBehaviours.

    ClassBehaviours is a javascript framework based on class-name parsing.
    Copyright (C) 2008  Maurice van Creij

    ClassBehaviours is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ClassBehaviours is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ClassBehaviours. If not, see http://www.gnu.org/licenses/gpl.html.
*/

	// create the jQuery object if it doesn't already exist
	if(typeof(jQuery)=='undefined') jQuery = function(){};

	// create the root classbehaviours object if it doesn't already exist
	if(typeof(jQuery.classBehaviours)=='undefined') jQuery.classBehaviours = function(){};

	// create the handlers child object if it doesn't already exist
	if(typeof(jQuery.classBehaviours.handlers)=='undefined') jQuery.classBehaviours.handlers = function(){}

	// Makes the headers of a table click/sortable
	jQuery.classBehaviours.handlers.sortByColumn = {
		// properties
		name: 'sortByColumn',
		column: 0,
		// methods
		start: function(node){
			node.onclick = this.sort;
			// apply the default sort direction style
			if(node.className.indexOf('sorted')<0) node.className += ' unSorted';
		},
		forward: function(rowA,rowB){
			var st = jQuery.classBehaviours.handlers.sortByColumn;
			var regTags = new RegExp('<(.|\n)+?>','gi');
			// get the string values from the node
			strA = (rowA.childNodes[st.column].childNodes.length == 0) ? ' ' : rowA.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');
			strB = (rowB.childNodes[st.column].childNodes.length == 0) ? ' ' : rowB.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');
			// check if this can be interpreted as a date
			dateA = Date.parse(strA);
			dateB = Date.parse(strB);
			// get the numeric values from the node
			intA = isNaN(dateA) ? parseInt(strA.replace(',','')) : dateA ;
			intB = isNaN(dateB) ? parseInt(strB.replace(',','')) : dateB ;
			// compare the values for the sort funtion
			if(strA==strB || (navigator.appVersion.indexOf('MSIE 5.0')>-1)){
				// equal
				return 0;
			}else if(isNaN(intA) || isNaN(intB)){
				// compare the textual values
				return (strA<strB) ? 1 : -1 ;
			}else{
				// compare the numeric values
				return intB - intA;
			}
		},
		reverse: function(rowA,rowB){
			var st = jQuery.classBehaviours.handlers.sortByColumn;
			var regTags = new RegExp('<(.|\n)+?>','gi');
			// get the string values from the node
			strA = (rowA.childNodes[st.column].childNodes.length == 0) ? ' ' : rowA.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');
			strB = (rowB.childNodes[st.column].childNodes.length == 0) ? ' ' : rowB.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');
			// check if this can be interpreted as a date
			dateA = Date.parse(strA);
			dateB = Date.parse(strB);
			// get the numeric values from the node
			intA = isNaN(dateA) ? parseInt(strA.replace(',','')) : dateA ;
			intB = isNaN(dateB) ? parseInt(strB.replace(',','')) : dateB ;
			// compare the values for the sort funtion
			if(strA==strB || (navigator.appVersion.indexOf('MSIE 5.0')>-1)){
				// equal
				return 0;
			}else if(isNaN(intA) || isNaN(intB)){
				// compare the textual values
				return (strA>strB) ? 1 : -1 ;
			}else{
				// compare the numeric values
				return intA - intB;
			}
		},
		// events
		sort: function(that){
			var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
			var st = jQuery.classBehaviours.handlers.sortByColumn;
			// defaults
			sortDirection	= 'sortedReverse';
			// find column number
			var objSiblings	= objNode.parentNode.childNodes;
			for(var intA=0; intA<objSiblings.length; intA++){
				// is this a cell of a text-node
				if(objSiblings[intA].nodeName=="TD" || objSiblings[intA].nodeName=="TH"){
					// test if this is the clicked node
					if(objSiblings[intA] == objNode){
						// remember the clicked column
						st.column = intA;
						// toggle the sort direction
						sortDirection = (objSiblings[intA].className.indexOf('sortedReverse')>-1) ? 'sortedForward' : 'sortedReverse' ;
						// adjust the sorting direction classname
						objSiblings[intA].className = objSiblings[intA].className.replace('sortedReverse', sortDirection);
						objSiblings[intA].className = objSiblings[intA].className.replace('sortedForward', sortDirection);
						objSiblings[intA].className = objSiblings[intA].className.replace('unSorted', sortDirection);
					}else{
						// unmark any previously sorted column
						objSiblings[intA].className = objSiblings[intA].className.replace('sortedReverse', 'unSorted');
						objSiblings[intA].className = objSiblings[intA].className.replace('sortedForward', 'unSorted');
					}
				}
			}
			// make a nodelist
			var fullTable		= objNode.parentNode.parentNode.parentNode;
			var sortParent		= fullTable.getElementsByTagName('TBODY')[0];
			var nodeList		= sortParent.childNodes;
			var nodeArray		= new Array();
			// for all table rows
			for(var intA=0; intA<nodeList.length; intA++){
				if(nodeList[intA].nodeName.indexOf('TR')>-1){
					// store it in an array
					nodeArray[nodeArray.length] = nodeList[intA];
				}
			}
			// sort the collection using a helper function
			nodeArray = (sortDirection=='sortedForward') ? nodeArray.sort(st.forward) : nodeArray.sort(st.reverse);
			// clear the unsorted nodelist
			for(var intA=0; intA<nodeList.length; intA++){
				if(nodeList[intA].nodeName.indexOf('TR')>-1){
					sortParent.removeChild(nodeList[intA]);
				}
			}
			// append the sorted nodelist
			for(var intA=0; intA<nodeArray.length; intA++){
				sortParent.appendChild(nodeArray[intA]);
			}
			// reapply the zebra effect
			if(typeof(jQuery.classBehaviours.handlers.zebraTable)!='undefined') jQuery.classBehaviours.handlers.zebraTable.process(fullTable);
		}
	}

	// add this addon to the jQuery object
	if(typeof(jQuery.fn)!='undefined'){
		// extend jQuery with this method
		jQuery.fn.sortByColumn = function(){
			return this.each(
				function(){
					jQuery.classBehaviours.handlers.sortByColumn.start(this);
				}
			);
		};
		// set the event handler for this jQuery method
		$(document).ready(
			function(){
				$(".sortByColumn").sortByColumn();
			}
		);
	}
