Por que google.load faz com que minha página fique em branco?

103

Bem, isso parece estranho, mas não consigo encontrar uma solução.

Por que diabos este fiddle http://jsfiddle.net/carlesso/PKkFf/ mostra o conteúdo da página e, quando ocorre google.load, a página fica em branco?

Funciona bem se google.load for executado imediatamente, mas atrasá-lo não funciona.

Aqui está o código-fonte da página para você mais preguiçoso (ou mais inteligente):

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Ciao</title>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
  </head>
  <body>
    <h1>Test</h1>
    <div id="quicivanno">
      <p>ciao</p>
    </div>
  </body>
  <script type="text/javascript">
       setTimeout(function() {google.load('visualization', '1.0', {'packages':['corechart']});}, 2000);
  </script>
</html>​
Enrico Carlesso
fonte
1
boa pergunta, aqui está um link: friendlybit.com/js/lazy-loading-asyncronous-javascript (em outras palavras: nenhuma pista ainda)
mindandmedia
Eu notei que document.write ('qualquer coisa') irá limpar o html anterior também, talvez o documento esteja fora de sintonia no contexto de settimeout?
mindandmedia

Respostas:

109

Parece que google.load está adicionando o script à página usando um document.write (), que, se usado após o carregamento da página, limpa o html.

Isso explica com mais detalhes: http://groups.google.com/group/google-ajax-search-api/browse_thread/thread/e07c2606498094e6

Usando uma das ideias, você poderia usar um retorno de chamada para o carregamento para forçá-lo a usar append em vez de doc.write:

setTimeout(function(){google.load('visualization', '1', {'callback':'alert("2 sec wait")', 'packages':['corechart']})}, 2000);

Isso demonstra a espera de 2 segundos com a janela de alerta atrasada

onda
fonte
Não quero que seja exibida uma janela de alerta. Há algum trabalho disponível para fazer isso?
Shoib Mohammed A
4
O alerta era apenas um exemplo de trecho de código. Pode ser qualquer coisa.
onda
Isso é ótimo. A única coisa que mudei para funcionar como esperava foi chamar a função drawChart em vez da função de alerta.
chiurox
Apenas adicionar um parâmetro de retorno de chamada vazio consertou para mim.
Adam B
32

Você apenas tem que definir um retorno de chamada, e ele não limpará a página (talvez as versões anteriores de google.load () limpassem, mas aparentemente as novas não se usadas com retorno de chamada). Aqui está um exemplo simplificado quando estou carregando a biblioteca "google.charts":

if(google) {
    google.load('visualization', '1.0', {
        packages: ['corechart'],
        callback: function() {
            // do stuff, if you wan't - it doesn't matter, because the page isn't blank!
        }
    } )
}

Quando faço isso sem callback (), eu ainda recebo a página em branco também - mas com callback, é corrigido para mim.

Katai
fonte
5

Nota: O que segue é bom para evitar atrasos - é bem na hora. O exemplo pode ser usado geralmente por todos os scripts (precisando dele), mas foi particularmente usado com Greasemonkey. Ele também usa a API de gráficos do Google como exemplo, mas esta solução vai além de outras APIs do Google e pode ser usada em qualquer lugar que você precise esperar o carregamento de um script.

Usar google.load com retorno de chamada não resolveu o problema ao usar Greasemonkey para adicionar um gráfico do Google. No processo (Greasemonkey injetado na página), o nó de script www.google.com/jsapi é adicionado. Depois de adicionar esse elemento para jsapi javascript do Google, o script injetado (ou página) está pronto para usar o comando google.load (que precisa ser carregado no nó adicionado), mas esse script jsapi ainda não foi carregado. Definir um tempo limite funcionou, mas o tempo limite foi apenas uma solução alternativa para a corrida de tempo de carregamento do script jsapi do Google com o script injetado / página. Mover-se onde um script executa o google.load (e possivelmente google.setOnLoadCallback) pode afetar a situação de corrida de tempo. O seguinte oferece uma solução que aguarda o carregamento do elemento google script antes de chamar google.load. Aqui está um exemplo:

// ********* INJECTED SCRIPT *********//
// add element
var gscript = document.createElement('script');
gscript.setAttribute("type", "application/javascript");
gscript.setAttribute("id", "XX-GMPlusGoogle-XX");
document.body.appendChild(gscript);

// event listener setup     
gscript.addEventListener("load",    
    function changeCB(params) {
        gscript.removeEventListener("load", changeCB);
        google.load("visualization", "1", {packages:["corechart"], "callback": 
            function drawChart() {
                var data;
                // set the durationChart data (not in example)
                data = new google.visualization.arrayToDataTable(durationChart);

                var options = {
                    title:"Chart Title",
                    legend: {position:"none"},
                    backgroundColor:"white",
                    colors:["white","Blue"],
                    width: window.innerWidth || document.body.clientWidth,
                    height: window.innerHeight || document.body.clientHeight,
                    vAxis: {title: "Durations", baselineColor: "black", textStyle:{fontSize:12}},
                    hAxis: {title: "Days Since First Instance"},
                    height: ((cnt > 5)? cnt * 50 : 300),
                    isStacked: true
                }; // options


                // put chart into your div element
                var chart = new google.visualization.BarChart(document.getElementById('XX-ChartDiv-XX'));
                chart.draw(data, options);
            } // drawChart function
        }); //packages within google.load & google load
    } // callback changeCB
);

// can use SSL as "https://www.google.com/jsapi";
gscript.src = "http://www.google.com/jsapi";
codeaperatura
fonte
2

Você não precisa definir o tempo limite. Existe outra maneira:

$.getScript("https://www.google.com/jsapi", function () {
     google.load('visualization', '1', { 'callback': 'alert()', 'packages': ['corechart'] });
});

Explicação:

 function () {
     google.load('visualization', '1', { 'callback': 'alert()', 'packages': ['corechart'] });
 }

será executado após o carregamento bem-sucedido do script JSAPI, alert () será executado após o sucesso do google.load ()

Kamil Mierzyński
fonte
2

Eu encontrei esse problema ao tentar mover um google.load(…)dentro de um $(document).ready(…)wrapper jQuery . Mover a google.load(…) parte traseira para fora da função pronta para que ela seja executada imediatamente resolveu o problema.

Por exemplo, isso não funciona:

$(document).ready(function() {
    google.load('visualization', '1', {packages: ['corechart']});
});

Mas isso faz:

google.load('visualization', '1', {packages: ['corechart']});
$(document).ready(function() {
    // …
});
Quinn Comendant
fonte