Rolf B: wie kann ich optisch eine checkbox verstecken? (oder code auf radiobuttons anpassen)

Beitrag lesen

Hallo AnLu,

aufgrund beruflicher Nebentätigkeit und dem Vollzeitstudium fehlt mir sehr viel Zeit.....

Studieren und Geld dafür verdienen ist eine eklige Kombination, vor allem, wenn man dann mit komplexen Dingen wie Webdesign konfrontiert wird.

Ich habe ja keine Ahnung, welche Voraussetzungen Du laut Curriculum für diese Aufgabe mitbringen solltest. Es ist allerdings eine unangenehme Sache, sie nicht zu haben und dann irgendwohin zu laufen und eine Abschreibvorlage zu erbitten. Das macht nämlich deine Lage nicht besser. Du schaffst vielleicht den Schein, schmückst Dich dann aber mit Federn, die nicht Deine sind. Und irgendwann kriegt Dich die Wissenslücke dann doch am Allerwertesten.

Der Checkbox-Hack, nach dem Du suchst, ist eine komplexe Sache. Das muss visuell passen, und man muss einige Dinge nachbauen, die einem die Checkbox schenkt

  • Darstellen des Eingabefokus (bei Tastatursteuerung)
  • Darstellen des Angekreuztseins
  • Reaktion auf Klick - eine versteckte Checkbox kann man nicht anklicken.

Letzteres ist ziemlich einfach, und es fehlt Dir sowieso. Ein input-Element braucht immer ein Label. Und wenn man auf das Label für eine Checkbox klickt, reagiert die Checkbox automatisch.

Labels und Inputs werden entweder über eine id gekoppelt, oder dadurch, dass man das input ins label hineinsetzt. Das ist einfacher, macht den Checkbox-Hack aber umständlicher.

<label>
   <input type="checkbox" name="num1" value="1">
   <span>1</span>
</label>

Davon brauchst Du 49 Stück. Ohne Tabelle. Einfach so, mit einem <br> nach jeweils 7 Stück. Man kann das auch mit einem Grid-Element machen, aber ich will Komplexität raushalten.

Der Name muss eindeutig sein. Bei Radio-Elementen muss der Name gleich sein, bei Checkboxen darf er es nicht. Es sei denn, du verarbeitest den Kram Serverseitig mit PHP. Dann könntest Du bei allen name="box[]" setzen und bekommst dann serverseitig in $_POST["box"] ein Array mit den angekreuzten Nummern.

Mit CSS gibst Du dem Ganzen Style (was CSS ist und wie Du es einbaust, weißt Du? Solltest Du wissen, behaupte ich, wenn Du so eine Seite machen sollst). Ansonsten schau in unser Wiki.

label {
   display: inline-block;     /* Dadurch können die Labels nebeneinander */
   margin: 1.1em 0;           /* Etwas Luft unten und oben */
   border: 1px solid red;     /* Lottozahlen gehören in Kästchen */
}

label:focus-within {          /* Darstellen, dass die Checkbox im Label Fokus hat */
  outline: 2px solid red;
}

label input[type=checkbox] {  /* Checkbox visuell verstecken */
   width: 0;
}

label span {
   display: inline-block;     /* Span-Element für width empfänglich machen */
   width: 1.2em; 
   text-align: center;
}

Ich erkläre das jetzt nicht alles. Lies es nach, wenn Du was davon nicht kennst. :focus-within ist relativ neu, das ist eine CSS Pseudoklasse, die aktiv wird wenn das Element oder ein Kind davon den Eingabefokus hat. Alle Browser außer Internet Explorer kennen es mittlerweile.

Der Rahmen ist dann

<head>
<style>
/* CSS von oben kommt hierhin */

#sechsAus49 {
  width: max-content;
}
</style>
</head>
<body>
  <h1>6 aus 49</h1>
  <form name="formular">
    <fieldset id="sechsAus49">
      <legend>Sechs aus Neunundvierzig</legend>
      <label>...</label>
      <label>...</label>
      <label>...</label>
      <label>...</label>
      <label>...</label>
      <label>...</label>
      <label>...</label>
      <br>
      <label>...</label>
      usw.
    </fieldset>
    <fieldset id="zusatzzahl">
      <legend>Zusatzzahl</legend>
      <label><input type="radio" name="superzahl" value="0"><span>0</span></label>
      ...
      <label><input type="radio" name="superzahl" value="9"><span>9</span></label>
    </fieldset>
  </form>
</body>

Kein <br> nach <h1>. Brrr. Wenn Du mehr Abstand willst, setze den margin-bottom des h1 via CSS. Oder ein margin-top für das Form. Wie Du willst. Aber nicht <br>. Hinter den siebten Eiern Labels ist es nötig.

Ein Fieldset erzeugt eine Groupbox. Mittels CSS wird ihre Breite auf "max-content" gesetzt, auch das ist relativ neu, aber von den Browsern gut unterstützt. Ein IE macht die Box auf 100% Breite. Egal. Den hat dein Prof nicht.

Vermisst Du das onclick auf den Checkboxen? Das kommt jetzt. Zuerst: verschiebe dein Script aus dem <head> ans Ende des <body>. Der Vorteil ist, dass dann die HTML Elemente schon vorhanden sind, dadurch muss man nicht drauf warten dass sie da sind.

An Stelle eines onclick auf jeder Checkbox registrieren wir einen Klickhandler auf dem Fieldset, in dem die 49 Zahlen stehen:

<script>
let zahlenfeld = document.getElementById("sechsAus49");
zahlenfeld.addEventListener("input", lottoNumberChanged);

function lottoNumberChanged(event) {

}
</script>

Das nennt man unaufdringliches JavaScript - keine Event-Registrierung im HTML. Das kann das Script alleine. Dieser Rahmen registriert die Funktion lottoNumberChanged als Behandler für ein input-Ereignis auf dem Element mit Id "sechsAus49". Das Ereignis "input" wird gefeuert, wenn sich der Wert eines input-Elements ändert, und das ist für unser Problem angemessener als ein click. Checkboxen sind zwar so gnädig und simulieren ein click, wenn man sie mit der Tastatur umschaltet, aber richtig ist das nicht.

Diese Behandlungsfunktion bekommt vom Browser einen Parameter mit, das event-Objekt. Darauf gibt's ein Property namens "target", und das ist das Element, das sich geändert hat. Irgendwie müssen wir ja wissen, wer sich geändert hat, wenn wir ganz allgemein auf das Fieldset lauschen. Aber solche Ereignisse "blubbern" hoch und man kann sich oben hinstellen und sie alle in Empfang nehmen, ohne jede einzelne Checkbox belauschen zu müssen.

function lottoNumberChanged(event) {
   let kreuzchen = zahlenfeld.querySelectorAll("input[type=checkbox]:checked");
   if (kreuzchen.length > 6) {
     event.target.checked = false;
     alert("Mit sieben Zahlen wird Ihr Tippschein ungültig!");
   }
}

Hey, das ist alles. Unser Fieldset enthält außer den Checkboxen nichts, was ein input Event werfen könnte, darum müssen wir nicht großartig prüfen, ob das Event auch von einer Checkbox kommt. Andernfalls müssten wir das mit tagName und ggf. noch type Property von event.target überprüfen.

Um zu bestimmen, wieviele Kreuzchen da sind, zählt man nicht von Hand. Der Browser kann das selbst, mit Hilfe eines CSS Selektors und querySelectorAll. Der Selektor, der da angegeben ist, findet input Elemente mit dem Attribut type="checkbox" und der Pseudoklasse :checked - die immer dann gesetzt ist wenn die Checkbox einen Haken hat.

Sind es mehr als 6, dann wird einfach der checked-Zustand von event.target - also der gerade veränderten Checkbox - wieder auf false gesetzt.

So. Damit ist wohl alles beisammen. Checkbox-Hack, Senden als Array an PHP, und jede Menge Erklärungen zu HTML und JS. Viel Glück!

Hier ist eine Demo

Rolf

--
sumpsi - posui - obstruxi