もっと便利に!jQueryでラクラクサイト制作(実践サンプル付き)

第12回jQueryでセレクトボックスをデザインする

デザインされたセレクトボックスを実装する

画像

セレクトボックスはCSSでほとんどスタイルを当てることができないので、フォームをデザインするときに苦労する方が多いのではないでしょうか。今回は、HTMLとCSS、そしてjQueryを利用して疑似セレクトボックスを作成してみましょう。

作成方法はとても簡単なので、覚えておけば色々なシーンで流用できるでしょう。

まずは、完成サンプルを見て作成するセレクトボックスのイメージを掴んでください。

疑似セレクトボックス

そもそもデフォルトのセレクトボックスの挙動は

  1. クリックするとプルダウンが表示
  2. プルダウンの項目をクリックする
  3. セレクトボックスの中身が選択した項目に置き換わる

というようになっているのでこれを実装していきます。

セレクトボックスはselect要素とそれに内包されるoption要素(プルダウン部分)で構成されるので、それらを代替要素で構成し、プルダウンの表示などはjQueryに任せます。

セレクトボックスのHTML

疑似セレクトボックスのHTML
<div class="selectbox">
    <a href="#" class="select"><span>疑似セレクトボックス</span></a>
    <div class="pulldown">
        <a href="#">疑似セレクトボックス</a>
        <a href="#項目1">項目1</a>
        <a href="#項目2">項目2</a>
        <a href="#項目3">項目3</a>
        <a href="#項目4">項目4</a>
        <a href="#項目5">項目5</a>
    </div>
    <input type="hidden" name="selectbox" value="" />
</div>

まず疑似セレクトボックスに必要な要素をまとめるためのdiv.selectboxを用意します。その中に

  1. a要素:セレクトボックス(見えているところ)
  2. div要素:プルダウン
  3. input要素:選択されたデータを保存する

をそれぞれ入れておきます。optionのvalueにあたる部分はhrefの#に続けて入力しておきます。

CSSでデザインを適用する

スクリプトを書く前に、CSSでスタイルを適用しておきましょう。適用していくデザインは以下の通りです。

画像

プルダウンには以下の画像を使用します。

画像
  • 通常時の画像
  • hover時の画像
  • focus時の画像

の3パターンの画像をCSS Spriteを利用して表示を切り替えます。まずはセレクトボックスの部分ですが、その前にdiv.selectboxにposition: relativeを定義しておきます。。

div.selectbox
div.selectbox {
    display: inline-block;
    *display: inline;
    zoom: 1;
    position: relative;
}

セレクトボックス部分

画像
a.selectとその子要素
div.selectbox a.select {
    border: solid #ddd 1px;
    display: inline-block;
    *display: inline;
    zoom: 1;
    width: 170px;
    color: #262626;
    text-decoration: none;
    cursor: default;
}
    
    div.selectbox a.select span {
        padding: 0 22px 0 7px;
        display: block;
        height: 22px;
        background: url(img/icon_select.gif) no-repeat right 0;
        line-height: 22px;
        cursor: default;
    }
    
    div.selectbox a.select:hover span { background-position: right -21px }
    div.selectbox a.select_focus span { background-position: right -42px !important }

セレクトボックスはinline要素ですが、今回は代替で作成するため、inline要素だと高さが指定できずに、デザインをうまく適用することができません。floatを使ってしまうと、文字に挟まれた場合などに対応できなくなります。以上の理由でここでは「inline-block」を使っています。

inline-blockについて多くは記述しませんが

  • だいたいのブラウザは display: inline-block; で使える
  • IE用に display: inline; zoom: 1; を適用
  • Firefox2系はinline-blockの子要素がblockになっていればOK

というような条件を満たしていれば、問題なく使うことができるでしょう。

プルダウン部分

画像

同じようにプルダウン部分にもスタイルを適用します。

div.pulldownとその子要素
div.selectbox div.pulldown {
    border: solid #bbb 1px;
    width: 170px;
    max-height: 150px;
    position: absolute;
    left: 0;
    top: 28px;
    background: #fff;
    overflow: auto;
}

    div.selectbox div.pulldown a {
        border-bottom: solid #bbb 1px;
        padding: 5px 8px;
        display: block;
    }
    div.selectbox div.pulldown a.last-child {
        border: none;
    }
    div.selectbox div.pulldown a:hover,
    div.selectbox div.pulldown a.selected {
        color: #666;
        background: #eee;
        text-decoration: none;
    }

こちらはいたって簡単ですが、最後のa要素にはスクリプトを使ってlast-childを割り振り、borderを表示しないようにします。

スクリプトの記述

セレクトボックスの挙動としては最初に示した通り

  1. クリックするとプルダウンが表示
  2. プルダウンの項目をクリックする
  3. セレクトボックスの中身が選択した項目に置き換わる

です。順番に見ていきましょう。

1. クリックするとプルダウンが表示

1. クリックするとプルダウンが表示
$('div.selectbox').each(function(){
    var self = $(this);
    var select = $('a.select',self);
    var pulldown = $('div.pulldown',self);
    
    pulldown.hide().children(':last-child').addClass('last-child'); // 1
    
    select.click(function(){
        $('div.pulldown').hide();
        pulldown.show(); // 2
        $(this).addClass('select_focus'); // 3
        return false;
    });
});

まず最初にdiv.selectboxがページ内に複数あってもいいように、each関数を使って処理をdiv.selectboxの個数分繰り返させます。

eachで得られるthisを何度も使うので、変数selfに保存しておきます。さらに、a.selectとdiv.pulldownも同じようにselectとpulldownに保存しておきます。その後、表示されているpulldownを非表示にした上で、最後の子要素(div.pulldown a:last-child)にlast-childを割り振っておきます。

clickイベントに、

  1. 表示されているpulldownを非表示
  2. クリックされた疑似セレクトボックスが内包するpulldownを表示
  3. 選択中のクラスを割り当てる

以上で1の動作が完成します。

注意ではないですが、a要素をクリックした際に、href属性に#が入っていると、ページ上部へ移動してしまうので、return false;を入れてブラウザのデフォルトの動作を無効にしておきます。

2-3 プルダウンの項目をクリックするとセレクトボックスの中身が選択した項目に置き換わる

2、3は一連の動作なので同時に扱います。

2-3 プルダウンの項目をクリックするとセレクトボックスの中身が選択した項目に置き換わる
var select_value = $('span',select);

$('a',pulldown).click(function(){
    var value = $(this).attr('href').replace('#',''); // 1
    var text = $(this).text(); // 2
    
    select_value.text(text); // 3
    
    $('a.selected',pulldown).removeClass('selected'); // 4
    $('a.select_focus').removeClass('select_focus'); // 5
    $(this).addClass('selected'); // 6
    pulldown.hide(); // 7
    
    return false;
});

プルダウン内のa要素をクリックした場合に、

  1. optionのvalueにあたる部分とテキストを得る
  2. テキストは疑似セレクトボックスのテキストと入れ替え
  3. 疑似セレクトボックスのテキストをtextに入れ替える
  4. 選択中になっているa.selectedからselectedを外す
  5. 同じくfocusされているa.select_focusからselect_focusを外す
  6. クリックしたa要素にはselectedを付与する
  7. プルダウンを隠す

の順番で適用します。

以上で

  1. クリックするとプルダウンが表示
  2. プルダウンの項目をクリックする
  3. セレクトボックスの中身が選択した項目に置き換わる

の基本動作は設定しましたが、もう少し詰めて見て

  • プルダウンが表示されている状態で、プルダウン以外の箇所をクリックするとプルダウンが閉じる
  • formのactionでデータをPOSTできるようにinput:hiddenにvalueを入れておく

もそれぞれ実装してみましょう。

プルダウン以外の箇所をクリックでプルダウンが閉じる

画像

これを実装するためには、プルダウン以外の箇所をクリックした、というイベントをキャプチャする必要があります。どこでキャプチャすればいいでしょうか?

答えは色々あると思いますが、bodyにbindしてしまうのが手軽な方法です。

bodyをclickするとプルダウンが閉じる

bodyをclickするとプルダウンが閉じる
$('body').click(function(){
    $('a.select_focus').removeClass('select_focus');
    $('div.pulldown').hide();
});

input:hiddenにvalueを入れておく

最後に、input:hiddenのvalueにデータを入れる処理ですが、これは単純にdiv.pulldown aをクリックした際にvalueで得ておいたデータをinput:hiddenのvalueに挿入するだけです。

input:hiddenにvalueを入れておく
$('input:hidden',self).val(value);

以上で疑似プルダウンの実装が完了しました。

まとめ

いかがだったでしょうか。疑似プルダウン自体はCSSだけでも実装できたりしますが、jQueryを使うことの利点としては、show(hide)メソッド部分をslideDown(slideUp)やfadeIn(fadeOut)メソッドに変えるだけで、アニメーションするプルダウンが実装できてしまう点ではないでしょうか。

今回アニメーションはつけずにシンプルなサンプルで紹介しましたが、ぜひアニメーションバージョンなど色々な方法で実装してみてください。

おまけ

今回紹介したサンプルは、JSがON環境でないと動作しないようになっています。JSがOFFときも動作するような構成にしたい場合は、デフォルトのセレクトボックスを今回紹介した構成に置き換えるjQueryプラグインを過去に作っているので、そちらを使ってみてください。

jQselectable: http://code.google.com/p/jqselectable/

また、前回紹介したバリデーションも、より手軽に使いたい場合もjQueryプラグインがありますので、よければ参考にしてみてください。

jQuery.validation.js: http://moto-mono.net/validation

おすすめ記事

記事・ニュース一覧