¿Alguna idea de por qué el siguiente código no agrega el elemento de script al DOM?
var code = "<script></script>";
$("#someElement").append(code);
¿Alguna idea de por qué el siguiente código no agrega el elemento de script al DOM?
var code = "<script></script>";
$("#someElement").append(code);
Respuestas:
He visto problemas en los que algunos navegadores no respetan algunos cambios cuando los haces directamente (con lo que me refiero a crear el HTML a partir del texto como si estuvieras intentando con la etiqueta del script), pero cuando los haces con comandos integrados Las cosas van mejor. Prueba esto:
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );
De: JSON para jQuery
$("#someElement")[0].appendChild( script );
La buena noticia es:
Funciona al 100%.
Simplemente agregue algo dentro de la etiqueta del script como alert('voila!');
. La pregunta correcta que tal vez quiera hacer, "¿Por qué no la vi en el DOM?" .
Karl Swedberg ha hecho una buena explicación al comentario de los visitantes en el sitio jQuery API . Yo no quiero repetir todas sus palabras, se puede leer directamente hay aquí (me pareció difícil de navegar a través de los comentarios allí) .
Todos los métodos de inserción de jQuery utilizan una función domManip internamente para limpiar / procesar elementos antes y después de que se inserten en el DOM. Una de las cosas que hace la función domManip es extraer los elementos de script que se van a insertar y ejecutarlos a través de una "rutina evalScript" en lugar de inyectarlos con el resto del fragmento DOM. Inserta los scripts por separado, los evalúa y luego los elimina del DOM.
Creo que una de las razones por las que jQuery hace esto es para evitar errores de "Permiso denegado" que pueden ocurrir en Internet Explorer al insertar scripts bajo ciertas circunstancias. También evita insertar / evaluar repetidamente el mismo script (que podría causar problemas) si está dentro de un elemento que está insertando y luego se mueve alrededor del DOM.
Lo siguiente es que resumiré cuáles son las malas noticias usando la .append()
función para agregar un script.
Y la mala noticia es ...
No puedes depurar tu código.
No estoy bromeando, incluso si agrega debugger;
palabras clave entre la línea que desea establecer como punto de interrupción, terminará obteniendo solo la pila de llamadas del objeto sin ver el punto de interrupción en el código fuente (sin mencionar que esto la palabra clave solo funciona en el navegador webkit, todos los demás navegadores principales parecen omitir esta palabra clave) .
Si comprende completamente lo que hace su código, esto será un inconveniente menor. Pero si no lo hace, terminará agregando una debugger;
palabra clave en todo el lugar solo para descubrir qué está mal con su (o mi) código. De todos modos, hay una alternativa, no olvides que JavaScript puede manipular de forma nativa HTML DOM.
Solución alterna.
Use javascript (no jQuery) para manipular HTML DOM
Si no desea perder la capacidad de depuración, puede usar la manipulación DOM HTML nativa de JavaScript. Considere este ejemplo:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "path/to/your/javascript.js"; // use this for linked script
script.text = "alert('voila!');" // use this for inline script
document.body.appendChild(script);
Ahí está, al igual que en los viejos tiempos, ¿no? Y no olvide limpiar las cosas, ya sea en el DOM o en la memoria, para todos los objetos a los que se hace referencia y que ya no son necesarios para evitar pérdidas de memoria. Puede considerar este código para limpiar las cosas:
document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.
El inconveniente de esta solución es que puede agregar accidentalmente un script duplicado, y eso es malo. Desde aquí, puede imitar ligeramente la .append()
función agregando una verificación de objeto antes de agregar y eliminando el script del DOM justo después de que se agregó. Considere este ejemplo:
function AddScript(url, object){
if (object != null){
// add script
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "path/to/your/javascript.js";
document.body.appendChild(script);
// remove from the dom
document.body.removeChild(document.body.lastChild);
return true;
} else {
return false;
};
};
function DeleteObject(UnusedReferencedObjects) {
delete UnusedReferencedObjects;
}
De esta manera, puede agregar secuencias de comandos con capacidad de depuración mientras está a salvo de la duplicación de secuencias de comandos. Esto es solo un prototipo, puede expandirse para lo que quiera que sea. He estado usando este enfoque y estoy bastante satisfecho con esto. Efectivamente, nunca usaré jQuery .append()
para agregar un script.
$.getScript
está integrado en jQuery.
Es posible cargar dinámicamente un archivo JavaScript usando la función jQuerygetScript
$ .getScript ('http://www.whatever.com/shareprice/shareprice.js', function () { Display.sharePrice (); });
Ahora se llamará al script externo y, si no se puede cargar, se degradará correctamente.
eval()
.
¿Qué quieres decir con "no funciona"?
jQuery detecta que está intentando crear un elemento SCRIPT y ejecutará automáticamente el contenido del elemento dentro del contexto global. ¿Me estás diciendo que esto no funciona para ti? -
$('#someElement').append('<script>alert("WORKING");</script>');
Editar: si no está viendo el elemento SCRIPT en el DOM (en Firebug, por ejemplo) después de ejecutar el comando, es porque jQuery, como dije, ejecutará el código y luego eliminará el elemento SCRIPT: creo que los elementos SCRIPT siempre se adjuntan al cuerpo ... pero de todos modos, la ubicación no tiene absolutamente ninguna relación con la ejecución del código en esta situación.
Esto funciona:
$('body').append($("<script>alert('Hi!');<\/script>")[0]);
Parece que jQuery está haciendo algo inteligente con los scripts, por lo que debe agregar el elemento html en lugar del objeto jQuery.
Pruebe esto puede ser útil:
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);
<script>
...
...jQuery("<script></script>")...
...
</script>
El </script>
literal dentro de la cadena termina todo el script, para evitar que "</scr" + "ipt>"
se pueda usar en su lugar.
"\x3cscript\x3e\x3c/script\x3e"
. En XHTML, solo necesita poner un bloque CDATA comentado.
</
que no está permitido. Ver stackoverflow.com/questions/236073/…
Agregar el sourceURL en el archivo de script ayudó como se menciona en esta página: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
Su script se está ejecutando, simplemente no puede usarlo document.write
. Use una alerta para probarlo y evite usarlo document.write
. Las declaraciones de su archivo js con document.write
no se ejecutarán y el resto de la función se ejecutará.
Esto es lo que creo que es la mejor solución. Google Analytics se inyecta de esta manera.
var (function(){
var p="https:" == document.location.protocol ? "https://" : "http://";
d=document,
g=d.createElement('script'),
s=d.getElementsByTagName('script')[0];
g.type='text/javascript';
g.src=p+'url-to-your-script.js';
s.parentNode.insertBefore(g,s); })();
No necesita jQuery para crear un elemento DOM del script . Se puede hacer con vainilla ES6 así:
const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
(function(i,s,o,g,r,a,m){
a=s.createElement(o),m=s.getElementsByTagName(o)[0];
a.innerText=g;
a.onload=r;m.parentNode.insertBefore(a,m)}
)(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))
No necesita estar envuelto en un Promise
, pero hacerlo le permite resolver la promesa cuando se carga el script, lo que ayuda a evitar condiciones de carrera para los scripts de larga ejecución.
Agregar script al cuerpo:
$(document).ready(function() {
$("<script>", { src : "bootstrap.min.js", type : "text/javascript" }).appendTo("body");
});
Otra forma de hacerlo si desea agregar código es usar el document.createElement
método pero luego usar en .innerHTML
lugar de .src
.
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );
Puede intentar así
var code = "<script></" + "script>";
$("#someElement").append(code);
La única razón por la que no puede hacerlo "<script></script>"
es porque la cadena no está permitida dentro de JavaScript porque la capa DOM no puede analizar qué es js y qué es HTML.
Escribí un npm
paquete que le permite tomar una cadena HTML, incluidas las etiquetas de secuencia de comandos y agregarla a un contenedor mientras ejecuta las secuencias de comandos
Ejemplo:
import appendHtml from 'appendhtml';
const html = '<p>Hello</p><script src="some_js_file.js"></script>';
const container = document.getElementById('some-div');
await appendHtml(html, container);
// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)
Encuéntralo aquí: https://www.npmjs.com/package/appendhtml
Simplemente cree un elemento analizándolo con jQuery.
<div id="someElement"></div>
<script>
var code = "<script>alert(123);<\/script>";
$("#someElement").append($(code));
</script>
Ejemplo de trabajo: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz