web-dev-qa-db-fra.com

Comment puis-je utiliser l'attribut FOR d'une balise LABEL sans l'attribut ID sur la balise INPUT

Existe-t-il une solution au problème illustré dans le code ci-dessous? Commencez par ouvrir le code dans un navigateur pour aller droit au but et ne pas avoir à parcourir tout ce code avant de savoir ce que vous recherchez.

<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>
62
Shawn

Le mieux, à mon avis, ce que vous pouvez faire, est de renommer toutes les cases à cocher, en ajoutant un préfixe à leurs identifiants, par exemple 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>

De cette façon, vous n'aurez aucun conflit avec d'autres identifiants sur une page, et en cliquant sur l'étiquette, la case à cocher sera désactivée sans fonction javascript spéciale.

14
Draco Ater

c'est résolu ici: https://stackoverflow.com/a/8537641 faites-le comme ça

<label><input type="checkbox">Some text</label>
121
user2046841

EDIT: Rétrospectivement, ma solution est loin d'être idéale. Je vous recommande plutôt d'utiliser "l'association implicite d'étiquettes" comme indiqué dans cette réponse: stackoverflow.com/a/8537641/884734

Ma solution proposée, moins que idéale, est ci-dessous:

Ce problème peut être facilement résolu avec un peu de javascript. Jetez simplement le code suivant dans l'un des fichiers js de votre page pour donner <label> marque le comportement suivant:

Lorsqu'une étiquette est cliquée:

S'il y a un élément sur la page avec un id correspondant à l'attribut for de l'étiquette, revenez à la fonctionnalité par défaut et concentrez cette entrée.

Si aucune correspondance n'a été trouvée à l'aide de id, recherchez un frère de label avec un class correspondant à l'attribut label de for, et concentrez-le.

Cela signifie que vous pouvez disposer vos formulaires comme ceci:

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

Hélas, le code actuel:

$(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();
        }
    })
});

Remarque: cela peut entraîner des problèmes lors de la validation de votre site par rapport aux spécifications du W3C, car le <label>for attribut est censé avoir toujours un élément correspondant sur la page avec un ID correspondant.

J'espère que cela t'aides!

6
Eric Seastrand

En termes simples, un ID n'est censé être utilisé qu'une seule fois sur une page, donc non, ils ne concevraient pas une solution de contournement pour plusieurs ID sur une seule page qui ne sont pas censés exister.

Pour répondre au reste de la question: non, l'attribut ID est la seule chose que l'attribut 'for' d'une étiquette examinera. Vous pouvez toujours utiliser un événement JavaScript onclick pour récupérer l'entrée par nom et la modifier, bien que cela semble trop compliqué lorsque vous pouvez simplement résoudre votre problème d'ID, ce qui aurait beaucoup plus de sens.

3
animuson

Peut-être qu'une solution simple et simple consisterait à utiliser uniqueid () php ou une autre fonction alternative du langage de programmation.

1
FantomX1