Tenho usado freqüentemente scripts como fat.js e blendtrans.js para criar efeitos de fade em elementos HTML, aqueles que se excuta por um determinado espaço de tempo, permitindo ao usuário ver o elemento mudar de cor ou sumir/aparecer lentamente.
Bem, por curiosidade, fui ver como a coisa era feita nos dois scripts citados acima e me assustei com a simplicidade. É um simples loop que ao invés de executar comandos diretamente usa a função setTimeout, incrementando o timeout a cada volta. Mas os dois scripts tem funções dedicadas a determinada propriedade do elemento: o fat.js muda a cor e o blendtrans.js, a opacidade. Fiquei pensando em uma função polivalente que permitisse fazer mudanças em outras propriedades de um elemento durante um período de tempo e dessas elocubrações nasceu a função loopDelayed.
Antes de mostrar a função, vamos entender o que ela faz. Enviaremos para ela os seguintes parâmetros:
- o ID do elemento a ser modificado
- o valor inicial para o loop
- o valor final para o loop
- intervalo em milisegundos
- o nome da função que irá modificar o elemento
Portanto se fizermos uma chamada assim:
loopDelayed("meu_elemento", 0, 4, 5000, "minha_func");
Isso significa que a função loopDelayed irá executar 5 chamadas à função minha_func com 5 segundos de intervalo entre as chamadas e enviando como parâmetro o elemento (como objeto DOM) e o número equivalente à volta do loop solicitado:
minha_func([Object], 0);// imediatamenteminha_func([Object], 1);// 5 seg. depoisminha_func([Object], 2);// 10 seg. depoisminha_func([Object], 3);// 15 seg. depoisminha_func([Object], 4);// 20 seg. depois
Se houvesse mais do que 5 parâmetros, os excedentes (6º, 7º, 8º, etc.) seriam enviados à minha_func, como os parâmetros 3, 4, 5, etc.
Entendida a idéia, vamos à função:
function loopDelayed(id, ini, end, delay, func) {
_looping = (typeof(id) == "object" ? id : document.getElementById(id)) || null;
var args = loopDelayed.arguments, interval = 0, params = [];
if(args.length < 5 || ini == end || !_looping) return;
if(args.length > 5)
for(var i = 5; i < args.length; i++)
if(/number|boolean|null|string/i.test(typeof(args[i])))
params.push(typeof(args[i]) == "string" ? "'"+args[i]+"'" : args[i]);
params = params.length ? ", "+params.join(", ") : "";
if(ini < end) {
for(var i = ini; i <= end; i++) {
setTimeout(func+"(_looping , "+i+params+");", interval);
interval += delay;
}
} else {
for(var i = ini; i >= end; i = i - 1) {
setTimeout(func+"(_looping, "+i+params+");", interval);
interval += delay;
}
}
}
Bem, não se trata exatamente de "uma função polivalente que muda várias propriedades", mas de uma função que aplica uma dada função a um elemento um determinado número de vezes, com um determinado espaço de tempo entre as chamadas e isso permite criar modificações graduais em qualquer propriedade de um elemento HTML, durante um certo período de tempo.
Aí há ainda uma pulga atrás da orelha: se iniciamos o loop em 0 e vamos até 3, comm 500 milisegundos de delay, a última chamada deveria acontecer exatamente 1500 milisegundos após o disparo, mas sempre demora um pouco mais… mas nada que inviabilize o uso. Vou acabar descobrindo porquê…
Veja aqui uma página com exemplos de como criar funções para interagir com a função loopDelayed.
Bixo, precisei disso hoje uaehaehuae, pena que não li antes.
Dá uma lida no método call() e apply() lá no MDC. Assim não precisará passar o nome da função via string só por causa de ter que enviar parametros pra ela.