基於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