ハイパーニートプログラマーへの道

頑張ったり頑張らなかったり

Bootstrapのアコーディオンパネル(collapse)でページ遷移の際に開いた状態を維持する

Bootstrap3でのアコーディオンパネル(今回は.list-groupを使用)を作成したのですけど、

http://getbootstrap.com/javascript/#collapse-example-accordion

ページ遷移が起こった際に、パネルが閉じた状態になる。これを開いたままにしたい。特にパネルを複数用意した場合に便利かと。

調べてみると「Cookie使え」みたいな記事が出てくるので、js-cookieというものを使います。

github.com

HTML

これはほぼ公式サイトのまま。前述したように.panel-bodyの代わりに.list-groupを使用する。

<div id="accordion" class="panel panel-group" role="tablist">
  <div class="panel panel-default">
    <div class="panel-heading" role="tab" id="collapseListGroupHeading1">
      <h4 class="panel-title">
        <a class="" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseListGroup1" aria-expanded="true" aria-controls="collapseListGroup1"> Collapsible list group #1</a>
      </h4>
    </div>
    <div id="collapseListGroup1" class="panel-collapse collapse" role="tabpanel" aria-labelledby="collapseListGroupHeading1" aria-expanded="true">
      <ul class="list-group">
        <li class="list-group-item">Bootply</li>
        <li class="list-group-item">One itmus ac facilin</li>
        <li class="list-group-item">Second eros</li>
      </ul>
    </div>
  </div>

  <div class="panel panel-default">
    <div class="panel-heading" role="tab" id="collapseListGroupHeading2">
      <h4 class="panel-title">
        <a class="" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseListGroup2" aria-expanded="true" aria-controls="collapseListGroup2"> Collapsible list group #2</a>
      </h4>
    </div>
    <div id="collapseListGroup2" class="panel-collapse collapse" role="tabpanel" aria-labelledby="collapseListGroupHeading2" aria-expanded="true">
      <ul class="list-group">
        <li class="list-group-item">Bootply</li>
        <li class="list-group-item">One itmus ac facilin</li>
        <li class="list-group-item">Second eros</li>
      </ul>
    </div>
  </div>

  <div class="panel panel-default">
    <div class="panel-heading" role="tab" id="collapseListGroupHeading3">
      <h4 class="panel-title">
        <a class="" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseListGroup3" aria-expanded="true" aria-controls="collapseListGroup3"> Collapsible list group #3</a>
      </h4>
    </div>
    <div id="collapseListGroup3" class="panel-collapse collapse" role="tabpanel" aria-labelledby="collapseListGroupHeading3" aria-expanded="true">
      <ul class="list-group">
        <li class="list-group-item">Bootply</li>
        <li class="list-group-item">One itmus ac facilin</li>
        <li class="list-group-item">Second eros</li>
      </ul>
    </div>
  </div>
</div>

js-cookie

Cookieの使用はいたって簡単で

値をセットする

Cookies.set('name', 'value');

Cookieの期限も設定できる。expiresオプション。下記の例では7日間です。

Cookies.set('name', 'value', { expires: 7 });

Railsで使用する場合はこのオプションとパスを設定しないとうまく動作しないようです。

【Rails】RailsとJQueryでCookieを相互に利用したい時に気をつけるべき2つの注意点 - 働かないで3億貯めてさっさとリタイアするブログ

値を読むこむ

Cookies.get('name'); // => 'value'

Cookieを削除

Cookies.remove('name');

オプションはEncode/Decodeオプション、Secure属性を付加するためのsecureオプションというものがあります。
今回の場合はidを読み書きするだけなので、設定はしてません。

JavaScript(jQuery)

// http://stackoverflow.com/questions/12733238/retain-twitter-bootstrap-collapse-state-on-page-refresh-navigation

$(document).ready(function () {
  //when a group is shown, save it as the active accordion group
  $("#accordion").on('shown.bs.collapse', function () {
      var active = $("#accordion .in").attr('id');
      Cookies.set('activeAccordionGroup', active, { expires: 7 });
      alert(active);
  });
  $("#accordion").on('hidden.bs.collapse', function () {
      Cookies.remove('activeAccordionGroup');
  });
  var last = Cookies.get('activeAccordionGroup');
  if (last != null) {
    //remove default collapse settings
    $("#accordion .collapse").removeClass('in');
    //show the account_last visible group
    $("#" + last).addClass("in");
  }
});

パネルの開閉のイベントでは、Bootstrapのshown.bs.collapsehidden.bs.collapseを使っています。

.collapseが開いているときは.inクラスが付加されているので、そこのidを取得し、activeという変数に代入。
そしてそれをCookieに設定する。

そしてアラートを出しているのですが、先ほど取得したidを表示しています。

パネルが閉じたときはCookieを削除。

ページが読み込まれた際に、保存しておいたCookieを取得。lastに代入しておきます。
そして.collapseクラスから.inを削除。先ほど取得したidを持つ要素に.inクラスを追加。
取得したid#の付いていないものなので、先頭に付けることも忘れず。

http://getbootstrap.com/javascript/#collapse-usage

http://getbootstrap.com/javascript/#collapse-events

参考にした記事はこちら。

stackoverflow.com

こちらのコードの方を参考にしたかな。Bootstrapのイベントを使っているので。

http://stackoverflow.com/a/25258290

Codepen上で作ってみました。

See the Pen Bootstrap accordion with js-cookie by Noriyo Akita (@noriyotcp) on CodePen.

パネルを開くとアラートが出ます。その後、右下の「RERUN」ボタンを押すと、先ほど開いたパネルの状態が維持されているのを確認できるかとー。Codepen便利。