基于jquery的复选树的插件。
业务需求:复选树,带有多选功能,有子级被选中时父级需要有提示,层级不定,基于jquery。
/*
* name: checkboxTree 复选树结构
*/
/**输入的数据结构:
data
[
{
name: 'label1',
value: 'some info'
children: [
{
name: 'label11'
}
]
},
{
name: 'label1',
value: 'some info'
children: [
{
name: 'label11'
}
]
}
]
initSelectOptions
[]
暴露的方法:
addSelect: 增加选中
getSelect: 获取选中的项
*/
(function($) {
jQuery.fn.checkboxTree = function (settings_) {
settings = $.extend({
data:[],
initSelectOptions: null // 默认选中项,只要底层。
}, settings_)
var container = $(this)
// 子元素html
function getChildrenHtml(treesdata){
var result = '',
len = treesdata.length,
node, // 节点
clen // 子元素的数量
for(var i = 0; i < len; i++){
node = treesdata[i]
// 判断子元素数量
clen = (node.children && node.children.length > 0) ? node.children.length : 0
result += "<li"
if (!clen) result += " class='nochildren'"
result += " data-rel='" + node.value + "'>"
if (clen) result += "<i class='fa fa-plus-square'></i>"
result += "<input type='checkbox' id='" + node.name + "'><div class='checkbox'><label for='" + node.name + "'></label></div><label for='" + node.name + "'>" + node.name + "</label>"
// 加载子元素
if (clen) result += "<ul class='hide'>" + getChildrenHtml(node.children) + "</ul>"
result += "</li>"
}
return result
}
// 渲染树
(function initCheckTree() {
var treesHtml = "<ul class='checktree'><li><i class='fa fa-minus-square'></i><input type='checkbox' id='all'><div class='checkbox'><label for='all'></label></div><label for='all'>全部</label><ul>"
treesHtml += getChildrenHtml(settings.data)
container.empty().append(treesHtml + '</ul></li></ul>')
})();
// checkbox的click事件
container.on('click', 'input', function () {
var $this = $(this),
$li = $this.parent(),
$parentCheckbox, // 父级的复选框
checked = $this.prop("checked")
// 向下传递
// 1.获取所有后辈checkbox。 2.选中状态改成和祖辈一样 3.取消所有后辈的半选状态
var childCheckbox = $li.find("input[type='checkbox']")
if (childCheckbox.length > 1) {
$li.find(".checkbox").removeClass("half-select")
childCheckbox.each(function () {
if($(this).prop("checked") !== checked) {
$(this).prop("checked", checked)
}
})
}
// 判断修改父级checkbox状态
(function calculateParentStatus (li_) {
var elementLi = $(li_)
if (elementLi.parent().hasClass("checktree")) return
// 1.获取兄弟li的数量。 2.遍历查看是否全被选中。 4.未全部选中,判断所有父级是否选中,选中就改为未选中。
// selectOne判断半选状态.表明是否有一个元素被选中
var $sibCheckbox = elementLi.parent().find("li").children("input[type='checkbox']")
var selectAll = true
var selectOne = false
for (var i = 0; i < $sibCheckbox.length; i++) {
if (!$sibCheckbox[i].checked) {
selectAll = false
if (selectOne === true) break
} else {
selectOne = true
if (selectAll === false) break
}
}
// 全部选中。触发父级选中事件(父级checkboxclick事件)
if (selectAll) {
// 上层
elementLi.parent().parent().children(".checkbox").removeClass("half-select")
$parentCheckbox = elementLi.parent().parent().children("input[type='checkbox']")
$parentCheckbox.trigger("click")
}
if (selectAll === false) {
$parentCheckbox = elementLi.parents("li").children("input[type='checkbox']")
if ($parentCheckbox.prop("checked")) {
$parentCheckbox.prop("checked", false)
}
if (selectOne) {
// 祖先元素全部半选
elementLi.parents("li").children(".checkbox").addClass("half-select")
} else {
// 取消父辈半选状态
elementLi.parent().parent().children(".checkbox").removeClass("half-select")
// 向上再检查
calculateParentStatus(elementLi.parent().parent())
}
}
})($li)
})
// 开合操作
container.off('click', '.fa').on('click', '.fa', function () {
var $i = $(this)
var $li = $(this).parent()
var $ul = $li.find(">ul")
if ($i.hasClass("fa-plus-square")) {
$i.removeClass("fa-plus-square").addClass("fa-minus-square")
$ul.removeClass("hide")
} else if ($i.hasClass("fa-minus-square")) {
$i.removeClass("fa-minus-square").addClass("fa-plus-square")
$ul.addClass("hide")
}
});
// 通过传入li的value集合,选中相应checkbox
function addSelect (options_) {
if (options_ && options_.length) {
for (var i = 0; i < options_.length; i++) {
container.find("li[data-rel='" + options_[i] + "']").children("input").trigger("click")
}
}
}
// 获取已经被选中的子项
function getSelect () {
var selectedLi = container.find("li.nochildren").find("input[type=checkbox]:checked").parent()
var selectedValue = []
selectedLi.each(function (i, e) {
selectedValue.push(e.getAttribute("data-rel"))
})
return selectedValue
}
// initSelect
if (settings.initSelectOptions) addSelect(settings.initSelectOptions)
return {
addSelect: addSelect,
getSelect: getSelect
}
}
})(jQuery)
css
// 自定义复选框树组件
.checkboxTree {
max-height: 400px;
overflow: auto;
.checktree {
width: 400px;
padding-left: 100px;
li {
list-style-type: none;
input[type="checkbox"] {
position: relative;
top: 7px;
visibility: hidden;
&:checked + .checkbox label:after {
opacity: 1;
}
}
label {
position: relative;
left: -10px;
cursor: pointer;
}
.checkbox {
width: 13px;
height: 13px;
display: inline-block;
position: relative;
margin: 3px 3px 3px 4px;
top: 7px;
left: -16px;
&.half-select {
label {
background-color: #BBE5DF;
}
}
label {
cursor: pointer;
position: absolute;
width: 13px;
height: 13px;
top: 0;
left: 0;
background: #eee;
border: 1px solid #ddd;
&:after {
opacity: 0;
content: '';
position: absolute;
width: 8px;
height: 4px;
top: 2px;
left: 1px;
background: 0 0;
border: 1px solid #000000;
border-top: none;
border-right: none;
transform: rotate(-47deg);
-webkit-transform: rotate(-47deg);
-moz-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
}
}
}
i {
color: #BBE5DF;
cursor: pointer;
}
}
.hide {
display: none;
}
}
}