ブラウザの「戻る」で戻ったときに選択しているoption要素を戻す方法

select要素のonchangeで即ページ遷移するような実装をすることがたまにある。ボタン押して普通にsubmitさせろよとも思うけど、手順一つ省略したい気持ちもまあわかる。

$('select').on('change', function () { $(this).closest('form').submit() });

まあ、こんな感じに。

これ自体は問題ない。問題はこの後にブラウザの「戻る」で戻った場合で、ほとんどのブラウザの実装では、キャッシュがある限り、フォームコントロールはそのまま戻ることになる。

普通ならそれで問題はないのだが、select要素でonchangeでやってる場合ちょっとやっかいなことになる。なぜかというと、select要素をクリックして、メニューを開いた後、選択を変えずにメニューを閉じた場合、onchangeは発火しないから。

だからこのような使い方をする場合、HTML上のselected属性の通りに選択されていて欲しい。それをどう実現するか?

結論から言うと、window.onloadと、Firefoxなど向けにwindow.onshowpageに、HTML上のselectedをじっさいの選択に合わせる関数を登録すればいい。jQueryでやるならこんな感じ。

function init() {
  if ($('select option[selected=selected]').attr('selected')) {
    $('select').val($('select option[selected=selected]').val());
  }
  else {
    $('select option:first').prop('selected', 'selected');
  }
}

jQuery(function () {
    init();
    $(window).on('pageshow', init);
});

注意点がいくつかあって、

  1. :selected擬似セレクタではなく、[selected=selected]を使う。
  2. selected属性がどのoption要素にもない場合に、ブラウザっぽく最初のoption要素をselectedにするようにする。
  3. selectedにするのにはval(), attr()あたりではなくprop()を使う。