Bridge para encapsular o Cross Browser

{ October 5th, 2007 }


cmilfont

Autor: cmilfont

No rastro do meu último post, aproveitando a deixa de detecção otimizada trabalhando junto com o Design Pattern Bridge, aproveitaremos esse conceito para encapsularmos a complexidade de se trabalhar com códigos que tenham que rodar em múltiplos Browsers.

O padrão Bridge define o desacoplamento da abstração (interface) com suas implementações e cada implementação possa variar independentemente.

No código passado vimos isso implementado na função addEvent como segue:

var addEvent = function(el, type, fn) {
    el['on'+type] = fn;
};
if(document.addEventListener) {
    addEvent = function(el, type, fn) {
        el.addEventListener(type, fn, false);
    };
} else if(document.attachEvent) {
    addEvent = function(el, type, fn) {
        el.attachEvent('on'+type, fn);
    };
}

Nesse código o método addEvent é uma forma genérica de adicionar eventos a um elemento DOM na página e encapsula o comportamento implementado pelos Browsers. Essa estratégia pode e deve ser adotada em todo o código que necessite de implementação diferente dependendo do navegador, o chamado Cross Browser.

Cross Browser é a técnica de implementar uma construção que rode em múltiplos navegadores sem diferença perceptível ao usuário. O custo de aplicar essa técnica é diminuir a performance da aplicação como um todo, aumentar a complexidade do código mantido, propiciar um ambiente mais sujeito a falhas de implementação e cair em bugs do próprio navegador (como o Memory-Leak no IE).

Instanciar o objeto XMLHttpRequest é outra situação que possui diferença entre o líder de mercado e os demais navegadores. Aplicando essa técnica, faríamos o seguinte código:

var getXHR = function() {
	this.http = new XMLHttpRequest;
	return this.http;
}
var isIE = !!document.attachEvent;
if(isIE) {
      var msxml = [
        'MSXML2.XMLHTTP.3.0',
        'MSXML2.XMLHTTP',
        'Microsoft.XMLHTTP'
      ];
      for (var i=0, len = msxml.length; i < len; ++i) {
        try {
          http = new ActiveXObject(msxml[i]);
          //cria nova implementação
          getXHR = function() {
            return new ActiveXObject(msxml[i]);
          };
          break;
        }
        catch(e) {}
      }
};

Dei a dica no artigo passado de criar um arquivo para cada implementação de navegador diferente e aplicar o conceito de Lazy Loading para carregar sob demanda.

Posted in Ajax, Design Patterns, JavaScript, Melhores práticas ~ 8 Comments

Adicionar ao Rec6

Detecção otimizada com javascript

{ October 4th, 2007 }


cmilfont

Autor: cmilfont

Uma dica interessante para melhorar a otimização do seu código javascript é realizar a detecção no início da interpretação, para isso montar o código de encapsulamento de acordo com o Browser.

Geralmente quando queremos encapsular uma funcionalidade, por diferença de comportamento dos Browsers, testamos em qual Browser o código está sendo verificado e só então definimos o corpo do código. Algo como:

var addEvent = function(el, type, fn) {
    if(document.addEventListener) {
        el.addEventListener(type, fn, false);
    } else if(document.attachEvent) {
        el.attachEvent('on'+type, fn);
    } else {
        el['on'+type] = fn;
    }
}

Observe que sempre na chamada da function addEvent, testamos em qual Browser o código está sendo executado e então utilizamos a forma apropriada com a qual o Browser trabalha.

Imagine que esse tipo de construção, na medida que vai aumentando a complexidade da aplicação, onera a performance em geral, porque sempre terá que executar operações alheias ao objetivo do negócio, como detectar qual o Browser ou construir a function em tempo de execução.

Uma forma de evitar essa construção é uma estrutura como a que segue:

var addEvent = function(el, type, fn) {
    el['on'+type] = fn;
};
if(document.addEventListener) {
    addEvent = function(el, type, fn) {
        el.addEventListener(type, fn, false);
    };
} else if(document.attachEvent) {
    addEvent = function(el, type, fn) {
        el.attachEvent('on'+type, fn);
    };
}

Um código lido no início da interpretação que redefine o método de acordo com o Browser e deixa disponível para o restante da aplicação, sem a necessidade de testar novamente quando for acionada.

Uma forma interessante seria criar um arquivo “js” para cada implementação de Browser (como um para quem implementa o W3C e outro para o IE), detectar qual o Browser e acionar o arquivo em tempo de execução enquanto estão sendo carregados os recursos da página por exemplo.

Posted in Design Patterns, JavaScript, Melhores práticas ~ 4 Comments

Adicionar ao Rec6