Archive for the “javascript” Category

jQuery plugin para rolagem suave de âncoras

Fala galera esperta, blz?

Essa semana estava precisando fazer com que uma âncoras. Mas perae, o que são âncoras?

Segundo o Wikipedia:

A predefinição {{âncora}} insere uma âncora em HTML <a></a> numa página, permitindo que se criem ligações para essa parte da página.

http://pt.wikipedia.org/wiki/Predefinição:Âncora

Precisei fazer com que essas âncoras não fosse uma mudança brusca na página, mas que tivessem uma rolagem suave, ou seja, frescura de designer.

Vamos ao código:

$('.anchorList a').smoothScroll();

jQuery.fn.smoothScroll = function(){
	$(this).each(function(){
		var node = $(this);
		$(node).click(function(e){
			var anchor = $(this).attr('href');
			anchor = anchor.split("#");
			anchor = anchor[1];
			var t = 0;
			var found = false;
			var tName = 'a[name='+anchor+']';
			var tId = '#'+anchor;
			if (!!$(tName).length){
				t = $(tName).offset().top;
				if ($(tName).text() == ""){
					t = $(tName).parent().offset().top;
				}
				found = true;
			} else if(!!$(tId).length){
				t = $(tId).offset().top;
				found = true;
			}
			if (found){
				$("body, html").animate({scrollTop: t}, 500);
			}
			//e.preventDefault();
		});
	});
	var lAnchor = location.hash;
	if (lAnchor.length > 0){
		lAnchor = lAnchor.split("#");
		lAnchor = lAnchor[1];
		if (lAnchor.length > 0){
			$("body, html").scrollTop(0);
			var lt = 0;
			var lfound = false;
			var ltName = 'a[name='+lAnchor+']';
			var ltId = '#'+lAnchor;
			if (!!$(ltName).length){
				lt = $(ltName).offset().top;
				if ($(ltName).text() == ""){
					lt = $(ltName).parent().offset().top;
				}
				lfound = true;
			} else if(!!$(ltId).length){
				lt = $(ltId).offset().top;
				lfound = true;
			}
			if (lfound){
				$("body, html").animate({scrollTop: lt}, 500);
			}
		}
	}
}

O que nós fazemos?

Pegamos todos os links, que nesse caso, são filhos de “.anchorList”, você pode mudar para o que quiser, só um id ou todos os links da página.

Ao clicar no link, explodo o href para pegar só o que tiver depois do tralha, para poder buscar se é a ancora é feita com name em um link, ou se é por id.

Ao verificar qual o gancho da âncora, pego a distancia do topo da página até o elemento, mas caso a âncora seja com name no link e nao tenha conteudo, html ou texto, tenho o cuidado de pegar a medida do elemento pai da âncora, pois no chrome tive uns problemas por não ter conteudo dentro dela.

Feito isso, faço uma verificação para saber se realmente existe a ancora e fazer a rolagem suave.

Olha lá o exemplo do plugin de jQuery para rolagem suave de âncoras.

E como sempre, gostou? não gostou? comentae.

Abraços.

ago 8, 2011 Posted Under: exemplos, javascript, praticando, âncora   Read More

Palestra Engenharia de frontend de alta performance

Minha palestra sobre frontend de alta performance no frontinrio, que aconteceu dia 18/06/2011

jun 20, 2011 Posted Under: css, front in rio, html, javascript, palestra   Read More

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

Rounded corners – Cantos arredondados e como fazê-los

Atualmente os cantos arredondados, são uma grande dor-de-cabeça no desenvolvimento, pois existem vários modos de implementar, com uma, duas ou quatro imagens?, sem imagens?, só com css?, javascript? qual javascript utilizar?, essas questões incomodam a cada vez que é necessário implementar este tipos de borda, que até o presente momento, não tem como serem feitas somente com css, quem sabe um dia, quando o css3 for lançado.

http://www.w3.org/TR/css3-background/#the-border-radius

Mas enquanto esta e muitas outras melhorias no css3 não chegam e não vão chegam nem tão cedo, temos que nos virar com o que temos, então abaixo listarei algumas técnicas que são as mais interessantes de se implementar, cada uma tem suas vantagens e desvantagens.

Cantos arredondados com uma imagem.

A imagem para criar os cantos arredondados é esta aqui embaixo, para o fundo branco e sem borda, o procedimento para criar a imagem é simples, faça um box de cantos arredondados, em seu software de edição de imagens preferido, e corte um dos cantos, faça uma imagem como a abaixo, colocando os cantos de forma que cada um fique na posição oposta ao outro.

Imagem com 4 cantos arredondados

Crie um div para segurar todo o conteúdo do box arredondado e outros dois, um para os cantos de cima e o outro para os cantos de baixo, com mais um dentro de cada um, parece complicado? mas olhe o código abaixo é bem simples…

<div class="wrap-rounded_corners">
    <div class="top_corners">
      <div></div>
    </div>
    conteúdo do box
    <div class="bottom_corners">
      <div></div>
    </div>
  </div><!-- /wrap-rounded_corners -->

E o seguinte css:


/* define o estilo para o box que segura todo o conteúdo
   o overflow hidden é para esconder o que estiver para
   fora da div.wrap-rounded_corners, retire e veja o que acontece
*/
div.wrap-rounded_corners {
        margin: 10px;
        padding: 0 10px;
        background: #0f0;
        overflow: hidden;
}

/* define que todos os divs abaixo terão posição relativa,
    largura de 100% e 9px de altura */
div.wrap-rounded_corners div.top_corners,
div.wrap-rounded_corners div.top_corners div,
div.wrap-rounded_corners div.bottom_corners,
div.wrap-rounded_corners div.bottom_corners div {
        position: relative;
        width: 100%;
        height: 9px;
}

/* define que esta div tem o posicionamento relativo à esquerda negativa em 10px,
    para compensar os 10px de padding da div.wrap-rounded_corners
*/
div.wrap-rounded_corners div.top_corners {
  left: -10px;
  background: transparent url(images/corners.gif) no-repeat -10px -10px;
}

/* define que esta div tem o posicionamento relativo à direita negativa em 30px,
    para compensar os 20px de padding (10px de cada lado) da div.wrap-rounded_corners
    e os 10px de margem negativa da div.top_corners
*/
div.wrap-rounded_corners div.top_corners div {
  right: -30px;
  background: transparent url(images/corners.gif) no-repeat right -10px;
}

/* define que esta div tem o posicionamento relativo à esquerda negativa em 10px,
    para compensar os 10px de padding da div.wrap-rounded_corners
*/
div.wrap-rounded_corners div.bottom_corners {
  left: -10px;
  background: #f00 url(images/corners.gif) no-repeat -10px 0;
}

/* define que esta div tem o posicionamento relativo à direita negativa em 30px,
    para compensar os 20px de padding (10px de cada lado) da div.wrap-rounded_corners
    e os 10px de margem negativa da div.bottom_corners e o overflow hidden, para corrigir
    um bug do IEca que aparentemente não tem explicação para estar ocorrendo,
    retire e veja do que estou falando
*/
div.wrap-rounded_corners div.bottom_corners div {
  right: -30px;
  background: transparent url(images/corners.gif) no-repeat right 0;
  overflow:hidden;
}

Você pode conferir aqui este exemplo funcionando.

Cantos arredondados com duas imagens.

Este tipo de canto arredondado é para um box com largura fixa, o procedimento é simples, é so criar duas imagens, uma com cantos arredondados de cima, e outra com os cantos de baixo, como estas do exemplo abaixo.

Cantos arredondados superiores Cantos arredondados inferiores

Agora, é só criar dois divs, como no exemplo abaixo, um dentro do outro e colocar uma classe em cada um, se quizer caso não queira não tem necessidade, mas é melhor para nao haver problemas, de herança de estilos, com outras divs que possam estar dentro do box:

<div class="top_corners">
  <div class="bottom_corners">
    conteudo do box
  </div><!-- /bottom_corners -->
</div><!-- /top_corners -->

e o seguinte css:


    /*
      Esta div é para segurar todo o conteudo do box de cantos arredondados,
      definindo a largura do box, e colocando a cor de fundo e a imagem dos cantos superiores
    */
      div.top_corners {
        width: 104px;
        background: #2a70ff url(images/rounded_top.gif) no-repeat 0 0;
      }

      /*
        e esta div é para os cantos inferiores, coloca-se a imagem dos cantos
        inferiores com alinhamento ao rodape, esta div não deve ter cor de fundo,
        pois caso tenha irá "esconder" os cantos superiores, e um espaçamento
        para não ter nenhum conteúdo sobre os cantos.
      */
      div.top_corners div.bottom_corners {
        padding: 10px;
        background: transparent url(images/rounded_bottom.gif) no-repeat 0 bottom;
      }

Você pode conferir aqui este exemplo funcionando.

Estes foram dois exemplos simples para dar a direção de como podem ser feitos boxes com cantos arredondados, existem uma grande variedade de possibilidades para fazer os cantos arredondados, é só colocar a cabeça para funcionar que surgirão idéias para resolver o problema.

Agora mostrarei alguns javascripts para fazer os cantos arredondados que você irá ver os prós e contras para ver se é melhor ou pior que fazer com imagens, um ponto a favor é que são “menos trabalhosos” de se implementar e um contra, se o site for “grande e/ou pesado” pode demorar “renderizar” os cantos arredondados.

O primeiro exemplo é o do transcorners, que foi criado por um(a) “cara” ou site chamado Inviz , que o site não está mais no ar, pelo menos não esta pagina, que por acaso eu so consegui depois de sofrer muito em achar para deixar de exemplo, e so me dei esse trabalho porque é um bom script.

Você pode conferir o exemplo funcionado. (em inglês)

Este outro exemplo de javascript foi visto aqui, que por acaso estava fora no momento em que estava escrevendo este post.

Não sei se utilizei todas as configurações disponiveis no exemplo, caso não tenham sido, me avise que coloco todas as propriedades possiveis. Este script é bastante simples de ser implementado e compreendido, ele pode ser conferido aqui.

Esses foram somente alguns exemplos de como colocar em prática os cantos arredondados, caso queira mais algum exemplo vc pode usar um de seus amigos, o Google ou o Yahoo, ou o seu site de buscas preferido, ou este excelente link no CssJuice com uma lista de 25 técnicas diferentes de cantos arredondados.

[]´s e até o próximo post, que pretendo que não demore tanto novamente.