Matthias: Javascript läßt sich nicht auslagern

Hallo,

Ich habe einen Code geschrieben, der mir eine Anzeigt wenn eine Checkbox aktiviert wird. Das klapt auch soweit ganz gut, nur wenn ich das <script> in die Datei 'boxentest.js' auslagere funktioniert das ganze nicht mehr. (Ja die beiden Dateien liegen im selben Ordner!!) Was mache ich also falsch?

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="boxentest.js"></script>
  <meta name="viewport" content="width=device-width">
  <title>Test</title>
</head>
<body>
  <tr>
<td> Rand: <input type="checkbox" id="s1" value="Rand"> </td>
<td> Schatten: <input type="checkbox" id="s2" value="Schatten"> </td>
<td> Steg: <input type="checkbox" id="s3" value="Steg"> </td>
</tr>
  <p id="box1"></p>
  <p id="box2"></p>
  <p id="box3"></p>  
  
<script>
document.getElementById("s1").addEventListener("change", function() {
  if(this.checked) {
    document.getElementById("box1").innerHTML = "Rand ist aktiviert!";
  } else {
    document.getElementById("box1").innerHTML = "";
  }
});

document.getElementById("s2").addEventListener("change", function() {
  if(this.checked) {
    document.getElementById("box2").innerHTML = "Schatten ist aktiviert!";
  } else {
    document.getElementById("box2").innerHTML = "";
  }
});

document.getElementById("s3").addEventListener("change", function() {
  if(this.checked) {
    document.getElementById("box3").innerHTML = "Steg ist aktiviert!";
  } else {
    document.getElementById("box3").innerHTML = "";
  }
});
</script>

</body>
</html>

akzeptierte Antworten

  1. @@Matthias

    Was mache ich also falsch?

    Da du nicht das zeigst, was nicht funktioniert, kann man dir auch nicht sagen, warum es nicht funktioniert.

    Eine Vermutung habe ich aber: Wo setzt du das script-Element denn hin? JavaScript wird (ohne weiteres Zutun) sofort dort ausgeführt, wo es steht – und blockiert solange das Parsen des nachfolgenden HTMLs und das Rendern der Seite, was nicht gut für die percieved performance ist. Wenn es ausgeführt wird und Elemente ansprechen will, die zu dem Zeitpunkt noch gar nicht im DOM vorhanden sind, dann kann das nur schiefgehen.

        document.getElementById("box1").innerHTML = "Rand ist aktiviert!";
    

    Was du außerdem falsch machst: Es gibt keinen Grund, die Strings, die kein Markup enthalten, nach Markup zu parsen. Verwende nicht innerHTML, sondern textContent.

    Kwakoni Yiquan

    --
    Ad astra per aspera
  2. @@Matthias

    Was mache ich also falsch?

    Und noch was:

      <p id="box1"></p>
      <p id="box2"></p>
      <p id="box3"></p>  
    
        document.getElementById("box1").innerHTML = "Rand ist aktiviert!";
    

    Du lässt Änderungen in den Boxen nicht von assistiven Technologien (wie bspw. Screenreadern) bekanntgeben. Die Boxen sollten das aria-live-Attribut tragen:

      <p id="box1" aria-live="polite"></p>
      <p id="box2" aria-live="polite"></p>
      <p id="box3" aria-live="polite"></p>  
    

    Kwakoni Yiquan

    --
    Ad astra per aspera
  3. Lieber Matthias,

    als Ergänzung zu den Hinweisen von Gunnar noch dieses:

    DRY (don't repeat yourself) - vermeide identischen Code, wenn Du kannst.

    In Deinem gezeigten JS-Code prüfst Du dreimal, ob eine Checkbox aktiviert ist, um dann einen Elementinhalt passend zu ändern. Da sollte es möglich sein, den Code genau nur einmal zu schreiben und dann entsprechend oft anzuwenden. Damit das sinnvoll gegliedert werden kann, hier ein Beispiel, wie ich das tun würde:

    const tasks = [
      {
        "checkboxID": "s1",
        "checked": "Rand ist aktiviert!",
        "outputID": "box1",
        "unchecked": ""
      },
      {
        "checkboxID": "s2",
        "checked": "Schatten ist aktiviert!",
        "outputID": "box2",
        "unchecked": ""
      },
      {
        "checkboxID": "s3",
        "checked": "Steg ist aktiviert!",
        "outputID": "box3",
        "unchecked": ""
      }
    ];
    
    document.body.addEventListener("input", event => {
    
      tasks.forEach(data => {
        const
          checkbox = document.getElementById(data.checkboxID),
          output = document.getElementById(data.outputID);
    
        if (checkbox && output && event.target == checkbox) {
          output.textContent = checkbox.checked ? data.checked : data.unchecked;
        }
      });
    });
    

    Zuerst wird eine Liste (Array) namens tasks beschrieben, die Objekte enthält, die jeweils darstellen sollen, was wie zusammenhängt und welche Textausgaben hat. Ein solches Objekt (als Objekt-Literal notiert) hat vier Eigenschaften:

    1. checkboxID - die ID von <input type="checkbox">
    2. checked - der anzuzeigende Textinhalt, wenn die Checkbox aktiviert ist
    3. outputID - die ID desjenigen Elements, dessen Textinhalt als Ausgabe dient
    4. unchecked - der anzuzeigende Textinhalt, wenn die Checkbox nicht aktiviert ist

    Der EventListener der Wahl lautet nicht change, sondern input. Die Funktion, die als zweiter Parameter für addEventListener() angegeben ist, wurde hier als Pfeilfunktion notiert. Wichtig ist der Parameter event, der das Event-Objekt enthalten wird, wenn ein Eingabefeld bedient wird. Mit event.target lässt sich dann prüfen, ob eine unserer Checkboxen aktuell „angefasst“ wurde. Es ist sinnvoll, nur einen EventListener zu verwenden, anstatt an jedes Element einen eigenen zu pappen, weshalb er hier an document.body geklebt wird. In Deinem Fall kannst Du ihn auch auf das passende <form> aufkleben.

    In der EventListener-Funktion wird nun jedes der Objekte in tasks einzeln abgearbeitet. Die Array-Methode forEach funktioniert im Grunde wie eine Schleife, nur dass man sich innerhalb einer (anonymen) Funktion befindet, die das jeweilige Array-Element als Parameter übergeben bekommt. Die anonyme Funktion hier (auch wieder als Pfeilfunktion notiert) nimmt das Element in der Variable data entgegen.

    Mit dem Objekt in data können wir nun die Checkbox und das Anzeige-Element suchen. Wenn in den Variablen checkbox und output passende HTML-Element-Objekte stehen, dann ist das wie ein true, und wenn das HTML-Element in checkbox auch wirklich dasjenige ist, von dem das Ereignis ausgegangen ist, dann kann in das Ausgabe-Element ein entsprechender Inhalt geschrieben werden. Der ternäre Operator ist eine verkürzte Schreibweise, um sich ein if-else zu sparen.

    Liebe Grüße

    Felix Riesterer

  4. Hey, Danke für die Hilfreichen Info's ich werde mal versuchen die Tips umzusetzen und mich dann zurück melden..... Da mache ich aber einen neuen Beitrag auf weil ich die Fragestellung noch um einen Colorinput und eine verknüpfte Ausgabe erweitern werde.... Ich war nämlich erst skeptisch wie komplex die Anfragen hier sein sollten, aber ich sehe - Ich habe hier mit 'den Guten' zu tun also werde ich mich wagen.....

    Außerdem habe ich jetzt einen Account und würde meine Frage darüber stellen wollen.

    Danke bis hierhin!