From bdb8194d2fa5b33bc72a872ee14f6d6bbfc11236 Mon Sep 17 00:00:00 2001 From: jonmiles Date: Sat, 2 May 2015 17:59:31 +0100 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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(); };