29. marts 2004 - 14:29Der er
23 kommentarer og 2 løsninger
Problem med .innerHTML
Hejsa !
Jeg har et javascript der bygger en popup-menu op som html og indsætter det i et <div> tag, via .innerHTML.
Det giver imidlertid nogle problemer hvis jeg laver en table i html'et. Hvis jeg fjerner følgende kode:
html += '<table border="0" width="100%"><tr>'; html += '<td>' + menu[i][0].substring(0, menu[i][0].length - 1) + '</td><td width="16" style="vertical-align: center;" align="right"><img src="images/button_arrow_right.gif" alt=""></td>'; html += '</tr></table>';
og erstatter den med:
html += menu[i][0];
så virker det fint, men koden som jeg fjerner virker ikke. Jeg synes jeg har checket at alt er escapet korrekt (der er intet der skal escapes) samt at jeg ikke har for mange ' eller " nogle steder.
Jeg får en "Unknown runtime error" når jeg prøver at køre scriptet.
I hvert fald er det en skør konstruktion at tage indholdet af en streng fra den første karakter til den sidste i stedet for bare at tage strengen -- resultatet er nemlig det samme ...
Prøv med:
html += '<table border="0" width="100%"><tr>'; html += '<td>' + menu[i][0] + '</td><td width="16" style="vertical-align: center;" align="right"><img src="images/button_arrow_right.gif" alt=""></td>'; html += '</tr></table>';
den tager fra pos 0 til og med <længde> - 1 .. altså MINUS den sisdste karakter (som er en '>' og betyder for mit script at den skal bruge <table> konstruktionen istedet for en "clean" en (hvor der ikke er en "pil" til sidst))
Jeg er ikke den syge javascript haj, men jeg mener dog at min kode er korrekt nok - men jeg undrer mig over hvorfor jeg får en Unknown runtime error på:
-- og så vil jeg da anbefale, at du ikke ændrer classname on-the-fly, specielt på genererede elementer er det en langsommelig metode, så lav din setClassName f.eks. sådan:
var styles = ['border:2px solid black;background:#987','border:0px;background:#fff']; function setClassName(elm,idx){ var st = styles[idx].split(";"); for(i=0;st.length>i;i++){ st[i] = st[i].split(":"); elm.style.setAttribute(st[i][0],st[i][1]); } }
-- den sidste har jeg ikke selv testet, men ideen skulle være klar nok, og i hvert fald bedre end, at browseren hele tiden skal kaste sit css-DOM-træ ud, og lave et nyt forfra !-)
Ja, det er lidt langsommelidt at ændre classname, har jeg fundet ud af - men jeg tænkte ikke på at gøre det på den måde du har gjort. Problemet, om man kan kalde det, er at jeg har et stylesheet som bruges overalt på et intranet, hvor klasserne som bruges på denne popup menu også bruges andre steder, så det at have dem i et array, det ødelægger lidt det at have et "centralt" stylesheet .. men jeg vil da lige prøve det :)
'innerHTML' er ikke standard og kan være en quirky ting at bruge ... ikke mindst når man bevæger sig ud i mere komplekse transaktioner og ikke skriver pinlig korrekt HTML. Derfor løber folk ofte ind i runtime-errors i den slags situationer.
Det er langt mere problemfrit at anvende de standardiserede DOM/ECMA bindings. F.eks: 'document.createElement', 'OBJECT.appendChild', 'OBJECT.replaceChild', osv
-- og, hvis du godt vil nogle lidt mere specielle ting, f.eks. kalde funktioner med parametre, kan du bruge OBJECT.cloneNode(deep), hvor du så kan have et oprettet objekt, klone det og ændre en smule på dets attributter !-)
-- og kig her efter de standardiserede definitioner:
Et table-element har _altid_ et tbody element - det kan jeg ikke se, du anvender. Alene af den grund kan du ikke kalde din HTML ren :)
At '<!table>' kan håndteres, skyldes formodentlig, at det overhovedet intet har med HTML at gøre - og derfor tolkes som en ren tekststreng. Et table-element uden et tbody-element er derimod HTML - men dårlig HTML.
Desuden kan man komme i alvorlige vanskeligheder, når man forsøger at opdatere en tabel fra sit eget indre ... svarer lidt til 'personlig hjerneoperationer' :)
Skal man anvende innerHTML til komplekse transaktioner, kræver det langt bedre indsigt i DOM, end det gør at bruge DOM/ECMA bindings (det, du fejlagtigt kalder DOM). Er du ikke stærk i DOM, bør du altså helt klart bruge de metoder, jeg refererede til ovenfor - så kan du meget lettere slippe udenom runtime-errors. /mvh
olebole: Jeg har endnu ikke set én eneste <table> konstruktion hvor der har været brugt en <tbody>. Hvem siger forøvrigt at det er dårligt HTML når det ikke er der? W3 eller dig?
Jeg har opgivet at få det til at virke. Jeg har ikke tid til at sætte mig ind i .createElement, .appendChild, .replaceChild osv.
Gider i begge lægge et svar, så i kan få point som tak for hjælpen?
Det siger jeg, fordi det er en del af W3C's HTML-rekommendationer - og har været det i årevis. Læs W3C's rekommendationer, så vil du finde ud af det.
Hvad enten du har set det eller ej - der er _altid_ et tbody-element i en tabel. Er det ikke skrevet, sætter browseren det automatisk, når siden fortolkes. Det bliver ikke skrevet ud til siden, men ligger i DOM-træet, hvilket du kan forvisse dig om, hvis du kalder en tabels 'firstChild' - og beder om at få alert'et dettes 'tagName'.
Hvis man ikke skriver det - og begynder at fiddle med mere komplekst, dynamisk HTML - er det en meget almindelig årsag til, at man får en runtime-error. Hvis man ikke skriver det, er det umuligt at lave noget somhelst fornuftig DOM-manipulation ... uanset, hvordan man prøver at lave det.
Forøvrigt er det da lidt spøjst, at Mozilla accepterer appendChild og lignende metoder på table-elementer (og ikke viser tbody-elementet i sin element-oversigt !-), mens IE holder sig strikt til at der jo er en tbody, så et tr-element ikke kan indsættes i et table-element (og de værktøjer, man kan få til IE, viser tbody-elementet !-)
Ehhhh ... Moz viser nu tbody-elementet i sin DOM-Inspector og skriver det ved alert(document.body.innerHTML) hvad enten tbody-elementet er skrevet i koden eller ej :)
Selvtak :) Det er, hvad jeg laver - og hvis du taler med en automekaniker, vil du hurtig finde ud af, at det at reparere biler ikke bare er at banke lidt med en svensknøgle hist og her. At operere en blindtarm er sikkert heller ikke ukompliceret - og vi kunne blive ved i samme spor :) Den slags opdager man dog somregel først, når man selv har kastet sig ud på en dybde, der var større end man selv troede ;o) /mvh
Jeg kender det selv alt for godt - men al respekt for forsøget ;o) ... og selv tak :)
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.