Avatar billede al1407 Nybegynder
29. marts 2004 - 14:29 Der 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.

Nogle der har en idé til en løsning?
Avatar billede roenving Novice
29. marts 2004 - 14:37 #1
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>';
Avatar billede al1407 Nybegynder
29. marts 2004 - 14:42 #2
roenving:

menu[i][0].substring(0, menu[i][0].length - 1)

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å:

popupDiv.innerHTML = html;
Avatar billede roenving Novice
29. marts 2004 - 14:56 #3
Ja, undskyld, jeg havde tænkt på forskellen mellem .substring og .substr, hvor det er længde i den sidste men index i den første ...

Men det index tæller hen til, men ikke med, så lige her virker de to metoder altså ens !-)

-- har du prøvet at alerte din html-streng lige før den sættes i popupDiv ?-)

-- og du er vel ikke kommet til at bruge et span-tag ?o]
Avatar billede al1407 Nybegynder
29. marts 2004 - 15:00 #4
Jeg har prøvet at alerte den, ja .. og der får jeg html'et helt fint - det er .innerHTML "kaldet" der fejler, ikke mit HTML.
Hvis jeg bruger:

popupDiv.innerHTML = escape(html);

så "virker" det, dvs. jeg får en escapet streng i mit div, men den fejler ikke.

Nedenfor er mit <div> tag, som bruges til popup-menuen:

<div
    id="popupMenu"
    class="popupMenuBorder"

    onmouseover="if (popupTimeout != null) clearTimeout(popupTimeout);" onmouseout="popupTimeout = setTimeout('closePopup();', 100);"
    style="z-index: 3; padding: 2px; width: 100px; height: 50px; left: 15px; position: absolute; overflow: hidden; visibility: hidden; display: none;"
>

Sådan ser hele min kontruktion, der "laver" menuen ud:

// Build menu
for (var i = 0; i < menu.length; i++)
{
    if (menu[i][0] != '-')
    {
        if (menu[i][1].substring(0, 1) == '*')
        {
            var openLink = ' window.open(\'' + http_host + menu[i][1].substring(1, menu[i][1].length) + '\')';
        } else {
            var openLink = ' location.href = \'' + http_host + menu[i][1] + '\'';
        }
       
        html += '<div onclick="closePopup(); ' + openLink + ';" style="padding: 2px; height: 19px; vertical-align: center; cursor: pointer;" class="border_blank" onmouseover="setClassName(this, \'border_selected\');" onmouseout="setClassName(this, \'border_blank\');">';
        if (menu[i][0].charAt(menu[i][0].length - 1) == '>')
        {
            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>';
        } else {
            html += menu[i][0];
        }

        html += '</div>';

        if (menu[i][0].length > divWidth) divWidth = menu[i][0].length;
        divHeight += 21;
    } else {
        html += '<hr style="height: 1px;" class="popupMenuBorder">';
        divHeight += 15;
    }
}
Avatar billede al1407 Nybegynder
29. marts 2004 - 15:12 #5
'menu' er lavet som følger:

menu = Array(
    Array('Item text', 'item link'),
    ...
);
Avatar billede roenving Novice
29. marts 2004 - 15:29 #6
Der var nogle detaljer, men jeg kan ikke se, at de skulle være alvorlige, men prøv en gang:

var openLink;
for (var i = 0; menu.length > i; i++){
    if (menu[i][0] != '-'){
        if (menu[i][1].charAt(0) == '*'){
            openLink = 'window.open(\'' + http_host + menu[i][1].substring(1) + '\')';
        } else {
            openLink = 'location.href = \'' + http_host + menu[i][1] + '\'';
        }
       
        html += '<div onclick="closePopup(); ' + openLink + ';" style="padding: 2px; height: 19px; vertical-align: center; cursor: pointer;" class="border_blank" onmouseover="setClassName(this,0);" onmouseout="setClassName(this,1);">';
        if (menu[i][0].charAt(menu[i][0].length - 1) == '>'){
            html += '<table border="0" width="100%"><tr>';
            html += '<td>' + menu[i][0].substring(0, menu[i][0].length - 1) + '<\57td><td width="16" style="vertical-align: center;" align="right"><img src="images/button_arrow_right.gif" alt=""><\57td>';
            html += '<\57tr><\57table>';
        } else {
            html += menu[i][0];
        }

        html += '<\57div>';

        if (menu[i][0].length > divWidth) divWidth = menu[i][0].length;
        divHeight += 21;
    } else {
        html += '<hr style="height: 1px;" class="popupMenuBorder">';
        divHeight += 15;
    }
}

-- 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 !-)
Avatar billede al1407 Nybegynder
29. marts 2004 - 15:34 #7
Jeg prøver lige ..

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 :)
Avatar billede al1407 Nybegynder
29. marts 2004 - 15:42 #8
Det fungerer desværre ikke :( ..
Jeg får stadig en Unknown Runtime Error .. :/
Avatar billede al1407 Nybegynder
29. marts 2004 - 15:53 #9
Det er <table> tagget der gør knuder :| ..

html += '<!table><tr><td>' + menu[i][0].substring(1, menu[i][0].length) + '</td>\n        <td width="16" style="vertical-align: center;" align="right"><img src="images/button_arrow_right.gif" alt=""></td></tr></table>';

virker fint .. men fjerner jeg ! i "!table" så virker det ikke ...

Det forstår jeg intet af ..
Avatar billede roenving Novice
29. marts 2004 - 16:12 #10
Ja, det lyder zq underligt ?-)

Bare for at teste, så prøv:

            html += '\74table border="0" width="100%"><tr>';
Avatar billede al1407 Nybegynder
29. marts 2004 - 16:29 #11
Kan først prøve det i morgen (det er på arbejdet jeg skal bruge det), så det gør jeg i morgen :)
Avatar billede olebole Juniormester
29. marts 2004 - 16:53 #12
<ole>

'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

/mvh
</bole>
Avatar billede al1407 Nybegynder
29. marts 2004 - 17:12 #13
olebole: Jeg *skulle* mene mit HTML er 'pinligt rent'..
Desuden .. <!table ..> er vist ikke 'rent' HTML, og når jeg gør sådan, så "virker" det .. :/

Jeg har kigget lidt på noget DOM, men jeg synes ikke rigtigt jeg fattede noget af det :$ ..
Avatar billede roenving Novice
29. marts 2004 - 17:18 #14
-- 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:

http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/ecma-script-language-binding.html
Avatar billede olebole Juniormester
29. marts 2004 - 17:42 #15
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
Avatar billede al1407 Nybegynder
31. marts 2004 - 09:59 #16
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?
Avatar billede olebole Juniormester
31. marts 2004 - 13:26 #17
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.

... hvorfor tror du, jeg skriver det til dig?
Avatar billede roenving Novice
31. marts 2004 - 14:59 #18
Den har jeg forøvrigt også kæmpet med engang, i forhold til dynamisk at indsætte tabel-rækker og -celler, men så må det vel være:

        html += '<div onclick="closePopup(); ' + openLink + ';" style="padding: 2px; height: 19px; vertical-align: center; cursor: pointer;" class="border_blank" onmouseover="setClassName(this,0);" onmouseout="setClassName(this,1);">';
        if (menu[i][0].charAt(menu[i][0].length - 1) == '>'){
            html += '<table border="0" width="100%"><tbody><tr>';
            html += '<td>' + menu[i][0].substring(0, menu[i][0].length - 1) + '<\57td><td width="16" style="vertical-align: center;" align="right"><img src="images/button_arrow_right.gif" alt=""><\57td>';
            html += '<\57tr><\57tbody><\57table>';
        } else {
            html += menu[i][0];
        }

        html += '<\57div>';

-- og velbekomme, selv hvis du ikke får hul på den, skulle der jo være noget at arbejde videre med !-)
Avatar billede roenving Novice
31. marts 2004 - 17:35 #19
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 !-)
Avatar billede olebole Juniormester
31. marts 2004 - 17:48 #20
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  :)
Avatar billede al1407 Nybegynder
31. marts 2004 - 19:08 #21
Puha .. det er godtnok langhåret :) .. men i har da styr på jeres stuff ;) ..
Tak for jeres svar :) ..
Avatar billede olebole Juniormester
31. marts 2004 - 21:20 #22
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
Avatar billede roenving Novice
31. marts 2004 - 23:45 #23
-- og jeg takker også for points ;~}
Avatar billede al1407 Nybegynder
31. marts 2004 - 23:50 #24
olebole:

"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)"

ha ha, nej nej - jeg vidste godt jeg var på dybere vand, end jeg kunne bunde på ;) .. Men man kan ikke give mig skyld for ikke at forsøge? :D

Det var så lidt, og tak til jer begge :)
Avatar billede olebole Juniormester
01. april 2004 - 03:22 #25
Jeg kender det selv alt for godt - men al respekt for forsøget  ;o)
... og selv tak  :)
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
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

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

IT-JOB

Netcompany A/S

Network Engineer

Forsvarsministeriets Materiel- og Indkøbsstyrelse

Cyberdivisionen søger Entreprise Arkitekt

Riskpoint A/S (Riskpoint Solutions Limited)

IT Business Analyst