アコーディオンパネルUIの自作

続いてアコーディオンパネルUIを自作してみる。まずは基本的な動作の部分から。

<html>
  <head>
    <style>
dl{
    width:800px;
}
dt{
    line-height:35px;
    font-size:large;
    text-indent:3em;
    font-weight:bold;
    color:white;
    height:35px;
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background.jpg")
}
dd{
    margin:0;
    height:300px;
    background:#D4D0C8;
}
dd p{
    margin:0;
    text-indent:1em;
    padding:20px;
}
    </style>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">google.load("jquery", "1.3.2");</script>
    <script type="text/javascript">
    $(function(){
      //先頭のdd要素以外を非表示にする。
      $("dd:not(:first)").css("display","none");
      //dt要素をクリックされた場合のイベントを登録
      $("dl dt").click(function(){
        //「コンテキスト」であるセレクターの第2引数 thisと、
        //「隣接セレクター」である、"+" の複合技。
        //thisで、現在処理対象になっているクリックされた dt 要素を対象とし、
        //隣接セレクターでその次以降に出現する dd 要素のCSSプロパティのdisplayが
        //noneの場合(非表示)の場合のみ if ブロックの処理を行う感じ。
        if($("+dd",this).css("display")=="none"){
          //すべての dd 要素をスライドアップして非表示に。
          $("dd").slideUp("slow");
          //その後クリックされたdt要素に対応するdd要素をスライドダウンして表示する。
          $("+dd",this).slideDown("slow");
        }
      });
    })
    </script>
  </head>
  <body>
    <dl>
      <dt>Step.1</dt>
      <dd><p>Lorem ...(中略)... venenatis.</p></dd>
      <dt>Step.2</dt>
      <dd><p>Integer ...(中略)... accumsan. </p></dd>
      <dt>Step.3</dt>
      <dd><p>Integer ...(中略)... imperdiet. </p></dd>
    </dl>  
  </body>
</html>

以上で一通り動くアコーディオンパネルは作成できた。もう少しブラッシュアップしてみよう。変更する内容は次の3点。

  • 現在開いているラベルの色
  • 閉じているラベルにマウスカーソルが重なったとき(マウスオーバー時)の色
  • マウスカーソルの形状
これらの修正項目を適用したのが次のコード。

<html>
  <head>
    <style>
dl{
    width:800px;
}
dt{
    line-height:35px;
    font-size:large;
    text-indent:3em;
    font-weight:bold;
    color:white;
    height:35px;
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background.jpg")
}
dd{
    margin:0;
    height:300px;
    background:#D4D0C8;
}
dd p{
    margin:0;
    text-indent:1em;
    padding:20px;
}

dt.over{
    /* マウスカーソルの形状を手の形に */
    cursor: pointer;
    /* dtの上にマウスカーソルが来たときのラベルの背景を指定 */
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-over.jpg");
}
dt.selected{
    /* マウスカーソルの形状 */
    cursor: default;
    /* 選択されたときのラベルの背景を指定 */
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background_selected.jpg");
    color: black;
}
    </style>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">google.load("jquery", "1.3.2");</script>
    <script type="text/javascript">
    $(function(){
      $("dd:not(:first)").css("display","none");

      //デフォルトで先頭のddが選択されている状態なので、dt.selectedを適用する。
      $("dt:first").addClass("selected");

      $("dl dt").click(function(){
        if($("+dd",this).css("display")=="none"){
          $("dd").slideUp("slow");
          $("+dd",this).slideDown("slow")

          //------------------------------
          //現在開いているラベルの色を変更する処理
          //------------------------------
          //すべてのdt要素から、selectedクラスを削除する。
          $("dt").removeClass("selected")
          //自分のクラスだけselectedクラスを適用する。
          $(this).addClass("selected")
        }
      });
      $("dl dt").mouseover(function(){
        $(this).addClass("over");
      }).mouseout(function(){
        $(this).removeClass("over");
      });
    })
    </script>
  </head>
  <body>
    <dl>
      <dt>Step.1</dt>
      <dd><p>Lorem ...(中略)... venenatis.</p></dd>
      <dt>Step.2</dt>
      <dd><p>Integer ...(中略)... accumsan. </p></dd>
      <dt>Step.3</dt>
      <dd><p>Integer ...(中略)... imperdiet. </p></dd>
    </dl>  
  </body>
</html>

イイヨイイヨ〜♪
最初、参考URLの記事を見ずに「閉じているラベルにマウスカーソルが重なったとき(マウスオーバー時)の色」と「マウスカーソルの形状」を自力でやってみようと思って「dt:hover」を使って実装してみたんだが、選択済みのdtの上に来たときはマウスカーソルの形状を変えたくないのに対応できずに結局参考URLのコードを見ることに。

結局のところ、その時のデザインに合致したクラスを定義しておいて、状況に応じてクラスを変更する、ってやり方がどうも王道らしい。肝に命じておこう!


最後に縦のアコーディオンパネルではなく、横のアコーディオンパネルについて実装してみる。

dtの部分は英文字が縦書きになるけども、クロスブラウザで縦書きを指定することはできないので、画像で代用。。
(昔一時だけ、CSS3のドラフトにwriting-modeプロパティが上がったこともあったようだが、結局削除されたとのこと。今のところクロスブラウザで縦書き表示をしたければSVGを使うのが安全?らしい。)

<html>
  <head>
    <style>
div{
    width:800px;
    height:300px;
    margin:50px auto;
    overflow:hidden;
}
dl{
    width:900px;
    height:300px;
}
dt{
    width:35px;
    height:300px;
    float:left;
}
dt span{
    display:block;
    width:100%;
    height:100%;
    text-indent:-9999px;
}
/* dtの上にマウスがきた場合に指定されるクラス */
dt span.over{
    cursor:pointer;
}
/* 選択されたdtに指定されるクラス */
dt span.selected{
    cursor:default;
}


/* 以下、Step.X専用に、マウスオーバー状態、選択状態によって、画像を変更しなければならない為に必要なクラス群が定義される。 */

/* Step.1専用に指定されるクラス群 */
dt#step1 span{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-1.jpg");
}
dt#step1 span.over{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-1-over.jpg");
}
dt#step1 span.selected{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-1-selected.jpg");
}

/* Step.2専用に指定されるクラス群 */
dt#step2 span{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-2.jpg");
}
dt#step2 span.over{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-2-over.jpg");
}
dt#step2 span.selected{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-2-selected.jpg");
}

/* Step.3専用に指定されるクラス群 */
dt#step3 span{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-3.jpg");
}
dt#step3 span.over{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-3-over.jpg");
}
dt#step3 span.selected{
    background:url("http://editors.ascii.jp/m-kobashigawa/jquery_sample/014/images/background-3-selected.jpg");
}
dd{
    margin:0;
    width:695px;
    height:300px;
    float:left;
    background:#D4D0C8;
    overflow:hidden;
}
dd  p{
    width:655px;
    text-indent:1em;
    padding:20px;
}
    </style>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">google.load("jquery", "1.3.2");</script>
    <script type="text/javascript">
    $(function(){
      //先頭のdd要素以外を非表示にする。
      $("dd:not(:first)").css({"width":"0px"})
      //先頭のdtにselectedクラスを適用する。
      $("dt:first span").addClass("selected");
      //dtのクリックイベントを登録する。
      $("dl dt").click(function(){
        //選択したdtの次のdd要素の幅が0px(つまり非表示)の場合のみ、処理を行う。
        if($("+dd",this).css("width")=="0px"){
	  //selectedクラスが適用されているdt要素の次のdd要素を非表示にアニメーション。
          $("dt:has(.selected) +dd").animate({"width":"0px"})
	  //現在選択中のdtの次のdd要素が幅695pxになるようにアニメーション。(表示する。)
          $("+dd",this).animate({"width":"695px"})
	  //すべての dt span 要素からselectedクラスを削除する。
          $("dt span").removeClass("selected");
	  //現在選択中のdt要素中に存在するspan要素にselectedクラスを適用する。
          $("span",this).addClass("selected");
        }
      }).mouseover(function(){
        //現在選択中のdt要素配下のspan要素の上にマウスカーソルが来た場合、overクラスを適用する。
        $("span",this).addClass("over");
      }).mouseout(function(){
        //現在選択中のdt要素配下のspan要素の上からマウスカーソルが出た場合、overクラスを削除する。
        $("span",this).removeClass("over");
      })
    })
    </script>
  </head>
  <body>
    <div>
      <dl>
        <dt id="step1"><span>Step.1</span></dt>
        <dd><p>Lorem ...(中略)... venenatis.</p></dd>
        <dt id="step2"><span>Step.2</span></dt>
        <dd><p>Integer ...(中略)... accumsan. </p></dd>
        <dt id="step3"><span>Step.3</span></dt>
        <dd><p>Integer ...(中略)... imperdiet. </p></dd>
      </dl>
    </div>
  </body>
</html>

横はめんどくせーなー。やりたかないねぇ。