Aufklappbare Tabelle will nicht so recht

PHPler

Grünschnabel
Huhu,

ich habe mal wieder ein Problem mit meinem JavaScript und finde einfach den Fehler nicht.

Mein Problem besteht darin, dass ich mit dem ersten Klick eine Gruppe öffnen möchte und mit dem zweiten Klick den Inhalt verstecken möchte. Jedoch kann ich nur bei Gruppe 3 mehrmals öffnen und wieder verstecken. Bei Gruppe 1 und 2 kann ich jeweils nur einmal öffnen und verstecken. Um das ganze in Quellcode zu zeigen, hier meine Dateien:

ajaxBaum.js
Code:
            function getXMLObject()  //XML OBJECT
            {
                var xmlHttp = false;
                try {
                    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP")  // For Old Microsoft Browsers
                }
                catch (e) {
                    try {
                        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")  // For Microsoft IE 6.0+
                    }
                    catch (e2) {
                        xmlHttp = false   // No Browser accepts the XMLHTTP Object then false
                    }
                }
                if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
                    xmlHttp = new XMLHttpRequest();        //For Mozilla, Opera Browsers
                }
                return xmlHttp;  // Mandatory Statement returning the ajax object created
            }
            var xmlhttp = new getXMLObject();	//xmlhttp holds the ajax object

            function request(s) {
                if(xmlhttp) {
                    xmlhttp.open("GET","gettime?orgID="+s.title,true); //send to servlet
                    xmlhttp.onreadystatechange = function(){
                        handleServerResponse(s);
                    }
                    xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                    xmlhttp.send(null);
                }
            }

            function handleServerResponse(objCell) {
                if (xmlhttp.readyState == 4) {// 4 = "loaded"
                    if(xmlhttp.status == 200) {// 200 = "OK"
                        var cName = objCell.className;
                        if (cName.toString() == "open") {
                            objCell.className = "closed";
                            hide(objCell);
                        } else {
                            var result = xmlhttp.responseText;  // Antwort
                            var intIndex = -1;                  // Zeilenindex
                            var objRow = objCell.parentNode;    // Zugehörige Zeile zur übergebenen Zelle
                            var objTBody = objRow.parentNode;   // Tabellenkörper

                            // Kollektion aller Tabellenzellen
                            var arrRows = objRow.parentNode.getElementsByTagName("tr");

                            // Kollektion durchlaufen und Zeilenindex ermitteln
                            for(var i=0; i<arrRows.length; i++){
                                if(arrRows[i] == objRow){
                                    intIndex = i;
                                    break;
                                }
                            }

                            // Falls es sich um keine gültige Zeile handelt
                            if(intIndex == -1) return;

                            // Falls der "Löschindex" existiert, werden die Felder gelöscht und aktualisiert!
                            if(intIndex+1 < arrRows.length){
                                // del-Zeilen entfernen
                                v1 = objTBody.rows[intIndex+1].cells[3].title;
                                while (v1 == "del") {
                                    objTBody.deleteRow(intIndex+1);
                                    v1 = (intIndex+1 < arrRows.length)? objTBody.rows[intIndex+1].cells[3].title : null;
                                }
                            }

                            /*/ Falls der "Löschindex" existiert, werden die Felder gelöscht
                        for(var i=0; i < arrRows.length; i++) {
                            // del-Zeilen entfernen
                            v1 = objTBody.rows[i].cells[3].title;
                            while (v1 == "del") {
                                objTBody.deleteRow(i);
                                v1 = objTBody.rows[i].cells[3].title;
                            }
                        }*/

                            objTBody.rows[intIndex].cells[0].innerHTML = "<img src=\"bullet-down.png\" />";

                            // Reihe hinzufügen!
                            for(var z = 0; z < 4; z++){
                                var newRow = objTBody.insertRow(intIndex+1);
                                for (var i = 0; i < 7; i++) {
                                    var newCell = newRow.insertCell(i);
                                    if (i > 2) {
                                        newCell.innerHTML = result + " - " + new Date().getTime();
                                        newCell.title = "del";
                                    }
                                }
                            }
                        }
                        objCell.className = "open";
                    }
                    else {
                        alert("Error during AJAX call. Please try again");
                    }
                }
            }

            function hide(objRef) {
                var objRow = objRef.parentNode;
                var objTBody = objRow.parentNode;
                var arrRows = objRow.parentNode.getElementsByTagName("tr");
                var intIndex = -1;

                for(var i=0; i<arrRows.length; i++){
                    if(arrRows[i] == objRow){
                        intIndex = i;
                        break;
                    }
                }
                for(var i=intIndex+1; arrRows.length; i++) {
                    v1 = objTBody.rows[i].cells[3].title;
                    if (v1 == "del") {
                        objTBody.rows[i].className = "gone";
                        if (i == intIndex+1) {
                            objTBody.rows[intIndex].cells[0].innerHTML = "<img src=\"bullet-right.png\" />";
                            objTBody.rows[intIndex].cells[0].value = objTBody.rows[intIndex].cells[1].value;
                        }
                    } else {
                        return;
                    }
                }
            }

index.jsp
HTML:
    <body>
        <table id="history">
            <tr id="f1">
                <th id="no"></th>
                <th id="no"></th>
                <th id="no"></th>
                <th>Art</th>
                <th>Beginn</th>
                <th>Ende</th>
                <th>Anzahl Tage</th>
            </tr>
            <tr>
                <th id="no">Abteilung II</th>
                <th id="no">-</th>
                <th id="no">-</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
            </tr>
            <tr>
                <th id="no" onClick="hide(this);"><img src="bullet-right.png" /></th>
                <th onClick="request(this);" id="no" title="12" class="closed">Gruppe 1</th>
                <th id="no">-</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
            </tr>
            <tr>
                <th id="no" onClick="hide(this);"><img src="bullet-right.png" /></th>
                <th onClick="request(this);" id="no" title="13" class="closed">Gruppe 2</th>
                <th id="no">-</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
            </tr>
            <tr>
                <th id="no" onClick="hide(this);"><img src="bullet-right.png" /></th>
                <th onClick="request(this);" id="no" title="14" class="closed">Gruppe 3</th>
                <th id="no">-</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
                <th>&nbsp;</th>
            </tr>
        </table>
    </body>

Und noch meine gettime.java welche aber wenig mit dem Problem zu tun hat sondern nur der vollständigkeit halber hier auftaucht!
Code:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 *
 * @author Roth-D
 */
public class gettime extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            /* TODO output your page here
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet gettime</title>");  
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet gettime at " + request.getContextPath () + "</h1>");
            out.println("</body>");
            out.println("</html>");
             */

            out.println(request.getParameter("orgID"));

            //out.println(request.getParameter("orgID"));
        } finally {
            out.close();
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}

Ich hoffe ihr könnt mir aus meiner kleinen Hirnblockade helfen, denn ich denke es ist nur ein kleiner Fehler.

Ich denke das Problem liegt hier bei der Zuweisung im Fett markierten Block!

Vielen Dank für eure Mühen!
 
Hi,

hoffentlich reden wir dieses Mal nicht wieder aneinander vorbei ;-)

Die hide-Funktion im readystade-Handler aufzurufen macht keinen Sinn, da die Zeilen bei einem Request ohnehin ausgetauscht werden und deshalb sichtbar sind.

Das Ein- und Ausblenden würde ich über den aktuellen Zustand der übergeordneten Tabellenzeile regeln. Dabei wird die display-Eigenschaft verwendet und entsprechend geändert.

Nach dem gleichen Schema kannst du ja auch den Klassennamen noch anpassen.

Mein Lösungsvorschlag:
Code:
function handleServerResponse(objCell) {
    if (xmlhttp.readyState == 4) {// 4 = "loaded"
        if(xmlhttp.status == 200) {// 200 = "OK"
            var cName = objCell.className;
//            if (cName.toString() == "open") {
//                objCell.className = "closed";
//                hide(objCell);
//            } else {
                var result = xmlhttp.responseText;  // Antwort
                var intIndex = -1;                  // Zeilenindex
                var objRow = objCell.parentNode;    // Zugehörige Zeile zur übergebenen Zelle
                var objTBody = objRow.parentNode;   // Tabellenkörper

                // Kollektion aller Tabellenzellen
                var arrRows = objRow.parentNode.getElementsByTagName("tr");

                // Kollektion durchlaufen und Zeilenindex ermitteln
                for(var i=0; i<arrRows.length; i++){
                    if(arrRows[i] == objRow){
                        intIndex = i;
                        break;
                    }
                }

                // Falls es sich um keine gültige Zeile handelt
                if(intIndex == -1) return;

                // Falls der "Löschindex" existiert, werden die Felder gelöscht und aktualisiert!
                if(intIndex+1 < arrRows.length){
                    // del-Zeilen entfernen
                    v1 = objTBody.rows[intIndex+1].cells[3].title;
                    while (v1 == "del") {
                        objTBody.deleteRow(intIndex+1);
                        v1 = (intIndex+1 < arrRows.length)? objTBody.rows[intIndex+1].cells[3].title : null;
                    }
                }

                /*/ Falls der "Löschindex" existiert, werden die Felder gelöscht
            for(var i=0; i < arrRows.length; i++) {
                // del-Zeilen entfernen
                v1 = objTBody.rows[i].cells[3].title;
                while (v1 == "del") {
                    objTBody.deleteRow(i);
                    v1 = objTBody.rows[i].cells[3].title;
                }
            }*/

                objTBody.rows[intIndex].cells[0].innerHTML = "<img src=\"bullet-down.png\" />";

                // Reihe hinzufügen!
                for(var z = 0; z < 4; z++){
                    var newRow = objTBody.insertRow(intIndex+1);
                    for (var i = 0; i < 7; i++) {
                        var newCell = newRow.insertCell(i);
                        if (i > 2) {
                            newCell.innerHTML = result + " - " + new Date().getTime();
                            newCell.title = "del";
                        }
                    }
                }
//            }
            objCell.className = "open";
        }
        else {
            alert("Error during AJAX call. Please try again");
        }
    }
}

function hide(objRef) {
  var objRow = objRef.parentNode;
  var objTBody = objRow.parentNode;
  var arrRows = objRow.parentNode.getElementsByTagName("tr");
  var intIndex = -1;

  for(var i=0; i<arrRows.length; i++){
      if(arrRows[i] == objRow){
          intIndex = i;
          break;
      }
  }

  for(var i=intIndex+1; objTBody.rows[i].cells[3].title=='del'; i++) {
    //objTBody.rows[i].className = "gone";
    objTBody.rows[i].style.display = (objTBody.rows[i].style.display=="none")? "" : "none";

    if (i == intIndex+1) {
        objTBody.rows[intIndex].cells[0].innerHTML = (objTBody.rows[i].style.display=="none")? "<img src=\"bullet-down.png\" />" : "<img src=\"bullet-right.png\" />";
    }

    // Fehler bei zu grossem Index abfangen
    try{
      objTBody.rows[i+1].cells[3].title;
    }catch(objExc){
      break;
    }
  }
}

Ciao
Quaese
 
Das Problem ist, ich will nicht nur bei Klick auf den Bullet Image (cells[0]) sondern auch bei Klick auf "Gruppe 1" (cells[1]) den Inhalt verstecken (hide()) in meiner vorigen Version ging das ja soweit, bis auf dass ich nur die letzte Gruppe mehrmals verstecken konnte.

Was ich vielleicht noch dazusagen hätte sollen die Klasse "gone" hat im stylesheet ein
Code:
display: none;

Nun bringt deine Version mich zwar Logik Technisch voran, was den Umgang mit JavaScript und den Möglichkeiten Stylesheets zu verändern betrifft, aber mein Problem bleibt ungelöst (tut mir leid das ich so anstrengend bin), soweit ich das verstehe.

Ich schreibe das "open" und "closed" schon extra in Zeilen die sowieso IMMER sichtbar sind und sich nicht verändern, also müsste es doch sehr einfach sein diese Auszulesen, was ich ja m.M. nach mache, aber irgendwie scheint sich bei mir der Wurm eingenistet zu haben und es will nicht so wie ich es will.

Code:
                        var cName = objCell.className;
                        if (cName.toString() == "open") {
                            objCell.className = "closed";
                            hide(objCell);
                        }
über diese Struktur prüfe ich ja, ob die Untergeordneten Elemente angezeigt werden oder nicht, wenn ja, verstecke ich diese und aktualisiere Sie nicht.

Wenn ich jetzt "Gruppe 1" anklicke bekomme ich folgendes:
Zustand 1:
Code:
			Art	Beginn	Ende	Anzahl Tage
Abteilung II	-	-	 	 	 	 
	Gruppe 1	-	 	 	 	 
12 - 1245738801223	12 - 1245738801223	12 - 1245738801223	12 - 1245738801223
12 - 1245738801223	12 - 1245738801223	12 - 1245738801223	12 - 1245738801223
12 - 1245738801223	12 - 1245738801223	12 - 1245738801223	12 - 1245738801223
12 - 1245738801222	12 - 1245738801222	12 - 1245738801222	12 - 1245738801222
	Gruppe 2	-	 	 	 	 
	Gruppe 3	-

Klicke ich wieder auf "Gruppe 1" folgendes:
Zustand 2:
Code:
			Art	Beginn	Ende	Anzahl Tage
Abteilung II	-	-	 	 	 	 
	Gruppe 1	-	 	 	 	 
	Gruppe 2	-	 	 	 	 
	Gruppe 3	-

bei erneutem Klick auf "Gruppe 1" bleibt es dann weiterhin so, obwohl Zustand 1 wieder eintreten sollte. Einzig bei "Gruppe 3" kann ich von Zustand 2 wieder Zustand 1 aufrufen und ich verstehe nicht, warum das so ist. Er will einfach nicht "closed" in das class-Tag eintragen bei den anderen Gruppen.

Ich hoffe das ist jetzt einigermaßen verständlich rübergekommen. Aber ich danke dir trotzdem schon mal, dafür dass du dir so viel Mühe gibst mir zu Helfen und ich dadurch trotzdem lerne ;)

Gruß
 
Hi,

gestern bin ich nicht mehr zum Antworten gekommen - dafür heute.

Also, mein Lösungsvorschlag gestaltet sich wie folgt:

Ich schreibe das Kriterium (open/closed) in den jeweils zugehörigen TR-Knoten der Zeilen, die immer angezeigt werden sollen. Das erledige ich in der Funktion hide, indem ich teste, welcher Wert aktuell enthalten ist und entsprechend den anderen einsetze.

Im readystate-Handler prüfe ich, ob der Klassenname open ist.
- Im Erfolgsfall blende ich die Zeilen ohne Aktualisierung aus.
- Sonst wird aktualisiert und die Zeilen eingeblendet.

Die Schaltfläche in der ersten Zelle dient wie bisher lediglich dem Toggeln der Ansicht.
Code:
function handleServerResponse(objCell) {
  if (xmlhttp.readyState == 4) {// 4 = "loaded"
    if(xmlhttp.status == 200) {// 200 = "OK"
      var cName = objCell.className;

      var result = xmlhttp.responseText;  // Antwort
      var intIndex = -1;                  // Zeilenindex
      var objRow = objCell.parentNode;    // Zugehörige Zeile zur übergebenen Zelle
      var objTBody = objRow.parentNode;   // Tabellenkörper

      // Falls die Zeilen bereits sichtbar sind -> nur verstecken
      if (objRow.className == "open") {
      	hide(objCell);

      // Falls die Zeilen nicht sichtbar sind -> aktualisieren und anzeigen
      } else {

        // Kollektion aller Tabellenzellen
        var arrRows = objRow.parentNode.getElementsByTagName("tr");

        // Kollektion durchlaufen und Zeilenindex ermitteln
        for(var i=0; i<arrRows.length; i++){
          if(arrRows[i] == objRow){
            intIndex = i;
            break;
          }
        }

        // Falls es sich um keine gültige Zeile handelt
        if(intIndex == -1) return;

        // Falls der "Löschindex" existiert, werden die Felder gelöscht und aktualisiert!
        if(intIndex+1 < arrRows.length){
          // del-Zeilen entfernen
          v1 = objTBody.rows[intIndex+1].cells[3].title;
          while (v1 == "del") {
            objTBody.deleteRow(intIndex+1);
            v1 = (intIndex+1 < arrRows.length)? objTBody.rows[intIndex+1].cells[3].title : null;
          }
        }

        objTBody.rows[intIndex].cells[0].innerHTML = "<img src=\"bullet-down.png\" />";

        // Reihe hinzufügen!
        for(var z = 0; z < 4; z++){
          var newRow = objTBody.insertRow(intIndex+1);
           for (var i = 0; i < 7; i++) {
             var newCell = newRow.insertCell(i);
             if (i > 2) {
               newCell.innerHTML = result + " - " + new Date().getTime();
               newCell.title = "del";
             }
           }
        }
        objRow.className = "open";
      }
    }
    else {
    	alert("Error during AJAX call. Please try again");
    }
  }
}

function hide(objRef) {
  var objRow = objRef.parentNode;
  var objTBody = objRow.parentNode;
  var arrRows = objRow.parentNode.getElementsByTagName("tr");
  var intIndex = -1;

  for(var i=0; i<arrRows.length; i++){
    if(arrRows[i] == objRow){
      intIndex = i;
      break;
    }
  }

  for(var i=intIndex+1; objTBody.rows[i].cells[3].title=='del'; i++) {
    if(objTBody.rows[i].style.display=="none"){
      objTBody.rows[i].style.display = "";
      objTBody.rows[i].className = "";
    }else{
      objTBody.rows[i].style.display = "none";
      objTBody.rows[i].className = "gone";
    }

    if (i == intIndex+1) {
      objTBody.rows[intIndex].cells[0].innerHTML = (objTBody.rows[i].style.display=="none")? "<img src=\"bullet-down.png\" />" : "<img src=\"bullet-right.png\" />";
      objTBody.rows[intIndex].className = (objTBody.rows[intIndex].className=="open")? "closed" : "open";
    }
    try{
      objTBody.rows[i+1].cells[3].title;
    }catch(objExc){
      break;
    }
  }
}

Ciao
Quaese
 
Hi,

gestern bin ich nicht mehr zum Antworten gekommen - dafür heute.

Also, mein Lösungsvorschlag gestaltet sich wie folgt:

Ich schreibe das Kriterium (open/closed) in den jeweils zugehörigen TR-Knoten der Zeilen, die immer angezeigt werden sollen. Das erledige ich in der Funktion hide, indem ich teste, welcher Wert aktuell enthalten ist und entsprechend den anderen einsetze.

Im readystate-Handler prüfe ich, ob der Klassenname open ist.
- Im Erfolgsfall blende ich die Zeilen ohne Aktualisierung aus.
- Sonst wird aktualisiert und die Zeilen eingeblendet.

Die Schaltfläche in der ersten Zelle dient wie bisher lediglich dem Toggeln der Ansicht.

Vielen herzlichen Dank, es funktioniert genau so, wie ich es mir gedacht habe.

Habe lediglich noch die Zeile hier angepasst, um auch die "bullets" richtig anzuzeigen:
Code:
objTBody.rows[intIndex].cells[0].innerHTML = (objTBody.rows[intIndex].className=="open") ? "<img src=\"bullet-right.png\" />" : "<img src=\"bullet-down.png\" />";

und die Zeile:
Code:
var cName = objCell.className;
gelöscht, weil ich die dann nicht mehr benötige.

Evtl. werden demnächst weitere Fragen aufkommen, da ich das ganze jetzt noch erweitern werde.

Vielen Dank nocheinmal!

Gruß
 

Neue Beiträge

Zurück