2009-10-08 16 views
17

Me gustaría crear una página que ejecute un script de terceros que incluya document.write después de que el DOM ya esté completamente cargado.JavaScript - control del punto de inserción para document.write

Mi página no es XHTML. Mi problema es que document.write está sobrescribiendo mi propia página. (que es lo que hace una vez que se cargó DOM).

Intenté sobreescribir la función document.write (de una manera similar a http://ejohn.org/blog/xhtml-documentwrite-and-adsense/) pero eso no cubre casos donde el document.write contiene etiquetas parciales.

Un ejemplo que rompería el código anterior es:

document.write("<"+"div"); 
document.write(">"+"Done here<"+"/"); 
document.write("div>"); 

¿Hay alguna manera de modificar el punto de inserción a través de JavaScript document.write? ¿Alguien tiene una mejor idea de cómo hacer esto?

+0

es el script de terceros descargado, por lo que puede editarlo?Creo que podría ser una mejor solución que hackear 'document.write()' – peirix

+0

Mi ejemplo pasó. Lo que quise decir fue: document.write ('<' + 'div'); document.write ('>' + 'Text Content' + '<'); document.write ('\ div>') –

+0

Podría editarlo, pero además del análisis completo de JS, ¿hay alguna forma de garantizar que el código editado funcione correctamente? –

Respuesta

3

respuesta original antes de la edición:


Básicamente el problema de document.write es que does not work in XHTML documents. La solución más amplia entonces (por más dura que pueda parecer) es no usar XHTML/xml para su página. Debido a IE + XHTML y al mimetype problem, la ruptura de Google Adsense (puede ser una buena cosa :), y el cambio general hacia HTML5 no creo que sea tan malo como parece.

Sin embargo, si desea realmente le gusta utilizar XHTML para su página, entonces la secuencia de comandos de John que ha vinculado es la mejor que tiene en este momento. Solo huele para IE en el servidor. Si la solicitud es de IE, no haga nada (y no ¡sirva el tipo mimético application/xhtml+xml!). De lo contrario, colóquelo en el <head> de su página y estará listo para las carreras.

Volviendo a leer su pregunta, ¿hay algún problema específico con el guión de John? Se sabe que falla en Safari 2.0, pero eso es todo.

+0

Mi página no usa XHTML, pero cargué las secuencias de comandos de terceros después de que se cargó el DOM y anulan mi página. Mi problema es que el siguiente código fallará: document.write ('<' + 'div');
document.write ('>' + 'Text Content' + '<');
document.write (' \ div> '); –

+0

@yeeeev: wow, ¿esto no tiene nada que ver con XHTML? Deberías poner ese código en tu pregunta como un fragmento de código para que podamos ayudarte. Parece incorrecto como un comentario. –

+0

@yeeev: Veo que de hecho trataste de ponerlo ya. Déjame editar tu pregunta .... –

0

Para modificar el contenido de la página después de que el DOM lo haya renderizado, necesita utilizar una biblioteca de JavaScript para agregar HTML o texto en ciertos puntos (jQuery, mootools, prototype, ...) o simplemente usar innerHTML propiedad de cada elemento DOM para modificar/anexarle texto. Esto funciona con navegador cruzado y no requiere ninguna biblioteca.

-2

Hay mejores formas de hacerlo. 2 maneras

1) adjuntar

<html><head> 
<script> 
    window.onload = function() { 
    var el = document.createTextNode('hello world'); 
    document.body.appendChild(el); 
    } 
</script></head><body></body></html> 

2) InnerHtml

<html><head><script> 
    window.onload = function() { 
    document.body.innerHTML = 'hello world'; 
    } 
</script></head><body></body></html> 
+0

¿No te encanta la respuesta correcta? –

+2

Esta solución es inútil si no puede alterar el script de terceros. También la solución # 2 reemplazará todo el cuerpo con 'hello world'. Typo? – gregers

+0

@gregers. Es solo un ejemplo de la técnica. –

3

Usted puede estar interesado en the Javascript library I developed que permite cargar scripts de 3 ª parte utilizando document.write después window.onload . Internamente, la biblioteca anula document.write, agregando elementos DOM de forma dinámica, ejecutando cualquier script incluido que también pueda usar document.write.

A diferencia de la solución de John Resig (que fue parte de la inspiración para mi propio código), el módulo he desarrollado soporta las escrituras parciales, como el ejemplo que das con el div:

document.write("<"+"div"); 
document.write(">"+"Done here<"+"/"); 
document.write("div>"); 

Mi biblioteca esperarán el final del script antes de analizar y renderizar el marcado. En el ejemplo anterior, se ejecutará una vez con la cadena completa "<div>Done here</div>" en lugar de 3 veces con marcado parcial.

He configurado a demo, in which I load 3 Google Ads, an Amazon widget as well as Google Analytics dynamically.

11

Si se trata de scripts de terceros, simplemente reemplazar document.write para capturar el resultado y pegarlo en el lugar correcto no es suficiente, ya que podrían cambiar el script y su sitio se rompería.

writeCapture.js hace lo que necesita (divulgación completa: soy el autor). Básicamente reescribe las etiquetas de script para que cada una capture su propia salida document.write y la coloque en el lugar correcto. El uso (usando jQuery) sería algo así como:

$(document.body).writeCapture().append('<script type="text/javascript" src="http://3rdparty.com/foo.js"></script>'); 

Aquí estoy suponiendo que desea añadir al final del cuerpo. Todos los selectores jQuery y los métodos de manipulación funcionarán con el complemento, por lo que puede inyectarlo en cualquier lugar y como desee. También se puede usar sin jQuery, si eso es un problema.

+0

Cuando uso esto código, Chrome me ladra y arroja un error: 'Uncaught SyntaxError: Inexpected token ILEGAL' –

4

Es posible anular el método document.write. De modo que puede almacenar en búfer las cadenas enviadas a document.write y generar el búfer donde desee. Sin embargo, cambiar un script de sincrónico a asincrónico puede causar errores si no se maneja correctamente. He aquí un ejemplo:

reemplazo document.write simplificado

(function() { 
    // WARNING: This is just a simplified example 
    // to illustrate a problem. 
    // Do NOT use this code! 

    var buffer = []; 
    document.write = function(str) { 
     // Every time document.write is called push 
     // the data into buffer. document.write can 
     // be called from anywhere, so we also need 
     // a mechanism for multiple positions if 
     // that's needed. 
     buffer.push(str); 
    }; 

    function flushBuffer() { 
     // Join everything in the buffer to one string and put 
     // inside the element we want the output. 
     var output = buffer.join(''); 
     document.getElementById("ad-position-1").innerHTML = output; 
    } 

    // Inject the thid-party script dynamically and 
    // call flushBuffer when the script is loaded 
    // (and executed). 
    var script = document.createElement("script"); 
    script.onload = flushBuffer; 
    script.src = "http://someadserver.com/example.js"; 

})(); 

contenido de http://someadserver.com/example.js

var flashAdObject = "<object>...</object>"; 
document.write("<div id='example'></div>"); 

// Since we buffer the data the getElementById will fail 
var example = document.getElementById("example"); 
example.innerHTML = flashAdObject; // ReferenceError: example is not defined 

he documentado los diferentes problemas que he encontrado al escribir y usar mi reemplazo de document.write: https://github.com/gregersrygg/crapLoader/wiki/What-to-think-about-when-replacing-document.write

Pero el peligro de utilizar un reemplazo document.write son todos los problemas desconocidos que puedan surgir. Algunos ni siquiera son posibles de recorrer.

document.write("<scr"+"ipt src='http://someadserver.com/adLib.js'></scr"+"ipt>"); 
adLib.doSomething(); // ReferenceError: adLib is not defined 

Por suerte no me he encontrado con el problema anterior en la naturaleza, pero eso no garantiza que no ocurrirá;)

Aún quieres probarlo? Pruebe crapLoader (mío) o writeCapture:

También debe consultar friendly iframes. Básicamente crea un iframe del mismo dominio y carga todo allí en lugar de en su documento. Desafortunadamente, no he encontrado ninguna buena biblioteca para manejar esto todavía.

1

FWIW, encontré que postscribe es la mejor opción en la actualidad: maneja un molesto módulo de renderizado de anuncios como un amuleto que permite que nuestra página cargue sin ser bloqueada.

Cuestiones relacionadas