ラジオボタンでグラフィカルなトグルボタンを作ってみる
この記事は賞味期限切れです。(更新から1年が経過しています)
HTMLでトグルボタンを実装するにはinput[type=radio]が近道ですが、 リッチな雰囲気にする為に見た目を制御したい。今回はそんなお話です。
ラジオボタンでグラフィカルなトグルボタン
「ラジオボタンがすでにグラフィカルでは?」という細かいつっこみは置いといて頂き、 本稿ではより自由度高く外見をカスタマイズする方法を記していきます。
ラジオボタンでなくともトグルボタンはJavaScriptで作れますが、 択一で選択する仕組みをわざわざ自前で実装するよりも、 その為に作られた物をその為に使って実現してみます。
マークアップ
例えばこんなHTMLとCSSを書きます。 血液型を選択する簡単なトグルボタンです。
HTML
<form class="question">
<h1>あなたの血液型は?</h1>
<ul class="bloodtype-list">
<li><label><input type="radio" name="bloodtype" value="A" checked />A</label></li>
<li><label><input type="radio" name="bloodtype" value="B" />B</label></li>
<li><label><input type="radio" name="bloodtype" value="O" />O</label></li>
<li><label><input type="radio" name="bloodtype" value="AB" />AB</label></li>
</ul>
</form>
CSS
/**
* 重要な箇所のみ抜粋
*/
.bloodtype-list label input {
display:none;
}
.bloodtype-list label {
/* 非選択時のスタイル */
}
.bloodtype-list label.selected {
/* 選択時のスタイル */
}
label>input という構造にして、inputをdisplay:none;で隠してしまいます。 選択されたラジオボタンのlabelに「selected」クラスが付加されれば、選択状態を表現できまね。 その部分は、JavaScriptにお任せします。
JavaScript
jQueryを使います。非常に単純な処理です。
var radios = $("input[name=bloodtype]");
radios.on("change", function(e){
// 一旦全てのlabel要素からselectedクラスを除去
radios.closest("label").removeClass("selected");
// 選択されたラジオボタンの親のlabelにselectedクラスを設定
$(e.target).closest("label").addClass("selected");
// 選択変更時に何かしたければここで
console.log("Changed to " + e.target.value);
});
// 選択状態を初期化する
radios.filter(":checked").trigger("change");
これで概ね動くのですが、IE8以下はもう一工夫必要です。
旧IE対策
IE8以下は、非表示にしているラジオボタンのlabel要素をクリックしても 選択状態は変わらず、changeイベントも発火しない様子です。
なので、その挙動を簡単にエミュレートしてあげます。
radios.closest("label").on("click", function(e){
var input = $(this).find("input");
if(! input.prop("checked")){
input.prop("checked", true).trigger("change");
}
});
親のlabel要素をクリックした時に、子のinput要素が選択されていなければ、 checkedにしてchangeイベントに着火します。
jQueryプラグインにまとめてみる
一連の動作をプラグインにまとめてみました。
$.fn.extend({
toggleButtons : function(callback){
var radios = this;
radios.on("change", function(e){
radios.closest("label").removeClass("selected");
$(e.target).closest("label").addClass("selected");
callback.call(this, e);
});
radios.closest("label").on("click", function(e){
var input = $(this).find("input");
if(! input.prop("checked")){
input.prop("checked", true).trigger("change");
}
});
radios.filter(":checked").trigger("change");
}
});
使い方
引数のcallbackは、選択状態が変更された時にコールされます。
$("input[name=bloodtype]").toggleButtons(function(e){
// 選択変更時に何かする
console.log("Changed to " + e.target.value);
});
デモ
JSBinにデモを用意しました。
まとめ
あとはlabelとlabel.selectedの見た目を存分にデザインしてあげましょう。 CSS3で記述するもよし、画像置換するもよし、子にimgを入れて差し替えてもよし。 お好みのコースで心ゆくまでごゆっくりと。
- 2013/06/22
- checkedにあわせて選択するようにコードを調整
コメント
非常に助かります。radios.filter(":checked")とするのですね、勉強不足でした。コメントしてよかったです。</p>
例えば、デフォルトで「O型」を選択状態にするには、どのようにすればよろしいでしょうか?
回答のほど、よろしくお願い致します。</p>
デフォルトで「checked」されていない状態にしたいのですが、
javaの勉強不足のため分かりません…。。申し訳ないです。。
早めにご回答頂けるとありがたいです。
宜しくお願い致します。</p>