/**
* jQuery.colorize
* Copyright (c) 2008-2009 Eric Karimov - ekarim57(at)gmail(dot)com | http://franca.exofire.net/jq/
* Dual licensed under MIT and GPL.
* Date: 9/15/2009
*
* @projectDescription Table colorize using jQuery.
* http://franca.exofire.net/jq/colorize
*
* @author Eric Karimov, contributor Aymeric Augustin
* @version 2.0.0
*/

jQuery.fn.colorize = function(params) {
	options = {
		altColor: '#ebf0f4',
		bgColor: '#fff',
		hoverColor: '#d0dee3',
		hoverClass:'',
		hiliteColor: '#fce6a2',
		hiliteClass:'',
		oneClick: false,
		hover:'row',
		click:'row',
		banColumns: [],
		banRows:[],
		banDataClick:false,
		ignoreHeaders:true,
		nested:false
	};
	jQuery.extend(options, params);

	var colorHandler = {

		addHoverClass: function(){
			this.origColor = this.style.backgroundColor;
			this.style.backgroundColor='';
			jQuery(this).addClass(options.hoverClass);
		},

		addBgHover:function (){
			this.origColor = this.style.backgroundColor;
			this.style.backgroundColor= options.hoverColor;
		},

		removeHoverClass: function(){
			jQuery(this).removeClass(options.hoverClass);
			this.style.backgroundColor=this.origColor;
		},

		removeBgHover: function(){
			  this.style.backgroundColor=this.origColor;
		},

		checkHover: function() {
			if(checkRowBan(this)) return;
			if (!this.onfire) this.hover();
		},

		checkHoverOut: function() {
			if (!this.onfire) this.removeHover();
		},

		highlight: function() {
			if(options.hiliteClass.length>0 || options.hiliteColor != 'none')
			{
				if(checkRowBan(this)) return;
				this.onfire = true;

				if(options.hiliteClass.length>0){
					this.style.backgroundColor='';
					jQuery(this).addClass(options.hiliteClass).removeClass(options.hoverClass);
				}
				else if (options.hiliteColor != 'none') {
			         this.style.backgroundColor= options.hiliteColor;
					if(options.hoverClass.length>0) jQuery(this).removeClass(options.hoverClass);
				}
			}
		},
		stopHighlight: function() {
		    this.onfire = false;
			this.style.backgroundColor = (this.origColor)?this.origColor:'';
			jQuery(this).removeClass(options.hiliteClass).removeClass(options.hoverClass);
		}
	}


	 function  processCells (cells, idx, func) {
		var colCells = getColCells(cells, idx);

		jQuery.each(colCells, function(index, cell2) {
			func.call(cell2);
		});

	    function getColCells (cells, idx) {
			var arr = [];
			for (var i = 0; i < cells.length; i++) {
				if (cells[i].cellIndex == idx)
					arr.push(cells[i]);
			}
			return arr;
		}
	}

	function processAdapter(cells, cell, func) {
		processCells(cells, cell.cellIndex, func);
	}



  var clickHandler = {
	toggleColumnClick : function (cells) {
		var func = (!this.onfire) ? colorHandler.highlight : colorHandler.stopHighlight;
		processAdapter(cells, this, func);
	},

	toggleRowClick: function(cells) {
		row = jQuery(this).parent().get(0);
		if (!row.onfire)
			colorHandler.highlight.call(row);
		else
			colorHandler.stopHighlight.call(row);
	},

     oneClick : function (clicked){
			if(clicked != null) {
				   if (this.isRepeatClick())
				   {
					   this.stopHilite();
					   this.cancel ();
				   }
				   else{
					   this.stopHilite();
					   this.hilite();
				   }
			   }
			   else{
				   this.hilite();
			   }
      },

	   oneColumnClick : function (cells) {
	       var indx = this.cellIndex;
		   function repeat (){
		   	  return (cells.clicked == indx);
		   }
		   Column.handleClick (this, cells, indx, repeat);
	   },

	    oneRowClick  : function (cells) {
	           var row = jQuery(this).parent().get(0);
	           var indx = row.rowIndex;
	           function repeat (){
	                 return (cells.rowClicked == indx);
	            }
	           Row.handleClick (this, cells, row.rowIndex, repeat);
	    },

	    oneColumnRowClick : function (cells) {

				   var indx = this.cellIndex;
				   var row = jQuery(this).parent().get(0);

				   function isRepeatColumn(){
					   return (cells.clicked == indx && cells.rowClicked  == row.rowIndex) ;
				   }

				   function isRepeatRow(){
					   return (cells.rowClicked  == row.rowIndex && this.cellIndex == cells.clicked) ;
				   }

			    Column.handleClick (this, cells,indx, isRepeatColumn);
				Row.handleClick (this, cells,row.rowIndex, isRepeatRow);
           }
	 }

	var Column ={

	      init: function(cell, cells, indx){
			  this.cell = cell;
			  this.cells = cells;
		 	  this.indx = indx;
		  },

		  handleClick: function(cell, cells, indx, func){
              this.init(cell, cells, indx);
              this.isRepeatClick = func;
              clickHandler.oneClick.call (this, cells.clicked);
		  },
	     stopHilite : function(){
	        processCells(this.cells, this.cells.clicked, colorHandler.stopHighlight);
	    },
	    hilite : function(){
	        processAdapter(this.cells, this.cell, colorHandler.highlight);
	        this.cells.clicked  = this.indx;
	    },
	    cancel: function(){
	         this.cells.clicked = null;
	     }
	 }

	var Row ={
	      init: function(cell, cells, indx){
		  		this.cell = cell;
		  		this.cells = cells;
		  		this.indx = indx;
		  },
		  handleClick: function(cell, cells, indx, func){
		        this.init(cell, cells, indx);
		        this.isRepeatClick = func;
		        clickHandler.oneClick.call (this, cells.rowClicked);
		  },
	      stopHilite : function(){
	         colorHandler.stopHighlight.call(clickHandler.tbl.rows[this.cells.rowClicked]); // delete the selected row
	     },
	     hilite : function(){
	          var row = jQuery(this.cell).parent().get(0);
			  if(options.hover=='column')  colorHandler.addBgHover.call (row);
	          colorHandler.highlight.call(row); // the current row is set to select
	          this.cells.rowClicked = this.indx; //the current row is recorded

	     },
	     cancel: function(){
	         this.cells.rowClicked = null;
	     }
	 }

    function isDataCell(){
	     return (this.nodeName == 'TD');
    }

	function checkBan() {
		return (jQuery.inArray(this.cellIndex, options.banColumns) != -1) ;
	}

	function checkRowBan(cell){
			if(options.banRows.length>0){
				var row = jQuery(cell).parent().get(0);
				return jQuery.inArray(row.rowIndex, options.banRows) != -1;
			}
			else
				return false;
	}

	function attachHoverHandler(){
		this.hover = optionsHandler.hover;
		this.removeHover = optionsHandler.removeHover;
	}

	function handleColumnHoverEvents(cell, cells){
		attachHoverHandler.call (cell);
		cell.onmouseover = function() {
			if (checkBan.call(this)) return;
			processAdapter(cells, this, colorHandler.checkHover);
		}
		cell.onmouseout = function() {
			if (checkBan.call(this)) return;
			processAdapter(cells, this, colorHandler.checkHoverOut);
		}
	}

	function handleRowHoverEvents(cell, cells){
		row = jQuery(cell).parent().get(0);
		attachHoverHandler.call (row);
		row.onmouseover = colorHandler.checkHover ;
		row.onmouseout = colorHandler.checkHoverOut ;
	}

	function handleRowColHoverEvents(cell, cells){
		handleRowHoverEvents(cell, cells);
		handleColumnHoverEvents(cell, cells);
	}


	var optionsHandler ={
		setHover: function(){
			if(options.hoverClass.length>0){
				this.hover = colorHandler.addHoverClass;
				this.removeHover = colorHandler.removeHoverClass;
			}
			else{
				this.hover = colorHandler.addBgHover;
				this.removeHover = colorHandler.removeBgHover;
			}
		},

		getRowClick : 	function (){
			if(options.oneClick)
				return clickHandler.oneRowClick;
			else
				return clickHandler.toggleRowClick;
		},

		getColumnClick : 	function (){
			if(options.oneClick)
				return clickHandler.oneColumnClick;
			else
				return clickHandler.toggleColumnClick;
		},
		getRowColClick:function(){
			return clickHandler.oneColumnRowClick;
		}
	}

	var handler = {
		clickFunc : getClickHandler(),
		handleHoverEvents :getHoverHandler()
	};

	function getHoverHandler(){
		if(options.hover=='column')
			return handleColumnHoverEvents;
		else if(options.hover=='cross')
			return handleRowColHoverEvents;
		else
			return handleRowHoverEvents;
	}

	function getClickHandler(){
		if(options.click=='column')
			return optionsHandler.getColumnClick();
		else if(options.click =='cross')
			return optionsHandler.getRowColClick();
		else
			return  optionsHandler.getRowClick();
	}

	return this.each(function() {

		if (options.altColor!='none') {
			var odd, even;
			odd = even =(options.ignoreHeaders)? 'tr:has(td)': 'tr';
			if(options.nested){
				odd  +=  ':nth-child(odd)';
				even += ':nth-child(even)';
			}
			else{
				odd+= ':odd';
				even += ':even';
			}
		     jQuery(this).find(even).css('background', options.bgColor);
		     jQuery(this).find(odd).css('background', options.altColor);
        }

		if(options.columns)
			alert("The 'columns' option is deprecated.\nPlease use the 'click' and 'hover' options instead.");

    	if (jQuery(this).find('thead tr:last th').length > 0)
			 var cells = jQuery(this).find('td, thead tr:last th');
		else
			var cells = jQuery(this).find('td,th');

		cells.clicked = null;

		if (jQuery.inArray('last', options.banColumns) != -1){
			if(this.rows.length>0){
				options.banColumns.push(this.rows[0].cells.length-1);
			}
		}

	    optionsHandler.setHover();
		clickHandler.tbl = this;

		jQuery.each(cells, function(i, cell) {
			 handler.handleHoverEvents (this, cells);
			 $(this).bind("click", function(e) {
				if(checkBan.call(this)) return;
			 	if(options.banDataClick && isDataCell.call(this)) return;
				handler.clickFunc.call(this, cells);
			});
		});
	});
 }

