From e34b1bbaae0212e69b5e85dae6ba2e61f9876f1a Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 01:47:37 +0100 Subject: [PATCH 01/36] Tidy up of API method option handling Replaced isSilent with default options, merging user and default options to ensure silent is always set. This means we can stop passing silent around in favour of the options hash, ready to be extended in the future. --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 105 ++++++++++++++++++-------------- src/js/bootstrap-treeview.js | 105 ++++++++++++++++++-------------- tests/lib/bootstrap-treeview.js | 105 ++++++++++++++++++-------------- 4 files changed, 175 insertions(+), 142 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index eb0293de6..599876600 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'',item:'
  • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(a,b){var c=this.isSilent(b);this.setSelectedState(this.identifyNode(a),!0,c),this.render()},g.prototype.unselectNode=function(a,b){var c=this.isSilent(b);this.setSelectedState(this.identifyNode(a),!1,c),this.render()},g.prototype.toggleNodeSelected=function(a,b){this.toggleSelectedState(this.identifyNode(a),this.isSilent(b))},g.prototype.collapseAll=function(b){var c=this.isSilent(b);a.each(this.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,c)},this)),this.render()},g.prototype.collapseNode=function(a,b){var c=this.isSilent(b);this.setExpandedState(this.identifyNode(a),!1,c),this.render()},g.prototype.expandAll=function(b){var c=this.isSilent(b);b&&b.levels?this.expandLevels(this.tree,b.levels,c):a.each(this.nodes,a.proxy(function(a,b){this.setExpandedState(b,!0,c)},this)),this.render()},g.prototype.expandNode=function(a,b){var c=this.isSilent(b),d=this.identifyNode(a);this.setExpandedState(d,!0,c),d.nodes&&b&&b.levels&&this.expandLevels(d.nodes,b.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(a,b){this.toggleExpandedState(this.identifyNode(a),this.isSilent(b))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.isSilent=function(a){return a&&a.hasOwnProperty("silent")?a.silent:!1},g.prototype.search=function(b,c){this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
      ',item:'
    • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index bdda5bc03..1b70f551d 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -25,7 +25,9 @@ var pluginName = 'treeview'; - var defaults = { + var _default = {}; + + _default.settings = { injectStyle: true, @@ -61,6 +63,16 @@ onSearchCleared: undefined }; + _default.options = { + silent: false, + ignoreChildren: false + }; + + _default.searchOptions = { + ignoreCase: true, + exactMatch: false + }; + var Tree = function (element, options) { this.$element = $(element); @@ -113,7 +125,7 @@ this.tree = $.extend(true, [], options.data); delete options.data; } - this.options = $.extend({}, defaults, options); + this.options = $.extend({}, _default.settings, options); this.destroy(); this.subscribeEvents(); @@ -265,13 +277,13 @@ if ((classList.indexOf('click-expand') != -1) || (classList.indexOf('click-collapse') != -1)) { - this.toggleExpandedState(node); + this.toggleExpandedState(node, _default.options); } else if (node) { if (node.selectable) { - this.toggleSelectedState(node); + this.toggleSelectedState(node, _default.options); } else { - this.toggleExpandedState(node); + this.toggleExpandedState(node, _default.options); } } }; @@ -289,19 +301,20 @@ return node; }; - Tree.prototype.toggleExpandedState = function (node, silent) { + Tree.prototype.toggleExpandedState = function (node, options) { if (!node) return; - this.setExpandedState(node, !node.state.expanded, silent); + this.setExpandedState(node, !node.state.expanded, options); this.render(); }; - Tree.prototype.setExpandedState = function (node, state, silent) { + Tree.prototype.setExpandedState = function (node, state, options) { if (state) { // Expand a node node.state.expanded = true; - if (!silent) { + + if (!options.silent) { this.$element.trigger('nodeExpanded', $.extend(true, {}, node)); } } @@ -309,32 +322,33 @@ // Collapse a node node.state.expanded = false; - if (!silent) { + + if (!options.silent) { this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); } } }; - Tree.prototype.toggleSelectedState = function (node, silent) { + Tree.prototype.toggleSelectedState = function (node, options) { if (!node) { return; } - this.setSelectedState(node, !node.state.selected, silent); + this.setSelectedState(node, !node.state.selected, options); this.render(); }; - Tree.prototype.setSelectedState = function (node, state, silent) { + Tree.prototype.setSelectedState = function (node, state, options) { if (state) { // If multiSelect false, unselect previously selected if (!this.options.multiSelect) { $.each(this.findNodes('true', 'g', 'state.selected'), $.proxy(function (index, node) { - this.setSelectedState(node, false, silent); + this.setSelectedState(node, false, options); }, this)); } // Continue selecting node node.state.selected = true; - if (!silent) { + if (!options.silent) { this.$element.trigger('nodeSelected', $.extend(true, {}, node) ); } } @@ -342,7 +356,7 @@ // Unselect node node.state.selected = false; - if (!silent) { + if (!options.silent) { this.$element.trigger('nodeUnselected', $.extend(true, {}, node) ); } } @@ -573,8 +587,8 @@ @param {optional Object} options */ Tree.prototype.selectNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setSelectedState(this.identifyNode(identifier), true, silent); + options = $.extend({}, _default.options, options); + this.setSelectedState(this.identifyNode(identifier), true, options); this.render(); }; @@ -584,8 +598,8 @@ @param {optional Object} options */ Tree.prototype.unselectNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setSelectedState(this.identifyNode(identifier), false, silent); + options = $.extend({}, _default.options, options); + this.setSelectedState(this.identifyNode(identifier), false, options); this.render(); }; @@ -595,8 +609,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeSelected = function (identifier, options) { - this.toggleSelectedState(this.identifyNode(identifier), - this.isSilent(options)); + options = $.extend({}, _default.options, options); + this.toggleSelectedState(this.identifyNode(identifier), options); }; @@ -605,10 +619,10 @@ @param {optional Object} options */ Tree.prototype.collapseAll = function (options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); $.each(this.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, false, silent); + this.setExpandedState(node, false, options); }, this)); this.render(); @@ -620,8 +634,8 @@ @param {optional Object} options */ Tree.prototype.collapseNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setExpandedState(this.identifyNode(identifier), false, silent); + options = $.extend({}, _default.options, options); + this.setExpandedState(this.identifyNode(identifier), false, options); this.render(); }; @@ -630,14 +644,14 @@ @param {optional Object} options */ Tree.prototype.expandAll = function (options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); if (options && options.levels) { - this.expandLevels(this.tree, options.levels, silent); + this.expandLevels(this.tree, options.levels, options); } else { $.each(this.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, true, silent); + this.setExpandedState(node, true, options); }, this)); } @@ -650,23 +664,25 @@ @param {optional Object} options */ Tree.prototype.expandNode = function (identifier, options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); var node = this.identifyNode(identifier); - this.setExpandedState(node, true, silent); + this.setExpandedState(node, true, options); if (node.nodes && (options && options.levels)) { - this.expandLevels(node.nodes, options.levels-1, silent); + this.expandLevels(node.nodes, options.levels-1, options); } this.render(); }; - Tree.prototype.expandLevels = function (nodes, level, silent) { + Tree.prototype.expandLevels = function (nodes, level, options) { + options = $.extend({}, _default.options, options); + $.each(nodes, $.proxy(function (index, node) { - this.setExpandedState(node, (level > 0) ? true : false) + this.setExpandedState(node, (level > 0) ? true : false, options); if (node.nodes) { - this.expandLevels(node.nodes, level-1, silent); + this.expandLevels(node.nodes, level-1, options); } }, this)); }; @@ -677,8 +693,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeExpanded = function (identifier, options) { - this.toggleExpandedState(this.identifyNode(identifier), - this.isSilent(options)); + options = $.extend({}, _default.options, options); + this.toggleExpandedState(this.identifyNode(identifier), options); }; Tree.prototype.identifyNode = function (identifier) { @@ -687,12 +703,6 @@ identifier; }; - Tree.prototype.isSilent = function (options) { - return (options && options.hasOwnProperty('silent')) ? - options.silent : - false; - }; - /** Searches the tree for nodes (text) that match given criteria @@ -701,6 +711,7 @@ @return {Array} nodes - Matching nodes */ Tree.prototype.search = function (pattern, options) { + options = $.extend({}, _default.searchOptions, options); this.clearSearch(); @@ -789,10 +800,10 @@ }; var logError = function (message) { - if(window.console) { - window.console.error(message); - } - }; + if(window.console) { + window.console.error(message); + } + }; // Prevent against multiple instantiations, // handle updates and method calls diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index bdda5bc03..1b70f551d 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -25,7 +25,9 @@ var pluginName = 'treeview'; - var defaults = { + var _default = {}; + + _default.settings = { injectStyle: true, @@ -61,6 +63,16 @@ onSearchCleared: undefined }; + _default.options = { + silent: false, + ignoreChildren: false + }; + + _default.searchOptions = { + ignoreCase: true, + exactMatch: false + }; + var Tree = function (element, options) { this.$element = $(element); @@ -113,7 +125,7 @@ this.tree = $.extend(true, [], options.data); delete options.data; } - this.options = $.extend({}, defaults, options); + this.options = $.extend({}, _default.settings, options); this.destroy(); this.subscribeEvents(); @@ -265,13 +277,13 @@ if ((classList.indexOf('click-expand') != -1) || (classList.indexOf('click-collapse') != -1)) { - this.toggleExpandedState(node); + this.toggleExpandedState(node, _default.options); } else if (node) { if (node.selectable) { - this.toggleSelectedState(node); + this.toggleSelectedState(node, _default.options); } else { - this.toggleExpandedState(node); + this.toggleExpandedState(node, _default.options); } } }; @@ -289,19 +301,20 @@ return node; }; - Tree.prototype.toggleExpandedState = function (node, silent) { + Tree.prototype.toggleExpandedState = function (node, options) { if (!node) return; - this.setExpandedState(node, !node.state.expanded, silent); + this.setExpandedState(node, !node.state.expanded, options); this.render(); }; - Tree.prototype.setExpandedState = function (node, state, silent) { + Tree.prototype.setExpandedState = function (node, state, options) { if (state) { // Expand a node node.state.expanded = true; - if (!silent) { + + if (!options.silent) { this.$element.trigger('nodeExpanded', $.extend(true, {}, node)); } } @@ -309,32 +322,33 @@ // Collapse a node node.state.expanded = false; - if (!silent) { + + if (!options.silent) { this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); } } }; - Tree.prototype.toggleSelectedState = function (node, silent) { + Tree.prototype.toggleSelectedState = function (node, options) { if (!node) { return; } - this.setSelectedState(node, !node.state.selected, silent); + this.setSelectedState(node, !node.state.selected, options); this.render(); }; - Tree.prototype.setSelectedState = function (node, state, silent) { + Tree.prototype.setSelectedState = function (node, state, options) { if (state) { // If multiSelect false, unselect previously selected if (!this.options.multiSelect) { $.each(this.findNodes('true', 'g', 'state.selected'), $.proxy(function (index, node) { - this.setSelectedState(node, false, silent); + this.setSelectedState(node, false, options); }, this)); } // Continue selecting node node.state.selected = true; - if (!silent) { + if (!options.silent) { this.$element.trigger('nodeSelected', $.extend(true, {}, node) ); } } @@ -342,7 +356,7 @@ // Unselect node node.state.selected = false; - if (!silent) { + if (!options.silent) { this.$element.trigger('nodeUnselected', $.extend(true, {}, node) ); } } @@ -573,8 +587,8 @@ @param {optional Object} options */ Tree.prototype.selectNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setSelectedState(this.identifyNode(identifier), true, silent); + options = $.extend({}, _default.options, options); + this.setSelectedState(this.identifyNode(identifier), true, options); this.render(); }; @@ -584,8 +598,8 @@ @param {optional Object} options */ Tree.prototype.unselectNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setSelectedState(this.identifyNode(identifier), false, silent); + options = $.extend({}, _default.options, options); + this.setSelectedState(this.identifyNode(identifier), false, options); this.render(); }; @@ -595,8 +609,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeSelected = function (identifier, options) { - this.toggleSelectedState(this.identifyNode(identifier), - this.isSilent(options)); + options = $.extend({}, _default.options, options); + this.toggleSelectedState(this.identifyNode(identifier), options); }; @@ -605,10 +619,10 @@ @param {optional Object} options */ Tree.prototype.collapseAll = function (options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); $.each(this.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, false, silent); + this.setExpandedState(node, false, options); }, this)); this.render(); @@ -620,8 +634,8 @@ @param {optional Object} options */ Tree.prototype.collapseNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setExpandedState(this.identifyNode(identifier), false, silent); + options = $.extend({}, _default.options, options); + this.setExpandedState(this.identifyNode(identifier), false, options); this.render(); }; @@ -630,14 +644,14 @@ @param {optional Object} options */ Tree.prototype.expandAll = function (options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); if (options && options.levels) { - this.expandLevels(this.tree, options.levels, silent); + this.expandLevels(this.tree, options.levels, options); } else { $.each(this.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, true, silent); + this.setExpandedState(node, true, options); }, this)); } @@ -650,23 +664,25 @@ @param {optional Object} options */ Tree.prototype.expandNode = function (identifier, options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); var node = this.identifyNode(identifier); - this.setExpandedState(node, true, silent); + this.setExpandedState(node, true, options); if (node.nodes && (options && options.levels)) { - this.expandLevels(node.nodes, options.levels-1, silent); + this.expandLevels(node.nodes, options.levels-1, options); } this.render(); }; - Tree.prototype.expandLevels = function (nodes, level, silent) { + Tree.prototype.expandLevels = function (nodes, level, options) { + options = $.extend({}, _default.options, options); + $.each(nodes, $.proxy(function (index, node) { - this.setExpandedState(node, (level > 0) ? true : false) + this.setExpandedState(node, (level > 0) ? true : false, options); if (node.nodes) { - this.expandLevels(node.nodes, level-1, silent); + this.expandLevels(node.nodes, level-1, options); } }, this)); }; @@ -677,8 +693,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeExpanded = function (identifier, options) { - this.toggleExpandedState(this.identifyNode(identifier), - this.isSilent(options)); + options = $.extend({}, _default.options, options); + this.toggleExpandedState(this.identifyNode(identifier), options); }; Tree.prototype.identifyNode = function (identifier) { @@ -687,12 +703,6 @@ identifier; }; - Tree.prototype.isSilent = function (options) { - return (options && options.hasOwnProperty('silent')) ? - options.silent : - false; - }; - /** Searches the tree for nodes (text) that match given criteria @@ -701,6 +711,7 @@ @return {Array} nodes - Matching nodes */ Tree.prototype.search = function (pattern, options) { + options = $.extend({}, _default.searchOptions, options); this.clearSearch(); @@ -789,10 +800,10 @@ }; var logError = function (message) { - if(window.console) { - window.console.error(message); - } - }; + if(window.console) { + window.console.error(message); + } + }; // Prevent against multiple instantiations, // handle updates and method calls diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index bdda5bc03..1b70f551d 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -25,7 +25,9 @@ var pluginName = 'treeview'; - var defaults = { + var _default = {}; + + _default.settings = { injectStyle: true, @@ -61,6 +63,16 @@ onSearchCleared: undefined }; + _default.options = { + silent: false, + ignoreChildren: false + }; + + _default.searchOptions = { + ignoreCase: true, + exactMatch: false + }; + var Tree = function (element, options) { this.$element = $(element); @@ -113,7 +125,7 @@ this.tree = $.extend(true, [], options.data); delete options.data; } - this.options = $.extend({}, defaults, options); + this.options = $.extend({}, _default.settings, options); this.destroy(); this.subscribeEvents(); @@ -265,13 +277,13 @@ if ((classList.indexOf('click-expand') != -1) || (classList.indexOf('click-collapse') != -1)) { - this.toggleExpandedState(node); + this.toggleExpandedState(node, _default.options); } else if (node) { if (node.selectable) { - this.toggleSelectedState(node); + this.toggleSelectedState(node, _default.options); } else { - this.toggleExpandedState(node); + this.toggleExpandedState(node, _default.options); } } }; @@ -289,19 +301,20 @@ return node; }; - Tree.prototype.toggleExpandedState = function (node, silent) { + Tree.prototype.toggleExpandedState = function (node, options) { if (!node) return; - this.setExpandedState(node, !node.state.expanded, silent); + this.setExpandedState(node, !node.state.expanded, options); this.render(); }; - Tree.prototype.setExpandedState = function (node, state, silent) { + Tree.prototype.setExpandedState = function (node, state, options) { if (state) { // Expand a node node.state.expanded = true; - if (!silent) { + + if (!options.silent) { this.$element.trigger('nodeExpanded', $.extend(true, {}, node)); } } @@ -309,32 +322,33 @@ // Collapse a node node.state.expanded = false; - if (!silent) { + + if (!options.silent) { this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); } } }; - Tree.prototype.toggleSelectedState = function (node, silent) { + Tree.prototype.toggleSelectedState = function (node, options) { if (!node) { return; } - this.setSelectedState(node, !node.state.selected, silent); + this.setSelectedState(node, !node.state.selected, options); this.render(); }; - Tree.prototype.setSelectedState = function (node, state, silent) { + Tree.prototype.setSelectedState = function (node, state, options) { if (state) { // If multiSelect false, unselect previously selected if (!this.options.multiSelect) { $.each(this.findNodes('true', 'g', 'state.selected'), $.proxy(function (index, node) { - this.setSelectedState(node, false, silent); + this.setSelectedState(node, false, options); }, this)); } // Continue selecting node node.state.selected = true; - if (!silent) { + if (!options.silent) { this.$element.trigger('nodeSelected', $.extend(true, {}, node) ); } } @@ -342,7 +356,7 @@ // Unselect node node.state.selected = false; - if (!silent) { + if (!options.silent) { this.$element.trigger('nodeUnselected', $.extend(true, {}, node) ); } } @@ -573,8 +587,8 @@ @param {optional Object} options */ Tree.prototype.selectNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setSelectedState(this.identifyNode(identifier), true, silent); + options = $.extend({}, _default.options, options); + this.setSelectedState(this.identifyNode(identifier), true, options); this.render(); }; @@ -584,8 +598,8 @@ @param {optional Object} options */ Tree.prototype.unselectNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setSelectedState(this.identifyNode(identifier), false, silent); + options = $.extend({}, _default.options, options); + this.setSelectedState(this.identifyNode(identifier), false, options); this.render(); }; @@ -595,8 +609,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeSelected = function (identifier, options) { - this.toggleSelectedState(this.identifyNode(identifier), - this.isSilent(options)); + options = $.extend({}, _default.options, options); + this.toggleSelectedState(this.identifyNode(identifier), options); }; @@ -605,10 +619,10 @@ @param {optional Object} options */ Tree.prototype.collapseAll = function (options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); $.each(this.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, false, silent); + this.setExpandedState(node, false, options); }, this)); this.render(); @@ -620,8 +634,8 @@ @param {optional Object} options */ Tree.prototype.collapseNode = function (identifier, options) { - var silent = this.isSilent(options); - this.setExpandedState(this.identifyNode(identifier), false, silent); + options = $.extend({}, _default.options, options); + this.setExpandedState(this.identifyNode(identifier), false, options); this.render(); }; @@ -630,14 +644,14 @@ @param {optional Object} options */ Tree.prototype.expandAll = function (options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); if (options && options.levels) { - this.expandLevels(this.tree, options.levels, silent); + this.expandLevels(this.tree, options.levels, options); } else { $.each(this.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, true, silent); + this.setExpandedState(node, true, options); }, this)); } @@ -650,23 +664,25 @@ @param {optional Object} options */ Tree.prototype.expandNode = function (identifier, options) { - var silent = this.isSilent(options); + options = $.extend({}, _default.options, options); var node = this.identifyNode(identifier); - this.setExpandedState(node, true, silent); + this.setExpandedState(node, true, options); if (node.nodes && (options && options.levels)) { - this.expandLevels(node.nodes, options.levels-1, silent); + this.expandLevels(node.nodes, options.levels-1, options); } this.render(); }; - Tree.prototype.expandLevels = function (nodes, level, silent) { + Tree.prototype.expandLevels = function (nodes, level, options) { + options = $.extend({}, _default.options, options); + $.each(nodes, $.proxy(function (index, node) { - this.setExpandedState(node, (level > 0) ? true : false) + this.setExpandedState(node, (level > 0) ? true : false, options); if (node.nodes) { - this.expandLevels(node.nodes, level-1, silent); + this.expandLevels(node.nodes, level-1, options); } }, this)); }; @@ -677,8 +693,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeExpanded = function (identifier, options) { - this.toggleExpandedState(this.identifyNode(identifier), - this.isSilent(options)); + options = $.extend({}, _default.options, options); + this.toggleExpandedState(this.identifyNode(identifier), options); }; Tree.prototype.identifyNode = function (identifier) { @@ -687,12 +703,6 @@ identifier; }; - Tree.prototype.isSilent = function (options) { - return (options && options.hasOwnProperty('silent')) ? - options.silent : - false; - }; - /** Searches the tree for nodes (text) that match given criteria @@ -701,6 +711,7 @@ @return {Array} nodes - Matching nodes */ Tree.prototype.search = function (pattern, options) { + options = $.extend({}, _default.searchOptions, options); this.clearSearch(); @@ -789,10 +800,10 @@ }; var logError = function (message) { - if(window.console) { - window.console.error(message); - } - }; + if(window.console) { + window.console.error(message); + } + }; // Prevent against multiple instantiations, // handle updates and method calls From 7f1d89cd1ae4142fd1db1998119dd82e88cb6039 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 02:17:45 +0100 Subject: [PATCH 02/36] Fixes #68 child nodes not collapsing when collapseNode called. --- README.md | 5 +++-- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 7 +++++++ src/js/bootstrap-treeview.js | 7 +++++++ tests/lib/bootstrap-treeview.js | 7 +++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c72ffa93f..392280337 100644 --- a/README.md +++ b/README.md @@ -384,14 +384,15 @@ Triggers `nodeCollapsed` event; pass silent to suppress events. #### collapseNode(node | nodeId, options) -Collapse a given tree node, accepts node or nodeId +Collapse a given tree node and it's child nodes. If you don't want to collapse the child nodes, pass option `{ ignoreChildren: true }`. ```javascript -$('#tree').treeview('collapseNode', [ nodeId, { silent: true } ]); +$('#tree').treeview('collapseNode', [ nodeId, { silent: true, ignoreChildren: false } ]); ``` Triggers `nodeCollapsed` event; pass silent to suppress events. + #### expandAll(options) Expand all tree nodes. Optionally can be expanded to any given number of levels. diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 599876600..27fdc5002 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
        ',item:'
      • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
          ',item:'
        • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 1b70f551d..1fec0e3d9 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -323,6 +323,13 @@ // Collapse a node node.state.expanded = false; + // Collapse child nodes + if (node.nodes && !options.ignoreChildren) { + $.each(node.nodes, $.proxy(function (index, node) { + this.setExpandedState(node, false, $.extend({}, options, { silent: true })); + }, this)); + } + if (!options.silent) { this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); } diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 1b70f551d..1fec0e3d9 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -323,6 +323,13 @@ // Collapse a node node.state.expanded = false; + // Collapse child nodes + if (node.nodes && !options.ignoreChildren) { + $.each(node.nodes, $.proxy(function (index, node) { + this.setExpandedState(node, false, $.extend({}, options, { silent: true })); + }, this)); + } + if (!options.silent) { this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); } diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 1b70f551d..1fec0e3d9 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -323,6 +323,13 @@ // Collapse a node node.state.expanded = false; + // Collapse child nodes + if (node.nodes && !options.ignoreChildren) { + $.each(node.nodes, $.proxy(function (index, node) { + this.setExpandedState(node, false, $.extend({}, options, { silent: true })); + }, this)); + } + if (!options.silent) { this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); } From 46b29920af874bfc8ec34a35428ebc6316417803 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 19:21:52 +0100 Subject: [PATCH 03/36] Updates to state handling and transitioning logic - A node's state can only be expanded if it has nodes - A node's state can only transition to a new state, event are only triggered when state transitions - Method collapseAll only collapses nodes with an expanded state (using findNode) instead of just iterating all nodes. --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 22 ++++++++++++---------- src/js/bootstrap-treeview.js | 22 ++++++++++++---------- tests/lib/bootstrap-treeview.js | 22 ++++++++++++---------- 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 27fdc5002..35fab824f 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
            ',item:'
          • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
              ',item:'
            • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 1fec0e3d9..c884a9d1f 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -244,7 +244,7 @@ // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - if (level < _this.options.levels) { + if ((level < _this.options.levels) && node.nodes) { node.state.expanded = true; } else { @@ -309,30 +309,30 @@ Tree.prototype.setExpandedState = function (node, state, options) { - if (state) { + if (state === node.state.expanded) return; + + if (state && node.nodes) { // Expand a node node.state.expanded = true; - if (!options.silent) { this.$element.trigger('nodeExpanded', $.extend(true, {}, node)); } } - else { + else if (!state) { // Collapse a node node.state.expanded = false; + if (!options.silent) { + this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); + } // Collapse child nodes if (node.nodes && !options.ignoreChildren) { $.each(node.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, false, $.extend({}, options, { silent: true })); + this.setExpandedState(node, false, options); }, this)); } - - if (!options.silent) { - this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); - } } }; @@ -344,6 +344,8 @@ Tree.prototype.setSelectedState = function (node, state, options) { + if (state === node.state.selected) return; + if (state) { // If multiSelect false, unselect previously selected @@ -628,7 +630,7 @@ Tree.prototype.collapseAll = function (options) { options = $.extend({}, _default.options, options); - $.each(this.nodes, $.proxy(function (index, node) { + $.each(this.findNodes('true', 'g', 'state.expanded'), $.proxy(function (index, node) { this.setExpandedState(node, false, options); }, this)); diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 1fec0e3d9..c884a9d1f 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -244,7 +244,7 @@ // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - if (level < _this.options.levels) { + if ((level < _this.options.levels) && node.nodes) { node.state.expanded = true; } else { @@ -309,30 +309,30 @@ Tree.prototype.setExpandedState = function (node, state, options) { - if (state) { + if (state === node.state.expanded) return; + + if (state && node.nodes) { // Expand a node node.state.expanded = true; - if (!options.silent) { this.$element.trigger('nodeExpanded', $.extend(true, {}, node)); } } - else { + else if (!state) { // Collapse a node node.state.expanded = false; + if (!options.silent) { + this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); + } // Collapse child nodes if (node.nodes && !options.ignoreChildren) { $.each(node.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, false, $.extend({}, options, { silent: true })); + this.setExpandedState(node, false, options); }, this)); } - - if (!options.silent) { - this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); - } } }; @@ -344,6 +344,8 @@ Tree.prototype.setSelectedState = function (node, state, options) { + if (state === node.state.selected) return; + if (state) { // If multiSelect false, unselect previously selected @@ -628,7 +630,7 @@ Tree.prototype.collapseAll = function (options) { options = $.extend({}, _default.options, options); - $.each(this.nodes, $.proxy(function (index, node) { + $.each(this.findNodes('true', 'g', 'state.expanded'), $.proxy(function (index, node) { this.setExpandedState(node, false, options); }, this)); diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 1fec0e3d9..c884a9d1f 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -244,7 +244,7 @@ // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - if (level < _this.options.levels) { + if ((level < _this.options.levels) && node.nodes) { node.state.expanded = true; } else { @@ -309,30 +309,30 @@ Tree.prototype.setExpandedState = function (node, state, options) { - if (state) { + if (state === node.state.expanded) return; + + if (state && node.nodes) { // Expand a node node.state.expanded = true; - if (!options.silent) { this.$element.trigger('nodeExpanded', $.extend(true, {}, node)); } } - else { + else if (!state) { // Collapse a node node.state.expanded = false; + if (!options.silent) { + this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); + } // Collapse child nodes if (node.nodes && !options.ignoreChildren) { $.each(node.nodes, $.proxy(function (index, node) { - this.setExpandedState(node, false, $.extend({}, options, { silent: true })); + this.setExpandedState(node, false, options); }, this)); } - - if (!options.silent) { - this.$element.trigger('nodeCollapsed', $.extend(true, {}, node)); - } } }; @@ -344,6 +344,8 @@ Tree.prototype.setSelectedState = function (node, state, options) { + if (state === node.state.selected) return; + if (state) { // If multiSelect false, unselect previously selected @@ -628,7 +630,7 @@ Tree.prototype.collapseAll = function (options) { options = $.extend({}, _default.options, options); - $.each(this.nodes, $.proxy(function (index, node) { + $.each(this.findNodes('true', 'g', 'state.expanded'), $.proxy(function (index, node) { this.setExpandedState(node, false, options); }, this)); From 8c16c95d592bcfd1365e9db3acc4425e30c82d92 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 19:32:56 +0100 Subject: [PATCH 04/36] Fixes #69, displaying incorrect expandCollapseIcon when node equals an empty array --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 5 +++-- src/js/bootstrap-treeview.js | 5 +++-- tests/lib/bootstrap-treeview.js | 5 +++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 35fab824f..ed684258a 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                ',item:'
              • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                  ',item:'
                • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index c884a9d1f..8e8d5d71a 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -244,7 +244,9 @@ // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - if ((level < _this.options.levels) && node.nodes) { + + if ((level < _this.options.levels) && + (node.nodes && node.nodes.length > 0)) { node.state.expanded = true; } else { @@ -471,7 +473,6 @@ _this.$wrapper.append(treeItem); // Recursively add child ndoes - // console.log(node.text + ' ' + node.state.expanded); if (node.nodes && node.state.expanded) { return _this.buildTree(node.nodes, level); } diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index c884a9d1f..8e8d5d71a 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -244,7 +244,9 @@ // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - if ((level < _this.options.levels) && node.nodes) { + + if ((level < _this.options.levels) && + (node.nodes && node.nodes.length > 0)) { node.state.expanded = true; } else { @@ -471,7 +473,6 @@ _this.$wrapper.append(treeItem); // Recursively add child ndoes - // console.log(node.text + ' ' + node.state.expanded); if (node.nodes && node.state.expanded) { return _this.buildTree(node.nodes, level); } diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index c884a9d1f..8e8d5d71a 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -244,7 +244,9 @@ // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - if ((level < _this.options.levels) && node.nodes) { + + if ((level < _this.options.levels) && + (node.nodes && node.nodes.length > 0)) { node.state.expanded = true; } else { @@ -471,7 +473,6 @@ _this.$wrapper.append(treeItem); // Recursively add child ndoes - // console.log(node.text + ' ' + node.state.expanded); if (node.nodes && node.state.expanded) { return _this.buildTree(node.nodes, level); } From 1e12fd155fd85c35e62524bc49525549d701e15a Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 19:40:40 +0100 Subject: [PATCH 05/36] Code formatting / style updates --- public/js/bootstrap-treeview.js | 23 +++++++++++++---------- src/js/bootstrap-treeview.js | 23 +++++++++++++---------- tests/lib/bootstrap-treeview.js | 23 +++++++++++++---------- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 8e8d5d71a..301d587a7 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -221,7 +221,7 @@ */ Tree.prototype.setInitialStates = function (node, level) { - if (!node.nodes) { return; } + if (!node.nodes) return; level += 1; var parent = node; @@ -271,11 +271,11 @@ Tree.prototype.clickHandler = function (event) { - if (!this.options.enableLinks) { event.preventDefault(); } + if (!this.options.enableLinks) event.preventDefault(); - var target = $(event.target), - classList = target.attr('class') ? target.attr('class').split(' ') : [], - node = this.findNode(target); + var target = $(event.target); + var classList = target.attr('class') ? target.attr('class').split(' ') : []; + var node = this.findNode(target); if ((classList.indexOf('click-expand') != -1) || (classList.indexOf('click-collapse') != -1)) { @@ -294,8 +294,8 @@ // data attribute nodeid, which is used to lookup the node in the flattened structure. Tree.prototype.findNode = function (target) { - var nodeId = target.closest('li.list-group-item').attr('data-nodeid'), - node = this.nodes[nodeId]; + var nodeId = target.closest('li.list-group-item').attr('data-nodeid'); + var node = this.nodes[nodeId]; if (!node) { console.log('Error: node does not exist'); @@ -339,7 +339,7 @@ }; Tree.prototype.toggleSelectedState = function (node, options) { - if (!node) { return; } + if (!node) return; this.setSelectedState(node, !node.state.selected, options); this.render(); }; @@ -396,7 +396,7 @@ // structure we build the tree one node at a time Tree.prototype.buildTree = function (nodes, level) { - if (!nodes) { return; } + if (!nodes) return; level += 1; var _this = this; @@ -521,12 +521,15 @@ Tree.prototype.buildStyle = function () { var style = '.node-' + this.elementId + '{'; + if (this.options.color) { style += 'color:' + this.options.color + ';'; } + if (this.options.backColor) { style += 'background-color:' + this.options.backColor + ';'; } + if (!this.options.showBorder) { style += 'border:none;'; } @@ -810,7 +813,7 @@ }; var logError = function (message) { - if(window.console) { + if (window.console) { window.console.error(message); } }; diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 8e8d5d71a..301d587a7 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -221,7 +221,7 @@ */ Tree.prototype.setInitialStates = function (node, level) { - if (!node.nodes) { return; } + if (!node.nodes) return; level += 1; var parent = node; @@ -271,11 +271,11 @@ Tree.prototype.clickHandler = function (event) { - if (!this.options.enableLinks) { event.preventDefault(); } + if (!this.options.enableLinks) event.preventDefault(); - var target = $(event.target), - classList = target.attr('class') ? target.attr('class').split(' ') : [], - node = this.findNode(target); + var target = $(event.target); + var classList = target.attr('class') ? target.attr('class').split(' ') : []; + var node = this.findNode(target); if ((classList.indexOf('click-expand') != -1) || (classList.indexOf('click-collapse') != -1)) { @@ -294,8 +294,8 @@ // data attribute nodeid, which is used to lookup the node in the flattened structure. Tree.prototype.findNode = function (target) { - var nodeId = target.closest('li.list-group-item').attr('data-nodeid'), - node = this.nodes[nodeId]; + var nodeId = target.closest('li.list-group-item').attr('data-nodeid'); + var node = this.nodes[nodeId]; if (!node) { console.log('Error: node does not exist'); @@ -339,7 +339,7 @@ }; Tree.prototype.toggleSelectedState = function (node, options) { - if (!node) { return; } + if (!node) return; this.setSelectedState(node, !node.state.selected, options); this.render(); }; @@ -396,7 +396,7 @@ // structure we build the tree one node at a time Tree.prototype.buildTree = function (nodes, level) { - if (!nodes) { return; } + if (!nodes) return; level += 1; var _this = this; @@ -521,12 +521,15 @@ Tree.prototype.buildStyle = function () { var style = '.node-' + this.elementId + '{'; + if (this.options.color) { style += 'color:' + this.options.color + ';'; } + if (this.options.backColor) { style += 'background-color:' + this.options.backColor + ';'; } + if (!this.options.showBorder) { style += 'border:none;'; } @@ -810,7 +813,7 @@ }; var logError = function (message) { - if(window.console) { + if (window.console) { window.console.error(message); } }; diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 8e8d5d71a..301d587a7 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -221,7 +221,7 @@ */ Tree.prototype.setInitialStates = function (node, level) { - if (!node.nodes) { return; } + if (!node.nodes) return; level += 1; var parent = node; @@ -271,11 +271,11 @@ Tree.prototype.clickHandler = function (event) { - if (!this.options.enableLinks) { event.preventDefault(); } + if (!this.options.enableLinks) event.preventDefault(); - var target = $(event.target), - classList = target.attr('class') ? target.attr('class').split(' ') : [], - node = this.findNode(target); + var target = $(event.target); + var classList = target.attr('class') ? target.attr('class').split(' ') : []; + var node = this.findNode(target); if ((classList.indexOf('click-expand') != -1) || (classList.indexOf('click-collapse') != -1)) { @@ -294,8 +294,8 @@ // data attribute nodeid, which is used to lookup the node in the flattened structure. Tree.prototype.findNode = function (target) { - var nodeId = target.closest('li.list-group-item').attr('data-nodeid'), - node = this.nodes[nodeId]; + var nodeId = target.closest('li.list-group-item').attr('data-nodeid'); + var node = this.nodes[nodeId]; if (!node) { console.log('Error: node does not exist'); @@ -339,7 +339,7 @@ }; Tree.prototype.toggleSelectedState = function (node, options) { - if (!node) { return; } + if (!node) return; this.setSelectedState(node, !node.state.selected, options); this.render(); }; @@ -396,7 +396,7 @@ // structure we build the tree one node at a time Tree.prototype.buildTree = function (nodes, level) { - if (!nodes) { return; } + if (!nodes) return; level += 1; var _this = this; @@ -521,12 +521,15 @@ Tree.prototype.buildStyle = function () { var style = '.node-' + this.elementId + '{'; + if (this.options.color) { style += 'color:' + this.options.color + ';'; } + if (this.options.backColor) { style += 'background-color:' + this.options.backColor + ';'; } + if (!this.options.showBorder) { style += 'border:none;'; } @@ -810,7 +813,7 @@ }; var logError = function (message) { - if(window.console) { + if (window.console) { window.console.error(message); } }; From 90f6165ed41bf33645c871ec95e6c768b6fae12d Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 19:50:23 +0100 Subject: [PATCH 06/36] Examples updated - Removed events example trivet - Added events output to selectable and expandable --- public/index.html | 54 +++++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/public/index.html b/public/index.html index b84fb22fb..ce893774d 100644 --- a/public/index.html +++ b/public/index.html @@ -122,6 +122,8 @@

                  Tree

                  +

                  Events

                  +
                  @@ -169,22 +171,8 @@

                  Tree

                  -
                  - -
                  -
                  -

                  Events

                  -
                  -

                  Input

                  -
                  -
                  -
                  -

                  Output

                  -
                  -
                  -
                  - +

                  Events

                  +
                  @@ -433,23 +421,7 @@

                  enableLinks: true, data: defaultData }); - - $('#treeview-events').treeview({ - data: defaultData, - onNodeCollapsed: function(event, node) { - $('#event-output').prepend('

                  ' + node.text + ' was collapsed

                  '); - }, - onNodeExpanded: function (event, node) { - $('#event-output').prepend('

                  ' + node.text + ' was expanded

                  '); - }, - onNodeSelected: function(event, node) { - $('#event-output').prepend('

                  ' + node.text + ' was selected

                  '); - }, - onNodeUnselected: function (event, node) { - $('#event-output').prepend('

                  ' + node.text + ' was unselected

                  '); - } - }); - + var $searchableTree = $('#treeview-searchable').treeview({ @@ -483,7 +455,13 @@

                  var $selectableTree = $('#treeview-selectable').treeview({ - data: defaultData + data: defaultData, + onNodeSelected: function(event, node) { + $('#selectable-output').prepend('

                  ' + node.text + ' was selected

                  '); + }, + onNodeUnselected: function (event, node) { + $('#selectable-output').prepend('

                  ' + node.text + ' was unselected

                  '); + } }); var findSelectableNode = function() { @@ -512,7 +490,13 @@

                  var $expandibleTree = $('#treeview-expandible').treeview({ - data: defaultData + data: defaultData, + onNodeCollapsed: function(event, node) { + $('#expandible-output').prepend('

                  ' + node.text + ' was collapsed

                  '); + }, + onNodeExpanded: function (event, node) { + $('#expandible-output').prepend('

                  ' + node.text + ' was expanded

                  '); + } }); var findExpandibleNode = function() { From 3d7f9d10830aff4043a2a215e6f0e3f75643951f Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 20:02:42 +0100 Subject: [PATCH 07/36] Updates to change log --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8caad5b3a..143eff336 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## v1.2.0 - [Unreleased] + +### New Features + +### Changes +- Method collapseNode accepts new option `{ignoreChildren: true | false }`. The default is false, passing true will leave child nodes uncollapsed. + +### Bug Fixes +- Child nodes should collapse by default on collapseNode +- Incorrect expand collapse icon displayed when nodes array is empty + + ## v1.1.0 - 29th March, 2015 ### New Features From 17ddaa0dc7cad2626021ee46a37d2228f6fa9e68 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 21:13:36 +0100 Subject: [PATCH 08/36] Implemented stated based get methods `getSelected`, `getUnselected`, `getExpanded` and `getCollapsed` #63 --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 40 +++++++++++++++++++++++++++++++-- src/js/bootstrap-treeview.js | 40 +++++++++++++++++++++++++++++++-- tests/lib/bootstrap-treeview.js | 40 +++++++++++++++++++++++++++++++-- 4 files changed, 115 insertions(+), 7 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index ed684258a..c869e5ee3 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                    ',item:'
                  • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                      ',item:'
                    • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 301d587a7..1cd6ef544 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -94,6 +94,10 @@ getNode: $.proxy(this.getNode, this), getParent: $.proxy(this.getParent, this), getSiblings: $.proxy(this.getSiblings, this), + getSelected: $.proxy(this.getSelected, this), + getUnselected: $.proxy(this.getUnselected, this), + getExpanded: $.proxy(this.getExpanded, this), + getCollapsed: $.proxy(this.getCollapsed, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -572,7 +576,7 @@ /** Returns the parent node of a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id - @returns {Object} parent - The parent node + @returns {Object} node - The parent node */ Tree.prototype.getParent = function (identifier) { var node = this.identifyNode(identifier); @@ -582,7 +586,7 @@ /** Returns an array of sibling nodes for a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id - @returns {Array} siblings - Sibling nodes + @returns {Array} nodes - Sibling nodes */ Tree.prototype.getSiblings = function (identifier) { var node = this.identifyNode(identifier); @@ -593,6 +597,38 @@ }); }; + /** + Returns an array of selected nodes. + @returns {Array} nodes - Selected nodes + */ + Tree.prototype.getSelected = function () { + return this.findNodes('true', 'g', 'state.selected'); + }; + + /** + Returns an array of unselected nodes. + @returns {Array} nodes - Unselected nodes + */ + Tree.prototype.getUnselected = function () { + return this.findNodes('false', 'g', 'state.selected'); + }; + + /** + Returns an array of expanded nodes. + @returns {Array} nodes - Expanded nodes + */ + Tree.prototype.getExpanded = function () { + return this.findNodes('true', 'g', 'state.expanded'); + }; + + /** + Returns an array of collapsed nodes. + @returns {Array} nodes - Collapsed nodes + */ + Tree.prototype.getCollapsed = function () { + return this.findNodes('false', 'g', 'state.expanded'); + }; + /** Set a node state to selected diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 301d587a7..1cd6ef544 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -94,6 +94,10 @@ getNode: $.proxy(this.getNode, this), getParent: $.proxy(this.getParent, this), getSiblings: $.proxy(this.getSiblings, this), + getSelected: $.proxy(this.getSelected, this), + getUnselected: $.proxy(this.getUnselected, this), + getExpanded: $.proxy(this.getExpanded, this), + getCollapsed: $.proxy(this.getCollapsed, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -572,7 +576,7 @@ /** Returns the parent node of a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id - @returns {Object} parent - The parent node + @returns {Object} node - The parent node */ Tree.prototype.getParent = function (identifier) { var node = this.identifyNode(identifier); @@ -582,7 +586,7 @@ /** Returns an array of sibling nodes for a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id - @returns {Array} siblings - Sibling nodes + @returns {Array} nodes - Sibling nodes */ Tree.prototype.getSiblings = function (identifier) { var node = this.identifyNode(identifier); @@ -593,6 +597,38 @@ }); }; + /** + Returns an array of selected nodes. + @returns {Array} nodes - Selected nodes + */ + Tree.prototype.getSelected = function () { + return this.findNodes('true', 'g', 'state.selected'); + }; + + /** + Returns an array of unselected nodes. + @returns {Array} nodes - Unselected nodes + */ + Tree.prototype.getUnselected = function () { + return this.findNodes('false', 'g', 'state.selected'); + }; + + /** + Returns an array of expanded nodes. + @returns {Array} nodes - Expanded nodes + */ + Tree.prototype.getExpanded = function () { + return this.findNodes('true', 'g', 'state.expanded'); + }; + + /** + Returns an array of collapsed nodes. + @returns {Array} nodes - Collapsed nodes + */ + Tree.prototype.getCollapsed = function () { + return this.findNodes('false', 'g', 'state.expanded'); + }; + /** Set a node state to selected diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 301d587a7..1cd6ef544 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -94,6 +94,10 @@ getNode: $.proxy(this.getNode, this), getParent: $.proxy(this.getParent, this), getSiblings: $.proxy(this.getSiblings, this), + getSelected: $.proxy(this.getSelected, this), + getUnselected: $.proxy(this.getUnselected, this), + getExpanded: $.proxy(this.getExpanded, this), + getCollapsed: $.proxy(this.getCollapsed, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -572,7 +576,7 @@ /** Returns the parent node of a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id - @returns {Object} parent - The parent node + @returns {Object} node - The parent node */ Tree.prototype.getParent = function (identifier) { var node = this.identifyNode(identifier); @@ -582,7 +586,7 @@ /** Returns an array of sibling nodes for a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id - @returns {Array} siblings - Sibling nodes + @returns {Array} nodes - Sibling nodes */ Tree.prototype.getSiblings = function (identifier) { var node = this.identifyNode(identifier); @@ -593,6 +597,38 @@ }); }; + /** + Returns an array of selected nodes. + @returns {Array} nodes - Selected nodes + */ + Tree.prototype.getSelected = function () { + return this.findNodes('true', 'g', 'state.selected'); + }; + + /** + Returns an array of unselected nodes. + @returns {Array} nodes - Unselected nodes + */ + Tree.prototype.getUnselected = function () { + return this.findNodes('false', 'g', 'state.selected'); + }; + + /** + Returns an array of expanded nodes. + @returns {Array} nodes - Expanded nodes + */ + Tree.prototype.getExpanded = function () { + return this.findNodes('true', 'g', 'state.expanded'); + }; + + /** + Returns an array of collapsed nodes. + @returns {Array} nodes - Collapsed nodes + */ + Tree.prototype.getCollapsed = function () { + return this.findNodes('false', 'g', 'state.expanded'); + }; + /** Set a node state to selected From 2d081c7f490d3107d295081786a0039de5056ad9 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Mon, 13 Apr 2015 23:30:51 +0100 Subject: [PATCH 09/36] Added tests and doc #63 --- README.md | 31 +++++++++++++++++++++++++++++++ tests/tests.js | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 392280337..137b69fac 100644 --- a/README.md +++ b/README.md @@ -413,6 +413,21 @@ $('#tree').treeview('expandNode', [ nodeId, { levels: 2, silent: true } ]); Triggers `nodeExpanded` event; pass silent to suppress events. +#### getCollapsed() + +Returns an array of collapsed nodes e.g. state.expanded = false. + +```javascript +$('#tree').treeview('getCollapsed', nodeId); +``` +#### getExpanded() + +Returns an array of expanded nodes e.g. state.expanded = true. + +```javascript +$('#tree').treeview('getExpanded', nodeId); +``` + #### getNode(nodeId) Returns a single node object that matches the given node id. @@ -429,6 +444,14 @@ Returns the parent node of a given node, if valid otherwise returns undefined. $('#tree').treeview('getParent', node); ``` +#### getSelected() + +Returns an array of selected nodes e.g. state.selected = true. + +```javascript +$('#tree').treeview('getSelected', nodeId); +``` + #### getSiblings(node | nodeId) Returns an array of sibling nodes for a given node, if valid otherwise returns undefined. @@ -437,6 +460,14 @@ Returns an array of sibling nodes for a given node, if valid otherwise returns u $('#tree').treeview('getSiblings', node); ``` +#### getUnselected() + +Returns an array of unselected nodes e.g. state.selected = false. + +```javascript +$('#tree').treeview('getUnselected', nodeId); +``` + #### remove() Removes the tree view component. Removing attached events, internal attached objects, and added HTML elements. diff --git a/tests/tests.js b/tests/tests.js index ece522cef..18127dca9 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -375,7 +375,7 @@ test('getNode', function () { var $tree = init({ data: data }); var nodeParent1 = $tree.treeview('getNode', 0); - equal(nodeParent1.text, 'Parent 1', 'Correct node returned : requested "Parent 1", for "Parent 1"'); + equal(nodeParent1.text, 'Parent 1', 'Correct node returned : requested "Parent 1", got "Parent 1"'); }); test('getParent', function () { @@ -412,6 +412,47 @@ ok(results, 'Correct siblings for "Child 1" [non root] : results OK'); }); + test('getSelected', function () { + var $tree = init({ data: data }) + .treeview('selectNode', 0); + + var selectedNodes = $tree.treeview('getSelected'); + ok((selectedNodes instanceof Array), 'Result is an array'); + equal(selectedNodes.length, 1, 'Correct number of nodes returned'); + equal(selectedNodes[0].text, 'Parent 1', 'Correct node returned'); + }); + + test('getUnselected', function () { + var $tree = init({ data: data }) + .treeview('selectNode', 0); + + var unselectedNodes = $tree.treeview('getUnselected'); + ok((unselectedNodes instanceof Array), 'Result is an array'); + equal(unselectedNodes.length, 8, 'Correct number of nodes returned'); + }); + + // Assumptions: + // Default tree + expanded to 2 levels, + // means 1 node 'Parent 1' should be expanded and therefore returned + test('getExpanded', function () { + var $tree = init({ data: data }); + var expandedNodes = $tree.treeview('getExpanded'); + ok((expandedNodes instanceof Array), 'Result is an array'); + equal(expandedNodes.length, 1, 'Correct number of nodes returned'); + equal(expandedNodes[0].text, 'Parent 1', 'Correct node returned'); + }); + + // Assumptions: + // Default tree + expanded to 2 levels, means only 'Parent 1' should be expanded + // as all other parent nodes have no children their state will be collapsed + // which means 8 of the 9 nodes should be returned + test('getCollapsed', function () { + var $tree = init({ data: data }); + var collapsedNodes = $tree.treeview('getCollapsed'); + ok((collapsedNodes instanceof Array), 'Result is an array'); + equal(collapsedNodes.length, 8, 'Correct number of nodes returned'); + }); + test('selectNode / unselectNode', function () { var $tree = init({ data: data }); var el; From 3f64f7cd7519e9a5b4fd5605f31415f720f5ac21 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Tue, 14 Apr 2015 20:58:15 +0100 Subject: [PATCH 10/36] Implemented revealNodes method, updated doc and tests #65 --- README.md | 10 ++++++++++ dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 16 ++++++++++++++++ src/js/bootstrap-treeview.js | 16 ++++++++++++++++ tests/lib/bootstrap-treeview.js | 16 ++++++++++++++++ tests/tests.js | 11 +++++++++++ 6 files changed, 70 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 137b69fac..6959475c4 100644 --- a/README.md +++ b/README.md @@ -476,6 +476,16 @@ Removes the tree view component. Removing attached events, internal attached obj $('#tree').treeview('remove'); ``` +#### revealNode() + +Reveals a given tree node, expanding the tree from node to root. + +```javascript +$('#tree').treeview('revealNode'); +``` + +Triggers `nodeExpanded` event; pass silent to suppress events. + #### search(pattern, options) Searches the tree view for nodes that match a given string, highlighting them in the tree. diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index c869e5ee3..7bc2744a1 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                        ',item:'
                      • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                          ',item:'
                        • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c);for(var d=this.getParent(b);d;)this.expandNode(d),d=this.getParent(d)},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 1cd6ef544..488735b72 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -110,6 +110,7 @@ expandAll: $.proxy(this.expandAll, this), expandNode: $.proxy(this.expandNode, this), toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this), + revealNode: $.proxy(this.revealNode, this), // Search methods search: $.proxy(this.search, this), @@ -736,6 +737,21 @@ }, this)); }; + /** + Reveals a given tree node, expanding the tree from node to root. + @param {Object|Number} identifier - A valid node or node id + @param {optional Object} options + */ + Tree.prototype.revealNode = function (identifier, options) { + options = $.extend({}, _default.options, options); + + var parentNode = this.getParent(identifier); + while (parentNode) { + this.expandNode(parentNode); + parentNode = this.getParent(parentNode); + }; + }; + /** Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. @param {Object|Number} identifier - A valid node or node id diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 1cd6ef544..488735b72 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -110,6 +110,7 @@ expandAll: $.proxy(this.expandAll, this), expandNode: $.proxy(this.expandNode, this), toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this), + revealNode: $.proxy(this.revealNode, this), // Search methods search: $.proxy(this.search, this), @@ -736,6 +737,21 @@ }, this)); }; + /** + Reveals a given tree node, expanding the tree from node to root. + @param {Object|Number} identifier - A valid node or node id + @param {optional Object} options + */ + Tree.prototype.revealNode = function (identifier, options) { + options = $.extend({}, _default.options, options); + + var parentNode = this.getParent(identifier); + while (parentNode) { + this.expandNode(parentNode); + parentNode = this.getParent(parentNode); + }; + }; + /** Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. @param {Object|Number} identifier - A valid node or node id diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 1cd6ef544..488735b72 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -110,6 +110,7 @@ expandAll: $.proxy(this.expandAll, this), expandNode: $.proxy(this.expandNode, this), toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this), + revealNode: $.proxy(this.revealNode, this), // Search methods search: $.proxy(this.search, this), @@ -736,6 +737,21 @@ }, this)); }; + /** + Reveals a given tree node, expanding the tree from node to root. + @param {Object|Number} identifier - A valid node or node id + @param {optional Object} options + */ + Tree.prototype.revealNode = function (identifier, options) { + options = $.extend({}, _default.options, options); + + var parentNode = this.getParent(identifier); + while (parentNode) { + this.expandNode(parentNode); + parentNode = this.getParent(parentNode); + }; + }; + /** Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. @param {Object|Number} identifier - A valid node or node id diff --git a/tests/tests.js b/tests/tests.js index 18127dca9..df52b830a 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -556,6 +556,17 @@ equal($($tree.selector + ' ul li').length, 9, 'Expand node (levels = 2, by node) works, 9 nodes displayed'); }); + test('revealNode', function () { + var $tree = init({ data: data, levels: 1 }); + + $tree.treeview('revealNode', 1); // Child_1 + equal($($tree.selector + ' ul li').length, 7, 'Reveal node (by id) works, reveal Child 1 and 7 nodes displayed'); + + var nodeGrandchild1 = $tree.treeview('getNode', 2); // Grandchild 1 + $tree.treeview('revealNode', nodeGrandchild1); + equal($($tree.selector + ' ul li').length, 9, 'Reveal node (by node) works, reveal Grandchild 1 and 9 nodes displayed'); + }); + test('search', function () { var cbWorked, onWorked = false; var $tree = init({ From ef99728edad1bb769a7ffc47634caef0d7938bdf Mon Sep 17 00:00:00 2001 From: jonmiles Date: Tue, 14 Apr 2015 21:17:31 +0100 Subject: [PATCH 11/36] Improved revealNode to only render once. #65 - Using setExpandedState instead of expandNode and then only rendering once when finished. --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 4 +++- src/js/bootstrap-treeview.js | 4 +++- tests/lib/bootstrap-treeview.js | 4 +++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 7bc2744a1..9ea22f8ae 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                            ',item:'
                          • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c);for(var d=this.getParent(b);d;)this.expandNode(d),d=this.getParent(d)},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                              ',item:'
                            • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c);for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d);this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 488735b72..c1d7f8532 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -747,9 +747,11 @@ var parentNode = this.getParent(identifier); while (parentNode) { - this.expandNode(parentNode); + this.setExpandedState(parentNode, true, options); parentNode = this.getParent(parentNode); }; + + this.render(); }; /** diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 488735b72..c1d7f8532 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -747,9 +747,11 @@ var parentNode = this.getParent(identifier); while (parentNode) { - this.expandNode(parentNode); + this.setExpandedState(parentNode, true, options); parentNode = this.getParent(parentNode); }; + + this.render(); }; /** diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 488735b72..c1d7f8532 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -747,9 +747,11 @@ var parentNode = this.getParent(identifier); while (parentNode) { - this.expandNode(parentNode); + this.setExpandedState(parentNode, true, options); parentNode = this.getParent(parentNode); }; + + this.render(); }; /** From ef86a8fa20d65329f655aa4eca8d7306cfc62744 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Tue, 14 Apr 2015 21:59:29 +0100 Subject: [PATCH 12/36] Updated search method to optionally reveal results. #65 - New option `{revealResults: true|false}`, true by default - Updated revealNode to accept an array of nodes. - Updated searchable tree example --- README.md | 5 +++-- dist/bootstrap-treeview.min.js | 2 +- public/index.html | 11 ++++++++-- public/js/bootstrap-treeview.js | 37 ++++++++++++++++++++++++++------- src/js/bootstrap-treeview.js | 37 ++++++++++++++++++++++++++------- tests/lib/bootstrap-treeview.js | 37 ++++++++++++++++++++++++++------- 6 files changed, 100 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 6959475c4..f648af012 100644 --- a/README.md +++ b/README.md @@ -494,8 +494,9 @@ Returns an array of matching nodes. ```javascript $('#tree').treeview('search', [ 'Parent', { - ignoreCase: true, - exactMatch: false + ignoreCase: true, // case insensitive + exactMatch: false, // like or equals + revealResults: false, // reveal matching nodes }]); ``` diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 9ea22f8ae..99ff350c5 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                ',item:'
                              • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c);for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d);this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                  ',item:'
                                • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/index.html b/public/index.html index ce893774d..fc58bd165 100644 --- a/public/index.html +++ b/public/index.html @@ -85,6 +85,12 @@

                                  Input

                                  Exact Match
                                  +
                                  + +
                                  @@ -421,7 +427,7 @@

                                  enableLinks: true, data: defaultData }); - + var $searchableTree = $('#treeview-searchable').treeview({ @@ -432,7 +438,8 @@

                                  var pattern = $('#input-search').val(); var options = { ignoreCase: $('#chk-ignore-case').is(':checked'), - exactMatch: $('#chk-exact-match').is(':checked') + exactMatch: $('#chk-exact-match').is(':checked'), + revealResults: $('#chk-reveal-results').is(':checked') }; var results = $searchableTree.treeview('search', [ pattern, options ]); diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index c1d7f8532..6b5416f4f 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -70,7 +70,8 @@ _default.searchOptions = { ignoreCase: true, - exactMatch: false + exactMatch: false, + revealResults: true }; var Tree = function (element, options) { @@ -739,17 +740,26 @@ /** Reveals a given tree node, expanding the tree from node to root. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number|Array} identifier - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.revealNode = function (identifier, options) { options = $.extend({}, _default.options, options); - var parentNode = this.getParent(identifier); - while (parentNode) { - this.setExpandedState(parentNode, true, options); - parentNode = this.getParent(parentNode); - }; + if (!(identifier instanceof Array)) { + identifier = [identifier]; + } + + // Iterate nodes + $.each(identifier, $.proxy(function (index, identifier) { + + // Traverse the tree expanding parents from node to root + var parentNode = this.getParent(identifier); + while (parentNode) { + this.setExpandedState(parentNode, true, options); + parentNode = this.getParent(parentNode); + }; + }, this)); this.render(); }; @@ -795,11 +805,22 @@ } results = this.findNodes(pattern, modifier); + + // Add searchResult property to all matching nodes + // This will be used to apply custom styles + // and when identifying result to be cleared $.each(results, function (index, node) { node.searchResult = true; }) - this.render(); + // If revealResults, then render is triggered from revealNode + // otherwise we just call render. + if (options.revealResults) { + this.revealNode(results); + } + else { + this.render(); + } } this.$element.trigger('searchComplete', $.extend(true, {}, results)); diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index c1d7f8532..6b5416f4f 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -70,7 +70,8 @@ _default.searchOptions = { ignoreCase: true, - exactMatch: false + exactMatch: false, + revealResults: true }; var Tree = function (element, options) { @@ -739,17 +740,26 @@ /** Reveals a given tree node, expanding the tree from node to root. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number|Array} identifier - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.revealNode = function (identifier, options) { options = $.extend({}, _default.options, options); - var parentNode = this.getParent(identifier); - while (parentNode) { - this.setExpandedState(parentNode, true, options); - parentNode = this.getParent(parentNode); - }; + if (!(identifier instanceof Array)) { + identifier = [identifier]; + } + + // Iterate nodes + $.each(identifier, $.proxy(function (index, identifier) { + + // Traverse the tree expanding parents from node to root + var parentNode = this.getParent(identifier); + while (parentNode) { + this.setExpandedState(parentNode, true, options); + parentNode = this.getParent(parentNode); + }; + }, this)); this.render(); }; @@ -795,11 +805,22 @@ } results = this.findNodes(pattern, modifier); + + // Add searchResult property to all matching nodes + // This will be used to apply custom styles + // and when identifying result to be cleared $.each(results, function (index, node) { node.searchResult = true; }) - this.render(); + // If revealResults, then render is triggered from revealNode + // otherwise we just call render. + if (options.revealResults) { + this.revealNode(results); + } + else { + this.render(); + } } this.$element.trigger('searchComplete', $.extend(true, {}, results)); diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index c1d7f8532..6b5416f4f 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -70,7 +70,8 @@ _default.searchOptions = { ignoreCase: true, - exactMatch: false + exactMatch: false, + revealResults: true }; var Tree = function (element, options) { @@ -739,17 +740,26 @@ /** Reveals a given tree node, expanding the tree from node to root. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number|Array} identifier - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.revealNode = function (identifier, options) { options = $.extend({}, _default.options, options); - var parentNode = this.getParent(identifier); - while (parentNode) { - this.setExpandedState(parentNode, true, options); - parentNode = this.getParent(parentNode); - }; + if (!(identifier instanceof Array)) { + identifier = [identifier]; + } + + // Iterate nodes + $.each(identifier, $.proxy(function (index, identifier) { + + // Traverse the tree expanding parents from node to root + var parentNode = this.getParent(identifier); + while (parentNode) { + this.setExpandedState(parentNode, true, options); + parentNode = this.getParent(parentNode); + }; + }, this)); this.render(); }; @@ -795,11 +805,22 @@ } results = this.findNodes(pattern, modifier); + + // Add searchResult property to all matching nodes + // This will be used to apply custom styles + // and when identifying result to be cleared $.each(results, function (index, node) { node.searchResult = true; }) - this.render(); + // If revealResults, then render is triggered from revealNode + // otherwise we just call render. + if (options.revealResults) { + this.revealNode(results); + } + else { + this.render(); + } } this.$element.trigger('searchComplete', $.extend(true, {}, results)); From 18fb8c7514a8c2565e703fffdcce281f43d11d81 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Tue, 14 Apr 2015 22:11:24 +0100 Subject: [PATCH 13/36] Corrected doc on revealNode #65 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f648af012..e9544e724 100644 --- a/README.md +++ b/README.md @@ -476,12 +476,12 @@ Removes the tree view component. Removing attached events, internal attached obj $('#tree').treeview('remove'); ``` -#### revealNode() +#### revealNode(node | nodeId, options) Reveals a given tree node, expanding the tree from node to root. ```javascript -$('#tree').treeview('revealNode'); +$('#tree').treeview('revealNode', [ nodeId, { silent: true } ]); ``` Triggers `nodeExpanded` event; pass silent to suppress events. From a3c3b12c309378979f7aaf1a525d2a6b5c1f3e23 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Wed, 15 Apr 2015 10:35:17 +0100 Subject: [PATCH 14/36] Doc update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e9544e724..c88926d4f 100644 --- a/README.md +++ b/README.md @@ -496,7 +496,7 @@ Returns an array of matching nodes. $('#tree').treeview('search', [ 'Parent', { ignoreCase: true, // case insensitive exactMatch: false, // like or equals - revealResults: false, // reveal matching nodes + revealResults: true, // reveal matching nodes }]); ``` From b8b7eabaf81e926b4ef686211ad82aa21a532b35 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Wed, 15 Apr 2015 10:56:57 +0100 Subject: [PATCH 15/36] Updates to change log --- CHANGELOG.md | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 143eff336..5fc715dda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,13 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## v1.2.0 - [Unreleased] ### New Features +- New search option `{ revealResults : true | false }` which when set to true will automatically expand the tree view to reveal matching nodes +- New method `revealNode` which expands the tree view to reveal a given node +- New methods `getSelected`, `getUnselected`, `getExpanded` and `getCollapsed` to retrieve nodes by state ### Changes -- Method collapseNode accepts new option `{ignoreChildren: true | false }`. The default is false, passing true will leave child nodes uncollapsed. +- By default search will expand tree view and reveal results +- Method collapseNode accepts new option `{ ignoreChildren: true | false }`. The default is false, passing true will leave child nodes uncollapsed ### Bug Fixes - Child nodes should collapse by default on collapseNode @@ -17,16 +21,16 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## v1.1.0 - 29th March, 2015 ### New Features -- Node states `expanded` and `selected` to set a node's initial state -- Methods `getNode`, `getParent` and `getSiblings` methods -- Methods `selectNode`, `unselectNode` and `toggleNodeSelected` methods -- Events `nodeUnselected` -- Option `multiSelect` -- Methods `expandAll`, `collapseAll`, `expandNode`, `collapseNode` and `toggleNodeExpanded` methods -- Events `nodeExpanded` and `nodeCollapsed` events -- Methods `search` and `clearSearch` methods, -- Events `searchComplete` and `searchCleared` events -- Options `highlightSearchResults`, `searchResultColor` and `searchResultBackColor` +- Added node state properties `expanded` and `selected` so a node's intial state can be set +- New get methods `getNode`, `getParent` and `getSiblings` for retrieving nodes and their immediate relations +- New select methods `selectNode`, `unselectNode` and `toggleNodeSelected` +- Adding `nodeUnselected` event +- New global option `multiSelect` which allows multiple nodes to hold the selected state, default is false +- New expand collapse methods `expandAll`, `collapseAll`, `expandNode`, `collapseNode` and `toggleNodeExpanded` +- Adding events `nodeExpanded` and `nodeCollapsed` +- New methods `search` and `clearSearch` which allow you to query the tree view for nodes based on a `text` value +- Adding events `searchComplete` and `searchCleared` +- New global options `highlightSearchResults`, `searchResultColor` and `searchResultBackColor` for configuring how search results are displayed ## v1.0.2 - 6th February, 2015 From 8508fb297e8df02296e98c3b82fabdb2083bca3c Mon Sep 17 00:00:00 2001 From: jonmiles Date: Wed, 15 Apr 2015 20:42:15 +0100 Subject: [PATCH 16/36] Updated methods that accept identifiers, to also accept an array of identifiers --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 104 +++++++++++++++++++++++--------- src/js/bootstrap-treeview.js | 104 +++++++++++++++++++++++--------- tests/lib/bootstrap-treeview.js | 104 +++++++++++++++++++++++--------- 4 files changed, 223 insertions(+), 91 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 99ff350c5..e880eac8f 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                    ',item:'
                                  • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!0,c),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),this.setSelectedState(this.identifyNode(b),!1,c),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),this.toggleSelectedState(this.identifyNode(b),c)},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),this.setExpandedState(this.identifyNode(b),!1,c),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c);var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),this.toggleExpandedState(this.identifyNode(b),c)},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                      ',item:'
                                    • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 6b5416f4f..d2374e8dc 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -634,34 +634,57 @@ /** Set a node state to selected - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.selectNode = function (identifier, options) { + Tree.prototype.selectNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setSelectedState(this.identifyNode(identifier), true, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setSelectedState(this.identifyNode(identifier), true, options); + }, this)); + this.render(); }; /** Set a node state to unselected - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.unselectNode = function (identifier, options) { + Tree.prototype.unselectNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setSelectedState(this.identifyNode(identifier), false, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setSelectedState(this.identifyNode(identifier), false, options); + }, this)); + this.render(); }; /** Toggles a node selected state; selecting if unselected, unselecting if selected. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.toggleNodeSelected = function (identifier, options) { + Tree.prototype.toggleNodeSelected = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.toggleSelectedState(this.identifyNode(identifier), options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleSelectedState(this.identifyNode(identifier), options); + }, this)); }; @@ -681,12 +704,20 @@ /** Collapse a given tree node - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.collapseNode = function (identifier, options) { + Tree.prototype.collapseNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setExpandedState(this.identifyNode(identifier), false, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setExpandedState(this.identifyNode(identifier), false, options); + }, this)); + this.render(); }; @@ -711,19 +742,24 @@ /** Expand a given tree node - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.expandNode = function (identifier, options) { + Tree.prototype.expandNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - var node = this.identifyNode(identifier); - this.setExpandedState(node, true, options); - - if (node.nodes && (options && options.levels)) { - this.expandLevels(node.nodes, options.levels-1, options); + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; } + $.each(identifiers, $.proxy(function (index, identifier) { + var node = this.identifyNode(identifier); + this.setExpandedState(node, true, options); + if (node.nodes && (options && options.levels)) { + this.expandLevels(node.nodes, options.levels-1, options); + } + }, this)); + this.render(); }; @@ -740,20 +776,17 @@ /** Reveals a given tree node, expanding the tree from node to root. - @param {Object|Number|Array} identifier - A valid node, node id or array of node identifiers + @param {Object|Number|Array} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.revealNode = function (identifier, options) { + Tree.prototype.revealNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - if (!(identifier instanceof Array)) { - identifier = [identifier]; + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; } - // Iterate nodes - $.each(identifier, $.proxy(function (index, identifier) { - - // Traverse the tree expanding parents from node to root + $.each(identifiers, $.proxy(function (index, identifier) { var parentNode = this.getParent(identifier); while (parentNode) { this.setExpandedState(parentNode, true, options); @@ -766,14 +799,25 @@ /** Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.toggleNodeExpanded = function (identifier, options) { + Tree.prototype.toggleNodeExpanded = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.toggleExpandedState(this.identifyNode(identifier), options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleExpandedState(this.identifyNode(identifier), options); + }, this)); }; + + /* + Identifies a node from either a node id or object + */ Tree.prototype.identifyNode = function (identifier) { return ((typeof identifier) === 'number') ? this.nodes[identifier] : diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 6b5416f4f..d2374e8dc 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -634,34 +634,57 @@ /** Set a node state to selected - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.selectNode = function (identifier, options) { + Tree.prototype.selectNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setSelectedState(this.identifyNode(identifier), true, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setSelectedState(this.identifyNode(identifier), true, options); + }, this)); + this.render(); }; /** Set a node state to unselected - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.unselectNode = function (identifier, options) { + Tree.prototype.unselectNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setSelectedState(this.identifyNode(identifier), false, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setSelectedState(this.identifyNode(identifier), false, options); + }, this)); + this.render(); }; /** Toggles a node selected state; selecting if unselected, unselecting if selected. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.toggleNodeSelected = function (identifier, options) { + Tree.prototype.toggleNodeSelected = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.toggleSelectedState(this.identifyNode(identifier), options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleSelectedState(this.identifyNode(identifier), options); + }, this)); }; @@ -681,12 +704,20 @@ /** Collapse a given tree node - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.collapseNode = function (identifier, options) { + Tree.prototype.collapseNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setExpandedState(this.identifyNode(identifier), false, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setExpandedState(this.identifyNode(identifier), false, options); + }, this)); + this.render(); }; @@ -711,19 +742,24 @@ /** Expand a given tree node - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.expandNode = function (identifier, options) { + Tree.prototype.expandNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - var node = this.identifyNode(identifier); - this.setExpandedState(node, true, options); - - if (node.nodes && (options && options.levels)) { - this.expandLevels(node.nodes, options.levels-1, options); + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; } + $.each(identifiers, $.proxy(function (index, identifier) { + var node = this.identifyNode(identifier); + this.setExpandedState(node, true, options); + if (node.nodes && (options && options.levels)) { + this.expandLevels(node.nodes, options.levels-1, options); + } + }, this)); + this.render(); }; @@ -740,20 +776,17 @@ /** Reveals a given tree node, expanding the tree from node to root. - @param {Object|Number|Array} identifier - A valid node, node id or array of node identifiers + @param {Object|Number|Array} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.revealNode = function (identifier, options) { + Tree.prototype.revealNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - if (!(identifier instanceof Array)) { - identifier = [identifier]; + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; } - // Iterate nodes - $.each(identifier, $.proxy(function (index, identifier) { - - // Traverse the tree expanding parents from node to root + $.each(identifiers, $.proxy(function (index, identifier) { var parentNode = this.getParent(identifier); while (parentNode) { this.setExpandedState(parentNode, true, options); @@ -766,14 +799,25 @@ /** Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.toggleNodeExpanded = function (identifier, options) { + Tree.prototype.toggleNodeExpanded = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.toggleExpandedState(this.identifyNode(identifier), options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleExpandedState(this.identifyNode(identifier), options); + }, this)); }; + + /* + Identifies a node from either a node id or object + */ Tree.prototype.identifyNode = function (identifier) { return ((typeof identifier) === 'number') ? this.nodes[identifier] : diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 6b5416f4f..d2374e8dc 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -634,34 +634,57 @@ /** Set a node state to selected - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.selectNode = function (identifier, options) { + Tree.prototype.selectNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setSelectedState(this.identifyNode(identifier), true, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setSelectedState(this.identifyNode(identifier), true, options); + }, this)); + this.render(); }; /** Set a node state to unselected - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.unselectNode = function (identifier, options) { + Tree.prototype.unselectNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setSelectedState(this.identifyNode(identifier), false, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setSelectedState(this.identifyNode(identifier), false, options); + }, this)); + this.render(); }; /** Toggles a node selected state; selecting if unselected, unselecting if selected. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.toggleNodeSelected = function (identifier, options) { + Tree.prototype.toggleNodeSelected = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.toggleSelectedState(this.identifyNode(identifier), options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleSelectedState(this.identifyNode(identifier), options); + }, this)); }; @@ -681,12 +704,20 @@ /** Collapse a given tree node - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.collapseNode = function (identifier, options) { + Tree.prototype.collapseNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.setExpandedState(this.identifyNode(identifier), false, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setExpandedState(this.identifyNode(identifier), false, options); + }, this)); + this.render(); }; @@ -711,19 +742,24 @@ /** Expand a given tree node - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.expandNode = function (identifier, options) { + Tree.prototype.expandNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - var node = this.identifyNode(identifier); - this.setExpandedState(node, true, options); - - if (node.nodes && (options && options.levels)) { - this.expandLevels(node.nodes, options.levels-1, options); + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; } + $.each(identifiers, $.proxy(function (index, identifier) { + var node = this.identifyNode(identifier); + this.setExpandedState(node, true, options); + if (node.nodes && (options && options.levels)) { + this.expandLevels(node.nodes, options.levels-1, options); + } + }, this)); + this.render(); }; @@ -740,20 +776,17 @@ /** Reveals a given tree node, expanding the tree from node to root. - @param {Object|Number|Array} identifier - A valid node, node id or array of node identifiers + @param {Object|Number|Array} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.revealNode = function (identifier, options) { + Tree.prototype.revealNode = function (identifiers, options) { options = $.extend({}, _default.options, options); - if (!(identifier instanceof Array)) { - identifier = [identifier]; + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; } - // Iterate nodes - $.each(identifier, $.proxy(function (index, identifier) { - - // Traverse the tree expanding parents from node to root + $.each(identifiers, $.proxy(function (index, identifier) { var parentNode = this.getParent(identifier); while (parentNode) { this.setExpandedState(parentNode, true, options); @@ -766,14 +799,25 @@ /** Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. - @param {Object|Number} identifier - A valid node or node id + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ - Tree.prototype.toggleNodeExpanded = function (identifier, options) { + Tree.prototype.toggleNodeExpanded = function (identifiers, options) { options = $.extend({}, _default.options, options); - this.toggleExpandedState(this.identifyNode(identifier), options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleExpandedState(this.identifyNode(identifier), options); + }, this)); }; + + /* + Identifies a node from either a node id or object + */ Tree.prototype.identifyNode = function (identifier) { return ((typeof identifier) === 'number') ? this.nodes[identifier] : From 62e2b307fa18dd2dfd4c2cd9c93355ba701fd71d Mon Sep 17 00:00:00 2001 From: jperkelens Date: Fri, 17 Apr 2015 16:08:53 -0400 Subject: [PATCH 17/36] Adds support for selectedIcon --- README.md | 11 +++++++++++ src/js/bootstrap-treeview.js | 18 ++++++++++++++---- tests/tests.js | 9 ++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c72ffa93f..9c75f8458 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ If you want to do more, here's the full node specification { text: "Node 1", icon: "glyphicon glyphicon-stop", + selectedIcon: "glyphicon glyphicon-stop", color: "#000000", backColor: "#FFFFFF", href: "#node-1", @@ -159,6 +160,11 @@ For simplicity we directly leverage [Bootstraps Glyphicons support](http://getbo By providing the base class you retain full control over the icons used. If you want to use your own then just add your class to this icon field. +#### selectedIcon +`String` `Optional` + +The icon displayed on a given node when selected, typically to the left of the text. + #### color `String` `Optional` @@ -290,6 +296,11 @@ String, class name(s). Default: "glyphicon glyphicon-stop" as defined by [Boots Sets the default icon to be used on all nodes, except when overridden on a per node basis in data. +#### selectedIcon +String, class name(s). Default: "glyphicon glyphicon-stop" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) + +Sets the default icon to be used on all selected nodes, except when overridden on a per node basis in data. + #### onhoverColor String, [any legal color value](http://www.w3schools.com/cssref/css_colors_legal.asp). Default: '#F5F5F5'. diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index bdda5bc03..e5ba09bec 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -35,6 +35,7 @@ collapseIcon: 'glyphicon glyphicon-minus', emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-stop', + selectedIcon: 'glyphicon glyphicon-stop', color: undefined, // '#000000', backColor: undefined, // '#FFFFFF', @@ -414,10 +415,19 @@ } // Add node icon - treeItem - .append($(_this.template.icon) - .addClass(node.icon ? node.icon : _this.options.nodeIcon) - ); + var selected = node.state.selected + if (selected) { + treeItem + .append($(_this.template.icon) + .addClass(node.selectedIcon ? (node.selectedIcon || node.icon) : _this.options.selectedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass(node.icon ? node.icon : _this.options.nodeIcon) + ); + } // Add text if (_this.options.enableLinks) { diff --git a/tests/tests.js b/tests/tests.js index ece522cef..3a434a3b7 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -92,6 +92,7 @@ equal(options.collapseIcon, 'glyphicon glyphicon-minus', 'collapseIcon default ok'); equal(options.emptyIcon, 'glyphicon', 'emptyIcon default ok'); equal(options.nodeIcon, 'glyphicon glyphicon-stop', 'nodeIcon default ok'); + equal(options.selectedIcon, 'glyphicon glyphicon-stop', 'selectedIcon default ok'); equal(options.color, undefined, 'color default ok'); equal(options.backColor, undefined, 'backColor default ok'); equal(options.borderColor, undefined, 'borderColor default ok'); @@ -120,6 +121,7 @@ collapseIcon: 'glyphicon glyphicon-collapse', emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-node', + selectedIcon: 'glyphicon glyphicon-selected', color: 'yellow', backColor: 'purple', borderColor: 'purple', @@ -149,6 +151,7 @@ equal(options.collapseIcon, 'glyphicon glyphicon-collapse', 'collapseIcon set ok'); equal(options.emptyIcon, 'glyphicon', 'emptyIcon set ok'); equal(options.nodeIcon, 'glyphicon glyphicon-node', 'nodeIcon set ok'); + equal(options.selectedIcon, 'glyphicon glyphicon-selected', 'selectedIcon set ok'); equal(options.color, 'yellow', 'color set ok'); equal(options.backColor, 'purple', 'backColor set ok'); equal(options.borderColor, 'purple', 'borderColor set ok'); @@ -413,7 +416,7 @@ }); test('selectNode / unselectNode', function () { - var $tree = init({ data: data }); + var $tree = init({ data: data, selectedIcon: 'glyphicon glyphicon-selected' }); var el; var nodeId = 0; var node = $tree.treeview('getNode', 0); @@ -422,24 +425,28 @@ $tree.treeview('selectNode', nodeId); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by id) : Node is selected'); + ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-selected'), 'Select node (by id) : Node icon is correct'); ok(($('.node-selected').length === 1), 'Select node (by id) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', nodeId); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by id) : Node is no longer selected'); + ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-stop'), 'Select node (by id) : Node icon is correct'); ok(($('.node-selected').length === 0), 'Select node (by id) : There are no selected nodes'); // Select node using node $tree.treeview('selectNode', node); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by node) : Node is selected'); + ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-selected'), 'Select node (by node) : Node icon is correct'); ok(($('.node-selected').length === 1), 'Select node (by node) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', node); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by node) : Node is no longer selected'); + ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-stop'), 'Select node (by node) : Node icon is correct'); ok(($('.node-selected').length === 0), 'Select node (by node) : There are no selected nodes'); }); From 66edb9511143b6a2fa58a8e5f3ae7e7be8b44d71 Mon Sep 17 00:00:00 2001 From: jperkelens Date: Fri, 17 Apr 2015 16:18:43 -0400 Subject: [PATCH 18/36] Distro --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 18 ++++++++++++++---- tests/lib/bootstrap-treeview.js | 18 ++++++++++++++---- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index eb0293de6..d9f8afda3 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=cg;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                        ',item:'
                                      • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(a,b){var c=this.isSilent(b);this.setSelectedState(this.identifyNode(a),!0,c),this.render()},g.prototype.unselectNode=function(a,b){var c=this.isSilent(b);this.setSelectedState(this.identifyNode(a),!1,c),this.render()},g.prototype.toggleNodeSelected=function(a,b){this.toggleSelectedState(this.identifyNode(a),this.isSilent(b))},g.prototype.collapseAll=function(b){var c=this.isSilent(b);a.each(this.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,c)},this)),this.render()},g.prototype.collapseNode=function(a,b){var c=this.isSilent(b);this.setExpandedState(this.identifyNode(a),!1,c),this.render()},g.prototype.expandAll=function(b){var c=this.isSilent(b);b&&b.levels?this.expandLevels(this.tree,b.levels,c):a.each(this.nodes,a.proxy(function(a,b){this.setExpandedState(b,!0,c)},this)),this.render()},g.prototype.expandNode=function(a,b){var c=this.isSilent(b),d=this.identifyNode(a);this.setExpandedState(d,!0,c),d.nodes&&b&&b.levels&&this.expandLevels(d.nodes,b.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(a,b){this.toggleExpandedState(this.identifyNode(a),this.isSilent(b))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.isSilent=function(a){return a&&a.hasOwnProperty("silent")?a.silent:!1},g.prototype.search=function(b,c){this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(cg;g++)f.append(d.template.indent);f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon));var h=e.state.selected;return f.append(h?a(d.template.icon).addClass(e.selectedIcon?e.selectedIcon:d.options.selectedIcon):a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                          ',item:'
                                        • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.selectNode=function(a,b){var c=this.isSilent(b);this.setSelectedState(this.identifyNode(a),!0,c),this.render()},g.prototype.unselectNode=function(a,b){var c=this.isSilent(b);this.setSelectedState(this.identifyNode(a),!1,c),this.render()},g.prototype.toggleNodeSelected=function(a,b){this.toggleSelectedState(this.identifyNode(a),this.isSilent(b))},g.prototype.collapseAll=function(b){var c=this.isSilent(b);a.each(this.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,c)},this)),this.render()},g.prototype.collapseNode=function(a,b){var c=this.isSilent(b);this.setExpandedState(this.identifyNode(a),!1,c),this.render()},g.prototype.expandAll=function(b){var c=this.isSilent(b);b&&b.levels?this.expandLevels(this.tree,b.levels,c):a.each(this.nodes,a.proxy(function(a,b){this.setExpandedState(b,!0,c)},this)),this.render()},g.prototype.expandNode=function(a,b){var c=this.isSilent(b),d=this.identifyNode(a);this.setExpandedState(d,!0,c),d.nodes&&b&&b.levels&&this.expandLevels(d.nodes,b.levels-1,c),this.render()},g.prototype.expandLevels=function(b,c,d){a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.toggleNodeExpanded=function(a,b){this.toggleExpandedState(this.identifyNode(a),this.isSilent(b))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.isSilent=function(a){return a&&a.hasOwnProperty("silent")?a.silent:!1},g.prototype.search=function(b,c){this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index bdda5bc03..cf1c79b69 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -35,6 +35,7 @@ collapseIcon: 'glyphicon glyphicon-minus', emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-stop', + selectedIcon: 'glyphicon glyphicon-stop', color: undefined, // '#000000', backColor: undefined, // '#FFFFFF', @@ -414,10 +415,19 @@ } // Add node icon - treeItem - .append($(_this.template.icon) - .addClass(node.icon ? node.icon : _this.options.nodeIcon) - ); + var selected = node.state.selected + if (selected) { + treeItem + .append($(_this.template.icon) + .addClass(node.selectedIcon ? node.selectedIcon : _this.options.selectedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass(node.icon ? node.icon : _this.options.nodeIcon) + ); + } // Add text if (_this.options.enableLinks) { diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index bdda5bc03..cf1c79b69 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -35,6 +35,7 @@ collapseIcon: 'glyphicon glyphicon-minus', emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-stop', + selectedIcon: 'glyphicon glyphicon-stop', color: undefined, // '#000000', backColor: undefined, // '#FFFFFF', @@ -414,10 +415,19 @@ } // Add node icon - treeItem - .append($(_this.template.icon) - .addClass(node.icon ? node.icon : _this.options.nodeIcon) - ); + var selected = node.state.selected + if (selected) { + treeItem + .append($(_this.template.icon) + .addClass(node.selectedIcon ? node.selectedIcon : _this.options.selectedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass(node.icon ? node.icon : _this.options.nodeIcon) + ); + } // Add text if (_this.options.enableLinks) { From ba912688250087882807fbf9eb47a4ba65313ad8 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Tue, 21 Apr 2015 12:40:48 +0100 Subject: [PATCH 19/36] Change log updated --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fc715dda..a7a159636 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## v1.2.0 - [Unreleased] ### New Features +- New option selectedIcon to support displaying different icons when node is selected. - New search option `{ revealResults : true | false }` which when set to true will automatically expand the tree view to reveal matching nodes - New method `revealNode` which expands the tree view to reveal a given node - New methods `getSelected`, `getUnselected`, `getExpanded` and `getCollapsed` to retrieve nodes by state From 8b889910c756d822bc6b9f24085f9a33fe7987cc Mon Sep 17 00:00:00 2001 From: jonmiles Date: Tue, 21 Apr 2015 12:57:35 +0100 Subject: [PATCH 20/36] Change log updated --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7a159636..38292cacb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## v1.2.0 - [Unreleased] ### New Features -- New option selectedIcon to support displaying different icons when node is selected. +- New option + node property `selectedIcon` to support displaying different icons when a node is selected. - New search option `{ revealResults : true | false }` which when set to true will automatically expand the tree view to reveal matching nodes - New method `revealNode` which expands the tree view to reveal a given node - New methods `getSelected`, `getUnselected`, `getExpanded` and `getCollapsed` to retrieve nodes by state From 8219ac2e3fc3bb97c09dd449bbc9c94a1bcd9635 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Tue, 21 Apr 2015 14:36:23 +0100 Subject: [PATCH 21/36] Tweaked selectedIcon logic It should not revert to nodeIcon when node.selectedIcon does not exist, before checking options.selectedIcon. I've also updated it so that it's either the selected icon or node icon, which should always fall back to a valid icon unless the user specifically removes either icons from configuration. --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 7 +++---- src/js/bootstrap-treeview.js | 7 +++---- tests/lib/bootstrap-treeview.js | 7 +++---- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 6a6f91ca1..12dae2174 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon));var h=e.state.selected;return f.append(h?a(d.template.icon).addClass(e.selectedIcon?e.selectedIcon||e.icon:d.options.selectedIcon):a(d.template.icon).addClass(e.icon?e.icon:d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                            ',item:'
                                          • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(e.state.selected?a(d.template.icon).addClass(e.selectedIcon||d.options.selectedIcon):a(d.template.icon).addClass(e.icon||d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                              ',item:'
                                            • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index de8f7c41e..a6f0645be 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -446,17 +446,16 @@ } // Add node icon - var selected = node.state.selected - if (selected) { + if (node.state.selected) { treeItem .append($(_this.template.icon) - .addClass(node.selectedIcon ? (node.selectedIcon || node.icon) : _this.options.selectedIcon) + .addClass(node.selectedIcon || _this.options.selectedIcon) ); } else { treeItem .append($(_this.template.icon) - .addClass(node.icon ? node.icon : _this.options.nodeIcon) + .addClass(node.icon || _this.options.nodeIcon) ); } diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index de8f7c41e..a6f0645be 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -446,17 +446,16 @@ } // Add node icon - var selected = node.state.selected - if (selected) { + if (node.state.selected) { treeItem .append($(_this.template.icon) - .addClass(node.selectedIcon ? (node.selectedIcon || node.icon) : _this.options.selectedIcon) + .addClass(node.selectedIcon || _this.options.selectedIcon) ); } else { treeItem .append($(_this.template.icon) - .addClass(node.icon ? node.icon : _this.options.nodeIcon) + .addClass(node.icon || _this.options.nodeIcon) ); } diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index de8f7c41e..a6f0645be 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -446,17 +446,16 @@ } // Add node icon - var selected = node.state.selected - if (selected) { + if (node.state.selected) { treeItem .append($(_this.template.icon) - .addClass(node.selectedIcon ? (node.selectedIcon || node.icon) : _this.options.selectedIcon) + .addClass(node.selectedIcon || _this.options.selectedIcon) ); } else { treeItem .append($(_this.template.icon) - .addClass(node.icon ? node.icon : _this.options.nodeIcon) + .addClass(node.icon || _this.options.nodeIcon) ); } From bdb8194d2fa5b33bc72a872ee14f6d6bbfc11236 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 2 May 2015 17:59:31 +0100 Subject: [PATCH 22/36] Initial idea prototyped. - Using glyphicons for checked, unchecked state rather than an actual checkbox. Glyphicons scale and fit better with the bootstrap theme. - Tweaked css and icon classses used for better formatting. --- dist/bootstrap-treeview.min.css | 2 +- dist/bootstrap-treeview.min.js | 2 +- public/css/bootstrap-treeview.css | 7 +-- public/js/bootstrap-treeview.js | 79 ++++++++++++++++++++++++++----- src/css/bootstrap-treeview.css | 7 +-- src/js/bootstrap-treeview.js | 79 ++++++++++++++++++++++++++----- tests/lib/bootstrap-treeview.css | 7 +-- tests/lib/bootstrap-treeview.js | 79 ++++++++++++++++++++++++++----- tests/tests.js | 8 ++-- 9 files changed, 213 insertions(+), 57 deletions(-) diff --git a/dist/bootstrap-treeview.min.css b/dist/bootstrap-treeview.min.css index a1205eac2..dc46c218e 100644 --- a/dist/bootstrap-treeview.min.css +++ b/dist/bootstrap-treeview.min.css @@ -1 +1 @@ -.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px} \ No newline at end of file +.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px} \ No newline at end of file diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 12dae2174..9d4924c73 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(b.state.expanded=c0?!0:!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!=d.indexOf("click-expand")||-1!=d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.expandCollapseIcon).addClass("click-collapse").addClass(d.options.collapseIcon):a(d.template.expandCollapseIcon).addClass("click-expand").addClass(d.options.expandIcon):a(d.template.expandCollapseIcon).addClass(d.options.emptyIcon)),f.append(e.state.selected?a(d.template.icon).addClass(e.selectedIcon||d.options.selectedIcon):a(d.template.icon).addClass(e.icon||d.options.nodeIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                ',item:'
                                              • ',indent:'',expandCollapseIcon:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("click-expand")||-1!==d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("node-checked")||-1!==d.indexOf("node-unchecked")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(a,b,c){b!==a.state.checked&&(b?a.state.checked=!0:a.state.checked=!1)},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.icon).addClass("expand-collapse-icon click-collapse").addClass(d.options.collapseIcon):a(d.template.icon).addClass("expand-collapse-icon click-expand").addClass(d.options.expandIcon):a(d.template.icon).addClass(d.options.emptyIcon)),f.append(e.state.selected?a(d.template.icon).addClass("node-icon").addClass(e.selectedIcon||d.options.selectedIcon):a(d.template.icon).addClass("node-icon").addClass(e.icon||d.options.nodeIcon)),f.append(e.state.checked?a(d.template.icon).addClass("checked-icon node-checked").addClass(d.options.checkedIcon):a(d.template.icon).addClass("checked-icon node-unchecked").addClass(d.options.uncheckedIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                  ',item:'
                                                • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/css/bootstrap-treeview.css b/public/css/bootstrap-treeview.css index 863ab3f22..625912e17 100644 --- a/public/css/bootstrap-treeview.css +++ b/public/css/bootstrap-treeview.css @@ -26,12 +26,7 @@ margin-right: 10px; } -.treeview span.expand-collapse { - width: 1rem; - height: 1rem; -} - .treeview span.icon { - margin-left: 10px; + width: 12px; margin-right: 5px; } diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index a6f0645be..cc910c0e1 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -38,6 +38,8 @@ emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-stop', selectedIcon: 'glyphicon glyphicon-stop', + checkedIcon: 'glyphicon glyphicon-check', + uncheckedIcon: 'glyphicon glyphicon-unchecked', color: undefined, // '#000000', backColor: undefined, // '#FFFFFF', @@ -246,7 +248,7 @@ node.selectable = true; } - // where provided we shouuld preserve states + // where provided we should preserve states node.state = node.state || {}; // set expanded state; if not provided based on levels @@ -266,6 +268,11 @@ node.state.selected = false; } + // set checked state; unless set always false + if (!node.state.hasOwnProperty('checked')) { + node.state.checked = false; + } + // index nodes in a flattened structure for use later _this.nodes.push(node); @@ -284,10 +291,14 @@ var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - if ((classList.indexOf('click-expand') != -1) || - (classList.indexOf('click-collapse') != -1)) { + if ((classList.indexOf('click-expand') !== -1) || + (classList.indexOf('click-collapse') !== -1)) { this.toggleExpandedState(node, _default.options); } + else if ((classList.indexOf('node-checked') !== -1) || + (classList.indexOf('node-unchecked') !== -1)) { + this.toggleCheckedState(node, _default.options); + } else if (node) { if (node.selectable) { this.toggleSelectedState(node, _default.options); @@ -380,6 +391,34 @@ } }; + Tree.prototype.toggleCheckedState = function (node, options) { + if (!node) return; + this.setCheckedState(node, !node.state.checked, options); + this.render(); + }; + + Tree.prototype.setCheckedState = function (node, state, options) { + + if (state === node.state.checked) return; + + if (state) { + + // Check node + node.state.checked = true; + // if (!options.silent) { + // this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + // } + } + else { + + // Uncheck node + node.state.checked = false; + // if (!options.silent) { + // this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + // } + } + }; + Tree.prototype.render = function () { if (!this.initialized) { @@ -412,7 +451,8 @@ var treeItem = $(_this.template.item) .addClass('node-' + _this.elementId) .addClass(node.state.selected ? 'node-selected' : '') - .addClass(node.searchResult ? 'search-result' : '') + .addClass(node.state.checked ? 'node-checked' : '') + .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -425,22 +465,22 @@ if (node.nodes) { if (!node.state.expanded) { treeItem - .append($(_this.template.expandCollapseIcon) - .addClass('click-expand') + .append($(_this.template.icon) + .addClass('expand-collapse-icon click-expand') .addClass(_this.options.expandIcon) ); } else { treeItem - .append($(_this.template.expandCollapseIcon) - .addClass('click-collapse') + .append($(_this.template.icon) + .addClass('expand-collapse-icon click-collapse') .addClass(_this.options.collapseIcon) ); } } else { treeItem - .append($(_this.template.expandCollapseIcon) + .append($(_this.template.icon) .addClass(_this.options.emptyIcon) ); } @@ -449,16 +489,34 @@ if (node.state.selected) { treeItem .append($(_this.template.icon) + .addClass('node-icon') .addClass(node.selectedIcon || _this.options.selectedIcon) ); } else { treeItem .append($(_this.template.icon) + .addClass('node-icon') .addClass(node.icon || _this.options.nodeIcon) ); } + // Add check / unchecked icon + if (node.state.checked) { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-checked') + .addClass(_this.options.checkedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-unchecked') + .addClass(_this.options.uncheckedIcon) + ); + } + // Add text if (_this.options.enableLinks) { // Add hyperlink @@ -566,13 +624,12 @@ list: '
                                                    ', item: '
                                                  • ', indent: '', - expandCollapseIcon: '', icon: '', link: '', badge: '' }; - Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}' + Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}' /** diff --git a/src/css/bootstrap-treeview.css b/src/css/bootstrap-treeview.css index 863ab3f22..625912e17 100644 --- a/src/css/bootstrap-treeview.css +++ b/src/css/bootstrap-treeview.css @@ -26,12 +26,7 @@ margin-right: 10px; } -.treeview span.expand-collapse { - width: 1rem; - height: 1rem; -} - .treeview span.icon { - margin-left: 10px; + width: 12px; margin-right: 5px; } diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index a6f0645be..cc910c0e1 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -38,6 +38,8 @@ emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-stop', selectedIcon: 'glyphicon glyphicon-stop', + checkedIcon: 'glyphicon glyphicon-check', + uncheckedIcon: 'glyphicon glyphicon-unchecked', color: undefined, // '#000000', backColor: undefined, // '#FFFFFF', @@ -246,7 +248,7 @@ node.selectable = true; } - // where provided we shouuld preserve states + // where provided we should preserve states node.state = node.state || {}; // set expanded state; if not provided based on levels @@ -266,6 +268,11 @@ node.state.selected = false; } + // set checked state; unless set always false + if (!node.state.hasOwnProperty('checked')) { + node.state.checked = false; + } + // index nodes in a flattened structure for use later _this.nodes.push(node); @@ -284,10 +291,14 @@ var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - if ((classList.indexOf('click-expand') != -1) || - (classList.indexOf('click-collapse') != -1)) { + if ((classList.indexOf('click-expand') !== -1) || + (classList.indexOf('click-collapse') !== -1)) { this.toggleExpandedState(node, _default.options); } + else if ((classList.indexOf('node-checked') !== -1) || + (classList.indexOf('node-unchecked') !== -1)) { + this.toggleCheckedState(node, _default.options); + } else if (node) { if (node.selectable) { this.toggleSelectedState(node, _default.options); @@ -380,6 +391,34 @@ } }; + Tree.prototype.toggleCheckedState = function (node, options) { + if (!node) return; + this.setCheckedState(node, !node.state.checked, options); + this.render(); + }; + + Tree.prototype.setCheckedState = function (node, state, options) { + + if (state === node.state.checked) return; + + if (state) { + + // Check node + node.state.checked = true; + // if (!options.silent) { + // this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + // } + } + else { + + // Uncheck node + node.state.checked = false; + // if (!options.silent) { + // this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + // } + } + }; + Tree.prototype.render = function () { if (!this.initialized) { @@ -412,7 +451,8 @@ var treeItem = $(_this.template.item) .addClass('node-' + _this.elementId) .addClass(node.state.selected ? 'node-selected' : '') - .addClass(node.searchResult ? 'search-result' : '') + .addClass(node.state.checked ? 'node-checked' : '') + .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -425,22 +465,22 @@ if (node.nodes) { if (!node.state.expanded) { treeItem - .append($(_this.template.expandCollapseIcon) - .addClass('click-expand') + .append($(_this.template.icon) + .addClass('expand-collapse-icon click-expand') .addClass(_this.options.expandIcon) ); } else { treeItem - .append($(_this.template.expandCollapseIcon) - .addClass('click-collapse') + .append($(_this.template.icon) + .addClass('expand-collapse-icon click-collapse') .addClass(_this.options.collapseIcon) ); } } else { treeItem - .append($(_this.template.expandCollapseIcon) + .append($(_this.template.icon) .addClass(_this.options.emptyIcon) ); } @@ -449,16 +489,34 @@ if (node.state.selected) { treeItem .append($(_this.template.icon) + .addClass('node-icon') .addClass(node.selectedIcon || _this.options.selectedIcon) ); } else { treeItem .append($(_this.template.icon) + .addClass('node-icon') .addClass(node.icon || _this.options.nodeIcon) ); } + // Add check / unchecked icon + if (node.state.checked) { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-checked') + .addClass(_this.options.checkedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-unchecked') + .addClass(_this.options.uncheckedIcon) + ); + } + // Add text if (_this.options.enableLinks) { // Add hyperlink @@ -566,13 +624,12 @@ list: '
                                                      ', item: '
                                                    • ', indent: '', - expandCollapseIcon: '', icon: '', link: '', badge: '' }; - Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}' + Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}' /** diff --git a/tests/lib/bootstrap-treeview.css b/tests/lib/bootstrap-treeview.css index 863ab3f22..625912e17 100644 --- a/tests/lib/bootstrap-treeview.css +++ b/tests/lib/bootstrap-treeview.css @@ -26,12 +26,7 @@ margin-right: 10px; } -.treeview span.expand-collapse { - width: 1rem; - height: 1rem; -} - .treeview span.icon { - margin-left: 10px; + width: 12px; margin-right: 5px; } diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index a6f0645be..cc910c0e1 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -38,6 +38,8 @@ emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-stop', selectedIcon: 'glyphicon glyphicon-stop', + checkedIcon: 'glyphicon glyphicon-check', + uncheckedIcon: 'glyphicon glyphicon-unchecked', color: undefined, // '#000000', backColor: undefined, // '#FFFFFF', @@ -246,7 +248,7 @@ node.selectable = true; } - // where provided we shouuld preserve states + // where provided we should preserve states node.state = node.state || {}; // set expanded state; if not provided based on levels @@ -266,6 +268,11 @@ node.state.selected = false; } + // set checked state; unless set always false + if (!node.state.hasOwnProperty('checked')) { + node.state.checked = false; + } + // index nodes in a flattened structure for use later _this.nodes.push(node); @@ -284,10 +291,14 @@ var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - if ((classList.indexOf('click-expand') != -1) || - (classList.indexOf('click-collapse') != -1)) { + if ((classList.indexOf('click-expand') !== -1) || + (classList.indexOf('click-collapse') !== -1)) { this.toggleExpandedState(node, _default.options); } + else if ((classList.indexOf('node-checked') !== -1) || + (classList.indexOf('node-unchecked') !== -1)) { + this.toggleCheckedState(node, _default.options); + } else if (node) { if (node.selectable) { this.toggleSelectedState(node, _default.options); @@ -380,6 +391,34 @@ } }; + Tree.prototype.toggleCheckedState = function (node, options) { + if (!node) return; + this.setCheckedState(node, !node.state.checked, options); + this.render(); + }; + + Tree.prototype.setCheckedState = function (node, state, options) { + + if (state === node.state.checked) return; + + if (state) { + + // Check node + node.state.checked = true; + // if (!options.silent) { + // this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + // } + } + else { + + // Uncheck node + node.state.checked = false; + // if (!options.silent) { + // this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + // } + } + }; + Tree.prototype.render = function () { if (!this.initialized) { @@ -412,7 +451,8 @@ var treeItem = $(_this.template.item) .addClass('node-' + _this.elementId) .addClass(node.state.selected ? 'node-selected' : '') - .addClass(node.searchResult ? 'search-result' : '') + .addClass(node.state.checked ? 'node-checked' : '') + .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -425,22 +465,22 @@ if (node.nodes) { if (!node.state.expanded) { treeItem - .append($(_this.template.expandCollapseIcon) - .addClass('click-expand') + .append($(_this.template.icon) + .addClass('expand-collapse-icon click-expand') .addClass(_this.options.expandIcon) ); } else { treeItem - .append($(_this.template.expandCollapseIcon) - .addClass('click-collapse') + .append($(_this.template.icon) + .addClass('expand-collapse-icon click-collapse') .addClass(_this.options.collapseIcon) ); } } else { treeItem - .append($(_this.template.expandCollapseIcon) + .append($(_this.template.icon) .addClass(_this.options.emptyIcon) ); } @@ -449,16 +489,34 @@ if (node.state.selected) { treeItem .append($(_this.template.icon) + .addClass('node-icon') .addClass(node.selectedIcon || _this.options.selectedIcon) ); } else { treeItem .append($(_this.template.icon) + .addClass('node-icon') .addClass(node.icon || _this.options.nodeIcon) ); } + // Add check / unchecked icon + if (node.state.checked) { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-checked') + .addClass(_this.options.checkedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-unchecked') + .addClass(_this.options.uncheckedIcon) + ); + } + // Add text if (_this.options.enableLinks) { // Add hyperlink @@ -566,13 +624,12 @@ list: '
                                                        ', item: '
                                                      • ', indent: '', - expandCollapseIcon: '', icon: '', link: '', badge: '' }; - Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.expand-collapse{width:1rem;height:1rem}.treeview span.icon{margin-left:10px;margin-right:5px}' + Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}' /** diff --git a/tests/tests.js b/tests/tests.js index 6c785569e..498c3a90b 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -466,28 +466,28 @@ $tree.treeview('selectNode', nodeId); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by id) : Node is selected'); - ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-selected'), 'Select node (by id) : Node icon is correct'); + ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-selected'), 'Select node (by id) : Node icon is correct'); ok(($('.node-selected').length === 1), 'Select node (by id) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', nodeId); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by id) : Node is no longer selected'); - ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-stop'), 'Select node (by id) : Node icon is correct'); + ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-stop'), 'Select node (by id) : Node icon is correct'); ok(($('.node-selected').length === 0), 'Select node (by id) : There are no selected nodes'); // Select node using node $tree.treeview('selectNode', node); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by node) : Node is selected'); - ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-selected'), 'Select node (by node) : Node icon is correct'); + ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-selected'), 'Select node (by node) : Node icon is correct'); ok(($('.node-selected').length === 1), 'Select node (by node) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', node); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by node) : Node is no longer selected'); - ok((el.find('.icon').attr('class') === 'icon glyphicon glyphicon-stop'), 'Select node (by node) : Node icon is correct'); + ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-stop'), 'Select node (by node) : Node icon is correct'); ok(($('.node-selected').length === 0), 'Select node (by node) : There are no selected nodes'); }); From af16fa6ab985cc0439b38ad368803ddf33155eeb Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 2 May 2015 18:02:51 +0100 Subject: [PATCH 23/36] Added events and show methods - Added nodeChecked / nodeUnchecked events - Added options showCheckbox to control when check boxes are displayed - Added option showIcon to control when icons are displayed --- README.md | 40 +++++++++--- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 112 ++++++++++++++++---------------- src/js/bootstrap-treeview.js | 112 ++++++++++++++++---------------- tests/lib/bootstrap-treeview.js | 112 ++++++++++++++++---------------- tests/tests.js | 91 ++++++++++++++++++++++++-- 6 files changed, 286 insertions(+), 183 deletions(-) diff --git a/README.md b/README.md index 4526cf8cc..d7c54c797 100644 --- a/README.md +++ b/README.md @@ -131,8 +131,9 @@ If you want to do more, here's the full node specification href: "#node-1", selectable: true, state: { - expanded: true, - selected: true + checked: true, + expanded: true, + selected: true }, tags: ['available'], nodes: [ @@ -187,9 +188,13 @@ Whether or not a node is selectable in the tree. False indicates the node should #### state `Object` `Optional` - Describes a node's initial state. +#### state.checked +`Boolean` `Default: false` + +Whether or not a node is checked, represented by a checkbox style glyphicon. + #### state.expanded `Boolean` `Default: false` @@ -246,6 +251,9 @@ String, [any legal color value](http://www.w3schools.com/cssref/css_colors_legal Sets the border color for the component; set showBorder to false if you don't want a visible border. +#### checkedIcon +String, class names(s). Default: "glyphicon glyphicon-check" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) + #### collapseIcon String, class name(s). Default: "glyphicon glyphicon-minus" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) @@ -296,16 +304,16 @@ String, class name(s). Default: "glyphicon glyphicon-stop" as defined by [Boots Sets the default icon to be used on all nodes, except when overridden on a per node basis in data. -#### selectedIcon -String, class name(s). Default: "glyphicon glyphicon-stop" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) - -Sets the default icon to be used on all selected nodes, except when overridden on a per node basis in data. - #### onhoverColor String, [any legal color value](http://www.w3schools.com/cssref/css_colors_legal.asp). Default: '#F5F5F5'. Sets the default background color activated when the users cursor hovers over a node. +#### selectedIcon +String, class name(s). Default: "glyphicon glyphicon-stop" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) + +Sets the default icon to be used on all selected nodes, except when overridden on a per node basis in data. + #### searchResultBackColor String, [any legal color value](http://www.w3schools.com/cssref/css_colors_legal.asp). Default: undefined, inherits. @@ -331,11 +339,23 @@ Boolean. Default: true Whether or not to display a border around nodes. +#### showCheckbox +Boolean. Default: false + +Whether or not to display a nodes checked icon. + +#### showIcon +Boolean. Default: true + +Whether or not to display a nodes icon. + #### showTags Boolean. Default: false Whether or not to display tags to the right of each node. The values of which must be provided in the data structure on a per node basis. +#### uncheckedIcon +String, class names(s). Default: "glyphicon glyphicon-unchecked" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) ## Methods @@ -581,12 +601,16 @@ $('#tree').on('nodeSelected', function(event, data) { ### List of Events +`nodeChecked (event, node)` - A node is checked. + `nodeCollapsed (event, node)` - A node is collapsed. `nodeExpanded (event, node)` - A node is expanded. `nodeSelected (event, node)` - A node is selected. +`nodeUnchecked (event, node)` - A node is unchecked. + `nodeUnselected (event, node)` - A node is unselected. `searchComplete (event, results)` - After a search completes diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 9d4924c73..1149b4135 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showTags:!1,multiSelect:!1,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),"function"==typeof this.options.onNodeCollapsed&&this.$element.off("nodeCollapsed"),"function"==typeof this.options.onNodeExpanded&&this.$element.off("nodeExpanded"),"function"==typeof this.options.onNodeSelected&&this.$element.off("nodeSelected"),"function"==typeof this.options.onNodeUnselected&&this.$element.off("nodeUnselected"),"function"==typeof this.options.onSearchComplete&&this.$element.off("searchComplete"),"function"==typeof this.options.onSearchCleared&&this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("click-expand")||-1!==d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("node-checked")||-1!==d.indexOf("node-unchecked")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(a,b,c){b!==a.state.checked&&(b?a.state.checked=!0:a.state.checked=!1)},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.icon).addClass("expand-collapse-icon click-collapse").addClass(d.options.collapseIcon):a(d.template.icon).addClass("expand-collapse-icon click-expand").addClass(d.options.expandIcon):a(d.template.icon).addClass(d.options.emptyIcon)),f.append(e.state.selected?a(d.template.icon).addClass("node-icon").addClass(e.selectedIcon||d.options.selectedIcon):a(d.template.icon).addClass("node-icon").addClass(e.icon||d.options.nodeIcon)),f.append(e.state.checked?a(d.template.icon).addClass("checked-icon node-checked").addClass(d.options.checkedIcon):a(d.template.icon).addClass("checked-icon node-unchecked").addClass(d.options.uncheckedIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                          ',item:'
                                                        • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("click-expand")||-1!==d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("node-checked")||-1!==d.indexOf("node-unchecked")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.icon).addClass("expand-collapse-icon click-collapse").addClass(d.options.collapseIcon):a(d.template.icon).addClass("expand-collapse-icon click-expand").addClass(d.options.expandIcon):a(d.template.icon).addClass(d.options.emptyIcon)),d.options.showIcon&&f.append(e.state.selected?a(d.template.icon).addClass("node-icon").addClass(e.selectedIcon||d.options.selectedIcon):a(d.template.icon).addClass("node-icon").addClass(e.icon||d.options.nodeIcon)),d.options.showCheckbox&&f.append(e.state.checked?a(d.template.icon).addClass("checked-icon node-checked").addClass(d.options.checkedIcon):a(d.template.icon).addClass("checked-icon node-unchecked").addClass(d.options.uncheckedIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                            ',item:'
                                                          • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index cc910c0e1..b06b920d1 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -54,13 +54,17 @@ highlightSelected: true, highlightSearchResults: true, showBorder: true, + showIcon: true, + showCheckbox: false, showTags: false, multiSelect: false, // Event handlers + onNodeChecked: undefined, onNodeCollapsed: undefined, onNodeExpanded: undefined, onNodeSelected: undefined, + onNodeUnchecked: undefined, onNodeUnselected: undefined, onSearchComplete: undefined, onSearchCleared: undefined @@ -165,30 +169,14 @@ Tree.prototype.unsubscribeEvents = function () { this.$element.off('click'); - - if (typeof (this.options.onNodeCollapsed) === 'function') { - this.$element.off('nodeCollapsed'); - } - - if (typeof (this.options.onNodeExpanded) === 'function') { - this.$element.off('nodeExpanded'); - } - - if (typeof (this.options.onNodeSelected) === 'function') { - this.$element.off('nodeSelected'); - } - - if (typeof (this.options.onNodeUnselected) === 'function') { - this.$element.off('nodeUnselected'); - } - - if (typeof (this.options.onSearchComplete) === 'function') { - this.$element.off('searchComplete'); - } - - if (typeof (this.options.onSearchCleared) === 'function') { - this.$element.off('searchCleared'); - } + this.$element.off('nodeChecked'); + this.$element.off('nodeCollapsed'); + this.$element.off('nodeExpanded'); + this.$element.off('nodeSelected'); + this.$element.off('nodeUnchecked'); + this.$element.off('nodeUnselected'); + this.$element.off('searchComplete'); + this.$element.off('searchCleared'); }; Tree.prototype.subscribeEvents = function () { @@ -197,6 +185,10 @@ 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); } @@ -209,6 +201,10 @@ 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); } @@ -405,17 +401,17 @@ // Check node node.state.checked = true; - // if (!options.silent) { - // this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); - // } + if (!options.silent) { + this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + } } else { // Uncheck node node.state.checked = false; - // if (!options.silent) { - // this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); - // } + if (!options.silent) { + this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + } } }; @@ -486,35 +482,39 @@ } // Add node icon - if (node.state.selected) { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.selectedIcon || _this.options.selectedIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.icon || _this.options.nodeIcon) - ); + if (_this.options.showIcon) { + if (node.state.selected) { + treeItem + .append($(_this.template.icon) + .addClass('node-icon') + .addClass(node.selectedIcon || _this.options.selectedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('node-icon') + .addClass(node.icon || _this.options.nodeIcon) + ); + } } // Add check / unchecked icon - if (node.state.checked) { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-checked') - .addClass(_this.options.checkedIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-unchecked') - .addClass(_this.options.uncheckedIcon) - ); + if (_this.options.showCheckbox) { + if (node.state.checked) { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-checked') + .addClass(_this.options.checkedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-unchecked') + .addClass(_this.options.uncheckedIcon) + ); + } } // Add text diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index cc910c0e1..b06b920d1 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -54,13 +54,17 @@ highlightSelected: true, highlightSearchResults: true, showBorder: true, + showIcon: true, + showCheckbox: false, showTags: false, multiSelect: false, // Event handlers + onNodeChecked: undefined, onNodeCollapsed: undefined, onNodeExpanded: undefined, onNodeSelected: undefined, + onNodeUnchecked: undefined, onNodeUnselected: undefined, onSearchComplete: undefined, onSearchCleared: undefined @@ -165,30 +169,14 @@ Tree.prototype.unsubscribeEvents = function () { this.$element.off('click'); - - if (typeof (this.options.onNodeCollapsed) === 'function') { - this.$element.off('nodeCollapsed'); - } - - if (typeof (this.options.onNodeExpanded) === 'function') { - this.$element.off('nodeExpanded'); - } - - if (typeof (this.options.onNodeSelected) === 'function') { - this.$element.off('nodeSelected'); - } - - if (typeof (this.options.onNodeUnselected) === 'function') { - this.$element.off('nodeUnselected'); - } - - if (typeof (this.options.onSearchComplete) === 'function') { - this.$element.off('searchComplete'); - } - - if (typeof (this.options.onSearchCleared) === 'function') { - this.$element.off('searchCleared'); - } + this.$element.off('nodeChecked'); + this.$element.off('nodeCollapsed'); + this.$element.off('nodeExpanded'); + this.$element.off('nodeSelected'); + this.$element.off('nodeUnchecked'); + this.$element.off('nodeUnselected'); + this.$element.off('searchComplete'); + this.$element.off('searchCleared'); }; Tree.prototype.subscribeEvents = function () { @@ -197,6 +185,10 @@ 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); } @@ -209,6 +201,10 @@ 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); } @@ -405,17 +401,17 @@ // Check node node.state.checked = true; - // if (!options.silent) { - // this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); - // } + if (!options.silent) { + this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + } } else { // Uncheck node node.state.checked = false; - // if (!options.silent) { - // this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); - // } + if (!options.silent) { + this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + } } }; @@ -486,35 +482,39 @@ } // Add node icon - if (node.state.selected) { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.selectedIcon || _this.options.selectedIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.icon || _this.options.nodeIcon) - ); + if (_this.options.showIcon) { + if (node.state.selected) { + treeItem + .append($(_this.template.icon) + .addClass('node-icon') + .addClass(node.selectedIcon || _this.options.selectedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('node-icon') + .addClass(node.icon || _this.options.nodeIcon) + ); + } } // Add check / unchecked icon - if (node.state.checked) { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-checked') - .addClass(_this.options.checkedIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-unchecked') - .addClass(_this.options.uncheckedIcon) - ); + if (_this.options.showCheckbox) { + if (node.state.checked) { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-checked') + .addClass(_this.options.checkedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-unchecked') + .addClass(_this.options.uncheckedIcon) + ); + } } // Add text diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index cc910c0e1..b06b920d1 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -54,13 +54,17 @@ highlightSelected: true, highlightSearchResults: true, showBorder: true, + showIcon: true, + showCheckbox: false, showTags: false, multiSelect: false, // Event handlers + onNodeChecked: undefined, onNodeCollapsed: undefined, onNodeExpanded: undefined, onNodeSelected: undefined, + onNodeUnchecked: undefined, onNodeUnselected: undefined, onSearchComplete: undefined, onSearchCleared: undefined @@ -165,30 +169,14 @@ Tree.prototype.unsubscribeEvents = function () { this.$element.off('click'); - - if (typeof (this.options.onNodeCollapsed) === 'function') { - this.$element.off('nodeCollapsed'); - } - - if (typeof (this.options.onNodeExpanded) === 'function') { - this.$element.off('nodeExpanded'); - } - - if (typeof (this.options.onNodeSelected) === 'function') { - this.$element.off('nodeSelected'); - } - - if (typeof (this.options.onNodeUnselected) === 'function') { - this.$element.off('nodeUnselected'); - } - - if (typeof (this.options.onSearchComplete) === 'function') { - this.$element.off('searchComplete'); - } - - if (typeof (this.options.onSearchCleared) === 'function') { - this.$element.off('searchCleared'); - } + this.$element.off('nodeChecked'); + this.$element.off('nodeCollapsed'); + this.$element.off('nodeExpanded'); + this.$element.off('nodeSelected'); + this.$element.off('nodeUnchecked'); + this.$element.off('nodeUnselected'); + this.$element.off('searchComplete'); + this.$element.off('searchCleared'); }; Tree.prototype.subscribeEvents = function () { @@ -197,6 +185,10 @@ 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); } @@ -209,6 +201,10 @@ 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); } @@ -405,17 +401,17 @@ // Check node node.state.checked = true; - // if (!options.silent) { - // this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); - // } + if (!options.silent) { + this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + } } else { // Uncheck node node.state.checked = false; - // if (!options.silent) { - // this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); - // } + if (!options.silent) { + this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + } } }; @@ -486,35 +482,39 @@ } // Add node icon - if (node.state.selected) { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.selectedIcon || _this.options.selectedIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.icon || _this.options.nodeIcon) - ); + if (_this.options.showIcon) { + if (node.state.selected) { + treeItem + .append($(_this.template.icon) + .addClass('node-icon') + .addClass(node.selectedIcon || _this.options.selectedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('node-icon') + .addClass(node.icon || _this.options.nodeIcon) + ); + } } // Add check / unchecked icon - if (node.state.checked) { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-checked') - .addClass(_this.options.checkedIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-unchecked') - .addClass(_this.options.uncheckedIcon) - ); + if (_this.options.showCheckbox) { + if (node.state.checked) { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-checked') + .addClass(_this.options.checkedIcon) + ); + } + else { + treeItem + .append($(_this.template.icon) + .addClass('checked-icon node-unchecked') + .addClass(_this.options.uncheckedIcon) + ); + } } // Add text diff --git a/tests/tests.js b/tests/tests.js index 498c3a90b..b8cd67fb2 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -93,6 +93,8 @@ equal(options.emptyIcon, 'glyphicon', 'emptyIcon default ok'); equal(options.nodeIcon, 'glyphicon glyphicon-stop', 'nodeIcon default ok'); equal(options.selectedIcon, 'glyphicon glyphicon-stop', 'selectedIcon default ok'); + equal(options.checkedIcon, 'glyphicon glyphicon-check', 'checkedIcon default ok'); + equal(options.uncheckedIcon, 'glyphicon glyphicon-unchecked', 'uncheckedIcon default ok'); equal(options.color, undefined, 'color default ok'); equal(options.backColor, undefined, 'backColor default ok'); equal(options.borderColor, undefined, 'borderColor default ok'); @@ -105,11 +107,15 @@ equal(options.highlightSelected, true, 'highlightSelected default ok'); equal(options.highlightSearchResults, true, 'highlightSearchResults default ok'); equal(options.showBorder, true, 'showBorder default ok'); + equal(options.showIcon, true, 'showIcon default ok'); + equal(options.showCheckbox, false, 'showCheckbox default ok'); equal(options.showTags, false, 'showTags default ok'); equal(options.multiSelect, false, 'multiSelect default ok'); + equal(options.onNodeChecked, null, 'onNodeChecked default ok'); equal(options.onNodeCollapsed, null, 'onNodeCollapsed default ok'); equal(options.onNodeExpanded, null, 'onNodeExpanded default ok'); equal(options.onNodeSelected, null, 'onNodeSelected default ok'); + equal(options.onNodeUnchecked, null, 'onNodeUnchecked default ok'); equal(options.onNodeUnselected, null, 'onNodeUnselected default ok'); equal(options.onSearchComplete, null, 'onSearchComplete default ok'); equal(options.onSearchCleared, null, 'onSearchCleared default ok'); @@ -122,6 +128,8 @@ emptyIcon: 'glyphicon', nodeIcon: 'glyphicon glyphicon-node', selectedIcon: 'glyphicon glyphicon-selected', + checkedIcon: 'glyphicon glyphicon-checked-icon', + uncheckedIcon: 'glyphicon glyphicon-unchecked-icon', color: 'yellow', backColor: 'purple', borderColor: 'purple', @@ -134,11 +142,15 @@ highlightSelected: false, highlightSearchResults: true, showBorder: false, + showIcon: false, + showCheckbox: true, showTags: true, multiSelect: true, + onNodeChecked: function () {}, onNodeCollapsed: function () {}, onNodeExpanded: function () {}, onNodeSelected: function () {}, + onNodeUnchecked: function () {}, onNodeUnselected: function () {}, onSearchComplete: function () {}, onSearchCleared: function () {} @@ -152,6 +164,8 @@ equal(options.emptyIcon, 'glyphicon', 'emptyIcon set ok'); equal(options.nodeIcon, 'glyphicon glyphicon-node', 'nodeIcon set ok'); equal(options.selectedIcon, 'glyphicon glyphicon-selected', 'selectedIcon set ok'); + equal(options.checkedIcon, 'glyphicon glyphicon-checked-icon', 'checkedIcon set ok'); + equal(options.uncheckedIcon, 'glyphicon glyphicon-unchecked-icon', 'uncheckedIcon set ok'); equal(options.color, 'yellow', 'color set ok'); equal(options.backColor, 'purple', 'backColor set ok'); equal(options.borderColor, 'purple', 'borderColor set ok'); @@ -164,11 +178,15 @@ equal(options.highlightSelected, false, 'highlightSelected set ok'); equal(options.highlightSearchResults, true, 'highlightSearchResults set ok'); equal(options.showBorder, false, 'showBorder set ok'); + equal(options.showIcon, false, 'showIcon set ok'); + equal(options.showCheckbox, true, 'showCheckbox set ok'); equal(options.showTags, true, 'showTags set ok'); equal(options.multiSelect, true, 'multiSelect set ok'); + equal(typeof options.onNodeChecked, 'function', 'onNodeChecked set ok'); equal(typeof options.onNodeCollapsed, 'function', 'onNodeCollapsed set ok'); equal(typeof options.onNodeExpanded, 'function', 'onNodeExpanded set ok'); equal(typeof options.onNodeSelected, 'function', 'onNodeSelected set ok'); + equal(typeof options.onNodeUnchecked, 'function', 'onNodeUnchecked set ok'); equal(typeof options.onNodeUnselected, 'function', 'onNodeUnselected set ok'); equal(typeof options.onSearchComplete, 'function', 'onSearchComplete set ok'); equal(typeof options.onSearchCleared, 'function', 'onSearchCleared set ok'); @@ -319,7 +337,7 @@ ok(onWorked, 'nodeUnselected was fired'); }); - test('Clicking a non-selectable, colllapsed node expands the node', function () { + test('Clicking a non-selectable, collapsed node expands the node', function () { var testData = $.extend(true, {}, data); testData[0].selectable = false; @@ -363,15 +381,76 @@ var nodeCount = $('.list-group-item').length; var el = $('.list-group-item:first'); - // console.log(el); el.trigger('click'); el = $('.list-group-item:first'); + ok(!el.hasClass('node-selected'), 'Node should not be selected'); ok(!cbCalled, 'onNodeSelected function should not be called'); ok(!onCalled, 'nodeSelected should not fire'); ok(($('.list-group-item').length < nodeCount), 'Number of nodes has decreased, so node must have collapsed'); }); + test('Checking a node', function () { + + // setup test + var cbWorked, onWorked = false; + var $tree = init({ + data: data, + showCheckbox: true, + onNodeChecked: function(/*event, date*/) { + cbWorked = true; + } + }) + .on('nodeChecked', function(/*event, date*/) { + onWorked = true; + }); + var options = getOptions($tree); + + // simulate click event on check icon + var $el = $('.checked-icon:first'); + $el.trigger('click'); + + // check state is correct + $el = $('.checked-icon:first'); + ok(($el.attr('class').split(' ').indexOf('node-checked') !== -1), 'Node is checked : class "node-checked" added'); + ok(($el.attr('class').indexOf(options.checkedIcon) !== -1), 'Node is checked : icon is correct'); + ok(cbWorked, 'onNodeChecked function was called'); + ok(onWorked, 'nodeChecked was fired'); + }); + + test('Unchecking a node', function () { + + // setup test + var cbWorked, onWorked = false; + var $tree = init({ + data: data, + showCheckbox: true, + onNodeUnchecked: function(/*event, date*/) { + cbWorked = true; + } + }) + .on('nodeUnchecked', function(/*event, date*/) { + onWorked = true; + }); + var options = getOptions($tree); + + // first check a node + var $el = $('.checked-icon:first'); + $el.trigger('click'); + + // then simulate unchecking a node + cbWorked = onWorked = false; + $el = $('.checked-icon:first'); + $el.trigger('click'); + + // check state is correct + $el = $('.checked-icon:first'); + ok(($el.attr('class').split(' ').indexOf('node-checked') === -1), 'Node is unchecked : class "node-checked" removed'); + ok(($el.attr('class').indexOf(options.uncheckedIcon) !== -1), 'Node is unchecked : icon is correct'); + ok(cbWorked, 'onNodeUnchecked function was called'); + ok(onWorked, 'nodeUnchecked was fired'); + }); + module('Methods'); @@ -466,28 +545,28 @@ $tree.treeview('selectNode', nodeId); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by id) : Node is selected'); - ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-selected'), 'Select node (by id) : Node icon is correct'); + ok((el.find('.node-icon').attr('class').indexOf('glyphicon glyphicon-selected') !== -1), 'Select node (by id) : Node icon is correct'); ok(($('.node-selected').length === 1), 'Select node (by id) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', nodeId); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by id) : Node is no longer selected'); - ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-stop'), 'Select node (by id) : Node icon is correct'); + ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Select node (by id) : Node icon is correct'); ok(($('.node-selected').length === 0), 'Select node (by id) : There are no selected nodes'); // Select node using node $tree.treeview('selectNode', node); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by node) : Node is selected'); - ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-selected'), 'Select node (by node) : Node icon is correct'); + ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-selected') !== -1), 'Select node (by node) : Node icon is correct'); ok(($('.node-selected').length === 1), 'Select node (by node) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', node); el = $('.list-group-item:first'); ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by node) : Node is no longer selected'); - ok((el.find('.node-icon').attr('class') === 'icon node-icon glyphicon glyphicon-stop'), 'Select node (by node) : Node icon is correct'); + ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Select node (by node) : Node icon is correct'); ok(($('.node-selected').length === 0), 'Select node (by node) : There are no selected nodes'); }); From f9ce9cfa25ec45f92bfa855a2f74f4b1b301f9d4 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 2 May 2015 20:17:40 +0100 Subject: [PATCH 24/36] Check / uncheck methods added --- README.md | 50 +++++++++ dist/bootstrap-treeview.min.js | 2 +- public/index.html | 83 ++++++++++++++ public/js/bootstrap-treeview.js | 188 +++++++++++++++++++++++++------- src/js/bootstrap-treeview.js | 188 +++++++++++++++++++++++++------- tests/lib/bootstrap-treeview.js | 188 +++++++++++++++++++++++++------- tests/tests.js | 111 ++++++++++++++++--- 7 files changed, 668 insertions(+), 142 deletions(-) diff --git a/README.md b/README.md index d7c54c797..73373e2ba 100644 --- a/README.md +++ b/README.md @@ -393,6 +393,26 @@ $('#tree').data('treeview') The following is a list of all available methods. +#### checkAll(options) + +Checks all tree nodes + +```javascript +$('#tree').treeview('checkAll', { silent: true }); +``` + +Triggers `nodeChecked` event; pass silent to suppress events. + +#### checkNode(node | nodeId, options) + +Checks a given tree node, accepts node or nodeId. + +```javascript +$('#tree').treeview('checkNode', [ nodeId, { silent: true } ]); +``` + +Triggers `nodeChecked` event; pass silent to suppress events. + #### clearSearch() Clear the tree view of any previous search results e.g. remove their highlighted state. @@ -543,6 +563,16 @@ $('#tree').treeview('selectNode', [ nodeId, { silent: true } ]); Triggers `nodeSelected` event; pass silent to suppress events. +#### toggleNodeChecked(node | nodeId, options) + +Toggles a nodes checked state; checking if unchecked, unchecking if checked. + +```javascript +$('#tree').treeview('toggleNodeChecked', [ nodeId, { silent: true } ]); +``` + +Triggers either `nodeChecked` or `nodeUnchecked` event; pass silent to suppress events. + #### toggleNodeExpanded(node | nodeId, options) Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. @@ -563,6 +593,26 @@ $('#tree').treeview('toggleNodeSelected', [ nodeId, { silent: true } ]); Triggers either `nodeSelected` or `nodeUnselected` event; pass silent to suppress events. +#### uncheckAll(options) + +Uncheck all tree nodes. + +```javascript +$('#tree').treeview('uncheckAll', { silent: true }); +``` + +Triggers `nodeUnchecked` event; pass silent to suppress events. + +#### uncheckNode(node | nodeId, options) + +Uncheck a given tree node, accepts node or nodeId. + +```javascript +$('#tree').treeview('uncheckNode', [ nodeId, { silent: true } ]); +``` + +Triggers `nodeUnchecked` event; pass silent to suppress events. + #### unselectNode(node | nodeId, options) Unselects a given tree node, accepts node or nodeId. diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 1149b4135..e9146fcd4 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("click-expand")||-1!==d.indexOf("click-collapse")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("node-checked")||-1!==d.indexOf("node-unchecked")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);return f.append(e.nodes?e.state.expanded?a(d.template.icon).addClass("expand-collapse-icon click-collapse").addClass(d.options.collapseIcon):a(d.template.icon).addClass("expand-collapse-icon click-expand").addClass(d.options.expandIcon):a(d.template.icon).addClass(d.options.emptyIcon)),d.options.showIcon&&f.append(e.state.selected?a(d.template.icon).addClass("node-icon").addClass(e.selectedIcon||d.options.selectedIcon):a(d.template.icon).addClass("node-icon").addClass(e.icon||d.options.nodeIcon)),d.options.showCheckbox&&f.append(e.state.checked?a(d.template.icon).addClass("checked-icon node-checked").addClass(d.options.checkedIcon):a(d.template.icon).addClass("checked-icon node-unchecked").addClass(d.options.uncheckedIcon)),f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                              ',item:'
                                                            • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("expand-icon")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("check-icon")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                ',item:'
                                                              • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.checkAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("false","g","state.checked"),a.proxy(function(a,c){this.setCheckedState(c,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setCheckedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.uncheckAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.checked"),a.proxy(function(a,c){this.setCheckedState(c,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setCheckedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleCheckedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/index.html b/public/index.html index fc58bd165..1a0c101f6 100644 --- a/public/index.html +++ b/public/index.html @@ -181,6 +181,43 @@

                                                                Events

                                                                +
                                                                +
                                                                +

                                                                Checkable Tree

                                                                +
                                                                +

                                                                Input

                                                                +
                                                                + + +
                                                                +
                                                                +
                                                                + +
                                                                +
                                                                +
                                                                + +
                                                                +
                                                                + +
                                                                +
                                                                +
                                                                +
                                                                + +
                                                                +
                                                                + +
                                                                +
                                                                +

                                                                Tree

                                                                +
                                                                +
                                                                +
                                                                +

                                                                Events

                                                                +
                                                                +
                                                                +

                                                                Data

                                                                @@ -542,6 +579,52 @@

                                                                + var $checkableTree = $('#treeview-checkable').treeview({ + data: defaultData, + showIcon: false, + showCheckbox: true, + onNodeChecked: function(event, node) { + $('#checkable-output').prepend('

                                                                ' + node.text + ' was checked

                                                                '); + }, + onNodeUnchecked: function (event, node) { + $('#checkable-output').prepend('

                                                                ' + node.text + ' was unchecked

                                                                '); + } + }); + + var findCheckableNode = function() { + return $checkableTree.treeview('search', [ $('#input-check-node').val(), { ignoreCase: false, exactMatch: true } ]); + }; + var checkableNode = findCheckableNode(); + + // Check/uncheck/toggle nodes + $('#input-check-node').on('keyup', function (e) { + checkableNode = findCheckableNode(); + $('.check-node').prop('disabled', !(checkableNode.length === 1)); + }); + + $('#btn-check-node.check-node').on('click', function (e) { + $checkableTree.treeview('checkNode', [ checkableNode[0], { } ]); + }); + + $('#btn-uncheck-node.check-node').on('click', function (e) { + $checkableTree.treeview('uncheckNode', checkableNode[0]); + }); + + $('#btn-toggle-checked.check-node').on('click', function (e) { + $checkableTree.treeview('toggleNodeChecked', checkableNode[0]); + }); + + // Check/uncheck all + $('#btn-check-all').on('click', function (e) { + $checkableTree.treeview('checkAll', { }); + }); + + $('#btn-uncheck-all').on('click', function (e) { + $checkableTree.treeview('uncheckAll'); + }); + + + var $tree = $('#treeview12').treeview({ data: json }); diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index b06b920d1..3c7d0dbc2 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -106,6 +106,8 @@ getUnselected: $.proxy(this.getUnselected, this), getExpanded: $.proxy(this.getExpanded, this), getCollapsed: $.proxy(this.getCollapsed, this), + getChecked: $.proxy(this.getChecked, this), + getUnchecked: $.proxy(this.getUnchecked, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -120,6 +122,13 @@ toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this), revealNode: $.proxy(this.revealNode, this), + // Expand / collapse methods + checkAll: $.proxy(this.checkAll, this), + checkNode: $.proxy(this.checkNode, this), + uncheckAll: $.proxy(this.uncheckAll, this), + uncheckNode: $.proxy(this.uncheckNode, this), + toggleNodeChecked: $.proxy(this.toggleNodeChecked, this), + // Search methods search: $.proxy(this.search, this), clearSearch: $.proxy(this.clearSearch, this) @@ -287,12 +296,10 @@ var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - if ((classList.indexOf('click-expand') !== -1) || - (classList.indexOf('click-collapse') !== -1)) { + if ((classList.indexOf('expand-icon') !== -1)) { this.toggleExpandedState(node, _default.options); } - else if ((classList.indexOf('node-checked') !== -1) || - (classList.indexOf('node-unchecked') !== -1)) { + else if ((classList.indexOf('check-icon') !== -1)) { this.toggleCheckedState(node, _default.options); } else if (node) { @@ -401,6 +408,8 @@ // Check node node.state.checked = true; + + if (!options.silent) { this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); } @@ -458,63 +467,58 @@ } // Add expand, collapse or empty spacer icons + var classList = []; if (node.nodes) { - if (!node.state.expanded) { - treeItem - .append($(_this.template.icon) - .addClass('expand-collapse-icon click-expand') - .addClass(_this.options.expandIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('expand-collapse-icon click-collapse') - .addClass(_this.options.collapseIcon) - ); - } + classList.push('expand-icon'); + if (node.state.expanded) { + classList.push(_this.options.collapseIcon); + } + else { + classList.push(_this.options.expandIcon); + } } else { - treeItem - .append($(_this.template.icon) - .addClass(_this.options.emptyIcon) - ); + classList.push(_this.options.emptyIcon); } + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); + + // Add node icon if (_this.options.showIcon) { + + var classList = ['node-icon']; if (node.state.selected) { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.selectedIcon || _this.options.selectedIcon) - ); + classList.push(node.selectedIcon || _this.options.selectedIcon); } else { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.icon || _this.options.nodeIcon) - ); + classList.push(node.icon || _this.options.nodeIcon); } + + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); } // Add check / unchecked icon if (_this.options.showCheckbox) { + + var classList = ['check-icon']; if (node.state.checked) { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-checked') - .addClass(_this.options.checkedIcon) - ); + classList.push(_this.options.checkedIcon); } else { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-unchecked') - .addClass(_this.options.uncheckedIcon) - ); + classList.push(_this.options.uncheckedIcon); } + + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); } // Add text @@ -697,6 +701,22 @@ return this.findNodes('false', 'g', 'state.expanded'); }; + /** + Returns an array of checked nodes. + @returns {Array} nodes - Checked nodes + */ + Tree.prototype.getChecked = function () { + return this.findNodes('true', 'g', 'state.checked'); + }; + + /** + Returns an array of unchecked nodes. + @returns {Array} nodes - Unchecked nodes + */ + Tree.prototype.getUnchecked = function () { + return this.findNodes('false', 'g', 'state.checked'); + }; + /** Set a node state to selected @@ -881,6 +901,90 @@ }; + /** + Check all tree nodes + @param {optional Object} options + */ + Tree.prototype.checkAll = function (options) { + options = $.extend({}, _default.options, options); + + $.each(this.findNodes('false', 'g', 'state.checked'), $.proxy(function (index, node) { + this.setCheckedState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Check a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.checkNode = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setCheckedState(this.identifyNode(identifier), true, options); + }, this)); + + this.render(); + }; + + /** + Uncheck all tree nodes + @param {optional Object} options + */ + Tree.prototype.uncheckAll = function (options) { + options = $.extend({}, _default.options, options); + + $.each(this.findNodes('true', 'g', 'state.checked'), $.proxy(function (index, node) { + this.setCheckedState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Uncheck a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.uncheckNode = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setCheckedState(this.identifyNode(identifier), false, options); + }, this)); + + this.render(); + }; + + /** + Toggles a nodes checked state; checking if unchecked, unchecking if checked. + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.toggleNodeChecked = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleCheckedState(this.identifyNode(identifier), options); + }, this)); + }; + + /* Identifies a node from either a node id or object */ diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index b06b920d1..3c7d0dbc2 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -106,6 +106,8 @@ getUnselected: $.proxy(this.getUnselected, this), getExpanded: $.proxy(this.getExpanded, this), getCollapsed: $.proxy(this.getCollapsed, this), + getChecked: $.proxy(this.getChecked, this), + getUnchecked: $.proxy(this.getUnchecked, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -120,6 +122,13 @@ toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this), revealNode: $.proxy(this.revealNode, this), + // Expand / collapse methods + checkAll: $.proxy(this.checkAll, this), + checkNode: $.proxy(this.checkNode, this), + uncheckAll: $.proxy(this.uncheckAll, this), + uncheckNode: $.proxy(this.uncheckNode, this), + toggleNodeChecked: $.proxy(this.toggleNodeChecked, this), + // Search methods search: $.proxy(this.search, this), clearSearch: $.proxy(this.clearSearch, this) @@ -287,12 +296,10 @@ var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - if ((classList.indexOf('click-expand') !== -1) || - (classList.indexOf('click-collapse') !== -1)) { + if ((classList.indexOf('expand-icon') !== -1)) { this.toggleExpandedState(node, _default.options); } - else if ((classList.indexOf('node-checked') !== -1) || - (classList.indexOf('node-unchecked') !== -1)) { + else if ((classList.indexOf('check-icon') !== -1)) { this.toggleCheckedState(node, _default.options); } else if (node) { @@ -401,6 +408,8 @@ // Check node node.state.checked = true; + + if (!options.silent) { this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); } @@ -458,63 +467,58 @@ } // Add expand, collapse or empty spacer icons + var classList = []; if (node.nodes) { - if (!node.state.expanded) { - treeItem - .append($(_this.template.icon) - .addClass('expand-collapse-icon click-expand') - .addClass(_this.options.expandIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('expand-collapse-icon click-collapse') - .addClass(_this.options.collapseIcon) - ); - } + classList.push('expand-icon'); + if (node.state.expanded) { + classList.push(_this.options.collapseIcon); + } + else { + classList.push(_this.options.expandIcon); + } } else { - treeItem - .append($(_this.template.icon) - .addClass(_this.options.emptyIcon) - ); + classList.push(_this.options.emptyIcon); } + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); + + // Add node icon if (_this.options.showIcon) { + + var classList = ['node-icon']; if (node.state.selected) { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.selectedIcon || _this.options.selectedIcon) - ); + classList.push(node.selectedIcon || _this.options.selectedIcon); } else { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.icon || _this.options.nodeIcon) - ); + classList.push(node.icon || _this.options.nodeIcon); } + + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); } // Add check / unchecked icon if (_this.options.showCheckbox) { + + var classList = ['check-icon']; if (node.state.checked) { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-checked') - .addClass(_this.options.checkedIcon) - ); + classList.push(_this.options.checkedIcon); } else { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-unchecked') - .addClass(_this.options.uncheckedIcon) - ); + classList.push(_this.options.uncheckedIcon); } + + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); } // Add text @@ -697,6 +701,22 @@ return this.findNodes('false', 'g', 'state.expanded'); }; + /** + Returns an array of checked nodes. + @returns {Array} nodes - Checked nodes + */ + Tree.prototype.getChecked = function () { + return this.findNodes('true', 'g', 'state.checked'); + }; + + /** + Returns an array of unchecked nodes. + @returns {Array} nodes - Unchecked nodes + */ + Tree.prototype.getUnchecked = function () { + return this.findNodes('false', 'g', 'state.checked'); + }; + /** Set a node state to selected @@ -881,6 +901,90 @@ }; + /** + Check all tree nodes + @param {optional Object} options + */ + Tree.prototype.checkAll = function (options) { + options = $.extend({}, _default.options, options); + + $.each(this.findNodes('false', 'g', 'state.checked'), $.proxy(function (index, node) { + this.setCheckedState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Check a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.checkNode = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setCheckedState(this.identifyNode(identifier), true, options); + }, this)); + + this.render(); + }; + + /** + Uncheck all tree nodes + @param {optional Object} options + */ + Tree.prototype.uncheckAll = function (options) { + options = $.extend({}, _default.options, options); + + $.each(this.findNodes('true', 'g', 'state.checked'), $.proxy(function (index, node) { + this.setCheckedState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Uncheck a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.uncheckNode = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setCheckedState(this.identifyNode(identifier), false, options); + }, this)); + + this.render(); + }; + + /** + Toggles a nodes checked state; checking if unchecked, unchecking if checked. + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.toggleNodeChecked = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleCheckedState(this.identifyNode(identifier), options); + }, this)); + }; + + /* Identifies a node from either a node id or object */ diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index b06b920d1..3c7d0dbc2 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -106,6 +106,8 @@ getUnselected: $.proxy(this.getUnselected, this), getExpanded: $.proxy(this.getExpanded, this), getCollapsed: $.proxy(this.getCollapsed, this), + getChecked: $.proxy(this.getChecked, this), + getUnchecked: $.proxy(this.getUnchecked, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -120,6 +122,13 @@ toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this), revealNode: $.proxy(this.revealNode, this), + // Expand / collapse methods + checkAll: $.proxy(this.checkAll, this), + checkNode: $.proxy(this.checkNode, this), + uncheckAll: $.proxy(this.uncheckAll, this), + uncheckNode: $.proxy(this.uncheckNode, this), + toggleNodeChecked: $.proxy(this.toggleNodeChecked, this), + // Search methods search: $.proxy(this.search, this), clearSearch: $.proxy(this.clearSearch, this) @@ -287,12 +296,10 @@ var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - if ((classList.indexOf('click-expand') !== -1) || - (classList.indexOf('click-collapse') !== -1)) { + if ((classList.indexOf('expand-icon') !== -1)) { this.toggleExpandedState(node, _default.options); } - else if ((classList.indexOf('node-checked') !== -1) || - (classList.indexOf('node-unchecked') !== -1)) { + else if ((classList.indexOf('check-icon') !== -1)) { this.toggleCheckedState(node, _default.options); } else if (node) { @@ -401,6 +408,8 @@ // Check node node.state.checked = true; + + if (!options.silent) { this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); } @@ -458,63 +467,58 @@ } // Add expand, collapse or empty spacer icons + var classList = []; if (node.nodes) { - if (!node.state.expanded) { - treeItem - .append($(_this.template.icon) - .addClass('expand-collapse-icon click-expand') - .addClass(_this.options.expandIcon) - ); - } - else { - treeItem - .append($(_this.template.icon) - .addClass('expand-collapse-icon click-collapse') - .addClass(_this.options.collapseIcon) - ); - } + classList.push('expand-icon'); + if (node.state.expanded) { + classList.push(_this.options.collapseIcon); + } + else { + classList.push(_this.options.expandIcon); + } } else { - treeItem - .append($(_this.template.icon) - .addClass(_this.options.emptyIcon) - ); + classList.push(_this.options.emptyIcon); } + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); + + // Add node icon if (_this.options.showIcon) { + + var classList = ['node-icon']; if (node.state.selected) { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.selectedIcon || _this.options.selectedIcon) - ); + classList.push(node.selectedIcon || _this.options.selectedIcon); } else { - treeItem - .append($(_this.template.icon) - .addClass('node-icon') - .addClass(node.icon || _this.options.nodeIcon) - ); + classList.push(node.icon || _this.options.nodeIcon); } + + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); } // Add check / unchecked icon if (_this.options.showCheckbox) { + + var classList = ['check-icon']; if (node.state.checked) { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-checked') - .addClass(_this.options.checkedIcon) - ); + classList.push(_this.options.checkedIcon); } else { - treeItem - .append($(_this.template.icon) - .addClass('checked-icon node-unchecked') - .addClass(_this.options.uncheckedIcon) - ); + classList.push(_this.options.uncheckedIcon); } + + treeItem + .append($(_this.template.icon) + .addClass(classList.join(' ')) + ); } // Add text @@ -697,6 +701,22 @@ return this.findNodes('false', 'g', 'state.expanded'); }; + /** + Returns an array of checked nodes. + @returns {Array} nodes - Checked nodes + */ + Tree.prototype.getChecked = function () { + return this.findNodes('true', 'g', 'state.checked'); + }; + + /** + Returns an array of unchecked nodes. + @returns {Array} nodes - Unchecked nodes + */ + Tree.prototype.getUnchecked = function () { + return this.findNodes('false', 'g', 'state.checked'); + }; + /** Set a node state to selected @@ -881,6 +901,90 @@ }; + /** + Check all tree nodes + @param {optional Object} options + */ + Tree.prototype.checkAll = function (options) { + options = $.extend({}, _default.options, options); + + $.each(this.findNodes('false', 'g', 'state.checked'), $.proxy(function (index, node) { + this.setCheckedState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Check a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.checkNode = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setCheckedState(this.identifyNode(identifier), true, options); + }, this)); + + this.render(); + }; + + /** + Uncheck all tree nodes + @param {optional Object} options + */ + Tree.prototype.uncheckAll = function (options) { + options = $.extend({}, _default.options, options); + + $.each(this.findNodes('true', 'g', 'state.checked'), $.proxy(function (index, node) { + this.setCheckedState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Uncheck a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.uncheckNode = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.setCheckedState(this.identifyNode(identifier), false, options); + }, this)); + + this.render(); + }; + + /** + Toggles a nodes checked state; checking if unchecked, unchecking if checked. + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.toggleNodeChecked = function (identifiers, options) { + options = $.extend({}, _default.options, options); + + if (!(identifiers instanceof Array)) { + identifiers = [identifiers]; + } + + $.each(identifiers, $.proxy(function (index, identifier) { + this.toggleCheckedState(this.identifyNode(identifier), options); + }, this)); + }; + + /* Identifies a node from either a node id or object */ diff --git a/tests/tests.js b/tests/tests.js index b8cd67fb2..047e55ab9 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -232,6 +232,7 @@ var cbWorked, onWorked = false; init({ data: data, + levels: 1, onNodeExpanded: function(/*event, date*/) { cbWorked = true; } @@ -241,7 +242,7 @@ }); var nodeCount = $('.list-group-item').length; - var el = $('.click-expand:first'); + var el = $('.expand-icon:first'); el.trigger('click'); ok(($('.list-group-item').length > nodeCount), 'Number of nodes are increased, so node must have expanded'); ok(cbWorked, 'onNodeExpanded function was called'); @@ -253,6 +254,7 @@ var cbWorked, onWorked = false; init({ data: data, + levels: 2, onNodeCollapsed: function(/*event, date*/) { cbWorked = true; } @@ -262,7 +264,7 @@ }); var nodeCount = $('.list-group-item').length; - var el = $('.click-collapse:first'); + var el = $('.expand-icon:first'); el.trigger('click'); ok(($('.list-group-item').length < nodeCount), 'Number of nodes has decreased, so node must have collapsed'); ok(cbWorked, 'onNodeCollapsed function was called'); @@ -407,12 +409,11 @@ var options = getOptions($tree); // simulate click event on check icon - var $el = $('.checked-icon:first'); + var $el = $('.check-icon:first'); $el.trigger('click'); // check state is correct - $el = $('.checked-icon:first'); - ok(($el.attr('class').split(' ').indexOf('node-checked') !== -1), 'Node is checked : class "node-checked" added'); + $el = $('.check-icon:first'); ok(($el.attr('class').indexOf(options.checkedIcon) !== -1), 'Node is checked : icon is correct'); ok(cbWorked, 'onNodeChecked function was called'); ok(onWorked, 'nodeChecked was fired'); @@ -435,17 +436,16 @@ var options = getOptions($tree); // first check a node - var $el = $('.checked-icon:first'); + var $el = $('.check-icon:first'); $el.trigger('click'); // then simulate unchecking a node cbWorked = onWorked = false; - $el = $('.checked-icon:first'); + $el = $('.check-icon:first'); $el.trigger('click'); // check state is correct - $el = $('.checked-icon:first'); - ok(($el.attr('class').split(' ').indexOf('node-checked') === -1), 'Node is unchecked : class "node-checked" removed'); + $el = $('.check-icon:first'); ok(($el.attr('class').indexOf(options.uncheckedIcon) !== -1), 'Node is unchecked : icon is correct'); ok(cbWorked, 'onNodeUnchecked function was called'); ok(onWorked, 'nodeUnchecked was fired'); @@ -535,6 +535,87 @@ equal(collapsedNodes.length, 8, 'Correct number of nodes returned'); }); + test('getChecked', function () { + var $tree = init({ data: data, showCheckbox: true }) + .treeview('checkNode', 0); + + var checkedNodes = $tree.treeview('getChecked'); + ok((checkedNodes instanceof Array), 'Result is an array'); + equal(checkedNodes.length, 1, 'Correct number of nodes returned'); + equal(checkedNodes[0].text, 'Parent 1', 'Correct node returned'); + }); + + test('getUnchecked', function () { + var $tree = init({ data: data }) + .treeview('checkNode', 0); + + var uncheckedNodes = $tree.treeview('getUnchecked'); + ok((uncheckedNodes instanceof Array), 'Result is an array'); + equal(uncheckedNodes.length, 8, 'Correct number of nodes returned'); + }); + + test('checkAll / uncheckAll', function () { + var $tree = init({ data: data, levels: 3, showCheckbox: true }); + + $tree.treeview('checkAll'); + equal($($tree.selector + ' ul li.node-checked').length, 9, 'Check all works, 9 nodes with node-checked class'); + equal($($tree.selector + ' ul li .glyphicon-check').length, 9, 'Check all works, 9 nodes with glyphicon-check icon'); + + $tree.treeview('uncheckAll'); + equal($($tree.selector + ' ul li.node-checked').length, 0, 'Check all works, 9 nodes non with node-checked class'); + equal($($tree.selector + ' ul li .glyphicon-unchecked').length, 9, 'Check all works, 9 nodes with glyphicon-unchecked icon'); + }); + + test('checkNode / uncheckNode', function () { + var $tree = init({ data: data, showCheckbox: true }); + var options = getOptions($tree); + var nodeId = 0; + var node = $tree.treeview('getNode', 0); + + // Check node using node id + $tree.treeview('checkNode', nodeId); + ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') !== -1), 'Check node (by id) : Node is checked'); + ok(($('.node-checked').length === 1), 'Check node (by id) : There is only one checked node'); + ok(($('.check-icon:first').attr('class').indexOf(options.checkedIcon) !== -1), 'Check node (by id) : Node icon is correct'); + + // Uncheck node using node id + $tree.treeview('uncheckNode', nodeId); + ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') === -1), 'Uncheck node (by id) : Node is no longer checked'); + ok(($('.node-checked').length === 0), 'Uncheck node (by id) : There are no checked nodes'); + ok(($('.check-icon:first').attr('class').indexOf(options.uncheckedIcon) !== -1), 'Uncheck node (by id) : Node icon is correct'); + + // Check node using node + $tree.treeview('checkNode', node); + ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') !== -1), 'Check node (by node) : Node is checked'); + ok(($('.node-checked').length === 1), 'Check node (by node) : There is only one checked node'); + ok(($('.check-icon:first').attr('class').indexOf(options.checkedIcon) !== -1), 'Check node (by node) : Node icon is correct'); + + // Uncheck node using node + $tree.treeview('uncheckNode', node); + ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') === -1), 'Uncheck node (by node) : Node is no longer checked'); + ok(($('.node-checked').length === 0), 'Uncheck node (by node) : There are no checked nodes'); + ok(($('.check-icon:first').attr('class').indexOf(options.uncheckedIcon) !== -1), 'Uncheck node (by node) : Node icon is correct'); + }); + + test('toggleNodeChecked', function () { + var $tree = init({ data: data, showCheckbox: true }); + var options = getOptions($tree); + var nodeId = 0; + var node = $tree.treeview('getNode', 0); + + // Toggle checked using node id + $tree.treeview('toggleNodeChecked', nodeId); + ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') !== -1), 'Toggle node (by id) : Node is checked'); + ok(($('.node-checked').length === 1), 'Toggle node (by id) : There is only one checked node'); + ok(($('.check-icon:first').attr('class').indexOf(options.checkedIcon) !== -1), 'Check node (by id) : Node icon is correct'); + + // Toggle checked using node + $tree.treeview('toggleNodeChecked', node); + ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') === -1), 'Toggle node (by node) : Node is unchecked'); + ok(($('.node-checked').length === 0), 'Toggle node (by node) : There are no checked nodes'); + ok(($('.check-icon:first').attr('class').indexOf(options.uncheckedIcon) !== -1), 'Uncheck node (by id) : Node icon is correct'); + }); + test('selectNode / unselectNode', function () { var $tree = init({ data: data, selectedIcon: 'glyphicon glyphicon-selected' }); var el; @@ -551,9 +632,9 @@ // Unselect node using node id $tree.treeview('unselectNode', nodeId); el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by id) : Node is no longer selected'); - ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Select node (by id) : Node icon is correct'); - ok(($('.node-selected').length === 0), 'Select node (by id) : There are no selected nodes'); + ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Unselect node (by id) : Node is no longer selected'); + ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Unselect node (by id) : Node icon is correct'); + ok(($('.node-selected').length === 0), 'Unselect node (by id) : There are no selected nodes'); // Select node using node $tree.treeview('selectNode', node); @@ -565,9 +646,9 @@ // Unselect node using node id $tree.treeview('unselectNode', node); el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Select node (by node) : Node is no longer selected'); - ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Select node (by node) : Node icon is correct'); - ok(($('.node-selected').length === 0), 'Select node (by node) : There are no selected nodes'); + ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Unselect node (by node) : Node is no longer selected'); + ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Unselect node (by node) : Node icon is correct'); + ok(($('.node-selected').length === 0), 'Unselect node (by node) : There are no selected nodes'); }); test('toggleNodeSelected', function () { From 76c16babf7114bf53cf7499eb2699084e806352c Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 2 May 2015 20:49:35 +0100 Subject: [PATCH 25/36] Doc update --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73373e2ba..1f2c33438 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,8 @@ Sets the border color for the component; set showBorder to false if you don't wa #### checkedIcon String, class names(s). Default: "glyphicon glyphicon-check" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) +Sets the icon to be as a checked checkbox, used in conjunction with showCheckbox. + #### collapseIcon String, class name(s). Default: "glyphicon glyphicon-minus" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) @@ -342,7 +344,7 @@ Whether or not to display a border around nodes. #### showCheckbox Boolean. Default: false -Whether or not to display a nodes checked icon. +Whether or not to display checkboxes on nodes. #### showIcon Boolean. Default: true @@ -357,6 +359,8 @@ Whether or not to display tags to the right of each node. The values of which m #### uncheckedIcon String, class names(s). Default: "glyphicon glyphicon-unchecked" as defined by [Bootstrap Glyphicons](http://getbootstrap.com/components/#glyphicons) +Sets the icon to be as an unchecked checkbox, used in conjunction with showCheckbox. + ## Methods From a04f4d5965e2019083ef7abfe9e5caf556c43793 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sun, 3 May 2015 12:52:12 +0100 Subject: [PATCH 26/36] Examples updated - Update to support multi select and update tree methods - Add silent checkbox to demonstrate event suppression - Add multi-select to selectable tree --- public/index.html | 109 ++++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 38 deletions(-) diff --git a/public/index.html b/public/index.html index 1a0c101f6..9d46c22c9 100644 --- a/public/index.html +++ b/public/index.html @@ -113,6 +113,18 @@

                                                                Input

                                                                +
                                                                + +
                                                                +
                                                                + +
                                                                @@ -141,6 +153,12 @@

                                                                Input

                                                                +
                                                                + +
                                                                @@ -190,6 +208,12 @@

                                                                Input

                                                                +
                                                                + +
                                                                @@ -497,38 +521,47 @@

                                                                }); + var initSelectableTree = function() { + return $('#treeview-selectable').treeview({ + data: defaultData, + multiSelect: $('#chk-select-multi').is(':checked'), + onNodeSelected: function(event, node) { + $('#selectable-output').prepend('

                                                                ' + node.text + ' was selected

                                                                '); + }, + onNodeUnselected: function (event, node) { + $('#selectable-output').prepend('

                                                                ' + node.text + ' was unselected

                                                                '); + } + }); + }; + var $selectableTree = initSelectableTree(); - var $selectableTree = $('#treeview-selectable').treeview({ - data: defaultData, - onNodeSelected: function(event, node) { - $('#selectable-output').prepend('

                                                                ' + node.text + ' was selected

                                                                '); - }, - onNodeUnselected: function (event, node) { - $('#selectable-output').prepend('

                                                                ' + node.text + ' was unselected

                                                                '); - } - }); - - var findSelectableNode = function() { - return $selectableTree.treeview('search', [ $('#input-select-node').val(), { ignoreCase: false, exactMatch: true } ]); + var findSelectableNodes = function() { + return $selectableTree.treeview('search', [ $('#input-select-node').val(), { ignoreCase: false, exactMatch: false } ]); }; - var selectableNode = findSelectableNode(); + var selectableNodes = findSelectableNodes(); + + $('#chk-select-multi:checkbox').on('change', function () { + console.log('multi-select change'); + $selectableTree = initSelectableTree(); + selectableNodes = findSelectableNodes(); + }); // Select/unselect/toggle nodes $('#input-select-node').on('keyup', function (e) { - selectableNode = findSelectableNode(); - $('.select-node').prop('disabled', !(selectableNode.length === 1)); + selectableNodes = findSelectableNodes(); + $('.select-node').prop('disabled', !(selectableNodes.length >= 1)); }); $('#btn-select-node.select-node').on('click', function (e) { - $selectableTree.treeview('selectNode', selectableNode[0]); + $selectableTree.treeview('selectNode', [ selectableNodes, { silent: $('#chk-select-silent').is(':checked') }]); }); $('#btn-unselect-node.select-node').on('click', function (e) { - $selectableTree.treeview('unselectNode', selectableNode[0]); + $selectableTree.treeview('unselectNode', [ selectableNodes, { silent: $('#chk-select-silent').is(':checked') }]); }); $('#btn-toggle-selected.select-node').on('click', function (e) { - $selectableTree.treeview('toggleNodeSelected', selectableNode[0]); + $selectableTree.treeview('toggleNodeSelected', [ selectableNodes, { silent: $('#chk-select-silent').is(':checked') }]); }); @@ -543,38 +576,38 @@

                                                                } }); - var findExpandibleNode = function() { - return $expandibleTree.treeview('search', [ $('#input-expand-node').val(), { ignoreCase: false, exactMatch: true } ]); + var findExpandibleNodess = function() { + return $expandibleTree.treeview('search', [ $('#input-expand-node').val(), { ignoreCase: false, exactMatch: false } ]); }; - var expandibleNode = findExpandibleNode(); + var expandibleNodes = findExpandibleNodess(); // Expand/collapse/toggle nodes $('#input-expand-node').on('keyup', function (e) { - expandibleNode = findExpandibleNode(); - $('.expand-node').prop('disabled', !(expandibleNode.length === 1)); + expandibleNodes = findExpandibleNodess(); + $('.expand-node').prop('disabled', !(expandibleNodes.length >= 1)); }); $('#btn-expand-node.expand-node').on('click', function (e) { var levels = $('#select-expand-node-levels').val(); - $expandibleTree.treeview('expandNode', [ expandibleNode[0], { levels: levels } ]); + $expandibleTree.treeview('expandNode', [ expandibleNodes, { levels: levels, silent: $('#chk-expand-silent').is(':checked') }]); }); $('#btn-collapse-node.expand-node').on('click', function (e) { - $expandibleTree.treeview('collapseNode', expandibleNode[0]); + $expandibleTree.treeview('collapseNode', [ expandibleNodes, { silent: $('#chk-expand-silent').is(':checked') }]); }); $('#btn-toggle-expanded.expand-node').on('click', function (e) { - $expandibleTree.treeview('toggleNodeExpanded', expandibleNode[0]); + $expandibleTree.treeview('toggleNodeExpanded', [ expandibleNodes, { silent: $('#chk-expand-silent').is(':checked') }]); }); // Expand/collapse all $('#btn-expand-all').on('click', function (e) { var levels = $('#select-expand-all-levels').val(); - $expandibleTree.treeview('expandAll', { levels: levels }); + $expandibleTree.treeview('expandAll', { levels: levels, silent: $('#chk-expand-silent').is(':checked') }); }); $('#btn-collapse-all').on('click', function (e) { - $expandibleTree.treeview('collapseAll'); + $expandibleTree.treeview('collapseAll', { silent: $('#chk-expand-silent').is(':checked') }); }); @@ -591,36 +624,36 @@

                                                                } }); - var findCheckableNode = function() { - return $checkableTree.treeview('search', [ $('#input-check-node').val(), { ignoreCase: false, exactMatch: true } ]); + var findCheckableNodess = function() { + return $checkableTree.treeview('search', [ $('#input-check-node').val(), { ignoreCase: false, exactMatch: false } ]); }; - var checkableNode = findCheckableNode(); + var checkableNodes = findCheckableNodess(); // Check/uncheck/toggle nodes $('#input-check-node').on('keyup', function (e) { - checkableNode = findCheckableNode(); - $('.check-node').prop('disabled', !(checkableNode.length === 1)); + checkableNodes = findCheckableNodess(); + $('.check-node').prop('disabled', !(checkableNodes.length >= 1)); }); $('#btn-check-node.check-node').on('click', function (e) { - $checkableTree.treeview('checkNode', [ checkableNode[0], { } ]); + $checkableTree.treeview('checkNode', [ checkableNodes, { silent: $('#chk-check-silent').is(':checked') }]); }); $('#btn-uncheck-node.check-node').on('click', function (e) { - $checkableTree.treeview('uncheckNode', checkableNode[0]); + $checkableTree.treeview('uncheckNode', [ checkableNodes, { silent: $('#chk-check-silent').is(':checked') }]); }); $('#btn-toggle-checked.check-node').on('click', function (e) { - $checkableTree.treeview('toggleNodeChecked', checkableNode[0]); + $checkableTree.treeview('toggleNodeChecked', [ checkableNodes, { silent: $('#chk-check-silent').is(':checked') }]); }); // Check/uncheck all $('#btn-check-all').on('click', function (e) { - $checkableTree.treeview('checkAll', { }); + $checkableTree.treeview('checkAll', { silent: $('#chk-check-silent').is(':checked') }); }); $('#btn-uncheck-all').on('click', function (e) { - $checkableTree.treeview('uncheckAll'); + $checkableTree.treeview('uncheckAll', { silent: $('#chk-check-silent').is(':checked') }); }); From 28543da281d7e46bf34382f1469e6da25a304784 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sun, 3 May 2015 15:16:48 +0100 Subject: [PATCH 27/36] Refactored API methods - Added forEachIdentifier to remove duplicate code executed in most methods. --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 124 ++++++++++---------------------- src/js/bootstrap-treeview.js | 124 ++++++++++---------------------- tests/lib/bootstrap-treeview.js | 124 ++++++++++---------------------- 4 files changed, 115 insertions(+), 259 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index e9146fcd4..4b7575bad 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("expand-icon")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("check-icon")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                  ',item:'
                                                                • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.unselectNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setSelectedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleSelectedState(this.identifyNode(b),c)},this))},g.prototype.collapseAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.expanded"),a.proxy(function(a,c){this.setExpandedState(c,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setExpandedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.expandAll=function(b){b=a.extend({},f.options,b),b&&b.levels?this.expandLevels(this.tree,b.levels,b):a.each(this.nodes,a.proxy(function(a,c){this.setExpandedState(c,!0,b)},this)),this.render()},g.prototype.expandNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){var d=this.identifyNode(b);this.setExpandedState(d,!0,c),d.nodes&&c&&c.levels&&this.expandLevels(d.nodes,c.levels-1,c)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){for(var d=this.getParent(b);d;)this.setExpandedState(d,!0,c),d=this.getParent(d)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleExpandedState(this.identifyNode(b),c)},this))},g.prototype.checkAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("false","g","state.checked"),a.proxy(function(a,c){this.setCheckedState(c,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setCheckedState(this.identifyNode(b),!0,c)},this)),this.render()},g.prototype.uncheckAll=function(b){b=a.extend({},f.options,b),a.each(this.findNodes("true","g","state.checked"),a.proxy(function(a,c){this.setCheckedState(c,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.setCheckedState(this.identifyNode(b),!1,c)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){this.toggleCheckedState(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("expand-icon")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("check-icon")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                    ',item:'
                                                                  • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this))},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this))},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this))},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 3c7d0dbc2..9fd85e69d 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -724,14 +724,8 @@ @param {optional Object} options */ Tree.prototype.selectNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setSelectedState(this.identifyNode(identifier), true, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setSelectedState(node, true, options); }, this)); this.render(); @@ -743,14 +737,8 @@ @param {optional Object} options */ Tree.prototype.unselectNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setSelectedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setSelectedState(node, false, options); }, this)); this.render(); @@ -762,14 +750,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeSelected = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleSelectedState(this.identifyNode(identifier), options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleSelectedState(node, options); }, this)); }; @@ -779,9 +761,8 @@ @param {optional Object} options */ Tree.prototype.collapseAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('true', 'g', 'state.expanded'), $.proxy(function (index, node) { + var identifiers = this.findNodes('true', 'g', 'state.expanded'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, false, options); }, this)); @@ -794,14 +775,8 @@ @param {optional Object} options */ Tree.prototype.collapseNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setExpandedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setExpandedState(node, false, options); }, this)); this.render(); @@ -818,7 +793,8 @@ this.expandLevels(this.tree, options.levels, options); } else { - $.each(this.nodes, $.proxy(function (index, node) { + var identifiers = this.findNodes('false', 'g', 'state.expanded'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); }, this)); } @@ -832,14 +808,7 @@ @param {optional Object} options */ Tree.prototype.expandNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - var node = this.identifyNode(identifier); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); if (node.nodes && (options && options.levels)) { this.expandLevels(node.nodes, options.levels-1, options); @@ -866,14 +835,8 @@ @param {optional Object} options */ Tree.prototype.revealNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - var parentNode = this.getParent(identifier); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + var parentNode = this.getParent(node); while (parentNode) { this.setExpandedState(parentNode, true, options); parentNode = this.getParent(parentNode); @@ -889,14 +852,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeExpanded = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleExpandedState(this.identifyNode(identifier), options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleExpandedState(node, options); }, this)); }; @@ -906,9 +863,8 @@ @param {optional Object} options */ Tree.prototype.checkAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('false', 'g', 'state.checked'), $.proxy(function (index, node) { + var identifiers = this.findNodes('false', 'g', 'state.checked'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, true, options); }, this)); @@ -921,14 +877,8 @@ @param {optional Object} options */ Tree.prototype.checkNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setCheckedState(this.identifyNode(identifier), true, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setCheckedState(node, true, options); }, this)); this.render(); @@ -939,9 +889,8 @@ @param {optional Object} options */ Tree.prototype.uncheckAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('true', 'g', 'state.checked'), $.proxy(function (index, node) { + var identifiers = this.findNodes('true', 'g', 'state.checked'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, false, options); }, this)); @@ -954,14 +903,8 @@ @param {optional Object} options */ Tree.prototype.uncheckNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setCheckedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setCheckedState(node, false, options); }, this)); this.render(); @@ -973,6 +916,17 @@ @param {optional Object} options */ Tree.prototype.toggleNodeChecked = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleCheckedState(node, options); + }, this)); + }; + + + /** + Common code for processing multiple identifiers + */ + Tree.prototype.forEachIdentifier = function (identifiers, options, callback) { + options = $.extend({}, _default.options, options); if (!(identifiers instanceof Array)) { @@ -980,11 +934,10 @@ } $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleCheckedState(this.identifyNode(identifier), options); - }, this)); + callback(this.identifyNode(identifier), options); + }, this)); }; - /* Identifies a node from either a node id or object */ @@ -994,7 +947,6 @@ identifier; }; - /** Searches the tree for nodes (text) that match given criteria @param {String} pattern - A given string to match against diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 3c7d0dbc2..9fd85e69d 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -724,14 +724,8 @@ @param {optional Object} options */ Tree.prototype.selectNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setSelectedState(this.identifyNode(identifier), true, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setSelectedState(node, true, options); }, this)); this.render(); @@ -743,14 +737,8 @@ @param {optional Object} options */ Tree.prototype.unselectNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setSelectedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setSelectedState(node, false, options); }, this)); this.render(); @@ -762,14 +750,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeSelected = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleSelectedState(this.identifyNode(identifier), options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleSelectedState(node, options); }, this)); }; @@ -779,9 +761,8 @@ @param {optional Object} options */ Tree.prototype.collapseAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('true', 'g', 'state.expanded'), $.proxy(function (index, node) { + var identifiers = this.findNodes('true', 'g', 'state.expanded'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, false, options); }, this)); @@ -794,14 +775,8 @@ @param {optional Object} options */ Tree.prototype.collapseNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setExpandedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setExpandedState(node, false, options); }, this)); this.render(); @@ -818,7 +793,8 @@ this.expandLevels(this.tree, options.levels, options); } else { - $.each(this.nodes, $.proxy(function (index, node) { + var identifiers = this.findNodes('false', 'g', 'state.expanded'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); }, this)); } @@ -832,14 +808,7 @@ @param {optional Object} options */ Tree.prototype.expandNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - var node = this.identifyNode(identifier); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); if (node.nodes && (options && options.levels)) { this.expandLevels(node.nodes, options.levels-1, options); @@ -866,14 +835,8 @@ @param {optional Object} options */ Tree.prototype.revealNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - var parentNode = this.getParent(identifier); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + var parentNode = this.getParent(node); while (parentNode) { this.setExpandedState(parentNode, true, options); parentNode = this.getParent(parentNode); @@ -889,14 +852,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeExpanded = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleExpandedState(this.identifyNode(identifier), options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleExpandedState(node, options); }, this)); }; @@ -906,9 +863,8 @@ @param {optional Object} options */ Tree.prototype.checkAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('false', 'g', 'state.checked'), $.proxy(function (index, node) { + var identifiers = this.findNodes('false', 'g', 'state.checked'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, true, options); }, this)); @@ -921,14 +877,8 @@ @param {optional Object} options */ Tree.prototype.checkNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setCheckedState(this.identifyNode(identifier), true, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setCheckedState(node, true, options); }, this)); this.render(); @@ -939,9 +889,8 @@ @param {optional Object} options */ Tree.prototype.uncheckAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('true', 'g', 'state.checked'), $.proxy(function (index, node) { + var identifiers = this.findNodes('true', 'g', 'state.checked'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, false, options); }, this)); @@ -954,14 +903,8 @@ @param {optional Object} options */ Tree.prototype.uncheckNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setCheckedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setCheckedState(node, false, options); }, this)); this.render(); @@ -973,6 +916,17 @@ @param {optional Object} options */ Tree.prototype.toggleNodeChecked = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleCheckedState(node, options); + }, this)); + }; + + + /** + Common code for processing multiple identifiers + */ + Tree.prototype.forEachIdentifier = function (identifiers, options, callback) { + options = $.extend({}, _default.options, options); if (!(identifiers instanceof Array)) { @@ -980,11 +934,10 @@ } $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleCheckedState(this.identifyNode(identifier), options); - }, this)); + callback(this.identifyNode(identifier), options); + }, this)); }; - /* Identifies a node from either a node id or object */ @@ -994,7 +947,6 @@ identifier; }; - /** Searches the tree for nodes (text) that match given criteria @param {String} pattern - A given string to match against diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 3c7d0dbc2..9fd85e69d 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -724,14 +724,8 @@ @param {optional Object} options */ Tree.prototype.selectNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setSelectedState(this.identifyNode(identifier), true, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setSelectedState(node, true, options); }, this)); this.render(); @@ -743,14 +737,8 @@ @param {optional Object} options */ Tree.prototype.unselectNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setSelectedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setSelectedState(node, false, options); }, this)); this.render(); @@ -762,14 +750,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeSelected = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleSelectedState(this.identifyNode(identifier), options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleSelectedState(node, options); }, this)); }; @@ -779,9 +761,8 @@ @param {optional Object} options */ Tree.prototype.collapseAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('true', 'g', 'state.expanded'), $.proxy(function (index, node) { + var identifiers = this.findNodes('true', 'g', 'state.expanded'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, false, options); }, this)); @@ -794,14 +775,8 @@ @param {optional Object} options */ Tree.prototype.collapseNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setExpandedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setExpandedState(node, false, options); }, this)); this.render(); @@ -818,7 +793,8 @@ this.expandLevels(this.tree, options.levels, options); } else { - $.each(this.nodes, $.proxy(function (index, node) { + var identifiers = this.findNodes('false', 'g', 'state.expanded'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); }, this)); } @@ -832,14 +808,7 @@ @param {optional Object} options */ Tree.prototype.expandNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - var node = this.identifyNode(identifier); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); if (node.nodes && (options && options.levels)) { this.expandLevels(node.nodes, options.levels-1, options); @@ -866,14 +835,8 @@ @param {optional Object} options */ Tree.prototype.revealNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - var parentNode = this.getParent(identifier); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + var parentNode = this.getParent(node); while (parentNode) { this.setExpandedState(parentNode, true, options); parentNode = this.getParent(parentNode); @@ -889,14 +852,8 @@ @param {optional Object} options */ Tree.prototype.toggleNodeExpanded = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleExpandedState(this.identifyNode(identifier), options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleExpandedState(node, options); }, this)); }; @@ -906,9 +863,8 @@ @param {optional Object} options */ Tree.prototype.checkAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('false', 'g', 'state.checked'), $.proxy(function (index, node) { + var identifiers = this.findNodes('false', 'g', 'state.checked'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, true, options); }, this)); @@ -921,14 +877,8 @@ @param {optional Object} options */ Tree.prototype.checkNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setCheckedState(this.identifyNode(identifier), true, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setCheckedState(node, true, options); }, this)); this.render(); @@ -939,9 +889,8 @@ @param {optional Object} options */ Tree.prototype.uncheckAll = function (options) { - options = $.extend({}, _default.options, options); - - $.each(this.findNodes('true', 'g', 'state.checked'), $.proxy(function (index, node) { + var identifiers = this.findNodes('true', 'g', 'state.checked'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, false, options); }, this)); @@ -954,14 +903,8 @@ @param {optional Object} options */ Tree.prototype.uncheckNode = function (identifiers, options) { - options = $.extend({}, _default.options, options); - - if (!(identifiers instanceof Array)) { - identifiers = [identifiers]; - } - - $.each(identifiers, $.proxy(function (index, identifier) { - this.setCheckedState(this.identifyNode(identifier), false, options); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setCheckedState(node, false, options); }, this)); this.render(); @@ -973,6 +916,17 @@ @param {optional Object} options */ Tree.prototype.toggleNodeChecked = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.toggleCheckedState(node, options); + }, this)); + }; + + + /** + Common code for processing multiple identifiers + */ + Tree.prototype.forEachIdentifier = function (identifiers, options, callback) { + options = $.extend({}, _default.options, options); if (!(identifiers instanceof Array)) { @@ -980,11 +934,10 @@ } $.each(identifiers, $.proxy(function (index, identifier) { - this.toggleCheckedState(this.identifyNode(identifier), options); - }, this)); + callback(this.identifyNode(identifier), options); + }, this)); }; - /* Identifies a node from either a node id or object */ @@ -994,7 +947,6 @@ identifier; }; - /** Searches the tree for nodes (text) that match given criteria @param {String} pattern - A given string to match against From 037701113b7282ed7b9359983b53c596a122dde2 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sun, 3 May 2015 15:23:57 +0100 Subject: [PATCH 28/36] Refactored toggle methods - Removed multiple render calls when processing multiple identifiers --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 19 ++++++++++++++----- src/js/bootstrap-treeview.js | 19 ++++++++++++++----- tests/lib/bootstrap-treeview.js | 19 ++++++++++++++----- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 4b7575bad..6e51d2d72 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("expand-icon")?this.toggleExpandedState(e,f.options):-1!==d.indexOf("check-icon")?this.toggleCheckedState(e,f.options):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options))},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&(this.setExpandedState(a,!a.state.expanded,b),this.render())},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&(this.setSelectedState(a,!a.state.selected,b),this.render())},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&(this.setCheckedState(a,!a.state.checked,b),this.render())},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                      ',item:'
                                                                    • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this))},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this))},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this))},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("expand-icon")?(this.toggleExpandedState(e,f.options),this.render()):-1!==d.indexOf("check-icon")?(this.toggleCheckedState(e,f.options),this.render()):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options),this.render())},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                        ',item:'
                                                                      • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 9fd85e69d..260ec858c 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -297,17 +297,24 @@ var node = this.findNode(target); 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) { + if (node.selectable) { this.toggleSelectedState(node, _default.options); } else { this.toggleExpandedState(node, _default.options); } + + this.render(); } }; @@ -327,7 +334,6 @@ Tree.prototype.toggleExpandedState = function (node, options) { if (!node) return; this.setExpandedState(node, !node.state.expanded, options); - this.render(); }; Tree.prototype.setExpandedState = function (node, state, options) { @@ -362,7 +368,6 @@ Tree.prototype.toggleSelectedState = function (node, options) { if (!node) return; this.setSelectedState(node, !node.state.selected, options); - this.render(); }; Tree.prototype.setSelectedState = function (node, state, options) { @@ -397,8 +402,7 @@ Tree.prototype.toggleCheckedState = function (node, options) { if (!node) return; this.setCheckedState(node, !node.state.checked, options); - this.render(); - }; + } Tree.prototype.setCheckedState = function (node, state, options) { @@ -409,7 +413,6 @@ // Check node node.state.checked = true; - if (!options.silent) { this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); } @@ -753,6 +756,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleSelectedState(node, options); }, this)); + + this.render(); }; @@ -855,6 +860,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleExpandedState(node, options); }, this)); + + this.render(); }; @@ -919,6 +926,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleCheckedState(node, options); }, this)); + + this.render(); }; diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 9fd85e69d..260ec858c 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -297,17 +297,24 @@ var node = this.findNode(target); 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) { + if (node.selectable) { this.toggleSelectedState(node, _default.options); } else { this.toggleExpandedState(node, _default.options); } + + this.render(); } }; @@ -327,7 +334,6 @@ Tree.prototype.toggleExpandedState = function (node, options) { if (!node) return; this.setExpandedState(node, !node.state.expanded, options); - this.render(); }; Tree.prototype.setExpandedState = function (node, state, options) { @@ -362,7 +368,6 @@ Tree.prototype.toggleSelectedState = function (node, options) { if (!node) return; this.setSelectedState(node, !node.state.selected, options); - this.render(); }; Tree.prototype.setSelectedState = function (node, state, options) { @@ -397,8 +402,7 @@ Tree.prototype.toggleCheckedState = function (node, options) { if (!node) return; this.setCheckedState(node, !node.state.checked, options); - this.render(); - }; + } Tree.prototype.setCheckedState = function (node, state, options) { @@ -409,7 +413,6 @@ // Check node node.state.checked = true; - if (!options.silent) { this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); } @@ -753,6 +756,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleSelectedState(node, options); }, this)); + + this.render(); }; @@ -855,6 +860,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleExpandedState(node, options); }, this)); + + this.render(); }; @@ -919,6 +926,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleCheckedState(node, options); }, this)); + + this.render(); }; diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 9fd85e69d..260ec858c 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -297,17 +297,24 @@ var node = this.findNode(target); 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) { + if (node.selectable) { this.toggleSelectedState(node, _default.options); } else { this.toggleExpandedState(node, _default.options); } + + this.render(); } }; @@ -327,7 +334,6 @@ Tree.prototype.toggleExpandedState = function (node, options) { if (!node) return; this.setExpandedState(node, !node.state.expanded, options); - this.render(); }; Tree.prototype.setExpandedState = function (node, state, options) { @@ -362,7 +368,6 @@ Tree.prototype.toggleSelectedState = function (node, options) { if (!node) return; this.setSelectedState(node, !node.state.selected, options); - this.render(); }; Tree.prototype.setSelectedState = function (node, state, options) { @@ -397,8 +402,7 @@ Tree.prototype.toggleCheckedState = function (node, options) { if (!node) return; this.setCheckedState(node, !node.state.checked, options); - this.render(); - }; + } Tree.prototype.setCheckedState = function (node, state, options) { @@ -409,7 +413,6 @@ // Check node node.state.checked = true; - if (!options.silent) { this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); } @@ -753,6 +756,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleSelectedState(node, options); }, this)); + + this.render(); }; @@ -855,6 +860,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleExpandedState(node, options); }, this)); + + this.render(); }; @@ -919,6 +926,8 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleCheckedState(node, options); }, this)); + + this.render(); }; From f3b039199b01e5a6f2452bf89ce6e6087ffe92e0 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sun, 3 May 2015 18:24:26 +0100 Subject: [PATCH 29/36] Initial idea prototyped #51 - Add node.state disabled - Updated css and inline styles to distinguish visually - Disabled click events --- README.md | 6 +++++ dist/bootstrap-treeview.min.css | 2 +- dist/bootstrap-treeview.min.js | 2 +- public/css/bootstrap-treeview.css | 5 +++++ public/js/bootstrap-treeview.js | 37 ++++++++++++++++++------------- src/css/bootstrap-treeview.css | 5 +++++ src/js/bootstrap-treeview.js | 37 ++++++++++++++++++------------- tests/lib/bootstrap-treeview.css | 5 +++++ tests/lib/bootstrap-treeview.js | 37 ++++++++++++++++++------------- 9 files changed, 89 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 1f2c33438..541d1216b 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ If you want to do more, here's the full node specification selectable: true, state: { checked: true, + disabled: true, expanded: true, selected: true }, @@ -195,6 +196,11 @@ Describes a node's initial state. Whether or not a node is checked, represented by a checkbox style glyphicon. +#### state.disabled +`Boolean` `Default: false` + +Whether or not a node is disabled (not selectable, expandable or checkable). + #### state.expanded `Boolean` `Default: false` diff --git a/dist/bootstrap-treeview.min.css b/dist/bootstrap-treeview.min.css index dc46c218e..57a348a87 100644 --- a/dist/bootstrap-treeview.min.css +++ b/dist/bootstrap-treeview.min.css @@ -1 +1 @@ -.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px} \ No newline at end of file +.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed} \ No newline at end of file diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 6e51d2d72..4cb798491 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("expanded")||(c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),b.state.hasOwnProperty("checked")||(b.state.checked=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=c.attr("class")?c.attr("class").split(" "):[],e=this.findNode(c);-1!==d.indexOf("expand-icon")?(this.toggleExpandedState(e,f.options),this.render()):-1!==d.indexOf("check-icon")?(this.toggleCheckedState(e,f.options),this.render()):e&&(e.selectable?this.toggleSelectedState(e,f.options):this.toggleExpandedState(e,f.options),this.render())},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.selected?"node-selected":"").addClass(e.state.checked?"node-checked":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                          ',item:'
                                                                        • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                            ',item:'
                                                                          • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/css/bootstrap-treeview.css b/public/css/bootstrap-treeview.css index 625912e17..3f5dc60bf 100644 --- a/public/css/bootstrap-treeview.css +++ b/public/css/bootstrap-treeview.css @@ -30,3 +30,8 @@ width: 12px; margin-right: 5px; } + +.treeview .node-disabled { + color: silver; + cursor: not-allowed; +} \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 260ec858c..b371243c1 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -256,10 +256,20 @@ // where provided we should preserve states node.state = node.state || {}; + // set checked state; unless set always false + if (!node.state.hasOwnProperty('checked')) { + node.state.checked = false; + } + + // set enabled state; unless set always false + if (!node.state.hasOwnProperty('disabled')) { + node.state.disabled = false; + } + // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - - if ((level < _this.options.levels) && + if (!node.state.disabled && + (level < _this.options.levels) && (node.nodes && node.nodes.length > 0)) { node.state.expanded = true; } @@ -273,11 +283,6 @@ node.state.selected = false; } - // set checked state; unless set always false - if (!node.state.hasOwnProperty('checked')) { - node.state.checked = false; - } - // index nodes in a flattened structure for use later _this.nodes.push(node); @@ -293,9 +298,10 @@ if (!this.options.enableLinks) event.preventDefault(); var target = $(event.target); - var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - + if (!node || node.state.disabled) return; + + var classList = target.attr('class') ? target.attr('class').split(' ') : []; if ((classList.indexOf('expand-icon') !== -1)) { this.toggleExpandedState(node, _default.options); @@ -306,7 +312,7 @@ this.toggleCheckedState(node, _default.options); this.render(); } - else if (node) { + else { if (node.selectable) { this.toggleSelectedState(node, _default.options); @@ -458,8 +464,9 @@ var treeItem = $(_this.template.item) .addClass('node-' + _this.elementId) - .addClass(node.state.selected ? 'node-selected' : '') .addClass(node.state.checked ? 'node-checked' : '') + .addClass(node.state.disabled ? 'node-disabled': '') + .addClass(node.state.selected ? 'node-selected' : '') .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -553,7 +560,7 @@ _this.$wrapper.append(treeItem); // Recursively add child ndoes - if (node.nodes && node.state.expanded) { + if (node.nodes && node.state.expanded && !node.state.disabled) { return _this.buildTree(node.nodes, level); } }); @@ -619,8 +626,8 @@ style += '}'; if (this.options.onhoverColor) { - style += '.node-' + this.elementId + ':hover{' + - 'background-color:' + this.options.onhoverColor + ';' + + style += '.node-' + this.elementId + ':not(.node-disabled):hover{' + + 'background-color:' + this.options.onhoverColor + ';' + '}'; } @@ -636,7 +643,7 @@ badge: '' }; - Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}' + Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}' /** diff --git a/src/css/bootstrap-treeview.css b/src/css/bootstrap-treeview.css index 625912e17..3f5dc60bf 100644 --- a/src/css/bootstrap-treeview.css +++ b/src/css/bootstrap-treeview.css @@ -30,3 +30,8 @@ width: 12px; margin-right: 5px; } + +.treeview .node-disabled { + color: silver; + cursor: not-allowed; +} \ No newline at end of file diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 260ec858c..b371243c1 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -256,10 +256,20 @@ // where provided we should preserve states node.state = node.state || {}; + // set checked state; unless set always false + if (!node.state.hasOwnProperty('checked')) { + node.state.checked = false; + } + + // set enabled state; unless set always false + if (!node.state.hasOwnProperty('disabled')) { + node.state.disabled = false; + } + // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - - if ((level < _this.options.levels) && + if (!node.state.disabled && + (level < _this.options.levels) && (node.nodes && node.nodes.length > 0)) { node.state.expanded = true; } @@ -273,11 +283,6 @@ node.state.selected = false; } - // set checked state; unless set always false - if (!node.state.hasOwnProperty('checked')) { - node.state.checked = false; - } - // index nodes in a flattened structure for use later _this.nodes.push(node); @@ -293,9 +298,10 @@ if (!this.options.enableLinks) event.preventDefault(); var target = $(event.target); - var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - + if (!node || node.state.disabled) return; + + var classList = target.attr('class') ? target.attr('class').split(' ') : []; if ((classList.indexOf('expand-icon') !== -1)) { this.toggleExpandedState(node, _default.options); @@ -306,7 +312,7 @@ this.toggleCheckedState(node, _default.options); this.render(); } - else if (node) { + else { if (node.selectable) { this.toggleSelectedState(node, _default.options); @@ -458,8 +464,9 @@ var treeItem = $(_this.template.item) .addClass('node-' + _this.elementId) - .addClass(node.state.selected ? 'node-selected' : '') .addClass(node.state.checked ? 'node-checked' : '') + .addClass(node.state.disabled ? 'node-disabled': '') + .addClass(node.state.selected ? 'node-selected' : '') .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -553,7 +560,7 @@ _this.$wrapper.append(treeItem); // Recursively add child ndoes - if (node.nodes && node.state.expanded) { + if (node.nodes && node.state.expanded && !node.state.disabled) { return _this.buildTree(node.nodes, level); } }); @@ -619,8 +626,8 @@ style += '}'; if (this.options.onhoverColor) { - style += '.node-' + this.elementId + ':hover{' + - 'background-color:' + this.options.onhoverColor + ';' + + style += '.node-' + this.elementId + ':not(.node-disabled):hover{' + + 'background-color:' + this.options.onhoverColor + ';' + '}'; } @@ -636,7 +643,7 @@ badge: '' }; - Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}' + Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}' /** diff --git a/tests/lib/bootstrap-treeview.css b/tests/lib/bootstrap-treeview.css index 625912e17..3f5dc60bf 100644 --- a/tests/lib/bootstrap-treeview.css +++ b/tests/lib/bootstrap-treeview.css @@ -30,3 +30,8 @@ width: 12px; margin-right: 5px; } + +.treeview .node-disabled { + color: silver; + cursor: not-allowed; +} \ No newline at end of file diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 260ec858c..b371243c1 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -256,10 +256,20 @@ // where provided we should preserve states node.state = node.state || {}; + // set checked state; unless set always false + if (!node.state.hasOwnProperty('checked')) { + node.state.checked = false; + } + + // set enabled state; unless set always false + if (!node.state.hasOwnProperty('disabled')) { + node.state.disabled = false; + } + // set expanded state; if not provided based on levels if (!node.state.hasOwnProperty('expanded')) { - - if ((level < _this.options.levels) && + if (!node.state.disabled && + (level < _this.options.levels) && (node.nodes && node.nodes.length > 0)) { node.state.expanded = true; } @@ -273,11 +283,6 @@ node.state.selected = false; } - // set checked state; unless set always false - if (!node.state.hasOwnProperty('checked')) { - node.state.checked = false; - } - // index nodes in a flattened structure for use later _this.nodes.push(node); @@ -293,9 +298,10 @@ if (!this.options.enableLinks) event.preventDefault(); var target = $(event.target); - var classList = target.attr('class') ? target.attr('class').split(' ') : []; var node = this.findNode(target); - + if (!node || node.state.disabled) return; + + var classList = target.attr('class') ? target.attr('class').split(' ') : []; if ((classList.indexOf('expand-icon') !== -1)) { this.toggleExpandedState(node, _default.options); @@ -306,7 +312,7 @@ this.toggleCheckedState(node, _default.options); this.render(); } - else if (node) { + else { if (node.selectable) { this.toggleSelectedState(node, _default.options); @@ -458,8 +464,9 @@ var treeItem = $(_this.template.item) .addClass('node-' + _this.elementId) - .addClass(node.state.selected ? 'node-selected' : '') .addClass(node.state.checked ? 'node-checked' : '') + .addClass(node.state.disabled ? 'node-disabled': '') + .addClass(node.state.selected ? 'node-selected' : '') .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -553,7 +560,7 @@ _this.$wrapper.append(treeItem); // Recursively add child ndoes - if (node.nodes && node.state.expanded) { + if (node.nodes && node.state.expanded && !node.state.disabled) { return _this.buildTree(node.nodes, level); } }); @@ -619,8 +626,8 @@ style += '}'; if (this.options.onhoverColor) { - style += '.node-' + this.elementId + ':hover{' + - 'background-color:' + this.options.onhoverColor + ';' + + style += '.node-' + this.elementId + ':not(.node-disabled):hover{' + + 'background-color:' + this.options.onhoverColor + ';' + '}'; } @@ -636,7 +643,7 @@ badge: '' }; - Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}' + Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}' /** From 837640c00e2dfc2e18fce943effea9b4bfd5f625 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sun, 3 May 2015 19:49:19 +0100 Subject: [PATCH 30/36] Implementation, doc + tests #51 - Added methodst to disable + enable nodes - Added get mehods to retrieve node based on disabled state - Added events nodeDIsabled + nodeEnabled --- README.md | 70 +++++++++++++++ dist/bootstrap-treeview.min.js | 2 +- public/index.html | 96 +++++++++++++++++++++ public/js/bootstrap-treeview.js | 145 ++++++++++++++++++++++++++++++-- src/js/bootstrap-treeview.js | 145 ++++++++++++++++++++++++++++++-- tests/lib/bootstrap-treeview.js | 145 ++++++++++++++++++++++++++++++-- tests/tests.js | 77 +++++++++++++++++ 7 files changed, 661 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 541d1216b..577e23ba2 100644 --- a/README.md +++ b/README.md @@ -453,6 +453,45 @@ $('#tree').treeview('collapseNode', [ nodeId, { silent: true, ignoreChildren: fa Triggers `nodeCollapsed` event; pass silent to suppress events. +#### disableAll(options) + +Disable all tree nodes + +```javascript +$('#tree').treeview('disableAll', { silent: true }); +``` + +Triggers `nodeDisabled` event; pass silent to suppress events. + +#### disableNode(node | nodeId, options) + +Disable a given tree node, accepts node or nodeId. + +```javascript +$('#tree').treeview('disableNode', [ nodeId, { silent: true } ]); +``` + +Triggers `nodeDisabled` event; pass silent to suppress events. + +#### enableAll(options) + +Enable all tree nodes + +```javascript +$('#tree').treeview('enableAll', { silent: true }); +``` + +Triggers `nodeEnabled` event; pass silent to suppress events. + +#### enableNode(node | nodeId, options) + +Enable a given tree node, accepts node or nodeId. + +```javascript +$('#tree').treeview('enableNode', [ nodeId, { silent: true } ]); +``` + +Triggers `nodeEnabled` event; pass silent to suppress events. #### expandAll(options) @@ -481,6 +520,23 @@ Returns an array of collapsed nodes e.g. state.expanded = false. ```javascript $('#tree').treeview('getCollapsed', nodeId); ``` + +#### getDisabled() + +Returns an array of disabled nodes e.g. state.disabled = true. + +```javascript +$('#tree').treeview('getDisabled', nodeId); +``` + +#### getEnabled() + +Returns an array of enabled nodes e.g. state.disabled = false. + +```javascript +$('#tree').treeview('getEnabled', nodeId); +``` + #### getExpanded() Returns an array of expanded nodes e.g. state.expanded = true. @@ -583,6 +639,16 @@ $('#tree').treeview('toggleNodeChecked', [ nodeId, { silent: true } ]); Triggers either `nodeChecked` or `nodeUnchecked` event; pass silent to suppress events. +#### toggleNodeDisabled(node | nodeId, options) + +Toggles a nodes disabled state; disabling if enabled, enabling if disabled. + +```javascript +$('#tree').treeview('toggleNodeDisabled', [ nodeId, { silent: true } ]); +``` + +Triggers either `nodeDisabled` or `nodeEnabled` event; pass silent to suppress events. + #### toggleNodeExpanded(node | nodeId, options) Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. @@ -665,6 +731,10 @@ $('#tree').on('nodeSelected', function(event, data) { `nodeCollapsed (event, node)` - A node is collapsed. +'nodeDisabled (event, node)' - A node is disabled. + +'nodeEnabled (event, node)' - A node is enabled. + `nodeExpanded (event, node)` - A node is expanded. `nodeSelected (event, node)` - A node is selected. diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 4cb798491..af479bb99 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                              ',item:'
                                                                            • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeDisabled:d,onNodeEnabled:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),getDisabled:a.proxy(this.getDisabled,this),getEnabled:a.proxy(this.getEnabled,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),disableAll:a.proxy(this.disableAll,this),disableNode:a.proxy(this.disableNode,this),enableAll:a.proxy(this.enableAll,this),enableNode:a.proxy(this.enableNode,this),toggleNodeDisabled:a.proxy(this.toggleNodeDisabled,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.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")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.setDisabledState=function(b,c,d){c!==b.state.disabled&&(c?(b.state.disabled=!0,this.setExpandedState(b,!1,d),this.setSelectedState(b,!1,d),this.setCheckedState(b,!1,d),d.silent||this.$element.trigger("nodeDisabled",a.extend(!0,{},b))):(b.state.disabled=!1,d.silent||this.$element.trigger("nodeEnabled",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){if(a.state.disabled)return"";var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&!a.state.disabled&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                                ',item:'
                                                                              • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},g.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.disableAll=function(b){var c=this.findNodes("false","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.disableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.enableAll=function(b){var c=this.findNodes("true","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.enableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeDisabled=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!a.state.disabled,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/index.html b/public/index.html index 9d46c22c9..6f23ccd23 100644 --- a/public/index.html +++ b/public/index.html @@ -242,6 +242,49 @@

                                                                                Events

                                                                                +
                                                                                +
                                                                                +

                                                                                Disabled Tree

                                                                                +
                                                                                +

                                                                                Input

                                                                                +
                                                                                + + +
                                                                                +
                                                                                + +
                                                                                +
                                                                                +
                                                                                + +
                                                                                +
                                                                                +
                                                                                + +
                                                                                +
                                                                                + +
                                                                                +
                                                                                +
                                                                                +
                                                                                + +
                                                                                +
                                                                                + +
                                                                                +
                                                                                +

                                                                                Tree

                                                                                +
                                                                                +
                                                                                +
                                                                                +

                                                                                Events

                                                                                +
                                                                                +
                                                                                +

                                                                                Data

                                                                                @@ -658,6 +701,59 @@

                                                                                + var $disabledTree = $('#treeview-disabled').treeview({ + data: defaultData, + onNodeDisabled: function(event, node) { + $('#disabled-output').prepend('

                                                                                ' + node.text + ' was disabled

                                                                                '); + }, + onNodeEnabled: function (event, node) { + $('#disabled-output').prepend('

                                                                                ' + node.text + ' was enabled

                                                                                '); + }, + onNodeCollapsed: function(event, node) { + $('#disabled-output').prepend('

                                                                                ' + node.text + ' was collapsed

                                                                                '); + }, + onNodeUnchecked: function (event, node) { + $('#disabled-output').prepend('

                                                                                ' + node.text + ' was unchecked

                                                                                '); + }, + onNodeUnselected: function (event, node) { + $('#disabled-output').prepend('

                                                                                ' + node.text + ' was unselected

                                                                                '); + } + }); + + var findDisabledNodes = function() { + return $disabledTree.treeview('search', [ $('#input-disable-node').val(), { ignoreCase: false, exactMatch: false } ]); + }; + var disabledNodes = findDisabledNodes(); + + // Expand/collapse/toggle nodes + $('#input-disable-node').on('keyup', function (e) { + disabledNodes = findDisabledNodes(); + $('.disable-node').prop('disabled', !(disabledNodes.length >= 1)); + }); + + $('#btn-disable-node.disable-node').on('click', function (e) { + $disabledTree.treeview('disableNode', [ disabledNodes, { silent: $('#chk-disable-silent').is(':checked') }]); + }); + + $('#btn-enable-node.disable-node').on('click', function (e) { + $disabledTree.treeview('enableNode', [ disabledNodes, { silent: $('#chk-disable-silent').is(':checked') }]); + }); + + $('#btn-toggle-disabled.disable-node').on('click', function (e) { + $disabledTree.treeview('toggleNodeDisabled', [ disabledNodes, { silent: $('#chk-disable-silent').is(':checked') }]); + }); + + // Expand/collapse all + $('#btn-disable-all').on('click', function (e) { + $disabledTree.treeview('disableAll', { silent: $('#chk-disable-silent').is(':checked') }); + }); + + $('#btn-enable-all').on('click', function (e) { + $disabledTree.treeview('enableAll', { silent: $('#chk-disable-silent').is(':checked') }); + }); + + + var $tree = $('#treeview12').treeview({ data: json }); diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index b371243c1..0047547b3 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -62,6 +62,8 @@ // Event handlers onNodeChecked: undefined, onNodeCollapsed: undefined, + onNodeDisabled: undefined, + onNodeEnabled: undefined, onNodeExpanded: undefined, onNodeSelected: undefined, onNodeUnchecked: undefined, @@ -108,6 +110,8 @@ getCollapsed: $.proxy(this.getCollapsed, this), getChecked: $.proxy(this.getChecked, this), getUnchecked: $.proxy(this.getUnchecked, this), + getDisabled: $.proxy(this.getDisabled, this), + getEnabled: $.proxy(this.getEnabled, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -129,6 +133,13 @@ uncheckNode: $.proxy(this.uncheckNode, this), toggleNodeChecked: $.proxy(this.toggleNodeChecked, this), + // Disable / enable methods + disableAll: $.proxy(this.disableAll, this), + disableNode: $.proxy(this.disableNode, this), + enableAll: $.proxy(this.enableAll, this), + enableNode: $.proxy(this.enableNode, this), + toggleNodeDisabled: $.proxy(this.toggleNodeDisabled, this), + // Search methods search: $.proxy(this.search, this), clearSearch: $.proxy(this.clearSearch, this) @@ -180,6 +191,8 @@ 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'); @@ -202,6 +215,14 @@ 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); } @@ -392,7 +413,7 @@ // Continue selecting node node.state.selected = true; if (!options.silent) { - this.$element.trigger('nodeSelected', $.extend(true, {}, node) ); + this.$element.trigger('nodeSelected', $.extend(true, {}, node)); } } else { @@ -400,7 +421,7 @@ // Unselect node node.state.selected = false; if (!options.silent) { - this.$element.trigger('nodeUnselected', $.extend(true, {}, node) ); + this.$element.trigger('nodeUnselected', $.extend(true, {}, node)); } } }; @@ -408,7 +429,7 @@ Tree.prototype.toggleCheckedState = function (node, options) { if (!node) return; this.setCheckedState(node, !node.state.checked, options); - } + }; Tree.prototype.setCheckedState = function (node, state, options) { @@ -420,7 +441,7 @@ node.state.checked = true; if (!options.silent) { - this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + this.$element.trigger('nodeChecked', $.extend(true, {}, node)); } } else { @@ -428,7 +449,35 @@ // Uncheck node node.state.checked = false; if (!options.silent) { - this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + this.$element.trigger('nodeUnchecked', $.extend(true, {}, node)); + } + } + }; + + Tree.prototype.setDisabledState = function (node, state, options) { + + if (state === node.state.disabled) return; + + if (state) { + + // Disable node + node.state.disabled = true; + + // Disable all other states + this.setExpandedState(node, false, options); + this.setSelectedState(node, false, options); + this.setCheckedState(node, false, options); + + if (!options.silent) { + this.$element.trigger('nodeDisabled', $.extend(true, {}, node)); + } + } + else { + + // Enabled node + node.state.disabled = false; + if (!options.silent) { + this.$element.trigger('nodeEnabled', $.extend(true, {}, node)); } } }; @@ -571,6 +620,8 @@ // 2. node|data assigned color overrides Tree.prototype.buildStyleOverride = function (node) { + if (node.state.disabled) return ''; + var color = node.color; var backColor = node.backColor; @@ -583,7 +634,7 @@ } } - if (this.options.highlightSearchResults && node.searchResult) { + if (this.options.highlightSearchResults && node.searchResult && !node.state.disabled) { if (this.options.searchResultColor) { color = this.options.searchResultColor; } @@ -727,6 +778,22 @@ return this.findNodes('false', 'g', 'state.checked'); }; + /** + Returns an array of disabled nodes. + @returns {Array} nodes - Disabled nodes + */ + Tree.prototype.getDisabled = function () { + return this.findNodes('true', 'g', 'state.disabled'); + }; + + /** + Returns an array of enabled nodes. + @returns {Array} nodes - Enabled nodes + */ + Tree.prototype.getEnabled = function () { + return this.findNodes('false', 'g', 'state.disabled'); + }; + /** Set a node state to selected @@ -938,6 +1005,72 @@ }; + /** + Disable all tree nodes + @param {optional Object} options + */ + Tree.prototype.disableAll = function (options) { + var identifiers = this.findNodes('false', 'g', 'state.disabled'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Disable a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.disableNode = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Enable all tree nodes + @param {optional Object} options + */ + Tree.prototype.enableAll = function (options) { + var identifiers = this.findNodes('true', 'g', 'state.disabled'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Enable a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.enableNode = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Toggles a nodes disabled state; disabling is enabled, enabling if disabled. + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.toggleNodeDisabled = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, !node.state.disabled, options); + }, this)); + + this.render(); + }; + + /** Common code for processing multiple identifiers */ diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index b371243c1..0047547b3 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -62,6 +62,8 @@ // Event handlers onNodeChecked: undefined, onNodeCollapsed: undefined, + onNodeDisabled: undefined, + onNodeEnabled: undefined, onNodeExpanded: undefined, onNodeSelected: undefined, onNodeUnchecked: undefined, @@ -108,6 +110,8 @@ getCollapsed: $.proxy(this.getCollapsed, this), getChecked: $.proxy(this.getChecked, this), getUnchecked: $.proxy(this.getUnchecked, this), + getDisabled: $.proxy(this.getDisabled, this), + getEnabled: $.proxy(this.getEnabled, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -129,6 +133,13 @@ uncheckNode: $.proxy(this.uncheckNode, this), toggleNodeChecked: $.proxy(this.toggleNodeChecked, this), + // Disable / enable methods + disableAll: $.proxy(this.disableAll, this), + disableNode: $.proxy(this.disableNode, this), + enableAll: $.proxy(this.enableAll, this), + enableNode: $.proxy(this.enableNode, this), + toggleNodeDisabled: $.proxy(this.toggleNodeDisabled, this), + // Search methods search: $.proxy(this.search, this), clearSearch: $.proxy(this.clearSearch, this) @@ -180,6 +191,8 @@ 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'); @@ -202,6 +215,14 @@ 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); } @@ -392,7 +413,7 @@ // Continue selecting node node.state.selected = true; if (!options.silent) { - this.$element.trigger('nodeSelected', $.extend(true, {}, node) ); + this.$element.trigger('nodeSelected', $.extend(true, {}, node)); } } else { @@ -400,7 +421,7 @@ // Unselect node node.state.selected = false; if (!options.silent) { - this.$element.trigger('nodeUnselected', $.extend(true, {}, node) ); + this.$element.trigger('nodeUnselected', $.extend(true, {}, node)); } } }; @@ -408,7 +429,7 @@ Tree.prototype.toggleCheckedState = function (node, options) { if (!node) return; this.setCheckedState(node, !node.state.checked, options); - } + }; Tree.prototype.setCheckedState = function (node, state, options) { @@ -420,7 +441,7 @@ node.state.checked = true; if (!options.silent) { - this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + this.$element.trigger('nodeChecked', $.extend(true, {}, node)); } } else { @@ -428,7 +449,35 @@ // Uncheck node node.state.checked = false; if (!options.silent) { - this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + this.$element.trigger('nodeUnchecked', $.extend(true, {}, node)); + } + } + }; + + Tree.prototype.setDisabledState = function (node, state, options) { + + if (state === node.state.disabled) return; + + if (state) { + + // Disable node + node.state.disabled = true; + + // Disable all other states + this.setExpandedState(node, false, options); + this.setSelectedState(node, false, options); + this.setCheckedState(node, false, options); + + if (!options.silent) { + this.$element.trigger('nodeDisabled', $.extend(true, {}, node)); + } + } + else { + + // Enabled node + node.state.disabled = false; + if (!options.silent) { + this.$element.trigger('nodeEnabled', $.extend(true, {}, node)); } } }; @@ -571,6 +620,8 @@ // 2. node|data assigned color overrides Tree.prototype.buildStyleOverride = function (node) { + if (node.state.disabled) return ''; + var color = node.color; var backColor = node.backColor; @@ -583,7 +634,7 @@ } } - if (this.options.highlightSearchResults && node.searchResult) { + if (this.options.highlightSearchResults && node.searchResult && !node.state.disabled) { if (this.options.searchResultColor) { color = this.options.searchResultColor; } @@ -727,6 +778,22 @@ return this.findNodes('false', 'g', 'state.checked'); }; + /** + Returns an array of disabled nodes. + @returns {Array} nodes - Disabled nodes + */ + Tree.prototype.getDisabled = function () { + return this.findNodes('true', 'g', 'state.disabled'); + }; + + /** + Returns an array of enabled nodes. + @returns {Array} nodes - Enabled nodes + */ + Tree.prototype.getEnabled = function () { + return this.findNodes('false', 'g', 'state.disabled'); + }; + /** Set a node state to selected @@ -938,6 +1005,72 @@ }; + /** + Disable all tree nodes + @param {optional Object} options + */ + Tree.prototype.disableAll = function (options) { + var identifiers = this.findNodes('false', 'g', 'state.disabled'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Disable a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.disableNode = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Enable all tree nodes + @param {optional Object} options + */ + Tree.prototype.enableAll = function (options) { + var identifiers = this.findNodes('true', 'g', 'state.disabled'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Enable a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.enableNode = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Toggles a nodes disabled state; disabling is enabled, enabling if disabled. + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.toggleNodeDisabled = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, !node.state.disabled, options); + }, this)); + + this.render(); + }; + + /** Common code for processing multiple identifiers */ diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index b371243c1..0047547b3 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -62,6 +62,8 @@ // Event handlers onNodeChecked: undefined, onNodeCollapsed: undefined, + onNodeDisabled: undefined, + onNodeEnabled: undefined, onNodeExpanded: undefined, onNodeSelected: undefined, onNodeUnchecked: undefined, @@ -108,6 +110,8 @@ getCollapsed: $.proxy(this.getCollapsed, this), getChecked: $.proxy(this.getChecked, this), getUnchecked: $.proxy(this.getUnchecked, this), + getDisabled: $.proxy(this.getDisabled, this), + getEnabled: $.proxy(this.getEnabled, this), // Select methods selectNode: $.proxy(this.selectNode, this), @@ -129,6 +133,13 @@ uncheckNode: $.proxy(this.uncheckNode, this), toggleNodeChecked: $.proxy(this.toggleNodeChecked, this), + // Disable / enable methods + disableAll: $.proxy(this.disableAll, this), + disableNode: $.proxy(this.disableNode, this), + enableAll: $.proxy(this.enableAll, this), + enableNode: $.proxy(this.enableNode, this), + toggleNodeDisabled: $.proxy(this.toggleNodeDisabled, this), + // Search methods search: $.proxy(this.search, this), clearSearch: $.proxy(this.clearSearch, this) @@ -180,6 +191,8 @@ 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'); @@ -202,6 +215,14 @@ 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); } @@ -392,7 +413,7 @@ // Continue selecting node node.state.selected = true; if (!options.silent) { - this.$element.trigger('nodeSelected', $.extend(true, {}, node) ); + this.$element.trigger('nodeSelected', $.extend(true, {}, node)); } } else { @@ -400,7 +421,7 @@ // Unselect node node.state.selected = false; if (!options.silent) { - this.$element.trigger('nodeUnselected', $.extend(true, {}, node) ); + this.$element.trigger('nodeUnselected', $.extend(true, {}, node)); } } }; @@ -408,7 +429,7 @@ Tree.prototype.toggleCheckedState = function (node, options) { if (!node) return; this.setCheckedState(node, !node.state.checked, options); - } + }; Tree.prototype.setCheckedState = function (node, state, options) { @@ -420,7 +441,7 @@ node.state.checked = true; if (!options.silent) { - this.$element.trigger('nodeChecked', $.extend(true, {}, node) ); + this.$element.trigger('nodeChecked', $.extend(true, {}, node)); } } else { @@ -428,7 +449,35 @@ // Uncheck node node.state.checked = false; if (!options.silent) { - this.$element.trigger('nodeUnchecked', $.extend(true, {}, node) ); + this.$element.trigger('nodeUnchecked', $.extend(true, {}, node)); + } + } + }; + + Tree.prototype.setDisabledState = function (node, state, options) { + + if (state === node.state.disabled) return; + + if (state) { + + // Disable node + node.state.disabled = true; + + // Disable all other states + this.setExpandedState(node, false, options); + this.setSelectedState(node, false, options); + this.setCheckedState(node, false, options); + + if (!options.silent) { + this.$element.trigger('nodeDisabled', $.extend(true, {}, node)); + } + } + else { + + // Enabled node + node.state.disabled = false; + if (!options.silent) { + this.$element.trigger('nodeEnabled', $.extend(true, {}, node)); } } }; @@ -571,6 +620,8 @@ // 2. node|data assigned color overrides Tree.prototype.buildStyleOverride = function (node) { + if (node.state.disabled) return ''; + var color = node.color; var backColor = node.backColor; @@ -583,7 +634,7 @@ } } - if (this.options.highlightSearchResults && node.searchResult) { + if (this.options.highlightSearchResults && node.searchResult && !node.state.disabled) { if (this.options.searchResultColor) { color = this.options.searchResultColor; } @@ -727,6 +778,22 @@ return this.findNodes('false', 'g', 'state.checked'); }; + /** + Returns an array of disabled nodes. + @returns {Array} nodes - Disabled nodes + */ + Tree.prototype.getDisabled = function () { + return this.findNodes('true', 'g', 'state.disabled'); + }; + + /** + Returns an array of enabled nodes. + @returns {Array} nodes - Enabled nodes + */ + Tree.prototype.getEnabled = function () { + return this.findNodes('false', 'g', 'state.disabled'); + }; + /** Set a node state to selected @@ -938,6 +1005,72 @@ }; + /** + Disable all tree nodes + @param {optional Object} options + */ + Tree.prototype.disableAll = function (options) { + var identifiers = this.findNodes('false', 'g', 'state.disabled'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Disable a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.disableNode = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, true, options); + }, this)); + + this.render(); + }; + + /** + Enable all tree nodes + @param {optional Object} options + */ + Tree.prototype.enableAll = function (options) { + var identifiers = this.findNodes('true', 'g', 'state.disabled'); + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Enable a given tree node + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.enableNode = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, false, options); + }, this)); + + this.render(); + }; + + /** + Toggles a nodes disabled state; disabling is enabled, enabling if disabled. + @param {Object|Number} identifiers - A valid node, node id or array of node identifiers + @param {optional Object} options + */ + Tree.prototype.toggleNodeDisabled = function (identifiers, options) { + this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { + this.setDisabledState(node, !node.state.disabled, options); + }, this)); + + this.render(); + }; + + /** Common code for processing multiple identifiers */ diff --git a/tests/tests.js b/tests/tests.js index 047e55ab9..8741774f3 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -113,6 +113,8 @@ equal(options.multiSelect, false, 'multiSelect default ok'); equal(options.onNodeChecked, null, 'onNodeChecked default ok'); equal(options.onNodeCollapsed, null, 'onNodeCollapsed default ok'); + equal(options.onNodeDisabled, null, 'onNodeDisabled default ok'); + equal(options.onNodeEnabled, null, 'onNodeEnabled default ok'); equal(options.onNodeExpanded, null, 'onNodeExpanded default ok'); equal(options.onNodeSelected, null, 'onNodeSelected default ok'); equal(options.onNodeUnchecked, null, 'onNodeUnchecked default ok'); @@ -148,6 +150,8 @@ multiSelect: true, onNodeChecked: function () {}, onNodeCollapsed: function () {}, + onNodeDisabled: function () {}, + onNodeEnabled: function () {}, onNodeExpanded: function () {}, onNodeSelected: function () {}, onNodeUnchecked: function () {}, @@ -184,6 +188,8 @@ equal(options.multiSelect, true, 'multiSelect set ok'); equal(typeof options.onNodeChecked, 'function', 'onNodeChecked set ok'); equal(typeof options.onNodeCollapsed, 'function', 'onNodeCollapsed set ok'); + equal(typeof options.onNodeDisabled, 'function', 'onNodeDisabled set ok'); + equal(typeof options.onNodeEnabled, 'function', 'onNodeEnabled set ok'); equal(typeof options.onNodeExpanded, 'function', 'onNodeExpanded set ok'); equal(typeof options.onNodeSelected, 'function', 'onNodeSelected set ok'); equal(typeof options.onNodeUnchecked, 'function', 'onNodeUnchecked set ok'); @@ -554,6 +560,77 @@ equal(uncheckedNodes.length, 8, 'Correct number of nodes returned'); }); + test('getDisabled', function () { + var $tree = init({ data: data }) + .treeview('disableNode', 0); + + var disabledNodes = $tree.treeview('getDisabled'); + ok((disabledNodes instanceof Array), 'Result is an array'); + equal(disabledNodes.length, 1, 'Correct number of nodes returned'); + equal(disabledNodes[0].text, 'Parent 1', 'Correct node returned'); + }); + + test('getEnabled', function () { + var $tree = init({ data: data }) + .treeview('disableNode', 0); + + var enabledNodes = $tree.treeview('getEnabled'); + ok((enabledNodes instanceof Array), 'Result is an array'); + equal(enabledNodes.length, 8, 'Correct number of nodes returned'); + }); + + test('disableAll / enableAll', function () { + var $tree = init({ data: data, levels: 1 }); + + $tree.treeview('disableAll'); + equal($($tree.selector + ' ul li.node-disabled').length, 5, 'Disable all works, 9 nodes with node-disabled class'); + + $tree.treeview('enableAll'); + equal($($tree.selector + ' ul li.node-disabled').length, 0, 'Check all works, 9 nodes non with node-disabled class'); + }); + + test('disableNode / enableNode', function () { + var $tree = init({ data: data, levels: 1 }); + var nodeId = 0; + var node = $tree.treeview('getNode', 0); + + // Disable node using node id + $tree.treeview('disableNode', nodeId); + ok($('.list-group-item:first').hasClass('node-disabled'), 'Disable node (by id) : Node has class node-disabled'); + ok(($('.node-disabled').length === 1), 'Disable node (by id) : There is only one disabled node'); + + // Enable node using node id + $tree.treeview('enableNode', nodeId); + ok(!$('.list-group-item:first').hasClass('node-disabled'), 'Enable node (by id) : Node does not have class node-disabled'); + ok(($('.node-checked').length === 0), 'Enable node (by id) : There are no disabled nodes'); + + // Disable node using node + $tree.treeview('disableNode', node); + ok($('.list-group-item:first').hasClass('node-disabled'), 'Disable node (by node) : Node has class node-disabled'); + ok(($('.node-disabled').length === 1), 'Disable node (by node) : There is only one disabled node'); + + // Enable node using node + $tree.treeview('enableNode', node); + ok(!$('.list-group-item:first').hasClass('node-disabled'), 'Enable node (by node) : Node does not have class node-disabled'); + ok(($('.node-checked').length === 0), 'Enable node (by node) : There are no disabled nodes'); + }); + + test('toggleNodeDisabled', function () { + var $tree = init({ data: data, levels: 1 }); + var nodeId = 0; + var node = $tree.treeview('getNode', 0); + + // Toggle disabled using node id + $tree.treeview('toggleNodeDisabled', nodeId); + ok($('.list-group-item:first').hasClass('node-disabled'), 'Toggle node (by id) : Node has class node-disabled'); + ok(($('.node-disabled').length === 1), 'Toggle node (by id) : There is only one disabled node'); + + // Toggle disabled using node + $tree.treeview('toggleNodeDisabled', node); + ok(!$('.list-group-item:first').hasClass('node-disabled'), 'Toggle node (by node) : Node does not have class node-disabled'); + ok(($('.node-disabled').length === 0), 'Toggle node (by node) : There are no disabled nodes'); + }); + test('checkAll / uncheckAll', function () { var $tree = init({ data: data, levels: 3, showCheckbox: true }); From de8bd7e5aa594d50352664c012e45c8da1117d50 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 9 May 2015 13:07:13 +0100 Subject: [PATCH 31/36] Release notes updated to include checkbox + disable node changes --- CHANGELOG.md | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38292cacb..0500daf9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,32 +5,68 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## v1.2.0 - [Unreleased] ### New Features + +- Disable nodes, allow a tree node to disabled (not selectable, expandable or checkable) + + - Added node state property `disabled` to set a node initial state + + - Methods `disableAll`, `disableNode`, `enableAll`, `enableNode` and `toggleNodeDisabled` added to control state programmatically + + - Events `nodeDisabled` and `nodeEnabled` + +- Checkable nodes, allows a tree node to be checked or unchecked. + + - Added node state property `checked` to set a node initial state + + - Pass option `{showCheckbox: true}` to initialize tree view with checkboxes + + - Use options `checkedIcon` and `uncheckedIcon` to configure checkbox icons + + - Methods `checkAll`, `checkNode`, `uncheckAll`, `uncheckNode` and `toggleNodeChecked` to control state programmatically + + - Events `nodeChecked` and `nodeUnchecked` + - New option + node property `selectedIcon` to support displaying different icons when a node is selected. + - New search option `{ revealResults : true | false }` which when set to true will automatically expand the tree view to reveal matching nodes + - New method `revealNode` which expands the tree view to reveal a given node -- New methods `getSelected`, `getUnselected`, `getExpanded` and `getCollapsed` to retrieve nodes by state + +- New methods to retrieve nodes by state : `getSelected`, `getUnselected`, `getExpanded`, `getCollapsed`, `getChecked`, `getUnchecked`, `getDisabled` and `getEnabled`. ### Changes -- By default search will expand tree view and reveal results +- Search behaviour, by default search will the expand tree view and reveal results. Alternatively pass `{revealResults:false}`. + - Method collapseNode accepts new option `{ ignoreChildren: true | false }`. The default is false, passing true will leave child nodes uncollapsed ### Bug Fixes - Child nodes should collapse by default on collapseNode + - Incorrect expand collapse icon displayed when nodes array is empty -## v1.1.0 - 29th March, 2015 +## v1.1.0 - 29th March, 2015 ### New Features + - Added node state properties `expanded` and `selected` so a node's intial state can be set + - New get methods `getNode`, `getParent` and `getSiblings` for retrieving nodes and their immediate relations + - New select methods `selectNode`, `unselectNode` and `toggleNodeSelected` + - Adding `nodeUnselected` event + - New global option `multiSelect` which allows multiple nodes to hold the selected state, default is false + - New expand collapse methods `expandAll`, `collapseAll`, `expandNode`, `collapseNode` and `toggleNodeExpanded` + - Adding events `nodeExpanded` and `nodeCollapsed` + - New methods `search` and `clearSearch` which allow you to query the tree view for nodes based on a `text` value + - Adding events `searchComplete` and `searchCleared` + - New global options `highlightSearchResults`, `searchResultColor` and `searchResultBackColor` for configuring how search results are displayed @@ -41,4 +77,5 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Bug Fixes - Events not unbound when re-initialised + - CSS selectors too general, affecting other page elements From 712f1c1b9917783d7fc784f7590ff9e3c0846a96 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 9 May 2015 13:25:48 +0100 Subject: [PATCH 32/36] Fix for #77, stops unnecessary re-render when calling search --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 29 +++++++++++++++++------------ src/js/bootstrap-treeview.js | 29 +++++++++++++++++------------ tests/lib/bootstrap-treeview.js | 29 +++++++++++++++++------------ 4 files changed, 52 insertions(+), 37 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index af479bb99..f1f179645 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeDisabled:d,onNodeEnabled:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),getDisabled:a.proxy(this.getDisabled,this),getEnabled:a.proxy(this.getEnabled,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),disableAll:a.proxy(this.disableAll,this),disableNode:a.proxy(this.disableNode,this),enableAll:a.proxy(this.enableAll,this),enableNode:a.proxy(this.enableNode,this),toggleNodeDisabled:a.proxy(this.toggleNodeDisabled,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.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")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.setDisabledState=function(b,c,d){c!==b.state.disabled&&(c?(b.state.disabled=!0,this.setExpandedState(b,!1,d),this.setSelectedState(b,!1,d),this.setCheckedState(b,!1,d),d.silent||this.$element.trigger("nodeDisabled",a.extend(!0,{},b))):(b.state.disabled=!1,d.silent||this.$element.trigger("nodeEnabled",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){if(a.state.disabled)return"";var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&!a.state.disabled&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                                  ',item:'
                                                                                • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},g.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.disableAll=function(b){var c=this.findNodes("false","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.disableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.enableAll=function(b){var c=this.findNodes("true","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.enableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeDisabled=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!a.state.disabled,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch();var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0}),c.revealResults?this.revealNode(d):this.render()}return this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(){var b=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},b))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeDisabled:d,onNodeEnabled:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),getDisabled:a.proxy(this.getDisabled,this),getEnabled:a.proxy(this.getEnabled,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),disableAll:a.proxy(this.disableAll,this),disableNode:a.proxy(this.disableNode,this),enableAll:a.proxy(this.enableAll,this),enableNode:a.proxy(this.enableNode,this),toggleNodeDisabled:a.proxy(this.toggleNodeDisabled,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.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")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.setDisabledState=function(b,c,d){c!==b.state.disabled&&(c?(b.state.disabled=!0,this.setExpandedState(b,!1,d),this.setSelectedState(b,!1,d),this.setCheckedState(b,!1,d),d.silent||this.$element.trigger("nodeDisabled",a.extend(!0,{},b))):(b.state.disabled=!1,d.silent||this.$element.trigger("nodeEnabled",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){if(a.state.disabled)return"";var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&!a.state.disabled&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                                    ',item:'
                                                                                  • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},g.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.disableAll=function(b){var c=this.findNodes("false","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.disableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.enableAll=function(b){var c=this.findNodes("true","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.enableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeDisabled=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!a.state.disabled,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch({render:!1});var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0})}return c.revealResults?this.revealNode(d):this.render(),this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(b){b=a.extend({},{render:!0},b);var c=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});b.render&&this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},c))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 0047547b3..8c6b4a7df 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -1105,7 +1105,7 @@ Tree.prototype.search = function (pattern, options) { options = $.extend({}, _default.searchOptions, options); - this.clearSearch(); + this.clearSearch({ render: false }); var results = []; if (pattern && pattern.length > 0) { @@ -1127,15 +1127,15 @@ $.each(results, function (index, node) { node.searchResult = true; }) + } - // If revealResults, then render is triggered from revealNode - // otherwise we just call render. - if (options.revealResults) { - this.revealNode(results); - } - else { - this.render(); - } + // If revealResults, then render is triggered from revealNode + // otherwise we just call render. + if (options.revealResults) { + this.revealNode(results); + } + else { + this.render(); } this.$element.trigger('searchComplete', $.extend(true, {}, results)); @@ -1146,14 +1146,19 @@ /** Clears previous search results */ - Tree.prototype.clearSearch = function () { + Tree.prototype.clearSearch = function (options) { + + options = $.extend({}, { render: true }, options); var results = $.each(this.findNodes('true', 'g', 'searchResult'), function (index, node) { node.searchResult = false; }); - this.render(); - + // TEMP FIX UNTIL #50 + #76 + if (options.render) { + this.render(); + } + this.$element.trigger('searchCleared', $.extend(true, {}, results)); }; diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 0047547b3..8c6b4a7df 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -1105,7 +1105,7 @@ Tree.prototype.search = function (pattern, options) { options = $.extend({}, _default.searchOptions, options); - this.clearSearch(); + this.clearSearch({ render: false }); var results = []; if (pattern && pattern.length > 0) { @@ -1127,15 +1127,15 @@ $.each(results, function (index, node) { node.searchResult = true; }) + } - // If revealResults, then render is triggered from revealNode - // otherwise we just call render. - if (options.revealResults) { - this.revealNode(results); - } - else { - this.render(); - } + // If revealResults, then render is triggered from revealNode + // otherwise we just call render. + if (options.revealResults) { + this.revealNode(results); + } + else { + this.render(); } this.$element.trigger('searchComplete', $.extend(true, {}, results)); @@ -1146,14 +1146,19 @@ /** Clears previous search results */ - Tree.prototype.clearSearch = function () { + Tree.prototype.clearSearch = function (options) { + + options = $.extend({}, { render: true }, options); var results = $.each(this.findNodes('true', 'g', 'searchResult'), function (index, node) { node.searchResult = false; }); - this.render(); - + // TEMP FIX UNTIL #50 + #76 + if (options.render) { + this.render(); + } + this.$element.trigger('searchCleared', $.extend(true, {}, results)); }; diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 0047547b3..8c6b4a7df 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -1105,7 +1105,7 @@ Tree.prototype.search = function (pattern, options) { options = $.extend({}, _default.searchOptions, options); - this.clearSearch(); + this.clearSearch({ render: false }); var results = []; if (pattern && pattern.length > 0) { @@ -1127,15 +1127,15 @@ $.each(results, function (index, node) { node.searchResult = true; }) + } - // If revealResults, then render is triggered from revealNode - // otherwise we just call render. - if (options.revealResults) { - this.revealNode(results); - } - else { - this.render(); - } + // If revealResults, then render is triggered from revealNode + // otherwise we just call render. + if (options.revealResults) { + this.revealNode(results); + } + else { + this.render(); } this.$element.trigger('searchComplete', $.extend(true, {}, results)); @@ -1146,14 +1146,19 @@ /** Clears previous search results */ - Tree.prototype.clearSearch = function () { + Tree.prototype.clearSearch = function (options) { + + options = $.extend({}, { render: true }, options); var results = $.each(this.findNodes('true', 'g', 'searchResult'), function (index, node) { node.searchResult = false; }); - this.render(); - + // TEMP FIX UNTIL #50 + #76 + if (options.render) { + this.render(); + } + this.$element.trigger('searchCleared', $.extend(true, {}, results)); }; From bc33cabbcfc2c73dde4f75ed437b0a808e07ce92 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 9 May 2015 14:24:32 +0100 Subject: [PATCH 33/36] Removed nodeIcon by default #3 --- dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 14 ++-- src/js/bootstrap-treeview.js | 14 ++-- tests/lib/bootstrap-treeview.js | 14 ++-- tests/tests.js | 137 +++++++++++++++++--------------- 5 files changed, 93 insertions(+), 88 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index f1f179645..9e2803815 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"glyphicon glyphicon-stop",selectedIcon:"glyphicon glyphicon-stop",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeDisabled:d,onNodeEnabled:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),getDisabled:a.proxy(this.getDisabled,this),getEnabled:a.proxy(this.getEnabled,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),disableAll:a.proxy(this.disableAll,this),disableNode:a.proxy(this.disableNode,this),enableAll:a.proxy(this.enableAll,this),enableNode:a.proxy(this.enableNode,this),toggleNodeDisabled:a.proxy(this.toggleNodeDisabled,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.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")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.setDisabledState=function(b,c,d){c!==b.state.disabled&&(c?(b.state.disabled=!0,this.setExpandedState(b,!1,d),this.setSelectedState(b,!1,d),this.setCheckedState(b,!1,d),d.silent||this.$element.trigger("nodeDisabled",a.extend(!0,{},b))):(b.state.disabled=!1,d.silent||this.$element.trigger("nodeEnabled",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.state.selected?e.selectedIcon||d.options.selectedIcon:e.icon||d.options.nodeIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){if(a.state.disabled)return"";var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&!a.state.disabled&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                                      ',item:'
                                                                                    • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},g.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.disableAll=function(b){var c=this.findNodes("false","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.disableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.enableAll=function(b){var c=this.findNodes("true","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.enableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeDisabled=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!a.state.disabled,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch({render:!1});var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0})}return c.revealResults?this.revealNode(d):this.render(),this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(b){b=a.extend({},{render:!0},b);var c=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});b.render&&this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},c))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"",selectedIcon:"",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeDisabled:d,onNodeEnabled:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),getDisabled:a.proxy(this.getDisabled,this),getEnabled:a.proxy(this.getEnabled,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),disableAll:a.proxy(this.disableAll,this),disableNode:a.proxy(this.disableNode,this),enableAll:a.proxy(this.enableAll,this),enableNode:a.proxy(this.enableNode,this),toggleNodeDisabled:a.proxy(this.toggleNodeDisabled,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.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")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.setDisabledState=function(b,c,d){c!==b.state.disabled&&(c?(b.state.disabled=!0,this.setExpandedState(b,!1,d),this.setSelectedState(b,!1,d),this.setCheckedState(b,!1,d),d.silent||this.$element.trigger("nodeDisabled",a.extend(!0,{},b))):(b.state.disabled=!1,d.silent||this.$element.trigger("nodeEnabled",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.icon||d.options.nodeIcon),e.state.selected&&(h.pop(),h.push(e.selectedIcon||d.options.selectedIcon||e.icon||d.options.nodeIcon)),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){if(a.state.disabled)return"";var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&!a.state.disabled&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'
                                                                                        ',item:'
                                                                                      • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},g.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.disableAll=function(b){var c=this.findNodes("false","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.disableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.enableAll=function(b){var c=this.findNodes("true","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.enableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeDisabled=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!a.state.disabled,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch({render:!1});var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0})}return c.revealResults?this.revealNode(d):this.render(),this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(b){b=a.extend({},{render:!0},b);var c=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});b.render&&this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},c))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 8c6b4a7df..163b77e8d 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -36,8 +36,8 @@ expandIcon: 'glyphicon glyphicon-plus', collapseIcon: 'glyphicon glyphicon-minus', emptyIcon: 'glyphicon', - nodeIcon: 'glyphicon glyphicon-stop', - selectedIcon: 'glyphicon glyphicon-stop', + nodeIcon: '', + selectedIcon: '', checkedIcon: 'glyphicon glyphicon-check', uncheckedIcon: 'glyphicon glyphicon-unchecked', @@ -550,11 +550,12 @@ if (_this.options.showIcon) { var classList = ['node-icon']; + + classList.push(node.icon || _this.options.nodeIcon); if (node.state.selected) { - classList.push(node.selectedIcon || _this.options.selectedIcon); - } - else { - classList.push(node.icon || _this.options.nodeIcon); + classList.pop(); + classList.push(node.selectedIcon || _this.options.selectedIcon || + node.icon || _this.options.nodeIcon); } treeItem @@ -1154,7 +1155,6 @@ node.searchResult = false; }); - // TEMP FIX UNTIL #50 + #76 if (options.render) { this.render(); } diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 8c6b4a7df..163b77e8d 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -36,8 +36,8 @@ expandIcon: 'glyphicon glyphicon-plus', collapseIcon: 'glyphicon glyphicon-minus', emptyIcon: 'glyphicon', - nodeIcon: 'glyphicon glyphicon-stop', - selectedIcon: 'glyphicon glyphicon-stop', + nodeIcon: '', + selectedIcon: '', checkedIcon: 'glyphicon glyphicon-check', uncheckedIcon: 'glyphicon glyphicon-unchecked', @@ -550,11 +550,12 @@ if (_this.options.showIcon) { var classList = ['node-icon']; + + classList.push(node.icon || _this.options.nodeIcon); if (node.state.selected) { - classList.push(node.selectedIcon || _this.options.selectedIcon); - } - else { - classList.push(node.icon || _this.options.nodeIcon); + classList.pop(); + classList.push(node.selectedIcon || _this.options.selectedIcon || + node.icon || _this.options.nodeIcon); } treeItem @@ -1154,7 +1155,6 @@ node.searchResult = false; }); - // TEMP FIX UNTIL #50 + #76 if (options.render) { this.render(); } diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 8c6b4a7df..163b77e8d 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -36,8 +36,8 @@ expandIcon: 'glyphicon glyphicon-plus', collapseIcon: 'glyphicon glyphicon-minus', emptyIcon: 'glyphicon', - nodeIcon: 'glyphicon glyphicon-stop', - selectedIcon: 'glyphicon glyphicon-stop', + nodeIcon: '', + selectedIcon: '', checkedIcon: 'glyphicon glyphicon-check', uncheckedIcon: 'glyphicon glyphicon-unchecked', @@ -550,11 +550,12 @@ if (_this.options.showIcon) { var classList = ['node-icon']; + + classList.push(node.icon || _this.options.nodeIcon); if (node.state.selected) { - classList.push(node.selectedIcon || _this.options.selectedIcon); - } - else { - classList.push(node.icon || _this.options.nodeIcon); + classList.pop(); + classList.push(node.selectedIcon || _this.options.selectedIcon || + node.icon || _this.options.nodeIcon); } treeItem @@ -1154,7 +1155,6 @@ node.searchResult = false; }); - // TEMP FIX UNTIL #50 + #76 if (options.render) { this.render(); } diff --git a/tests/tests.js b/tests/tests.js index 8741774f3..421b789e2 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -91,8 +91,8 @@ equal(options.expandIcon, 'glyphicon glyphicon-plus', 'expandIcon default ok'); equal(options.collapseIcon, 'glyphicon glyphicon-minus', 'collapseIcon default ok'); equal(options.emptyIcon, 'glyphicon', 'emptyIcon default ok'); - equal(options.nodeIcon, 'glyphicon glyphicon-stop', 'nodeIcon default ok'); - equal(options.selectedIcon, 'glyphicon glyphicon-stop', 'selectedIcon default ok'); + equal(options.nodeIcon, '', 'nodeIcon default ok'); + equal(options.selectedIcon, '', 'selectedIcon default ok'); equal(options.checkedIcon, 'glyphicon glyphicon-check', 'checkedIcon default ok'); equal(options.uncheckedIcon, 'glyphicon glyphicon-unchecked', 'uncheckedIcon default ok'); equal(options.color, undefined, 'color default ok'); @@ -128,7 +128,7 @@ expandIcon: 'glyphicon glyphicon-expand', collapseIcon: 'glyphicon glyphicon-collapse', emptyIcon: 'glyphicon', - nodeIcon: 'glyphicon glyphicon-node', + nodeIcon: 'glyphicon glyphicon-stop', selectedIcon: 'glyphicon glyphicon-selected', checkedIcon: 'glyphicon glyphicon-checked-icon', uncheckedIcon: 'glyphicon glyphicon-unchecked-icon', @@ -166,7 +166,7 @@ equal(options.expandIcon, 'glyphicon glyphicon-expand', 'expandIcon set ok'); equal(options.collapseIcon, 'glyphicon glyphicon-collapse', 'collapseIcon set ok'); equal(options.emptyIcon, 'glyphicon', 'emptyIcon set ok'); - equal(options.nodeIcon, 'glyphicon glyphicon-node', 'nodeIcon set ok'); + equal(options.nodeIcon, 'glyphicon glyphicon-stop', 'nodeIcon set ok'); equal(options.selectedIcon, 'glyphicon glyphicon-selected', 'selectedIcon set ok'); equal(options.checkedIcon, 'glyphicon glyphicon-checked-icon', 'checkedIcon set ok'); equal(options.uncheckedIcon, 'glyphicon glyphicon-unchecked-icon', 'uncheckedIcon set ok'); @@ -280,7 +280,7 @@ test('Selecting a node', function () { var cbWorked, onWorked = false; - init({ + var $tree = init({ data: data, onNodeSelected: function(/*event, date*/) { cbWorked = true; @@ -289,38 +289,30 @@ .on('nodeSelected', function(/*event, date*/) { onWorked = true; }); + var options = getOptions($tree); - var el = $('.list-group-item:first'); - el.trigger('click'); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Node is correctly selected : class "node-selected" added'); - ok(($('.node-selected').length === 1), 'There is only one selected node'); - ok(cbWorked, 'onNodeSelected function was called'); - ok(onWorked, 'nodeSelected was fired'); - }); - - test('Selecting multiple nodes (multiSelect true)', function () { - - init({ - data: data, - multiSelect: true - }); + // Simulate click + $('.list-group-item:first').trigger('click'); - var $firstEl = $('.list-group-item:nth-child(1)').trigger('click'); - var $secondEl = $('.list-group-item:nth-child(2)').trigger('click'); + // Has class node-selected + ok($('.list-group-item:first').hasClass('node-selected'), 'Node is correctly selected : class "node-selected" added'); + + // Only one can be selected + ok(($('.node-selected').length === 1), 'There is only one selected node'); - $firstEl = $('.list-group-item:nth-child(1)'); - $secondEl = $('.list-group-item:nth-child(2)'); + // Has correct icon + var iconClass = options.selectedIcon || options.nodeIcon; + ok(!iconClass || $('.expand-icon:first').hasClass(iconClass), 'Node icon is correct'); - ok(($firstEl.attr('class').split(' ').indexOf('node-selected') !== -1), 'First node is correctly selected : class "node-selected" added'); - ok(($secondEl.attr('class').split(' ').indexOf('node-selected') !== -1), 'Second node is correctly selected : class "node-selected" added'); - ok(($('.node-selected').length === 2), 'There are two selected nodes'); + // Events triggered + ok(cbWorked, 'onNodeSelected function was called'); + ok(onWorked, 'nodeSelected was fired'); }); test('Unselecting a node', function () { var cbWorked, onWorked = false; - init({ + var $tree = init({ data: data, onNodeUnselected: function(/*event, date*/) { cbWorked = true; @@ -329,22 +321,47 @@ .on('nodeUnselected', function(/*event, date*/) { onWorked = true; }); + var options = getOptions($tree); // First select a node - var el = $('.list-group-item:first'); - el.trigger('click'); - - // Then test unselect by simulating another click + $('.list-group-item:first').trigger('click'); cbWorked = onWorked = false; - el = $('.list-group-item:first'); - el.trigger('click'); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Node is correctly unselected : class "node-selected" removed'); + + // Simulate click + $('.list-group-item:first').trigger('click'); + + // Has class node-selected + ok(!$('.list-group-item:first').hasClass('node-selected'), 'Node is correctly unselected : class "node-selected" removed'); + + // Only one can be selected ok(($('.node-selected').length === 0), 'There are no selected nodes'); + + // Has correct icon + ok(!options.nodeIcon || $('.expand-icon:first').hasClass(options.nodeIcon), 'Node icon is correct'); + + // Events triggered ok(cbWorked, 'onNodeUnselected function was called'); ok(onWorked, 'nodeUnselected was fired'); }); + test('Selecting multiple nodes (multiSelect true)', function () { + + init({ + data: data, + multiSelect: true + }); + + var $firstEl = $('.list-group-item:nth-child(1)').trigger('click'); + var $secondEl = $('.list-group-item:nth-child(2)').trigger('click'); + + $firstEl = $('.list-group-item:nth-child(1)'); + $secondEl = $('.list-group-item:nth-child(2)'); + + ok($firstEl.hasClass('node-selected'), 'First node is correctly selected : class "node-selected" added'); + ok($secondEl.hasClass('node-selected'), 'Second node is correctly selected : class "node-selected" added'); + ok(($('.node-selected').length === 2), 'There are two selected nodes'); + }); + test('Clicking a non-selectable, collapsed node expands the node', function () { var testData = $.extend(true, {}, data); testData[0].selectable = false; @@ -651,27 +668,27 @@ // Check node using node id $tree.treeview('checkNode', nodeId); - ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') !== -1), 'Check node (by id) : Node is checked'); + ok($('.list-group-item:first').hasClass('node-checked'), 'Check node (by id) : Node has class node-checked'); ok(($('.node-checked').length === 1), 'Check node (by id) : There is only one checked node'); - ok(($('.check-icon:first').attr('class').indexOf(options.checkedIcon) !== -1), 'Check node (by id) : Node icon is correct'); + ok($('.check-icon:first').hasClass(options.checkedIcon), 'Check node (by id) : Node icon is correct'); // Uncheck node using node id $tree.treeview('uncheckNode', nodeId); - ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') === -1), 'Uncheck node (by id) : Node is no longer checked'); + ok(!$('.list-group-item:first').hasClass('node-checked'), 'Uncheck node (by id) : Node does not have class node-checked'); ok(($('.node-checked').length === 0), 'Uncheck node (by id) : There are no checked nodes'); - ok(($('.check-icon:first').attr('class').indexOf(options.uncheckedIcon) !== -1), 'Uncheck node (by id) : Node icon is correct'); + ok($('.check-icon:first').hasClass(options.uncheckedIcon), 'Uncheck node (by id) : Node icon is correct'); // Check node using node $tree.treeview('checkNode', node); - ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') !== -1), 'Check node (by node) : Node is checked'); + ok($('.list-group-item:first').hasClass('node-checked'), 'Check node (by node) : Node has class node-checked'); ok(($('.node-checked').length === 1), 'Check node (by node) : There is only one checked node'); - ok(($('.check-icon:first').attr('class').indexOf(options.checkedIcon) !== -1), 'Check node (by node) : Node icon is correct'); + ok($('.check-icon:first').hasClass(options.checkedIcon), 'Check node (by node) : Node icon is correct'); // Uncheck node using node $tree.treeview('uncheckNode', node); - ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') === -1), 'Uncheck node (by node) : Node is no longer checked'); + ok(!$('.list-group-item:first').hasClass('node-checked'), 'Uncheck node (by node) : Node does not have class node-checked'); ok(($('.node-checked').length === 0), 'Uncheck node (by node) : There are no checked nodes'); - ok(($('.check-icon:first').attr('class').indexOf(options.uncheckedIcon) !== -1), 'Uncheck node (by node) : Node icon is correct'); + ok($('.check-icon:first').hasClass(options.uncheckedIcon), 'Uncheck node (by node) : Node icon is correct'); }); test('toggleNodeChecked', function () { @@ -682,68 +699,56 @@ // Toggle checked using node id $tree.treeview('toggleNodeChecked', nodeId); - ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') !== -1), 'Toggle node (by id) : Node is checked'); + ok($('.list-group-item:first').hasClass('node-checked'), 'Toggle node (by id) : Node has class node-checked'); ok(($('.node-checked').length === 1), 'Toggle node (by id) : There is only one checked node'); - ok(($('.check-icon:first').attr('class').indexOf(options.checkedIcon) !== -1), 'Check node (by id) : Node icon is correct'); + ok($('.check-icon:first').hasClass(options.checkedIcon), 'Toggle node (by id) : Node icon is correct'); // Toggle checked using node $tree.treeview('toggleNodeChecked', node); - ok(($('.list-group-item:first').attr('class').split(' ').indexOf('node-checked') === -1), 'Toggle node (by node) : Node is unchecked'); + ok(!$('.list-group-item:first').hasClass('node-checked'), 'Toggle node (by node) : Node does not have class node-checked'); ok(($('.node-checked').length === 0), 'Toggle node (by node) : There are no checked nodes'); - ok(($('.check-icon:first').attr('class').indexOf(options.uncheckedIcon) !== -1), 'Uncheck node (by id) : Node icon is correct'); + ok($('.check-icon:first').hasClass(options.uncheckedIcon), 'Toggle node (by node) : Node icon is correct'); }); test('selectNode / unselectNode', function () { var $tree = init({ data: data, selectedIcon: 'glyphicon glyphicon-selected' }); - var el; var nodeId = 0; var node = $tree.treeview('getNode', 0); // Select node using node id $tree.treeview('selectNode', nodeId); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by id) : Node is selected'); - ok((el.find('.node-icon').attr('class').indexOf('glyphicon glyphicon-selected') !== -1), 'Select node (by id) : Node icon is correct'); + ok($('.list-group-item:first').hasClass('node-selected'), 'Select node (by id) : Node has class node-selected'); ok(($('.node-selected').length === 1), 'Select node (by id) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', nodeId); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Unselect node (by id) : Node is no longer selected'); - ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Unselect node (by id) : Node icon is correct'); + ok(!$('.list-group-item:first').hasClass('node-selected'), 'Unselect node (by id) : Node does not have class node-selected'); ok(($('.node-selected').length === 0), 'Unselect node (by id) : There are no selected nodes'); // Select node using node $tree.treeview('selectNode', node); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Select node (by node) : Node is selected'); - ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-selected') !== -1), 'Select node (by node) : Node icon is correct'); + ok($('.list-group-item:first').hasClass('node-selected'), 'Select node (by node) : Node has class node-selected'); ok(($('.node-selected').length === 1), 'Select node (by node) : There is only one selected node'); // Unselect node using node id $tree.treeview('unselectNode', node); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Unselect node (by node) : Node is no longer selected'); - ok((el.find('.node-icon').attr('class').indexOf('icon node-icon glyphicon glyphicon-stop') !== -1), 'Unselect node (by node) : Node icon is correct'); + ok(!$('.list-group-item:first').hasClass('node-selected'), 'Unselect node (by node) : Node does not have class node-selected'); ok(($('.node-selected').length === 0), 'Unselect node (by node) : There are no selected nodes'); }); test('toggleNodeSelected', function () { var $tree = init({ data: data }); - var el; var nodeId = 0; var node = $tree.treeview('getNode', 0); // Toggle selected using node id $tree.treeview('toggleNodeSelected', nodeId); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') !== -1), 'Toggle node (by id) : Node is selected'); + ok($('.list-group-item:first').hasClass('node-selected'), 'Toggle node (by id) : Node has class node-selected'); ok(($('.node-selected').length === 1), 'Toggle node (by id) : There is only one selected node'); // Toggle selected using node $tree.treeview('toggleNodeSelected', node); - el = $('.list-group-item:first'); - ok((el.attr('class').split(' ').indexOf('node-selected') === -1), 'Toggle node (by node) : Node is unselected'); + ok(!$('.list-group-item:first').hasClass('node-selected'), 'Toggle node (by id) : Node does not have class node-selected'); ok(($('.node-selected').length === 0), 'Toggle node (by node) : There are no selected nodes'); }); From 9093e15b42bb374013ce0be8a0069e066b6fabfa Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 9 May 2015 15:15:25 +0100 Subject: [PATCH 34/36] Release notes updated --- CHANGELOG.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0500daf9a..a90b082c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## v1.2.0 - [Unreleased] +## v1.2.0 - 9th May, 2015 ### New Features @@ -32,19 +32,27 @@ This project adheres to [Semantic Versioning](http://semver.org/). - New method `revealNode` which expands the tree view to reveal a given node -- New methods to retrieve nodes by state : `getSelected`, `getUnselected`, `getExpanded`, `getCollapsed`, `getChecked`, `getUnchecked`, `getDisabled` and `getEnabled`. +- New methods to retrieve nodes by state : `getSelected`, `getUnselected`, `getExpanded`, `getCollapsed`, `getChecked`, `getUnchecked`, `getDisabled` and `getEnabled` + ### Changes -- Search behaviour, by default search will the expand tree view and reveal results. Alternatively pass `{revealResults:false}`. +- Removed nodeIcon by default, by popular demand. Use `{nodeIcon: 'glyphicon glyphicon-stop'}` in initial options to add a node icon. + +- Search behaviour, by default search will the expand tree view and reveal results. Alternatively pass `{revealResults:false}` - Method collapseNode accepts new option `{ ignoreChildren: true | false }`. The default is false, passing true will leave child nodes uncollapsed + ### Bug Fixes +- Remove unnecessary render in clearSearch when called from search + - Child nodes should collapse by default on collapseNode - Incorrect expand collapse icon displayed when nodes array is empty + + ## v1.1.0 - 29th March, 2015 ### New Features @@ -70,6 +78,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - New global options `highlightSearchResults`, `searchResultColor` and `searchResultBackColor` for configuring how search results are displayed + + ## v1.0.2 - 6th February, 2015 ### Changes From dddb27caa973604bbe80a406272a83ee2c3c2463 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 9 May 2015 15:15:55 +0100 Subject: [PATCH 35/36] README fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 577e23ba2..8422ce045 100644 --- a/README.md +++ b/README.md @@ -731,9 +731,9 @@ $('#tree').on('nodeSelected', function(event, data) { `nodeCollapsed (event, node)` - A node is collapsed. -'nodeDisabled (event, node)' - A node is disabled. +`nodeDisabled (event, node)` - A node is disabled. -'nodeEnabled (event, node)' - A node is enabled. +`nodeEnabled (event, node)` - A node is enabled. `nodeExpanded (event, node)` - A node is expanded. From c6dfae18f174413827a03172007c69c13917ca2b Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 9 May 2015 15:21:01 +0100 Subject: [PATCH 36/36] Version updated to v1.2.0 --- README.md | 2 +- bower.json | 2 +- package.json | 2 +- public/css/bootstrap-treeview.css | 2 +- public/js/bootstrap-treeview.js | 2 +- src/css/bootstrap-treeview.css | 2 +- src/js/bootstrap-treeview.js | 2 +- tests/lib/bootstrap-treeview.css | 2 +- tests/lib/bootstrap-treeview.js | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 8422ce045..c0a724235 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ or using npm: $ npm install bootstrap-treeview ``` -or [download](https://github.com/jonmiles/bootstrap-treeview/releases/tag/v1.1.0) manually. +or [download](https://github.com/jonmiles/bootstrap-treeview/releases/tag/v1.2.0) manually. diff --git a/bower.json b/bower.json index c18fae82e..1b009d7da 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "bootstrap-treeview", "description": "Tree View for Twitter Bootstrap", - "version": "1.1.0", + "version": "1.2.0", "homepage": "https://github.com/jonmiles/bootstrap-treeview", "main": [ "dist/bootstrap-treeview.min.js", diff --git a/package.json b/package.json index e5cda80e2..31ef86ddb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bootstrap-treeview", "description": "Tree View for Twitter Bootstrap", - "version": "1.1.0", + "version": "1.2.0", "homepage": "https://github.com/jonmiles/bootstrap-treeview", "author": { "name": "Jonathan Miles" diff --git a/public/css/bootstrap-treeview.css b/public/css/bootstrap-treeview.css index 3f5dc60bf..23c6cf066 100644 --- a/public/css/bootstrap-treeview.css +++ b/public/css/bootstrap-treeview.css @@ -1,5 +1,5 @@ /* ========================================================= - * bootstrap-treeview.css v1.0.2 + * bootstrap-treeview.css v1.2.0 * ========================================================= * Copyright 2013 Jonathan Miles * Project URL : http://www.jondmiles.com/bootstrap-treeview diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 163b77e8d..7a82a2eeb 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -1,5 +1,5 @@ /* ========================================================= - * bootstrap-treeview.js v1.0.2 + * bootstrap-treeview.js v1.2.0 * ========================================================= * Copyright 2013 Jonathan Miles * Project URL : http://www.jondmiles.com/bootstrap-treeview diff --git a/src/css/bootstrap-treeview.css b/src/css/bootstrap-treeview.css index 3f5dc60bf..23c6cf066 100644 --- a/src/css/bootstrap-treeview.css +++ b/src/css/bootstrap-treeview.css @@ -1,5 +1,5 @@ /* ========================================================= - * bootstrap-treeview.css v1.0.2 + * bootstrap-treeview.css v1.2.0 * ========================================================= * Copyright 2013 Jonathan Miles * Project URL : http://www.jondmiles.com/bootstrap-treeview diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 163b77e8d..7a82a2eeb 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -1,5 +1,5 @@ /* ========================================================= - * bootstrap-treeview.js v1.0.2 + * bootstrap-treeview.js v1.2.0 * ========================================================= * Copyright 2013 Jonathan Miles * Project URL : http://www.jondmiles.com/bootstrap-treeview diff --git a/tests/lib/bootstrap-treeview.css b/tests/lib/bootstrap-treeview.css index 3f5dc60bf..23c6cf066 100644 --- a/tests/lib/bootstrap-treeview.css +++ b/tests/lib/bootstrap-treeview.css @@ -1,5 +1,5 @@ /* ========================================================= - * bootstrap-treeview.css v1.0.2 + * bootstrap-treeview.css v1.2.0 * ========================================================= * Copyright 2013 Jonathan Miles * Project URL : http://www.jondmiles.com/bootstrap-treeview diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 163b77e8d..7a82a2eeb 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -1,5 +1,5 @@ /* ========================================================= - * bootstrap-treeview.js v1.0.2 + * bootstrap-treeview.js v1.2.0 * ========================================================= * Copyright 2013 Jonathan Miles * Project URL : http://www.jondmiles.com/bootstrap-treeview