bootstrap treeview默认不提供全选 / 全部取消操作, 需要开发者自定义. 自定义效果如下, 点击父节点, 子节点全部选中, 再次点击, 子节点全部取消选中. 在笔者的情况下, 需要实现父节点的单独选中, 所以这里做了子节点全部不选中的情况下, 依然保持父节点单独选中状态.
html代码如下:
<div id="modal-departments-lessonManage" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modal-detail-title" data-backdrop="static" >
<div class="modal-dialog" style="width: 80%;">
<div class="modal-content" style="min-height:500px">
<div class="modal-header">
<button class="close" type="button" data-dismiss="modal">
<span>×</span>
</button>
<h5 id="modal-detail-title" class="modal-title">选择必修部门</h5>
</div>
<div class="modal-body" style="min-height:380px;padding:30px 25px;">
<div class="form-group">
<button class="btn btn-primary" id="expandTree_btn_lessonManage">展开全部</button>
<button class="btn btn-primary" id="collapseTree_btn_lessonManage">折叠全部</button>
<div class="col-sm-6" style="padding-left:0;">
<input id="search-departmentsTree-lessonManage" class="col-sm-5 form-control" type="text" placeholder="输入关键字, 匹配部门会高亮显示"/>
</div>
</div>
<div id="tree-departments-lessonManage"></div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal" id="btn-confirm-departments-lessonManage">确定</button>
<button class="btn btn-default" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
JavaScript代码如下:
var checkableTree_lessonMange = {};
function buildLessonDepartmentTree(treeData, id) {
checkableTree_lessonMange = $('#tree-departments-lessonManage').treeview({
data: treeData,
showIcon: false,
color: "#428bca",
showCheckbox: true,
selectedColor: "#428bca",
selectedBackColor: "#eee",
nodeIcon: "glyphicon glyphicon-user",
onNodeChecked: function(event, node) { // 选中事件
var childrenIds = listChildrenIds(node); // 获取所有子节点ID, 包括当前节点ID
checkableTree_lessonMange.treeview('checkNode', [childrenIds, { silent: true }]); //全部选中
handleParentCheckedStatus(node); // 处理父节点状态
},
onNodeUnchecked: function(event, node) { //取消选中事件
var allChildrenNodeIds = listChildrenIds(node); //获取所有子节点
var uncheckedchildrenIds = getUncheckedChildrenIds(node); //获取未被选中的子节点
if (allChildrenNodeIds && uncheckedchildrenIds.length == 0) { //有子节点且都被选中情况下,取消选中所有子节点. 加判断防止触发父节点uncheck事件导致兄弟节点及兄弟节点的子节点触发uncheck事件
checkableTree_lessonMange.treeview('uncheckNode', [allChildrenNodeIds, { silent: true }]);
}
}
});
$('#expandTree_btn_lessonManage').click(function() { // 展开所有节点
checkableTree_lessonMange.treeview('expandAll');
});
$('#collapseTree_btn_lessonManage').click(function() { //合并所有节点
checkableTree_lessonMange.treeview('collapseAll');
});
$('#search-departmentsTree-lessonManage').on('input', function (e) { // 搜索指定节点, 并高亮显示
checkableTree_lessonMange.treeview('search', [ $(this).val(), { ignoreCase: false, exactMatch: false }]);
});
}
// 处理父节点的选中状态, 在这个方法中能够处理是否当所有子节点被选中时自动选中父节点, 任意一子节点取消选中时取消选中父节点
function handleParentCheckedStatus(node) {
var parentNode = $('#tree-departments-lessonManage').treeview("getNode", node.parentId);
if (parentNode.nodes) {
var checkedCount = 0;
for (childIndex in parentNode.nodes) {
if (!parentNode.nodes[childIndex].state.checked) {
return;
}
checkedCount++;
}
$('#tree-departments-lessonManage').treeview("checkNode", parentNode.nodeId);
setParentNodeCheck(parentNode);
}
}
// 获取指定节点下所有未被选中的子节点ID
function getUncheckedChildrenIds(parentNode) {
var children = parentNode.nodes, uncheckedIds = []; //当前节点子集中未被选中的集合
if (!children) {
return uncheckedIds;
}
for (nodeIndex in children) {
!children[nodeIndex].state.checked ? uncheckedIds.push(children[nodeIndex].nodeId) : '';
if (children[nodeIndex].nodes) {
var recursionNodes = getUncheckedChildrenIds[nodeIndex];
for (recursionIndex in recursionNodes) {
!recursionNodes[recursionIndex].state.checked ? uncheckedIds.push(recursionNodes[recursionIndex]) : '';
}
}
}
return uncheckedIds;
}
// 获取指定节点下的所有子节点ID
function listChildrenIds(parentNode) {
var childrenIds = [], children = parentNode.nodes;
if (!children) {
childrenIds.push(parentNode.nodeId);
return childrenIds;
}
for (nodeIndex in children) {
childrenIds.push(children[nodeIndex].nodeId);
if (children[nodeIndex].nodes) {
var recursionNodes = listChildrenIds(children[nodeIndex]);
for (recursionIndex in recursionNodes) {
childrenIds.push(recursionNodes[recursionIndex]);
}
}
}
return childrenIds;
}