LoginSignup
1
4

More than 5 years have passed since last update.

チェックボックスだらけのtableでチェックしやすくしたい

Posted at

やりたいこと

下記のような表を想定する。

Col Col Col Col
Row [x] [x] [x] [x]
Row [x] [x] [x] [x]
Row [x] [x] [x] [x]
Row [x] [x] [x] [x]

入力補助として下記を作りたい:

  • チェックボックスを直接押さなくても同一セルなら押したことにする
  • 上記表の「Row」を押すと、その行全部にチェックが入る。もう一度押すとその行全部からチェックが外れる
  • 上記表の「Col」を押すと、その列全部にチェックが入る。もう一度押すとその列全部からチェックが外れる

制限

  • nodejsが関連するいろいろは使わない。
  • ライブラリ(jQueryとか)もできるだけ避ける。
  • IE8で動くこと。

結果

何となくそれらしく動く。
コールバック祭りになってしまっている気がするけどどうしたらいいのかよく分からない。

書いたもの

forEach風関数

// Array.prototype.forEach風
function forEachArrayLike(arrayLikeObj, func) {
    var len = arrayLikeObj.length;
    var i = 0;
    for (i = 0; i < len; i++) {
        func(arrayLikeObj[i], i, arrayLikeObj);
    }
}

チェックボックスを直接押さなくても同一セルなら押したことにする

function setCellClickEvent() {
    var tds = document.querySelectorAll('td');
    forEachArrayLike(tds, function (tdElem) {
        var checkbox = tdElem.querySelector('input[type=checkbox]');
        if (checkbox === null) {
            return;
        }
        tdElem.addEventListener('click', function (event) {
            // チェックボックスを押したときにこれが発火すると
            // チェックがついてから即外れてしまうので
            if (event.target !== checkbox) {
                checkbox.checked = !checkbox.checked;
            }
        });
    });
}

上記表の「Row」を押すと、その行全部にチェックが入る。もう一度押すとその行全部からチェックが外れる

function setRowClickEvent() {
    var trs = document.querySelectorAll('tr');
    forEachArrayLike(trs, function (trElem) {
        var firstTd = trElem.querySelector('td');
        if (firstTd === null) {
            return;
        }
        var checkboxes = trElem.querySelectorAll('td>input[type=checkbox]');
        var isCheck = false;
        firstTd.addEventListener('click', function () {
            isCheck = !isCheck;
            forEachArrayLike(checkboxes, function (checkboxElem) {
                checkboxElem.checked = isCheck;
            });
        });
    });
}

このisCheckをキャプチャするのはどうなんだろうかと思いつつほかの書き方を思いつけなかった。

上記表の「Col」を押すと、その列全部にチェックが入る。もう一度押すとその列全部からチェックが外れる

function setColumnClickEvent() {
    var trs = document.querySelectorAll('tr');
    var ths = trs[0].querySelectorAll('th');
    forEachArrayLike(ths, function (thElem, thIndex) {
        var reactionCheckboxes = [];
        forEachArrayLike(trs, function (trElem) {
            var tds = trElem.querySelectorAll('td');
            forEachArrayLike(tds, function (tdElem, tdIndex) {
                if (tdIndex !== thIndex) {
                    return;
                }
                var checkbox = tdElem.querySelector('input[type=checkbox]');
                if (checkbox === null) {
                    return;
                }
                reactionCheckboxes.push(checkbox);
            });
        });
        if (reactionCheckboxes.length === 0) {
            return;
        }
        var isCheck = false;
        thElem.addEventListener('click', function () {
            isCheck = !isCheck;
            forEachArrayLike(reactionCheckboxes, function (e) {
                e.checked = isCheck;
            });
        });
    });
}

長いしネストが深いしHTMLが一番上の行thで書いていて残りをtdで書いていることに依存しているし、
何か微妙な感じがする。ここもisCheck変数が出てきてなんかうーーん。

1
4
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
1
4