我不确定该如何解释。希望我的代码是不言而喻的。我对javascript很陌生。
<div>
<input type="checkbox" id="checkBox1" onclick="toggleCheckBox(this)">Check Box 1</input>
<div>
<input type="checkbox" id="checkBox2">Check Box 2</input>
</div>
</div>
function toggleCheckBox(checkBox1) {
// I've also tried 'checkBox1.parent' and 'checkBox1.parentElement'
var cb2 = checkBox1.parentNode.getElementByTagName('div').getElementByTagName('input');
if (checkBox1.checked == true) {
cb2.checked = true;
} else {
cb2.checked = false;
};
};
我不断得到checkBox1.parent
的信息。
编辑:
最终的期望结果是:
<div id="a">
<input type="checkbox" onclick="toggleCheckBox(this)">Check Box 1</input>
<div>
<input type="checkbox">Check Box 2</input>
<input type="checkbox">Check Box 3</input>
</div>
</div>
<div id="b">
<input type="checkbox" onclick="toggleCheckBox(this)">Check Box 1</input>
<div>
<input type="checkbox">Check Box 2</input>
<input type="checkbox">Check Box 3</input>
</div>
</div>
以此类推。
编辑:父级不确定
我让父母去indeterminate
,但是除非您单击它,否则它不会离开。
/* clicked child checkbox */
var parentId = clickedBox.dataset.parent;
var checkedTrue = false;
var checkedFalse = false;
var checkState = clickedBox.checked;
Array.prototype.slice.call(allCheckboxes).forEach(function(checkbox) {
/* search checkboxes having same data-parent as clickedBox and is not checked */
if (parentId === checkbox.dataset.parent && !checkbox.checked) {
checkedFalse = true;
checkState = false;
return false;
} else if (parentId === checkbox.dataset.parent && checkbox.checked) {
checkedTrue = true;
return false;
}
});
/* search parent checkbox of clickedBox */
Array.prototype.slice.call(allCheckboxes).forEach(function(parentBox) {
if (parentBox.id === parentId) {
if (checkedTrue === true && checkedFalse === true) {
parentBox.indeterminate = true;
return false;
} else {
parentBox.checked = checkState;
return false;
}
}
});
答案 0 :(得分:1)
这就是我要做的。需要注意的一点是,该解决方案不支持IE11或更低版本,因为它使用closest()
通过选择器查找父节点。
https://caniuse.com/#search=closest
(您可能必须单击GIF才能播放它。)
<div data-checkbox-group>
<label><input type="checkbox" data-master-checkbox /> Master</label>
<div>
<label><input type="checkbox" /> Check Box 1</label><br>
<label><input type="checkbox" /> Check Box 2</label><br>
<label><input type="checkbox" /> Check Box 3</label><br>
<label><input type="checkbox" /> Check Box 4</label><br>
<label><input type="checkbox" /> Check Box 5</label><br>
</div>
</div>
<hr>
<div data-checkbox-group>
<label><input type="checkbox" data-master-checkbox /> Master</label>
<div>
<label><input type="checkbox" /> Check Box 1</label><br>
<label><input type="checkbox" /> Check Box 2</label><br>
<label><input type="checkbox" /> Check Box 3</label><br>
<label><input type="checkbox" /> Check Box 4</label><br>
<label><input type="checkbox" /> Check Box 5</label><br>
</div>
</div>
<hr>
<div data-checkbox-group>
<label><input type="checkbox" data-master-checkbox /> Master</label>
<div>
<label><input type="checkbox" /> Check Box 1</label><br>
<label><input type="checkbox" /> Check Box 2</label><br>
<label><input type="checkbox" /> Check Box 3</label><br>
<label><input type="checkbox" /> Check Box 4</label><br>
<label><input type="checkbox" /> Check Box 5</label><br>
</div>
</div>
<hr>
<script>
var toggleChecks = function() {
var isMaster = this.hasAttribute('data-master-checkbox')
var group = this.closest('[data-checkbox-group]')
var boxes = group.querySelectorAll('input[type=checkbox]:not([data-master-checkbox])')
var master = isMaster ? this : group.querySelector('input[type=checkbox][data-master-checkbox]')
if (isMaster) {
// Set all children to the value of the parent
for(var i = 0; i < boxes.length; i++) {
boxes[i].checked = this.checked
}
} else {
// Toggle all children to the state of the master
var checkedCount = 0
for(var i = 0; i < boxes.length; i++) {
if(boxes[i].checked) { checkedCount += 1 }
}
master.checked = checkedCount == boxes.length
master.indeterminate = !master.checked && !checkedCount == 0
}
}
var nodes = document.querySelectorAll('[data-checkbox-group] input[type=checkbox]')
for(var i = 0; i < nodes.length; i++) {
nodes[i].addEventListener('change', toggleChecks)
}
</script>
答案 1 :(得分:1)
在不限制使用HTML5 data-*
的情况下,此解决方案适用于大多数更新的浏览器,包括IE11。在这里,我正在使用data-parent
属性(其值与{{1相同) }}(父级)链接到其父级复选框。 id
的值-1
表示给定的复选框没有父级。
data-parent
let allCheckboxes;
/* checkbox click handler */
let toggleCheck = function(e) {
e.stopPropagation();
var clicked = this;
/* clicked ones is the parent */
if ('-1' === clicked.dataset.parent) {
/* search child checkboxes having data-parent=id of clicked ones */
Array.prototype.slice.call(allCheckboxes).forEach(function(c) {
if (c.dataset.parent === clicked.id) {
/* set checked state same as clicked ones */
c.checked = clicked.checked;
}
});
} else {
/* clicked ones is child checkbox */
var parentId = clicked.dataset.parent;
var checkState = clicked.checked;
Array.prototype.slice.call(allCheckboxes).forEach(function(c) {
/* search checkboxes having data-parent same as clicked ones and is not checked */
if (parentId === c.dataset.parent && !c.checked) {
checkState = false;
return false;
}
});
/* search parent checkbox of clicked ones */
Array.prototype.slice.call(allCheckboxes).forEach(function(c) {
if (c.id === parentId) {
c.checked = checkState;
return false;
}
});
}
};
/* wait till DOM renderes and available to bind event listneres */
document.addEventListener('DOMContentLoaded', function() {
/* fetch all checkboxes having attributes data-parent and id */
allCheckboxes = document.querySelectorAll('input[type=checkbox][data-parent][id]');
/* iterate over all checkboxed to bind click listeners */
Array.prototype.slice.call(allCheckboxes).forEach(function(c) {
c.addEventListener('click', toggleCheck);
});
});
div {
margin-left: 1.5rem;
}
P.S。 <div>
<label><input type="checkbox" data-parent="-1" id="c1"/>Check Box 1</label>
<div>
<label><input type="checkbox" data-parent="c1" id="c2">Check Box 2</label>
<label><input type="checkbox" data-parent="c1" id="c3">Check Box 3</label>
</div>
</div>
<div>
<label><input type="checkbox" data-parent="-1" id="c4">Check Box 1</label>
<div>
<label><input type="checkbox" data-parent="c4" id="c5">Check Box 2</label>
<label><input type="checkbox" data-parent="c4" id="c6">Check Box 3</label>
</div>
</div>
是无效标记。
已编辑:关于</input>
,因为到目前为止,我还没有为父复选框提供任何checkState
状态,所以我所做的是将{{1 }}子复选框(如果已选中),则从具有相同父ID的其他其余子复选框的列表中进行搜索。当再遇到未选中的子复选框时,我只需将父复选框标记为intermediate
。
使用中级:嗯,不是那么花哨,但是可以解决问题。
clicked
unchecked
let allCheckboxes;
let repeat = Array.prototype.slice;
let applyState = function(checkbox, state) {
let classes = checkbox.parentNode.classList;
if (!state || !checkbox.checked) {
classes.remove("checked");
classes.remove("intermediate");
checkbox.dataset.state = 0;
}
if (1 === state || checkbox.checked) {
classes.add("checked");
checkbox.dataset.state = 1;
}
if (2 === state) {
classes.remove("checked");
classes.add("intermediate");
checkbox.dataset.state = 2;
}
}
/* checkbox click handler */
let toggleCheck = function(e) {
e.stopPropagation();
var clicked = this;
applyState(clicked);
/* clicked ones is the parent */
if ('-1' === clicked.dataset.parent) {
/* search child checkboxes having data-parent=id of clicked ones */
repeat.call(allCheckboxes).forEach(function(c) {
if (c.dataset.parent === clicked.id) {
/* set checked state same as clicked ones */
c.checked = clicked.checked;
applyState(c);
}
});
} else {
/* clicked ones is child checkbox */
var parentId = clicked.dataset.parent;
var check = 0,
uncheck = 0;
repeat.call(allCheckboxes).forEach(function(c) {
/* search checkboxes having data-parent same as clicked ones */
if (parentId === c.dataset.parent) {
if (c.checked) {
check++;
} else {
uncheck++;
}
}
});
/* search parent checkbox of clicked ones */
repeat.call(allCheckboxes).forEach(function(c) {
if (c.id === parentId) {
var state = 1;
if (0 === check) {
state = 0;
c.checked = false;
} else if (0 < uncheck) {
state = 2;
}
applyState(c, state);
return false;
}
});
}
};
/* wait till DOM renderes and available to bind event listneres */
document.addEventListener('DOMContentLoaded', function() {
/* fetch all checkboxes having attributes data-parent and id */
allCheckboxes = document.querySelectorAll('input[type=checkbox][data-parent][id]');
/* iterate over all checkboxed to bind click listeners */
repeat.call(allCheckboxes).forEach(function(c) {
c.addEventListener('click', toggleCheck);
});
});