Anne: onclick registriert nur erstes Klicken

Hallo, ich habe ein kleines Problem: Ich versuche ein Script zu schreiben, das es ermöglicht, mit <a name = "spoiler"> gekennzeichnete Bereiche zu löschen und durch das Wort "Spoiler" zu ersetzen. (In der hier gezeigten Testversion erfolgt die Ersetzung durch Klicken auf den Spoilertext.) Wenn man dann darauf klickt, soll der ursprüngliche Text wieder erscheinen.
Die Ersetzung klappt, aber wenn ich auf den ersetzten Text klicke, passiert nichts. Weiß jemand, woran das liegt und wie man es ändern kann?

Quelltext (enthält auskommentiert frühere Versuche, das Problem zu lösen):

function initspoiler() {
   aspoiler = new Array();
   var node;
   //var par;
   //var att;
   //var bnode;
   //var btext;
   var arr = document.getElementsByName('spoiler');     // Array mit sämtlichen Elementen, die den Namen "spoiler" haben
   for (var i = 0; i < arr.length; i++) {
      node = arr[i];
      /*par = arr[i].parentNode;
      aspoiler[i] = arr[i].firstChild.nodeValue;                  // so dass man mithilfe der id auf den entsprechenden Spoilertext zugreifen kann
      arr[i].removeChild(arr[i].firstChild);                      // entferne Spoilertext
      par.removeChild(arr[i]);*/

node.setAttribute("id", i);
      node.setAttribute("onclick", "showSpoiler('" + i + "')");
      node.firstChild.nodeValue = 'Spoiler';

/*      bnode = document.createElement("b");          // ersetze Text durch <b>Spoiler</b>
      node = document.createElement("a");
      att = document.createAttribute("id");
      att.nodeValue = i;
      node.setAttributeNode(att);                               // setze id jedes Elements auf seinen Platz im Array,
      att = document.createAttribute("onClick");
      att.nodeValue = "myclick('"+i+"')";
      node.setAttributeNode(att);
      btext = document.createTextNode("Spoiler");
      node.appendChild(btext);
      bnode.appendChild(node);
      par.appendChild(bnode);*/
   }
}

function showSpoiler(id) {
   alert('showSpoiler('+i+')');
   var el = document.getElementById(id);
   el.firstChild.removeChild();                                     // entferne <b>Spoiler</b>
   el.removeChild();
   var text = document.createTextNode(spoiler[id]);     // und ersetze es durch den im Array gespeicherten ursprünglichen Text
   el.appendChild(text);
   node.setAttribute("onclick", "hideSpoiler('"+id+"')");
}

Ich wäre für jegliche Hilfe dankbar!

MfG,
Anne

  1. Hi,

    var arr = document.getElementsByName('spoiler');     // Array mit sämtlichen Elementen, die den Namen "spoiler" haben

    Dürfen die betroffenen Elemente überhaupt ein name-Attribut haben?

    for (var i = 0; i < arr.length; i++) {

    [...]

    node.setAttribute("id", i);

    i ist eine Zahl. Eine Zahl kann kein gültiger Wert für eine id sein.
    Außerdem: verwende node.id = ..., sonst zickt der IE.

    node.setAttribute("onclick", "showSpoiler('" + i + "')");

    Das wird im IE nicht funktionieren, weise node.onclick eine passende Funktion zu.

    att = document.createAttribute("id");

    att.nodeValue = i;

    Eine Zahl kann immer noch kein gültiger Wert für eine id sein.
    Abgesehen davon: dieselbe ungültige Id hast Du schon für ein anderes Element verwendet, siehe oben. Id-Werte müssen dokumentweit eindeutig sein.

    node.setAttributeNode(att);                               // setze id jedes Elements auf seinen Platz im Array,

    Auch hier: node.id = ...

    att = document.createAttribute("onClick");

    s.o.

    att.nodeValue = "myclick('"+i+"')";
          node.setAttributeNode(att);

    s.o.

    function showSpoiler(id) {
       alert('showSpoiler('+i+')');

    i? oder doch id?

    var el = document.getElementById(id);

    Da Deine ungültigen ids nicht eindeutig sind, ist ein Erfolg dieses Aufrufs fraglich.

    var text = document.createTextNode(spoiler[id]);     // und ersetze es durch den im Array gespeicherten ursprünglichen Text
       el.appendChild(text);
       node.setAttribute("onclick", "hideSpoiler('"+id+"')");

    s.o.

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    Schreinerei Waechter
    O o ostern ...
    Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
    1. Hallo und erstmal danke für die Antwort!

      var arr = document.getElementsByName('spoiler');     // Array mit sämtlichen Elementen, die den Namen "spoiler" haben

      Dürfen die betroffenen Elemente überhaupt ein name-Attribut haben?

      Es ist ein <a>-Tag, also ja. Da komme ich auch problemlos dran; die Ersetzung funktioniert ja. Ebenso wie die Zuweisung einer Integer-Variablen als id (JavaScript ist ja nicht streng getyped); das habe ich extra noch mal ausprobiert. Die ID ist auch eindeutig, wenn ich nicht einen ganz bösen Programmierfehler übersehen habe.
      Daran dürfte es also nicht liegen.

      Ich habe alles mit IE und Netscape getestet. Folgender Code funktioniert:

      <script type = "text/javascript">
      <!--
      var count = 0;
      function myclick(id) {
            //alert('click ' + id);
            var node = document.getElementById(id);
            var i = 3;
            if (count == 0) {
               node.setAttribute("id", i);
               alert(node.getAttribute("id"));
               node.removeChild(node.firstChild);                      // entferne Spoilertext
               var bnode = document.createElement("b");              // und ersetze ihn durch <b>Spoiler</b>
               var btext = document.createTextNode("Spoiler");
               node.appendChild(bnode);
               node.firstChild.appendChild(btext);
               count++;
            }
            else {
               node.firstChild.nodeValue='Hallo';
               count = 0;
            }
       }

      function myclick2() {
       var node = document.getElementById('3');
              alert(node.id);
      }

      //-->
      </script>
      </head><body>
      <a id = "2" name = "spoiler" onClick="myclick('2')">Hallo</a>
      </br>
      <a onClick="myclick2()">Ashura</a>

      Es ist wirklich nur das Ersetzen des onclick - bzw. dessen zweite Ausführung - die nicht funktioniert...

  2. Hallo Anne,

    ergänzend zu MudGuard:

    att = document.createAttribute("onClick");

    ich bin mir nicht sicher, ob's an dieser Stelle wirklich entscheidend ist, aber vielleicht möchtest du sicherheitshalber die korrekte Schreibweise onclick benutzen, anstatt der mit dem Großbuchstaben mittendrin.
    Ich könnte mir vorstellen, dass genau darin der Grund liegt, dass dein neuer Eventhandler nicht beachtet wird, weil onClick etwas anderes ist als onclick.

    So long,
     Martin

    --
    Wer im Glashaus sitzt, sollte sich nur im Dunkeln ausziehen.
  3. Ich wäre für jegliche Hilfe dankbar!

    Prizipiell würde ich diese ganzen create-, set- und getAttribute Funktionen weglassen, es sei denn du willst selbstdefinierte Attribute verwenden.
    Du kannst in JS jederzeit mit object.attribut = value einem Attribut einen wert zuweisen und automatisch erzeugen. Zumal z.b. jedes HTML Element nach createElement ein id Attribut besitzt. Gerade der IE zickt mit diesen Funktionen gerne rum.

    Den onclick Event kannst du so registieren:
    node.onclick = showSpoiler;

    Den Parameter benötigst du gar nicht, da innerhalb von showSpoiler this dem angeklickten Element entspricht und das ist ja das was du dort bearbeitet möchtest.

    Struppi.

    --
    Javascript ist toll (Perl auch!)
    1. In der ganz, ganz verkürzten Version zumindest funktioniert es damit! Danke! (Das mit dem this hatte ich übrigens vermutet und im Netz gesucht, aber nichts dazu gefunden. Gut, dass ich das jetzt weiß, dann kann ich mir den ganzen id-Kram tatsächlich sparen.)

      Prizipiell würde ich diese ganzen create-, set- und getAttribute Funktionen weglassen, es sei denn du willst selbstdefinierte Attribute verwenden.
      Du kannst in JS jederzeit mit object.attribut = value einem Attribut einen wert zuweisen und automatisch erzeugen. Zumal z.b. jedes HTML Element nach createElement ein id Attribut besitzt. Gerade der IE zickt mit diesen Funktionen gerne rum.

      Den onclick Event kannst du so registieren:
      node.onclick = showSpoiler;

      Den Parameter benötigst du gar nicht, da innerhalb von showSpoiler this dem angeklickten Element entspricht und das ist ja das was du dort bearbeitet möchtest.

      Struppi.

  4. Okay, ich hab's hingekriegt. Vielen Dank für Eure Hilfe!

    Hier ist der vollständige Code, getestet unter Windows XP auf IE 6.0 und Netscape 7.2 (falls jemand mal etwas Ähnliches braucht):

    <html><head><title>Test</title>
    <script type = "text/javascript">
    <!--
    var aspoiler;

    function initSpoiler() {
       aspoiler = new Array();
       var node;
       var par;
       var bnode;
       var btext;
       var arr = document.getElementsByName('spoiler');     // Array mit sämtlichen Elementen, die den Namen "spoiler" haben
       for (var i = 0; i < arr.length; i++) {
          node = arr[i];
          aspoiler[i] = node.firstChild.nodeValue;                  // so dass man mithilfe der id auf den entsprechenden Spoilertext zugreifen kann

    node.id = i;
          node.onclick=showSpoiler;

    bnode = document.createElement("b");                      // ersetze Text durch <b>Spoiler</b>
          btext = document.createTextNode("Spoiler");
          node.replaceChild(bnode, node.firstChild);
          node.firstChild.appendChild(btext);
       }
    }

    function showSpoiler() {
       var el = this;
       var text = document.createTextNode(aspoiler[this.id]);   // ersetze <b>Spoiler</b> durch den im Array gespeicherten ursprünglichen Text
       el.replaceChild(text, el.firstChild);
       el.onclick = hideSpoiler;
    }

    function hideSpoiler() {
       this.onclick=showSpoiler;

    bnode = document.createElement("b");                          // ersetze Spoilertext wieder durch <b>Spoiler</b>
       btext = document.createTextNode("Spoiler");
       this.replaceChild(bnode, this.firstChild);
       this.firstChild.appendChild(btext);
    }

    //-->
    </script>
    </head><body onLoad = "initSpoiler()">

    <a id = "2" name = "spoiler" onclick="showSpoiler()">Hallo</a></br>
    <a id = "3" name = "spoiler">Hallo2</a>
    </br>
    </body></html>

    1. ... und nachdem ich gerade kapiert habe, weshalb eine id keine Zahl sein sollte, hab ich noch zwei Zeilen geändert:

      in initSpoiler
          node.id = 'a'+i;

      und in showSpoiler
             var text = document.createTextNode(aspoiler[this.id.substr(1,1)]);