# Aufklappbare Tabelle mit Javascript



## mysai (13. November 2009)

*EDIT: In Post 13 gibt's meine aktuelle Problemstellung*


----------



## Sven Mintel (13. November 2009)

Moin mysai,

könntest du bitte mal den Quelltext posten, den dein JSP-kript erzeugt?


----------



## mysai (13. November 2009)

EDIT: siehe Post 13 für Quellcode


----------



## Sven Mintel (13. November 2009)

Inwiefern bist du daran gebunden, diese Daten mit einer Tabelle darzustellen?

Weshalb ich frage?
für das, was du  vorhast, wäre eine entsprechend deiner Datenstruktur vershachtelte <ul> wesentlich besser geeignet.


----------



## mysai (13. November 2009)

Hallo,
leider benötige ich die Tabelle.
Es ist eine Aufzählung von Bauteilen, bei der man nach Spalten sortieren kann und ich brauche für diese Sortierung die Schachtelung nach Modell.

Kann man nicht irgendwie diese Zeilen anhand ihrer ID heraussuchen und ihre Display-Eigenschaft umstellen?

EDIT: Wenn mir vielleicht noch jemand sagen könnte, wie ich aus einem Element auf eine ID prüfen könnte wäre ich sehr glücklich 
Das Problem dabei wäre nur, dass ich anhand einer Wildcard, also "*",  prüfen müsste, ob die ID passt.
Hatte mir das so in etwa vorgestellt:

```
if(aElement[i].Id == "*h*l*o"){
...
}
```


----------



## Quaese (13. November 2009)

Hi,

du könntest es mit regulären Ausdrücken verwenden. Hierzu übergibst du ein Suchmuster an die Toggle-Routine. Dort wird daraus ein regulärer Ausdruck generiert, der zum Testen dient.

Beispiel:

```
<html>
<head>
<title>www.tutorials.de</title>
<meta name="author" content="Quaese">
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
  <!--
function toggle(strPattern, _this){
  // Suchmuster generieren
  var strP = new RegExp(strPattern);
  // Kollektion aller Tabellenzeilen
  var arrTR = document.getElementById("tableID").getElementsByTagName("tr");

  // Tabellenzeilen durchlaufen
  for(var i=0; i<arrTR.length; i++){
    // Falls es sich nicht um das auslösende Element handelt UND die ID dem Suchkriterium entspricht
    if((arrTR[i] != _this) && (arrTR[i].id.search(strP) != -1)){
      // Ansicht toggeln
      if(arrTR[i].style.display == "none")
        arrTR[i].style.display = "";
      else
      	arrTR[i].style.display = "none";
    }
  }
}

window.onload = function(){
  var arrTR = document.getElementById("tableID").getElementsByTagName("tr");

  for(var i=0; i<arrTR.length; i++){
    if(arrTR[i].id != "klapper"){
      arrTR[i].style.display = "none";
    }
  }
}
 //-->
</script>
</head>
<body>
<table id="tableID">
	<tr id="klapper" onclick="toggle('1.00', this);"><td>1000 (top)</td></tr>
	<tr id="1000" onclick="toggle('10.0', this);"><td>&nbsp;1000</td></tr>
	<tr id="1010"><td>&nbsp;&nbsp;1010</td></tr>
	<tr id="1020"><td>&nbsp;&nbsp;1020</td></tr>
	<tr id="1100" onclick="toggle('11.0', this);"><td>&nbsp;1100</td></tr>
	<tr id="1110"><td>&nbsp;&nbsp;1110</td></tr>
	<tr id="1120"><td>&nbsp;&nbsp;1120</td></tr>
	<tr id="1130"><td>&nbsp;&nbsp;1130</td></tr>
	<tr id="1200" onclick="toggle('12.0', this);"><td>&nbsp;1200</td></tr>
	<tr id="1210"><td>&nbsp;&nbsp;1210</td></tr>
	<tr id="1220"><td>&nbsp;&nbsp;1220</td></tr>
	<tr id="1230"><td>&nbsp;&nbsp;1230</td></tr>
	<tr id="klapper" onclick="toggle('2.00', this);"><td>2000 (top)</td></tr>
	<tr id="2000" onclick="toggle('20.0', this);"><td>&nbsp;2000</td></tr>
	<tr id="2010"><td>&nbsp;&nbsp;2010</td></tr>
	<tr id="2020"><td>&nbsp;&nbsp;2020</td></tr>
	<tr id="2100" onclick="toggle('21.0', this);"><td>&nbsp;2100</td></tr>
	<tr id="2110"><td>&nbsp;&nbsp;2110</td></tr>
	<tr id="2120"><td>&nbsp;&nbsp;2120</td></tr>
	<tr id="2130"><td>&nbsp;&nbsp;2130</td></tr>
	<tr id="2200" onclick="toggle('22.0', this);"><td>&nbsp;2200</td></tr>
	<tr id="2210"><td>&nbsp;&nbsp;2210</td></tr>
	<tr id="2220"><td>&nbsp;&nbsp;2220</td></tr>
	<tr id="2230"><td>&nbsp;&nbsp;2230</td></tr>
</table>
</body>
</html>
```
 
Vielleicht hilft dir das weiter.

Ciao
Quaese


----------



## mysai (16. November 2009)

Hi,
vielen Dank! 
Hab das jetzt mal bei mir eingefügt und angepasst und habe leider noch ein Problem.
Wenn ich jetzt an folgendem Punkt bin:

```
Modell
Bereich<- hier bin ich/klick ich
Bauteil
Eintrag
Eintrag
Bauteil
Eintrag
Eintrag
...
```
Dann blendet er mir bei einem Klick auf Modell das Modell selbst aus und sämtliche Unterpunkte ebenso.


----------



## Quaese (16. November 2009)

Hi,

es handelt sich bei meinem Beispiel auch weniger um eine Musterlösung für dein Problem als um eine Verdeutlichung, wie die Lösung aussehen könnte.

So sind in meinem Beispiel die *onclick*-Events im *tr*-Element notiert. Damit ist es mir möglich, zu entscheiden, dass auslösende Element (this) nicht mit zu schliessen. 
Bei dir wird die Routine in Links angestossen. Entweder du hangelst dich bis zum *tr*-Element durch den Dokumentenbaum nach oben oder notierst die *onlick*-Events in den jeweiligen Zeilenelementen.

Weiterhin möchte ich anmerken, dass IDs innerhalb eines Dokuments eindeutig sein müssen.

Ciao
Quaese


----------



## mysai (16. November 2009)

Hi,
so, hat jetzt mit dem Anzeigen erstmal alles geklappt. Vielen Dank nochmal.
Habe jetzt nurnoch das Problem, dass man beim Schließen der Tabellenebenen, wenn man nicht genau die Überliegende schließt, sondern eine Ebene auslässt, nicht alle Unterebenen ausgeblendet werden.

Habe es im Moment damit gelöst, dass ich beim Schließen einer Ebene einfach alle Ebenen schließe, aber das ist ja auch keine Lösung.
Vll. hat da noch jemand ne Idee.


----------



## Quaese (16. November 2009)

Hi,

du könntest für den Fall, dass Zweige eingeklappt werden sollen, die zugehörigen Suchmuster dynamisch anpassen. Soll heissen, ab dem bereits existierenden Punkt werden die Suchmuster bis zum Stringende mit weiteren Punkten aufgefüllt.

In meinem zuerst geposteten Code, könntest du das mit folgendem angepassten Script erreichen.

```
function toggle(strPattern, _this){
  // Suchmuster generieren
  var strP = new RegExp(strPattern);
  // Kollektion aller Tabellenzeilen
  var arrTR = document.getElementById("tableID").getElementsByTagName("tr");
  var blnCheck = true;

  // Tabellenzeilen durchlaufen
  for(var i=0; i<arrTR.length; i++){
    // Falls es sich nicht um das auslösende Element handelt UND die ID dem Suchkriterium entspricht
    if((arrTR[i] != _this) && (arrTR[i].id.search(strP) != -1)){
      // Ansicht toggeln
      if(blnCheck && (arrTR[i].style.display == "none"))
        arrTR[i].style.display = "";
      else{
      	// Falls Elemente eingeklappt werden sollen
      	if(blnCheck){
          // Position des Punkts im Suchmuster ermitteln
          var intI = strPattern.search(/\./);
          // Neues Suchmuster generieren (bis zum Punkt)
          var strNewP = strPattern.substr(0,intI);
          // Rest des Suchmusters mit Punkten auffüllen
          for(var j=intI; j<strPattern.length; j++)
            strNewP += ".";

          // Neues regulären Ausdruck generieren
          strP = new RegExp(strNewP);
          // Flag setzen, um zu vermeiden, dass if-Zweig häufiger durchlaufen wird UND
          // als Kriterium in übergeordneter if-Anweisung, um sicherzustellen,
          // dass Unterkategorien auch tatsächlich geschlossen bleiben
          blnCheck = false;
        }
      	arrTR[i].style.display = "none";
      }
    }
  }
}
```
 
Ciao
Quaese


----------



## mysai (16. November 2009)

Also ganz durchblicken tu' ich da leider noch nicht ganz, aber vielleicht kannste mir ja nochmal kurz meine offen Fragen klären 


```
if(blnCheck){
	// Position des Punkts im Suchmuster ermitteln
	var intI = strPattern.search(/\./);
```
Ich verstehe nicht, wie ich hieraus meine aktuelle Position suchen kann.
also die beiden "/" sind eine Suchanfrage mit einem Array als Rückgabewert, wie ich das verstanden habe.
Das "\" ist noch einmal eine Suche ohne Array und der "." ist doch nur ein Platzhalter, oder?

Leider klappt die Funktion bei mir aber auch nicht ganz richtig, was aber möglicherwiese an einer falschen Implementierung liegen könnte. (Die alte Funktion läuft ohne Änderung einwandfrei)


----------



## Quaese (16. November 2009)

Hi,

die Funktion bekommt im ersten Argument einen String übergeben, der als Suchmuster für den regulären Ausdruck dient. Der Punkt innerhalb dieser Zeichenkette ist variabel, soll heissen:
'1.00' findet 1000, 1100, 1200, ... 1n00

Wird der Punkt nach rechts verschoben, so wird die darunter liegende Ebene angesprochen.

Willst du alle Ebenen unterhalb einer Zeile ausblenden, so müssen dort entsprechend Punkte gesetzt werden.
'11..' schliesst zum Beispiel 1101, 1110, 1120, 1132 usw.

Trifft das Script nun auf die Passage

```
if(blnCheck){
  // Position des Punkts im Suchmuster ermitteln
  var intI = strPattern.search(/\./);
```
sollen Ebenen geschlossen werden. In diesem Fall ist es notwendig, alle darunterliegenden Ebenen zu schliessen. Dazu wird das erste Vorkommen des Punktes ermittelt (mehr zur reg. Ausdrücken findest du bei SelfHTML)

```
var intI = strPattern.search(/\./); // Die "/" begrenzen den reg. Exp., "\" maskiert den Punkt, so dass er als Zeichen erkannt wird
```
Alles was vor dieser Positionsangabe steht, wird übernommen

```
var strNewP = strPattern.substr(0,intI);
```
der Rest mit Punkten aufgefüllt (siehe Kommentar im vorhergehenden Post).

Wird zum Beispiel 1.00 übergeben und es soll der Zweig und alle darunterliegenden Ebenen eingeklappt werden, wird daraus die Zeichenkette '1...' und die zugehörige Suchmaske /1.../ generiert.

Das daraus resultierende Suchmuster schliesst nun alle Ebenen, die unterhalb des Ausgangselement liegen.

Voraussetzung sind jedoch eine korrekte Struktur und die korrekte Vergabe der IDs. Das will ich hier jedoch nicht weiter erörtern, da ich der Meinung bin, dass dies aus meinem geposteten Beispiel ersichtlich ist.

Ciao
Quaese


----------



## mysai (16. November 2009)

Ah, vielen Dank für die Erklärung!
Hat mir wirklich sehr geholfen das ganze zu verstehen.
Jetzt läuft auch alles!
Vielen Dank dir noch einmal


----------

