2011-11-20 9 views
8

Estoy intentando cargar la API de Skyscanner de forma dinámica, pero parece que no funciona. Intenté de todas las formas posibles en que podía pensar y todo sucede, el contenido desaparece.Intentando cargar una API y un archivo JS de forma dinámica

Probé console.log que no da resultados; Probé elementos de las herramientas de desarrollo de Chrome y aunque toda la CSS del contenido sigue siendo la misma, aún así el contenido desaparece (pensé que podría estar agregando display: ninguno en el tipo html/body). Probé todos los trucos de asynch de Google, una vez más la página en blanco. Probé todos los plugins js para la carga asíncrona con los mismos resultados.

La documentación de la API Skyscanner es deficiente y, aunque ofrecen una devolución de llamada, no funciona como lo hace la devolución de llamada de la API de Google.

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

Ejemplo con la API de carga en sección de la cabeza: http://jsfiddle.net/s2HkR/

Entonces, ¿cómo puedo cargar el API en el botón de clic o asíncrona? Sin el archivo en la sección HEAD. Si hay una forma de evitar que document.write ponga la página en blanco o de otra manera. No me importaría usar js, jQuery o PHP simples.

EDIT:

he fijado una recompensa de 250 sábana de los 50 que tenía anteriormente.

Orlando Leite respondió una idea muy cercana sobre cómo hacer esta carga de la API de sincronización, aunque algunas características no funcionan, como la selección de fechas, y no puedo configurar el estilo.

Estoy buscando una respuesta de la cual podré usar todas las características para que funcione como funcionaría si se carga con carga.

Aquí es el violín actualizada por Orlando: http://jsfiddle.net/cxysA/12/

-

EDIT 2 EN Gijs RESPUESTA:

Gijs mencionó dos enlaces a sobrescribir document.write. Eso suena una idea increíble, pero creo que no es posible lograr lo que estoy intentando.

utilicé manera Resig de John para evitar document.write de los cuales se puede encontrar aquí: http://ejohn.org/blog/xhtml-documentwrite-and-adsense/

Cuando he usado este método, que cargue el API exitosamente pero el archivo snippets.js no se carga en absoluto.

violín: http://jsfiddle.net/9HX7N/

+0

Parece que el script carga otro guión, basado en la clave de API. Es extraño, cuando hago clic en el botón, limpia la etiqueta del cuerpo o.O –

+0

que es mi pregunta – jQuerybeast

+0

Me encanta que su mango sea jQuerybeast y su representante es 666. Su trabajo aquí está hecho. – ThinkingStiff

Respuesta

3

Para los casos problemáticos como éste, sólo puede sobrescribir document.write. Hacky como el infierno, pero funciona y puedes decidir a dónde va todo el contenido. Ver por ej. this blogpost by John Resig. Esto ignora IE, pero con un poco de trabajo, el truco también funciona en IE, ver, por ejemplo. this blogpost.

Por lo tanto, me gustaría sugerir sobrescribir document.write con su propia función, lote hasta la salida, cuando sea necesario, y lo puse en el que desee (por ejemplo. En un div en la parte inferior de su <body> '). Eso debería evitar que el script destruya el contenido de su página.

Editar: Bien, entonces tuve/me tomé un tiempo para mirar este guión. Para referencia futura, use algo como http://jsbeautifier.org/ para investigar scripts de terceros. Mucho más fácil de leer de esa manera. Afortunadamente, apenas hay ofuscación/minificación en absoluto, por lo que tiene un suplemento para su documentación API (que no pude encontrar, por cierto, solo encontré 'asistentes de código', que no me interesaron) .

Aquí es un ejemplo casi-trabajo: http://jsfiddle.net/a8q2s/1/

He aquí los pasos que tomé:

  1. anulación document.write. Esto debe suceder antes de cargar la secuencia de comandos inicial. Su función de reemplazo debería agregar su cadena de código al DOM. No llame al antiguo document.write, que obtendrá errores y no hará lo que quiera de todos modos. En este caso, tiene suerte porque todo el contenido está en una sola llamada document.write (verifique el origen del script inicial). Si este no fuera el caso, tendrías que procesar todo hasta que el HTML que te habían dado fuera válido y/o estuvieras seguro de que no venía nada más.
  2. cargar la secuencia de comandos inicial en el botón hacer clic con jQuery's $.getScript o equivalente. Pasar una función de devolución de llamada (utilicé una referencia de función nombrada para mayor claridad, pero puede encuadrarla si lo prefiere).
  3. Indique a Skyscanner que cargue el módulo.

Edición # 2: Ah, tienen una API (skyscanner.loadAndWait) para obtener una devolución de llamada una vez que su guión se ha cargado. El uso que funciona:

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

(nota: esto todavía parece utilizar un bucle de tiempo de espera internamente)

+0

Estoy tratando de resolver esto. En serio, si seré capaz de resolverlo, seré el hombre más feliz. – jQuerybeast

+0

Creo que esto no es posible. Tienes que cargar la API, luego cargar el fragmento y luego establecer una devolución de llamada. Si detiene document.write antes del fragmento, el fragmento no se carga. Y viceversa, si primero carga el fragmento, la página queda en blanco. Comprueba mi violín: http://jsfiddle.net/bLmer/ – jQuerybeast

+0

Básicamente estoy buscando una forma en la que permita el nuevo document.write pero evite borrar la página. – jQuerybeast

3

En el archivo skyrunner.js que están utilizando document.write para hacer la página en blanco en la llamada carga de vuelta ... Así que aquí están algunas de las consecuencias en el escenario ..

  1. Este está haciendo página en blanco cuando haces clic en el botón.
  2. Por lo tanto, elimina todo, incluso de la página 'jQuery.js', por lo que la devolución de llamada no funciona ... es decir, no se puede invocar la función principal ya que está escrita usando jQuery.
  3. Y ha perdido una etiqueta de destino 'div' con id = map (de acuerdo con el código).En realidad, este es el objetivo donde se carga el mapa.
  4. Otra cosa que he observado es que los mapas no son en realidad un div en el contexto actual, es decir, mapas api para cargar.

Aquí debe ir con el enfoque de la vieja escuela, es decir .. Debe incluir su archivo skyrunner.js en la parte superior del contenido principal.

Así que intente descargar ese archivo e incluirlo en la etiqueta de la cabecera.

Gracias

+0

@ brandon-tilley Gracias por su edición :-) – Exception

+0

Me he dado cuenta. Mi pregunta NO es usar skyscanner.js en la cabeza, porque a veces es lento, causando que toda mi aplicación web se quede rezagada. – jQuerybeast

+0

¿Hay alguna manera en la tierra (PHP, AJAX) para cargar ese botón al hacer clic? ¿Algo que pueda decir, cancelar toda la página de document.write en blanco? – jQuerybeast

5

Me creer lo que quiere es que:

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(); 
}); 

Es skyscanner carga en iframe # sky_loader, después de la llamada a la función para crear el SearchPanelControl cargado. Pero al final, el fragmento se dibuja en el documento principal. Es realmente una solución extraña, pero funciona.

La única restricción es que necesita un iframe. Pero puedes ocultarlo usando display:none.

A working example

EDITAR

chico Lo siento, yo no lo vi. Ahora podemos ver cuán horrible es la API de skyscanner. Coloca dos divs para hacer la autocompletar, pero no en relación con el elemento que llama para dibujar, sino el documento. Cuando se carga un script en un iframe, document es el documento de iframe.

Hay una solución, pero no lo recomiendo, es realmente una solución:

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(); 
}); 

carga un iframe con otra html que las cargas y de devolución de llamada cuando se carga el fragmento. Una vez cargado, crea el fragmento que quieras y luego configura un tiempo de espera porque no podemos saber cuándo se carga SearchPanelControl. Este realWorkaround mueve los divs de autocompletar al documento principal.

You can see a work example here

The iframe loaded is this

EDITAR

Corregido el error que has encontrado y actualizan el enlace.

El ciclo for se ha ido y ha añadido un tiempo, funciona mejor ahora.

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

Parece ser lo que estaba buscando, aunque tenga en cuenta que la función de autocompletar no funciona. Por favor, consulte aquí: http://jsfiddle.net/s2HkR/ Esta es la forma predeterminada de cargar la API. Tenga en cuenta la autocompleta del formulario de búsqueda cuando escribe una ciudad. En su ejemplo de trabajo, eso se está deteniendo de trabajar. Tu idea de hacerlo es genio y no me importa tener un iframe escondido. Gracias – jQuerybeast

+0

Impresionante. Bueno, no lo recomiendas, pero creo que no tengo otra solución, ¿no? Es para una aplicación web de tablero de instrumentos y cuando su servidor es lento, todo el tablero está descuidado. – jQuerybeast

+0

Bien, ha pasado una hora tratando de resolver esto. Pensé que era un problema en mi página, pero descubrí que tampoco funciona en tu ejemplo. Mira esto: http://jsfiddle.net/orlleite/cxysA/7/show/ Si ves tu violín solo, no muestra nada. (Esto funciona bien: http://fiddle.jshell.net/orlleite/cxysA/7/show/) Gracias una vez más – jQuerybeast

Cuestiones relacionadas