less

きづかないくらいイージーなクオリティー

Archive

8月
29th
permalink

$.dataはHTML5 datasetのラッパーではない

HTML5では要素に任意の属性を追加出来るdata-*属性がサポートされました。仕様では

<div data-foo="bar">...</div>

data-fooの値にはdiv.dataset.fooからアクセスすることが出来ます。ただしdatasetは現在一部ブラウザでしかサポートされていない。。そこでjQueryに存在する$.dataメソッドを使いましょう、という流れなのですが、$.dataをラッパーとして見た場合結構罠がありおすすめ出来ません。中途半端に対応してしまったために誤解されがちですが、$.dataはdatasetのラッパーではありません。

属性値がJSONとして解釈出来る場合、パースして返す

<div id="test1" data-json="{&quot;foo&quot;:&quot;bar&quot;}">...</div>
$('#foo').data('json').foo // = "bar"

<div id="test2" data-number="42">...</div>
$('#test2').data('number') // = 42

<div id="test3" data-null="null">...</div>
$('#test3').data('null') // = null

HTML5 datasetは全ての値を文字列として扱いますが、$.dataはJSONとして扱える場合JSONとして処理します。上の例のようにJSONテキストはオブジェクトに、数値文字列は数値型に、「null」はnullに変換されます。また、「true」と「false」は特別に真偽値に変換されます。

このためユーザーの入力値をdata-*属性に入れている場合、処理内容によってはセキュリティ的に問題になったり、文字列のみが返る想定で作っているとJSのエラーを引き起こす可能性があります。TwitterのポストIDのように極端に桁が大きい数値文字列は、この型変換で丸められて正常に取得出来なくなってしまうかもしれません。

元々jQueryは独自に要素にデータを持たせる仕組みを持っており、HTML5でdata-*属性が仕様化された後に「data-*属性にデフォルト値を指定出来る」扱いでdata-*属性の値取得をサポートしました。データそのものの扱いはjQueryの以前からの仕組みのままです。そのため、1.6.2現在でも$.dataで書き込んだ値にDOMからアクセス出来ないなど、単純に属性値を読み書きするメソッドとして考えるのは無理があります。

このような状況なので、使うならば仕様を良く理解した上で、data-*属性の内容が任意の場合やパース処理が余計な場合には$.dataを使わずに単純に文字列で入出力するメソッドを作るのがいいと思います($.attrも使える)。先に触れたように誤解されやすいので、jQueryに$.datasetメソッドが新設されてもいいかもしれないですね。プラグインはあるようです(ただしこのプラグインは$(element).dataset('fooBar', 123)をdata-foobar属性に書き込む。仕様に合わせる意味でdata-foo-barに書き込まれるのがベターだと思うし、最新のjQueryではそうなっている)。

自前でjquery.dataset.js作りました