基于jquery的复选树的插件


基于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;
    }
  }
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM