You are currently browsing the category archive for the ‘JavaScript’ category.

É comum usar checkboxes nas configurações ou na interface de seu site. Ao clicar nela alguma coisa é ligada, ao clicar novamente é desligada. Simples, não?

[X] Fundo colorido

O código para fazer uma opção destas é trivial:

<input id="fundo" onClick="trocaFundo()" type="checkbox">
Fundo colorido

No evento onClick é chamada a função trocaFundo(), que se encarrega de ligar ou desligar as cores no fundo do site. Até aí tudo bem.

O que é chato mesmo, é o usuário ter que mirar precisamente na caixinha do checkbox para poder ligar/desligar a opção. Uma interface mais amigável deveria permitir que o usuário também pudesse clicar no próprio texto de descrição (label) da opção, o “Fundo colorido”. Com mais área para cliques, o uso do site torna-se mais confortável.

Para fazer esse label clicável, basta adicionar o evento onClick nele também. E o que esse evento fará? Você pode colocar ali um “trocaFundo()” também, para ficar igual ao onClick do checkbox.

<input id="fundo" onClick="trocaFundo()" type="checkbox">
<span onClick="trocaFundo()">Fundo colorido</span>

Mas duplicar coisas não é bom. Se você ainda não aprendeu isso, pode deixar que a experiência um dia te ensinará. E se a trocaFundo() recebesse um this para identificar de onde veio o clique, também não funcionaria.

Uma solução mais robusta é fazer com que ao clicar no label, seja feito um clique “virtual” na própria checkbox. Deste modo, para a lógica do seu programa, é como se o usuário tivesse de fato clicado na checkbox.

<input id="fundo" onClick="trocaFundo()" type="checkbox">
<span onClick="document.getElementById('fundo').click()">
Fundo colorido
</span>

Atualização:
Quando escrevi este texto, eu não sabia que a tag LABEL era clicável e que ao clicar nela, o checkbox atrelado a ela era marcado/desmarcado. Muito obrigado a todos que comentaram sobre isso!

Assim sendo, não é preciso essa gambiarra JavaScript que eu sugeri, basta apenas usar a tag correta:

<input id="fundo" onClick="trocaFundo()" type="checkbox">
<label for="fundo">Fundo colorido</label>

O atributo for leva o nome do checkbox ao qual esta label está atrelada. E pronto, só isso. O navegador se encarregará de fazer o resto.

Para obter a data (e hora) atual com o JavaScript, basta instanciar um objeto novo do tipo Date. Este objeto traz vários métodos para obter cada pedaço da data e da hora. Veja um exemplo:

// Obtém a data/hora atual
var data = new Date();

// Guarda cada pedaço em uma variável
var dia     = data.getDate();           // 1-31
var dia_sem = data.getDay();            // 0-6 (zero=domingo)
var mes     = data.getMonth();          // 0-11 (zero=janeiro)
var ano2    = data.getYear();           // 2 dígitos
var ano4    = data.getFullYear();       // 4 dígitos
var hora    = data.getHours();          // 0-23
var min     = data.getMinutes();        // 0-59
var seg     = data.getSeconds();        // 0-59
var mseg    = data.getMilliseconds();   // 0-999
var tz      = data.getTimezoneOffset(); // em minutos

// Formata a data e a hora (note o mês + 1)
var str_data = dia + '/' + (mes+1) + '/' + ano4;
var str_hora = hora + ':' + min + ':' + seg;

// Mostra o resultado
alert('Hoje é ' + str_data + ' às ' + str_hora);

Note a pegadinha do mês, que inicia com zero e não um. Se você não somar 1, janeiro aparecerá como 0 e dezembro como 11. Já o dia do mês vai de 1 a 31, não é preciso somá-lo.

O dia da semana também inicia em zero, representando o domingo, e vai até seis (sábado). Use um array para mostrar o dia da semana por extenso:

var data = new Date();
var dias = new Array(
 'domingo','segunda','terça','quarta','quinta','sexta','sábado'
);

alert('Hoje é ' + dias[data.getDay()]);

A dica é realmente interessante e já me ajudou em outros momentos. Existem momentos que vocês simplesmente deseja fazer aquela “alteração de estilo” no site sem ter que fazer aquele famigerado reload da página. Então, como fazer isso sem usar AJAX?

Pode parecer simples… e é! Basicamente basta chamar a função loadCSS descrita abaixo. A função se baseia apenas no bom e velho DOM e nada mais.

function loadCSS(url) {
    var lnk = document.createElement('link');
    lnk.setAttribute('type', "text/css" );
    lnk.setAttribute('rel', "stylesheet" );
    lnk.setAttribute('href', url );
    document.getElementsByTagName("head").item(0).appendChild(lnk);
}

NOTA: Só testei no IE 7 e no Firefox 2. Se alguém fizer testes em outros browsers e também funcionar avise e comente.

Palavras-chave: DEFER, onLoad, body, carregamento

O problema é clássico. Você tem uma função/método e deseja que ele seja chamado apenas após o carregamento da página pois esse script interage com algum elemento da página que precisa estar completamente renderizado para poder ser manipulado. Vejamos o exemplo a seguir que muda um objeto do tipo input text para apenas leitura:

<html>
<head>
<script type="text/javascript">
function setDisabled() {
  document.getElementById("foo").disabled = true;
}
// Chamada da função
setDisabled();
</script>
</head>
  <body>
    <form method="post">
      <input type="text" name="foo" id="foo" size="20">
      <input type="submit">
    </form>
  </body>
</html>

Inicialmente esse exemplo deveria ser o suficiente para funcionar. Contudo, não podemos considerar que toda a página será carregada de uma única vez. Caso isso aconteça, quando a função for chamada campo o input pode não ter sido carregado. Resultado: você terá um erro de script.

Existem várias saídas para esse tipo de situação. A mais conhecida é incluir a chamada da função pelo método onLoad da tag body ao invés de executá-lo dentro do bloco <script>:

<body onLoad="setDisabled()">

Mas pode não ser suficiente caso você tenha muitos mais funções a serem chamadas. Outra saída seria incluir o bloco <script> no final do código, mas isso foge um pouco do padrão do W3C de incluir todos os <scripts> entre as tags <head>. A saída para esse problema é a utilização de um atributo pouco conhecido da tag <script>, o DEFER.

O DEFER indica que o bloco script só será carregado após todo o carregamento da página. Dessa forma, para que o primeiro exemplo apresentado funcione bastaria alterá-lo para incluir o atributo:

<script type="text/javascript" DEFER="DEFER">
function setDisabled() {
  document.getElementById("foo").disabled = true;
}

// Chamada da função
setDisabled();
</script>

Palavras-chave: DOM, childnode, removechild, excluir itens

Quando começamos a trabalhar com telas javascript, especialmente quando o assunto tem a ver com Ajax e coisas parecidas, é praticamente inevitável o desejo de tornar aquelas páginas HTML estáticas em algo mais interativo, tal como uma aplicação Desktop, sem aquele eventual “reload”. Nesses casos nada melhor que a combinação DOM + Javascript.

Uma caso bem típico de páginas dinâmicas é atualizar uma coleção qualquer, removendo os itens existentes e incluindo novos.

...

<ul id="Foo">
  <li>um</li>
  <li>dois</li>
  <li>tres</li>
  <li>quatro</li>
  <li>cinco</li>
</ul>

<button onclick="recarrega()">recarrega</button>

...

O trecho acima é uma lista de itens de variando de “um” até “cinco”. Neste exemplo fazemos uso de uma lista comum (tag UL), mas poderíamos fazer o mesmo com qualquer outro tipo de elemento DOM.

Ao final existe um botão que chama uma função javascript chamada recarrega(). Vamos dar uma olhada nela:

function recarrega() {
  var p = document.getElementById('Foo');
  var filhos = p.childNodes;
  for( i = filhos.length - 1; i >= 0; i-- ) {
    if( filhos[i].tagName == 'LI' ) {
      p.removeChild( filhos[i] );
    }
  }

  var li = document.createElement('li');
  li.innerHTML = 'seis';
  p.appendChild(li);

  var li = document.createElement('li');
  li.innerHTML = 'sete';
  p.appendChild(li);
}

A função não tem segredo algum. Após recuperar o elemento “pai” da lista (identificado como Foo), buscamos todos os nós abaixo dele, que no nosso caso são os itens da lista (LI), através do atributo childNodes. Esse atributo é uma lista comum e pode ser acessada como se fosse um array.

Dentro do for tomamos cuidado de excluir apenas os elementos de tagName LI. Observe que os itens são recuperados do último para o primeiro. Naturalmente é neste ponto que geralmente as pessoas se perdem.

Se ao invés de iterar sobre a lista na ordem inversa tivéssemos ido em ordem crescente, ao excluir um elemento em uma dada posição, o elemento seguinte assumiria essa posição. No loop seguinte o contador i teria sido incrementado e buscaria o elemento nessa posição, que agora ocupa a posição do item excluído anteriormente.

Quando isso ocorre ou o script pula um elemento a ser excluído ou tenta excluir um item que não existe na lista gerando uma exceção.

Palavras-chave: Javascript, HTML, XHTML, SVG, XML, CDATA, válido, validator

Você mudou suas páginas de HTML para XHTML e agora elas não validam mais por causa do Javascript. O que acontece?

No HTML, todo o conteúdo da tag <script> é considerado texto normal (CDATA – Character Data) e é simplesmente ignorado pelo parser HTML. Nenhum < ou & que for usado no Javascript vai ser considerado início de tag ou de entidade.

Já no XHTML e outros formatos derivados do XML como o SVG, a tag <script> é uma tag como outra qualquer, que pode ter outras tags dentro dela. Seu conteúdo é analisado pelo parser. Por isso qualquer < encontrado no Javascript vai ser interpretado como início de tag e vai dar erro.

Tudo o que você precisa fazer, é dizer ao parser que o seu Javascript é CDATA, ou seja, texto normal que não deve ser interpretado como XML. Tem uma tag especial para isso:

<![CDATA[  ...  ]]>

Tudo o que estiver dentro dessa tag feia vai ser protegido. Então basta colocar todo seu código dentro dela:

<script type="text/javascript">
// <![CDATA[

alert("Funcionou!")

// ]]>
</script>

Note que as tags de início e fim do CDATA foram comentadas, assim evita-se o problema de o Javascript tentar interpretá-las também.

Palavras-chave: DOM, eventos, target

Existem diversas maneiras de registrar um evento. Na forma tradicional, a função deve ter como único parâmetro uma referência ao evento que a invocou. Então, se a função não recebe nada além desse parâmetro, como descobrir quem emitiu o evento?

Imagine que você possua três DIVs e deseje fazer alguma coisa com eles. Vamos associar o evento onClick a uma função chamada mudacor.

...
<div id="um">UM</div>
<div id="dois">DOIS</div>
<div id="tres">TRES</div>

<script type="text/javascript">
document.getElementById('um').onclick = mudacor;
document.getElementById('dois').onclick = mudacor;
document.getElementById('tres').onclick = mudacor;
</script>
...

O padrão W3C define que eventos possuem o atributo target, responsável por indicar a origem do evento. Contudo, o Internet Explorer ignora esse padrão e diz que deve ser usado srcElement. De qualquer maneira, o comportamento é o mesmo. Vejamos como implementar essa função.

O Internet Explorer ignora o parâmetro passado à função. Segundo ele, os eventos pertencem ao objeto window. Assim, antes de recuperar o atributo target (ou srcElement) é preciso verificar se o evento realmente existe.

function mudacor(e) {
    var emissor;
    if(!e) var e = window.event;
    if (e.target) emissor = e.target;
    else if (e.srcElement) emissor = e.srcElement;

    emissor.style.backgroundColor = '#00FF00';
}

Palavras-chave: array, foreach, undefined

Arrays em javascript tem um comportamento curioso. Você pode instanciá-los com um tamanho pré-definido ou incrementá-los / decrementá-los à medida que achar necessário.

Mas, existe uma situação peculiar. Imagine a seguinte situação:

var a = new Array();
a [3] = 'd';

Ao definir a posição 3 como a letra “d” o javascript criou juntamente todas as três posições que a antecedem (0, 1 e 2). Veja o que acontece quando itera sobre esse array utilizando um for comum:

for( i = 0; i < a.length; i++ ) {
    alert( a[i] );
}

O resultado será três registros “undefined” antes da posição 3. Então, como fazer para recuperar apenas os valores que tiverem tiverem sido definidos? A solução é o que, em outras linguagens, chamamos de foreach. Sua utilização faz uso do operador for de uma maneira diferente:

for( i in a ) {
    alert( a[i] );
}

O foreach em Javascript irá navegar em todos os valores do Array a que não forem undefined e atribuirá em i o índice desses valores no array.

Add to Technorati Favorites

Assuntos