Tableless

Busca Menu

jQuery: seletores personalizados

Seja o primeiro a comentar por

Um seletor pode ser composto de uma ou mais classes, atributos ou expressões e sua chamada retorna um conjunto de objetos que atendem suas regras.

[cce lang=”javascript”]
// seleciona todos os elementos
$(‘a’)
// seleciona todas as células com a classe projeto
$(‘td.projeto’)
// seleciona todas as imagens com o source “default.jpg”
$(‘img[src=”default.jpg”]’)
// seleciona todas as linhas diretamente filhas de uma table/tbody
$(‘table > tbody > tr’)
// seleciona o primeiro parágrafo da página
$(‘p:first’)
// os elementos com id “projeto-1” e “projeto-2” e todos os elementos com a classe “projeto”
$(‘#projeto-1, #projeto-2, .projeto’)
[/cce]

No entanto, em momentos bem específicos, para evitar a repetição de código, pode ser necessário desenvolver o seu próprio seletor.

As propriedades de um seletor

O cabeçalho básico de um seletor personalizado segue o modelo abaixo:

[cce lang=”javascript”]
$.expr[‘:’].seletor = function(objNode, intStackIndex, arrProperties, arrNodeStack){
// código que deve retornar true para incluir o objeto ou false
};
[/cce]

Através da alta flexibilidade do jQuery estamos estendendo o funcionamento da expressão “:” adicionando uma função própria, desenvolvida sob medida para nosso site ou aplicação web.

Um seletor personalizado nada mais é do que uma função que retorna true para incluir o elemento na lista ou false para não incluí-lo. Essa função pode receber até quatro parâmetros:

  • objNode – o objeto atual (referente ao elemento no DOM, ou seja, NÃO é um clone);
  • intStackIndex – o índice do objeto no conjunto de elementos do seletor. Vamos supor que nosso seletor busque ítens (<li>) de uma lista (<ul>). O primeiro ítem da lista terá o índice 0, o segundo o índice 1 e por aí vai;
  • arrProperties – esse parâmetro contém informações sobre nosso objeto atual no seletor. Só lidaremos mesmo com a posição 3, que representa o parâmetro passado no seletor, mas vejamos o que cada um representa:
    [cce lang=”javascript”]meta = [
    ‘:seletor(argumento)’, // o seletor completo
    ‘seletor’, // apenas o seletor
    ”, // aspas utilizadas nos parâmetros
    ‘argumento’ // parâmetros
    ][/cce]
  • arrNodeStack – o array completo, com todos os objetos capturados pelo nosso seletor.

Nosso primeiro seletor

Hora de colocar a mão na massa. Vamos começar com um seletor bem simples que buscará todos os links da nossa aplicação que possuam “#” como atributo href:

[cce lang=”javascript”]$.expr[‘:’].sem_link = function(obj){
return ($(obj).attr(‘href’) == “#”);
};[/cce]

Reparem que só utilizamos o primeiro parâmetro: o próprio objeto. A função compara o atributo href do elemento com o link “#” e automaticamente retorna true ou false. Como exemplo de uso do nosso seletor vamos fazer com que todos os links com a tralha no href percam sua ação padrão:

[cce lang=”javascript”]$(‘a:sem_link’).click(function(e){
e.preventDefault();
});[/cce]

É claro que a mesma coisa poderia ter sido obtido com o seguinte seletor nativo:

[cce lang=”javascript”]$(‘a[href=”#”]’).click(function(e){
e.preventDefault();
});[/cce]

Esse é o grande lance dos seletores personalizados: saber a hora de usá-los. Dificilmente uma expressão ou um seletor já existente não vai atender à sua necessidade. O que você precisa pesar é se o seletor novo vai facilitar a implementação e manutenção do seu código jQuery. O seletor :sem_link, por exemplo, poderia retornar true também para elementos com o href “javascript:;” ou vazio.

Seletores com parâmetros

Seguindo a onda das tabelas vamos utilizar como exemplo para nossos próximos seletores uma tabela com os principais jogadores do Mengão. O código completo você encontra lá no GitHub.

[cce lang=”html”]

apelidos nome completo jogos gols posição


<tr class=”jogador” data-atividade=”true”>

Leonardo Moura Leonardo da Silva Moura 179 27 Lateral Andrade Jorge Luís Andrade da Silva 160 7 Meia


[/cce]

Nosso objetivo é criar um set de seletores para marcar dados específicos na tabela: jogadores em atividade, jogadores com x ou mais gols, jogadores com x ou mais jogos e jogadores de uma posição específica.

Para selecionar apenas os jogadores em atividade apenas precisamos verificar se o atributo atividade nos dados do elemento (data-atividade, ou $(‘.jogador’).data(‘atividade’)) é verdadeiro.

[cce lang=”javascript”]$.expr[‘:’].em_atividade = function(obj){
return $(obj).data(‘atividade’);
};[/cce]

Já para os próximos filtros precisamos passar um parâmetro: um valor mínimo para a quantidade de gols e jogos ou a posição desejada. Lembra quando falamos lá em cima sobre o array de propriedades dos seletores, mais especificamenteo seu terceiro parâmetro? Ele é a nossa chave para seletores com parâmetros.

[cce lang=”javascript”]$.expr[‘:’].posicao = function(obj, index, meta, stack){
if($(obj).find(‘td:last’).text() == meta[3]) return true;
else return false;
};

$(‘.jogador:posicao(“Goleiro”)’).addClass(‘selected’);

$.expr[‘:’].gols = function(obj, index, meta, stack){
var gols = parseInt($(obj).find(‘td:eq(3)’).text());
if(gols >= meta[3]) return true;
else return false;
};

$(‘.jogador:gols(43)’).addClass(‘selected’);

$.expr[‘:’].jogos = function(obj, index, meta, stack){
var jogos = parseInt($(obj).find(‘td:eq(2)’).text());
if(jogos >= meta[3]) return true;
else return false;
};

$(‘.jogador:jogos(137)’).addClass(‘selected’);[/cce]

No filtro por posições, comparamos o conteúdo da última célula da linha ($(‘td:last’)), que armazena a posição do jogador, com o conteúdo passado como parâmetro (“Goleiro”).

Os filtros de gols e jogos utilizam um outro seletor especial, o :eq. Ele representa a posição do elemento no array de objetos do seletor. Por exemplo, $(‘tr td:eq(2)’) localiza a terceira célula de uma linha (começa em 0!).

Legal, né? As possibilidades realmente são infinitas e a flexibilidade do jQuery impressiona. Mas, assim como os plugins, lembre-se que nem sempre um seletor personalizado vai ser a melhor solução.

Clique aqui para fazer o download do exemplo ou aqui para visualizar o exemplo no navegador.

Publicado no dia