bootstrap-treeview中勾選父節點全選子節點,以及勾選一個子節點自動勾選父節點


  做了一個樹形菜單,想實現如下兩個操作:1.勾選父節點全選子節點  2.勾選子節點自動勾選父節點。本以為實現起來應該很簡單,但實際做的時候遇到了還是碰到很多問題,現在來記錄一下。

 

  直接上代碼:

let clickFlag = 0; // clickFlag用來記錄節點是被手動點擊而使state變為cheked的,而不是因為級聯選擇導致節點被checked
// 初始化樹形菜單
function initTreeView(model) {
   $('#treeview-checkable').treeview({
      data: getMenus(model),    // 加載的數據源
      showIcon: false,
      showCheckbox: true,       // 展示復選框
      levels: 2,
      onNodeChecked: function(event, node) {    //選中時觸發
         checkNode(node);
      },
      onNodeUnchecked: function (event, node) {  //取消選中時觸發
         unCheckNode(node);
      },
      onNodeClicked: function (event, node) { // click事件早於check事件
         if (node.nodes != undefined && !node.state.checked) {
            if (node.parentId == undefined) { // 頂層節點
               clickFlag = 1;
            } else { // 中間節點
               clickFlag = 2;
            }
         } else {
            clickFlag = 0;
         }
      },
   });
};


// 選擇父菜單節點后,選中所有子菜單;當父菜單下所有子菜單被選中之后,自動勾選上父菜單節點
function checkNode(data) {
   if(data.nodes != undefined && clickFlag != 0) {
      for(var i = 0; i < data.nodes.length; i++) {
         $('#treeview-checkable').treeview("checkNode", [data.nodes[i].nodeId, {slient: true}]);
      }
      if (clickFlag == 2) { // 點擊中間節點,選中了節點下所有子節點后,改變標識,防止污染后續操作
         clickFlag = 0;
      }
   }
   if (data.parentId != undefined) {
      var parentNode = $('#treeview-checkable').treeview('getParent', data.nodeId);
      let checkCount = 0;
      for (x in parentNode.nodes) {
         if (parentNode.nodes[x].state.checked) {
            checkCount++;
         }
      }
      if(checkCount > 0) {
         // 選中當前節點的父節點
         $('#treeview-checkable').treeview("checkNode", [parentNode.nodeId, {slient: true}]);
      }
   }


}
// 取消選擇父菜單節點后,自動取消菜單下全部人員
function unCheckNode(data) {
   if(data.nodes != undefined) {
      var flag = false;
      for(var i = 0; i < data.nodes.length; i++) {
         if (data.nodes[i].state.checked) {
            flag = true;
            break;
         }
      }
      if(flag) {
         for(var i = 0; i < data.nodes.length; i++) {
            $('#treeview-checkable').treeview("uncheckNode", [data.nodes[i].nodeId, {slient: true}]);
         }
      }
   }
   if (data.parentId != undefined) {
      var parentNode = $('#treeview-checkable').treeview('getParent', data.nodeId);
      var checkCount = 0;
      for (x in parentNode.nodes) {
         if (parentNode.nodes[x].state.checked) {
            checkCount++;
         }
      }
      if(checkCount == 0) {
         $('#treeview-checkable').treeview("uncheckNode", [parentNode.nodeId, {slient: true}]);
      }
   }
}
  其中clickFlag很重要,如果沒有這個屬性,會出現以下情況:點擊了子節點后自動勾選了父節點,因為定義了父節點被選中后就全選子節點,所以這時父節點下所有子節點都會被選中。因此,我就想到需要用一個flag來標注節點是被人手動點擊的,而不是因為級聯操作被選中的,這樣才能避免出現上面說的問題。
    節點的選中狀態判斷是通過onNodeChecked和onNodeUnchecked來判斷的,還需要一個點擊事件來記錄節點是否被點擊,bootstrap-treeview默認並沒有提供這個事件,需要我們另外添加,添加方式如下:
;(function ($, window, document, undefined) {
     /*global jQuery, console*/
     'use strict';
     var pluginName = 'treeview';
     var _default = {};
     _default.settings = {
          injectStyle: true,
          levels: 2,
          expandIcon: 'glyphicon glyphicon-plus',
          collapseIcon: 'glyphicon glyphicon-minus',
          emptyIcon: 'glyphicon',
          nodeIcon: '',
          selectedIcon: '',
          checkedIcon: 'glyphicon glyphicon-check',
          uncheckedIcon: 'glyphicon glyphicon-unchecked',
          color: undefined, // '#000000',
          backColor: undefined, // '#FFFFFF',
          borderColor: undefined, // '#dddddd',
          onhoverColor: '#F5F5F5',
          selectedColor: '#FFFFFF',
          selectedBackColor: '#428bca',
          searchResultColor: '#D9534F',
          searchResultBackColor: undefined, //'#FFFFFF',
          enableLinks: false,
          highlightSelected: true,
          highlightSearchResults: true,
          showBorder: true,
          showIcon: true,
          showCheckbox: false,
          showTags: false,
          multiSelect: false,
          // Event handlers          onNodeChecked: undefined,
          onNodeCollapsed: undefined,
          onNodeDisabled: undefined,
          onNodeEnabled: undefined,
          onNodeExpanded: undefined,
          onNodeSelected: undefined,
          onNodeUnchecked: undefined,
          onNodeUnselected: undefined,
          onSearchComplete: undefined,
          onSearchCleared: undefined,
          
          /**
         * 給 bootstrap treeview 添加 點擊事件 定義
         */
          onNodeClicked: undefined
     };
     Tree.prototype.unsubscribeEvents = function () {
          this.$element.off('click');
          this.$element.off('nodeChecked');
          this.$element.off('nodeCollapsed');
          this.$element.off('nodeDisabled');
          this.$element.off('nodeEnabled');
          this.$element.off('nodeExpanded');
          this.$element.off('nodeSelected');
          this.$element.off('nodeUnchecked');
          this.$element.off('nodeUnselected');
          this.$element.off('searchComplete');
          this.$element.off('searchCleared');
          
          /**
         * 給 bootstrap treeview 添加 點擊事件 元素
         */
          this.$element.off('nodeClicked');
     };
    Tree.prototype.subscribeEvents = function () {
          this.unsubscribeEvents();
          this.$element.on('click', $.proxy(this.clickHandler, this));
          if (typeof (this.options.onNodeChecked) === 'function') {
              this.$element.on('nodeChecked', this.options.onNodeChecked);
          }
          if (typeof (this.options.onNodeCollapsed) === 'function') {
              this.$element.on('nodeCollapsed', this.options.onNodeCollapsed);
          }
          if (typeof (this.options.onNodeDisabled) === 'function') {
              this.$element.on('nodeDisabled', this.options.onNodeDisabled);
          }
          if (typeof (this.options.onNodeEnabled) === 'function') {
              this.$element.on('nodeEnabled', this.options.onNodeEnabled);
          }
          if (typeof (this.options.onNodeExpanded) === 'function') {
              this.$element.on('nodeExpanded', this.options.onNodeExpanded);
          }
          if (typeof (this.options.onNodeSelected) === 'function') {
              this.$element.on('nodeSelected', this.options.onNodeSelected);
          }
          if (typeof (this.options.onNodeUnchecked) === 'function') {
              this.$element.on('nodeUnchecked', this.options.onNodeUnchecked);
          }
          if (typeof (this.options.onNodeUnselected) === 'function') {
              this.$element.on('nodeUnselected', this.options.onNodeUnselected);
          }
          if (typeof (this.options.onSearchComplete) === 'function') {
              this.$element.on('searchComplete', this.options.onSearchComplete);
          }
          if (typeof (this.options.onSearchCleared) === 'function') {
              this.$element.on('searchCleared', this.options.onSearchCleared);
          }
          
          /**
           * 給 bootstrap treeview 添加 點擊事件 賦值
           */
          if (typeof (this.options.onNodeClicked) === 'function') {
              this.$element.on('nodeClicked', this.options.onNodeClicked);
          }
     };
     Tree.prototype.clickHandler = function (event) {
          if (!this.options.enableLinks) event.preventDefault();
          var target = $(event.target);
          var node = this.findNode(target);
          if (!node || node.state.disabled) return;
          
          /**
           * @update by sxh: 先執行點擊事件
           */
          this.onClicked(node, _default.options);          

          var classList = target.attr('class') ? target.attr('class').split(' ') : [];
          if ((classList.indexOf('expand-icon') !== -1)) {
              this.toggleExpandedState(node, _default.options);
              this.render();
          }
          else if ((classList.indexOf('check-icon') !== -1)) {
              
              this.toggleCheckedState(node, _default.options);
              this.render();
          }
          else {
              
              if (node.selectable) {
                   this.toggleSelectedState(node, _default.options);
              } else {
                   this.toggleExpandedState(node, _default.options);
              }
              this.render();
          }
          
          /**
           * clickHandler -- 最后執行點擊事件
           */
        // this.onClicked(node, _default.options);
     };
     /**
     * 給 bootstrap treeview 添加 點擊事件
     * 依賴於clickHandler 方法。最后執行
     */
     Tree.prototype.onClicked = function (node, options) {
          if (!node) return;
        if (!options.silent) {
            this.$element.trigger('nodeClicked', $.extend(true, {}, node));
        }
     };

另外一點需要注意的是,添加的click事件一定要先於checked事件執行,否則仍然不生效。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM