Wie kann ich das FOR-Attribut eines LABEL-Tags ohne das ID-Attribut des INPUT-Tags verwenden?

74

Gibt es eine Lösung für das im folgenden Code dargestellte Problem? Öffnen Sie zunächst den Code in einem Browser, um direkt zum Punkt zu gelangen, und müssen Sie nicht den gesamten Code durchsehen, bevor Sie wissen, wonach Sie suchen.

<html>
 <head>
  <title>Input ID creates problems</title>
  <style type="text/css">
   #prologue, #summary { margin: 5em; }
  </style>
 </head>
 <body>
  <h1>Input ID creates a bug</h1>
  <p id="prologue">
   In this example, I make a list of checkboxes representing things which could appear in a book. If you want some in your book, you check them:
  </p>
  <form>
   <ul>
    <li>
     <input type="checkbox" id="prologue" />
     <label for="prologue">prologue</label>
    </li>
    <li>
     <input type="checkbox" id="chapter" />
     <label for="chapter">chapter</label>
    </li>
    <li>
     <input type="checkbox" id="summary" />
     <label for="summary">summary</label>
    </li>
    <li>
     <input type="checkbox" id="etc" />
     <label for="etc">etc</label>
     <label>
    </li>
   </ul>
  </form>
  <p id="summary">
   For each checkbox, I want to assign an ID so that clicking a label checks the corresponding checkbox. The problems occur when other elements in the page already use those IDs. In this case, a CSS declaration was made to add margins to the two paragraphs which IDs are "prologue" and "summary", but because of the IDs given to the checkboxes, the checkboxes named "prologue" and "summary" are also affected by this declaration. The following links simply call a javascript function which writes out the element whose id is <a href="javascript:alert(document.getElementById('prologue'));">prologue</a> and <a href="javascript:alert(document.getElementById('summary'));">summary</a>, respectively. In the first case (prologue), the script writes out [object HTMLParagraphElement], because the first element found with id "prologue" is a paragraph. But in the second case (summary), the script writes out [object HTMLInputElement] because the first element found with id "summary" is an input. In the case of another script, the consequences of this mix up could have been much more dramatic. Now try clicking on the label prologue in the list above. It does not check the checkbox as clicking on any other label. This is because it finds the paragraph whose ID is also "prologue" and tries to check that instead. By the way, if there were another checkbox whose id was "prologue", then clicking on the label would check the one which appears first in the code.
  </p>
  <p>
   An easy fix for this would be to chose other IDs for the checkboxes, but this doesn't apply if these IDs are given dynamically, by a php script for example.
   Another easy fix for this would be to write labels like this:
   <pre>
    &lt;label&gt;&lt;input type="checkbox" /&gt;prologue&lt;/label&gt;
   </pre>
   and not need to give an ID to the checkboxes. But this only works if the label and checkbox are next to each other.
  </p>
  <p>
   Well, that's the problem. I guess the ideal solution would be to link a label to a checkboxe using another mechanism (not using ID). I think the perfect way to do this would be to match a label to the input element whose NAME (not ID) is the same as the label's FOR attribute. What do you think?
  </p>
 </body>
</html>
Shawn
quelle
2
Dies ist nicht nur eine klare Frage, sondern auch ein Duplikat von stackoverflow.com/questions/8537621/… .
Mark E. Haase

Antworten:

15

Meiner Meinung nach können Sie am besten alle Kontrollkästchen umbenennen, indem Sie beispielsweise ihren IDs ein Präfix hinzufügen input

   <ul>
    <li>
     <input type="checkbox" id="input_prologue" />
     <label for="input_prologue">prologue</label>
    </li>
    <li>
     <input type="checkbox" id="input_chapter" />
     <label for="input_chapter">chapter</label>
    </li>
    <li>
     <input type="checkbox" id="input_summary" />
     <label for="input_summary">summary</label>
    </li>
    <li>
     <input type="checkbox" id="input_etc" />
     <label for="input_etc">etc</label>
    </li>
   </ul>

Auf diese Weise treten keine Konflikte mit anderen IDs auf einer Seite auf. Durch Klicken auf die Beschriftung wird das Kontrollkästchen ohne spezielle Javascript-Funktion umgeschaltet.

Draco Ater
quelle
138

Es wurde hier behoben: https://stackoverflow.com/a/8537641 Mach es einfach so

<label><input type="checkbox">Some text</label>
user2046841
quelle
10
Dies funktioniert nur, wenn das Etikett und das Kontrollkästchen nebeneinander liegen.
Shawn
11
@Shawn Was für den ursprünglichen Beitrag der Fall ist.
Igor Zevaka
Das einzige, was ich empfehlen würde, ist, den Text vor das Eingabe-Tag zu setzen. Ansonsten perfekt!
Stan
5
Das Problem ist, wenn Sie es stylen müssen. In CSS gibt es keinen übergeordneten Selektor.
Maciej Krawczyk
1
In einigen Layouts ist dies möglicherweise nicht möglich, aber ohne JS ist es einfach nicht möglich, Beschriftung und Eingabe zu verknüpfen. Dies ist die von WC3 genehmigte Lösung, ohne die ID für den Link zu verwenden. Und wenn Sie wirklich auf ein Styling- oder Markup-Problem stoßen, verwenden Sie JS.
Perry
6

EDIT: Rückblickend ist meine Lösung alles andere als ideal. Ich empfehle, stattdessen die "implizite Label-Zuordnung" zu nutzen, wie in dieser Antwort gezeigt: stackoverflow.com/a/8537641/884734

Meine vorgeschlagene, nicht ideale Lösung ist unten:

Dieses Problem kann leicht mit ein wenig Javascript gelöst werden. Wirf einfach den folgenden Code in eine der js-Dateien deiner Seite, um sie zu geben<label> Tags das folgende Verhalten :

Wenn auf ein Etikett geklickt wird:

Wenn sich auf der Seite ein Element befindet, das mit idden Beschriftungen übereinstimmtfor Attribut , kehren Sie zur Standardfunktionalität zurück und fokussieren Sie diese Eingabe.

Wenn mit keine Übereinstimmung gefunden wurde id, suchen Sie nach einem Geschwister des Attributs labelmit classdem labeldes forAttributs und fokussieren Sie es.

Dies bedeutet, dass Sie Ihre Formulare folgendermaßen gestalten können:

<form>
    <label for="login-validation-form-email">Email Address:</label>
    <input type="text" class="login-validation-form-email" />
</form>

Leider der eigentliche Code:

$(function(){
    $('body').on('click', 'label', function(e){
        var labelFor = $( this ).attr('for');
        if( !document.getElementById(labelFor) ){
            e.preventDefault(); e.stopPropagation();
            var input = $( this ).siblings('.'+labelFor);
            if( input )
                input[0].focus();
        }
    })
});

Hinweis: Dies kann zu Problemen bei der Überprüfung Ihrer Site <label> foranhand der W3C-Spezifikation führen, da das Attribut immer ein entsprechendes Element auf der Seite mit einer übereinstimmenden ID enthalten soll.

Hoffe das hilft!

Eric Seastrand
quelle
Vielen Dank an alle, die abgelehnt haben. Rückblickend ist meine Lösung alles andere als ideal. Ich empfehle, stattdessen die "implizite Label-Zuordnung" zu nutzen, wie in dieser Antwort gezeigt: stackoverflow.com/a/8537641/884734
Eric Seastrand
1
Dies führt nicht nur zu Problemen mit W3C-konformen Validatoren, sondern funktioniert auch nicht für unterstützende Technologien wie beispielsweise Bildschirmlesegeräte. Sie benötigen eine implizite Label-Zuordnung, wie Sie in Ihrem Kommentar geschrieben haben.
Volker E.
3

Einfach ausgedrückt, eine ID sollte nur einmal auf einer Seite verwendet werden. Nein, sie würden keine Problemumgehung für mehrere IDs auf einer einzelnen Seite entwerfen, die nicht vorhanden sein sollen.

Um den Rest der Frage zu beantworten: Nein, das ID-Attribut ist das einzige, was das 'for'-Attribut eines Labels betrachtet. Sie können jederzeit ein JavaScript-Ereignis onclick verwenden, um die Eingabe nach Namen abzurufen und zu ändern. Dies erscheint jedoch zu kompliziert, wenn Sie nur Ihr ID-Problem beheben können, was viel sinnvoller wäre.

animuson
quelle
+1 für zwei Probleme mit einer Klappe. Einige sinnlose FYI: Das for-Attribut ist vom Datentyp IDREF, der nach dem Wert der Typ-ID sucht, der eindeutig sein muss. Dies sind Legacy-Datentypen, die für XML Schema verfügbar sind. Ich nehme an, dies bedeutet, dass es sich um residente Datentypen von SGML handelt.
11
Das Problem tritt auf, wenn die IDs für die Eingaben dynamisch erstellt werden. Ich kann nicht wissen, wie sie aussehen werden, wenn ich die IDs für die anderen Elemente auf der Seite ausgewählt habe. Daher kann ich nicht sicherstellen, dass sie keine Duplikate enthalten. Und wie Sie sagen, ist die Javascript-Lösung zu kompliziert (und einige Leute haben kein Javascript).
Shawn
1
Generieren Sie GUIDs für die IDs.
Triynko
1

Vielleicht wäre eine einfache und unkomplizierte Lösung die Verwendung von uniqueid () php oder einer anderen alternativen Programmiersprachenfunktion.

FantomX1
quelle
0

Im Gegensatz zur akzeptierten Antwort stimme ich der von FantomX1 vorgeschlagenen Lösung zu, generiere eine zufällige ID für jedes Kontrollkästchen und verwende diese ID für die dem Kontrollkästchen zugeordnete Bezeichnung. Aber ich würde die zufällige ID mit einer UUID generieren (siehe GUID / UUID in JavaScript erstellen? )

Yancheelo
quelle