æ¬å½ã¯ãããªãã«é¢åãããJavaScriptã¨historyã¨Ajaxã®ã話
å£ä¸
historyã¨Ajaxã¨ããã°ãJavaScriptããããç¨åº¦ä»»æã§historyã®ã¨ã³ããªãpushã§ããhistory.pushStateã¨ããhistory.replaceStateã¯æ¢ã«å¤§åæåã«ãªã£ãæãããã
ç´ æ´ãããæªæ¥ã§ã¯ãå ¨ã¦ã®ãã©ã¦ã¶ã«pushStateãä¹ã£ã¦ãã¦ãlocation.hashã使ã£ãAjaxé·ç§»ã許ãããã®ã¯10å¹´åã®ãã©ã¦ã¶ã¾ã§ã ããã¼ãã¨ãããããã¼ãªä¸çãå®ç¾ããã®ã ãããããä»ç¾å¨ã§ã¯ã¾ã pushStateã«å¯¾å¿ãã¦ããªããã©ã¦ã¶ã®ã·ã§ã¢ãå¤ããAjaxã«ããæ¬ä¼¼ç»é¢é·ç§»ãã¢ãªã¢ãªè¡ããããªãµã¤ãã§ã¯pushStateã®ããç°å¢ããªãç°å¢ã®ä¸¡æ¹ãèæ ®ãã¦ããå¿ è¦ãããã
(ã¡ãªã¿ã«ãè¦ä»¶ã«ãã£ã¦ã¯ãpushStateããªããã©ã¦ã¶ã¯é常ã®é·ç§»ã§ææ ¢ããï¼ãã¨ããå²ãåããå ¨ç¶ããã ã¨æã)
å
ã«è¨ã£ã¦ããã¨ããã®è¨äºã¯é·ãã§ãã
ç°å¢ã®åé¡
history管çã¾ããã«ã¤ãã¦ãç¾å¨ã®ãã©ã¦ã¶ãåé¡ããã¨ã ããã以ä¸ã«3ã¤ã®ç°å¢ã«åããããã¨æãã
- history.pushStateãããç°å¢
- history.pushStateã¯ãªãããwindow.onhashchangeã®ããç°å¢
- history.pushStateããwindow.onhashchangeããªãç°å¢
å
¨ã¦ã®ãã©ã¦ã¶ãããã¿ã¶ãã«èª¿ã¹ãããã§ã¯ãªãã®ã§2.ã®ãããªç°å¢ã¯ã²ãã£ã¨ãããç¡ãã£ããããã®ãããããªãããã¾ã2ã¨3ã®ä¸¡å¯¾å¿ã¯é£ãããªãã®ã§ãã£ã¦ããªãã¦ãã¨ãããã対å¿ãã¦ããã¦ã½ã³ã¯ãªããã¡ãªã¿ã«ã3.ã®ç°å¢ã§ã¯æãæ¶ã§æ¿¡ãããªããhashã®å¤åãsetIntervalã§ç£è¦ãããã¨ã«ãªãã
pushStateã使ãå ´åã¨hashã使ãå ´åã®é·ç§»ããã¼
両対å¿ã®å ´åãããããã¡ãã£ã¨è©±ãé¢åããããªããpushState/hashã使ã£ã¦Ajaxã«ããé·ç§»ãå®è£
ããå ´åããããã®ããªã³ã¯ãèµ·å ã¨ããé·ç§»ã®ããã¼ã¯ä»¥ä¸ã®ããã«ãªããã¡ãªã¿ã«ãããã§ãããªã³ã¯ã¨ã¯aã¿ã°ãªããonclickã®ã¤ãããã®ä»ã®ã¿ã°ã®ãã¨ãæãã
ãªã³ã¯èµ·å ã®é·ç§»ããã¼ (with pushState)
ã¦ã¼ã¶ããªã³ã¯çãclick
â
ãããJSå´ã§ãã£ãããã¦ãå¿
è¦ãããã°preventDefaultã
â
該å½ããURLã«xhr
â
ãªã¯ã¨ã¹ããæåããå ´åãpushStateãhistoryãpush
â
(ãã®æç¹ã§historyã®ç¶æ
ãå¤å)
â
xhrã®ã¬ã¹ãã³ã¹(HTMLãªãJSONãªã)ã§ãç¹å®ã®DOMè¦ç´ ãæ¸ãæãã
ãªã³ã¯èµ·å ã®é·ç§»ããã¼ (with hash)
ã¦ã¼ã¶ããªã³ã¯çãclick
â
ãããJSå´ã§ãã£ãããã¦ãå¿
è¦ãããã°preventDefaultã
â
location.href =
â
(ãã®æç¹ã§historyã®ç¶æ
ãå¤å)
â
onhashchange, ã¾ãã¯hashã®pollingã§hashã®å¤åãæ¤ç¥
â
該å½ããURLã«xhr
â
xhrã®ã¬ã¹ãã³ã¹(HTMLãªãJSONãªã)ã§ãç¹å®ã®DOMè¦ç´ ãæ¸ãæãã
pushStateã®å ´åã«xhrã®success/errorãè¦ã¦ããhistoryãpushããå¿ è¦ã¯å¿ ããããªãã®ã ãã©ãåçç¡ç¨ã§historyã«çªã£è¾¼ããããã¯ãªã¼ã³ãªæ°ãããã®ã§ãhashé·ç§»ã®å ´åã§ããå ã«xhrãæãã¦ãæåã ã£ããURLãå¤ãããã¨ãã風ã«ããããåºæ¥ãããããããã¨å¾è¿°ã®ãã©ã¦ã¶ããã¯ã«ããé·ç§»ã¨ã®æ´åæ§ãåããªããªãï¼ãªã³ã¯èµ·å ã®é·ç§»ã¨ãã©ã¦ã¶ããã¯ã«ããé·ç§»ã§å¤ãªå ´ååããããªãã¦ã¯ãªããªããªãï¼ã®ã§ããã¾ããããããªãã
ãã©ã¦ã¶ããã¯(back, forwardå«ã)èµ·å ã®ããããã®é·ç§»ããã¼ã¯ä»¥ä¸ã
ãã©ã¦ã¶ããã¯èµ·å ã®é·ç§»ããã¼ (with pushState)
popstate eventãçºç«
â
event handlerå
ã§è©²å½ã®URL(stateã«å
¥ãã¦ãããããåã«location.hrefãã¿ã¦ããã)ã«xhr
â
xhrã®ã¬ã¹ãã³ã¹ã§ãDOMæ¸ãæã
popstate eventããé£ãªãé·ç§»ã®ä¸ã§ã¯pushStateã¯è¡ããªãã該å½ã®historyã¯ãæ¢ã«pushããã¦ããããã
ãã©ã¦ã¶ããã¯èµ·å ã®é·ç§»ããã¼ (with hash)
location.hashãå¤å
â
onhashchange, ã¾ãã¯hashã®pollingã§hashã®å¤åãæ¤ç¥
â
該å½ããURLã«xhr
â
xhrã®ã¬ã¹ãã³ã¹ã§ãDOMæ¸ãæã
ã¾ã¨ããã¨ãpushStateã¨hashã«ä¸¡å¯¾å¿ããå ´å
- ãã¼ã¸å ã®ãªã³ã¯èµ·å ã®é·ç§» with pushState
- ãã©ã¦ã¶ããã¯èµ·å ã®é·ç§» with pushState
- ãã¼ã¸å ã®ãªã³ã¯èµ·å ã®é·ç§» with hash
- ãã©ã¦ã¶ããã¯èµ·å ã®é·ç§» with hash
ã®ã4ã¤ã®å ´åã«ã¤ãã¦ããã¼ãæ´çãã¦ãhistoryãããããªãã¨ã«ãªããªãããã«ã±ã¢ãã¦ããå¿
è¦ããããéã«è¨ãã°ããã®4ã¤ã«ã¤ãã¦æ´çã§ããã°ã³ã¢ã®é¨åãæ¸ãã®ã¯ããã»ã©é£ãããªãã
ç¾å®ã®ãµã¤ãã«é©ç¨ããå ´åã®èæ ®ãã¹ãç¹
以ä¸ã®ãããªãã¨ãè¸ã¾ããä¸ã§ãåºå®ããããããã¼ãããã¿ã¼ãããã²ã¼ã·ã§ã³ãªã©ãåå¨ãããã以å¤ã®é¨åãAjaxã§ã¢ãªã¢ãªæ¸ãæãã¦æ¬ä¼¼ç»é¢é·ç§»ãè¡ããããªãµã¤ãã¸ã®é©ç¨ã«ã¤ãã¦èããã
é常ãªã³ã¯ã®æ¸ãæã
ä¸è¨ã®ãããªãµã¤ãã§ã¯ãä¾å¤ãå«ã¿ã¤ã¤ãåºæ¬çã«ã¯Ajaxã§ç»é¢é·ç§»ãè¡ãããªã®ã§ããã¼ã¸å ã®é常ã®ãªã³ã¯ãã¯ãªãã¯ãã¦è¡ãããã¢ã¯ã·ã§ã³ãä½ããã®å½¢ã§å·®ãæ¿ãã¦ããå¿ è¦ãããããã¼ã¸æ¯ã«ãã¡ãã¡addEventListenerããã®ã¯ããµã¤ãã®è¦æ¨¡ã«ãããããã¾ãç¾å®çã§ãªãã
ã±ã£ã¨æãã¤ãã®ã¯ä»¥ä¸ã®2ã¤ã
- hrefã¯ç¨ãããonclick="next('http://example.com/foo')"ã®ããã«åå¥ã«æ¸ãæãããaã¿ã°ä»¥å¤ã«ã«ã¤ãã¦ãåæ§ã«ãnextã¯pushState/hash対å¿ãªã©ãããããããã«è¨ãã£ã¦ãããé·ç§»ç¨ã®é¢æ°ã
- ãç¹å®ã®class, attributeãªã©ããã¤è¦ç´ ã«nextãbindãããã¨ããã«ã¼ã«ãã¼ã¹ãè¦ç´ ã¸ã®nextã®bindã¯ãAjaxã«ãããã¼ã¸é·ç§»æã«ã¾ã¨ãã¦è¡ãããã¾ãã¯event delegateãç¨ããã
åºæ¬çã«ã¯2.ã®æ¹ãHTMLå ã«onclick=""ã¨ãåºã¦ããªããè¦ãç®ãããããªãã ãã©ãã«ã¼ã«ãã¼ã¹æ ã«ç´°ããä¾å¤ã«å¯¾å¿ããã®ãé¢åãããã¨æããããã¾ããé·ç§»æã«ã¾ã¨ãã¦bindããå ´åããã¼ã¸å ã«å¤§éã®ãªã³ã¯ãããã¨ãããããªããevent delegateã使ãå ´åã®ã¯ãªãã¯ã¸ã®ã¬ã¹ãã³ã¹ã¯ãevent delegateã®å®è£ 次第ã
1.ã¯onclickãæ³¥èãããHTMLããã人ï¼ãã¼ã¯ã¢ããï¼ã¨JSããã人ï¼ã¨ã³ã¸ãã¢ï¼ãéãå ´åãåã«ãhrefãonclickãªãã¨ãã«ãã¨ãã¦ä¸ãããã¨ããã ãã§æ¸ã¿ããã¼ã¯ã¢ããã®äººãè¦ã¦ãã©ããAjaxé·ç§»ã®ãªã³ã¯ãªã®ãåãããããã¾ãåå¥ã«åãæ¿ããå¯è½ãªã®ã§ãç´°ããä¾å¤ã«å¯¾å¿ããããã¨ããå©ç¹ãããã
ç¾ç¶ã絶対ã«ã©ã¡ãããããã¨è¨ãåããªãã«ã³ã¸ããã£ã¨ããæ¹æ³ãªãããªã
URLã®æ£è¦å
æ£è¦åãã¨ããè¨èããã®å ´åã«ç¨æ³ã¨ãã¦æ£ããã®ãã¡ãã£ã¨å¾®å¦ã ãã©ã
pushStateã«ããé·ç§»ã¨hashã«ããé·ç§»ãå ±åãããå ´åãã¯ã©ã¤ã¢ã³ãå´ããè¦ãã¨åä¸ã®ãªã½ã¼ã¹ã«å¯¾ããURLã2種é¡ãããã¨ããç¶æ ã«ãªããã¤ã¾ããhttp://example.com/foo/bar ã¨ãããªã½ã¼ã¹ã«å¯¾ãã¦
- http://example.com/foo/bar
- http://example.com/#page=foo/bar (#foo/barã§ããããã ãã©ãã好ã¿ã§)
åè ãå½ç¶pushState対å¿ãã©ã¦ã¶ããè¦ããURLã§ãå¾è ãé対å¿ãã©ã¦ã¶ããè¦ããURLãã©ã¡ãã®å ´åãããã¼ã¸ã®ç¹å®ã®DOMè¦ç´ ã"http://example.com/foo/bar"ã«å¯¾ãã¦æããxhrã®ã¬ã¹ãã³ã¹ã使ã£ã¦æ¸ãæããããç¶æ ã«ãªã£ã¦ãããé常ã®ãã¼ã¸ãè¿ããããã¼ã¸ã®ä¸é¨åãè¿ããã¯HTTPã®request headerãªãquery parameterãªãã§å¤å¥ããã°ããã ããã
å°æ¥çã«ã¯pushStateã®è¼ã£ããã©ã¦ã¶ã°ããã«ãªãã ããããURLã®è¡¨ç¾ã¯ãã¡ãã«åãã¦ãããããã¤ã¾ããnext()ã«æ¸¡ãURLã«ã¯http://example.com/foo/barã¨ããhashã®ãªãããããªURLã使ããããã¾ãããµã¤ãå ¨ä½ã¨ãã¦ããã¡ãã®URLãæ£ã¨ãããã
ãªã®ã§ãnextã®ä¸ã§ã¯
function next(url) { if ( hasPushState ) { // pushStateãããå ´åã®å¦ç nextWithPushState(url); } else { // hashã使ãå ´åã®å¦çããã ãasHashUrlã§é常ã®URLãã2.ã®ãããªURLã«å¤æ nextWithHash(asHashUrl(url)); } }
ã®ããã«åå²ãè¡ããpushStateã®ãªããã©ã¦ã¶ã§hashãç¨ããé·ç§»ãè¡ãåã«URLã«å¯¾ãã¦é©åãªå¤æãããã¦ããå¿
è¦ãããã
redirect
hashã®pollingãªãã¦pushStateã®ãããã©ã¦ã¶ã§ãããã¯ãªãããéã«hashã§é·ç§»ãè¡ããã©ã¦ã¶ã§popstate eventãæ¾ã£ã¦ãæå³ã¯ãªããè¦ã¯ãpushStateã®ãããã©ã¦ã¶ã§ã¯ãã£ã¨æ£ããURLã®ã¿ãè¸ãã§pushState + Ajaxã§é·ç§»ãã¦ã»ããããhashã使ããã©ã¦ã¶ã§ã¯ãã£ã¨hashä»ãURLã®ä¸çã§æ®ããã¦ã»ããã
ããã§ããµã¤ãã«ãªã³ã¯å ±æã®ãããªæ©è½ãããå ´åãä¾ãã°pushStateã®ãªããã©ã¦ã¶ã使ã£ã¦ããã¦ã¼ã¶Aããµã¤ãå ã®ãªã½ã¼ã¹(http://example.com/#page=foo/bar)ã¸ã®ãªã³ã¯ãè²¼ãããã®ãªã³ã¯ãpushStateã®ãããã©ã¦ã¶ã使ãã¦ã¼ã¶Bãè¸ãã§ãã¾ããã¨ãããã¨ã¯å½ç¶ããå¾ããã¾ãããµã¤ãå ã«ããããæ©è½ããªãå ´åã§ããå¤é¨ããã¯ãã¼ã¯ãµã¤ããã®ä»ãå©ç¨ãã¦ãµã¤ãå ã¸ã®ãªã³ã¯ãä½ããããã¨ãããã¨ã¯å½ç¶èããªããã°ãªããªãã
pushStateã®ãããã©ã¦ã¶ã使ã£ã¦ããã¦ã¼ã¶ãhttp://example.com/#page=foo/barãè¸ãã§ãå½ç¶æ£ããé·ç§»ã¯ã§ããªãã®ã§ï¼ãããããªããããã®å ´åã ãhashã«fallbackãã¦ããããã©ãã¡ãã£ã¨æ²ããï¼ãhistoryã®å é ã«ã¡ãã£ã¨ã´ããå ¥ããã¨ãæ°ã«ãªããªããã°ãã®ãã©ã¦ã¶ã«é©ããURLã®æ¹ã«ãªãã¤ã¬ã¯ããã¦ããã°ããã¨æããã¤ã¾ãã
- pushStateã®ãããã©ã¦ã¶ã§http://example.com/#page=foo/bar ã«ã¢ã¯ã»ã¹ -> http://example.com/foo/bar ã¸ãªãã¤ã¬ã¯ã
- pushStateã®ãªããã©ã¦ã¶ã§http://example.com/foo/bar ã«ã¢ã¯ã»ã¹ -> http://example.com/#page=foo/bar ã¸ãªãã¤ã¬ã¯ã
ã®ãããªæãã«ããããã¦ããã°ãããããã®ä¸çç·ãã¯ãã¹ãããã¨ã¯ãªãããäºãã«å®çµãã¦ãããã
ãã®ãªãã¤ã¬ã¯ãã¯ãpushStateã®æç¡ãè¦ãªããã°ãããªãã®ã§JSã¬ã¤ã¤ã¼ã§è¡ãå¿
è¦ããããpushStateã®ããUAã®åæãªã©ãè¡ãã°ãµã¼ããµã¤ãã§ãçè«çã«ã¯å¯è½ã ãããããããæå³ã¯å¤åãªãã
ã¾ã¨ãã¨ãhist.jsã¤ãã£ããã¼ã¨ãã話
ãããªããã§ãpushState/hashã®ä¸¡å¯¾å¿ãè¡ãã¤ã¤Ajaxã§ã¢ãªã¢ãªé·ç§»ãè¡ãå ´åã¯ã¾ãã¾ãè²ã ãªãã¨ãèæ ®ãã¦ãããªãã¨ãããªãã
å®éã«ã³ã¼ãã«ãã¦ã¿ãã¨ããã¾ã§ã¯é·ããªããªãã®ã ãã©ãé¢åããã人ãå¤ãã ããã¨ã¨æãã®ã§ãã ãããä¸è¨ã®ãããªãã¨ãã±ã¢ããããã®ã©ã¤ãã©ãªãæ¸ããã
https://github.com/zentooo/hist.js
å¤é¨ã©ã¤ãã©ãªã¸ã®ä¾åã¯ãªãã使ãæ¹ã¯readmeã«ãæ¸ãã¦ãããã©ã以ä¸ã®ãããªæãã
hist.configure({ success: function(data) { // xhrãæåããå ´åã®callback document.getElementById("container").innerHTML = data; }, error: function(xhr) { // xhrã失æããå ´åã®callback } });
ãã®è¨å®ãè¡ã£ãä¸ã§ã
<a onclick="hist.next('http://example.com/foo/bar')">foobar</a>
ã¨ããããã風ã«ãªã³ã¯ãæ¸ããã¾ãã¯ã«ã¼ã«ãã¼ã¹ã§addEventListenerãã¦ãå é¨ã§hist.next()ãå¼ãã§ãããã
以ä¸ã®ãããªã»ã¼ããã©ã«ãè¨å®ã§åããã¨ã
- JSONãè¿ããã¨ããµã¼ãã«ç¥ãããããã®request header㯠X-Hist-XMLHttpRequest: 1
- hashãªURLã¯http://example.com/#page=foo/barå½¢å¼
- ãªãã¤ã¬ã¯ãã¯è¡ããªã
ã¨ããåä½ã«ãªãããããã®æåã¯ãªãã·ã§ã³ã§å¤æ´å¯è½ã
ã¾ãããªãã±ã¨ãã¦TwitterãFacebookãæ¡ç¨ãã¦ä¸æ話é¡ã«ãªã£ãcrunchbang(#!)ãªhash URLã«ã対å¿ãã¦ãããoptionã«withBang: trueã渡ããã¨ã§
ã®ãããªURLãçæãããããã«ãªãã
以åã«ä¼¼ããããªãã®ãæ¸ãã¦ã社å ã®ã©ã¤ãã©ãªã®ããã«ã¹ã¯ã©ããããæ¸ãç´ããä»ã®å½¢ã«åãåºãã¦ããå度ãªãã¡ã¯ã¿ãªã³ã° & ãã¹ãããã®ã§ããããªãã«ã¡ããã¨åãã¨ãããã
é·æä¹ã

Google API Expertã解説ããHTML5ã¬ã¤ãããã¯
- ä½è : ç¾½ç°é太巳,ç½ç³ä¿å¹³,å¤ç±ä¸æµ©,太ç°æå¾
- åºç社/ã¡ã¼ã«ã¼: ã¤ã³ãã¬ã¹ã¸ã£ãã³
- çºå£²æ¥: 2010/09/16
- ã¡ãã£ã¢: åè¡æ¬ï¼ã½ããã«ãã¼ï¼
- è³¼å ¥: 15人 ã¯ãªãã¯: 461å
- ãã®ååãå«ãããã° (14件) ãè¦ã