jQuery().waiting(), deixando o tempo carregamento menos constrangedor

Boa noite pessoal,

A coisa mais chata que vemos acontecer nas mais diversas aplicações WEB espalhadas mundo a fora, é um layout todo bagunçado devido ao tempo de carregamento da página, e ainda no pior dos casos é quando o navegador não terminou de baixar todos os arquivos CSS e/ou JS e o usuário clica em um botão AJAX que resulta um erro ou página em branco…isto é foda horrível, mas muitas vezes não é culpa do desenvolvedor ou designer, mas as vezes a infra do usuário final banda larga da Oi seja muito lenta…mesmo assim isto é algo que tem ser tratado durante o desenvolvimento ou então nas fases de testes.

Para contornarmos esses problemas, podemos usar algumas marotagens disponibilizadas pelos navegadores, como por exemplo o atributo ‘onload‘ do elemento body do HTML padrão. Este cara permite que a gente possa embutir lógicas nele durante o carregamento. Só que nós não podemos simplesmente colocar qualquer coisa ali devido ao fato da ordem dos carregamentos ou então outros Javascripts que podemos ter na nosso documento. Complicado não..?

Bom a ideia que eu proponho com este plugin para o jQuery é algo bem simples e que resolve grande parte deste problema, como o MacGyver falaria, nós basicamente precisamos de uma classe CSS e de um plugin pro jQuery…

O pulo do gato com uma CSS bem aplicada

Esse é o pulo do gato nessa marotagem pessoal é que se vocês olharem outros frameworks Javascript por aí como o ExtJS, jQuery UI, etc. verão que para aplicar o efeito modal eles usam uma série de DIVs sobrepostas e transparentes ou não. Estas DIVs sobrepostas ao conteúdo que ainda está sendo carregado e renderizado fica por baixo delas e naturalmente os elementos cobertos perdem a interatividade com o input do usuário devido a hierarquia do documento, ou seja, você não consegue pegar uma flor que esteja debaixo de um azulejo, a não ser que você tire ele de cima da flor.

Para nós fazermos isso devemos colocar uma DIV logo depois da abertura do elemento BODY do documento, mais ou menos assim:

[html]
<body>
<div></div>

</body>
[/html]

Para que esta DIV se torne diferente das demais, vamos aplicar uma classe CSS nela, logo:

[html]
<body>
<div class=”jquery-waiting-base-container”>Carregando tchê!</div>
…resto da página.
</body>
[/html]

Feito, agora devemos escrever um CSS maroto pra dar o efeito de carregamento que desejamos, logo temos isso:

[html]
.jquery-waiting-base-container {
position: absolute;
left: 0px;
top:0px;
margin:0px;
width: 100%;
height: 100%;
display:block;
z-index: 9999997;
opacity: 0.65;
-moz-opacity: 0.65;
filter: alpha(opacity = 65);
background: black;
background-image: url(“../images/loaders/ajax-loader.gif”);
background-repeat: no-repeat;
background-position:50% 50%;
text-align: center;
overflow: hidden;
font-weight: bold;
color: white;
padding-top: 25%;
}
[/html]

A classe CSS é bem tranquila, nela apenas nos asseguramos de alguns detalhes como:

  • a posição sendo absoluta para manter as suas características;
  • Largura e altura para ocupar todo o espaço da tela do navegador;
  • o z-index com um número bem grande para ficar acima de todos os elementos da página;
  • As configurações para garantir uma transparência que seja compatível em vários navegadores;
  • Um gif para simular o carregamento;

Se executarmos a nossa página neste momento vamos ter alguma coisa assim pessoal:

efeito-carregamento

O gran finale com o jQuery

Bom, se nós não fizermos nada, esta DIV ficará eternamente aí, temos que fazer ela sair somente quando a página tiver sido totalmente carregada. Mas como nós sabemos por meio do Javascript se a página foi totalmente carregada ? Boa pergunta..eu não sei, mas eu sei que o jQuery tem um método que já faz esse tratamento, o jQuery.ready. Este método é capaz de fazer a mesma associação dos binds, ou seja, podemos fazer pilhas de execuções de maneira fácil.

Voltando ao nosso caso, vamos aplicar um efeito de esmaecimento usando o método jQuery.fadeOut(). Este método irá fazer com que a nossa DIV marota vá esmaecendo até sumir totalmente e deixar todo o conteúdo acessível a interações com o usuário.

[javascript]
$(document).ready(function(){
$(“.jquery-waiting-base-container”).fadeOut(“slow”);
});
[/javascript]

Simples não ?! Agora vamos deixar esta solução mais robusta e elegante…vamos criar um plugin específico para essa lógica. Mas porque ? Pode parecer perda de tempo mas se pensarmos na empregabilidade futura, no reuso da solução vocês verão que é uma boa idéia. Vou dar algumas situações que poderiam acontecer:

  • Disparar algum evento quando a DIV terminar de esmaecer;
  • Fazer requisições AJAX enquanto carrega o documento;
  • Ao ir esmaecendo ir trocando a mensagem de carregamento;

Basicamente o nosso plugin jQuery ficaria assim:

[javascript]
(function( $ ){
$.fn.waiting = function(options) {
this.fadeOut(options.modo);
return this;
};
})( jQuery );
[/javascript]

E vamos colocar o nosso plugin pra executar no lugar daquele código anterior lá e passando a velocidade da saída do fadeOut:

[javascript]
$(document).ready(function(){
$(“.jquery-waiting-base-container”).waiting({modo:”slow”});
});
[/javascript]

A nossa versão final ficou assim malandragem:

[javascript]
(function($) {
$.fn.waiting = function(options) {
options = $.extend({modo: ‘normal’}, options);
this.fadeOut(options.modo);
return this;
};
})(jQuery);
[/javascript]

Download

Por enquanto é só, qualquer dúvida, crítica, etc. usem a área de comentários.
Abraços.