jQueryを使ったスライド開閉メニューをCookieでコントロールする

jQueryを使った開閉メニューをCookieでコントロールする

サンプル
サンプルファイルのダウンロード

ちょっと前に流行った?アコーディオンメニューの開閉状態を
Cookieで保存する方法をメモをかねて紹介します。

必要なファイルを集める

面倒だと思うのでサンプルにまとめました。
サンプルファイルをダウンロードして新しいHTMLでJSファイルを読み込んでください。

サンプルファイルのダウンロード

HTMLを用意する

CSSファイルを読み込む

この記事でCSSの解説はしてません。。



JSファイルを読み込む





HTMLをマークアップする


           

HTMLがちょっと気持ち悪いと思う人もいるかもしれませんが
今回はこんな感じでマークアップしてます。

JSを書く

普通にアコーディオンメニューにする

今回は特にアコーディオン部分の記述にはふれませんが
以下の記述でアコーディオンになります。

jQuery Easingプラグインを使ってちょっと動きを変えてます。
何気ないアコーディオンもこういう動きなら面白いかもしれないですね。
単純に鬱陶しいだけにもなり得ますけど…

ちなみに、前回のエントリjQuery.easingscroll.jsはEasingプラグインを
含んでいるので併せて使うと楽しい動き(≠うざい動き)のサイトになりますね!


/*
* @ スライドナビゲーション
*/
$("ul.sub_nav","div#sub").each(function(i){
// 開閉ナビで使う変数定義
  var me = $(this),
    box = me.parent(), // 親要素のdiv.nav
    heading = me.prev().append(""),
    // 兄要素のh2にspan.toggleを追加して変数に保存
    toggle = $("span.toggle",heading);// Toggle

  // 下層ナビとToggleボタンを隠す
  me.hide();
  toggle.hide();

  // Toggleボタンの表示非表示
  heading.hover(function(){
    toggle.show();
  },function(){
    // h2.openedの場合はToggleを表示したままにする
    if(!heading.hasClass("opened")) toggle.hide();
  });

  // Toggleクリック時の動作
  toggle.click(function(){
    heading.toggleClass("opened");
    if(!box.hasClass("opened")) box.addClass("opened");

    // アニメーション設定
    me.animate({
      height: "toggle"
    },{
      easing: "easeOutBounce",
      // jQuery Easingを使って開閉時に跳ねるようにしてみる
      duration: 400,
      complete: function(){
        if(!heading.hasClass("opened")) box.removeClass("opened");
      }
    });
  });
});

jQuery Cookieを使うのでちょっと紹介

jQuery.cookieプラグインを使ってます。
jQueryを使う場合はこれが一番わかりやすく、簡単にCookieを扱えます。

いちおう説明しておくと


$.cookie("Cookieの名前", "Cookieの値"); // 保存
$.cookie("Cookieの名前"); // 値の読み出し

という具合で使えます。
保存時、第3引数でオプションを指定することで保存日数などを指定できます。


$.cookie("Cookieの名前", "Cookieの値" { expires: 7, path: "/", domain: "jquery.com", secure: true });

また、値にnullを入れることでCookieを削除することができます。


$.cookie("Cookieの名前", null); // Cookieの削除

Cookieを使うタイミング

開閉状態を保存する場合Cookieを扱う箇所が3つあって

  • Toggleをクリックしたとき(開けるとき) – Cookieを保存
  • Toggleをクリックしたとき(閉じるとき) – Cookieを保存
  • ページをロードしたとき – Cookieを読み出す

この3つのタイミングでCookieを保存したり、読み出すことで開閉状態を保存できます。

Cookieの保存方法をどうするのか

全てのアコーディオンでCookieを保存するのはきれいなやり方ではないので
開いた状態を記憶するためにCookieには[i]という値を保存していくことにします。

例えば、1つめのパネルが開いた場合、Cookieには[0]が保存されることになります。
さらに、2つめも開いた場合、[0][1]という値が保存されます。

閉じる場合には逆で[i]を取り除くことで元の状態になります。
これらの値はパネルが開いた順に保存されていくので
3-2-4という順番で開いた場合、[2][1][3]といったように保存されますが
値の削除時にはreplace関数を使うので、この順番は特に問題ありません。

ちなみに[]を使う理由はパネル数が10を超える場合に
0と1〜9の区別がつかなくなるのを防ぐためです。

とりあえずCookieを使って保存していく

まずはCookieの値を変数に保存しておきます。
これはページロードのタイミングで行います。


var cookie = ($.cookie("menu") && $.cookie("menu")!=null) ? $.cookie("menu") : "";

Cookieの名前はmenuにしています。
Cookiに値がある場合はcookieに値を保存
それ以外の場合は空の値を渡しておきます。

あとCookieに保存する・識別用の値を宣言しておきます。


// 開閉ナビで使う変数定義に追記する
var pos = "["+i+"]"; // Cookieに保存する

この i はeach関数でループ時に得られる引数を使います。
準備ができたらClick時に保存するように記述します。


if(!box.hasClass("opened")){ // 開くとき
  box.addClass("opened");
  cookie += pos; // このパネルの識別用の値をCookieの値に追記
  $.cookie("menu",cookie); // Cookieの値をCookie["menu"]に保存する
}else{ // 閉じるとき
  cookie = cookie.replace(pos,""); // このパネルの識別用の値をCookieの値から削除する
  $.cookie("menu",cookie.length==0 ? null : cookie);
  // Cookieの値をCookie["menu"]に保存する
  // このとき値が空になったらCookie["menu"]を削除する
}

あとは初期表示パネルを最初に保存したCookieの値から決めます。
cookie.match(new RegExp(pos))の部分で判別してます。


// クッキーに[i]がある場合はナビを表示する
if($.cookie("menu")==null
|| cookie.indexOf(pos)==-1){
  me.hide();
  toggle.hide();
}else{
  box.addClass("opened");
  heading.addClass("opened");
}

これらのソースコードを追記した完成版が以下になります。


/*
* @ スライドナビゲーション
* @ Cookieを使って開閉をコントロール
*/
// ナビゲーションで使うCookieを読みこんでおく
var cookie = ($.cookie("menu") && $.cookie("menu")!=null) ? $.cookie("menu") : "";
$("ul.sub_nav","div#sub").each(function(i){
  // 開閉ナビで使う変数定義
  var me = $(this),
    box = me.parent(), // 親要素のdiv.nav
    heading = me.prev().append(""),
    // 兄要素のh2にspan.toggleを追加して変数に保存
    toggle = $("span.toggle",heading), // Toggle
    pos = "["+i+"]"; // Cookieに保存する

  // クッキーに[i]がある場合はナビを表示する
  if($.cookie("menu")==null
  || cookie.indexOf(pos)==-1){
    me.hide();
    toggle.hide();
  }else{
    box.addClass("opened");
    heading.addClass("opened");
  }

  // Toggleボタンの表示非表示
  heading.hover(function(){
    toggle.show();
  },function(){
    // h2.openedの場合はToggleを表示したままにする
    if(!heading.hasClass("opened")) toggle.hide();
  });

  // Toggleクリック時の動作
  toggle.click(function(){
    heading.toggleClass("opened");
    if(!box.hasClass("opened")){
      box.addClass("opened");
      cookie += pos;
      $.cookie("menu",cookie);
    }else{
      cookie = cookie.replace(pos,"");
      $.cookie("menu",cookie.length==0 ? null : cookie);
    }

    // アニメーション設定
    me.animate({
      height: "toggle"
    },{
      easing: "easeOutBounce", // jQuery Easing
      duration: 400,
      complete: function(){
        if(!heading.hasClass("opened")) box.removeClass("opened");
      }
    });
  });
});

完成サンプルを見る

というわけで

肝心のCookieはかなり簡単に使えるということが伝わったでしょうか。
Cookieの保存方法は色々考えられるので試してみると楽しいです。

jQueryとjquery.cookie.jsを使って開閉を保持するメニューを作ってみる – caraldo.net
jQueryを使用したCookie開閉保持メニューをよりjQueryっぽく書き直す – caraldo.net

同じHTMLで2通りのやり方とか。後の記事の方がCookieがすっきりします。

何か役に立つことがあったらシェアしてみてください

このエントリーをはてなブックマークに追加

Comments: 8 - Leave a comment

  1. kaz

    デフォルトを開いた状態にするには、どうすれば良いでしょうか。
    クッキー判定のあたりを変更するのかと思い、
    いろいろ試してみたのですが上手くいきませんでした。
    全体の処理を反対にする必要があるのでしょうか。

    よろしければご教示ください。

  2. yama

    メニューが複数、開けますが、
    1つのみにするにはどうしたらいいでしょうか。
    (別のメニューを開いたら、開いているメニューが閉じる。
    必ず開いているメニューは1つのみ。)

  3. chibi-ta

    貴重な情報、ありがとうございます!!
    最初に質問している「sato」同様に要素が10個以上の場合に、おかしな表示になってしまいます。
    何か回避方法ありますでしょうか?

    1. nori

      ソースコードが悪かったですね!
      32行目:
      !cookie.match(new RegExp(pos))
      部分を
      cookie.indexOf(pos)==-1
      に修正したのでもう大丈夫なはずです。

  4. ファジー

    ものすごーく参考になりました。
    ありがとうございます!
    1点だけご質問させてください。
    これを別ページ、別メニューにも使用する時、例えばページAでメニューA、ページBでメニューBと使用する場合同じcookieを見てしまう為、Aの情報をBが引き継いでしまいます。
    この使い方をする場合はcookieを別けるべきでしょうか?

    宜しくお願い致します。

  5. no8u

    貴重な情報をありがとうございました。
    とても参考になりました。

    ただ、サンプルソースではリンク先が全て空文字(=すべて同じという事)なので問題はないのですが、実際にリンク先を指定して実行すると、そのパス別にクッキーが保存されてしまうので、クッキーを保存する時にパスを指定してあげる必要があります。
    パスは何でも良いと思い’/'にしました。

    具体的にはこんな感じです。
    $.cookie(“menu”,cookie,{path: ‘/’});
    $.cookie(“menu”,cookie.length==0 ? null : cookie,{path: ‘/’});

    一応参考になればと思い、コメントさせて頂きました。

    1. nori

      お返事遅くなりごめんなさい。
      コメントありがとうございます!

      確かにそうですね。。そこ全然考えてなかったです。
      追記しておきます!ありがとうございました!

  6. sato

    大変参考になりました!!
    が、セクション(開閉するテーブル)が10個以上になると
    動作がおかしくなるようです。

    たとえば開閉テーブルが10個以上の時、
    1番目のテーブルを開いた状態でリロード(F5)すると
    11番目のテーブルも開いた状態でリロードされます。

    回避方法などありましたら教えていただけると大変助かります。

Leave a comment

Trackbacks: 2

Trackback URL for this entry
Listed below are links to weblogs that reference
jQueryを使ったスライド開閉メニューをCookieでコントロールする from 5509
  1. pingback from links for 2009-05-26 | Webデザインのリンク集 Webデザインポータルサイト S5-Style

    [...] jQueryを使ったスライド開閉メニューをCookieでコントロールする | 5509 [...]

  2. pingback from links for 2009-12-04 » ononolab.com -

    [...] jQueryを使ったスライド開閉メニューをCookieでコントロールする :: 5509 (tags: webdesign css tips javascript ajax tutorial jquery 案件) [...]

Author

nori
nori
- UI Engineer
Location
- ,