2011-11-20 14 views
8

Sto provando a caricare l'API Skyscanner in modo dinamico ma non sembra funzionare. Ho provato ogni possibile modo di pensare e tutto ciò che accade è che il contenuto scompare.Provare a caricare dinamicamente un'API e un file JS

Ho provato console.log che non dà risultati; Ho provato elementi dagli strumenti degli sviluppatori di Chrome e mentre tutti i css del contenuto rimangono gli stessi, tuttavia il contenuto scompare (ho pensato che potesse aggiungere display: nessuno nel tipo html/body). Ho provato tutti i trucchi asincroni di Google, ancora una volta una pagina vuota. Ho provato tutti i plugin js per il caricamento asincrono con gli stessi risultati.

La documentazione dell'API di Skyscanner è scadente e mentre offrono una richiamata non funziona come fa la richiamata dell'API di Google.

Esempio: http://jsfiddle.net/7TWYC/

Esempio con carico API nella sezione head: http://jsfiddle.net/s2HkR/

Così come posso caricare l'API sul pulsante di scatto o asincrono? Senza il file nella sezione HEAD. Se esiste un modo per impedire a document.write di rendere la pagina vuota o in un altro modo. Non mi dispiacerebbe usare plain js, jQuery o PHP.

EDIT:

Ho impostato una taglia di 250 ontop del 50 ho avuto in precedenza.

Orlando Leite ha risposto a un'idea molto precisa su come rendere questo asynch api carico anche se alcune funzioni non funzionano come la selezione delle date e non sono in grado di impostare lo stile.

Sto cercando una risposta di cui sarò in grado di utilizzare tutte le funzionalità in modo che funzioni come funzionerebbe se si caricasse sul carico.

Ecco il violino aggiornato da Orlando: http://jsfiddle.net/cxysA/12/

-

EDIT 2 ON Gijs RISPOSTA:

Gijs menzionato due link sul sovrascrivere document.write. Sembra un'idea fantastica, ma penso che non sia possibile realizzare ciò che sto provando.

ho usato modo Resig Giovanni per evitare document.write dei quali può essere trovato qui: http://ejohn.org/blog/xhtml-documentwrite-and-adsense/

Quando ho usato questo metodo, io caricare l'API con successo ma il file non viene caricato snippets.js affatto.

Fiddle: http://jsfiddle.net/9HX7N/

+0

Sembra che lo script carica un altro script, in base alla chiave API. È strano, quando clicco sul pulsante, pulisce il tag del corpo o.O –

+0

questa è la mia domanda – jQuerybeast

+0

Mi piace che il tuo handle sia jQuerybeast e il tuo rappresentante sia 666. Il tuo lavoro qui è finito. – ThinkingStiff

risposta

3

Per i casi problematici come questo, si può solo sovrascrivere document.write. Hacky come l'inferno, ma funziona e si arriva a decidere dove tutto il contenuto va. Vedi ad es. this blogpost by John Resig. Questo ignora IE, ma con un po 'di lavoro il trucco funziona anche in IE, vedi ad es. this blogpost.

Quindi, suggerirei di sovrascrivere document.write con la tua funzione, eseguire il batch dell'output dove necessario e metterlo dove preferisci (ad esempio in un div nella parte inferiore del tuo <body> '). Questo dovrebbe impedire allo script di mettere a fuoco il contenuto della tua pagina.

Modifica: OK, quindi ho avuto/voluto del tempo per esaminare questo script. Per riferimento futuro, utilizzare qualcosa come http://jsbeautifier.org/ per indagare su script di terze parti. Molto più facile da leggere in questo modo. Fortunatamente, non vi è quasi nessuna offuscazione/minimizzazione, e quindi avete un supplemento per la loro documentazione API (che non ero in grado di trovare, a proposito - ho trovato solo "wizard di codice", di cui non avevo alcun interesse) .

Ecco un esempio quasi-lavoro: http://jsfiddle.net/a8q2s/1/

Ecco i passi che ho preso:

  1. esclusione document.write. Questo deve accadere prima dello si carica lo script iniziale. La tua funzione di sostituzione dovrebbe aggiungere la propria stringa di codice nel DOM. Non chiamare il vecchio document.write, che ti farà solo errori e non farà comunque quello che vuoi. In questo caso sei fortunato perché tutto il contenuto è in una singola chiamata document.write (controlla l'origine dello script iniziale). Se così non fosse, dovresti mettere tutto in ordine fino a quando l'HTML che ti hanno dato era valido e/o eri sicuro che non sarebbe successo nient'altro.
  2. caricare lo script iniziale sul pulsante clic con jQuery $.getScript o equivalente. Passa una funzione di callback (ho usato un riferimento alla funzione con nome per chiarezza, ma puoi farlo in linea se preferisci).
  3. Comunicare a Skyscanner di caricare il modulo.

Modifica # 2: Hah, hanno un'API (skyscanner.loadAndWait) per ottenere una richiamata una volta caricato il loro script. Utilizzando che funziona:

http://jsfiddle.net/a8q2s/3/

(nota: questo sembra ancora utilizzare un ciclo di timeout internamente)

+0

Sto cercando di risolvere questo problema. Seriamente, se riuscirò a capirlo, sarò l'uomo più felice. – jQuerybeast

+0

Credo che questo non sia possibile. Devi caricare l'API, quindi caricare lo snippet e quindi impostare un callback. Se si interrompe document.write prima dello snippet, lo snippet non viene caricato. E viceversa, se si carica prima lo snippet, la pagina diventa vuota. Controlla il mio violino: http://jsfiddle.net/bLmer/ – jQuerybeast

+0

Fondamentalmente sto cercando un modo che consenta nuove document.write ma impedisce di cancellare la pagina. – jQuerybeast

3

Nel file skyrunner.js che stanno utilizzando document.write per rendere la pagina bianca su chiamata di carico posteriore ... Così qui sono alcune conseguenze nello scenario ..

  1. Questo sta facendo una pagina vuota quando si fa clic sul pulsante.
  2. Quindi, rimuove qualsiasi cosa dalla pagina anche 'jQuery.js' è per questo che la richiamata non funziona ... la funzione principale non può essere invocata poiché viene scritta usando jQuery.
  3. E hai perso un tag 'div' di destinazione con id = map (secondo il codice).In realtà questo è l'obiettivo in cui viene caricata la mappa.
  4. Un'altra cosa che ho osservato è che le mappe non sono in realtà un div nel contesto corrente, cioè le mappe api da caricare.

Qui devi seguire l'approccio Old School, Ovvero .. Dovresti includere il tuo file skyrunner.js nella parte superiore del contenuto principale.

Quindi prova a scaricare quel file e includi nel tag head.

Grazie

+0

@ brandon-tilley Grazie per la tua modifica :-) – Exception

+0

Ho notato. La mia domanda NON è quella di usare skyscanner.js nella testa perché a volte è laggoso, causando il ritardo dell'intera webapp. – jQuerybeast

+0

C'è un modo sulla terra (PHP, AJAX) per caricare quello sul clic del pulsante? Qualcosa che potrebbe dire, cancellare tutta la pagina document.write vuota? – jQuerybeast

5

I belive quello che vuoi è che:

function loadSkyscanner() 
{ 
    function loaded() 
    { 
     t.skyscanner.load('snippets', '1', {'nocss' : true}); 

     var snippet = new t.skyscanner.snippets.SearchPanelControl(); 
     snippet.setCurrency('GBP'); 
     snippet.setDeparture('uk'); 
     snippet.draw(document.getElementById('snippet_searchpanel')); 
    } 

    var t = document.getElementById('sky_loader').contentWindow; 
    var head = t.document.getElementsByTagName('head')[0]; 
    var script = document.createElement('script'); 
    script.type = 'text/javascript'; 
    script.onreadystatechange= function() { 
     if(this.readyState == 'complete') loaded(); 
    } 
    script.onload= loaded; 
    script.src= 'http://api.skyscanner.net/api.ashx?key=PUT_HERE_YOUR_SKYSCANNER_API_KEY'; 
    head.appendChild(script); 
} 

$("button").click(function(e) 
{ 
    loadSkyscanner(); 
}); 

E 'carico di Skyscanner nel iframe # sky_loader, dopo chiamata di funzione per creare l'SearchPanelControl caricato. Ma alla fine, snippet disegna nel documento principale. È davvero una soluzione bizzarra, ma funziona.

L'unica limitazione è che è necessario un iframe. Ma puoi nasconderlo usando display:none.

A working example

EDIT

ragazzo Mi dispiace, non l'ho visto. Ora possiamo vedere quanto sia orribile l'API skyscanner. Mette due div per fare il completamento automatico, ma non relativo all'elemento che chiamate per disegnare, ma il documento. Quando uno script viene caricato in un iframe, il documento è il documento iframe.

C'è una soluzione, ma io non lo consiglio, è davvero una soluzione alternativa:

function loadSkyscanner() 
{ 
    var t; 
    this.skyscanner; 
    var iframe = $("<iframe id=\"sky_loader\" src=\"http://fiddle.jshell.net/orlleite/2TqDu/6/show/\"></iframe>"); 

    function realWorkaround() 
    { 
     var tbody = t.document.getElementsByTagName("body")[0]; 
     var body = document.getElementsByTagName("body")[0]; 

     while(tbody.children.length != 0) 
     { 
      var temp = tbody.children[0]; 
      tbody.removeChild(temp); 
      body.appendChild(temp); 
     } 
    } 

    function snippetLoaded() 
    { 
     skyscanner = t.skyscanner; 

     var snippet = new skyscanner.snippets.SearchPanelControl(); 
     snippet.setCurrency('GBP'); 
     snippet.setDeparture('uk'); 
     snippet.draw(document.getElementById('snippet_searchpanel')); 

     setTimeout(realWorkaround, 2000); 
    } 

    var loaded = function() 
    { 
     console.log("loaded"); 
     t = document.getElementById('sky_loader').contentWindow; 

     t.onLoadSnippets(snippetLoaded); 
    } 

    $("body").append(iframe); 
    iframe.load(loaded); 
} 

$("button").click(function(e) 
{ 
    loadSkyscanner(); 
}); 

Caricare un iframe con un altro html che carichi e richiamata quando viene caricato lo snippet. Dopo aver caricato, creare lo snippet dove si desidera e dopo impostare un timeout perché non è possibile sapere quando viene caricato SearchPanelControl. Questo realWorkaround sposta i div di completamento automatico sul documento principale.

You can see a work example here

The iframe loaded is this

EDIT

corretto il bug che avete trovato e aggiornato il link.

il ciclo for è andato e aggiunto un po ', funziona meglio ora.

while(tbody.children.length != 0) 
    { 
     var temp = tbody.children[0]; 
     tbody.removeChild(temp); 
     body.appendChild(temp); 
    } 
+0

Sembra essere quello che stavo cercando anche se si ricorda che il completamento automatico non funziona? Si prega di controllare qui: http://jsfiddle.net/s2HkR/ Questo è il modo predefinito di caricare l'API. Notare il completamento automatico del modulo di ricerca quando si digita una città. Nel tuo esempio di lavoro, questo viene interrotto dal lavoro. La tua idea di farlo è geniale e non mi interessa avere un iframe nascosto. Grazie – jQuerybeast

+0

Fantastico. Beh, non lo consiglio ma penso di non avere un'altra soluzione, no? È per una webapp dashboard e quando il loro server è in ritardo, tutto il dashboard è in ritardo con esso. – jQuerybeast

+0

Okay, è da un'ora che sto cercando di capirlo. Ho pensato che fosse un problema sulla mia pagina ma ho capito che non funziona nemmeno sul tuo esempio. Controlla questo: http://jsfiddle.net/orlleite/cxysA/7/show/ Se guardi il violino da solo, non mostra nulla. (Funziona però: http://fiddle.jshell.net/orlleite/cxysA/7/show/) Grazie ancora – jQuerybeast

Problemi correlati