02. maj 2003 - 20:32Der er
17 kommentarer og 1 løsning
Dom og frames Part 2
Jeg har som sagt et problem med at lave et kald til et billede fra en anden frame end den jeg står i. Min side er opdelt i tre. Og jeg trykker altså på en knap på den ene frame, og så skal jeg tjekke src'en på et billede i den anden frame(top). Jeg er med hjælp kommet så langt:
function portplanner() { if (parent.top.document.images['dk'].src=="pics/flagdk.gif") { window.open('portplanner.htm','main'); }
Den så med en fejl: 'parent.top.document.images.dk.src' er null eller ikke et objekt.
du bør ikke kalde en frame top. hvis du gør kan du muligvis bruge en OleBole hack parent.frames["top"]. -> pointer til framen "top" (utestet i denne sammenhæng) men det er stadig noget sjusk. Bare for at undgå flere terminologi forbistringer; følgende har INTET med DOM at gøre: document.all[] document.frames[] document.forms[] document.forms[pointer].elements[] document.images[] document.links[] ALLE er oldnordiske og bør undgås i videst mulig omfang. Frames bør i det hele taget undgås. Blot 2-3% af hits i dag kommer fra browsere der ikke understøtter DOM, hvor man bruger document.getElementById(id) og document.getElementsByTagName(tag)
Selvfølgelig, det kunne jeg have sagt mig selv. Det er lang tid siden at jeg har arbejdet med HTML. Jeg blander åbenbart det og DOM sammen. Tak for hurtig svar i øvrigt.
DOM er den struktur der definerer et korrekt formateret HTML dokument. I modsætning til document.all er det 1) bygget op at dynamiske Collections og ikke statiske Arrays 2) noder der hentes bevarer deres struktur så man undgår kald til det meget arbejdstunge innerHTML (der kan koste flere millisekunder real-time!!). document.all er ikke en DOM struktur da det er fladt. NS4 understøttede en putativ DOM, der blev udviklet før den offielle W3C DOM. Denne indeholder ikke convinience funktioner og det kræver en hel del af koderen. Selvom NS-DOM 0 i teorien er en effektiv dokument-struktur er den så dårligt implementeret i NS4 at de mange bugs gør det håbløst at udnytte den fuldt ud. NS fra Gecko5, og IE fra version 5 understøtter begge W3C-DOM 1 eller opefter. Det er næsten 98% af alle hits der kommer fra disse browsere. Derfor: Brug DOM og parse siden ind uden hård kobling mellem JavaScript og HTML Udvikl siden i korrekt HTML4/XHTML På den måde kan siden også anvendes af folk der har slået JavaScript fra (og her er vi oppe og ringe på 9%, selvom en del af disse hits muligvis kommer fra crawlers). (kort sagt DOM er strukturen af et HTML/XML dokument)
=maddog= >> Dine betragtninger omkring innerHTML er ikke helt korrekte (udover, at innerHTML ikke er del af nogen officiel standard). Nogen gange kan det faktisk være voldsomt meget hurtigere at bruge end DOM. Prøv f.eks. disse to scripts:
<div id="myDIV"></div>
<script type="text/JavaScript"> var opt; document.getElementById("myDIV").innerHTML = "<select id='minSel'></select>"; for (var i=0; i<1000; i++) { opt = document.createElement( "OPTION" ); document.getElementById("minSel").options.add( opt ); opt.value = "val" + i; opt.innerHTML = "Bla " + i; } </script> <script type="text/JavaScript"> /* var a = new Array(); for (var i=0; i<1000; i++) { a[i] = "<option value='val" + i + "'>Bla " + i + "</option>"; } document.getElementById("myDIV").innerHTML = "<select id='minSel'>" + a.join() + "</select>"; */ </script>
Prøv først med den udkommentering, jeg har lavet - prøv derefter at udkommentere det første i stedet =8-O
/* Ingen kald til innerHTML - korrekt DOM timestamp=(new Date()).getTime(); div = document.getElementById("myDIV"); sel = document.createElement("select"); div.appendChild(sel); for (var i=0; i<1000; i++) { opt = document.createElement( "OPTION" ); opt.value = "val"+i; opt.appendChild(document.createTextNode("Bla"+i)); } document.writeln((new Date()).getTime()-timestamp+"<br>"); // 1700 ms i IE 6 // 1260 I NS 7 */
/* 1000 kald til innerHTML timestamp=(new Date()).getTime(); document.getElementById("myDIV").innerHTML = "<select id='minSel'></select>"; for (var i=0; i<1000; i++) { opt = document.createElement( "OPTION" ); document.getElementById("minSel").options.add( opt ); opt.value = "val" + i; opt.innerHTML = "Bla " + i; } document.writeln((new Date()).getTime()-timestamp+"<br>"); // 12890 ms i IE 6 // VIRKER IKKE I NS 7 - add ikke understøttet */
/* 1000 kald til innerText timestamp=(new Date()).getTime(); document.getElementById("myDIV").innerHTML = "<select id='minSel'></select>"; for (var i=0; i<1000; i++) { opt = document.createElement( "OPTION" ); document.getElementById("minSel").options.add( opt ); opt.value = "val" + i; opt.innerText = "Bla " + i; } document.writeln((new Date()).getTime()-timestamp+"<br>"); // 9450 ms i IE 6 // VIRKER IKKE I NS 7 - add ikke understøttet */
/* 1 kald til innerHTML - buffer timestamp=(new Date()).getTime(); var a = new Array(); for (var i=0; i<1000; i++) { a[i] = "<option value='val" + i + "'>Bla " + i + "</option>"; } document.getElementById("myDIV").innerHTML = "<select id='minSel'>" + a.join() + "</select>"; document.writeln((new Date()).getTime()-timestamp+"<br>"); // 390 ms i IE 6 // 880 ms i NS 7 */
/* // 1 kald til innerHTML - concatenation timestamp=(new Date()).getTime(); var a = "" for (var i=0; i<1000; i++) { a += "<option value='val" + i + "'>Bla " + i + "</option>"; } document.getElementById("myDIV").innerHTML = "<select id='minSel'>" + a + "</select>"; document.writeln((new Date()).getTime()-timestamp+"<br>"); // 2420 ms i IE 6 // 820 ms i NS 7 --- skyldes at precompileret strings først bliver samlet i en StringBuffer */
Konklusion... Det er svært at sige jo, men det er ser ud til at hvis man kan "samle" sin opgave i en enkelt operation med en buffer er innerHTML hurtigst, men den ser ud til at tage grusomt tid hvis man skal kalde den flere gange. Korrekt DOM ser ud til at være mere lineær i sin opførsel og ikke "peake" som innerHTML gør. Og husk at dette er en simpel opgave hvor der ikke skal fjernes elementer. Du har svært ved at "gemme" det der var før du satte ind, hvis du bruger innerHTML, mens original = original.replaceNode(newNode); giver dig mulighed for at gemme denne struktur uden at den skal parses når den skal sættes ind igen. Selvom det i dette tilfælde er hurtigst med innerHTML, vil jeg nu fortsat bruge det jeg finder som det mest pålidelige, nemlig DOM. Bemærk iøvrigt at IE bliver MEGET sløv hvis man ikke har en buffer til rådighed. Derfor bør de første linjer i god kode være System = new Object(); System.buffer = new Array(); eller tilsvarende, så man ALTID ved hvor man har en buffer. Genbrug den samme buffer igen og igen med System.buffer.length =0; og IE bliver meget meget hurtigere (i dette tilfælde 6 gange, men mere realistisk ca. en 20 gange i publiserings-aktuel kode). NS gør det automatisk.. :).
Her er en mere realistisk test: http://www.xs4all.nl/~ppk/js/innerhtml.html hvor der bygges et table. I det hele taget et godt site for dem der er interessede i en smule optimering.
Derfor skriver jeg netop " ... i nogle tilfælde ... " :)
Det varierer fra opgave til opgave - og er man ude i at lave meget store og tunge klient-applikationer, gør man klogt i hele tiden at teste, hvilken metode, der er den mest effektive til den opgave, man aktuelt ønsker udført.
Ikke mindst buffer-problematikken er vigtig at huske på. Hvis du bygger en HTML-konstruktion over mange linier med document.write() eller innerHTML, vil brugen af et array, der join'es til sidst, begave dig med en hastigheds forbedring på op til flere hundrede _gange_ - i forhold til, hvis du skriver enkelt-linier ud! Ikke desto mindre ser man det hele tiden gjort forkert :)
window.buffer = new Array(); ... ville være den naturlige måde at gøre det på i JS (hvis man nu har et OOP-hovede skruet på ... hehe). /mvh
hehe. jeg har bare OOP kasketten på hele tiden. window.buffer vil være den naturlige indgang. parent.buffer[parent.buffer.length]= (fra iframes) er ikke så meget mere at skrive end hut = og når man tænker på de omkostninger der er for windows compileren... Det kan også betale sig at overveje hvordan tingene bliver sat ind. Ting der i princippet er hurtigere, men som bliver sat ind løbende vil typisk opleves som langsommere af brugeren fordi det "flimrer". Den klassiske er en masse images der en efter en dukker op rundt om på siden. Det er bedre at "spilde" nogle millisekunder og først sætte ind når man er klar.
Synes godt om
Ny brugerNybegynder
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.