2009-09-15
ブラウザごとのlocation.hashの挙動のまとめ
今更ですが、location.hashで現在のステータスを管理するのがマイブームです。しかし、ASCII以外をぶち込むとブラウザごとに挙動が違うっぽいです。というのを調べておいて、書いておくのを忘れたので、まとめておきます。
方法
以下のアクションを起こした場合、location.hashで取得できる値がどうなるか、調べました。なお、ファイルはUTF-8で試しました。
ファイルに書いてあるリンクをクリックした場合
- A1:#test
- B1:#てすと
- C1:#%E3%81%A6%E3%81%99%E3%81%A8
- A2:#test#test
- B2:#てすと#てすと
- C2:#%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8
- A3:#test%23test
- B3:#てすと%23てすと
- C3:#%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8
頭が#じゃないやつの結果は見えているのでやりません。
location.hashへ代入した場合
a1〜c3まで上のテストの文字列から#を削ったものと一致します。
こいつを地道にクリックした感じです。もうちょい自動化されたやつはどっかいった。
<!doctype html> <html> <head><meta charset="UTF-8"></head> <body> <p> <a href="#test">A1</a> <a href="#てすと">B1</a> <a href="#%E3%81%A6%E3%81%99%E3%81%A8">C1</a> <a href="#test#test">A2</a> <a href="#てすと#てすと">B2</a> <a href="#%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8">C2</a> <a href="#test%23test">A3</a> <a href="#てすと%23てすと">B3</a> <a href="#%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8">C3</a> </p> <p> <span id="a1">a1</span> <span id="b1">b1</span> <span id="c1">c1</span> <span id="a2">a2</span> <span id="b2">b2</span> <span id="c2">c2</span> <span id="a3">a3</span> <span id="b3">b3</span> <span id="c3">c3</span> </p> <p><input id="r"></p> <script type="text/javascript"> function $(id) { return document.getElementById(id); } $("a1").onclick = function () { location.hash = "test"; }; $("b1").onclick = function () { location.hash = "てすと"; }; $("c1").onclick = function () { location.hash = "%E3%81%A6%E3%81%99%E3%81%A8"; }; $("a2").onclick = function () { location.hash = "test#test"; }; $("b2").onclick = function () { location.hash = "てすと#てすと"; }; $("c2").onclick = function () { location.hash = "%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8"; }; $("a3").onclick = function () { location.hash = "test%23test"; }; $("b3").onclick = function () { location.hash = "てすと%23てすと"; }; $("c3").onclick = function () { location.hash = "%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8"; }; setInterval(function () { $("r").value = location.hash; }, 1000); </script> </body> </html>
結果
ブラウザ | A1 | B1 | C1 | A2 | B2 | C2 | A3 | B3 | C3 |
---|---|---|---|---|---|---|---|---|---|
IE6 | #test | #てすと | #%E3%81%A6%E3%81%99%E3%81%A8 | #test#test | #てすと#てすと | #%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #てすと%23てすと | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
Fx3.5 | #test | #てすと | #てすと | #test#test | #てすと#てすと | #てすと#てすと | #test#test | #てすと#てすと | #てすと#てすと |
Opera10 | #test | #てすと | #%E3%81%A6%E3%81%99%E3%81%A8 | #test#test | #てすと#てすと | #%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #てすと%23てすと | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
Safari4 | #test | #%E3%81%A6%E3%81%99%E3%81%A8 | #%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
Chrome | #test | #てすと | #%E3%81%A6%E3%81%99%E3%81%A8 | #test#test | #てすと#てすと | #%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #てすと%23てすと | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
IE、Opera、Chromeは代入された値を返す。Firefoxは全てdecode、Safariは全てencodeされた結果を返す。
ブラウザ | a1 | b1 | b1 | a2 | b2 | c2 | a3 | b3 | c3 |
---|---|---|---|---|---|---|---|---|---|
IE6 | #test | #てすと | #%E3%81%A6%E3%81%99%E3%81%A8 | #test#test | #てすと#てすと | #%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #てすと%23てすと | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
Fx3.5 | #test | #てすと | #てすと | #test#test | #てすと#てすと | #てすと#てすと | #test#test | #てすと#てすと | #てすと#てすと |
Opera10 | #test | #てすと | #%E3%81%A6%E3%81%99%E3%81%A8 | #test#test | #てすと#てすと | #%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #てすと%23てすと | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
Safari4 | #test | #%E3%81%A6%E3%81%99%E3%81%A8 | #%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #fYh%23fYh | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
Chrome | #test | #てすと | #%E3%81%A6%E3%81%99%E3%81%A8 | #test#test | #てすと#てすと | #%E3%81%A6%E3%81%99%E3%81%A8#%E3%81%A6%E3%81%99%E3%81%A8 | #test%23test | #てすと%23てすと | #%E3%81%A6%E3%81%99%E3%81%A8%23%E3%81%A6%E3%81%99%E3%81%A8 |
Safariはencodeしないとバグる場合がある。
まとめ
- アンカーを付けたリンクを生成する場合は必ずencodeURIComponentでencodeして付与する。
- location.hashに代入する場合も必ずencodeURIComponentでencodeして代入する。
- 以上が守られたlocation.hashの値を取得する場合はFirefox以外はdecodeURIComponentでdecodeする。
と、クロスブラウザなlocation.hashの扱いが可能になる。
おまけ
jQueryライブラリにしてあったのを思い出した。
$.anchor = function (val, skip) { var fn = arguments.callee; switch (typeof val) { // getter case "undefined": var ret = location.hash; if (!ret) { return null; } ret = ret.replace(/^#/, ""); return $.browser.fx ? ret : decodeURIComponent(ret); // callback case "function": if (!fn.tid) { fn.hash = location.hash; (function rec() { if (!fn.skip && fn.hash !== location.hash) { fn.hash = location.hash; $(window).trigger("changeAnchor", $.anchor()); } fn.tid = setTimeout(rec, 300); })(); } return $(window).bind("changeAnchor", val); // setter default: if (skip) { fn.skip = true; location.hash = encodeURIComponent(val); fn.hash = location.hash; fn.skip = false; } else { location.hash = encodeURIComponent(val); } return; } }; // 取得 $.anchor(); // 代入 $.anchor("てすと"); $.anchor("てすと", true); // イベントに反映させない // location.hashが変化したら、取得 $.anchor(function (evt, hash) { alert(hash + "に変わったよ") });
なんか、ページ番号とかをlocation.hashで管理している場合は、使い道があるかもしれません。バグっているかもしれないけど。
- 60 http://reader.livedoor.com/reader/
- 58 http://b.hatena.ne.jp/entry/d.hatena.ne.jp/ofk/20090915/1252993893
- 38 http://www.google.co.jp/search?q=location.hash&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&client=firefox-a
- 38 http://www.google.co.jp/search?q=location.hash&lr=lang_ja&ie=utf-8&oe=utf-8&aq=t&rlz=1R1GGGL_ja___JP327&client=firefox-a
- 30 http://d.hatena.ne.jp/
- 27 http://d.hatena.ne.jp/tkng/20091003/1254578195
- 21 http://www.google.co.jp/search?hl=ja&source=hp&q=location.hash&lr=&aq=9&oq=locati
- 19 http://js.designlinkdatabase.net/data/frame_332967.aspx
- 19 http://www.google.co.jp/search?hl=ja&source=hp&q=location.hash&btnG=Google+検索&lr=&aq=f&oq=
- 18 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GGLJ_jaJP175JP176&q=location.hash