Dekodiertes Script ausführen
Peter
- javascript
Hallo,
ich hab mir schon einen Elch gesucht, bin aber nicht fündig geworden.
Problem: per JS dekodiertes Script wird nicht ausgeführt. Beispiel:
<html><head></head><body>
<div id="b64">... Base64 Inhalt ...</div>
<div id="klartext"></div>
<script type="text/javascript">
var text = atob(document.getElementByID("b64").innerHTML);
document.getElementByID("klartext").innerHTML = text;
</script>
</body></html>
Ein in "text" enthaltenes Script wird nicht ausgeführt. Soweit klar.
Jetzt aber stelle ich folgende Funktion zur Verfügung:
function id_add(id, text) {
var div = document.createElement("div");
div.innerHTML = text;
var docFrag = document.createDocumentFragment();
while(div.firstChild)
docFrag.appendChild(div.firstChild);
document.getElementById(id).appendChild(docFrag);
}
und ändere das o.g. Script wie folgt:
var text = atob(document.getElementByID("b64").innerHTML);
id_add("klartext", text);
Nach allem, was ich gelesen habe sollte nun das in "text" enthaltene Script ausgeführt werden, da es direkt in das DOM injiziert wird. Was läuft schief?
Anmerkung: das Script liegt "tief vergraben" im "text", "text" sieht im Prinzip so aus:
<div id="eins">
<div id="zwei">
Laber laber laber
</div>
<div id="drei">
Laber laber laber
<script type="text/javascript">
document.writeln("Hallo Welt");
</script>
</div>
Laber laber laber
</div>
Aber das dürfte kein Störfaktor sein, oder?!
Hallo Peter!
Die Methode heißt ja auch nicht getElementByID, sondern getElementById
.
Solche Fehler werden unter anderem von den eingebauten JavaScript-Konsolen der Browser bemängelt. Im Firefox erreicht man die über die Tastenkombination Ctrl+Shift+k, Chrome hört glaube auf Ctrl+Shift+j und bei Internet Explorer muss ich passen.
\0
Die Methode heißt ja auch nicht getElementByID, sondern
getElementById
.
Äh, sorry. IdF war das nur ein Vertipper im Beispiel. Der Code ist im Original syntaktisch einwandfrei (Firebug läuft mit und würde mir sowas um die Ohren hauen).
Merkwürdig finde ich, dass Events wie
onclick="externe_funktion();"
einwandfrei ausgeführt werden, nicht jedoch der Aufruf einer Funktion aus einem JS-Codeblock; ja nicht einmal ein simples writeln
wird ausgeführt.
Hum?! :-)
Hallo Peter,
so weit ich weiß, werden Scripte, wenn sie per innerHTML ins Dokument eingebunden werden, nicht ausgeführt. Du musst sie entweder mit eval ausführen oder (so mache ich das) in ein Script-Element einfügen.
Gruß, Jürgen
Hallo Jürgen,
so weit ich weiß, werden Scripte, wenn sie per innerHTML ins Dokument eingebunden werden, nicht ausgeführt. Du musst sie entweder mit eval ausführen oder (so mache ich das) in ein Script-Element einfügen.
Wenn ich das richtig interpretiere, dann muss ich "text" parsen, um an der passenden Stelle
var script = document.createElement("script");
script.type = "text/javascript";
script.text = "meine_function();"
document.getElementById(id).appendChild(script);
einzufügen. Und ohne parsen geht das schlicht nicht, oder?
Hallo Peter,
Und ohne parsen geht das schlicht nicht, oder?
so habe ich das verstanden. Probiers mal aus.
Gruß, Jürgen
Hallo,
Wenn ich das richtig interpretiere, dann muss ich "text" parsen, um an der passenden Stelle
var script = document.createElement("script");
script.type = "text/javascript";
script.text = "meine_function();"
document.getElementById(id).appendChild(script);
> einzufügen. Und ohne parsen geht das schlicht nicht, oder?
Du musst nicht selbst parsen, das erledigt ja der Browser für dich, wenn du `innerHTML = "<p>…<script>…</script>…</p>"`{:.language-javascript} zuweist. Die Script-Elemente existieren schon im DOM, der Code darin wurde nur nicht ausgeführt.
Du musst nach dem innerHTML nur alle script-Elemente unterhalb des betroffenen Elements suchen (z.B. mit `element.getElementsByTagName('script')`{:.language-javascript}) und diese mit eval() ausführen.
So macht es übrigens auch jQuerys html()-funktion ([intern domManip](https://github.com/jquery/jquery/blob/2.0.3/src/manipulation.js#L228-L270)).
Man sollte außerdem ein globales eval() verwenden, sonst sind in dem Code nämlich noch lokale Variablen verfügbar. In neueren Browsern reicht es, `(1,eval)("code");`{:.language-javascript} zu schreiben.
Hintergrund: <http://perfectionkills.com/global-eval-what-are-the-options/>
jQuery hat dazu auch eine Helferfunktion: <http://api.jquery.com/jQuery.globalEval/>
Mathias
Hallo Mathias,
danke für die ausführliche Erklärungen. Läuft. :-)
Hallo,
Merkwürdig finde ich, dass Events wie
onclick="externe_funktion();"
einwandfrei ausgeführt werden, nicht jedoch der Aufruf einer Funktion aus einem JS-Codeblock;
Das ist ganz logisch. Dieser Code wird ja nicht direkt ausgeführt, sondern es ist ein HTML-Attribut mit JavaScript-Code drin, der erst beim fraglichen Event ausgeführt wird. Bei der Zuweisung mit innerHTML muss also nichts besonderes getan werden, außer das Attribut zu setzen.
Bei script-Elementen ist das etwas anderes, deren Inhalt wird bei innerHTML wie gesagt nicht automatisch ausgeführt.
ja nicht einmal ein simples
writeln
wird ausgeführt.
Nur am Rande:
document.write/writeln wird nie korrekt ausgeführt in JavaScript-Code, der nicht während des Ladens des Dokuments aufgerufen wird. Wenn man nach dem initialen Laden des Dokuments document.write ausführt, ersetzt document.write das Dokument höchstens, es fügt aber nichts an die jeweilige Stelle ins Dokument ein. alert("Hallo Welt")
wäre ein besserer Test, das funktioniert immer.
Mathias