Avatar billede hermandsen Juniormester
28. oktober 2010 - 12:10 Der er 11 kommentarer og
1 løsning

IE evaluerer script-tags inden de indsættes i DOM

Hej eksperter

Se følgende:

function f(){
    var frag = document.createDocumentFragment();
    var s = document.createElement('script');
    frag.appendChild(s);
    alert('set text');
    s.text = "alert('dynamic');";
    alert('append fragment');
    document.body.appendChild(frag);
    alert('done');
};

Rækkefølgen på mine alerts burde være:
1. set text
2. append fragment
3. dynamic
4. done

Men i IE er den:
1. set text
2. dynamic
3. append fragment
4. done

Dvs. at Internet Explorer evaluerer mine scripts inden de bliver indsat i DOM.
Hvordan får jeg Internet Explorer til at vente med at evaluere scripts før de er indsat i DOM?

Det skal bruges til at parse HTML og JavaScript om til et DocumentFragment, som derefter kan indsættes og vil udføre JavaScript gennem DOM i stedet for brug af eval().

// hermandsen
Avatar billede mcb2001 Nybegynder
28. oktober 2010 - 15:34 #1
jeg vil næsten anbefale at du kigger på om ikke det er noget JQuery kan løse for dig, for den kan lave næsten alt arbejdet, så du mere skal tænke på hvad du vil have, mere end hvordan det skal virke.

http://jquery.com/
Avatar billede hermandsen Juniormester
29. oktober 2010 - 00:22 #2
Så er jQuery blevet testet, og det var et skridt bagud, selv i Firefox.
Kigger man ned i koden til jQuery, så ses det tydeligt at script-tags pilles ud af DOM, og lægges direkte i <head>-tagget ved brug af append(). Så de bliver også udført før elementet rent faktisk indsættes i document.

Følgende er prøvet med jQuery 1.4.3:
function f() {
    alert('createElement');
    var div = $(document.createElement('div'));
    alert('setup string');
    var s = '<'+'div><'+'script type="text/javascript">alert("dynamic")<'+'/script><'+'/div>';
    alert('append text');
    div.append(s);
    alert('append to body');
    document.body.appendChild(div[0]);
    alert('done');
};

Hvis vi skulle følge standarderne så skulle rækkefølgen være:
1. createElement
2. setup string
3. append text
4. append to body
5. dynamic
6. done

Men med jQuery ser det ud som følger:
1. createElement
2. setup string
3. append text
4. dynamic
5. append to body
6. done

Og kigger man i DOM efterfølgende, så er script-tagget ikke indsat - så jQuery virker ikke til formålet. Jeg har ikke gidet at tjekke det i IE, da jeg kan se i koden at resultatet vil blive det samme.
Avatar billede mcb2001 Nybegynder
29. oktober 2010 - 10:46 #3
med henvisning til din kode:
    var div = $(document.createElement('div'));
    alert('setup string');
    var s = '<'+'div><'+'script type="text/javascript">alert("dynamic")<'+'/script><'+'/div>';
    alert('append text');
    div.append(s);

Du laver et document.createElement('div'));
Denne opretter en ny div i DOM, og når du så kører div.append(s), så afvikler den det der står i div, så du får "dynamic" og der er jo også rigtigt.
Når du så i næste linie skriver alert('append to body') så kommer den jo efter at du har oprettet elementet, og derfor efter dynamic.
Avatar billede hermandsen Juniormester
29. oktober 2010 - 13:06 #4
Jeg beklager, men det desværre forkert hvad du skriver.
Når jeg kører document.createElement('div'), så får jeg et nyt div som ikke er indsat nogen steder. Der ligger ikke i DOM, men kun som en variabel i javascript. Derefter sætter jeg teksten ind i mit div-tag (som stadig ikke ligger noget sted i DOM). Først når der bliver kaldt appendChild på en node som ligger i DOM, så skal script-tagget udføres.

Prøv selv følgende i Firefox, chrome eller safari:
var s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.appendChild(document.createTextNode("alert('test');"));
var div = document.createElement('div');
div.appendChild(s);
setTimeout(function(){
  alert('før append');
  document.body.appendChild(div);
  alert('efter append');
}, 2000);

Rækkefølgen på dine alerts bliver:
1. før append
2. test
3. efter append

Hvis jeg gør noget lignende med jQuery, så bliver rækkefølgen:
1. test
-- vent to sekunder -
2. før append
3. efter append

Hvilket er forkert.
Avatar billede mcb2001 Nybegynder
29. oktober 2010 - 13:30 #5
men du initialiserer et objekt af typen div i dit document. Du tilknytter det ikke som et child til noget andet object i document endnu, men ikke desto mindre initialiserer du det, og derfor bør det jo eksistere i DOM, bare ikke som child af noget object.
Avatar billede hermandsen Juniormester
29. oktober 2010 - 13:48 #6
Det er også korrekt, men det betyder jo ikke at scriptet skal udføres. Det skal det først i det øjeblik at det indsættes som child.
Avatar billede mcb2001 Nybegynder
29. oktober 2010 - 13:53 #7
jeg tror ikke vi bliver enige i det her.

Skal vi tage den forfra og så prøve at finde en løsning, der kan anvendes på den problemstilling du sidder med?
Avatar billede hermandsen Juniormester
29. oktober 2010 - 16:45 #8
Fair nok...

Jeg forsøger at lave ajax-navigation i et system.
Mit response er html-data, incl <!DOCTYPE>, <html>, <head> etc.
Herefter skiller jeg mit response ad med en regexp så jeg får det der står i spørgsmålstegnene: <title>?</title>, <body class="?"> og <body>?</body>.

Herefter overtager et eller flere callbacks som jeg ikke nødvendigvis kender, der kan pille i strukturen. Her er et af mine callbacks tilfældigvis at pille script-tags fra som har en src-attribut:

var scripts = fragment.getElementsByTagName('script');
for (var i = scripts.length-1; i >= 0; i--)
  if (scripts[i].getAttribute('src'))
    scripts[i].parentNode.removeChild(scripts[i]);

Hvis scripts udføres med eval, eller forkerte steder i DOM, vil f.eks. et document.write()-statement give en blank side, derfor skal script-tags indsættes korrekt. Der bliver desuden gjort brug af nogle attributter på mine script-tags, så der kan laves referencer i DOM, afhængig af hvor tagget ligger, derfor er placeringen på tagget også vigtig.
Avatar billede hermandsen Juniormester
04. november 2010 - 11:52 #9
Det hjalp måske ikke så meget videre?
Avatar billede mcb2001 Nybegynder
04. november 2010 - 12:19 #10
så vidt jeg kan se, så indlæser du dit response i document, og så arbejder du videre på det. Hvorfor arbejder du ikke med det som XML, og formaterer det korrekt inden du indlæser det som element på siden?
Avatar billede hermandsen Juniormester
29. november 2010 - 12:36 #11
Hvad skulle det hjælpe?
Skulle jeg så hellere lave XML-nodes i stedet? Hvis jeg indsætter dom-nodes fra et andet document, så vil mine script-tags aldrig blive udført.
Avatar billede hermandsen Juniormester
28. april 2011 - 08:45 #12
Lukker.
Løste problemet ved et hack hvor jeg først indsætter teksten i script-tagsne efter alt andet er sat ind.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester