概要
- jQueryのfilterを活用して、まとめて取得したチェックボックスから、特定のグループだけを抽出する。
- ボタンの状態に応じて、全チェック・全解除。
- グループ内のチェックが1つでも外れた場合「全てチェック・解除ボタン」のチェック状態を外す。
- グループ内のチェックが全てついた場合「全てチェック・解除ボタン」にチェックを付ける。
実行サンプル
CSSなし
CSSあり
- http://jsfiddle.net/rxxcs73f/3/ (オブジェクトリテラル)
- http://codepen.io/yama-t/pen/VvxqvP (プロトタイプベース)
コード
オブジェクトリテラル
HTML
<h1>グループ1</h1>
<ul>
<li><label><input type="checkbox" name="group1">チェック1</label></li>
<li><label><input type="checkbox" name="group1">チェック2</label></li>
<li><label><input type="checkbox" name="group1">チェック3</label></li>
<li><label><input type="checkbox" name="group1">チェック4</label></li>
<li><label><input type="checkbox" name="group1">チェック5</label></li>
</ul>
<div><label><input type="checkbox" data-checked-all="group1" class="jscBtnCheckAll">グループ1を全チェック/解除</label></div>
<h1>グループ2</h1>
<ul>
<li><label><input type="checkbox" name="group2">チェック1</label></li>
<li><label><input type="checkbox" name="group2">チェック2</label></li>
<li><label><input type="checkbox" name="group2">チェック3</label></li>
<li><label><input type="checkbox" name="group2">チェック4</label></li>
<li><label><input type="checkbox" name="group2">チェック5</label></li>
</ul>
<div><label><input type="checkbox" data-checked-all="group2" class="jscBtnCheckAll">グループ2を全チェック/解除</label></div>
JS
var SAMPLE = SAMPLE || {}
SAMPLE.CheckAll = {
init: function() {
this.setParameter();
this.bindEvent();
},
setParameter: function(){
this.$checkbox = $('input[type=checkbox]');
this.$btnCheckAll = $('.jscBtnCheckAll');
},
bindEvent: function(){
var _self = this;
this.$btnCheckAll.on('click', function() {
_self.toggleCheckedAll(this);
});
this.$checkbox.on('click', function() {
_self.toggleBtnCheckedAll(this);
});
},
toggleCheckedAll: function(btnCheckAll){
// 同グループのチェックボックスの全チェック・全解除
var $btnCheckAll = $(btnCheckAll),
groupName = $btnCheckAll.attr('data-checked-all'),
$targetCheckbox = this.$checkbox.filter(function() {
return $(this).attr('name') === groupName;
});
if($btnCheckAll.is(':checked')){
$targetCheckbox.prop('checked', true);
} else {
$targetCheckbox.prop('checked', false);
}
},
toggleBtnCheckedAll: function(checkbox){
var $checkbox = $(checkbox),
groupName = $checkbox.attr('name'),
$targetBtnCheckAll = this.$btnCheckAll.filter(function() {
return $(this).attr('data-checked-all') === groupName;
});
// グループ内のチェックが1つでも外れたら、ボタンのチェックも外す
if(!$checkbox.is(':checked')){
$targetBtnCheckAll.prop('checked', false);
return;
}
// グループ内のボタンが全てチェックされたら、ボタンにチェックをつける
var $checkboxGroup = this.$checkbox.filter(function() {
return $(this).attr('name') === groupName;
}),
$checkboxGroupChecked = $checkboxGroup.filter(function() {
return $(this).prop('checked') === true;
});
if($checkboxGroup.length === $checkboxGroupChecked.length){
$targetBtnCheckAll.prop('checked', true);
}
}
}
$(function(){
SAMPLE.CheckAll.init();
})
プロトタイプベース
全てチェックボタン1つと、対応するチェックボックスのグループごとにインスタンスを生成する感じ。
読み込み時にグループ化するので、イベント発生時にやることが減る(チェック状態の確認と、チェックされている数の確認、それに応じた操作だけ)。
JS
var SAMPLE = SAMPLE || {}
SAMPLE.CheckAll = function(btnCheckAll){
this.$btnCheckAll = $(btnCheckAll);
this.init();
};
SAMPLE.CheckAll.prototype = {
init: function() {
this.setParameter();
this.bindEvent();
},
setParameter: function(){
this.groupName = this.$btnCheckAll.attr('data-checked-all');
this.$checkbox = this.getCheckboxGroup();
this.checkboxLength = this.$checkbox.length;
},
getCheckboxGroup: function(){
var groupName = this.groupName,
$result;
/* グループ化のための属性が設定されていない場合の例外処理。*/
if(!groupName){
return $('');
}
$result = $('input[type=checkbox]').filter(function() {
return $(this).attr('name') === groupName;
});
return $result;
},
bindEvent: function(){
var _self = this;
this.$btnCheckAll.on('click', function() {
_self.toggleCheckedAll();
});
this.$checkbox.on('click', function() {
_self.toggleBtnCheckedAll();
});
},
toggleCheckedAll: function(){
// 同グループのチェックボックスの全チェック・全解除
var checked = this.$btnCheckAll.is(':checked');
this.$checkbox.prop('checked', checked);
},
toggleBtnCheckedAll: function(){
// チェック項目が外れた時に全選択ボタンのチェック状態の解除
var checkedLength = this.$checkbox.filter(':checked').length,
checked = false;
// グループ内のボタンが全てチェックされたら、ボタンにチェックをつける
if(checkedLength === this.checkboxLength){
checked = true;
}
this.$btnCheckAll.prop('checked', checked);
}
}
$(function(){
$('.jscBtnCheckAll').each(function() {
new SAMPLE.CheckAll(this);
});
})
補足
同グループのチェックボックスの抽出(全チェック・解除ボタン除く)
var $checkboxGroup = this.$checkbox.filter(function() {
return $(this).attr('name') === groupName;
}),
全チェック・解除ボタンを除いた、同グループのチェックボックス全てを抽出する。
同グループのチェックボックスの中から、さらにchecked状態のものだけを抽出
$checkboxGroupChecked = $checkboxGroup.filter(function() {
return $(this).prop('checked') === true;
});
一度抽出したものからさらにフィルターを掛けて、チェック中のチェックボックスのみ抽出。
抽出した数をそれぞれ比較し、一致した場合にのみ全チェック・解除ボタンにチェックをつける
if($checkboxGroup.length === $checkboxGroupChecked.length){
$targetBtnCheckAll.prop('checked', true);
}
lengthを利用して両方の数を比較して、数が一致した時=グループ全てにチェックが付けられた時なので、そのタイミングで全チェック・解除ボタンにチェックを付ける。
修正
- サーバーの処理と絡める時、全チェック・解除ボタンにチェックボックスと同じname属性があると改竄エラーが出るというFBがあったので、全チェック・解除ボタンにはname属性ではなく、data-checked-all属性を持たせて、その名前をチェックボックスのグループ名と同じにした。