フォームのラジオボタンは、グループ内で1つの要素しか選択できません。
今回、同じ挙動をラジオボタン以外の要素で実装したのでメモ。
完成したラジオボタン風の動作を確認する(デモ)
動作デモ
今回、ブラウザの背景を切り替えるサンプルを作りました。
好きなパターンと色を指定できます。
実際の動作はこちらでご確認ください!(別ウィンドウが開きます)
ローカルストレージに値を保存しているので、タブを閉じたり、リロードしても選択したパターンが再現されます。また、プロキシで選択内容をリアルタイムで表示しています。
こちらについての解説はこちらを参考してください。
ソースコードを確認(全体)
実装に必要なコードだけ抜き出しました。
HTML
<div class="select_wrap pattern_item">
<p class="ttl">パターンの種類</p>
<div class="item">
<p class="elm" data-background="Hideout">
<img src="./images/hideout.svg" alt="Hideout">
</p>
<p class="elm" data-background="Charlie-Brown">
<img src="./images/charlie-brown.svg" alt="Charlie-Brown">
</p>
<p class="elm" data-background="YYY">
<img src="./images/yyy.svg" alt="YYY">
</p>
<p class="elm" data-background="Piano-Man">
<img src="./images/piano-man.svg" alt="Piano-Man">
</p>
<p class="elm" data-background="Pie-Factory">
<img src="./images/pie-factory.svg" alt="Pie-Factory">
</p>
<p class="elm" data-background="Connections">
<img src="./images/connections.svg" alt="Connections">
</p>
<p class="elm" data-background="no-data">
パターン<br>なし
</p>
</div>
</div>
<div class="select_wrap fill_color_item">
<p class="ttl">パターンの色</p>
<div class="item">
<p class="elm" data-fillcolor="#ff237e"></p>
<p class="elm" data-fillcolor="#508b94"></p>
<p class="elm" data-fillcolor="#595ee6"></p>
<p class="elm" data-fillcolor="#b5ac45"></p>
<p class="elm" data-fillcolor="#ac75c3"></p>
<p class="elm" data-fillcolor="#ffffff"></p>
<p class="elm" data-fillcolor="#9C92AC"></p>
</div>
</div>
<div class="select_wrap bg_color_item">
<p class="ttl">背景色</p>
<div class="item">
<p class="elm" data-bgcolor="#ffcece"></p>
<p class="elm" data-bgcolor="#bfedff"></p>
<p class="elm" data-bgcolor="#f2f9b0"></p>
<p class="elm" data-bgcolor="#cacaca"></p>
<p class="elm" data-bgcolor="#e8d0ff"></p>
<p class="elm" data-bgcolor="#fdeac1"></p>
<p class="elm" data-bgcolor="#fff9e9"></p>
</div>
</div>
css
.item > .elm.check_elm {
border: 3px solid red;
box-shadow: 0 0 8px #3a3a3a;
}
Javascript
//CSS変更
function changeCss(elm) {
const parent = elm.parentNode;
const child_nodes_count = parent.childElementCount;
for(var i=0; i<child_nodes_count; i++) {
const item = parent.children[i];
item.classList.remove("check_elm");
}
elm.classList.add("check_elm");
}
// イベント登録
document.querySelectorAll(".elm").forEach(function(elm) {
elm.addEventListener('click',function() {
changeCss(this);
});
});
HTML構造の確認
選択できる項目をPタグで作成し、各要素にはクラス名elmを設定しています。
そして、グループ化したい親要素にselect_wrapを設定しています。
CSSを確認
今回、選択された要素を赤色で囲ってます。
要素を赤色で囲うCSSのクラス名はcheck_elmです。javascriptで要素がクリックされた時、このクリック専用のクラス名を要素に追加します。
.item > .elm.check_elm {
border: 3px solid red;
box-shadow: 0 0 8px #3a3a3a;
}
Javascriptを確認
CSSを変更する関数を作成する
関数changeCssにCSSを変更する処理をまとめています。
引数elmにはクリックした要素が渡されます。
処理としては、次のような流れになります。
- クリックした要素の親を取得
- 同じグループの子要素の数を取得
- for文で同じグループの子要素全てにアクセス
- クリック専用のクラス名があれば削除
- クリックした要素にクリック専用のクラス名を追加
function changeCss(elm) {
const parent = elm.parentNode;
const child_nodes_count = parent.childElementCount;
for(var i=0; i<child_nodes_count; i++) {
const item = parent.children[i];
item.classList.remove("check_elm");
}
elm.classList.add("check_elm");
}
クリックした要素の親要素を取得する
クリックした要素と同じグループの要素を取得するには、まず共通の親となる要素を取得します。
//親要素を取得
const parent = elm.parentNode;
子要素にあるクリック専用のクラス名を削除する
親要素から同じグループの子要素が取得できます。
子要素には次の構文でアクセスします。
親要素.children[何番目];
子要素の数だけfor文で各要素にアクセスし、クリック専用のクラス名(check_elm)があれば削除します。
const parent = elm.parentNode;
const child_nodes_count = parent.childElementCount;
for(var i=0; i<child_nodes_count; i++) {
const item = parent.children[i];
item.classList.remove("check_elm");
}
クリック専用のクラス名を追加する
同じグループの子要素に対してクラス名を削除したら、クリックした要素にクリック専用のクラス名を追加します。
elm.classList.add("check_elm");
これで同じグループ内では1つの項目しか選択できなくなりました。
クリックイベントを設定する
最後にクリックイベントを設定すれば完了です!
// イベント登録
document.querySelectorAll(".elm").forEach(function(elm) {
elm.addEventListener('click',function() {
changeCss(this);
});
まとめ
フォーム以外でもグループ内で1つだけ選択してもらいたいシーンはあると思います。
ラジオボタンをCSSで調整してソレっぽく見せるのも大変なので、今回はJavascriptで調整しました。