Tengo un script que inserta contenido en un elemento usando innerHTML
.
El contenido podría ser, por ejemplo:
<script type="text/javascript">alert('test');</script>
<strong>test</strong>
El problema es que el código dentro de la <script>
etiqueta no se ejecuta. Lo busqué en Google un poco pero no había soluciones aparentes. Si inserté el contenido usando jQuery, $(element).append(content);
las partes del script se obtuvieron eval
antes de inyectarse en el DOM.
¿Alguien tiene un fragmento de código que ejecuta todos los <script>
elementos? El código de jQuery era un poco complejo, así que no pude entender cómo se hacía.
Editar :
Al echar un vistazo al código de jQuery, me las arreglé para descubrir cómo lo hace jQuery, lo que resultó en el siguiente código:
Demo:
<div id="element"></div>
<script type="text/javascript">
function insertAndExecute(id, text)
{
domelement = document.getElementById(id);
domelement.innerHTML = text;
var scripts = [];
ret = domelement.childNodes;
for ( var i = 0; ret[i]; i++ ) {
if ( scripts && nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
}
}
for(script in scripts)
{
evalScript(scripts[script]);
}
}
function nodeName( elem, name ) {
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
}
function evalScript( elem ) {
data = ( elem.text || elem.textContent || elem.innerHTML || "" );
var head = document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script");
script.type = "text/javascript";
script.appendChild( document.createTextNode( data ) );
head.insertBefore( script, head.firstChild );
head.removeChild( script );
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
insertAndExecute("element", "<scri"+"pt type='text/javascript'>document.write('This text should appear as well.')</scr"+"ipt><strong>this text should also be inserted.</strong>");
</script>
javascript
dom
eval
innerhtml
phidah
fuente
fuente
function testFunction(){ alert('test'); }
al código insertado en innerHTML, y luego intento llamarlo, dice que la función no está definida.Respuestas:
El script de OP no funciona en IE 7. Con la ayuda de SO, aquí hay un script que sí:
fuente
$(parent).html(code)
: vea mi respuesta a continuación.if (nodeName(child, "script" ) && (!child.type || child.type.toLowerCase() === "text/javascript")) { scripts.push(child); } else { exec_body_scripts(child); }
elem.src
y establecer condicionalmente lasrc
propiedad del elemento de script creado en lugar de establecer su contenido de texto.eval
truco global en lugar de crear un<script>
elemento e insertarlo en el<head>
? Ambos ejecutan código JS sin exponer el cierre actual.@phidah ... Aquí hay una solución muy interesante a su problema: http://24ways.org/2005/have-your-dom-and-script-it-too
En su lugar, se vería así:
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
fuente
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert('test');">
si desea evitar una solicitud http inútil.style="display:none;
) para ocultar el ícono de imagen rota<style>
es mejor que<img>
, porque no realiza una solicitud de redAquí hay una secuencia de comandos más corta y eficiente que también funciona para secuencias de comandos con la
src
propiedad:Nota: si bien
eval
puede causar una vulnerabilidad de seguridad si no se usa correctamente, es mucho más rápido que crear una etiqueta de script sobre la marcha.fuente
eval
fue diseñado para dañar a los usuarios. Cualquier ejecución de script dinámico es un riesgo y es por eso que CSP lo llama'unsafe-eval'
porque lo es. También está perjudicando la seguridad de sus sitios si lo usa en una biblioteca, ya que no pueden desactivarlo.src
propiedad se descargarán de forma asincrónica y se ejecutarán cuando lleguen. El pedido no se conserva. Los scripts en línea también se ejecutarán fuera de orden, sincrónicamente antes que los asincrónicos.No debe usar la propiedad innerHTML sino el método appendChild del Node: un nodo en un árbol de documentos [HTML DOM]. De esta manera, puede llamar más tarde a su código inyectado.
Asegúrese de entender que
node.innerHTML
no es lo mismo quenode.appendChild
. Es posible que desee dedicar algún tiempo a la referencia de cliente de Javascript para obtener más detalles y el DOM. Espero que lo siguiente ayude ...La inyección de muestra funciona:
Saludos,
fuente
try this, look how clever I am
respuestas. Se merece un UV, consiguió el mío.var _in = document.getElementById(inject);
, Yo creo que.Versión ES6 simplificada de la respuesta de @ joshcomley con un ejemplo.
Sin JQuery, sin biblioteca, sin evaluación, sin cambio de DOM, solo Javascript puro.
http://plnkr.co/edit/MMegiu?p=preview
Uso
fuente
setInnerHtml
no essetInnerHTML
setInnerHTML
pero se llamasetInnerHtml
desde dentro de larunB
función. Por lo tanto, el ejemplo no funcionaPrueba este fragmento:
fuente
Funciona en Chrome en mi proyecto.
fuente
Una solución sin usar "eval":
Esto esencialmente clona la etiqueta de secuencia de comandos y luego reemplaza la etiqueta de secuencia de comandos bloqueada con la recién generada, lo que permite la ejecución.
fuente
scriptNode.innerHTML = code
no funcionó para IE. Lo único que puede hacer es reemplazarloscriptNode.text = code
y funciona bienfuente
Es más fácil usar jquery en
$(parent).html(code)
lugar deparent.innerHTML = code
:Esto también funciona con scripts que utilizan
document.write
y scripts cargados mediantesrc
atributo. Desafortunadamente, incluso esto no funciona con los scripts de Google AdSense.fuente
Solo haz:
fuente
Puede echar un vistazo a esta publicación . El código podría verse así:
fuente
Gracias al script de Larry, que funcionó perfectamente bien en IE10, esto es lo que he usado:
fuente
Extendiéndose de Larry's. Hice que buscara recursivamente todo el bloque y los nodos secundarios.
El script ahora también llamará a los scripts externos que se especifican con el parámetro src. Los guiones se adjuntan al encabezado en lugar de insertarse y se colocan en el orden en que se encuentran. Así que se conservan específicamente los scripts de orden. Y cada secuencia de comandos se ejecuta sincrónicamente de forma similar a cómo el navegador maneja la carga DOM inicial. Entonces, si tiene un bloque de script que llama a jQuery desde un CDN y el siguiente nodo de script usa jQuery ... ¡No hay problema! Ah, y etiqueté los scripts adjuntos con una identificación serializada basada en lo que estableciste en el parámetro de etiqueta para que puedas encontrar lo que agregó este script.
fuente
Prueba esto, me funciona en Chrome, Safari y Firefox:
Sin embargo, una cosa a tener en cuenta es que el siguiente script anidado en div NO se ejecutará:
Para que un script se ejecute, debe crearse como un nodo y luego agregarse como un hijo. Incluso puede agregar un script dentro de un div previamente inyectado y se ejecutará (me he encontrado con esto antes cuando intentaba que el código del servidor de anuncios funcione):
fuente
Gastando la respuesta de Lambder
Puede usar la imagen base64 para crear y cargar su script
O si tienes un
Iframe
puedes usarlo en su lugarfuente
Necesitaba algo similar, pero necesitaba que el script permaneciera o se volviera a crear en el mismo lugar que el script original, ya que mi script apunta a la ubicación de la etiqueta del script en el DOM para crear / elementos de destino. También hice que el script fuera recursivo para asegurarme de que también funciona si está más de un nivel hacia abajo.
NOTA: Yo uso
const
aquí, si tiene un navegador más antiguo, solo usevar
.fuente
Hizo esta nueva función auxiliar en TypeScript, tal vez alguien la aprecie. Si elimina la declaración de tipo del parámetro de secuencia de comandos, será simplemente JS.
fuente
Prueba la función eval ().
Este es un ejemplo real de un proyecto que estoy desarrollando. Gracias a esta publicación
fuente
Aquí está mi solución en un proyecto reciente.
fuente