/**
 * VectorGrid jQuery Plugin
 * @author Rubens de Souza Silva (rubens21@gmail.com)
 * @requires jQuery v1.2.4 or later
 * @version 0.1
 * @revision $Rev: 1877 $ 
 * @date $Date: 2008-08-22 09:24:59 -0300 (sex, 22 ago 2008) $
 *
 * Copyright (c) 2008 Vector Internet Bussiness - Belo Hozironte - Brazil
 * www.vectornet.com.br
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 */
 
 
/**
var col = [
		{jsonName : "attname", //Nome do atributo que 'alimentará' essa coluna ÚNICO NÃO OPCIONAL
		headerTitle: "id",	   //Texto que será o título da coluna (Não use links!)
		headerId: "idCollumn", //id da celula do cabeçalho dessa coluna
		headerClass: "cabecalho_tabela",//classe CSS da celula do cabeçalho dessa coluna
		class_col: null,//classe que será colocada na tag col referente a coluna
		id: null,//id que será colocado na tag col referente a coluna
		valueToSort: "exemplo",//valor que será atribuído ao parâmetro de ordenação para recarregar a grid ordenada.
		sortable: true //Indica se essa coluna será ordenável.
		},
		{ ... }
]

refreshCallbackFunction = function(this, type, param)
{
	if(type == '')
	{
		alert('Executado pelo usuário');
	}
	
	if(type == 'sort')
	{
		alert('Executado pelo método de ordenação. Valor de ordenação:' + param);
	}
	
	alert(this.attr('id'));
}

*/

(function($){  
     $.fn.extend({   
         //plugin name - animatemenu  
		vectorGrid:	function(vectorGridOptions)
		{
			//Opções de configuração do sistema, veja mais a cima a definição do array cols
		 	var options_padrao = {
				cols: [],//Array com as informações sobre como cada coluna deverá ser construída (veja documentação acima)
				method: "POST",//Método que será utilizado para as solicitações AJAX
				url: 'json_script.php',//endereço do script que fornecerá o jSon
				params: {},//Parâmetros para serem enviados no momento da solicitação
				classHeader: '',	//Classe da linha do cabeçalho da tabela
				classfoot: '',//classe da linha do rodapé da tabelha
				classLoading: "grid_loading",//classe da tabela enquanto está sendo carregada
				sort: "ASC",//Ordem inicial 
				
				noRecordsText: "Nenhum registro encontrado",//Frase que substitui linhas quando não há registros
				noRecordsClass: "grid_sem_linhas",//Classe da linha (de apenas uma coluna) que é usada para informa que não há registros
		
				classHeaderSorted: "order_coluna_ordenada",//classe da célula do cabeçalho que está ordenando os registros
				classHeaderSortedDesc: "order_coluna_ordenada_desc",//classe da célula do cabeçalho que está ordenando os registros de forma decerscente
				classRowAlt: 'grid_linha_impar',//Classe CSS aplicado as linhas ímpares
				paramToSort: null,
						
				footPreviousText: "Anterior",//Palavra utilizada para o link para páginas anteriores
				footNextText: "Próxima",//Palavra utilizada para o link para próximas páginas
				footFirstText: "Primeira",//Palavra utilizada para o link para a primeira página
				footLastText: "Última",//Palavra utilizada para o link para a última página
		
				footPreviousClass: "grid_pagina_anterior",//Classe utilizada para o link para páginas anteriores
				footNextClass: "grid_pagina_proxima",//Classe utilizada para o link para próximas páginas
				footFirstClass: "grid_pagina_primeira",//Classe utilizada para o link para a primeira página
				footLastClass: "grid_pagina_ultima",//Classe utilizada para o link para a última página
				footJumpersClass: "grid_pagina_jumps",//Classe utilizada para o link para a última página
				footActualPageClass: "grid_pagina_atual",//Classe da página atual
				footNumRegsClass: "grid_qtd_registros", //classe da mensgem que conta a quantidade de registros.
				refreshCallbackFunction: null, //Veja exemplo acima. função executada logo após a atualização da grid. Assinatura: function(this, type, param), this é o objeto jquery da tabela, type é uma string que identifica quem executou o refresh e param é o parâmetro passado para uqem executou a função
				page: 1,//Número da página inicial
				rows: 20,//Quantidade de linhas por páginas
				rowsJump: 3,//Quantidade de páginas listadas para frente e para tráz 
				rowsOptions: [10, 20, 30]//opções de exibição de linhas por páginas.
			};
		
			//Cria o objeto VectorGrid, criando o cabeçado
			this.each(function(){
				
				this.vectorGridOptions = $.extend(options_padrao, vectorGridOptions);
			  	this.vectorGridOptions.instancia_id = this.id;
				//cria o Thead e insere uma linha e coloca a classe determinada para a linha de cabeçalho
				//var header = this.createTHead().insertRow(0);
				var tags_coluna = "";
				var header = "<thead><tr class=\""+this.vectorGridOptions.classHeader+"\">";
		
		
				//Cria uma coluna para cara uma defenida na configuração da VectorGrid
				for(i=0; i < this.vectorGridOptions.cols.length ; i++)
				{
				
					html_th = "<th";
					//cria os atributos ID e classe somente se eles forem setados, senão eles recebem o valor 'undefined'
					if(this.vectorGridOptions.cols[i].headerId)
						html_th += ' id="' + this.vectorGridOptions.cols[i].headerId + '"';
					if(this.vectorGridOptions.cols[i].headerClass)
						html_th += ' class="' + this.vectorGridOptions.cols[i].headerClass + '"';
						
					html_th += ">";
					//caso seja uma coluna ordenável, cria um link para ordena a tabela
					if(this.vectorGridOptions.cols[i].headerTitle)
					{
						if(this.vectorGridOptions.cols[i].sortable)
							html_th += '<a href="javaScript://" onclick="$(\'#'+ this.id +'\').vectorGridsort(\'' + this.vectorGridOptions.cols[i].valueToSort + '\');">' + this.vectorGridOptions.cols[i].headerTitle + '</a>';
						else
							html_th += this.vectorGridOptions.cols[i].headerTitle;
					}
					
					tags_coluna += "<colgroup";
					
					if(this.vectorGridOptions.cols[i].class_col)
						tags_coluna += ' class="' + this.vectorGridOptions.cols[i].class_col + '"';
					
					if(this.vectorGridOptions.cols[i].id)
						tags_coluna += ' id="' + this.vectorGridOptions.cols[i].id + '"';
					tags_coluna += " ></colgroup>"; 
					header += html_th + "</th>";
				}
				header += "</tr></thead>";
		
				//tags_coluna += header;
				$(this).html(tags_coluna + header);
				$(this).refresh('start');
		  	});
	

		},
		loadVectorGrid: function()
		{
			this.find('tbody').fadeTo("fast", 0.2);
			this.addClass(this.attr('vectorGridOptions').classLoading);
			var ParametrosGet = $.extend(this.attr('vectorGridOptions').params, 
				{
					'vectorGridOptions[rows]':			this.attr('vectorGridOptions').rows,
					'vectorGridOptions[page]': 			this.attr('vectorGridOptions').page,
					'vectorGridOptions[sort]': 			this.attr('vectorGridOptions').sort,
					'vectorGridOptions[paramToSort]': 	(this.attr('vectorGridOptions').paramToSort == null) ? '' : this.attr('vectorGridOptions').paramToSort
				}
			);
			$.ajax({
				url: this.attr('vectorGridOptions').url,
				data: ParametrosGet,
				type: this.attr('vectorGridOptions').method,
				instancia_id: this.attr('vectorGridOptions').instancia_id,
				async: false,
				dataType: "json",
				error: function(XMLHttpRequest, textStatus, errorThrown){alert(textStatus);},
				success: function(data, textStatus, XMLHttpRequest)
				{
					var Grid = $('#' + this.instancia_id);
					
					Grid.attr('vectorGridOptions').json = data;//armazena o Json recebido em um atributo do options
					Grid.clear();
					Grid.attr('vectorGridOptions').page = data.page;
					var TBody = document.createElement('tbody');//cria um Tbody na tabela
					document.getElementById(this.instancia_id).appendChild(TBody);
					if(Grid.attr('vectorGridOptions').json.totalRecords > 0)
						Grid.find("tbody").html(Grid.attr('vectorGridOptions').json.html);
					else
						Grid.find("tbody").html("<tr class=\"" + Grid.attr('vectorGridOptions').noRecordsClass + "\"><td colspan=\"" + Grid.attr('vectorGridOptions').cols.length +"\">" + Grid.attr('vectorGridOptions').noRecordsText + "</td></tr>");
					Grid.find('tbody').fadeTo("fast", 1.0);
					Grid.removeClass(Grid.attr('vectorGridOptions').classLoading);
				}
			});
		},
		jumpToPage: function(page)
		{
			if(page <= this.attr('vectorGridOptions').json.totalPages)
			{
				this.attr('vectorGridOptions').page = page;
				$(this).refresh('jump', page);
			}
		},
	//Método para ordenação das linhas por determinada coluna
	//ATENÇÃO: o plug não não ordena o Json para redesenhar a tabela! O Plug altera o parâmtro sort e recarrega o jSOn
		vectorGridsort: function(valueToSort)
		{
			if(this.attr('vectorGridOptions').paramToSort == valueToSort)//verifica se a tabela já estava ordenada por essa coluna, pois necessa caso o que muda é de asc para desc ou vice-versa
				this.attr('vectorGridOptions').sort = ((this.attr('vectorGridOptions').sort == "DESC") ? "ASC" : "DESC");
			else
				this.attr('vectorGridOptions').sort = "ASC";
			//altera o marâmetro enviado para o valor da coluna clicada
			this.attr('vectorGridOptions').paramToSort = valueToSort;
			
			var pos = false;//guardará a posição da coluna que foi clicada
			//varre o array de colunas para identificar qual delas possui esse valor para valueToSort e portanto foi a clicada
			for(i=0; i < this.attr('vectorGridOptions').cols.length ; i++)
			{
				//vai removendo de todas a classe de ordenado e ordenado asc
				$($(this).children()[i]).removeClass(this.attr('vectorGridOptions').classHeaderSorted);
				$($(this).children()[i]).removeClass(this.attr('vectorGridOptions').classHeaderSortedDesc);
				if(this.attr('vectorGridOptions').cols[i].valueToSort == valueToSort)
					pos = i;
			}
			//caso tenha identificado a coluna, coloca na coluna a classe que identica que ela foi ordenada
			if(pos !== false)
			{
				if(this.attr('vectorGridOptions').sort == "ASC")//verifica qual o sentido da ordenação para colocar a classe adequada
					$($(this).children()[pos]).addClass(this.attr('vectorGridOptions').classHeaderSorted);
				else
					$($(this).children()[pos]).addClass(this.attr('vectorGridOptions').classHeaderSortedDesc);
			}
			//atualiza a grid
			$(this).refresh('sort', valueToSort);
		},
	
	//limpa a grid removendo todos os Tbodys que possam existir
		clear: function()
		{
			if(this.find('tbody').length)
			{
				this.find('tbody').remove();
				this.find('tfoot').remove();
			}
		},
	
	//Atualiza a grid, limpando o que existir lá, carregando as linhas e montando o rodapé
		refresh: function(type, param)
		{
			this.loadVectorGrid();
			this.mountFoot();
			if(typeof this.attr('vectorGridOptions').refreshCallbackFunction == 'function')
				this.attr('vectorGridOptions').refreshCallbackFunction(this, type, param);
		},
	
		//monta o rodapé baseado no Json carregado e nos parâmetros de configuração
		mountFoot: function()
		{
			//cria o rodapé na tabela
			var foot = "<tr";
			if(this.attr('vectorGridOptions').classfoot)
				foot += " class=\"" + this.attr('vectorGridOptions').classfoot + "\"";
			foot += ">";
			//cria uma célula no rodapé e cria o mesmo número de colunas que existe nas linhas e no cabeçalho
			foot += "<th colspan=\"" + this.attr('vectorGridOptions').cols.length + "\"><span class=\"datagrid_footer_paginacao\"><p>Paginação: </p>";
			
			//Prepara os links que poderão ser utilizados para navegação
			var previous = '<li ' + ((this.attr('vectorGridOptions').footPreviousClass) ? 'class="' + this.attr('vectorGridOptions').footPreviousClass + '"' : '') + '>';
			previous += '<button onclick="$(\'#'+ this.attr('id') +'\').previous();">' + this.attr('vectorGridOptions').footPreviousText + '</button>';
			previous += '</li>';
			
			var next 	 = '<li ' + ((this.attr('vectorGridOptions').footNextClass) ? 'class="' + this.attr('vectorGridOptions').footNextClass + '"' : '') + '>';
			next += '<button onclick="$(\'#'+ this.attr('id') +'\').nextVectorGrid();">' + this.attr('vectorGridOptions').footNextText + '</button>';
			next += '</li>';		
	
			var frist 	= '<li ' + ((this.attr('vectorGridOptions').footFirstClass) ? 'class="' + this.attr('vectorGridOptions').footFirstClass + '"' : '') + '>';
			frist += '<button onclick="$(\'#'+ this.attr('id') +'\').first();">' + this.attr('vectorGridOptions').footFirstText + '</button>';
			frist += '</li>';
			
			var last 	= '<li ' + ((this.attr('vectorGridOptions').footLastClass) ? 'class="' + this.attr('vectorGridOptions').footLastClass + '"' : '') + '>';
			last += '<button onclick="$(\'#'+ this.attr('id') +'\').last();">' + this.attr('vectorGridOptions').footLastText + '</button>';
			last += '</li>';		
	
			//Cria os números das páginas como links para pular diretamente para páginas mais a frente ou mais à tráz.
			var jumps = "";
			for(var i = -this.attr('vectorGridOptions').rowsJump; i <= this.attr('vectorGridOptions').rowsJump; i++)//o parâmetro começa negativo pois o número de páginas de salto pode ser posterior ou anterior a página exibida 
			{		
				if(parseInt(this.attr('vectorGridOptions').page) + i <= this.attr('vectorGridOptions').json.totalPages && parseInt(this.attr('vectorGridOptions').page) + i > 0)
				{
					if(i == 0)//nesse caso essa posição é a página que está sendo exibida, portanto não precisa de link nela.
						jumps += '<li' + ((this.attr('vectorGridOptions').footActualPageClass) ? ' class="' + this.attr('vectorGridOptions').footActualPageClass + '"' : '') + '>' + parseInt(this.attr('vectorGridOptions').page) + '</li>';
					else
						jumps += '<li' + ((this.attr('vectorGridOptions').footJumpersClass) ? ' class="' + this.attr('vectorGridOptions').footJumpersClass + '"' : '') + '><button  onclick="$(\'#'+ this.attr('id') +'\').jumpToPage(' + (parseInt(this.attr('vectorGridOptions').page) + i) + ');">' + (parseInt(this.attr('vectorGridOptions').page) + i) + '</button></li>';
				}
			}
			
			foot += "<ul>";
			if(this.attr('vectorGridOptions').page >  1)//caso não seja primeira página, oferece links para páginas anteriores e para a primeira
				foot += frist + previous;
			
			foot += jumps;//coloca os links para pular para páginas
			
			if(this.attr('vectorGridOptions').page <  this.attr('vectorGridOptions').json.totalPages)//caso não seja última página, ofere links para páginas posteriores e para a última
				foot += next + last;
			
			foot += "</ul>";
			//Cria um select para oferecer os opções de linhas/páginas
			foot += "<select>";
	        //varre as opções do array rowsOptions que define as opções para serem exibidas
			for(var i=0; i < this.attr('vectorGridOptions').rowsOptions.length;i++)
			{
				foot += '<option value="' + this.attr('vectorGridOptions').rowsOptions[i] + '"';//cria um option para a opção
				foot += (this.attr('vectorGridOptions').rows == this.attr('vectorGridOptions').rowsOptions[i]) ? ' selected="selected"':'';
				foot += '>';
				foot += this.attr('vectorGridOptions').rowsOptions[i] + ' registros por página</option>';
	  		}
	  		foot += "</select>";
	  		if(this.attr('vectorGridOptions').cols.length >= 4)//quatro é o número de colunas no footer, se tiver menos de quatro o thead e tbody terá que se adaptar.
	  			var total_cols_span = this.attr('vectorGridOptions').cols.length - 3;//tem que colocar uma a menos que quatro para contar com a própria 4ª coluna 
	  		
	  		foot += "</span><span class=\"datagrid_footer_total_registros\"><p>Total de registros: ";
			foot += this.attr('vectorGridOptions').json.totalRecords + "</p></span>";
			
	
			var domfoot = document.getElementById(this.attr('id')).createTFoot();
			this.find('tfoot').html(foot);
			
	  		//cria a função que irá ser dispara a cada troca do número de registros por pág.
			this.find('tfoot select').change(function () {
		         $(this).parents('table').chngPage(this.value);
		          return true;
	        });
	        
		},
		
		//Altera a quantidade de linhas por páginas
		chngPage: function(size)
		{
			this.attr('vectorGridOptions').rows = size;
			this.refresh('change_rows', size);
			
		},
		
		//Retroce uma página baseada na página atual
		previous: function()
		{
			this.attr('vectorGridOptions').page = (this.attr('vectorGridOptions').page > 1) ? this.attr('vectorGridOptions').page - 1 : 1;
			this.refresh('previous');
		},
		
		//Pula para a primeira página
		first: function()
		{
			this.attr('vectorGridOptions').page = 1;
			this.refresh('first');
		},
		
		//Pula para a ultiam página
		last: function()
		{
			this.attr('vectorGridOptions').page = this.attr('vectorGridOptions').json.totalPages;
			this.refresh('last');
		},
		
		//avança uma página baseada na página atual	
		nextVectorGrid: function()
		{
			this.attr('vectorGridOptions').page = (this.attr('vectorGridOptions').page < this.attr('vectorGridOptions').json.totalPages) ? this.attr('vectorGridOptions').page + 1 : this.attr('vectorGridOptions').json.totalPages;
			this.refresh('nextVectorGrid');
		}
	}
	  
)})(jQuery); 

