El javascript añadido dinámicamente con script externo no se ejecuta

Así que este es nuestro escenario … Lo primero que hacemos es agregar un fragmento de código javascript que agrega script externo para documentar de esta manera:

(function() { var e = document.createElement('script'); e.type = 'text/javascript'; e.async = true; e.src = 'http://blabla.com/script.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(e, s); })(); 

Luego, en script.js sucede lo siguiente:

 function ajaxCall() { //... some script to send ajax request which calls createDiv() after success if (window.XMLHttpRequest){ xmlhttp=new XMLHttpRequest(); } else{ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function(){ if(xmlhttp.readyState==4&&xmlhttp.status==200){ createDiv(xmlhttp.responseText); } }; xmlhttp.open("GET","http://blabla.com/api/"); xmlhttp.send(); } function parseResponse(response) { var parser = new DOMParser(); var dom = parser.parseFromString(response, "text/html"); return dom; } function createDiv(responsetext) { var dom = parseResponse(responsetext); var _ws = dom.getElementById('styles'); var h = document.getElementsByTagName('head')[0]; h.appendChild(document.importNode(_ws, true)); var _jr = dom.getElementById('script1').outerHTML; var _vc = dom.getElementById('script2').outerHTML; var _rv = dom.getElementById('script3').outerHTML; var _rw = dom.getElementById('my_div'); var _b = document.getElementsByTagName('body')[0]; var _d = document.createElement('div'); _d.id = 'just_id'; _d.innerHTML = _jr + _vc + _rv; _d.appendChild(document.importNode(_rw, true)); _b.appendChild(_d); } ajaxCall(); 

Todo funciona bien, los scripts y un div se agregan como se espera y se espera, pero el script adjunto no se ejecuta y no afecta a los div agregados . ¿Porqué es eso? ¿Y cómo puedo hacer que se ejecute? Tampoco obtenemos advertencias / errores en la consola. Usando la última versión de Firefox.

EDIT 1

Comentario: El script de ejemplo que mostró solo define la función, pero en realidad nunca los llama

En realidad, llama a una función que hace una solicitud de AJAX, por favor revise el fragmento de código editado.

EDIT 2

Comentario: ¿Has intentado poner la lógica en una callback y luego llamarla en createDiv? Puede agregar algunos registros para probar si se llama pero no puede encontrar div

Acabo de probar console.log('hello world'); llamar a uno de los scripts que se anexan mediante la función createDiv() , pero no hace nada.

EDIT 3

Para más detalles. Cuando la página está cargada, puedo ver

    
Content here

En DOM-Inspector y como se mencionó anteriormente, está console.log('hello world'); para probarlo, pero no se ejecuta.

EDIT 4

Se agregó algo de CSS a través de la función createDiv() para documentar y esto afecta mi div con el id ‘just_id’. JS todavía no está funcionando.

EDIT 5

También intenté agregar javascript en línea en lugar de uno externo en mi función, pero aún no tuve éxito. Puede ver lo siguiente en DOM-Inspector, pero el código no registra nada.

  console.log('test');  

EDIT 6

También traté de importar nodos como se sugiere aquí

Este método no puede mover nodos entre documentos diferentes. Si desea agregar un nodo de un documento diferente, se debe usar el método document.importNode ().

y también trató de cambiar el orden. 1.css 2.div 3.js como este, pero todavía no tiene éxito … ¿Alguien tiene una idea de lo que está pasando aquí?

Verifica el código de arriba

EDIT 7

Como se sugiere en ¿Cómo se ejecuta un bloque de JavaScript cargado dinámicamente? Configuré innerHTML de mi div en secuencias de comandos + contenido y luego anexé a DOM de esta manera:

Verifica el código de arriba

Pero aún sin ningún éxito.

EDITAR 8

Se agregó código de función ajax. 3er parámetro en xmlhttp.open("GET","http://blabla.com/api/"); true (asynchronous) y false (synchronous) ya probados. Todavía no hay éxito

EDIT 9

función createDiv() como se sugiere en la respuesta:

 var dom = parseResponse(responsetext); var _jr = dom.getElementById('script1'); // tag with src attribute var _vc = dom.getElementById('script2'); //inline  for test purposes only, it should actualy be external script also var _rv = dom.getElementById('script3'); //inline  var _rw = dom.getElementById('external_div'); var _b = document.getElementsByTagName('body')[0]; var _d = document.createElement('div'); _d.id = 'internal_div'; _d.appendChild(document.importNode(_rw, true)); _d.appendChild(document.importNode(_jr, true)); _d.appendChild(document.importNode(_rv, true)); //without second parameter TRUE, I dont get script content _d.appendChild(document.importNode(_vc, true)); //without second parameter TRUE, I dont get script content _b.appendChild(_d); 

No funciona El trabajo es solo si tomo innerHTML de scripts en línea desde otro documento, creo elementos como los sugeridos en respuesta, establezco su innerHTML y luego anexo hago el documento actual. La secuencia de comandos externa no se carga en absoluto.

EDIT 10

.htaccess de localhost …:

  Order Deny,Allow Deny from all Allow from 127.0.0.1   Order Deny,Allow Deny from all Allow from 127.0.0.1   Order Allow,Deny Allow from all   RewriteEngine On RewriteBase /page1/ #RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]  

.htaccess desde 192. *** …:

 # BEGIN WordPress  RewriteEngine On RewriteBase /direktexpress/ RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /page2/index.php [L]  # END WordPress 

EDIT 11

Así que probablemente voy a dar recompensas @Drakes, solo por el esfuerzo y el tiempo dedicado a mi pregunta y voy a mostrar algunas capturas de pantalla de lo que está sucediendo. Definitivamente es un error de Firefox, acabo de probarlo en Chrome y funciona.

1ra foto: código fuente de 192.168.2.197/testing/whatever/etc. .htaccess sigue siendo el mismo que en el ejemplo anterior

Código fuente para 192.168.2.197

La segunda imagen es el código fuente de script.js, que se está cargando en 192.168.2.197 /testing/whatever/etc. .htaccess sigue siendo el mismo que en el ejemplo anterior:

Script.js Fuente

La 3ª imagen es una captura de pantalla del inspector, ¿cómo se ve mi dom:

Dom

4a imagen … no pasa nada. Solo una advertencia que no tiene nada que ver con mi problema (eso espero), porque incluso cuando elimino todos los scripts, aún aparece.

Consola

¿Es un error de Firefox?

El problema es que el código anterior está mezclando appendChild con innerHTML . No es intuitivamente obvio que los dos funcionan de manera diferente en algunos casos. El primero permite que los nodos de script recién insertados se ejecuten ya que están adjuntos al DOM. Este último no. Esto ha sido un problema para muchas personas. Sírvase Google “script and innerHTML” y verá que no está solo frente a este problema similar.

Si (1) cambias

 _d.innerHTML = _jr + _vc + _rv 

a

 _d.appendChild(document.importNode(_jr)); _d.appendChild(document.importNode(_vc)); _d.appendChild(document.importNode(_rv)); 

y adicionalmente (2) cambio

 var _jr = dom.getElementById('script1').outerHTML; var _vc = dom.getElementById('script2').outerHTML; var _rv = dom.getElementById('script3').outerHTML; 

a

 var _jr = dom.getElementById('script1'); var _vc = dom.getElementById('script2'); var _rv = dom.getElementById('script3'); 

entonces tus scripts serán ejecutados. Aquí hay una demostración:

 var b = document.getElementsByTagName('body')[0]; /* Works */ var s1 = document.createElement('script'); s1.innerHTML = "console.log('I will execute')"; b.appendChild(s1); /* Fails */ var s2 = document.createElement('script'); s2.innerHTML = "while(1){alert('Do not worry! I will not execute');}"; b.innerHTML = s2.outerHTML; console.log("It didn't execute"); 

El JavaScript de la página ya ha sido analizado, necesita eval el resultado para ponerlo en el contexto de la ventana.

 function evalRequest(url) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { eval(xmlhttp.responseText); } } xmlhttp.open("GET", url, true); xmlhttp.send(null); }; 

ACTUALIZACIÓN: es posible que necesite obtener el script como texto y luego evaluarlo)

 function getScriptsAsText() { var div = document.createElement('div'); var scripts = []; var scriptNodes = document.getElementsByTagName('script'); for (var i = 0, iLen = scriptNodes.length; i < iLen; i++) { div.appendChild(scriptNodes[i].cloneNode(true)); scripts.push(div.innerHTML); div.removeChild(div.firstChild); } return scripts; }; 

Actualmente estás cargando un script en tu página. Esto sucede DESPUÉS de que la página js ya se haya ejecutado (dado que es asíncrona y, por lo general, cargar un recurso externo lleva más tiempo que la ejecución del script).

Entonces … básicamente tienes las definiciones correctas de funciones y todo, y llamarlas desde la consola más tarde debería funcionar (creo que ya lo intentaste y estaba bien).

Aún así, las llamadas a sus funciones, incluso si piensan que están allí, no se ejecutarán, ya que no se computarán después de la carga.

Para evitar esto, puede crear una solicitud ajax a una página que tenga la secuencia de comandos, y en su callback para llamar a cualquier función que necesite llamar.

Yo diría eliminar asincrónico, ya que la acción viene después de la carga de la página inicial

El problema es que su método es la ejecución asincrónica no síncrona . Lo que significa que la página aún se está cargando mientras inserta sus scripts dynamics. Hay pocas maneras de hacerlo:

  1. La forma más fácil es usar jQuery $(document).append lugar de document.createElement, si no le importa utilizar la biblioteca.

  2. También puede usar jQuery $.getScript .

  3. Si prefiere no incluir 3ras bibliotecas, tiene que pensar en una manera de retrasar la carga de la página mientras inserta las secuencias de comandos, algo así como una alert para crear una ventana de aviso funcionará, pero la experiencia del usuario no es tan buena, piense en una camino.

  4. Use XMLHTTPRequest para recuperar sus scripts. Esto es sincrónico y puedo ver que estás familiarizado con él porque ya lo estás usando en tu script.

Buena suerte y feliz encoding.

  (function () { var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(CreateScriptTag('http://blabla.com/script.js',true), s); })(); function CreateScriptTag(src, isAsync) { var e = document.createElement('script') e.type = 'text/javascript'; e.async = isAsync; e.src = src; return e; } function ajaxCall() { //... some script to send ajax request which calls createDiv() after success if (window.XMLHttpRequest) xmlhttp = new XMLHttpRequest(); else xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("GET", "http://blabla.com/api/"); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState === 4 && xmlhttp.status === 200) createDiv(xmlhttp.responseText); }; xmlhttp.send(); } function parseResponse(response) { var parser = new DOMParser(); var dom = parser.parseFromString(response, "text/html"); return dom; } function createDiv(responsetext) { var head=document.getElementsByTagName('head')[0],dom = parseResponse(responsetext),_div=document.createElement('div'); head.appendChild(document.importNode(dom.getElementById('styles'), true)); //Assuming stylesheets are working fine. _div.id = 'just_id'; //div.innerHTML = _script1 + _script2 + _script3; document.getElementsByTagName('body')[0].appendChild(_div.appendChild(dom.getElementById('my_div'))); head.appendChild(CreateScriptTag(dom.getElementById('script1').getAttribute("src"),true)); head.appendChild(CreateScriptTag(dom.getElementById('script2').getAttribute("src"),true)); head.appendChild(CreateScriptTag(dom.getElementById('script3').getAttribute("src"),true)); /* or another idea; document.write(_script1 + _script2 + _script3); */ } ajaxCall(); 

¿Has intentado obtener la URL del archivo src y desactivarlo con la función getScript() jQuery?

Cambie su función de creatediv() :

 var _jr = dom.getElementById('script1').outerHTML; var srcScript1Left = _jr.split('src="'); srcScript1Right = srcScript1Left[1].split('"'); srcScript1 = srcScript1Right[0]; console.log(srcScript1); $.getScript(srcScript1, function() { // The external script has been executed. }); 

EDITAR

Método similar en Javascript puro:

 var _jr = dom.getElementById('script1').outerHTML; var srcScript1Left = _jr.split('src="'); srcScript1Right = srcScript1Left[1].split('"'); srcScript1 = srcScript1Right[0]; console.log(srcScript1); // Display the name of the external script file if(window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); } else { xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if(xmlhttp.readyState == 4 && xmlhttp.status == 200) { eval(xmlhttp.responseText); // Execute the external script } }; xmlhttp.open("GET",srcScript1); xmlhttp.send();