DOM: Objekt aus table löschen
bionic
- javascript
Hi miteinander,
ich möchte gerne mit JS mittels einer Checkbox selektierte <tr> Objekte aus einer Tabelle löschen. Meine Lösung funktioniert "halbwegs" in Firefox, aber nicht im IE6. Leider werden auch nicht alle selektierten Elemente auf einen Schlag gelöscht, was eigentlich erwünscht ist. Ist das selektieren von Objekten wirklich so aufwendig, wie ich es gemacht habe?
Hier ist der Auszug aus dem Quelltext. Habt ihr eine Idee, wie ich das besser (und vor allem korrekt) lösen könnte?
Vielen Dank!
bionic
###JS-Source###
function deleteline(elem){
for(i=0;i<document.dataform.DELETE.length;i++) {
if(document.dataform.DELETE[i].checked){
var Knoten = document.getElementsByTagName("table")[3].getElementsByTagName("tbody")[0].childNodes[i*2];
document.getElementsByTagName("table")[3].getElementsByTagName("tbody")[0].removeChild(Knoten);
}
}
}
###HTML-Auszug###
<table>
<thead>
<tr>
<td style="display: none;">Number</td>
<td class="searchcategories">1</td>
<td class="searchcategories" style="width: 80px;">2</td>
<td class="searchcategories" style="width: 80px;">3</td>
<td class="searchcategories" style="width: 40px;">Delete</td>
</tr>
<tbody id="list">
<tr>
<td style="display: none;">1</td>
<td class="searchresultsborder"><input class="class1" name="GTR1" value="asdfasdf" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="HUZ1" value="" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="POT1" value="" readonly="readonly" type="text"></td>
<td class="searchselect"><input name="DELETE" type="checkbox"></td>
</tr>
<tr>
<td style="display: none;">2</td>
<td class="searchresultsborder"><input class="class1" name="GTR2" value="asdfasdf" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="HUZ2" value="" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="POT2" value="" readonly="readonly" type="text"></td>
<td class="searchselect"><input name="DELETE" type="checkbox"></td>
</tr>
<tr>
<td style="display: none;">3</td>
<td class="searchresultsborder"><input class="class1" name="GTR3" value="asdfasdf" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="HUZ3" value="" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="POT3" value="" readonly="readonly" type="text"></td>
<td class="searchselect"><input name="DELETE" type="checkbox"></td>
</tr>
<tr>
<td style="display: none;">4</td>
<td class="searchresultsborder"><input class="notindb" name="GTR4" value="asdfasdf" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="HUZ4" value="" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="POT4" value="" readonly="readonly" type="text"></td>
<td class="searchselect"><input name="DELETE" type="checkbox"></td>
</tr>
<tr>
<td style="display: none;">5</td>
<td class="searchresultsborder"><input class="notindb" name="GTR5" value="asdfasdf" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="HUZ5" value="" readonly="readonly" type="text"></td>
<td class="searchresultsborder"><input class="class1" name="POT5" value="" readonly="readonly" type="text"></td>
<td class="searchselect"><input name="DELETE" type="checkbox"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: right;"><a href="javascript:deleteline();" class="bluebold">delete selection</a></td>
</tr>
</tfoot>
</table>
Hallo bionic,
var Knoten = document.getElementsByTagName("table")[3].getElementsByTagName("tbody")[0].childNodes[i*2];
der Einsatz von "childNodes" ist in Tabellen bei der Suche nach TRs oder TDs nicht zu empfehlen, da Zeilenumbrüche von einigen Browsern auch als Knoten angesehen werden. Ich vermute, dass du deswegen auch "2*i" als index verwendest. Versuch mal:
var Knoten = document.getElementsByTagName("table")[3].getElementsByTagName("tbody")[0].getElementsByTagName("tr")[i];
Gruß, Jürgen
Hi, das hat schon sehr viel geholfen. Danke! Hatte das vorher schonmal ausprobiert, aber da hats noch nicht geklappt. Jetzt gehts schon besser. Hast du noch eine Idee, wie man nun alle ausgewählten DELETE Checkboxen auf einmal löschen kann? Momentan ist es so, dass obwohl mehrere ausgewählt sind immer nur eine oder zwei pro Click gelöscht werden.
Merci & Gruss
Hallo bionic,
wenn du bei einer Tabelle eine Zeile löscht, "rutschen die anderen nach". Wenn also die 5. gelöscht wird, wird aus der 6. die 5 ,aus der 7. die 6 usw.. Wenn du jetzt in einer for-Schleife die Zeilen abarbeitest und einige löscht, wird die Zeile nach der gelöschten übersprungen. Lösungsvorschlag: fang unten an, also for(i=xxx.lenght-1,i>=0,i--) .
Gruß, Jürgen
Danke für dein Tipp. Ich habe das nun eingebaut und dieser Teil funktioniert. ;)
Ich habe allerdings noch ein paar Bugs:
Internet Explorer 6.0:
Firefox 1.5
Ich habe euch den Quellcode auf meinen Server geladen.
Archiv: http://www.koios.ch/js_for_selfhtml.zip
HTML: http://www.koios.ch/js_for_selfhtml/index.html
JS: http://www.koios.ch/js_for_selfhtml/scripts.js
Hat jemand eine Idee, was hier nicht sauber programmiert ist?
Vielen Dank für eure super Hilfe!
Gruss
bionic
P.S.: Kennt ihr einen guten (gratis oder OSS) Javascriptdebugger?
Hallo JürgenB.
Versuch mal:
var Knoten = document.getElementsByTagName("table")[3].getElementsByTagName("tbody")[0].getElementsByTagName("tr")[i];
Oder gleich:
var Knoten = document.getElementsByTagName("table")[3].[ref:self811;javascript/objekte/htmlelemente.htm#table@title=rows][i];
Einen schönen Montag noch.
Gruß, Ashura
Hallo Ashura,
var Knoten = document.getElementsByTagName("table")[3].[ref:self811;javascript/objekte/htmlelemente.htm#table@title=rows][i];
wenn es nur einen body gibt, kann man getElementsByTagName("tbody")[0] auch weglassen. Rows habe ich noch nie benutzt und denke daher auch nie daran. Ich benutze lieber DOM und die getElement-Methoden. Wenn man es aber einsetzt, kann man zum Löschen auch sofort deleteRow() nehmen.
Gruß, Jürgen
Hallo JürgenB.
wenn es nur einen body gibt, kann man getElementsByTagName("tbody")[0] auch weglassen.
Problem: Im IE und Opera wird implizit ein tbody-Element hinzu gefügt, wenn keines vorhanden ist, im Firefox nicht. Um sich die ganze Abfragerei zu ersparen, sollte man ruhig die älteren Kollektionen nutzen, denn dafür wurden sie geschaffen.
Ich benutze lieber DOM und die getElement-Methoden.
Ich auch, aber hin und wieder ist dies mit Kanonen auf Spatzen geschossen. Wenn für einen bestimmten Einsatzzweck bereits vorgefertigte Methoden existieren, sollte man sie meiner Meinung nach auch nutzen.
Wenn man es aber einsetzt, kann man zum Löschen auch sofort deleteRow() nehmen.
Das kann man auch per Zugriff über die DOM-Methoden.
Einen schönen Montag noch.
Gruß, Ashura
Hallo Ashura,
wenn es nur einen body gibt, kann man getElementsByTagName("tbody")[0] auch weglassen.
Problem: Im IE und Opera wird implizit ein tbody-Element hinzu gefügt, wenn keines vorhanden ist, im Firefox nicht. Um sich die ganze Abfragerei zu ersparen, sollte man ruhig die älteren Kollektionen nutzen, denn dafür wurden sie geschaffen.
also ich lasse "getElementsByTagName("tbody")[0]" bei nur einem Body immer weg, da die TRs ja immer unter TABLE liegen:
document.getElementsByTagName("table")[i].getElementsByTagName("tr")[j].getElementsByTagName("td")[k]...
Gruß, Jürgen
Hallo JürgenB.
also ich lasse "getElementsByTagName("tbody")[0]" bei nur einem Body immer weg, da die TRs ja immer unter TABLE liegen:
Ja, so ist das möglich. Ich hatte dich missverstanden.
Einen schönen Montag noch.
Gruß, Ashura
Hallo.
Wenn man es aber einsetzt, kann man zum Löschen auch sofort deleteRow() nehmen.
Das kann man auch per Zugriff über die DOM-Methoden.
BTW: Ist es ein Bug, dass Firefox hier keine Zeile entfernt?
window.onload = function () {
var mytable = document.getElementsByTagName("table")[0];
var myrowslength = mytable.getElementsByTagName("tr").length - 1;
for (var i = myrowslength; i > -1; i--) {
mytable.deleteRow(i);
}
}
<table>
<tr><td>Cell 1</td></tr>
<tr><td>Cell 2</td></tr>
<tr><td>Cell 3</td></tr>
<tr><td>Cell 4</td></tr>
</table>
Er lierfert nur Folgendes:
Fehler: uncaught exception: [Exception... "Index or size is negative or greater than the allowed amount" code: "1" nsresult: "0x80530001 (NS_ERROR_DOM_INDEX_SIZE_ERR)" location: "file:///… Line: 26"]
Konqueror, Opera und IE setzen den Code wie erwartet um.
Einen schönen Montag noch.
Gruß, Ashura
Hallo.
Wenn man es aber einsetzt, kann man zum Löschen auch sofort deleteRow() nehmen.
Das kann man auch per Zugriff über die DOM-Methoden.
BTW: Ist es ein Bug, dass Firefox hier keine Zeile entfernt?
Ob es ein Bug ist, kann ich nicht genau sagen, aber die Ursache habe ich gefunden: mein Scriptblock war als CDATA deklariert (da meine lokalen Testdokumente immer reines XHTML sind) und wurde dadurch offenbar vom Fx anders interpretiert. Eine HTML-Version des Testdokuments ohne CDATA-Deklaration lässt auch Fx das Script ausführen.
Komischer Panda.
Einen schönen Montag noch.
Gruß, Ashura
Hallo,
Ob es ein Bug ist, kann ich nicht genau sagen, aber die Ursache habe ich gefunden: mein Scriptblock war als CDATA deklariert
Nö, auch das geht bei mir im FF/1.5.
Vollständiges Beispiel:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Text des Titels</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<script type="text/javascript">
/* <![CDATA[ */
window.onload1 = function () {
var mytable = document.getElementsByTagName("table")[0];
var myrowslength = mytable.getElementsByTagName("tr").length - 1;
for (var i = myrowslength; i > -1; i--) {
mytable.deleteRow(i);
}
}
/* ]]> */
</script>
</head>
<body>
<table>
<tr><td>Cell 1</td></tr>
<tr><td>Cell 2</td></tr>
<tr><td>Cell 3</td></tr>
<tr><td>Cell 4</td></tr>
</table>
<p><a href="javascript:onload1()">test</a></p>
</body>
</html>
viele Grüße
Axel
Hallo Axel.
Vollständiges Beispiel:
Eben, mit HTML gibt es keine Probleme. Lieferst du das Dokument jedoch als XML aus, gibt es besagte Fehlermeldung und sonst keine Reaktion.
Einen schönen Montag noch.
Gruß, Ashura
Hallo,
BTW: Ist es ein Bug, dass Firefox hier keine Zeile entfernt?
Er lierfert nur Folgendes:Fehler: uncaught exception: [Exception... "Index or size is negative or greater than the allowed amount" code: "1" nsresult: "0x80530001 (NS_ERROR_DOM_INDEX_SIZE_ERR)" location: "file:///… Line: 26"]
Meiner nicht:
Mozilla/5.0 (Windows; U; Windows NT 5.0; de; rv:1.8) Gecko/20051111 Firefox/1.5
Vorher hatte ich Firefox/1.0.7, der auch nicht. Beide eliminieren die TRs vorbildlich ohne Fehler.
Die Fehler bei Nutzung von forum.de.selfhtml.org bekomme ich allerdings im 1.5er auch. Im 1.0.7er gab es die nicht.
viele Grüße
Axel
Hallo,
Hier auch nicht?
Doch, hier schon. Das lieferst Du aber auch als text/xml aus. Absicht?
viele Grüße
Axel
Hallo Axel.
Hier auch nicht?
Doch, hier schon. Das lieferst Du aber auch als text/xml aus. Absicht?
Ja, ist es. Da XHTML normalerweise möglichst auf diese Art und Weise ausgeliefert werden sollte, meine ich von Fx erwarten zu können, dass er damit keine Probleme hat.
Einen schönen Montag noch.
Gruß, Ashura
Hallo,
Hier auch nicht?
Doch, hier schon. Das lieferst Du aber auch als text/xml aus. Absicht?Ja, ist es. Da XHTML normalerweise möglichst auf diese Art und Weise ausgeliefert werden sollte,
Ähm, wie meinen? http://www.w3.org/TR/xhtml-media-types/#media-types
Hast Du mal den _wirklich_ empfohlenen Content-Type: application/xhtml+xml versucht? Ich kann leider im Moment nicht an einen Server ;-)
viele Grüße
Axel
Hallo Axel.
Hast Du mal den _wirklich_ empfohlenen Content-Type: application/xhtml+xml versucht? Ich kann leider im Moment nicht an einen Server ;-)
Ich hatte zwar nun eine .htaccess in das Verzeichnis des oben verlinkten Testdokumentes abgelegt und mit folgendem Inhalt versehen:
DefaultType application/xhtml+xml
<Files deleteRow>
ForceType application/xhtml+xml
</Files>
Aber das genügte noch nicht. Daher habe ich nun PHP eingesetzt.
Trotz application/xhtml+xml besteht der vermeintliche Fehler.
Einen schönen Montag noch.
Gruß, Ashura
Hallo,
Trotz application/xhtml+xml besteht der vermeintliche Fehler.
Hm, eventuell klärt uns ja noch jemand auf, ob das nun wirklich ein Bug ist.
Ich hatte die Vermutung, dass der Fehler auftritt, weil deleteRow() eine Methode eines HTMLTableElement und Bestandteil von Document Object Model HTML und nicht DOM XML ist. Aber mit application/xhtml+xml wird ja explizit (X)HTML ausgeliefert.
Abschließen könnte man noch testen, ob es mit Document Object Model Core, also mit getElementsByTagName auch nicht funktioniert. Wenn doch, dann ist application/xhtml+xml auch für den FireFox kein richtigs (X)HTML, sondern eher XML.
viele Grüße
Axel
Hallo Axel.
Abschließen könnte man noch testen, ob es mit Document Object Model Core, also mit getElementsByTagName auch nicht funktioniert.
Hm, das nutze ich doch bereits in meinem Beispieldokument?
window.onload = function () {
var mytable = document.getElementsByTagName("table")[0];
var myrowslength = mytable.getElementsByTagName("tr").length - 1;
for (var i = myrowslength; i > -1; i--) {
mytable.deleteRow(i);
}
}
Einen schönen Montag noch.
Gruß, Ashura
Hallo,
Abschließen könnte man noch testen, ob es mit Document Object Model Core, also mit getElementsByTagName auch nicht funktioniert.
Hm, das nutze ich doch bereits in meinem Beispieldokument?
Nein, ich meine eher so:
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function () {
var mytbody = document.getElementsByTagName("tbody")[0];
var myrows = mytbody.getElementsByTagName("tr");
for (var i = myrows.length-1; i > -1; i--) {
mytbody.removeChild(myrows[i]);
}
}
/*]]>*/
</script>
viele Grüße
Axel
Hallo Axel.
Nein, ich meine eher so:
Aha. Mit removeChild hatte ich bereits experimentiert.
Aber warum greifst du nun auf den unzuverlässigen tbody zu?
Dadurch spuckt Fx hier nur noch „Fehler: mytbody has no properties“ aus, es existiert also kein tbody-Element.
Einen schönen Montag noch.
Gruß, Ashura
Hallo,
Aber warum greifst du nun auf den unzuverlässigen tbody zu?
Dadurch spuckt Fx hier nur noch „Fehler: mytbody has no properties“ aus, es existiert also kein tbody-Element.
Dann mach halt eins rein in den HTML-Code ;-)).
Das ist übrigens auch die Fehlerquelle für FF.
Folgendes funktioniert mit
Content-Type: text/xml
und
Content-Type: application/xhtml+xml:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
<head>
<title>deleteRow</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
html,
body {
height:100%;
}
</style>
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function () {
var mytable = document.getElementsByTagName("table")[0];
var myrows = mytable.getElementsByTagName("tr");
for (var i = myrows.length-1; i > -1; i--) {
mytable.deleteRow(i);
}
}
/*]]>*/
</script>
</head>
<body>
<table>
<tbody>
<tr><td>Cell 1</td></tr>
<tr><td>Cell 2</td></tr>
<tr><td>Cell 3</td></tr>
<tr><td>Cell 4</td></tr>
<tr><td>Cell 5</td></tr>
<tr><td>Cell 6</td></tr>
<tr><td>Cell 7</td></tr>
</tbody>
</table>
</body>
</html>
Nimm das TBODY-Element raus und Der FF produziert den
Fehler: uncaught exception: [Exception... "Index or size is negative or greater than the allowed amount" code: "1" nsresult: "0x80530001 (NS_ERROR_DOM_INDEX_SIZE_ERR)" location: "http://localhost/test.xht Line: 25"]
Das _ist_ ein Bug, weil laut XHTML 1.0 DTD das TABLE-Element TBODY _oder_ TR enthalten darf. Mindestens eins davon _muss_ sein, aber TBODY _muss_ eben nicht sein.
viele Grüße
Axel
Hallo Axel.
[…] es existiert also kein tbody-Element.
Dann mach halt eins rein in den HTML-Code ;-)).
Das hatte ich in der Tat noch nicht ausprobiert.
Die Fehlermeldung des Fx ließ mich vermuten, dass er ein Problem mit der rückwärtigen Schleife hätte.
Das _ist_ ein Bug, weil laut XHTML 1.0 DTD das TABLE-Element TBODY _oder_ TR enthalten darf. Mindestens eins davon _muss_ sein, aber TBODY _muss_ eben nicht sein.
Laut Bugzilla ist dieser Bug bereits vor einigen Monaten gemeldet worden.
Einen schönen Dienstag noch.
Gruß, Ashura
Hallo,
Ich hatte die Vermutung, dass der Fehler auftritt, weil deleteRow() eine Methode eines HTMLTableElement und Bestandteil von Document Object Model HTML und nicht DOM XML ist. Aber mit application/xhtml+xml wird ja explizit (X)HTML ausgeliefert.
DOM HTML gilt auch für XHTML-Dokumente: »This section extends the DOM Level 2 Core API [DOM Level 2 Core] to describe objects and methods specific to HTML documents [HTML 4.01], and XHTML documents [XHTML 1.0].« (Introduction) Wenn Browser das DOM HTML nicht auf echte XHTML-Dokumente (XML-Dokumente mit dem XHTML-Namespace beim Wurzelelement) anwenden - wie es in der Vegangenheit zum Teil der Fall war-, dann sind sie höchstens fehlerhaft.
Mathias
hi,
Rows habe ich noch nie benutzt und denke daher auch nie daran. Ich benutze lieber DOM
*wunder* - das _ist_ doch Teil des DOM ...
gruß,
wahsaga
Hallo wahsaga,
Rows habe ich noch nie benutzt und denke daher auch nie daran. Ich benutze lieber DOM
*wunder* - das _ist_ doch Teil des DOM
Das wusste ich noch nicht. Wer die Original-Doku kennt, ist klar im Vorteil. Ich denke bei DOM immer an document.getElement... und übersehe (und meide) die "Spezialmethoden".
Gruß, Jürgen