web-dev-qa-db-ja.com

INPUTタグのID属性なしでLABELタグのFOR属性を使用するにはどうすればよいですか

以下のコードに示されている問題の解決策はありますか?まず、ブラウザーでコードを開いて、目的の場所をすぐに確認します。探しているものを知る前に、すべてのコードを調べる必要はありません。

<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

私の考えでは、最善の方法は、IDにプレフィックスを追加することで、すべてのチェックボックスの名前を変更することです。たとえば、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>

この方法では、ページ上の他のIDと競合することはありません。ラベルをクリックすると、特別なjavascript関数なしでチェックボックスが切り替わります。

14
Draco Ater

ここで解決されました: https://stackoverflow.com/a/8537641 ちょうどこのようにします

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

編集:振り返ってみると、私の解決策は理想からはほど遠い。この回答に示されているように、代わりに「暗黙的なラベルの関連付け」を活用することをお勧めします。 stackoverflow.com/a/8537641/884734

私が提案した、理想的ではない解決策は以下のとおりです。

この問題は、小さなjavascriptで簡単に解決できます。 <label>タグに次の動作を与えるには、ページのjsファイルのいずれかに次のコードをスローするだけです。

ラベルをクリックすると:

ラベルのid属性に一致するforを持つ要素がページにある場合、デフォルトの機能に戻り、その入力にフォーカスします。

idを使用して一致が見つからなかった場合、labelの兄弟を探し、classlabel属性と一致するforを探します。集中してください。

これは、次のようにフォームをレイアウトできることを意味します。

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

悲しいかな、実際のコード:

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

注:<label>for属性には、一致するIDを持つ対応する要素が常にページにあると想定されているため、これにより、サイトをW3C仕様に対して検証するときに問題が発生する可能性があります。

お役に立てれば!

6
Eric Seastrand

簡単に言えば、IDは1つのページで1回しか使用されないため、存在しないはずの単一ページ上の複数のIDの回避策を設計することはありません。

残りの質問に答えるには、いいえ、ラベルの「for」属性が参照するのはID属性だけです。 JavaScriptのonclickイベントを使用して、名前で入力を取得して変更できますが、IDの問題を修正するだけでは非常に複雑に思えますが、これは非常に理にかなっています。

3
animuson

たぶん簡単な簡単な解決策は、uniqueid()phpまたは他のプログラミング言語の代替関数を使用することです。

1
FantomX1