読者です 読者をやめる 読者になる 読者になる

7cc@はてなブログ

JavaScriptとかとか

ブラウザの戻ると進むを無理やり判別する

背景

多くのスムーズスクロールはスクロール後にハッシュを付与しているのでブラウザの「戻る」が動かない。そこで戻る」を可能にする方法を考えた・・・が無理やりな方法になってしまった。
「戻る」だけなら問題ないが、その後「進む」をする可能性があるので「進む」も考える必要があったのだ。

例えばページ内を #a -># b -> #a -> 戻 と移動したとする。このときハッシュは#bになり、進んでも戻っても次は#aになる。これを判別する手は思いつかない。

その無理やりな方法

そこで、ハッシュを追加することで一応判別できるようにした。具体的には

  1. ページ内リンクをクリックしたら#0, #1をつける
  2. 要素へ移動する
  3. 移動後に本来のハッシュをつける
  4. 「戻る」ならハッシュは#1, 「進む」ならハッシュは#0になる。やったね…?

無理やりゆえの欠点

  • onhashcange イベントが無駄に起こらないように注意がいる
  • history.lengthが加算されるのでページから抜けられなくなる可能性がある
    • history.lengthは最大値がある。Firefoxで50まで。それ以降は増えない。
  • location.hashの変更時にはidがあるか調べられているのでその分の負荷がかかる

無理やりなコード

var inpageLinks = document.querySelectorAll("a[href^='#']")

// add Events
for (var i=0, l=inpageLinks.length; i<l; i++) {
  inpageLinks[i].addEventListener("click", cl, false)
}

window.addEventListener("hashchange", ha, false)


// functions
var count = 0

function cl(){
  location.hash = "0"
  location.hash = "1"
  return count = 0
}

function ha(){
  console.log(count++)
  if(count > 3) {
    inpageHistoryBackForward()
    return count = 3
  }
}

function inpageHistoryBackForward() {
  if(location.hash === "#0") {
    history.go(2)
  } else if(location.hash === "#1"){
    history.go(-2)
  }
}