Archive for the “jquery” Category

Plugin jQuery para highlight em células de tabelas

Um dia desses estava no trabalho quando o AI (arquiteto de informação) me apresentou uma tabela cheia de efeitos no hover, você pode ver uma imagem dessa tabela ai embaixo.

Ele me explicou que quando o usuário passasse o mouse pela tabela as células anteriores, das respectivas linha e coluna, seriam marcadas por um background e quando clicasse a célula clicada ficaria marcada.

Como não era urgente e eu nunca tinha visto isso sendo feito com HTML logo fiz cara feia e que não saberia se seria possível fazer de uma forma que tivesse uma boa performance, para não deixar a página lenta por causa de um background bobo.

Logo pedi pra ele me mostrar um exemplo disso funcionando, o primeiro que não era exatamente o que ele queria não era uma tabela, na verdade era, mas feita com divs, ou seja, POG das brabas, eu imediatamente soltei um “rá eu te disse”, mas ele me mostrou outro exemplo que realmente era uma tabela, mas também não era exatamente o que ele queria.

Só para sacanear disse que iria tentar fazer, mas p ele ficar sabendo que o resultado seria horrível.

Alguns dias passaram e lembrei-me da tabela e por algum motivo, junto da lembrança da tabela veio a solução do problema, parei o que estava fazendo para testar a solução abaixo. Lembrando que estamos trabalhando com jQuery.

$(document).ready(function(){
	$('table.tab td').click(function(){
		$(this).parents('table').eq(0).find('td,th').each(function(){ $(this).removeClass('on'); });
		$(this).addClass('on');
		$(this).prevAll().addClass('on');
		var x  = $(this).prevAll().length;
		$(this).parent().prevAll().each(function(){
			$(this).find('>*').eq(x).addClass('on');
		});
		$(this).parents('table').eq(0).find('tr:first-child th').eq(x).addClass('on');
	}).hover(function(e){
		$(this).parents('table').eq(0).find('td,th').each(function(){ $(this).removeClass('on2'); });
		$(this).addClass('on2');
		$(this).parent().find('>:first-child').addClass('on2');
		var x  = $(this).prevAll().length;
		$(this).parents('table').eq(0).find('tr:first-child th').eq(x).addClass('on2');
	});
});

Agora vamos entender o que fiz, ah o HTML pra tabela que fiz foi esse aqui.

<table class="tab" border="1">
	<thead>
		<tr>
			<th> </th>
			<th><span>DOM</span> 24/12</th>
			<th><span>SEG</span> 25/12</th>
			<th><span>TER</span> 26/12</th>
			<th><span>QUA</span> 27/12</th>
			<th><span>QUI</span> 28/12</th>
			<th><span>SEX</span> 29/12</th>
			<th><span>SAB</span> 30/12</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<th><span>DOM</span> 24/12</th>
			<td><span>1</span></td>
			<td><span>2</span></td>
			<td><span>3</span></td>
			<td><span>4</span></td>
			<td><span>5</span></td>
			<td><span>6</span></td>
			<td><span>7</span></td>
		</tr>
		<tr>
			<th><span>SEG</span> 25/12</th>
			<td><span>1</span></td>
			<td><span>2</span></td>
			<td><span>3</span></td>
			<td><span>4</span></td>
			<td><span>5</span></td>
			<td><span>6</span></td>
			<td><span>7</span></td>
		</tr>
		<tr>
			<th><span>TER</span> 26/12</th>
			<td><span>1</span></td>
			<td><span>2</span></td>
			<td><span>3</span></td>
			<td><span>4</span></td>
			<td><span>5</span></td>
			<td><span>6</span></td>
			<td><span>7</span></td>
		</tr>
		<tr>
			<th><span>QUA</span> 27/12</th>
			<td><span>1</span></td>
			<td><span>2</span></td>
			<td><span>3</span></td>
			<td><span>4</span></td>
			<td><span>5</span></td>
			<td><span>6</span></td>
			<td><span>7</span></td>
		</tr>
		<tr>
			<th><span>QUI</span> 28/12</th>
			<td><span>1</span></td>
			<td><span>2</span></td>
			<td><span>3</span></td>
			<td><span>4</span></td>
			<td><span>5</span></td>
			<td><span>6</span></td>
			<td><span>7</span></td>
		</tr>
		<tr>
			<th><span>SEX</span> 29/12</th>
			<td><span>1</span></td>
			<td><span>2</span></td>
			<td><span>3</span></td>
			<td><span>4</span></td>
			<td><span>5</span></td>
			<td><span>6</span></td>
			<td><span>7</span></td>
		</tr>
		<tr>
			<th><span>SAB</span> 30/12</th>
			<td><span>1</span></td>
			<td><span>2</span></td>
			<td><span>3</span></td>
			<td><span>4</span></td>
			<td><span>5</span></td>
			<td><span>6</span></td>
			<td><span>7</span></td>
		</tr>
	</tbody>
</table>

Primeiramente defini o hook para a tabela com o seletor (‘table.tab td’), e adiciono o evento de hover em todos os TDs.

	$('table.tab td').hover(function(){
		//hover
	});

Feito isso passo a adicionar a classe on2 no TD com hover

		$(this).addClass('on2');

Mas antes de adicionar a classe do hover preciso remover qualquer outra classe on2 que possa ter em um TD, já que quando tirar o mouse de cima do TD tem que voltar ao estado sem background.

		$(this).parents('table').eq(0).find('td,th').each(function(){ $(this).removeClass('on2'); });

Após isso é que começa a brincadeira, primeiro pego todos os TDs, da mesma TR (linha), antes do TD com hover e adiciono a classe on2 também.

		$(this).prevAll().addClass('on2');

Agora veio a parte “mais chatinha” de ser feita. Dentro dessa tabela e dentro desse TR, pegar qual o índice do TD com hover, para poder colocar a classe on2 nos TDs da coluna.

		var x  = $(this).prevAll().length;
		$(this).parent().prevAll().each(function(){
			$(this).find('>*').eq(x).addClass('on2');
		});

Feito tudo isso a parte do hover estava pronta e devidamente testada, parti pra parte do click, que vai marcar a célula (TD) da tabela, então adiciono o evento de click adicionando a classe on para marcar.

	$('table.tab td').click(function(){
		$(this).addClass('on');
	});

Mas perae, tem que remover o estilo dos outros TDs que já foram clicados.

		$(this).parents('table').eq(0).find('td,th').each(function(){ $(this).removeClass('on'); });

Agora vamos transformar isso tudo em plugin, para não ter que repetir o código várias vezes, caso alguém ache motivos para fazer isso, ou colocar vários seletores, ou qualquer outro motivo que não seja somente a chamada do plugin.

( function( jQuery ) {
	jQuery.fn.highlightTable = function() {
		this.click(function(){
			jQuery(this).parents('table').eq(0).find('td,th').each(function(){ jQuery(this).removeClass('on'); });
			jQuery(this).addClass('on');
			jQuery(this).prevAll().addClass('on');
			var x  = jQuery(this).prevAll().length;
			jQuery(this).parent().prevAll().each(function(){
				jQuery(this).find('>*').eq(x).addClass('on');
			});
			jQuery(this).parents('table').eq(0).find('tr:first-child th').eq(x).addClass('on');
		}).hover(function(e){
			jQuery(this).parents('table').eq(0).find('td,th').each(function(){ jQuery(this).removeClass('on2'); });
			jQuery(this).addClass('on2');
			jQuery(this).parent().find('>:first-child').addClass('on2');
			var x  = jQuery(this).prevAll().length;
			jQuery(this).parents('table').eq(0).find('tr:first-child th').eq(x).addClass('on2');
		},function(){
			jQuery(this).parents('table').eq(0).find('td,th').each(function(){ jQuery(this).removeClass('on2'); });
		});
	};
} )( jQuery );

$(document).ready(function() {
    $("table.tab td").highlightTable();
});

Ah, mais uma coisinha de última hora, quando der o “blur”,entre aspas que o evento está mais para hover out mas não lembro de um nome para esse evento, da tabela remover a classe on2 para não ter nenhuma marcação de hover

,function(){
	jQuery(this).parents('table').eq(0).find('td,th').each(function(){ jQuery(this).removeClass('on2'); });
}

Bom, é isso espero que seja útil para muitas pessoas, gostou, não gostou, achou um bug ou simplesmente que falar alguma coisa comenta ai embaixo.

Ate a próxima.

Ah, já ia esquecendo o link para o exemplo funcional do plugin de highlight de hover e click em células de tabelas.

problemas com ajax e attr(‘href’) do Jquery

Semana passada eu estava desenvolvendo uma aplicação para um cliente, que fazia um ajax para solicitar uma listagem de produtos, que por sua vez, também pode fazer algumas requisições ajax. Finalizada a funcionalidade, tudo funcionando bonitnho, até ir testar no IE.

Percebo que ao fazer o ajax as proximas requisições não funcionavam. Fui debugar e vejo que as urls, que são relativas, estavam sendo recuperadas pelo attr(‘href’) do Jquery estavam, no javascript, vindo absolutas, com dominio e tudo mais.

Vou procurar uma solução, mas não acho nada satisfatório, somente um monte de reclamções e uma resposta de que não era bug no jquery e sim do IE, ou algo parecido com isso.

Resolvi então, criar uma solução para isso. Já que ao pegar o attr(‘href’) do link estava vindo a url absoluta, a primeira coisa que pensei foi em dar split na url, que não me agradou de cara pois eu não gosto de fazer split em “ambientes não controlados”. Alguém pode inventar de enfiar algum caractere estranho no meio da url e detonar o funcionamento do script.

Então a principio eu teria que fazer algo parecido com o seguinte (só avisando nao testei esse script, se nao estiver funcionando, é algo parecido com isso ;) ):

var myHref = $('a').attr('href');
var pUrl = document.location; // pega url da pagina
pUrl.split("/", 3); // explode de acordo com o limitador '/' e executa ate 3 vezes
var rUrl = pUrl[0]+"//"+pUrl[1]; // monto a url
myHref = myHref.replace(rUrl,'');
// ajax

Cinco linhas de js, para algo extremamente simples. Basicamente não gosto de ter que fazer muito código para coisas muito simples, exceto quando não há jeito. Curioso que sou, fui fazer algumas buscas e descubro duas funções(?) nativas do javascript que eu não conhecia, alias eu conheci umas dez, mas no caso em questão so precisaremos de duas mesmo ;) . São Elas location.protocol e location.host, que são intuitivas, mas vou explicar o que cada uma faz.

A função location.protocol retorna o protocolo da página com o dois pontos (:). Ex.: http:, https:, ftp:, etc.

Já a função location.host, retorna o dominio da pagina. Ex.: www.naoesqueca.com, yahoo.com, google.com, etc.

Logo aquelas 5 linhas de código viraram uma, location.protocol+’//’+location.host. Nesse momento eu fiquei feliz, foi uma boa troca, cinco linhas por uma.

Mas ai apareceu outro problema, eu teria de modificar umas 5 chamadas de $(‘a’).attr(‘href’) para as tres linhas abaixo.


var myHref = $('a').attr('href');
var dPath = location.protocol+'//'+location.host;
return myHref.replace(dPath,'');

Volto a ficar triste, mas ai tenho uma brilhante ideia, vou modificar o .attr(‘href’) do jquery, o que apesar de ser simples de fazer, é algo que acho que não vale o esforço, pq por mais facil que seja são umas 5500 linhas de js que tem uma grande chance de dar problema. Então parto para a segunda ideia, criar um plugin ( ou extensão) para o Jquery.

Faço um find and replace no meu js de $(‘a’).attr(‘href’) para $(‘a’).relativeHref().

E a função fica da seguinte forma:

jQuery.fn.relativeHref = function(){
	var myHref = $(this).attr('href'); //pego o href do elemento selecionado
	var dPath = location.protocol+'//'+location.host; //pego o protocolo e o dominio da pagina e monto a url.
	return myHref.replace(dPath,''); //substituo a url por nada. Caso esteja no href do elemento e retorna o valor final.
};

Então é isso, volto a ficar feliz por resolver o problema (com 3 linhas de js) do IE de retornar o href para o js como se fosse absoluto, mesmo estando relativo.

Ah, só uma coisa, quando crio esses, plugins para o jquery gosto de adicioná-los imediatamente após a contrução do jquery, é certeza que vai ser lido antes da sua chamada, com isso não haverá erros de função inexistente.

jun 23, 2010 Posted Under: extension, javascript, jquery, plugin, praticando   Read More