2010-04-24 8 views
47

Esiste una soluzione al problema illustrato nel codice qui sotto? Inizia aprendo il codice in un browser per arrivare direttamente al punto e non dover esaminare tutto quel codice prima di sapere cosa stai cercando.Come posso utilizzare l'attributo FOR di una tag LABEL senza l'attributo ID sul tag INPUT

<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> 
+1

Oltre a non avere una domanda chiara, questo è un duplicato di http://stackoverflow.com/questions/8537621/possible-to-associate-label-with-checkbox-without-using-for-id. –

risposta

13

Il migliore, a mio avviso, che cosa si può fare, è quello di rinominare tutte le caselle di controllo, con l'aggiunta di un po 'di prefisso al loro ID, ad esempio 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> 

In questo modo non avrà alcun conflitto con altri ID su una pagina e facendo clic sull'etichetta si sposterà la casella di controllo senza alcuna funzione javascript speciale.

2

In poche parole, un ID si suppone solo per essere utilizzato una sola volta in una pagina, in modo che nessuno non avrebbero progettare una soluzione per identità multiple di una singola pagina che non si suppone di esistere.

Per rispondere al resto della domanda: no, l'attributo ID è l'unica cosa che l'attributo 'for' di un'etichetta guarderà. Puoi sempre utilizzare un evento onclick di JavaScript per recuperare l'input per nome e cambiarlo, anche se ciò sembra eccessivamente complicato quando puoi semplicemente risolvere il problema dell'ID, il che sarebbe molto più sensato.

+0

+1 per aver colpito due problemi con una fava. Alcuni FYI inutili: l'attributo for è del tipo di dati IDREF, che considera il valore di tipo ID, che deve essere univoco. Questi sono tipi di dati legacy disponibili per XML Schema, quindi suppongo che significhi che sono tipi di dati residenti di SGML. –

+9

Il problema si verifica quando gli ID per gli input vengono creati dinamicamente. Non posso sapere cosa saranno quando ho scelto gli id ​​per gli altri elementi nella pagina, quindi non posso assicurarmi che non abbiano duplicati. E come dici tu, la soluzione javascript è eccessivamente complicata (e alcune persone non hanno javascript). – Shawn

+0

Genera GUID per gli ID. – Triynko

6

EDIT: In retrospettiva, la mia soluzione è tutt'altro che ideale. Vi consiglio invece di sfruttare "associazione etichetta implicito", come mostrato in questa risposta: stackoverflow.com/a/8537641/884734

mio proposto, meno-che-ideale soluzione è qui sotto:

Questo problema può essere facilmente risolto con un po 'di javascript. Basta buttare il seguente codice in uno dei file della tua pagina js per dare <label> tag il seguente comportamento:

Quando un'etichetta viene cliccato:

Se c'è un elemento della pagina con una id corrispondente attributo dell'etichetta for , ripristinare le funzionalità predefinite e mettere a fuoco quell'input.

Se nessuna corrispondenza è stata trovata usando id, cercare un fratello del label con un class corrispondente attributo di 's il labelfor, e focalizzarla.

Questo significa che è possibile tracciare i moduli in questo modo:

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

Ahimè, il codice vero e proprio:

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

Nota: Questo può causare problemi durante la convalida vostro sito contro le specifiche W3C , poiché si suppone che l'attributo <label>for abbia sempre un elemento corrispondente nella pagina con un ID corrispondente.

Spero che questo aiuti!

+0

Grazie a chi ha downvoted. Retrospettivamente, la mia soluzione è tutt'altro che ideale. Ti consiglio invece di utilizzare "associazione etichetta implicita" come mostrato in questa risposta: http://stackoverflow.com/a/8537641/884734 – Eric

100

che è stato risolto qui: https://stackoverflow.com/a/8537641 proprio fare in questo modo

<label><input type="checkbox">Some text</label> 
+8

Funziona solo se l'etichetta e la casella di controllo sono l'una accanto all'altra. – Shawn

+7

@Shawn Qual è il caso del post originale. –

+0

L'unica cosa che consiglierei è mettere il testo prima del tag di input. Altrimenti, perfetto! – Stan

0

soluzione Forse facile semplice sarebbe utilizzando uniqueid() php o altro linguaggio di programmazione funzione alternativa.