[js] Swapping nodes binnen een DOM tree

Pagina: 1
Acties:
  • 104 views sinds 30-01-2008
  • Reageer

  • KillR-B
  • Registratie: Mei 2002
  • Laatst online: 20-01 20:49
Ik probeer binnen tabel 2 rijen te swappen van positie, bijvoorbeeld rij 2 met rij 3:

code:
1
2
3
4
5
tableElement
-------------------
row_1      row_1
row_2  ->  row_3
row_3      row_2


IE heeft een hele mooie functie "moveRow(1, 2)", maar die wordt niet ondersteund in Mozilla en andere browsers.

Ik heb dus geprobeerd de innerHTML van beide TR-nodes te swappen. Maar dit pikt IE weer niet en het is bovendien geen nette manier natuurlijk ;).

Ik zat daarom aan de volgende manier te denken:
Door de TR-nodes binnen de DOM tree te swappen. En dit kan dus heel eenvoudig met de swapNode() functie van IE, maar niet in Mozilla (ik begin inmiddels van Microsoft te houden ;) )

Weet iemand een andere manier om toch deze TR-nodes (eigenlijk elke DOM-node) te kunnen 'swappen' binnen Internet Explorer EN Mozilla?

  • Rickets
  • Registratie: Augustus 2001
  • Niet online

Rickets

Finger and a shift

Er zijn zoveel leuke DOM-functies ;) Je zou eens kunnen kijken naar insertBefore in combinatie met removeChild

[ Voor 27% gewijzigd door Rickets op 25-02-2004 15:49 ]

If some cunt can fuck something up, that cunt will pick the worst possible time to fucking fuck it up, because that cunt’s a cunt.


  • McVirusS
  • Registratie: Januari 2000
  • Laatst online: 11-05 10:29
Als aanvulling op Rickets:

JavaScript:
1
2
3
4
5
6
Node.prototype.swapNode = function (node) {
    var nextSibling = this.nextSibling;
    var parentNode = this.parentNode;
    node.parentNode.replaceChild(this, node);
    parentNode.insertBefore(node, nextSibling);  
}

  • KillR-B
  • Registratie: Mei 2002
  • Laatst online: 20-01 20:49
Ah zoiets zocht ik idd, thanx McVirusS en Rickets.
Tenminste in Mozilla werkt het, alleen kent IE het Node prototype niet :(

Hij accepteert Node.prototype dus niet
Maar daar vind ik wel iets op....
Dit werkt nu:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (Browser.is_ie)  {
  tableElement.rows[nLastIndex].swapNode(tableElement.rows[nFirstIndex]);
} else {
  // Mozilla doesn't support the swapNode() method so we need to build one
  Node.prototype.swapNode = function (node) {
    var nextSibling = this.nextSibling;
    var parentNode = this.parentNode;
    node.parentNode.replaceChild(this, node);
    parentNode.insertBefore(node, nextSibling);  
  }
  
  if (nLastIndex > nFirstIndex) {
    tableElement.rows[nLastIndex].swapNode(tableElement.rows[nFirstIndex]);
  } else {
    tableElement.rows[nFirstIndex].swapNode(tableElement.rows[nLastIndex]);
  }
}

[ Voor 63% gewijzigd door KillR-B op 25-02-2004 17:06 ]


Verwijderd

KillR-B schreef op 25 februari 2004 @ 16:21:
Ah zoiets zocht ik idd, thanx McVirusS en Rickets.
Tenminste in Mozilla werkt het, alleen kent IE het Node prototype niet :(

Hij accepteert Node.prototype dus niet
Maar daar vind ik wel iets op....
Je hoeft er geen methode van te maken, natuurlijk (al is het wel iets mooier :P )...
JavaScript:
1
2
3
4
5
6
7
8
function SwapNodes( oNode1, oNode2 ) {
    var oParent1 = oNode1.parentNode;
    var oParent2 = oNode2.parentNode;
    var oClone = oNode2.cloneNode(true);
    oParent1.insertBefore(oClone, oNode1);
    oParent2.insertBefore(oNode1, oNode2);
    oParent2.removeChild(oNode2);
}

Voordeel is dat ze nu ook niet dezelfde parent hoeven te hebben.

Verwijderd

Je zou het eventueel ook iets met replaceChild kunnen doen, misschien dat dat iets sneller zou gaan. Niet dat het veel uitmaakt hoor.
Ik vraag me dan toch weer af waarom zoiets niet in dom level 3 zit, ik kon het zo gauw iig niet vinden.
edit:
Ja sorry, dat krijg je ervan als je een topic niet goed doorleest :+

[ Voor 15% gewijzigd door Verwijderd op 25-02-2004 22:44 ]


  • KillR-B
  • Registratie: Mei 2002
  • Laatst online: 20-01 20:49
Verwijderd schreef op 25 februari 2004 @ 16:58:
[...]


Je hoeft er geen methode van te maken, natuurlijk (al is het wel iets mooier :P )...
JavaScript:
1
2
3
4
5
6
7
8
function SwapNodes( oNode1, oNode2 ) {
    var oParent1 = oNode1.parentNode;
    var oParent2 = oNode2.parentNode;
    var oClone = oNode2.cloneNode(true);
    oParent1.insertBefore(oClone, oNode1);
    oParent2.insertBefore(oNode1, oNode2);
    oParent2.removeChild(oNode2);
}

Voordeel is dat ze nu ook niet dezelfde parent hoeven te hebben.
Zo kan het ook idd, maar als je een 'pointer' hebt naar de oNode2, dan ben je die pointer dus kwijt aangezien je deze node met removeChild() verwijdert ;) En ik gebruik dus zo'n 'pointer', dus de combinatie van cloneNode() en removeNode() kan ik niet gebruiken.

Met het swappen van nodes stuit ik trouwens op een nieuw probleem: Checkboxen en Radiobuttons verliezen in IE hun "checked" waarde wanneer deze in een te-swappen-node staan. Mozilla behoudt daarintegen wel de "checked" waarde. Is dit een bug van IE?
Een "selected" waarde van een SELECT blijft namelijk wel behouden onder zowel IE en Mozilla.

  • KillR-B
  • Registratie: Mei 2002
  • Laatst online: 20-01 20:49
Verwijderd schreef op 25 februari 2004 @ 17:13:
Je zou het eventueel ook iets met replaceChild kunnen doen, misschien dat dat iets sneller zou gaan. Niet dat het veel uitmaakt hoor.
Ik vraag me dan toch weer af waarom zoiets niet in dom level 3 zit, ik kon het zo gauw iig niet vinden.
Dat is ook wat ik doe ;)

Zie de Node.prototype.swapNode methode van McVirusS...

Verwijderd

KillR-B schreef op 25 februari 2004 @ 17:16:
Zo kan het ook idd, maar als je een 'pointer' hebt naar de oNode2, dan ben je die pointer dus kwijt aangezien je deze node met removeChild() verwijdert ;) En ik gebruik dus zo'n 'pointer', dus de combinatie van cloneNode() en removeNode() kan ik niet gebruiken.
In dat geval zou je ook een soort 'marker' node kunnen creeeren en invoegen. Die cloneNode heb ik nodig zodat ik de plek onthou waar de twee nodes staan. Met een marker node kan dat ook.
Met het swappen van nodes stuit ik trouwens op een nieuw probleem: Checkboxen en Radiobuttons verliezen in IE hun "checked" waarde wanneer deze in een te-swappen-node staan. Mozilla behoudt daarintegen wel de "checked" waarde. Is dit een bug van IE?
Ja, dat is een IE bug. Volgens mij onthoudt ie alleen de checked waarde als die expliciet in de HTML is gezet.

  • KillR-B
  • Registratie: Mei 2002
  • Laatst online: 20-01 20:49
Ja, dat is een IE bug. Volgens mij onthoudt ie alleen de checked waarde als die expliciet in de HTML is gezet.
Ok, daar bouw ik dan wel een workaround voor, thanx iig!

  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
KillR-B schreef op 25 februari 2004 @ 17:16:
Met het swappen van nodes stuit ik trouwens op een nieuw probleem: Checkboxen en Radiobuttons verliezen in IE hun "checked" waarde wanneer deze in een te-swappen-node staan. Mozilla behoudt daarintegen wel de "checked" waarde. Is dit een bug van IE?
Een "selected" waarde van een SELECT blijft namelijk wel behouden onder zowel IE en Mozilla.
Ik heb het probleem dat ik per te swappen divje 2 pijltjesknopjes voor het swappen heb staan (omhoog/omlaag). Dit zijn geCSS-de <a/> elementen met een speciale a:visited style. Na het swappen blijven ze op IE in de :visited stand staan. Zou dat hetzelfde probleem zijn?

Verwijderd

Genoil schreef op 25 februari 2004 @ 23:23:
Ik heb het probleem dat ik per te swappen divje 2 pijltjesknopjes voor het swappen heb staan (omhoog/omlaag). Dit zijn geCSS-de <a/> elementen met een speciale a:visited style. Na het swappen blijven ze op IE in de :visited stand staan. Zou dat hetzelfde probleem zijn?
Waarschijnlijk gebruik je zo'n constructie:
HTML:
1
2
3
<a href="javascript:doeiets()">...</a>
of
<a href="#" onclick="doeiets()">...</a>

Tip: return false.

  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
Verwijderd schreef op 26 februari 2004 @ 08:51:
[...]

Waarschijnlijk gebruik je zo'n constructie:
HTML:
1
2
3
<a href="javascript:doeiets()">...</a>
of
<a href="#" onclick="doeiets()">...</a>

Tip: return false.
Ja die tweede gebruik ik:

code:
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
    oMvu            = document.createElement("a");
    oMvu.className  = "eblock_mvu";
    oMvu.href       = "#";
    oMvu.onclick    = this.move;
    
    oMvd            = document.createElement("a");
    oMvd.className  = "eblock_mvd";
    oMvd.href       = "#";
    oMvd.onclick    = this.move;

...

MBE_Block.prototype.move =  function(e) {
    oSrc            = MBE_Editor2_EventSource(e); 
    oBlock          = oSrc.parentNode.parentNode;
    oElementBlock   = oBlock.parentNode;
    if(oSrc.className == "eblock_mvu") {
        if(oBlock.previousSibling !=null)
        {
            if(oBlock.previousSibling.className == "eblock") {
                oElementBlock.insertBefore(oBlock, oBlock.previousSibling);
            }
        }
    }
    else if(oSrc.className == "eblock_mvd") {
        if(oBlock.nextSibling!=null) {
            if(oBlock.nextSibling.className == "eblock") {
                oElementBlock.insertBefore(oBlock, oBlock.nextSibling.nextSibling);
            }
        }
    } 
    return false; // zonet erbij gezet
}


maar je tip leverde dus niets op...

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 01:01

crisp

Devver

Pixelated

nee, zo:

HTML:
1
<a href="#" onclick="doeiets();return false">bla</a>

Intentionally left blank


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
crisp schreef op 26 februari 2004 @ 10:38:
nee, zo:

HTML:
1
<a href="#" onclick="doeiets();return false">bla</a>
Hoe krijg ik dat DOM-style voor elkaar?
Ik heb nu:

code:
1
oAnchor.onclick = this.doeiets;


Zou niet weten hoe ik daar die return false bij krijg...

  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
ik loop dus vandaag ook tegen hetzelfde probleem aan als TS. hier een (niet zo generieke) workaround:

code:
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
MBE_Block.prototype.move =  function(e) {
    oSrc            = MBE_Editor2_EventSource(e); 
    oBlock          = oSrc.parentNode.parentNode;
    cBlock          = oBlock.obj;
    
    if(cBlock.m_sChildClass == "attribute") {
        oAttribute  = cBlock.getChild();
        aCheckState = oAttribute.obj.getCheckState();
    }
    
    oElementBlock   = oBlock.parentNode;
    if(oSrc.className == "eblock_mvu") {
        if(oBlock.previousSibling !=null)
        {
            if(oBlock.previousSibling.className == "eblock") {
                oElementBlock.insertBefore(oBlock, oBlock.previousSibling);
            }
        }
    }
    else if(oSrc.className == "eblock_mvd") {
        if(oBlock.nextSibling!=null) {
            if(oBlock.nextSibling.className == "eblock") {
                oElementBlock.insertBefore(oBlock, oBlock.nextSibling.nextSibling);
            }
        }
    }
    
    if(cBlock.m_sChildClass == "attribute") {
         oAttribute.obj.setCheckState(aCheckState);
    }
}


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MBE_Attribute.prototype.getCheckState = function() {
    aCBs = this.el.getElementsByTagName("input");
    aState = new Array();
    for(i = 0; i < aCBs.length; i++) {
        aState.push(aCBs[i].checked);
    }
    return aState;
}

MBE_Attribute.prototype.setCheckState = function(aCheckState) {
    aCBs = this.el.getElementsByTagName("input");
    for(i = 0; i < aCBs.length; i++) {
        aCBs[i].checked = aCheckState[i];
    }
}


overigens:
Ja, dat is een IE bug. Volgens mij onthoudt ie alleen de checked waarde als die expliciet in de HTML is gezet.
Dit is idd waar. Dit:
code:
1
2
3
4
oCB = document.createElement("input");
oCB.type = "checkbox";
oCB.checked = true;
oEl.appendChild(oCB);


levert een unchecked box op in IE6. Maar dit:
code:
1
oEl.innerHTML="<input type='radio' checked='checked'/>"

werkt dan weer wel, maar bij het swappen moet je de state dus alsnog onthouden...

[ Voor 36% gewijzigd door Genoil op 26-02-2004 13:54 ]


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
crisp schreef op 26 februari 2004 @ 10:38:
nee, zo:

HTML:
1
<a href="#" onclick="doeiets();return false">bla</a>
dus zo? (vgl m'n DOM code voor praktisch hetzelfde):

code:
1
2
3
4
5
6
    oMove           = document.createElement("span");
    sMvuHTML        = "<a class='eblock_mvu' href='#" +this.m_iId+"' onclick='MBE_Block_Move(this);return false'></a>";
    sMvdHTML        = "<a class='eblock_mvd' href='#" +this.m_iId+"' onclick='MBE_Block_Move(this);return false'></a>";
    oMove.innerHTML = sMvuHTML + sMvdHTML;
oBar.appendChild(oMove);
oBlock.appendChild(oBar)


MBE_Block_Move is ongeveer identiek (muv van verkrijgen van oSrc) aan de code die postte bij de workaround voor de checkboxes.

Maar dit werkt dus ook niet. Dus niet zo :P
Pagina: 1