Avatar billede jensgram Nybegynder
26. februar 2008 - 19:55 Der er 11 kommentarer og
2 løsninger

DOM: lastChild eller getElementsByTagName

Hej eksperter


Jeg må indrømme, at min erfaring med at tilgå HTML DOM via ECMA script er ikke-eksisterende. Derfor vil jeg gerne høre, _hvilken løsning, der er mest korrekt / virker på de ældste browsere_?

Min situation er, at jeg har noget kode, der ser omtrent således ud (en menu, hvor under-punkter først skal vises ved mouseover):


-- HTML (håber det bliver læseligt)

<ul>
  <li>
    <a href="...">...</a>
  </li>
  <li onmouseover="mnu_exp(this, true); void(0);" onmouseout="mnu_exp(this, false); void(0);">
    <a href="...">...</a>
    <ul>
      <li>
        <a href="...">...</a>
      </li>
    </ul>
  </li>
  <li>
    <a href="...">...</a>
  </li>
</ul>



-- script

/*
bliver kaldt med:
- elm : et <li>-element
- expand: skal undermenu vises eller ej?
*/


// 1.
function mnu_exp(elm, expand) {
    if (elm.hasChildNodes()) {
        sub = elm.lastChild;
       
        if (sub.nodeName.toLowerCase() == 'ul') {
            sub.style.display = (expand ? 'block' : 'none');
        }
    }
}


// 2.
function mnu_exp(elm, expand) {
    subs = elm.getElementsByTagName('ul');
   
    if (subs.length > 0) {
        subs[0].style.display = (expand ? 'block' : 'none');
    }
}



I bund og grund: Er det hip som hap at bruge hasChildNodes() og lastChild (jeg ved, at ul'en altid er den sidste) eller getElementsByTagName() ???

På forhånd tak.

- Jens Gram
Avatar billede jensgram Nybegynder
26. februar 2008 - 20:03 #1
Jeg håber naturligvis, at olebole falder over denne tråd :)
Avatar billede jensgram Nybegynder
26. februar 2008 - 20:08 #2
... og så ser jeg lige, at jeg - korrekt - har skrevet "jeg ved, at ul'en altid er den sidste"; så kan 1 vel erstattes med:

// 1.
function mnu_exp(elm, expand) {
    elm.lastChild.style.display = (expand ? 'block' : 'none');
}


(hvis det er lastChild-tilgangen, der er at foretrække...)
Avatar billede olebole Juniormester
26. februar 2008 - 22:16 #3
<ole>

Først: Tak for tilliden, Jens  ;o)

Prøv lige denne kode i både IE og FF:

<script type="text/JavaScript">
function foo() {
    var oUL = document.getElementById("gnu");
    alert( oUL.lastChild.nodeName );
}
</script>

<p><button onclick="foo()">TEST</button></p>

<ul id="gnu">
    <li>Blabla A</li>
    <li>Blabla B</li>
    <li>Blabla C</li>
    <li>Blabla D</li>
</ul>

Som du kan se, tolker de to browsere whitespace forskelligt. FF ser det sidste linjeskift i UL-blokken som ul-elementets lastChild - mens IE mener, det sidste li-element er ul-elementets lastChild  :o|

Den sikre fremgangsmåde er at skrive noget i stil med:

function foo() {
    var oUL = document.getElementById("gnu");
    var aLI = oUL.getElementsByTagName("li");
    alert( aLI[aLI.length-1].nodeName );
}

/mvh
</bole>
Avatar billede olebole Juniormester
26. februar 2008 - 22:17 #4
- og det betyder: Din egen løsning nummer 2 er bedst  ;o)
Avatar billede jensgram Nybegynder
26. februar 2008 - 22:26 #5
Jamen det var da herligt :)

I det her tilfælde bliver HTML'en spyttet ud på én lang linie, så whitespaces er i det mindste ikke noget problem.

Men #2 lader til at blive løsningen så. Jeg ved trods alt, at det er det første (og eneste) ul-element, så [0] må kunne gøre det.

Vil du smide et svar?
Avatar billede w13 Novice
26. februar 2008 - 22:29 #6
Bemærk i øvrigt også, at "void(0)" i følgende:

onmouseout="mnu_exp(this, false); void(0);"

ingen forskel gør. Du bør kun bruge den til at forhindre, f.eks. en href i at gå til en ny side, når du skriver:

href="java script:document.body.style='inline'"

det kan derfor løses med:

href="java script:document.body.style='inline';void(0)"

men i en Event-Handler (onclick, onmouseover, osv.), gør det absolut ingen forskel.
Avatar billede jensgram Nybegynder
26. februar 2008 - 22:31 #7
Jamen der er jo ingen grænser for hvor meget jeg lærer i dag...
Avatar billede w13 Novice
26. februar 2008 - 23:28 #8
:)
Avatar billede olebole Juniormester
26. februar 2008 - 23:34 #9
Når man itererer gennem en childNodes-collection - eller bruger next-/previousSibling - eller bruger first-/lastChild - så risikerer du problemer med whitespace i bl.a. Firefox.

Derfor kan der være gode grunde til at bruge din #2, men specielt når der er tale om dynamisk indsatte elementer - eller elementer, udskrevet på én linje med henblik på DOM-manipulation - kan man ofte med fordel bruge de andre  ;o)
Avatar billede olebole Juniormester
26. februar 2008 - 23:37 #10
Jeg bruger f.eks. (næsten) altid selv denne syntaks, når jeg dynamisk skal vise et eller andet stykke information/data på siden:

document.getElementById("gnu").firstChild.nodeValue = "Noget, et eller andet ...";

<div id="gnu">&nbsp;</div>
Avatar billede jensgram Nybegynder
27. februar 2008 - 08:20 #11
Jamen så bliver det den korte i dette tilfælde.

function mnu_exp(elm, expand) {
    elm.lastChild.style.display = (expand ? 'block' : 'none');
}



w13 > Gider du også lave et svar?

- Jens
Avatar billede w13 Novice
27. februar 2008 - 09:26 #12
:)
Avatar billede jensgram Nybegynder
27. februar 2008 - 09:33 #13
Mange tak for hjælpen begge.
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