You are currently browsing Masaru Hoshi’s articles.

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: object_id, negativo, __id__

Em Ruby, bem como em outras linguagens que trabalham orientadas a objetos, existe o conceito do ObjectID (ou id de objeto), que nada mais é do que uma identificação única para um objeto instanciado dentro de uma aplicação.

Para ter acesso ao ObjectID em Ruby basta utilizar o método object_id ou __id__. De acordo com a própria documentação da linguagem, o método retorna “um identificador inteiro do objeto. Esse número será retornado em todas as chamadas ao objeto e dois objetos ativos nunca compartilharão o mesmo id.”

Nada demais. Contudo, existe uma peculiaridade nessa definição que às vezes é passada despercebida:

$ ruby -e "class Foo; end; f = Foo.new; p f; puts f.object_id;"
#<Foo:0xb7d921c8>
-605253404

O trecho de código acima cria uma instância da class Foo e imprime o endereçamento da memória onde o objeto foi alocado, juntamento com seu respectivo ObjectID. Observou o número negativo? Ele é a representação inteira da posição da memória do objeto. (0xb7d921c8 <-> -605253404).

Assim, o ObjectID em Ruby é sempre um número inteiro, positivo ou negativo.

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: 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