やりたいこと
下記のような表を想定する。
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変数が出てきてなんかうーーん。