コンパクトにできたので紹介
内容
- ES6的、選択ラジオボタンのチェック外し
- アロー関数
- class
- static, get
- const
- Array.from()
- ES6でなくても、クロージャ使えばできる
- 関数型に慣れてる人はそちらでもどうぞ
- クロージャがクラス定義と実質的に同等(!?)
- でも、唯一性が担保されない
- シングルトンまですると楽
実際
<!-- name属性でグループ化されているので -->
<input type="radio" id="A" name="group0">
<input type="radio" id="B" name="group0">
<input type="radio" id="C" name="group0">
class OffRadio {
constructor(){
this.onclick = (evt)=>{
const sender = evt.target;
const name = sender.name;
if (this[name] === sender) { // 具体的には、Aがチェック済みならthis.group0 = Aのノード
this[name] = null;
sender.checked = false // クリックイベントが発生したチェックボックスのチェックを外す
} else {
this[name] = sender; // 例えばBをチェックしたらthis.group0 = Bのノード
}
}
}
static get onclick(){ // クラス定数でシングルトン
if (!OffRadio.instance){
OffRadio.instance = new OffRadio()
}
return OffRadio.instance.onclick
}
static attach(groupName=document.querySelector('input[type="radio"]')){
Array.from(document.getElementsByName(groupName)).forEach((e)=>{
e.addEventListener('click', OffRadio.onclick); //イベントを追加
})
}
}
// 使い方
// OffRadioはプログラム中でインスタンス一つだけで良い
// 静的にHTMLに書き下してある要素には
OffRadio.attach()
// 動的に作った要素には
OffRadio.attach('group0')
まれによくある課題
- チェックを外したいけど外れない
function offRadio(evt){
if (this.checked == true) {
this.checked = false);
// クリックして呼び出された時点でcheckedプロパティはtrue
// 従って、クリックしてもチェックされた状態にならない
// チェックされたけどイベントハンドラ中で常に解除してる状態
}
}
チェック済を保持する必要あり
- jQuery的解法
- これだけのためにjQuery?
<script type="text/javascript"> // ラジオボタングループ(name)ごとにプロパティを定義、初期化しておく var checkedRadioValue = { 'hogehoge': '', 'foo': '' }; $('input[type="radio"]').on('click', function() { var name = $(this).attr('name'); var value = $(this).val(); if (checkedRadioValue[name] === value) { checkedRadioValue[name] = ''; $(this).prop('checked', false); } else { checkedRadioValue[name] = value; } }); </script>
クロージャにすればいいんちゃう
function offRadio(){
var checkedRadioValue = {}
return function(evt){
var name = this.name;
if (checkedRadioValue[name] === this.id) {
checkedRadioValue[name] = '';
this.checked = false
} else {
checkedRadioValue[name] = this.id;
}
}
}
// 使い方
const off_radio = offRadio();
Array.prototype.filter.call(document.getElementsByTagName("input"), function(e){
return e.type == "radio"
}).forEach(function(e){
e.addEventListener('click', off_radio)
})
なんかうまくない
- しかし、オブジェクトそのものが{}よな...
- => クラス化すると宣言不要になる
- クロージャだけでは、引数で持ち回わるハメに
- 複数のインスタンス必要なし
- => シングルトン化
ということでクラス化、ところが
- thisが衝突するやんけ
- インスタンスのthis=チェック済状態の保持
- これまでのthis=イベント発生元
- ということはevt.targetやな
- シングルトン化はクラス定数で
- なお、使用する時点まで、newを遅延(getter)
- freezeしてもいいかもしれないね
最終
class OffRadio {
constructor(){
this.onclick = (evt)=>{
const sender = evt.target;
const name = sender.name;
if (this[name] === sender) { // 具体的には、Aがチェック済みならthis.group0 = Aのノード
this[name] = null;
sender.checked = false // クリックイベントが発生したチェックボックスのチェックを外す
} else {
this[name] = sender; // 例えばBをチェックしたらthis.group0 = Bのノード
}
}
}
static get onclick(){ // クラス定数でシングルトン
if (!OffRadio.instance){
OffRadio.instance = new OffRadio()
}
return OffRadio.instance.onclick
}
static attach(groupName=document.querySelector('input[type="radio"]')){
Array.from(document.getElementsByName(groupName)).forEach((e)=>{
e.addEventListener('click', OffRadio.onclick); //イベントを追加
})
}
}
まとめ
- ES6的、選択ラジオボタンのチェック外し
- アロー関数
- class
- static, get
- const
- Array.from()
- ES6でなくても、クロージャ使えばできる
- 関数型に慣れてる人はそちらでもどうぞ
- クロージャがクラス定義と実質的に同等(!?)
- でも、唯一性が担保されない
シングルトンまですると楽
参照情報は本文中に