jQueryでチェックボックスの全チェック/外しをしようとしてハマッたこと、attr()とprop()の違いは罠レベル

[Sponsored Link]


当ブログでは「役に立った!」「写真使いました!」などご参考頂いた方からのAmazonギフト券の寄付をお待ち致しております。

Share on FacebookTweet about this on TwitterShare on Google+Share on TumblrPin on PinterestShare on LinkedInDigg this

チェックボックスの全チェックボタン、全チェック外しボタンを実装して、一括チェック・一括チェック外しといった動的フォームを作成しようと思い、jQuery-1.9.1を使って実装していた。もともとjQueryは1.4系をメインに使っていたのだが、今回jQuery1.9系を使うようにしてみた。もっともここが落とし穴にハマる第一段階だったのだが……。

もともと、以下のようにjQueryのコードを書いていた。

$("#all_check_button").click(function(){
	$("input:checkbox[name='item']").attr({'checked':'checked'});
});
$("#all_clear_button").click(function(){
	$("input:checkbox[name='item']").attr({'checked':false});
});

しかし、一回全チェックをして一回全チェック外しをしたら、もう二度と全チェックができなくなるという不可思議な挙動。
attr()を使えば問題のないはずの動作なのに、なぜ一度目だけ動作するという状況になるのか……。

いろいろ調べていたら、以下のサイト様の説明がとても明快で救われた。

■CSSは分かるけどjQueryは苦手……という人が .attr()と .prop()に親しんでくれるといいなーと思って書きました。 – Ginpen.com
http://ginpen.com/2011/10/12/jquery-attr-prop/

jQuery-1.6からattr()の実装が変わったということのようだ。
ただ1.6.1では混乱の大きさから戻されているようではあった。確かに1.7系を使っていても問題はなかったような気がする……うん。たぶん。

しかし今回は1.9.1。ここで同様の変更が行われたのだろうか…ということで、コードをprop()に修正してみた。

$("#all_check_button").click(function(){
	$("input:checkbox[name='item']").prop({'checked':'checked'});
});
$("#all_clear_button").click(function(){
	$("input:checkbox[name='item']").prop({'checked':false});
});

動いた。みごとなまでに、予想通り。
やはり1.6.1での修正後にどこかでまた調整されたのだろう……ということで調べてみたら、こんなアップグレードガイドが見つかった(英語)。

■jQuery Core 1.9 Upgrade Guide
http://jquery.com/upgrade-guide/1.9/

その中の「.attr() versus .prop()」という節があって、これがプンプンするので読んでみたら、やはり1.9から明確に切り分けられる。
どうやらjQueryのセレクタで指定する場合の混乱を避ける目的で「属性」(もともとHTML設定された状態)と「プロパティ」(JavaScriptで動的に変更可能な設定値)を分離したのだという。

なお以下の日本語訳は英語不得意な私による翻訳である点ご了承願いたい。

jQuery 1.6 introduced the .prop() method for setting or getting properties on nodes and deprecated the use of .attr() to set properties. However, versions up to 1.9 continued to support using .attr() for specific situations. This behavior in the name of backwards compatibility causes confusion when selectors are used that distinguish between attributes and properties.
[拙意訳(誤訳可能性有)] jQuery 1.6ではノード上のプロパティの設定/取得のための.prop()メソッドを導入し、プロパティ設定をするために.attr()メソッドを使用することを非推奨とした。しかしながら1.9までは特定の状況のために.attr()使用のサポートを続けていた。後方互換性の名目であるこの挙動はセレクタが属性とプロパティを識別する際に使用される場合、混乱を引き起こす。

For example, boolean attributes such as checked and disabled on a checkbox are affected by this change. The correct behavior of “input[checked]” is to select checkboxes that have a checked attribute, regardless of its string value, and regardless of their current state. In contrast, “input:checked” selects checkboxes that are currently checked as reflected in their boolean (true or false) checked property, which is affected when the user clicks the box for example. Versions prior to 1.9 sometimes do not select the correct nodes with these selectors.
[拙意訳(誤訳可能性有)] 例えば、チェックボックスのcheckedやdisabledのようなboolean属性は、この変更によって影響を受ける。”input[checked]”の正しい挙動は、その文字列値に関わらず、かつそれらの現在の状態に関わらずchecked属性を有するチェックボックスを選択することである。対して”input:checked”は、例えばユーザがチェックボックスをクリックした際に影響されるboolean(trueかfalse)値としてプロパティに反映された、現在チェックされているチェックボックスを選択する。1.9以前のバージョンではときどき、それらのセレクタで正しいノードを選択できない。

Here are some examples of correct and incorrect usage when setting checked on a checkbox; the same rules apply for disabled. Note that only the property consistently reflects and updates the current state of the checkbox across all browsers; rarely will you need to set the attribute.
[拙意訳(誤訳可能性有)] 以下はチェックボックスにチェックを入れる際に使用するいくつかの正誤サンプルである。disabledの適用も同じ方法となる。すべてのブラウザに渡ってプロパティだけに現在のチェックボックスの状態が矛盾なく反映・更新されることに注意されたい。属性の設定が必要になるのはまれだ。

// Correct if changing the attribute is desired (拙訳:属性変更が期待されるのであれば正解)
$(elem).attr("checked", "checked");
// Correct for checking the checkbox (拙訳:チェックボックスのチェックで合っている)
$(elem).prop("checked", true);
// Correct if removing the attribute is desired (拙訳:属性削除が期待されるのでれば正解)
$(elem).removeAttr("checked");
// Correct for clearing the checkbox (拙訳:チェックボックスのクリアで合っている)
$(elem).prop("checked", false);

The value property versus attribute on input elements is another example of this ambiguity. The attribute generally reflects the value that was read from the HTML markup; the property reflects the current value. Since the .val() method is the recommended jQuery way to get or set the values of form elements, this confusion usually does not affect users.
[拙意訳(誤訳可能性有)] input要素のvalueプロパティと属性の比較は、もうひとつのあいまいな例だ。属性は一般的にHTMLマークアップから読まれるvalueを反映し、プロパティは現在のvalueを反映する。.val()メソッドがフォーム要素のvalueの取得・設定のための推奨されるjQueryでの方法であるため、この混乱はユーザにあまり影響を与えない。

However, when a selector like “input[value=abc]” is used, it should always select by the value attribute and not any change made to the property by the user, for example from them typing into a text input. As of jQuery 1.9, this behaves correctly and consistently. Earlier versions of jQuery would sometimes use the property when they should have used the attribute.
[拙意訳(誤訳可能性有)] しかしながら、”input[value=abc]”のようなセレクタが使われる場合、例えばテキスト入力といったユーザによるプロパティ変更ではなく、value属性によって常に選択されるべきである。jQuery 1.9の場合、この挙動は適切で一貫性がある。前のバージョンでは、属性を使用すべきはずの場合にもときどきプロパティを使用する。

The jQuery Migrate plugin restores the old attribute-vs-property rules.
[拙意訳(誤訳可能性有)] jQuery移行プラグインでは古い属性-プロパティ規則に修正する。

[Sponsored Link]


ということで、いよいよ1.9からは英断されてしまった、というところのようだ。

最後の移行プラグインについては、日本語に抄訳された方がおられるので、使う場合は参考にされるとよいだろう。

■jQuery Migrate plugin の使い方と警告文の自分なりのまとめ – 私的なjQuery
http://myjquery.blog.fc2.com/blog-entry-15.html

jQuery最高の教科書実践Webデザイン jQuery+CSSフレームワークでサクサクつくる「動き」と「仕掛け」開眼!  JavaScript ―言語仕様から学ぶJavaScriptの本質ミニハンバーガーセット ミニバーガー 8個セット【Sliderスライダー】[訳あり] A4A5ランク限定 100%黒毛和牛 切り落とし1kg湘南貿易 デュック・ド・モンターニュ ノンアルコールワイン 750ml

Share on FacebookTweet about this on TwitterShare on Google+Share on TumblrPin on PinterestShare on LinkedInDigg this

当ブログでは「役に立った!」「写真使いました!」などご参考頂いた方からのAmazonギフト券の寄付をお待ち致しております。


Atsushi Ezura について

ナチュラルな女性のしぐさや表情を撮りたいIT系エンジニア。女性モデル募集中プロフィール
カテゴリー: JavaScript, jQuery, コンピュータ, プログラミング言語 タグ: , , , パーマリンク

jQueryでチェックボックスの全チェック/外しをしようとしてハマッたこと、attr()とprop()の違いは罠レベル への1件のフィードバック

  1. ピンバック: jQuery チェックボックスの全チェック、外しを実装(修正版) | 日々の覚書…日常のことも少しだけ

コメントを残す

メールアドレスが公開されることはありません。