LoginSignup
3
6

More than 5 years have passed since last update.

チェックボックスの全チェック・全解除

Posted at

概要

  • jQueryのfilterを活用して、まとめて取得したチェックボックスから、特定のグループだけを抽出する。
  • ボタンの状態に応じて、全チェック・全解除。
  • グループ内のチェックが1つでも外れた場合「全てチェック・解除ボタン」のチェック状態を外す。
  • グループ内のチェックが全てついた場合「全てチェック・解除ボタン」にチェックを付ける。

実行サンプル

CSSなし

CSSあり

コード

オブジェクトリテラル

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属性を持たせて、その名前をチェックボックスのグループ名と同じにした。
3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6