blueboy: 2 Probleme mit DHTML

Hallo!

Ich hab da so meine Probleme mit dynamischem Html:
Ich benutze die DHTML-Bibliothek (daher der Befehl getElem)

array = new Array("Bogenschuetzen", "Laufen", "Eisstock");
var dynamisch =getElem("id", "dynamisch", "null")

for(i=0; i<array.length; i++) {
         var zeile=document.createElement("div");
         var text=document.createTextNode(array[i]);
         var id=document.createAttribute("id");
         id.nodeValue = array[i];
         zeile.appendChild(text);
         zeile.appendChild(id);
         dynamisch.appendChild(zeile);
         getElem("id", array[i], "null").addEventListener("click", meldung, true);
} //for

Warum funktioniert das nicht?
Ich bekomme in der Zeile zeile.appendChild(id) den Fehler "Schnittstelle nicht unterstützt" (IE6) oder Error: uncaught exception: [Exception... "Node cannot be inserted at the specified point in the hierarchy"  code: "3" nsresult: "0x80530003 (NS_ERROR_DOM_HIERARCHY_REQUEST_ERR)"  location: "file:functions.js Line: 29"] beim Firefox 1.0.1!

2. Problem:
Ich lösche vorher alle Knoten aus dem Bereich dynamisch:
for(i=0; i<dynamisch.childNodes.length; i++) {
dynamisch.removeChild(dynamisch.firstChild);
}//for
Beim 1. und 2. mal neu füllen kommt immer eine Zeile dazu, ab dem 3. mal bleibens dann 5 (obwohl es nur 3 sein sollen, siehe oben)

Was tun?

  1. Hallo,

    array = new Array("Bogenschuetzen", "Laufen", "Eisstock");
    var dynamisch =getElem("id", "dynamisch", "null")

    for(i=0; i<array.length; i++) {
             var zeile=document.createElement("div");
             var text=document.createTextNode(array[i]);
             var id=document.createAttribute("id");
             id.nodeValue = array[i];
             zeile.appendChild(text);
             zeile.appendChild(id);
             dynamisch.appendChild(zeile);
             getElem("id", array[i], "null").addEventListener("click", meldung, true);
    } //for

    Warum funktioniert das nicht?

    Weil id ein AttributeNode ist und kein normaler Node und deshalb auch nicht mit appenChild() ind den DOM-Baum eingehängt, sondern mit setAttributeNode() einem Element zugewiesen wird.
    http://de.selfhtml.org/javascript/objekte/document.htm#create_attribute

    1. Problem:

    Ich glaube/hoffe ;-)), das ist nur ein Folgefehler, wegen dem unsinnigen appendChild(id). Wenn nicht, dann melde Dich noch mal.

    viele Grüße

    Axel

    1. Also erst mal vielen Dank, das Erste funktioniert nun :)
      Das 2 Problem besteht weiterhin :|
      und ein weiteres ist aufgetaucht :(

      Ich füge einen EventListener hinzu, der an die Funktion meldung den Wert von id weitergeben soll! Warum kommt dann immer beim Laden der Seite die Meldung, nachher beim Klicken aber keine mehr? (Firefox) und beim IE gleich eine Fehlermeldung "Das Objekt unterstützt die Eigenschaft oder Methode nicht"
      Wenn ich nichts an meldung weitergebe, funktionierts aber so wie es sollte!

      function meldung(link) {
               alert("Gedrückt: " +link);
      }//Meldung

      getElem("id", array[i], "null").addEventListener("click", meldung(getElem("id", array[i], "null").getAttribute('id')), true);

      Kann ich anstatt dem "inneren" getElem auch sowas wie this oder self schreiben? die beiden funktionieren aber nicht!

      Vielen Dank im Voraus und Frohe Ostern !!

      1. Hallo,

        Also erst mal vielen Dank, das Erste funktioniert nun :)
        Das 2 Problem besteht weiterhin :|

        Hm, um da helfen zu können, müsste man sich das mal irgendwo ansehen können. Kanst Du das irgendwo online zur Verfügung stellen?

        und ein weiteres ist aufgetaucht :(

        Wenn ich nichts an meldung weitergebe, funktionierts aber so wie es sollte!

        function meldung(link) {
                 alert("Gedrückt: " +link);
        }//Meldung

        getElem("id", array[i], "null").addEventListener("click", meldung(getElem("id", array[i], "null").getAttribute('id')), true);

        Nein ;-)) Der zweite Parameter von addEventlistener() erwartet eben _keine_ einfache JavaScript-Funktion, sondern einen EventHandler. Das ist einfach ein Funktions_name_ und die Funkion bekommt das Event als _einzigen_ Parameter übergeben.
        http://de.selfhtml.org/dhtml/modelle/dom.htm#event_handling

        http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-registration

        http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventListener

        Kann ich anstatt dem "inneren" getElem auch sowas wie this oder self schreiben?

        Nein, aber das Event hat die Eigenschaft Event.target. Das ist das Element, welches das erste Ziel des Events war.

        http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-Event

        function meldung(ev) {
                 alert("Gedrückt: " + ev.target.id);
        }//Meldung

        getElem("id", array[i], "null").addEventListener("click", meldung, true);

        Soweit die DOM-Methode, die der IE nicht beherrscht.

        Ich würde es aber einfach so:

        function meldung(link) {
                 alert("Gedrückt: " +link.id);
        }//Meldung

        getElem("id", array[i], "null").onclick = function() {meldung(this);};
        machen.
        Das ist die Zuweisung einer anonymous-Funktion an die Eigenschaft onclick des Elements, welche dann wiederum die Funktion meldung(this) aufruft.

        viele Grüße

        Axel

        1. Vielen vielen Dank, das funktioniert nun super :)

          Ich hab dir die Dateien per Mail geschickt, groß sind sie ja noch nicht ;) Dieses Phänomen finde ich irgendwie witzig..

          MfG

          1. Hallo,

            Ich hab dir die Dateien per Mail geschickt, groß sind sie ja noch nicht ;)

            Bitte mach das nicht mehr. Der Sinn eines Fachforums ist es, Probleme _dort_ bis zum Ende auszudiskutieren. Das hat den Grund, dass andere Anwender, die Lösungen zu diesem Problem suchen, diese auch finden. Was nutzt denen die Aussage: "Ich hab Dir das mal gemailt." Wenn Du also keine Testseite hochladen kannst, dann poste hier den relevanten Quellcode.

            Dieses Phänomen finde ich irgendwie witzig..

            Nein ;-). Es ist das typische Problem von: "Um Rekursion zu verstehen, muss man zunächst mal Rekursion verstanden haben."

            Du hast folgende Schleife:

            for(i=0; i<dynamisch.childNodes.length; i++) {
                    alert(dynamisch.childNodes.length);
                    dynamisch.removeChild(dynamisch.firstChild);
            }//for

            Das dynamisch.removeChild(dynamisch.firstChild) ändert aber die Anzahl der childNodes in dynamisch. Dadurch wird der Endwert dynamisch.childNodes.length nach jedem Durchlauf der for-Schleife um 1 geringer. Die Schleife wird also nie alle childNodes entfernen. Nehmen wir an, dynamisch.childNodes.length wäre am Anfang 3. In der Schleife wird ein childNode enfernt, dann ist i==1 und dynamisch.childNodes.length==2. Nun wird noch ein childNode enfernt, dann ist i==2 und dynamisch.childNodes.length==1 und die Schleife ist beendet. Ein childNode bleibt übrig, drei kommen neu hinzu. Nun geht das Spiel weiter:
            anz==4; i==1; anz==3; i==2; anz==2 --> 2 bleiben übrig
            anz==5; i==1; anz==4; i==2; anz==3; i==3; anz==2 --> 2 bleiben übrig
            ...

            Das alert() zeigt übrigens, wie ich drauf gekommen bin.

            Die Lösung ist, die Anzahl der childNodes _vor_ der Schleife in einer Variablen zu seichern und _diese_ dann als Schleifenendwertzu nutzen.

            var lg_dynamisch = dynamisch.childNodes.length;
            for(i=0; i<lg_dynamisch; i++) {
                    dynamisch.removeChild(dynamisch.firstChild);
            }//for

            viele Grüße

            Axel

            1. Hallo!

              Ok, so hab ich dass dann nicht gesehen.. das nächste mal dann ;)

              Und jetzt erscheint das logisch, ich hab nicht dran gedacht, dass auch die Variable bei jedem Schleifendurchlauf aktualisiert wird! *grübel*

              Vielen vielen Dank für alles, du hast mir sehr geholfen und ich weiß, wohin ich mich wenden kann, wenn wieder was auftaucht :)

              MfG und Frohe Ostern

              1. Hallo!

                Gibt es eine Möglichkeit, einen String als Variablen-Name zu handeln?

                also:

                Variable1=Möglichkeit(Variable2);

                In Variable2 steht der Name von Variable3, und Variable1 soll den Wert von Variable3 annehmen!
                Hoff ich hab das gut genug ausgedrückt ;)

                Und wenn ich in einer externen JS-Datei globale Variablen (ausserhalb einer Funktion) definiere, und die Datei in eine HTML Datei einbinde, warum kann ich in einer Funktion dann nicht darauf zugreifen, bzw er meint, sie wären undefiniert?!

                so funktionierts, ich muss sie halt in den Funktionen erst füllen
                //Globale Variablen
                var main;
                var dynamisch;
                var lg_dynamisch;

                Aber wenn ich dynamisch global document.getElementById("dynamisch") zuweisen möchte, meint er in den Funktionen dynamisch ist undefined !
                Und wenn ich in einer Funktion die Variable als global (ohne dem var; wie irgendwo im selfhtml-script geschrieben) definieren möchte, gibts auch einen Fehler.

                Danke im Voraus!! :)

                1. Und wenn ich in einer externen JS-Datei globale Variablen (ausserhalb einer Funktion) definiere, und die Datei in eine HTML Datei einbinde, warum kann ich in einer Funktion dann nicht darauf zugreifen, bzw er meint, sie wären undefiniert?!

                  so funktionierts, ich muss sie halt in den Funktionen erst füllen
                  //Globale Variablen
                  var main;
                  var dynamisch;
                  var lg_dynamisch;

                  Die werden hier nicht gefüllt, sondern lediglich intialisiert

                  Aber wenn ich dynamisch global document.getElementById("dynamisch") zuweisen möchte, meint er in den Funktionen dynamisch ist undefined !

                  "dynamisch" hat nichts mit der Variabel dynamisch zu tun.

                  Struppi.

                  1. Die werden hier nicht gefüllt, sondern lediglich intialisiert

                    so wie ich das geschrieben hab, ist mir das klar, sie SOLLEN sich aber FÜLLEN, und das funktioniert aber nicht...

                    Aber wenn ich dynamisch global document.getElementById("dynamisch") zuweisen möchte, meint er in den Funktionen dynamisch ist undefined !

                    "dynamisch" hat nichts mit der Variabel dynamisch zu tun.

                    weiß nicht was du meinst, ich will der variable dynamisch global das da zuweisen: document.getElementById("dynamisch")
                    also
                    var dynamisch=document.getElementById("dynamisch");

                    1. Die werden hier nicht gefüllt, sondern lediglich intialisiert

                      so wie ich das geschrieben hab, ist mir das klar, sie SOLLEN sich aber FÜLLEN, und das funktioniert aber nicht...

                      Das hast du nicht geschrieben, woher sollen wir das Wissen?

                      Aber wenn ich dynamisch global document.getElementById("dynamisch") zuweisen möchte, meint er in den Funktionen dynamisch ist undefined !

                      "dynamisch" hat nichts mit der Variabel dynamisch zu tun.
                      weiß nicht was du meinst, ich will der variable dynamisch global das da zuweisen: document.getElementById("dynamisch")
                      also
                      var dynamisch=document.getElementById("dynamisch");

                      Warum schreibst du das nciht gleich so? Jetzt kommen wir der Sache näher.

                      Du kannst auf kein Element zugreifen, dass noch nicht vorhanden ist. D.h. du kannst diesen aufruf erst onload machen oder du plazierst das Skript hinter dem Element.

                      Struppi.

                      1. Sry, ich dachte, das geht aus meinem Text hervor..

                        Du kannst auf kein Element zugreifen, dass noch nicht vorhanden ist. D.h. du kannst diesen aufruf erst onload machen oder du plazierst das Skript hinter dem Element.

                        Das erscheint wiederum logisch, irgendwie so hab ich mir das auch gedacht *grübel*

                        Und für mein Problem mit den Variablen-Namen gibts keine Lösung?

                        Variable1=Möglichkeit(Variable2);

                        In Variable2 steht der Name von Variable3, und Variable1 soll den Wert von Variable3 annehmen!
                        Das ganze lässt sich mit Verzweigungen (switch) auch ausprobieren, halte ich aber für keine elegante Lösung, da das ganze dann nur schwer erweiterbar wird!

                        1. Und für mein Problem mit den Variablen-Namen gibts keine Lösung?

                          Variable1=Möglichkeit(Variable2);

                          In Variable2 steht der Name von Variable3, und Variable1 soll den Wert von Variable3 annehmen!

                          Das geht so:
                          Variable1= window[Variable2];

                          Struppi.

                    2. Hallo,

                      var dynamisch=document.getElementById("dynamisch");

                      Wenn es im Dokument ein HTML-Element (Hx, P, DIV, SPAN ...) mit der id="dynamisch" gibt, dann enthält nach dieser Zuweisung die Variable dynamisch die DOM-Node-Instanz dieses Elements.

                      Den Rest, also Dein Problem mit dem Gültigkeitsbereich von Vriablen habe ich auch nicht verstanden ;-)). Eventuell postest Du mal den Ausschnitt aus dem Quellcode.

                      viele Grüße

                      Axel

        2. getElem("id", array[i], "null").addEventListener("click", meldung(getElem("id", array[i], "null").getAttribute('id')), true);
          Nein ;-)) Der zweite Parameter von addEventlistener() erwartet eben _keine_ einfache JavaScript-Funktion, sondern einen EventHandler.

          Natürlich erwartet addEventListener eine einfache JavaScript-Funktion als Parameter. (Genauer gesagt ein Funktionsobjekt als Referenz.)

          Das ist einfach ein Funktions_name_

          Jo, eben. So wird das Funktionsobjekt referenziert, ohne die Funktion aufzurufen. Du meinst das richtige, aber die Erklärung war etwas missverständlich.

          Mathias

          1. Hallo,

            Natürlich erwartet addEventListener eine einfache JavaScript-Funktion als Parameter. (Genauer gesagt ein Funktionsobjekt als Referenz.)

            Nein, eigentlich nicht. Ein DOM-Node implementiert das Inteface EventTarget http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget. Nur deshalb gibt es Node.addEventListener() überhaupt. Die Methode
              void               addEventListener(in DOMString type,
                                                  in EventListener listener,
                                                  in boolean useCapture);
            erwartet genau diese Parameter. Ein EventListener http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventListener ist ein Interface, welches von der Funktion implementiert wird, die hier, also bei addEventListener() angegeben wurde. Soweit hast Du Recht. Was ich meinte, war, dass diese Funktion, eben weil sie das Interface EventListener implementiert, automatisch das Event als Parameter übergeben bekommt, weil sie praktisch die Methode handleEvent(e) überschreibt.

            Im Folgenden setze ich das Element mit der ID "id" als vorhanden voraus.

            Der Versuch des OPs, den EventListener zu implementieren:

            function meldung(link) {
                     alert("Gedrückt: " +link);
            }//Meldung

            getElem("id", array[i], "null").addEventListener("click", meldung(getElem("id", array[i], "null").getAttribute('id')), true);

            muss also scheitern.

            Der richtige[TM] ;-)) Weg, mit dem DOM-Eventhandling zu arbeiten wäre also:

            function meldung(evt) {
                     alert("Gedrückt: " + evt.target.id);
            }//Meldung

            getElem("id", array[i], "null").addEventListener("click", meldung, true);

            Das wollte ich zeigen.

            Da dies vom IE allerdings _gar nicht_ umgesetzt wird, schlug ich etwas anders vor.

            Dass man als EventListener natürlich auch eine Funktion mit Parameter übergeben kann, etwa so:

            function meldung(elem) {
                     alert("Gedrückt: " + elem.id);
            }//Meldung

            getElem("id", array[i], "null").addEventListener("click", function() {meldung(this);}, true);

            ist natürlich richtig. Allerdings ist das dann _nicht_ mehr DOM-Eventhandling.

            viele Grüße

            Axel

  2. So ich steh nun wirklich mit meinem Latein am Ende..

    Ich wollte die Funktionen der Navigation möglichst "abstrakt" gestalten, vor allem leicht handhabbar, ein Laie sollte auch die Punkte erweitern können.
    Mein erster Gedanke: Ein eindimensionales Array pro Menü-Hauptpunkt, die Einträge als Text anzuzeigen, und auch als ID zu speichern. Da kommt schon ein Problem, bei Umlauten funktionieren die Ids nicht mehr auf allen Systemen. Dann kommen noch die zu ladenden .html-Dateien dazu! Dann will ich vl noch eine Grafik pro Punkt einbinden..
    Das sind schon 4 Arrays nebeneinander, blöd zum Aufbauen, schwer zum Handhaben..
    Ich hab an ein mehrdimensionales Array gedacht, doch sind die doch nicht mehr so leicht zu füllen..
    Dann hab ich die Assoziativen Arrays gefunden, aber eine elegante Möglichkeit ist das auch nicht, vor allem wenn Methoden wie .length oder so nicht funktionieren..
    Datenbanken und JavaScript hab ich überhaupt noch nie was gehört, wenn das überhaupt geht, wirds nicht so einfach sein!
    Eine neue Programmiersprache wie PHP zu lernen fällt vorerst auch flach..

    Also wie würdet ihr das in JS lösen?
    Wie lösen das andere JS-basierende DHTML-Navigationen?
    Kann mir jemand einen Link zu solchen "Bibliotheken" geben, dass ich mir mal den Quelltext dort anschauen kann? Google wirft nichts gscheits aus, oder ich suche nach dem falschen ;)

    Vielen Dank schon mal!
    MfG
    ein verwirrter JS-Anfänger..

    1. Hallo,

      Ich wollte die Funktionen der Navigation möglichst "abstrakt" gestalten, vor allem leicht handhabbar, ein Laie sollte auch die Punkte erweitern können.

      *g* Das willst Du erreichen und bezeichnest Dich als "JS-Anfänger"? Das ist ein zu großes Projekt für den Anfang. Anfängerthemen sind das: http://de.selfhtml.org/dhtml/beispiele/index.htm oder das: http://de.selfhtml.org/javascript/beispiele/index.htm. Eventuell siehst Du Dir auch die Beispiele in den Tipps und Tricks- bzw. Feature-Artikeln an.

      Mein erster Gedanke: Ein eindimensionales Array pro Menü-Hauptpunkt, die Einträge als Text anzuzeigen, und auch als ID zu speichern. Da kommt schon ein Problem, bei Umlauten funktionieren die Ids nicht mehr auf allen Systemen.

      Nein, Ids dürfen keine Umlaute enthalten. http://www.w3.org/TR/html4/struct/global.html#adef-id, http://www.w3.org/TR/html4/types.html#type-name
      ...
      ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
      ...
      Der Term letter meint hier US ASCII letter [a-zA-Z].

      Dann hab ich die Assoziativen Arrays gefunden, aber eine elegante Möglichkeit ist das auch nicht, vor allem wenn Methoden wie .length oder so nicht funktionieren..

      Richtig, JavaScript kennt keine assoziativen Arrays. Die Schreibweise objektname["eigenschaftsname"] ist nur eine andere Form von objektname.eigenschaftsname oder collectionname["itemname"], collectionname.itemname oder im DOM collectionname.namedItem("itemname"). Es handelt sich also immer um ein Objekt, dessen Eigenschaft oder Item (Unterobjekt), Du anforderst, nicht um ein Array.

      Datenbanken und JavaScript hab ich überhaupt noch nie was gehört, wenn das überhaupt geht, wirds nicht so einfach sein!

      Mit JavaScript _alleine_ geht das nicht, aber: http://aktuell.de.selfhtml.org/artikel/javascript/datenbanken/index.htm.

      Wie lösen das andere JS-basierende DHTML-Navigationen?

      http://aktuell.de.selfhtml.org/links/dhtml.htm
      http://aktuell.de.selfhtml.org/links/dhtml.htm#deutschsprachige_sammlungen

      viele Grüße

      Axel

  3. Ich hab mir nun den Kopf zerbrochen, wie ich die Navigation lösen kann..

    Also mal die Problemstellung:
    Ich soll für unseren ASKÖ-Sportverein eine Homepage gestalten. Wir haben einige verschiedene Sektionen, bei alle solls dann Punkte wie Allgemeines, Termine, Ansprechpartner, Fotogalerien, Laufveranstaltungen, Anmeldung für Event usw.. geben!!
    Somit ergeben sich ziemlich viel Punkte, alle Menüpunkte statisch aufzulösen finde ich nicht optimal, da ich das einfach hasse, wenn ich in der Navigation scrollen muss. Paradebsp: http://www.inwow.de/
    Da ich aber auch nicht glaube, diese Homepage ewig verwalten zu wollen, soll das ganze ziemlich leicht überschaubar und ohne großartige Kenntnisse um Menüpunkte erweiterbar sein! Außerdem soll es möglich sein, auf zB Laufen->Allgemeines einen Bookmark im Browser setzen zu können, also ist das mit frames schon wieder nicht zu lösen (oder täusch ich mich da?)

    Also wollte ich das mit JavaScript dynamisch lösen, aber dazu reichen leider meine Programmierfähigkeiten nicht aus, siehe Rest dieses Threads^^
    Für dieses Projekt lerne ich sicher auch keine Programmiersprache wie CGI oder PHP..

    Habt ihr unter den Voraussetzungen einen Lösungsvorschlag für mich, dass dynamisch zu programmieren?

    Sonst muss ich wirklich auf eine statische Version mit verschiedene Navigations-Html-Dateien ausweichen..
    Oder gibts eine Möglichkeit, einen ganzen "Hauptpunkt" mit den Unterpunkten per JS oder so auszublenden?

    Was sagt ihr eigentlich, soll man frames noch verwenden, oder das mit Tabellen lösen, oder einfach mit CSS ausrichten?

    MfG und vielen Dank für die Mühe!

    1. Hi,

      Wir haben einige verschiedene Sektionen, bei alle solls dann Punkte wie Allgemeines, Termine, Ansprechpartner, Fotogalerien, Laufveranstaltungen, Anmeldung für Event usw.. geben!!

      dann erstelle eine Hauptnavigation für jede Sektion und jeweils angepaßte Unternavigationen.

      Somit ergeben sich ziemlich viel Punkte, alle Menüpunkte statisch aufzulösen finde ich nicht optimal, da ich das einfach hasse, wenn ich in der Navigation scrollen muss.

      Du verwechselst statisch mit "alle Menüpunkte auf jeder Seite verfügbar".

      Außerdem soll es möglich sein, auf zB Laufen->Allgemeines einen Bookmark im Browser setzen zu können, also ist das mit frames schon wieder nicht zu lösen (oder täusch ich mich da?)
      Korrekt.

      Also wollte ich das mit JavaScript dynamisch lösen, aber dazu reichen leider meine Programmierfähigkeiten nicht aus

      Und damit würdest Du einige Besucher sowiie Suchmschinen komplett ausschließen. Eine solche weitreichende Entscheidung solltest Du dem Vorstand überlassen.

      Oder gibts eine Möglichkeit, einen ganzen "Hauptpunkt" mit den Unterpunkten per JS oder so auszublenden?

      Lies mal ab http://de.selfhtml.org/css/layouts/navigationsleisten.htm#ebenen.

      freundliche Grüße
      Ingo