Marcar e desmarcar checkboxes de um form por javascript

O Danilo fez ontem um post no blog dele sobre como implementar uma solução com jQuery para fazer aquele famoso "marcar todos" onde um checkbox, ao ser clicado, marca ou desmarca todos os checkboxes d eum certo grupo. Bem bacana!

Ai, resolvi aproveitar o gancho e mostrar como pode ser feito isso sem o uso de qualquer biblioteca javascript – ou seja, na mão. O código, claro, é mais extenso do que se tivesse sido feito com alguma biblioteca, mas acho que vale no mínimo como referência!

Segue, abaixo, a implementação com os devidos comentários!

<html>
<head>
<title>Manipulação de checkboxes</title>
<script type="text/javascript">
    window.onload = function() {
        //listener para click do checkbox que marca/desmarca todos
        document.getElementById("checkAll").onclick = function() {
            var form = document.getElementById("myForm"); //formulário
            //percorre todos os checkboxes e seta se está ou não checado, conforme o valor do check mandatório
            var checks = form.getElementsByTagName("input");
            for(var i=0; i<checks.length; i++) {
                var chk = checks[i];
                if(chk.name == "dados[]")
                    chk.checked = this.checked;
            }
        }   
    }
</script>
</head>
<body>
<h1>Meu form</h1>
<form action="#" id="myForm">
    <fieldset>
    <input type="checkbox" name="dados[]" />check 1<br />
    <input type="checkbox" name="dados[]" />check 2<br />
    <input type="checkbox" name="dados[]" />check 3<br />
    <input type="checkbox" name="dados[]" />check 4<br />
    <input type="checkbox" name="dados[]" />check 5<br />
    </fieldset>
    marcar todos: <input type="checkbox" id="checkAll" />
</form>
</body>
</html>

Como criar seletores customizados com jQuery

Dia desses estava estudando os seletores do jQuery e nas pesquisas internérdicas encontrei um post bastante interessante sobre seletores customizados do jQuery. Isso significa que eu posso criar uma regra em javascript para praticamente verificar qualquer coisa dos elementos, e utilizar isso como um selector do jQuery.

Exemplo de uso

Tenho um site com diversos links para a wikipedia e gostaria de aplicar uma classe nos links específicos para a wikipedia. Eu posso colocar a classe para cada link criado, mas vamos supor que eu quero automatizar isso (para aplicar a aregra também em links antigos, por exemplo).

A idéia é eu criar um seletor tipo:

$("a:wikipedia").addClass("wikipedia")

Este seletor não existe no jQuery, então vamos ao objetivo do post: criar um seletor customizado. Para extender (não sei se esta seria a palavra correta) e jQuery e criar um seletor customizado o comando á:

$.expr[":"].nomedoseletor = function(obj){
   //Aqui vão as regras

   //return true inclui o elemento no seletor
   //return false
};

 

No meu caso, a regra é simples: quero que o seletor procure links que contenham em alguma parte de sua href o link "wikipedia.org". Para a regra resolvi utilizar expressões regulares (ER), e o nome do meu seletor é wikipedia.

 

Seletor customizado com jquery

Eis o código:

$.expr[":"].wikipedia = function(obj){
   return obj.href.match(/wikipedia.org/);

};

 

E para chamar o seletor:

$("a:wikipedia").addClass("wikipedia")

 

O Chris já alertou que isso não deve ser muito performático, mas tenho que dizer: pode ser bastante útil. Neste exemplo fiz um seletor simples, mas as regras podem ser mais complexas: selecionar links internos, links para áreas específicas do seu site para aplicar ícones nos links, selecionar imagens pelo tamanho, elementos com ou sem atributos específicos…

Ainda sobre a performance, recomendo utilizar seletores específicos preferencialmente dentro de ID´s, poe exemplo: $("#content a:wikipedia") e não "globalizar" os apenas quando necessário não deve causar TANTOS problemas, né?

Não realizei nenhum teste de performance com os seletores customizados, testei apenas o códido de exemplo, funcionou certinho. Hoje a noite quando eu estiver em casa publico o exemplo* no diretório de exemplos do O Desenvolvedor! 🙂

 

Referência: jQuery howto (recomendo a leitura, vários posts interessantes)

 

* resolvi postar mesmo sem o exemplo devido a simplicidade do código 😉

jQuery UI

Fazem algumas semanas que resolvi utilizar um plugin jQuery (não lembro qual) que utilizava a jQuery UI, um framework com diversas classes prontas para trabalhar com jQUery, uma verdadeira mão na roda!

Como utilizei apenas o plugin pronto, fiz as alterações necessárias mas não havia realmente trabalhando com o framework. Em um projeto recente em que estou trabalhando, fui procurar uma nova forma de fazer uma navegação com accordion (já havia utilizado um plugin eficiente de jQuery anteriormente) e encontrei novamente com o jQuery UI.

Deixei a preguiça de lado e fui verificar como funcionava o jQuery UI, gostei bastante! Apesar de estar apenas iniciando os estudos pareceu bem fácil de utilizar. 

 

jQuery UI CSS Framework

Essa foi a única parte que até o momento eu realmente utilize, um completo framework CSS que permite personalização fácil e vem com muitas, MUITAS classes prontas.

No site do jQuery UI existe um gerador de tema, que permite configurar o seu framework de CSS de forma rápida:

Theme Generator (clique para ampliar)

O gerador de temas gera um framework CSS, que facilita no desenvolvimento com o restante dos utilitários.

Existem diversas classes prontas, para:

  • Bordas arredondadas
  • Overlay ("cobrir" parte da página para destacar determinado conteúdo)
  • Interação (hover, focus, etc.)
  • Exibição de erro
  • Highlight
  • Elemento desabilitado

E mais algumas, que ainda não explorei… 🙂

Falar de CSS me embrou de uma idéia interessante, que instiga algumas boas práticas no desenvlvimento das folhas de estilos: CSS orientado a objetos

 Ah, a parte de 

Interação

Além das facilidades na parte do CSS o framework facilita muito a criação de efeitos de interação.

  • Draggable
  • Droppable
  • Resizable
  • Selectable
  • Sortable

O melhor de tudo é a simplicidade com a qual funciona tudo, por exemplo para criar um elemento que possa ser arrastado, com apenas uma linha isto é feito:

$("#draggable").draggable();

Para os outros comandos a facilidade é a mesma. Isso associado aos diversos estilos dos temas pode acelerar muito o desenvolvimento de interfaces amigáveis!

 

Widgets

Mais facilidades com pouco código, existem algumas ferramentas prontas como:

 

  • Accordion
  • Datepicker
  • Dialog
  • Progressbar
  • Slider
  • Tabs

Testei o accordion, as personalizações possíveis são bacanas! Nos testes que fiz do accordion o funcionamento foi bom em IE (inclusive o 6 – exceto com listas de conteúdo), FF (perfeito) e Chrome (perfeito).

 

Animação

Os comando apra animação com o jQuery são bastante evoluídos e permitem fazer muita coisa, mas para efeitos padrão de interface o framework de user interface facilita com alguns efeitos prontos e bastante customizaveis:

  • Effect
  • Show
  • Hide
  • Toggle
  • Color animation
  • Add class
  • Remove class

 

 

Escrevi o post como uma introdução e estímulo aos usuários da biblioteca jQuery para estudar e utilizar a jQuery UI e facilitar ainda mais a vida!

Usando funções de callback em javascript para sucesso ou erro

Em mais um post sobre funções como parâmetro de outras funções no javascript, vou mostrar como fazer para passar uma série de funções para determinados fins – como em caso de sucesso, em caso de falha, etc…

Onde sempre vemos isso? Frameworks como jQuery e Prototype dão a opção de você escolher uma função de callback para sucesso de um evento, outra para falha, outra para quando se inicia o drag de um elemento na tela, e por aí vai. Isso é feito passando, ao invés de uma função, uma lista de funções. No caso, para poder dar nome a elas, usamos a estrutura de chave/valor (key/value).

O exemplo abaixo explica como a função wrapper() passa 2 parâmetros e duas funções de callback: uma para sucesso, outra para falha. Na primeira chamada, a função de callback chamada será a de sucesso, pois é possível efetuar a rotina. No outro caso, dará erro, então será usada a função de falha.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
<script type="text/javascript">
function wrapper(par1, par2) {
    //verifica se o último parâmetro é uma função para chamá-la;
    //os demais parámetros são repassados para a função

    var lastArgument = arguments[arguments.length-1];
   
    try {
        //Classe Math possue o método max(), que retorna o maior valor entre dois parâmetros
        var sum = Math.max(par1, par2);
        //se não for erro, joga (throw) erro
        if(isNaN(sum))
            throw "not a valid result";
        //se chegar até aqui, é um resultado válido e chama função de sucesso
        lastArgument.onSuccess.call(this, sum);
    } catch(e) {
        //se não, chama a função de erro
        lastArgument.onFailure.call(this, e);
    }
       
   
}

function errorHandler(e) {
    alert("Error: " + e);
}

function myFunction(sum) {
    alert(sum);
}
wrapper(10, 2, {onSuccess: myFunction, onFailure:errorHandler}); //será chamado sucesso
wrapper(10, "a", {onSuccess: myFunction, onFailure:errorHandler}); //será chamado erro
</script>
</head>
<body>

</body>
</html>

 

Usando a prototype – passo 8 – seletores CSS

Muito se fala da facilidade que a jQuery tem em usar a sintaxe de CSS para selecionar elementos do DOM, o que facilita a vida de quem tem forte conhecimento em CSS. Mas poucos sabem que a prototype desde a versão 1.5 (agora está na 1.6.0.3) possui algo semelhante.

Enquanto na jQuery se utiliza o $ para fazer qualquer tipo de seleção (retornando ou um objeto ou uma lista), na prototype se utiliza o $ para selecionar um objeto pelo id dele e a função $$ para selecionar pelas regras do CSS, retornando um objeto Array da prototype (que é um objeto que extende o Array do javascript).

Vamos a um exemplo prático. Tendo o seguinte html:

<div>
   <ul id="main-nav">
      <li>abc</li>
      <li>fgh</li>
   </ul>
   <ul id="nav">
      <li>abc</li>
      <li>fgh</li>
      <li>abc</li>
      <li>fgh</li>
   </ul>
</div>

usando a função $$, você pode tentar retornar os elementos da seguinte forma:

$$("div ul"); //retorna as duas listas
$$("div.container ul"); //não retorna
$$("div ul#main-nav"); //retorna as lista com id main-nav
$$("div ul#main-nav li"); //retorna os itens de lista da lista com id main-nav
$$("div ul#main-nav li:first-child"); //retorna o primeiro item de lista da lista com id main-nav

A versão 1.6 (atual) suporta seletores do CSS3. Veja na documentação oficial quais são eles.

Uma coisa importante é notar que essa implementação é totalmente crossbrowser e que não está ligada a capacidade do browser de interpretar o CSS (ou seja, um browser que não entende seletores do CSS3 consegue pela prototype usar a função $$ igualmente a um browser que interprete o CSS3).

Quer ver esse código funcionando? Veja nesse html.