Franz Josef: Toggle Button verweigert den Dienst!

Hallo,

ok ich scheitere schon wieder an Grundsätzlichem :(

Was ich erreichen will ist eigentlich genauso simpel wie es trivial ist - ein Toggle Button als Bestandteil eines Javascript Quiz.

Dabei wird bei jedem Klick auf einen Link eine Funktion ausgelöst, die die Variable "eins" von false auf true setzt und den Link rot färbt. Wurde der Link allerdings bereits angeklickt, so wird die Variable "eins" wieder auf false zurückgesetzt und der Link wird grün; -

eine klassischer "Toggle" Funktion eben.

Ein weiterer Link löst die Funktion "Auswertung" aus, wenn der Link "aktiv" ist, so soll eine Alert Meldung "Ich bin richtig!", bzw. "Ich bin falsch!" auslösen, wenn der Link nicht geklickt wurde.

Nichts davon funktioniert leider. . . warum nicht?

Danke für eure Ideen!

<ul>
	<li><a href='javascript:klick(eins);' id="eins">Ich bin ein Link.</a></li>
</ul>
<p><a href='javascript:Auswertung();'>Auswertung</a></p>
<script>

var eins = false;

function klick(n) {
	if (n == false) {
		n = true;
		document.getElementById(n).style.color = "red"; 
	} else {
		n = false;
		document.getElementById(n).style.color = "green"; 
	}
}

function Auswertung () {
	if (eins) {
		alert("Ich bin richtig!");
	} else {
		alert("Ich bin falsch!");
	}
}
</script>
  1. Danke für eure Ideen!

    <input type="checkbox"> ist auch ein FlipFlop: Es speichert zwei Zustände und schaltet bei jedem Klick um.

    1. @@pl

      <input type="checkbox"> ist auch ein FlipFlop: Es speichert zwei Zustände und schaltet bei jedem Klick um.

      Dann könnte man damit ja einen Frequenzteiler bauen. Kann man.

      LLAP 🖖

      --
      “The best way to help people learn: answer their coding question an hour later, they’ll have likely figured it out by then.” —Todd Motto
      Selfcode: sh:) fo:} ch:? rl:) br:> n4:& va:| de:> zu:} fl:{ ss:| ls:# js:|
      1. @@pl

        <input type="checkbox"> ist auch ein FlipFlop: Es speichert zwei Zustände und schaltet bei jedem Klick um.

        Dann könnte man damit ja einen Frequenzteiler bauen. Kann man.

        Oder einen Ripplecounter, der Begriff ist vom Ausgangsdiagramm abgeleitet. Die Belichtungsuhr, siehe Foto, ist 33 Jahre alt, den asynchronen Zähler habe ich mit D-Flipflops aus der TTL-Schaltkreisreihe aufgebaut.

        Sogar der Optokoppler ist Eigenbau: In einem Stück Pertinax sind 2 Bohrungen, eine nimmt die LED auf, die Andere einen Fotowiderstand. Letzterer schaltet direkt die Vergrößerungslampe 220V/ max 150W.

        1. @@pl

          Dann könnte man damit ja einen Frequenzteiler bauen. Kann man.

          Oder einen Ripplecounter

          Letztendlich ist Frequenzteiler und Zähler dasselbe.

          Meiner zählte rückwärts (wenn man ☑︎ als 1 und ☐ als 0 nimmt).

          Zum Vorwärtszählen einfach die andere Flanke nehmen.
          Im Script heißt das: if (this.checked && this.nextSibling.nextSibling)
          ändern in if (!this.checked && this.nextSibling.nextSibling)

          LLAP 🖖

          --
          “The best way to help people learn: answer their coding question an hour later, they’ll have likely figured it out by then.” —Todd Motto
          Selfcode: sh:) fo:} ch:? rl:) br:> n4:& va:| de:> zu:} fl:{ ss:| ls:# js:|
  2. Hi,

    ok ich scheitere schon wieder an Grundsätzlichem :(

    ja, dein Ansatz ist unter mehreren Gesichtspunkten ungünstig bzw. sogar falsch.

    Was ich erreichen will ist eigentlich genauso simpel wie es trivial ist - ein Toggle Button als Bestandteil eines Javascript Quiz.

    Dabei wird bei jedem Klick auf einen Link eine Funktion ausgelöst, die die Variable "eins" von false auf true setzt und den Link rot färbt. Wurde der Link allerdings bereits angeklickt, so wird die Variable "eins" wieder auf false zurückgesetzt und der Link wird grün;

    Halten wir hier mal inne. Du willst beim Klicken den Zustand eines Elements ändern, das über eine ID angesprochen wird. Also brauchst du die ID als String. Gleichzeitig willst du den Zustand aber noch einmal in einer boolschen Variable halten, die dazu auch noch global ist. Warum doppelt? Frag doch an der entscheidenden Stelle direkt den Element-Status ab.

    Ich würde das Umschalten des Status realisieren, indem ich dem Element eine Klasse (z.B. "active") geben bzw. sie wieder wegnehme. Praktischerweise gibt's dafür schon was fertiges. Vom Vorhandensein dieser Klasse kann man dann auch gleich die Darstellung abhängig machen und diese Angaben ins Stylesheet verschieben, wo sie hingehören. Damit reduziert sich die Funktion auf eine einzige Anweisung, wenn man die Fehlerbehandlung außer Acht lässt. Das wollen wir aber nicht; das Script soll auch dann nicht auf die Schnauze fallen, wenn es gar kein Element mit der angegebenen ID gibt:

    function toggleStatus(eID)
     { var eRef = document.getElementById(eID);       // Element anhand der ID im DOM suchen
    
       if (eRef)                                      // Element gefunden?
        { eRef.classList.toggle("active");            // Klasse hinzufügen bzw. wegnehmen
          return (eRef.classList.contains("active");  // neuen Status zurückliefern
        }
       else                                           // im Fehlerfall (Element existiert nicht)
          return (null);                              // null als Fehler-Kennzeichen zurückgeben
     }
    

    Es gehört irgendwie zum guten Ton, dass eine Funktion auch ein Ergebnis zurückliefert; ich habe in diesem Fall den neuen Status nach dem Toggeln gewählt (true oder false), bzw. null im Fehlerfall.

    Kommen wir nun zum Aufruf der Funktion. Du hast dafür ein a-Element gewählt, und das ist eigentlich unpassend. Ein Link dient zum Aufruf einer neuen HTML-Seite, du willst aber eine Funktion innerhalb der Seite auslösen. Dafür ist das button-Element da. Also etwa so:

    <button id="eins" onclick="toggleStatus('eins');">Aktiv/Inaktiv</button>
    

    Mit CSS kann man sich den Button dann schönformatieren, wie man gerne möchte. Dasselbe für den Auswerten-Button.

    Jetzt fehlt noch deine Auswertung; auch hier fragen wir einfach die classList des ausgewählten Elements ab, ob die Klasse "active" derzeit gesetzt ist:

    function Auswertung(eID)
     { var eRef = document.getElementById(eID);       // Element anhand der ID im DOM suchen
    
       if (eRef)                                      // Element gefunden?
        { if (eRef.classList.contains("active")       // Klasse ist vorhanden
           { // Anweisungen für den OK-Fall
           }
          else
           { // Anweisungen für den Fehler-Fall
           }
        }
     }
    

    Nichts davon funktioniert leider. . . warum nicht?

    Sehen wir uns die entscheidenden Fehler bei dir an.

    <ul>
    	<li><a href='javascript:klick(eins);' id="eins">Ich bin ein Link.</a></li>
    </ul>
    

    Du übergibst den aktuellen Wert von eins, also true oder false. Innerhalb der Funktion versucht dann document.getElementById(), ein Element mit der ID true bzw. false zu finden, das geht in die Hose.

    function klick(n) {
    	if (n == false) {
    		n = true;
    		document.getElementById(n).style.color = "red"; 
    	} else {
    		n = false;
    		document.getElementById(n).style.color = "green"; 
    	}
    }
    

    Vom falschen Parametertyp mal abgesehen mixt du hier lustig Variablennamen, Variablenwerte und ID-Werte. Was du da machst, ist in Programmiersprachen wie C mit Zeigern durchaus möglich: Einer Funktion nicht den Wert einer Variablen zu übergeben, sondern eine sogenannte Referenz auf eine Variable außerhalb der Funktion. Mit JS ist das AFAIK nicht möglich.

    Was noch dazukommt: In deinem Code ist n eine lokale Variable in der Funktion. Ihr Wert wird aber nie auf die globale Variable eins zurückgeschrieben, deren Wert du übergeben hast.

    So long,
     Martin

    PS: Mit dem Vorschlag von pl, als zustandsspeicherndes Element ein checkbox-Element (einschließlich des zugehörigen label-Elements, versteht sich) zu verwenden, wird es noch wesentlich einfacher und eleganter. Das Umschalten erledigt der Browser ganz allein, und die Statusabfrage beschränkt sich auf das Abfragen der checked-Eigenschaft. Auch das Styling kann man dann von der Pseudoklasse :checked abhängig machen.

    --
    Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
    - Douglas Adams, The Hitchhiker's Guide To The Galaxy
    1. @ der Martin:

      Wow!

      VIELEN lieben Dank für die SEHR ausführliche Antwort!

      Bin unterwegs, werd mir deine Ausführungen aber später genauer zu Gemüte führen.

      LG

  3. Servus!

    Was ich erreichen will ist eigentlich genauso simpel wie es trivial ist - ein Toggle Button

    Im Wiki gibt es jetzt ein Tutorial, das erklärt, wie so etwas mit CSS zu realisieren ist:

    Herzliche Grüße

    Matthias Scharwies

    --
    Es gibt viel zu tun - packen wir's an: ToDo-Liste gewünschte Seiten