[Javascript DOM] getNextNodeWithTagName?

Pagina: 1
Acties:

  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
Ik heb op mijn scherm meerdere exemplaren van onderstaande form elementen:

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<table>
  <tr>
    <td>
      <select name="a">
        <option>...</option>
      </select>
    </td>
    <td>
      <button onclick="moveItemsFromAtoB()">--></button>
      <button onclick="moveItemsFromBtoA()"><--</button>
    </td>
    <td>
      <select name="b">
        <option>...</option>
      </select>
    </td>
  </tr>
</table>


Probleem: wegens andere onderdelen van mijn totale script, kan ik de beide <select>'s geen unieke Id meegeven. Toch zou ik graag willen dat beide <button>'s, die items van de ene <select> naar de andere verplaatsen, werken en dus weten welk element ze moeten hebben.

Deze constructie is altijd hetzelfde. Ik zou dus een functie kunnen maken, zeg: getNextNodeWithTagName(startDOMNode, tagName, direction), die vanaf de button de DOM-tree gaat aflopen (terug en vooruit) op zoek naar een <select>. De eerste <select>'s die hij in beide richtingen tegenkomt zijn de <select>'s die hij nodig heeft voor het verplaatsen van de <option>'s.

Nu zit ik al bijna twee uur te prutsen met de Javascript DOM, maar het lukt mij maar niet :'(.

Heeft een van jullie een idee hoe deze functie getNextNodeWithTagName eruit zou komen te zien?

  • Johnny
  • Registratie: December 2001
  • Laatst online: 11:27

Johnny

ondergewaardeerde internetguru

gebruik 'this' zodat bij het drukken op de knop je de node van de knop meekrijgt, dan is het simpel.

HTML:
1
2
      <button onclick="moveItemsFromAtoB(this)">--></button>
      <button onclick="moveItemsFromBtoA(this)"><--</button>


JavaScript:
1
2
3
4
5
6
7
8
9
10
11
function moveItemsFromAtoB(button) {

var select = button.parentNode.childNodes[0];

}

function moveItemsFromBtoA(button) {

var select = button.parentNode.childNodes[2];

}


Misschien zal je nog een paar keer .parentNode moeten toevoegen omdat de witruimte ook als node kan tellen.

[ Voor 14% gewijzigd door Johnny op 29-09-2006 16:22 ]

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 12-02 10:50

killercow

eth0

Hmm, lastig, maar je zou zo iets kunnen proberen:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
function getNextNodeWithTagName(thisObj,tagname){
    var tags=document.getElementsByTagName(tagname);
    if(tags.length>1){
        for(var i=0;i<(tags.length-1);i++){
            if(tags[i]==thisObj){               
                return tags[(i+1)];             
            }
        }
    } else {
        return false;
    }
}

aanroepen met:
HTML:
1
<a onclick="getNextNodeWithTagName(this,this.tagName);"></a>

Of een andere reference natuurlijk

[ Voor 6% gewijzigd door killercow op 29-09-2006 16:24 ]

openkat.nl al gezien?


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 22-01 23:51

NMe

Quia Ego Sic Dico.

Waar hoort mijn topic?

Je hebt in het verleden al topics over Javascript gehad, waarom open je deze dan in het foute subforum? :)

PRG>>WEB

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
-NMe- schreef op vrijdag 29 september 2006 @ 16:24:
Waar hoort mijn topic?

Je hebt in het verleden al topics over Javascript gehad, waarom open je deze dan in het foute subforum? :)

PRG>>WEB
Woepserdefloeps, sorry!

:)

[ Voor 40% gewijzigd door Rekcor op 29-09-2006 17:08 ]


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
@Johnny: bedankt, maar jouw oplossing is me weer iets te rigide (als ik bij wijze van spreke ergens 1 spatie toevoeg, doet hij het al niet meer)

@killercow: ook bedankt, heb jouw oplossing aangepast zodat hij nu precies doet wat ik wil.

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
 * function getNextNodeWithTagName(oOffsetObject, sTagname, iDirection)
 * 
 * + finds next node in tree with specific sTagname, starting from oOffsetObject
 *
 * @param  object   oOffsetObject     The offset object
 * @param  string   sTagname    The tagname of the node to be found
 * @param  integer  iDirection  The direction (-1 for upstream, 1 for downstream)
 *
 * @returns object
 **/
function getNextNodeWithTagName(oOffsetObject, sTagname, iDirection)
{
  /* Our masterplan:
     - get all DOM objects with tag names and put them in an array
     - find our offset object in this array
     - from this point, start walking forward (or back, depending on iDirection)
       and stop when element with tag name sTagname is found  
 */ 
  //get all DOM nodes with tags
  var aoTags=document.getElementsByTagName("*"); 
  if(aoTags.length>1) {
    //walk this array and stop when oOffsetObject is found    
    for(var i=0;i<(aoTags.length);i++) {            
      if(aoTags[i]==oOffsetObject){
                
        if (iDirection==1) { //start looking downstream for DOM node with tag name sTagname        
          for (j=i; j<(aoTags.length);j++) {
            if (aoTags[j].nodeName == sTagname) {              
              return aoTags[j];
            }
          }  
        }
        else if (iDirection==-1) { //start looking upstream for DOM node with tag name sTagname        
          for (j=i; j>=0; j--) {
            if (aoTags[j].nodeName == sTagname) {              
              return aoTags[j];
            }
          } 
        }                     
      } 
    } 
  }
  else
  { 
    return false; 
  } 
} 

  • user109731
  • Registratie: Maart 2004
  • Niet online
Dat zowel 'naar boven' als 'naar beneden' zoeken op basis van iDirection (1 of -1) kan een stuk korter:
JavaScript:
1
2
3
4
5
for (j=i; j>=0; j += iDirection) {
  if (aoTags[j].nodeName == sTagname) {              
    return aoTags[j];
  }
} 

iDirection is -1 of 1, dat is te mooi om niet te gebruiken :)

Misschien heb je er wat aan :)

  • Johnny
  • Registratie: December 2001
  • Laatst online: 11:27

Johnny

ondergewaardeerde internetguru

Rekcor schreef op vrijdag 29 september 2006 @ 17:08:
@Johnny: bedankt, maar jouw oplossing is me weer iets te rigide (als ik bij wijze van spreke ergens 1 spatie toevoeg, doet hij het al niet meer)
Dat is meestal zo met computers, in de paar regels JavaScript en HTML zijn er nog honderden punten waar een spatie funest zou zijn. Hoe meer code je hebt, hoe meer spaties er kunnen worden geplaatst.

Gelukkig verschijnen spaties niet zomaar. :)

[ Voor 18% gewijzigd door Johnny op 29-09-2006 18:56 ]

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
Grote prutser schreef op vrijdag 29 september 2006 @ 18:21:
Dat zowel 'naar boven' als 'naar beneden' zoeken op basis van iDirection (1 of -1) kan een stuk korter:
JavaScript:
1
2
3
4
5
for (j=i; j>=0; j += iDirection) {
  if (aoTags[j].nodeName == sTagname) {              
    return aoTags[j];
  }
} 

iDirection is -1 of 1, dat is te mooi om niet te gebruiken :)

Misschien heb je er wat aan :)
C-kers, thanx!

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
 * function getNextNodeWithTagName(oOffsetObject, sTagname, iDirection)
 * 
 * + finds next node in tree with specific sTagname, starting from oOffsetObject
 *
 * @param  object   oOffsetObject     The offset object
 * @param  string   sTagname    The tagname of the node to be found
 * @param  integer  iDirection  The direction (-1 for upstream, 1 for downstream)
 *
 * @returns object
 **/
function getNextNodeWithTagName(oOffsetObject, sTagname, iDirection)
{
  /* Our masterplan:
     - get all DOM objects with tag names and put them in an array
     - find our offset object in this array
     - from this point, start walking forward (or back, depending on iDirection)
       and stop when element with tag name sTagname is found  
 */ 
  //get all DOM nodes with tags
  var aoTags=document.getElementsByTagName("*"); 
  if(aoTags.length>1)
  {
    //walk this array and stop when oOffsetObject is found    
    for(var i=0;i<(aoTags.length);i++)
    {            
      if(aoTags[i]==oOffsetObject)
      {                
        //walk up/downstream to find our object
        for (j=i; j<(aoTags.length) && j>=0; j += iDirection)
        {
          if (aoTags[j].nodeName == sTagname)
          {                    
            return aoTags[j];
          }
        }                             
      } 
    } 
  }
  else
  { 
    return false; 
  } 
} 

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Just for the fun of it:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function getNextNodeWithTagName(oOffsetObject, sTagname)
{
    sTagname = sTagname.toLowerCase();
    var s, e, n, o = oOffsetObject.nextSibling || oOffsetObject.parentNode.nextSibling;

    do
    {
        s = [o];
        while ((e = s.pop()))
        {
            do
            {
                if (e.nodeType == 1)
                {
                    if (e.tagName.toLowerCase() == sTagname)
                        return e;
    
                    if ((n = e.nextSibling)) s.push(n);
                    e = e.firstChild;
                }
                else
                    e = e.nextSibling;
            }
            while (e);
        }
    }
    while ((o = o.parentNode.nextSibling));

    return null;
}

function getPreviousNodeWithTagName(oOffsetObject, sTagname)
{
    sTagname = sTagname.toLowerCase();
    var s, e, n, o = oOffsetObject.previousSibling || oOffsetObject.parentNode.previousSibling;

    do
    {
        s = [o];
        while ((e = s.shift()))
        {
            do
            {
                if (e.nodeType == 1)
                {
                    if (e.tagName.toLowerCase() == sTagname)
                        return e;
    
                    if ((n = e.previousSibling)) s.push(n);
                    e = e.lastChild;
                }
                else
                    e = e.previousSibling;
            }
            while (e);
        }
    }
    while ((o = o.parentNode.previousSibling));

    return null;
}

;)

Intentionally left blank


  • user109731
  • Registratie: Maart 2004
  • Niet online
:o

Netjes, het duurde alleen even voor ik doorhad wat er waar gebeurde :)

  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
@crisp:

wat zijn precies de voordelen van jouw script boven de mijne? (behalve toLowerCase, die moet ik idd ook inbouwen)

enne.....<bloos> (he ik zie geen blozende smilie in de lijst, blozen tweakers nooit? :))....ik begrijp de volgende regel niet:

JavaScript:
1
var s, e, n, o = oOffsetObject.nextSibling || oOffsetObject.parentNode.nextSibling


Wat gebeurt hier?

[ Voor 51% gewijzigd door Rekcor op 30-09-2006 07:04 ]


  • user109731
  • Registratie: Maart 2004
  • Niet online
Rekcor schreef op zaterdag 30 september 2006 @ 07:02:
JavaScript:
1
var s, e, n, o = oOffsetObject.nextSibling || oOffsetObject.parentNode.nextSibling


Wat gebeurt hier?
Is zoiets als dit:
JavaScript:
1
2
3
4
5
6
7
8
var s;
var e;
var n;

if (oOffsetObject.nextSibling) 
 var o = oOffsetObject.nextSibling;
else if (oOffsetObject.parentNode.nextSibling) 
 var o = oOffsetObject.parentNode.nextSibling;

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Grote prutser schreef op zaterdag 30 september 2006 @ 08:24:
[...]

Is zoiets als dit:
JavaScript:
1
2
3
4
5
6
7
8
var s;
var e;
var n;

if (oOffsetObject.nextSibling) 
 var o = oOffsetObject.nextSibling;
else if (oOffsetObject.parentNode.nextSibling) 
 var o = oOffsetObject.parentNode.nextSibling;
Huh? Wil Crisp's code niet zeggen dat 'o' een boolean wordt? Dat is dan wel een interessante constructie, scheelt flink wat if's.

Fat Pizza's pizza, they are big and they are cheezy


  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 12-02 13:44
Nee, als oOffsetObject.nextSibling false is wordt de waarde van "o" oOffsetObject.parentNode.nextSibling. Anders wordt het gewoon oOffsetObject.nextSibling.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Rekcor schreef op zaterdag 30 september 2006 @ 07:02:
@crisp:

wat zijn precies de voordelen van jouw script boven de mijne? (behalve toLowerCase, die moet ik idd ook inbouwen)
snelheid ;)

Intentionally left blank


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 12-02 10:50

killercow

eth0

Rekcor,

Waarom gebruik je getElementByTagName("*") als je eigenlijk alleen de pointers naar de elementen met de gegeven tag wilt hebben?

En crisp, jouw code ziet er leuk uit, maar is het manipulaten van een array echt sneller dat het loopen?

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

killercow schreef op maandag 02 oktober 2006 @ 21:48:
Rekcor,

Waarom gebruik je getElementByTagName("*") als je eigenlijk alleen de pointers naar de elementen met de gegeven tag wilt hebben?

En crisp, jouw code ziet er leuk uit, maar is het manipulaten van een array echt sneller dat het loopen?
Jep. De array is eigenlijk niets meer dan een tijdelijke stack van nodes die eventueel nog onderzocht moeten worden. Een alternatief, bijvoorbeeld recursie, is eigenlijk alleen maar zwaarder.

Intentionally left blank


  • user109731
  • Registratie: Maart 2004
  • Niet online
killercow schreef op maandag 02 oktober 2006 @ 21:48:
Rekcor,

Waarom gebruik je getElementByTagName("*") als je eigenlijk alleen de pointers naar de elementen met de gegeven tag wilt hebben?
Dat kan niet in zijn functie. Het offset object moet ook opgezocht worden, en die kan een andere tagName hebben. Het zou wel een leuke optimalisatie kunnen zijn eventueel, maar het kan dus niet in alle gevallen :)

  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
@Crisp:

Bedankt, maarreh....in onderstaand voorbeeld wordt de fieldset niet gevonden door jouw script.

HTML:
1
2
3
4
5
6
7
<form>
  <fieldset>
    <legend>
      <button type="button" onclick="getPreviousNodeWithTagName(this, 'FIELDSET')">Clone</button>
    </legend>
  </fieldset>
</form>


Weet jij hoe dat komt? (mijn script vindt hem overigens wel)

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Omdat het geen previous node is maar een parent ;)

Intentionally left blank


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
crisp schreef op woensdag 04 oktober 2006 @ 11:14:
Omdat het geen previous node is maar een parent ;)
Tsja, de previous node kan idd de parentNode van de offsetNode zijn, maar dat moet voor het script getPreviousNode niet uitmaken toch?

[ Voor 3% gewijzigd door Rekcor op 04-10-2006 11:24 ]


Verwijderd

Rekcor schreef op woensdag 04 oktober 2006 @ 11:22:
Tsja, de previous node kan idd de parentNode van de offsetNode zijn, maar dat moet voor het script getPreviousNode niet uitmaken toch?
Crisp bedoelt met previous (terecht) preceding, oftewel eerdere siblings. Jij hebt het over ancestors.

  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
Verwijderd schreef op woensdag 04 oktober 2006 @ 13:37:
[...]

Crisp bedoelt met previous (terecht) preceding, oftewel eerdere siblings. Jij hebt het over ancestors.
Huh? Ik had de functionaliteit toch verzonnen? Dan lijkt me dat mijn definitie de enige geldige is... :?

Bij mij is 'previous node' iedere node met een nodeName. Hierarchie maakt niet uit.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Rekcor schreef op woensdag 04 oktober 2006 @ 16:15:
[...]


Huh? Ik had de functionaliteit toch verzonnen? Dan lijkt me dat mijn definitie de enige geldige is... :?

Bij mij is 'previous node' iedere node met een nodeName. Hierarchie maakt niet uit.
Ik kon uit jouw posts niet afleiden dat het element dat je zoekt ook wel eens een ancester zou kunnen zijn. 'previous node' impliceert dat het gehele element dat je zoekt zich voor de huidige node in de DOM-tree bevind en niet enkel de start-tag.
Een element dat het huidige element omspant is in mijn opinie geen 'previous' of 'next' node

[ Voor 7% gewijzigd door crisp op 04-10-2006 16:22 ]

Intentionally left blank


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
crisp schreef op woensdag 04 oktober 2006 @ 16:21:
[...]

Ik kon uit jouw posts niet afleiden dat het element dat je zoekt ook wel eens een ancester zou kunnen zijn. 'previous node' impliceert dat het gehele element dat je zoekt zich voor de huidige node in de DOM-tree bevind en niet enkel de start-tag.
Een element dat het huidige element omspant is in mijn opinie geen 'previous' of 'next' node
Oke, een misverstand dus. Ik dacht altijd dat ieder element een 'node' is. Misschien moet ik mijn functie getNextElementByTagName o.i.d. gaan noemen.

Nogmaals hartelijk dank voor je posts!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Een element is een node en omvat een start-tag en (eventueel) een end-tag en childnodes ;)

Intentionally left blank


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10-2025
<neerknielmodus>Eh... is jouw functie een beetje gemakkelijk te verbouwen tot mijn functionaliteit? Ik heb nog niet het JS-niveau om het zelf te kunnen...</nierknielmodus>

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

parentNodes kan je eenvoudig los nog checken:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
function getParentNodeWithTagName(oOffsetObject, sTagname)
{
    sTagname = sTagname.toLowerCase();
    while((oOffsetObject = oOffsetObject.parentNode))
    {
        if (oOffsetObject.tagName.toLowerCase() == sTagname)
            break;
    }

    return oOffsetObject;
}

Intentionally left blank

Pagina: 1