Uma das mais “tradicionais” regras de performance de sites é colocar as chamadas para javascripts externos no final do documento HTML, antes do fechamento da tag body
. Mas não são raras as ocasiões em que nós, desenvolvedores web, precisamos inserir códigos que dependem da jQuery no meio do documento (posição que fica antes do indicado para se chamar a própria jQuery). Como proceder?
Antes de continuarmos, é importante saber que existem diferentes sintaxes possíveis para “ativar” o jQuery:
1 2 3 4 5 6 7 |
$(handler) // "handler" é a função a ser vinculada $(document).ready(handler); $().ready(handler) // maneira não recomendada $(document).bind('ready', handler); |
E existe solução para usar .ready() antes de incluir o jQuery?
Sim, existe solução para usar .ready()
antes de incluir o jQuery e, felizmente, a solução é eficaz em todas essas possibilidades apresentadas – e, talvez, até em algumas outras, quem sabe…
Em termos práticos, a solução é:
1 2 3 4 5 6 7 8 9 |
<!-- No <head> --> <script type="text/javascript"> (function(w,d,u){w.readyQ=[];w.bindReadyQ=[];function p(x,y){if(x=="ready"){w.bindReadyQ.push(y);}else{w.readyQ.push(x);}};var a={ready:p,bind:p};w.$=w.jQuery=function(f){if(f===d||f===u){return a}else{p(f)}}})(window,document) </script> <!-- No <body> (imediatamente após a jQuery) --> <script type="text/javascript"> (function($,d){$.each(readyQ,function(i,f){$(f)});$.each(bindReadyQ,function(i,f){$(d).bind("ready",f)})})(jQuery,document) </script> |
Claro que não dá pra entender a lógica olhando script comprimidos. Vejamos o de head
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
(function (w, d, u) { // Define duas queues para os handlers w.readyQ = []; w.bindReadyQ = []; // Insere um handler na queues correta function pushToQ(x, y) { if (x == "ready") { w.bindReadyQ.push(y); } else { w.readyQ.push(x); } } // Define um objeto alias (para uso posterior) var alias = { ready: pushToQ, bind: pushToQ } // Definir a função jQuery "fake" para capturar os handlers w.$ = w.jQuery = function (handler) { if (handler === d || handler === u) { // Coloca na queue $(document).ready(handler), $().ready(handler) // e $(document).bind("ready", handler), retornando um objeto com // os métodos de "alias" para pushToQ return alias; } else { // Queue $(handler) pushToQ(handler); } } })(window, document); |
O script de body
(imediatamente depois da jQuery):
1 2 3 4 5 6 7 8 9 10 11 |
(function ($, doc) { $.each(readyQ, function (index, handler) { $(handler); }); $.each(bindReadyQ, function (index, handler) { $(doc).bind("ready", handler); }); })(jQuery, document); |
Usa-se o $.each()
para associar corretamente todos os handlers na fila para o DOM pronto, mas, porque $(document).bind(“ready”, handler) pode ter sido chamado antes, é preciso dar um bind
, também, da maneira correta.
Exemplo de uso
OK, realmente é um pouco confuso de se entender de primeira, por isso, vejamos este exemplo de como usar o $.ready()
antes da jQuery, seguido de suas respectivas saídas num console.
Exemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<!DOCTYPE html> <html> <head> <title>Example</title> <script>(function(w,d,u){w.readyQ=[];w.bindReadyQ=[];function p(x,y){if(x=="ready"){w.bindReadyQ.push(y);}else{w.readyQ.push(x);}};var a={ready:p,bind:p};w.$=w.jQuery=function(f){if(f===d||f===u){return a}else{p(f)}}})(window,document)</script> </head> <body> <script> $(document).bind("ready", function () { console.log("Examplo D: $(document).bind("ready", handler)"); }); $(document).ready(function () { console.log("Examplo A: $(document).ready(handler)"); }); $().ready(function () { console.log("Examplo B: $().ready(handler)"); }); $(function(){ console.log("Examplo C: $(handler)"); }); </script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script>(function($,d){$.each(readyQ,function(i,f){$(f)});$.each(bindReadyQ,function(i,f){$(d).bind("ready",f)})})(jQuery,document)</script> </body> </html> |
Console:
1 2 3 4 |
Example A: $(document).ready(handler) Example B: $().ready(handler) Example C: $(handler) Example D: $(document).bind("ready", handler) |
Haha! Viu, só? Apesar de, no código, o scripts do “Exemplo D” ter sido o primeiro, na saída do console os exemplos executaram perfeitamente na ordem “A, B, C, D”!
Conclusão
E, com isso, vimos que é perfeitamente possível – e relativamente simples – usarmos chamadas ao .ready()
da jQuery de forma “não ordenada”. Isso faz abrir um leque de possibilidades interessante, pense bem!
Se gostou e/ou tem alguma ideia de como usar isso para melhorar seus scripts, comente e compartilhe! Ajude a desenvolver a web!