sexta-feira, 30 de outubro de 2009
Comet no IIS
quinta-feira, 24 de setembro de 2009
10 úteis dicas de usabilidade
Todos concordariam que usabilidade é um aspecto importante de Web Design. Seja trabalhando em um website de portfólio, loja online ou aplicação web, fazer as páginas fáceis e agradáveis para seus visitantes usarem é fundamental. Muitos estudos foram feitos ao passar dos anos sobre vários aspectos da Web e Design de interfaces, e os resultados são valiosos para nos ajudar a melhorar o nosso trabalho. Aqui estão 10 resultados sobre usabilidade que podem ajudar a melhorar a experiência do usuário em seu site.
quarta-feira, 23 de setembro de 2009
Combinando arquivos Javascript e CSS de forma descomplicada
Essa é a proposta do Javascript Combiner: agrupar diversos arquivos respeitando dependências.
A maioria dos sistemas que vi requerem que você indique as dependências entre arquivos em um arquivo separado. Isso me aborreceu por muito tempo. Porque as informações de dependência deve existir fora do arquivo que as utiliza? Porque introduzir um outro arquivo cuja única tarefa é gerenciar dependências? O que eu queria era um equivalente do#includepara C ouimportdo Java, algo que me permita especificar dependências no próprio arquivo fonte e depois combinar todos juntos respeitando a ordem de inclusão. Então no começo do ano passado comecei a trabalhar no Javascript Combiner.
Exemplo de declaração de um arquivo importado
/*requires yahoo.js*/
Veja mais no post original.
terça-feira, 15 de setembro de 2009
SpriteMe! Geração de CSS Sprite como nunca visto
terça-feira, 1 de setembro de 2009
Você acha que sabe desenvolver RIA?

quarta-feira, 26 de agosto de 2009
Como carregar Javascript dinâmicamente
google.load
<script type="text/javascript">
google.load("maps", "2");
google.load("search", "1");
// Call this function when the page has been loaded
function initialize(){
var map = new google.maps.Map2(document.getElementById("map"));
map.setCenter(new google.maps.LatLng(37.4419, -122.1419), 13);
var searchControl = new google.search.SearchControl();
searchControl.addSearcher(new google.search.WebSearch());
searchControl.addSearcher(new google.search.NewsSearch());
searchControl.draw(document.getElementById("searchcontrol"));
}
google.setOnLoadCallback(initialize);
</script>
Javascript Simple Loader
function loadScript(src, callback){
var scriptTag = document.createElement("scriptTag")
scriptTag.type = "text/javascriptTag";
if (scriptTag.readyState) {
//IE
scriptTag.onreadystatechange = function(){
if (scriptTag.readyState == "loaded" ||
scriptTag.readyState == "complete") {
scriptTag.onreadystatechange = null;
setTimeout(function(){
scriptTag.parentNode.removeChild(scriptTag)
}, 1)
callback();
}
};
}
else {
//Others
scriptTag.onload = function(){
setTimeout(function(){
scriptTag.parentNode.removeChild(scriptTag)
}, 1)
callback();
};
}
scriptTag.src = src;
document.getElementsByTagName("head")[0].appendChild(scriptTag);
}O melhor jeito
function loadScript(url, callback){
var script = document.createElement("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}sexta-feira, 7 de agosto de 2009
Tudo sobre Vazamento de Memória Javascript (Memory Leak)
Com o advento da programação Ajax as aplicações deixaram de ser submitadas a cada clique e passaram a permanecer na mesma página por longos períodos de tempo. Nesse tipo de aplicação pequenos problemas com gerenciamento de memória podem formar uma grande dor de cabeça para os usuários da aplicação, que manipulam um sistema lento, e para os programadores, que não sabem o que fazer para resolver o problema. Nesse ponto eu me encontrei semanas atrás, e foi aí que iniciei estudos em busca de soluções para problemas de memory leak. Acabei descubrindo muitas coisas bacanas e portanto aqui escrevo a vocês para publicar tudo que li. Bons estudos!
Memory o que?!
Memory leak é um problema conhecido também por vazamento de memória. Um dos artigos que li foi de Douglas Crockford, guru javascript, e ele resume o conceito dessa forma:
Quando um sistema não gerencia corretamente suas alocações de memória é dito que ele vaza memória. Um vazamento de memória é um bug. Sintomas incluem redução de performance e falhas.
Como ocorre e como Resolver?
O pior caso é (pasmem) no Internet Explorer. Apesar de falar sobre o IE, usaremos esse browser como exemplo, problemas de memórias ocorrem em todos os browsers. No IE o sistema de garbage collector (coletor de lixo) não consegue liberar memória quando referências cíclicas ocorrem. Caso você esteja se perguntando o que é referência cíclica, permita-me exemplificar: quando associamos um evento à um elemento DOM, esse elemento guarda a referência para o evento. Caso esse evento utilize o elemento DOM, em alguma referência, uma estrutura cíclica se forma, da qual não é liberada na memória pelo IE.
Referência Circular

<html>
<head>
<script language="JScript">
var myGlobalObject;
function SetupLeak()
{
// First set up the script scope to element reference
myGlobalObject =
document.getElementById("LeakedDiv");
// Next set up the element to script scope reference
document.getElementById("LeakedDiv").expandoProperty =
myGlobalObject;
}
function BreakLeak()
{
document.getElementById("LeakedDiv").expandoProperty =
null;
}
</script>
</head>
<body onload="SetupLeak()" onunload="BreakLeak()">
<div id="LeakedDiv"></div>
</body>
</html>
O problema
Um exemplo de problema de vazamento por referência circular é facilmente vísivel num pequeno teste criado por Douglas. No primeiro exemplo ele cria 10.000 elementos DOM (span) e os remove em seguida. Se você acompanhar o consumo de memória pelo gerenciador de tarefas do windows verá que o consumo e mantém estável.
function makeSpan(n) {
var s = document.createElement('span');
document.body.appendChild(s);
var t = document.createTextNode(' ' + n);
s.appendChild(t);
return s;
}
function process(n) {
queue.push(makeSpan(n));
var s = queue.shift();
if (s) {
s.parentNode.removeChild(s);
}
}No segundo exemplo ele faz a mesma coisa, porém para cada elemento ele associa um evento, e dentro desse evento utiliza a referência para o elemento. Agora é possível ver o consumo de memória aumentando cada vez mais.
function makeSpan(n) {
var s = document.createElement('span');
document.body.appendChild(s);
var t = document.createTextNode(' ' + n);
s.appendChild(t);
s.onclick = function (e) {
s.style.backgroundColor = 'red';
alert(n);
};
return s;
}Neste momento estou utilizando Internet Explorer 7.0.5730.13 e o erro ainda ocorre. Existe já o registro do bug no suporte da microsoft e eles dizem terem corrigido. Esse erro pode parecer banal para aplicações que usam submit a cada nova página do sistema, mas com o crescente uso de Ajax em aplicações e sites que nunca submitam são realidade.
A soluçãoPor segurança devemos nós resolver esse problema, já que o IE7 vai demorar um pouco para ser abandonado. Segundo a própria Microsoft, closures são os responsáveis por esse vazamento. Douglas propõe uma solução útil, porém não 100% segura:
function purge(d) {
var a = d.attributes, i, l, n;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
n = a[i].name;
if (typeof d[n] === 'function') {
d[n] = null;
}
}
}
a = d.childNodes;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
purge(d.childNodes[i]);
}
}
}Refatorando o exemplo para não gerar mais vazamentos:function process(n) {
queue.push(makeSpan(n));
var s = queue.shift();
if (s) {
purge(s);
s.parentNode.removeChild(s);
}
}Não é 100% segura porque ele mesmo nos avisa que eventos associados através do método attachEvent não serão coletados. Isso porque sua referência não é guardada para acesso do programador. Como não podemos acessar, não podemos remover. A não ser que guardamos a referência, aí podemos manualmente retirar o evento com detachEvent, e tudo fica resolvido (veremos essa solução adiante).
Closures

<html>
<head>
<script language="JScript">
function AttachEvents(element)
{
// This structure causes element to ref ClickEventHandler
element.attachEvent("onclick", ClickEventHandler);
function ClickEventHandler()
{
// This closure refs element
}
}
function SetupLeak()
{
// The leak happens all at once
AttachEvents(document.getElementById("LeakedDiv"));
}
function BreakLeak()
{
}
</script>
</head\>
<body onload="SetupLeak()" onunload="BreakLeak()">
<div id="LeakedDiv"></div>
</body>
</html>
O problema
Outro artigo que li era de um membro da equipe de desenvolvimento do IE, Justin Rogers. Ele resume o problema de vazamentos com closures muito bem:
Com referências circulares normais nós temos 2 objetos concretos segurando um a referência do outro, mas com closures é diferente. Além de fazer referência diretamente, elas são feitas importando informações do escopo da sua função pai. Normalmente uma variável global da função, e parâmetros utilizados quando a função é invocada existem somente pelo ciclo de vida da função em si. Com closures essas variáveis e paramêtros continuam a ter uma referência prolongada enquanto a closures está viva; e como closures podem permaner vivas além do tempo de vida de suas funções pais, o mesmo ocorre com qualquer uma dessas variáveis e paramêtros.A solução
Nesse caso a solução não é tão óbvia assim. Isso porque usamos uma função anônima, não guardamos sua referência e por isso não podemos removê-la. Uma solução proposta por Scott Isaacs em seu blog é guardar a referência da função no elemento para depois poder remover:
function DoThis()
{
var el = document.createElement("div");
el.attachEvent("onclick",DoThis);
window.attachEvent("onunload",Cleanup);
function DoThis()
{
alert("clicked");
}
function Cleanup()
{
el.detachEvent("onclick",DoThis);
window.detachEvent("onunload",Cleanup);
el = null;
}
}
Concluindo
Na realidade um assunto como esse deve ser praticado e estudado constantemente. Acredito não ter escrito um guia completo mas ao menos ter conseguido lhe colocar em um rumo muito melhor de desenvolvimento. Ainda irei abordar mais sobre isso aqui no framebox, mas por enquanto fiquem com essas dicas e alguns links de recursos que utilizei. Forte abraço e até o próximo post.
Referências
quarta-feira, 5 de agosto de 2009
Rotacionando texto com CSS
<div class="example-date">
<span class="day">31</span>
<span class="month">July</span>
<span class="year">2009</span>
</div>
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
segunda-feira, 3 de agosto de 2009
Aprenda o que é Javascript Closures

Muito tempo atrás (o segunto post do blog) eu abordei um tema muito bacana de Javascript: Closures. Alguns dias atrás, encontrei uma outra abordagem do assunto, um tanto quanto informativa e de nome cômico. Morris Johns é o autor de Javascript Closures for Dummies, uma abordagem completa de como dominar esse recurso poderoso de Javascript. Ele começa testando nossos conhecimentos:
Este artigo é destinado a programadores com alguma experiência, e que consegue ler a seguinte função Javascript :function sayHello(name) {
var text = 'Hello ' + name;
var sayAlert = function() { alert(text); }
sayAlert();
}E continua com uma série de exemplos e explicações como este:
function sayAlice() {
var sayAlert = function() { alert(alice); }
// Local variable that ends up within closure
var alice = 'Hello Alice';
return sayAlert;
}Infelizmente o artigo está em inglês. Para os que não simpatizam com o idioma sugiro ainda sim checar o site porque os exemplos explicam tudo.
quinta-feira, 30 de julho de 2009
JSONP e vazamento de memória
Neil Fraser fez um ótimo post em seu blog falando sobre como a técnica de carregamento de javascript dinâmico JSONP pode causar vazamentos de memória nos browsers.
JSONP é o nome da técnica onde criamos um elemento script, definimos o src e inserimos no head da página, ocasionando assim um carregamento dinâmico do seu conteúdo:
//cria elemento script
var script = document.createElement('script');
script.src = 'http://example.com/cgi-bin/jsonp?q=What+is+the+meaning+of+life%3F';
script.id = 'JSONP';
script.type = 'text/javascript';
script.charset = 'utf-8';
//adiciona no head, ocasionando seu carregamento
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
Não entrarei em detalhes, tudo isso funciona muito bem. O problema é que depois de alguns carregamentos o header da sua página pode estar cheio de tags <script>. Uma boa solução seria remover o elemento, assim que seu conteúdo foi extraido:
// Remove velhas tags scripts
var script;
while (script = document.getElementById('JSONP')) {
script.parentNode.removeChild(script);
}
O problema, segundo Neil, é que apesar do browser se livrar do elemento, o objeto dele continua ocupando espaço em memória. Neil então propõe uma solução que diz funcionar perfeitamente:
// Remove velhas tags scripts
var script;
while (script = document.getElementById('JSONP')) {
script.parentNode.removeChild(script);
// Browsers não coletam isso no garbage colletor.
// Então remove tudo para evitar isso
for (var prop in script) {
delete script[prop];
}
}
Remover o elemento e se livrar de suas propriedades. Enfim, a dica está dada. Mais detalhes podem ser vistos no post oficial.