From 93931f94580e20243aa872b32c8798bf8f56e528 Mon Sep 17 00:00:00 2001 From: Adexe Rivera Date: Thu, 13 Jul 2017 15:01:48 +0100 Subject: [PATCH 1/3] Adding dataUrl on actual branch, because development branch it's not merged --- dist/bootstrap-treeview.min.js | 2 +- src/js/bootstrap-treeview.js | 107 +++++++++++++++++++++++++------- tests/lib/bootstrap-treeview.js | 107 +++++++++++++++++++++++++------- 3 files changed, 173 insertions(+), 43 deletions(-) diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index 9e2803815..efcf8db71 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:"",selectedIcon:"",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeDisabled:d,onNodeEnabled:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),getDisabled:a.proxy(this.getDisabled,this),getEnabled:a.proxy(this.getEnabled,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),disableAll:a.proxy(this.disableAll,this),disableNode:a.proxy(this.disableNode,this),enableAll:a.proxy(this.enableAll,this),enableNode:a.proxy(this.enableNode,this),toggleNodeDisabled:a.proxy(this.toggleNodeDisabled,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeDisabled"),this.$element.off("nodeEnabled"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.setDisabledState=function(b,c,d){c!==b.state.disabled&&(c?(b.state.disabled=!0,this.setExpandedState(b,!1,d),this.setSelectedState(b,!1,d),this.setCheckedState(b,!1,d),d.silent||this.$element.trigger("nodeDisabled",a.extend(!0,{},b))):(b.state.disabled=!1,d.silent||this.$element.trigger("nodeEnabled",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.icon||d.options.nodeIcon),e.state.selected&&(h.pop(),h.push(e.selectedIcon||d.options.selectedIcon||e.icon||d.options.nodeIcon)),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){if(a.state.disabled)return"";var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&!a.state.disabled&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'',item:'
  • ',indent:'',icon:'',link:'',badge:''},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},g.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.disableAll=function(b){var c=this.findNodes("false","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.disableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.enableAll=function(b){var c=this.findNodes("true","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.enableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeDisabled=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!a.state.disabled,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch({render:!1});var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0})}return c.revealResults?this.revealNode(d):this.render(),this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(b){b=a.extend({},{render:!0},b);var c=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});b.render&&this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},c))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document); \ No newline at end of file +!function(j,i,p,o){var n="treeview",m={};m.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"",selectedIcon:"",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:o,backColor:o,borderColor:o,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:o,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onLoading:o,onLoadingFailed:o,onInitialized:o,onNodeChecked:o,onNodeCollapsed:o,onNodeDisabled:o,onNodeEnabled:o,onNodeExpanded:o,onNodeSelected:o,onNodeUnchecked:o,onNodeUnselected:o,onSearchComplete:o,onSearchCleared:o},m.options={silent:!1,ignoreChildren:!1},m.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0},m.dataUrl={method:"GET",dataType:"json",cache:!1};var l=function(a,d){return this.$element=j(a),this.elementId=a.id,this.styleId=this.elementId+"-style",this.init(d),{options:this.options,init:j.proxy(this.init,this),remove:j.proxy(this.remove,this),getNode:j.proxy(this.getNode,this),getParent:j.proxy(this.getParent,this),getSiblings:j.proxy(this.getSiblings,this),getSelected:j.proxy(this.getSelected,this),getUnselected:j.proxy(this.getUnselected,this),getExpanded:j.proxy(this.getExpanded,this),getCollapsed:j.proxy(this.getCollapsed,this),getChecked:j.proxy(this.getChecked,this),getUnchecked:j.proxy(this.getUnchecked,this),getDisabled:j.proxy(this.getDisabled,this),getEnabled:j.proxy(this.getEnabled,this),selectNode:j.proxy(this.selectNode,this),unselectNode:j.proxy(this.unselectNode,this),toggleNodeSelected:j.proxy(this.toggleNodeSelected,this),collapseAll:j.proxy(this.collapseAll,this),collapseNode:j.proxy(this.collapseNode,this),expandAll:j.proxy(this.expandAll,this),expandNode:j.proxy(this.expandNode,this),toggleNodeExpanded:j.proxy(this.toggleNodeExpanded,this),revealNode:j.proxy(this.revealNode,this),checkAll:j.proxy(this.checkAll,this),checkNode:j.proxy(this.checkNode,this),uncheckAll:j.proxy(this.uncheckAll,this),uncheckNode:j.proxy(this.uncheckNode,this),toggleNodeChecked:j.proxy(this.toggleNodeChecked,this),disableAll:j.proxy(this.disableAll,this),disableNode:j.proxy(this.disableNode,this),enableAll:j.proxy(this.enableAll,this),enableNode:j.proxy(this.enableNode,this),toggleNodeDisabled:j.proxy(this.toggleNodeDisabled,this),search:j.proxy(this.search,this),clearSearch:j.proxy(this.clearSearch,this)}};l.prototype.init=function(a){this.tree=[],this.nodes=[],this.initialized=!1,this.options=j.extend({},m.settings,a),this.destroy(),this.subscribeEvents(),this.triggerEvent("loading",null,m.options);this.load(a).then(j.proxy(function(b){return this.tree=j.extend(true,[],b)},this),j.proxy(function(b){this.triggerEvent("loadingFailed",b,m.options)},this)).then(j.proxy(function(b){return this.setInitialStates({nodes:b},0)},this)).then(j.proxy(function(){this.render()},this))},l.prototype.load=function(a){var c=new j.Deferred();if(a.data){this.loadLocalData(a,c)}else{if(a.dataUrl){this.loadRemoteData(a,c)}}return c.promise()},l.prototype.loadRemoteData=function(a,c){j.ajax(j.extend(true,{},m.dataUrl,a.dataUrl)).done(function(b){c.resolve(b)}).fail(function(e,b,d){c.reject(d)})},l.prototype.loadLocalData=function(a,c){c.resolve((typeof a.data==="string")?j.parseJSON(a.data):j.extend(true,[],a.data))},l.prototype.remove=function(){this.destroy(),j.removeData(this,n),j("#"+this.styleId).remove()},l.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},l.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("loading"),this.$element.off("loadingFailed"),this.$element.off("initialized"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeDisabled"),this.$element.off("nodeEnabled"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},l.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",j.proxy(this.clickHandler,this)),"function"==typeof this.options.onLoading&&this.$element.on("loading",this.options.onLoading),"function"==typeof this.options.onLoadingFailed&&this.$element.on("loadingFailed",this.options.onLoadingFailed),"function"==typeof this.options.onInitialized&&this.$element.on("initialized",this.options.onInitialized),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},l.prototype.triggerEvent=function(d,a,e){if(e&&!e.silent){this.$element.trigger(d,j.extend(1,{},a))}},l.prototype.setInitialStates=function(a,h){if(a.nodes){h+=1;var g=a,f=this;j.each(a.nodes,function(d,c){c.nodeId=f.nodes.length,c.parentId=g.nodeId,c.hasOwnProperty("selectable")||(c.selectable=!0),c.state=c.state||{},c.state.hasOwnProperty("checked")||(c.state.checked=!1),c.state.hasOwnProperty("disabled")||(c.state.disabled=!1),c.state.hasOwnProperty("expanded")||(!c.state.disabled&&h0?c.state.expanded=!0:c.state.expanded=!1),c.state.hasOwnProperty("selected")||(c.state.selected=!1),f.nodes.push(c),c.nodes&&f.setInitialStates(c,h)})}},l.prototype.clickHandler=function(a){this.options.enableLinks||a.preventDefault();var h=j(a.target),g=this.findNode(h);if(g&&!g.state.disabled){var f=h.attr("class")?h.attr("class").split(" "):[];-1!==f.indexOf("expand-icon")?(this.toggleExpandedState(g,m.options),this.render()):-1!==f.indexOf("check-icon")?(this.toggleCheckedState(g,m.options),this.render()):(g.selectable?this.toggleSelectedState(g,m.options):this.toggleExpandedState(g,m.options),this.render())}},l.prototype.findNode=function(e){var d=e.closest("li.list-group-item").attr("data-nodeid"),f=this.nodes[d];return f||console.log("Error: node does not exist"),f},l.prototype.toggleExpandedState=function(d,c){d&&this.setExpandedState(d,!d.state.expanded,c)},l.prototype.setExpandedState=function(a,f,e){f!==a.state.expanded&&(f&&a.nodes?(a.state.expanded=!0,e.silent||this.$element.trigger("nodeExpanded",j.extend(!0,{},a))):f||(a.state.expanded=!1,e.silent||this.$element.trigger("nodeCollapsed",j.extend(!0,{},a)),a.nodes&&!e.ignoreChildren&&j.each(a.nodes,j.proxy(function(d,c){this.setExpandedState(c,!1,e)},this))))},l.prototype.toggleSelectedState=function(d,c){d&&this.setSelectedState(d,!d.state.selected,c)},l.prototype.setSelectedState=function(a,f,e){f!==a.state.selected&&(f?(this.options.multiSelect||j.each(this.findNodes("true","g","state.selected"),j.proxy(function(d,c){this.setSelectedState(c,!1,e)},this)),a.state.selected=!0,e.silent||this.$element.trigger("nodeSelected",j.extend(!0,{},a))):(a.state.selected=!1,e.silent||this.$element.trigger("nodeUnselected",j.extend(!0,{},a))))},l.prototype.toggleCheckedState=function(d,c){d&&this.setCheckedState(d,!d.state.checked,c)},l.prototype.setCheckedState=function(a,f,e){f!==a.state.checked&&(f?(a.state.checked=!0,e.silent||this.$element.trigger("nodeChecked",j.extend(!0,{},a))):(a.state.checked=!1,e.silent||this.$element.trigger("nodeUnchecked",j.extend(!0,{},a))))},l.prototype.setDisabledState=function(a,f,e){f!==a.state.disabled&&(f?(a.state.disabled=!0,this.setExpandedState(a,!1,e),this.setSelectedState(a,!1,e),this.setCheckedState(a,!1,e),e.silent||this.$element.trigger("nodeDisabled",j.extend(!0,{},a))):(a.state.disabled=!1,e.silent||this.$element.trigger("nodeEnabled",j.extend(!0,{},a))))},l.prototype.render=function(){this.initialized||(this.$element.addClass(n),this.$wrapper=j(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},l.prototype.buildTree=function(a,f){if(a){f+=1;var e=this;j.each(a,function(c,s){for(var r=j(e.template.item).addClass("node-"+e.elementId).addClass(s.state.checked?"node-checked":"").addClass(s.state.disabled?"node-disabled":"").addClass(s.state.selected?"node-selected":"").addClass(s.searchResult?"search-result":"").attr("data-nodeid",s.nodeId).attr("style",e.buildStyleOverride(s)),q=0;f-1>q;q++){r.append(e.template.indent)}var d=[];if(s.nodes?(d.push("expand-icon"),d.push(s.state.expanded?e.options.collapseIcon:e.options.expandIcon)):d.push(e.options.emptyIcon),r.append(j(e.template.icon).addClass(d.join(" "))),e.options.showIcon){var d=["node-icon"];d.push(s.icon||e.options.nodeIcon),s.state.selected&&(d.pop(),d.push(s.selectedIcon||e.options.selectedIcon||s.icon||e.options.nodeIcon)),r.append(j(e.template.icon).addClass(d.join(" ")))}if(e.options.showCheckbox){var d=["check-icon"];d.push(s.state.checked?e.options.checkedIcon:e.options.uncheckedIcon),r.append(j(e.template.icon).addClass(d.join(" ")))}return r.append(e.options.enableLinks?j(e.template.link).attr("href",s.href).append(s.text):s.text),e.options.showTags&&s.tags&&j.each(s.tags,function(g,h){r.append(j(e.template.badge).append(h))}),e.$wrapper.append(r),s.nodes&&s.state.expanded&&!s.state.disabled?e.buildTree(s.nodes,f):void 0})}},l.prototype.buildStyleOverride=function(e){if(e.state.disabled){return""}var d=e.color,f=e.backColor;return this.options.highlightSelected&&e.state.selected&&(this.options.selectedColor&&(d=this.options.selectedColor),this.options.selectedBackColor&&(f=this.options.selectedBackColor)),this.options.highlightSearchResults&&e.searchResult&&!e.state.disabled&&(this.options.searchResultColor&&(d=this.options.searchResultColor),this.options.searchResultBackColor&&(f=this.options.searchResultBackColor)),"color:"+d+";background-color:"+f+";"},l.prototype.injectStyle=function(){this.options.injectStyle&&!p.getElementById(this.styleId)&&j('").appendTo("head")},l.prototype.buildStyle=function(){var b=".node-"+this.elementId+"{";return this.options.color&&(b+="color:"+this.options.color+";"),this.options.backColor&&(b+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(b+="border:1px solid "+this.options.borderColor+";"):b+="border:none;",b+="}",this.options.onhoverColor&&(b+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+b},l.prototype.template={list:'
      ',item:'
    • ',indent:'',icon:'',link:'',badge:''},l.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",l.prototype.getNode=function(b){return this.nodes[b]},l.prototype.getParent=function(d){var c=this.identifyNode(d);return this.nodes[c.parentId]},l.prototype.getSiblings=function(f){var e=this.identifyNode(f),h=this.getParent(e),g=h?h.nodes:this.tree;return g.filter(function(b){return b.nodeId!==e.nodeId})},l.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},l.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},l.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},l.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},l.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},l.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},l.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},l.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},l.prototype.selectNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setSelectedState(e,!0,c)},this)),this.render()},l.prototype.unselectNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setSelectedState(e,!1,c)},this)),this.render()},l.prototype.toggleNodeSelected=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.toggleSelectedState(e,c)},this)),this.render()},l.prototype.collapseAll=function(a){var d=this.findNodes("true","g","state.expanded");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setExpandedState(e,!1,c)},this)),this.render()},l.prototype.collapseNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setExpandedState(e,!1,c)},this)),this.render()},l.prototype.expandAll=function(a){if(a=j.extend({},m.options,a),a&&a.levels){this.expandLevels(this.tree,a.levels,a)}else{var d=this.findNodes("false","g","state.expanded");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setExpandedState(e,!0,c)},this))}this.render()},l.prototype.expandNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setExpandedState(e,!0,c),e.nodes&&c&&c.levels&&this.expandLevels(e.nodes,c.levels-1,c)},this)),this.render()},l.prototype.expandLevels=function(a,f,e){e=j.extend({},m.options,e),j.each(a,j.proxy(function(d,c){this.setExpandedState(c,f>0?!0:!1,e),c.nodes&&this.expandLevels(c.nodes,f-1,e)},this))},l.prototype.revealNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(f,e){for(var g=this.getParent(f);g;){this.setExpandedState(g,!0,e),g=this.getParent(g)}},this)),this.render()},l.prototype.toggleNodeExpanded=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.toggleExpandedState(e,c)},this)),this.render()},l.prototype.checkAll=function(a){var d=this.findNodes("false","g","state.checked");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setCheckedState(e,!0,c)},this)),this.render()},l.prototype.checkNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setCheckedState(e,!0,c)},this)),this.render()},l.prototype.uncheckAll=function(a){var d=this.findNodes("true","g","state.checked");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setCheckedState(e,!1,c)},this)),this.render()},l.prototype.uncheckNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setCheckedState(e,!1,c)},this)),this.render()},l.prototype.toggleNodeChecked=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.toggleCheckedState(e,c)},this)),this.render()},l.prototype.disableAll=function(a){var d=this.findNodes("false","g","state.disabled");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setDisabledState(e,!0,c)},this)),this.render()},l.prototype.disableNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setDisabledState(e,!0,c)},this)),this.render()},l.prototype.enableAll=function(a){var d=this.findNodes("true","g","state.disabled");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setDisabledState(e,!1,c)},this)),this.render()},l.prototype.enableNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setDisabledState(e,!1,c)},this)),this.render()},l.prototype.toggleNodeDisabled=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setDisabledState(e,!e.state.disabled,c)},this)),this.render()},l.prototype.forEachIdentifier=function(a,f,e){f=j.extend({},m.options,f),a instanceof Array||(a=[a]),j.each(a,j.proxy(function(d,c){e(this.identifyNode(c),f)},this))},l.prototype.identifyNode=function(b){return"number"==typeof b?this.nodes[b]:b},l.prototype.search=function(a,h){h=j.extend({},m.searchOptions,h),this.clearSearch({render:!1});var g=[];if(a&&a.length>0){h.exactMatch&&(a="^"+a+"$");var f="g";h.ignoreCase&&(f+="i"),g=this.findNodes(a,f),j.each(g,function(d,c){c.searchResult=!0})}return h.revealResults?this.revealNode(g):this.render(),this.$element.trigger("searchComplete",j.extend(!0,{},g)),g},l.prototype.clearSearch=function(a){a=j.extend({},{render:!0},a);var d=j.each(this.findNodes("true","g","searchResult"),function(e,c){c.searchResult=!1});a.render&&this.render(),this.$element.trigger("searchCleared",j.extend(!0,{},d))},l.prototype.findNodes=function(a,h,g){h=h||"g",g=g||"text";var f=this;return j.grep(this.nodes,function(b){var c=f.getNodeValue(b,g);return"string"==typeof c?c.match(new RegExp(a,h)):void 0})},l.prototype.getNodeValue=function(g,d){var r=d.indexOf(".");if(r>0){var q=g[d.substring(0,r)],h=d.substring(r+1,d.length);return this.getNodeValue(q,h)}return g.hasOwnProperty(d)?g[d].toString():o};var k=function(b){i.console&&i.console.error(b)};j.fn[n]=function(a,f){var e;return this.each(function(){var b=j.data(this,n);"string"==typeof a?b?j.isFunction(b[a])&&"_"!==a.charAt(0)?(f instanceof Array||(f=[f]),e=b[a].apply(b,f)):k("No such method : "+a):k("Not initialized, can not call method : "+a):"boolean"==typeof a?e=b:j.data(this,n,new l(this,j.extend(!0,{},a)))}),e||this}}(jQuery,window,document); diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 7a82a2eeb..6d377252e 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -60,6 +60,9 @@ multiSelect: false, // Event handlers + onLoading: undefined, + onLoadingFailed: undefined, + onInitialized: undefined, onNodeChecked: undefined, onNodeCollapsed: undefined, onNodeDisabled: undefined, @@ -83,6 +86,12 @@ revealResults: true }; + _default.dataUrl = { + method: 'GET', + dataType: 'json', + cache: false + }; + var Tree = function (element, options) { this.$element = $(element); @@ -150,20 +159,55 @@ this.tree = []; this.nodes = []; - - if (options.data) { - if (typeof options.data === 'string') { - options.data = $.parseJSON(options.data); - } - this.tree = $.extend(true, [], options.data); - delete options.data; - } + this.initialized = false; this.options = $.extend({}, _default.settings, options); this.destroy(); this.subscribeEvents(); - this.setInitialStates({ nodes: this.tree }, 0); - this.render(); + this.triggerEvent('loading', null, _default.options); + + this.load(options) + .then($.proxy(function (data) { + // load done + return this.tree = $.extend(true, [], data); + }, this), $.proxy(function (error) { + // load fail + this.triggerEvent('loadingFailed', error, _default.options); + }, this)) + .then($.proxy(function (treeData) { + // initialize data + return this.setInitialStates({ nodes: treeData }, 0); + }, this)) + .then($.proxy(function () { + // render to DOM + this.render(); + }, this)); + }; + + Tree.prototype.load = function (options) { + var done = new $.Deferred(); + if (options.data) { + this.loadLocalData(options, done); + } else if (options.dataUrl) { + this.loadRemoteData(options, done); + } + return done.promise(); + }; + + Tree.prototype.loadRemoteData = function (options, done) { + $.ajax($.extend(true, {}, _default.dataUrl, options.dataUrl)) + .done(function (data) { + done.resolve(data); + }) + .fail(function (xhr, status, error) { + done.reject(error); + }); + }; + + Tree.prototype.loadLocalData = function (options, done) { + done.resolve((typeof options.data === 'string') ? + $.parseJSON(options.data) : + $.extend(true, [], options.data)); }; Tree.prototype.remove = function () { @@ -189,6 +233,9 @@ Tree.prototype.unsubscribeEvents = function () { this.$element.off('click'); + this.$element.off('loading'); + this.$element.off('loadingFailed'); + this.$element.off('initialized'); this.$element.off('nodeChecked'); this.$element.off('nodeCollapsed'); this.$element.off('nodeDisabled'); @@ -207,6 +254,18 @@ this.$element.on('click', $.proxy(this.clickHandler, this)); + if (typeof (this.options.onLoading) === 'function') { + this.$element.on('loading', this.options.onLoading); + } + + if (typeof (this.options.onLoadingFailed) === 'function') { + this.$element.on('loadingFailed', this.options.onLoadingFailed); + } + + if (typeof (this.options.onInitialized) === 'function') { + this.$element.on('initialized', this.options.onInitialized); + } + if (typeof (this.options.onNodeChecked) === 'function') { this.$element.on('nodeChecked', this.options.onNodeChecked); } @@ -248,6 +307,12 @@ } }; + Tree.prototype.triggerEvent = function (event, data, options) { + if (options && !options.silent) { + this.$element.trigger(event, $.extend(true, {}, data)); + } + }; + /* Recurse the tree structure and ensure all nodes have valid initial states. User defined states will be preserved. @@ -321,7 +386,7 @@ var target = $(event.target); var node = this.findNode(target); if (!node || node.state.disabled) return; - + var classList = target.attr('class') ? target.attr('class').split(' ') : []; if ((classList.indexOf('expand-icon') !== -1)) { @@ -329,12 +394,12 @@ this.render(); } else if ((classList.indexOf('check-icon') !== -1)) { - + this.toggleCheckedState(node, _default.options); this.render(); } else { - + if (node.selectable) { this.toggleSelectedState(node, _default.options); } else { @@ -516,7 +581,7 @@ .addClass(node.state.checked ? 'node-checked' : '') .addClass(node.state.disabled ? 'node-disabled': '') .addClass(node.state.selected ? 'node-selected' : '') - .addClass(node.searchResult ? 'search-result' : '') + .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -548,13 +613,13 @@ // Add node icon if (_this.options.showIcon) { - + var classList = ['node-icon']; classList.push(node.icon || _this.options.nodeIcon); if (node.state.selected) { classList.pop(); - classList.push(node.selectedIcon || _this.options.selectedIcon || + classList.push(node.selectedIcon || _this.options.selectedIcon || node.icon || _this.options.nodeIcon); } @@ -569,7 +634,7 @@ var classList = ['check-icon']; if (node.state.checked) { - classList.push(_this.options.checkedIcon); + classList.push(_this.options.checkedIcon); } else { classList.push(_this.options.uncheckedIcon); @@ -935,7 +1000,7 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleExpandedState(node, options); }, this)); - + this.render(); }; @@ -1085,7 +1150,7 @@ $.each(identifiers, $.proxy(function (index, identifier) { callback(this.identifyNode(identifier), options); - }, this)); + }, this)); }; /* @@ -1156,9 +1221,9 @@ }); if (options.render) { - this.render(); + this.render(); } - + this.$element.trigger('searchCleared', $.extend(true, {}, results)); }; diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 7a82a2eeb..6d377252e 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -60,6 +60,9 @@ multiSelect: false, // Event handlers + onLoading: undefined, + onLoadingFailed: undefined, + onInitialized: undefined, onNodeChecked: undefined, onNodeCollapsed: undefined, onNodeDisabled: undefined, @@ -83,6 +86,12 @@ revealResults: true }; + _default.dataUrl = { + method: 'GET', + dataType: 'json', + cache: false + }; + var Tree = function (element, options) { this.$element = $(element); @@ -150,20 +159,55 @@ this.tree = []; this.nodes = []; - - if (options.data) { - if (typeof options.data === 'string') { - options.data = $.parseJSON(options.data); - } - this.tree = $.extend(true, [], options.data); - delete options.data; - } + this.initialized = false; this.options = $.extend({}, _default.settings, options); this.destroy(); this.subscribeEvents(); - this.setInitialStates({ nodes: this.tree }, 0); - this.render(); + this.triggerEvent('loading', null, _default.options); + + this.load(options) + .then($.proxy(function (data) { + // load done + return this.tree = $.extend(true, [], data); + }, this), $.proxy(function (error) { + // load fail + this.triggerEvent('loadingFailed', error, _default.options); + }, this)) + .then($.proxy(function (treeData) { + // initialize data + return this.setInitialStates({ nodes: treeData }, 0); + }, this)) + .then($.proxy(function () { + // render to DOM + this.render(); + }, this)); + }; + + Tree.prototype.load = function (options) { + var done = new $.Deferred(); + if (options.data) { + this.loadLocalData(options, done); + } else if (options.dataUrl) { + this.loadRemoteData(options, done); + } + return done.promise(); + }; + + Tree.prototype.loadRemoteData = function (options, done) { + $.ajax($.extend(true, {}, _default.dataUrl, options.dataUrl)) + .done(function (data) { + done.resolve(data); + }) + .fail(function (xhr, status, error) { + done.reject(error); + }); + }; + + Tree.prototype.loadLocalData = function (options, done) { + done.resolve((typeof options.data === 'string') ? + $.parseJSON(options.data) : + $.extend(true, [], options.data)); }; Tree.prototype.remove = function () { @@ -189,6 +233,9 @@ Tree.prototype.unsubscribeEvents = function () { this.$element.off('click'); + this.$element.off('loading'); + this.$element.off('loadingFailed'); + this.$element.off('initialized'); this.$element.off('nodeChecked'); this.$element.off('nodeCollapsed'); this.$element.off('nodeDisabled'); @@ -207,6 +254,18 @@ this.$element.on('click', $.proxy(this.clickHandler, this)); + if (typeof (this.options.onLoading) === 'function') { + this.$element.on('loading', this.options.onLoading); + } + + if (typeof (this.options.onLoadingFailed) === 'function') { + this.$element.on('loadingFailed', this.options.onLoadingFailed); + } + + if (typeof (this.options.onInitialized) === 'function') { + this.$element.on('initialized', this.options.onInitialized); + } + if (typeof (this.options.onNodeChecked) === 'function') { this.$element.on('nodeChecked', this.options.onNodeChecked); } @@ -248,6 +307,12 @@ } }; + Tree.prototype.triggerEvent = function (event, data, options) { + if (options && !options.silent) { + this.$element.trigger(event, $.extend(true, {}, data)); + } + }; + /* Recurse the tree structure and ensure all nodes have valid initial states. User defined states will be preserved. @@ -321,7 +386,7 @@ var target = $(event.target); var node = this.findNode(target); if (!node || node.state.disabled) return; - + var classList = target.attr('class') ? target.attr('class').split(' ') : []; if ((classList.indexOf('expand-icon') !== -1)) { @@ -329,12 +394,12 @@ this.render(); } else if ((classList.indexOf('check-icon') !== -1)) { - + this.toggleCheckedState(node, _default.options); this.render(); } else { - + if (node.selectable) { this.toggleSelectedState(node, _default.options); } else { @@ -516,7 +581,7 @@ .addClass(node.state.checked ? 'node-checked' : '') .addClass(node.state.disabled ? 'node-disabled': '') .addClass(node.state.selected ? 'node-selected' : '') - .addClass(node.searchResult ? 'search-result' : '') + .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -548,13 +613,13 @@ // Add node icon if (_this.options.showIcon) { - + var classList = ['node-icon']; classList.push(node.icon || _this.options.nodeIcon); if (node.state.selected) { classList.pop(); - classList.push(node.selectedIcon || _this.options.selectedIcon || + classList.push(node.selectedIcon || _this.options.selectedIcon || node.icon || _this.options.nodeIcon); } @@ -569,7 +634,7 @@ var classList = ['check-icon']; if (node.state.checked) { - classList.push(_this.options.checkedIcon); + classList.push(_this.options.checkedIcon); } else { classList.push(_this.options.uncheckedIcon); @@ -935,7 +1000,7 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleExpandedState(node, options); }, this)); - + this.render(); }; @@ -1085,7 +1150,7 @@ $.each(identifiers, $.proxy(function (index, identifier) { callback(this.identifyNode(identifier), options); - }, this)); + }, this)); }; /* @@ -1156,9 +1221,9 @@ }); if (options.render) { - this.render(); + this.render(); } - + this.$element.trigger('searchCleared', $.extend(true, {}, results)); }; From f67a99b37ecfe6c0ea0cb6d9fea30685fdc721de Mon Sep 17 00:00:00 2001 From: Adexe Rivera Date: Fri, 14 Jul 2017 08:26:07 +0100 Subject: [PATCH 2/3] Updating readme info of new functionality --- README.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c0a724235..371a02438 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,21 @@ Array of Objects. No default, expects data This is the core data to be displayed by the tree view. +#### dataUrl +jQuery Ajax settings object, [as documented here](http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings). + +Accepts a set of key/value pairs that configure an Ajax request. All settings are optional, any provided will be merge with the following default configuration. + +```javascript +{ + method: 'GET', + dataType: 'json', + cache: false +} +``` + +> JSON is the only format accepted. + #### backColor String, [any legal color value](http://www.w3schools.com/cssref/css_colors_legal.asp). Default: inherits from Bootstrap.css. @@ -727,6 +742,18 @@ $('#tree').on('nodeSelected', function(event, data) { ### List of Events +#### Lifecycle Events + +> Use callback handlers for lifecycle events otherwise you'll miss the events fired during creation. + +`loading (event)` - The tree has initiated data loading. + +`loadingFailed (event, error)` - The tree failed to load data (ajax error) + +`initialized (event, nodes)` - The tree has initialized itself and data ready for rendering. + +#### State Events + `nodeChecked (event, node)` - A node is checked. `nodeCollapsed (event, node)` - A node is collapsed. @@ -748,7 +775,6 @@ $('#tree').on('nodeSelected', function(event, data) { `searchCleared (event, results)` - After search results are cleared - ## Copyright and Licensing Copyright 2013 Jonathan Miles From aca17e3eab6fa7f3c1c1253f984b805115efdc28 Mon Sep 17 00:00:00 2001 From: Adexe Rivera Date: Mon, 24 Jul 2017 12:47:35 +0100 Subject: [PATCH 3/3] Adding reload method to update tree view component --- README.md | 8 ++ dist/bootstrap-treeview.min.js | 2 +- public/js/bootstrap-treeview.js | 129 ++++++++++++++++++++++++++------ src/js/bootstrap-treeview.js | 22 ++++++ tests/lib/bootstrap-treeview.js | 22 ++++++ 5 files changed, 161 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 371a02438..bdcb5f31e 100644 --- a/README.md +++ b/README.md @@ -600,6 +600,14 @@ Returns an array of unselected nodes e.g. state.selected = false. $('#tree').treeview('getUnselected', nodeId); ``` +#### reload() + +Reload the tree view component. + +```javascript +$('#tree').treeview('reload'); +``` + #### remove() Removes the tree view component. Removing attached events, internal attached objects, and added HTML elements. diff --git a/dist/bootstrap-treeview.min.js b/dist/bootstrap-treeview.min.js index efcf8db71..d2402e98a 100644 --- a/dist/bootstrap-treeview.min.js +++ b/dist/bootstrap-treeview.min.js @@ -1 +1 @@ -!function(j,i,p,o){var n="treeview",m={};m.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"",selectedIcon:"",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:o,backColor:o,borderColor:o,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:o,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onLoading:o,onLoadingFailed:o,onInitialized:o,onNodeChecked:o,onNodeCollapsed:o,onNodeDisabled:o,onNodeEnabled:o,onNodeExpanded:o,onNodeSelected:o,onNodeUnchecked:o,onNodeUnselected:o,onSearchComplete:o,onSearchCleared:o},m.options={silent:!1,ignoreChildren:!1},m.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0},m.dataUrl={method:"GET",dataType:"json",cache:!1};var l=function(a,d){return this.$element=j(a),this.elementId=a.id,this.styleId=this.elementId+"-style",this.init(d),{options:this.options,init:j.proxy(this.init,this),remove:j.proxy(this.remove,this),getNode:j.proxy(this.getNode,this),getParent:j.proxy(this.getParent,this),getSiblings:j.proxy(this.getSiblings,this),getSelected:j.proxy(this.getSelected,this),getUnselected:j.proxy(this.getUnselected,this),getExpanded:j.proxy(this.getExpanded,this),getCollapsed:j.proxy(this.getCollapsed,this),getChecked:j.proxy(this.getChecked,this),getUnchecked:j.proxy(this.getUnchecked,this),getDisabled:j.proxy(this.getDisabled,this),getEnabled:j.proxy(this.getEnabled,this),selectNode:j.proxy(this.selectNode,this),unselectNode:j.proxy(this.unselectNode,this),toggleNodeSelected:j.proxy(this.toggleNodeSelected,this),collapseAll:j.proxy(this.collapseAll,this),collapseNode:j.proxy(this.collapseNode,this),expandAll:j.proxy(this.expandAll,this),expandNode:j.proxy(this.expandNode,this),toggleNodeExpanded:j.proxy(this.toggleNodeExpanded,this),revealNode:j.proxy(this.revealNode,this),checkAll:j.proxy(this.checkAll,this),checkNode:j.proxy(this.checkNode,this),uncheckAll:j.proxy(this.uncheckAll,this),uncheckNode:j.proxy(this.uncheckNode,this),toggleNodeChecked:j.proxy(this.toggleNodeChecked,this),disableAll:j.proxy(this.disableAll,this),disableNode:j.proxy(this.disableNode,this),enableAll:j.proxy(this.enableAll,this),enableNode:j.proxy(this.enableNode,this),toggleNodeDisabled:j.proxy(this.toggleNodeDisabled,this),search:j.proxy(this.search,this),clearSearch:j.proxy(this.clearSearch,this)}};l.prototype.init=function(a){this.tree=[],this.nodes=[],this.initialized=!1,this.options=j.extend({},m.settings,a),this.destroy(),this.subscribeEvents(),this.triggerEvent("loading",null,m.options);this.load(a).then(j.proxy(function(b){return this.tree=j.extend(true,[],b)},this),j.proxy(function(b){this.triggerEvent("loadingFailed",b,m.options)},this)).then(j.proxy(function(b){return this.setInitialStates({nodes:b},0)},this)).then(j.proxy(function(){this.render()},this))},l.prototype.load=function(a){var c=new j.Deferred();if(a.data){this.loadLocalData(a,c)}else{if(a.dataUrl){this.loadRemoteData(a,c)}}return c.promise()},l.prototype.loadRemoteData=function(a,c){j.ajax(j.extend(true,{},m.dataUrl,a.dataUrl)).done(function(b){c.resolve(b)}).fail(function(e,b,d){c.reject(d)})},l.prototype.loadLocalData=function(a,c){c.resolve((typeof a.data==="string")?j.parseJSON(a.data):j.extend(true,[],a.data))},l.prototype.remove=function(){this.destroy(),j.removeData(this,n),j("#"+this.styleId).remove()},l.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},l.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("loading"),this.$element.off("loadingFailed"),this.$element.off("initialized"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeDisabled"),this.$element.off("nodeEnabled"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},l.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",j.proxy(this.clickHandler,this)),"function"==typeof this.options.onLoading&&this.$element.on("loading",this.options.onLoading),"function"==typeof this.options.onLoadingFailed&&this.$element.on("loadingFailed",this.options.onLoadingFailed),"function"==typeof this.options.onInitialized&&this.$element.on("initialized",this.options.onInitialized),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},l.prototype.triggerEvent=function(d,a,e){if(e&&!e.silent){this.$element.trigger(d,j.extend(1,{},a))}},l.prototype.setInitialStates=function(a,h){if(a.nodes){h+=1;var g=a,f=this;j.each(a.nodes,function(d,c){c.nodeId=f.nodes.length,c.parentId=g.nodeId,c.hasOwnProperty("selectable")||(c.selectable=!0),c.state=c.state||{},c.state.hasOwnProperty("checked")||(c.state.checked=!1),c.state.hasOwnProperty("disabled")||(c.state.disabled=!1),c.state.hasOwnProperty("expanded")||(!c.state.disabled&&h0?c.state.expanded=!0:c.state.expanded=!1),c.state.hasOwnProperty("selected")||(c.state.selected=!1),f.nodes.push(c),c.nodes&&f.setInitialStates(c,h)})}},l.prototype.clickHandler=function(a){this.options.enableLinks||a.preventDefault();var h=j(a.target),g=this.findNode(h);if(g&&!g.state.disabled){var f=h.attr("class")?h.attr("class").split(" "):[];-1!==f.indexOf("expand-icon")?(this.toggleExpandedState(g,m.options),this.render()):-1!==f.indexOf("check-icon")?(this.toggleCheckedState(g,m.options),this.render()):(g.selectable?this.toggleSelectedState(g,m.options):this.toggleExpandedState(g,m.options),this.render())}},l.prototype.findNode=function(e){var d=e.closest("li.list-group-item").attr("data-nodeid"),f=this.nodes[d];return f||console.log("Error: node does not exist"),f},l.prototype.toggleExpandedState=function(d,c){d&&this.setExpandedState(d,!d.state.expanded,c)},l.prototype.setExpandedState=function(a,f,e){f!==a.state.expanded&&(f&&a.nodes?(a.state.expanded=!0,e.silent||this.$element.trigger("nodeExpanded",j.extend(!0,{},a))):f||(a.state.expanded=!1,e.silent||this.$element.trigger("nodeCollapsed",j.extend(!0,{},a)),a.nodes&&!e.ignoreChildren&&j.each(a.nodes,j.proxy(function(d,c){this.setExpandedState(c,!1,e)},this))))},l.prototype.toggleSelectedState=function(d,c){d&&this.setSelectedState(d,!d.state.selected,c)},l.prototype.setSelectedState=function(a,f,e){f!==a.state.selected&&(f?(this.options.multiSelect||j.each(this.findNodes("true","g","state.selected"),j.proxy(function(d,c){this.setSelectedState(c,!1,e)},this)),a.state.selected=!0,e.silent||this.$element.trigger("nodeSelected",j.extend(!0,{},a))):(a.state.selected=!1,e.silent||this.$element.trigger("nodeUnselected",j.extend(!0,{},a))))},l.prototype.toggleCheckedState=function(d,c){d&&this.setCheckedState(d,!d.state.checked,c)},l.prototype.setCheckedState=function(a,f,e){f!==a.state.checked&&(f?(a.state.checked=!0,e.silent||this.$element.trigger("nodeChecked",j.extend(!0,{},a))):(a.state.checked=!1,e.silent||this.$element.trigger("nodeUnchecked",j.extend(!0,{},a))))},l.prototype.setDisabledState=function(a,f,e){f!==a.state.disabled&&(f?(a.state.disabled=!0,this.setExpandedState(a,!1,e),this.setSelectedState(a,!1,e),this.setCheckedState(a,!1,e),e.silent||this.$element.trigger("nodeDisabled",j.extend(!0,{},a))):(a.state.disabled=!1,e.silent||this.$element.trigger("nodeEnabled",j.extend(!0,{},a))))},l.prototype.render=function(){this.initialized||(this.$element.addClass(n),this.$wrapper=j(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},l.prototype.buildTree=function(a,f){if(a){f+=1;var e=this;j.each(a,function(c,s){for(var r=j(e.template.item).addClass("node-"+e.elementId).addClass(s.state.checked?"node-checked":"").addClass(s.state.disabled?"node-disabled":"").addClass(s.state.selected?"node-selected":"").addClass(s.searchResult?"search-result":"").attr("data-nodeid",s.nodeId).attr("style",e.buildStyleOverride(s)),q=0;f-1>q;q++){r.append(e.template.indent)}var d=[];if(s.nodes?(d.push("expand-icon"),d.push(s.state.expanded?e.options.collapseIcon:e.options.expandIcon)):d.push(e.options.emptyIcon),r.append(j(e.template.icon).addClass(d.join(" "))),e.options.showIcon){var d=["node-icon"];d.push(s.icon||e.options.nodeIcon),s.state.selected&&(d.pop(),d.push(s.selectedIcon||e.options.selectedIcon||s.icon||e.options.nodeIcon)),r.append(j(e.template.icon).addClass(d.join(" ")))}if(e.options.showCheckbox){var d=["check-icon"];d.push(s.state.checked?e.options.checkedIcon:e.options.uncheckedIcon),r.append(j(e.template.icon).addClass(d.join(" ")))}return r.append(e.options.enableLinks?j(e.template.link).attr("href",s.href).append(s.text):s.text),e.options.showTags&&s.tags&&j.each(s.tags,function(g,h){r.append(j(e.template.badge).append(h))}),e.$wrapper.append(r),s.nodes&&s.state.expanded&&!s.state.disabled?e.buildTree(s.nodes,f):void 0})}},l.prototype.buildStyleOverride=function(e){if(e.state.disabled){return""}var d=e.color,f=e.backColor;return this.options.highlightSelected&&e.state.selected&&(this.options.selectedColor&&(d=this.options.selectedColor),this.options.selectedBackColor&&(f=this.options.selectedBackColor)),this.options.highlightSearchResults&&e.searchResult&&!e.state.disabled&&(this.options.searchResultColor&&(d=this.options.searchResultColor),this.options.searchResultBackColor&&(f=this.options.searchResultBackColor)),"color:"+d+";background-color:"+f+";"},l.prototype.injectStyle=function(){this.options.injectStyle&&!p.getElementById(this.styleId)&&j('").appendTo("head")},l.prototype.buildStyle=function(){var b=".node-"+this.elementId+"{";return this.options.color&&(b+="color:"+this.options.color+";"),this.options.backColor&&(b+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(b+="border:1px solid "+this.options.borderColor+";"):b+="border:none;",b+="}",this.options.onhoverColor&&(b+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+b},l.prototype.template={list:'
        ',item:'
      • ',indent:'',icon:'',link:'',badge:''},l.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",l.prototype.getNode=function(b){return this.nodes[b]},l.prototype.getParent=function(d){var c=this.identifyNode(d);return this.nodes[c.parentId]},l.prototype.getSiblings=function(f){var e=this.identifyNode(f),h=this.getParent(e),g=h?h.nodes:this.tree;return g.filter(function(b){return b.nodeId!==e.nodeId})},l.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},l.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},l.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},l.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},l.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},l.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},l.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},l.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},l.prototype.selectNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setSelectedState(e,!0,c)},this)),this.render()},l.prototype.unselectNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setSelectedState(e,!1,c)},this)),this.render()},l.prototype.toggleNodeSelected=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.toggleSelectedState(e,c)},this)),this.render()},l.prototype.collapseAll=function(a){var d=this.findNodes("true","g","state.expanded");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setExpandedState(e,!1,c)},this)),this.render()},l.prototype.collapseNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setExpandedState(e,!1,c)},this)),this.render()},l.prototype.expandAll=function(a){if(a=j.extend({},m.options,a),a&&a.levels){this.expandLevels(this.tree,a.levels,a)}else{var d=this.findNodes("false","g","state.expanded");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setExpandedState(e,!0,c)},this))}this.render()},l.prototype.expandNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setExpandedState(e,!0,c),e.nodes&&c&&c.levels&&this.expandLevels(e.nodes,c.levels-1,c)},this)),this.render()},l.prototype.expandLevels=function(a,f,e){e=j.extend({},m.options,e),j.each(a,j.proxy(function(d,c){this.setExpandedState(c,f>0?!0:!1,e),c.nodes&&this.expandLevels(c.nodes,f-1,e)},this))},l.prototype.revealNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(f,e){for(var g=this.getParent(f);g;){this.setExpandedState(g,!0,e),g=this.getParent(g)}},this)),this.render()},l.prototype.toggleNodeExpanded=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.toggleExpandedState(e,c)},this)),this.render()},l.prototype.checkAll=function(a){var d=this.findNodes("false","g","state.checked");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setCheckedState(e,!0,c)},this)),this.render()},l.prototype.checkNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setCheckedState(e,!0,c)},this)),this.render()},l.prototype.uncheckAll=function(a){var d=this.findNodes("true","g","state.checked");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setCheckedState(e,!1,c)},this)),this.render()},l.prototype.uncheckNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setCheckedState(e,!1,c)},this)),this.render()},l.prototype.toggleNodeChecked=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.toggleCheckedState(e,c)},this)),this.render()},l.prototype.disableAll=function(a){var d=this.findNodes("false","g","state.disabled");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setDisabledState(e,!0,c)},this)),this.render()},l.prototype.disableNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setDisabledState(e,!0,c)},this)),this.render()},l.prototype.enableAll=function(a){var d=this.findNodes("true","g","state.disabled");this.forEachIdentifier(d,a,j.proxy(function(e,c){this.setDisabledState(e,!1,c)},this)),this.render()},l.prototype.enableNode=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setDisabledState(e,!1,c)},this)),this.render()},l.prototype.toggleNodeDisabled=function(a,d){this.forEachIdentifier(a,d,j.proxy(function(e,c){this.setDisabledState(e,!e.state.disabled,c)},this)),this.render()},l.prototype.forEachIdentifier=function(a,f,e){f=j.extend({},m.options,f),a instanceof Array||(a=[a]),j.each(a,j.proxy(function(d,c){e(this.identifyNode(c),f)},this))},l.prototype.identifyNode=function(b){return"number"==typeof b?this.nodes[b]:b},l.prototype.search=function(a,h){h=j.extend({},m.searchOptions,h),this.clearSearch({render:!1});var g=[];if(a&&a.length>0){h.exactMatch&&(a="^"+a+"$");var f="g";h.ignoreCase&&(f+="i"),g=this.findNodes(a,f),j.each(g,function(d,c){c.searchResult=!0})}return h.revealResults?this.revealNode(g):this.render(),this.$element.trigger("searchComplete",j.extend(!0,{},g)),g},l.prototype.clearSearch=function(a){a=j.extend({},{render:!0},a);var d=j.each(this.findNodes("true","g","searchResult"),function(e,c){c.searchResult=!1});a.render&&this.render(),this.$element.trigger("searchCleared",j.extend(!0,{},d))},l.prototype.findNodes=function(a,h,g){h=h||"g",g=g||"text";var f=this;return j.grep(this.nodes,function(b){var c=f.getNodeValue(b,g);return"string"==typeof c?c.match(new RegExp(a,h)):void 0})},l.prototype.getNodeValue=function(g,d){var r=d.indexOf(".");if(r>0){var q=g[d.substring(0,r)],h=d.substring(r+1,d.length);return this.getNodeValue(q,h)}return g.hasOwnProperty(d)?g[d].toString():o};var k=function(b){i.console&&i.console.error(b)};j.fn[n]=function(a,f){var e;return this.each(function(){var b=j.data(this,n);"string"==typeof a?b?j.isFunction(b[a])&&"_"!==a.charAt(0)?(f instanceof Array||(f=[f]),e=b[a].apply(b,f)):k("No such method : "+a):k("Not initialized, can not call method : "+a):"boolean"==typeof a?e=b:j.data(this,n,new l(this,j.extend(!0,{},a)))}),e||this}}(jQuery,window,document); +!function(d,e,f,g){var h="treeview",a={};a.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"",selectedIcon:"",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:g,backColor:g,borderColor:g,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:g,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onLoading:g,onLoadingFailed:g,onInitialized:g,onNodeChecked:g,onNodeCollapsed:g,onNodeDisabled:g,onNodeEnabled:g,onNodeExpanded:g,onNodeSelected:g,onNodeUnchecked:g,onNodeUnselected:g,onSearchComplete:g,onSearchCleared:g},a.options={silent:!1,ignoreChildren:!1},a.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0},a.dataUrl={method:"GET",dataType:"json",cache:!1};var b=function(i,j){return this.$element=d(i),this.elementId=i.id,this.styleId=this.elementId+"-style",this.init(j),{options:this.options,init:d.proxy(this.init,this),remove:d.proxy(this.remove,this),reload:d.proxy(this.reload,this),getNode:d.proxy(this.getNode,this),getParent:d.proxy(this.getParent,this),getSiblings:d.proxy(this.getSiblings,this),getSelected:d.proxy(this.getSelected,this),getUnselected:d.proxy(this.getUnselected,this),getExpanded:d.proxy(this.getExpanded,this),getCollapsed:d.proxy(this.getCollapsed,this),getChecked:d.proxy(this.getChecked,this),getUnchecked:d.proxy(this.getUnchecked,this),getDisabled:d.proxy(this.getDisabled,this),getEnabled:d.proxy(this.getEnabled,this),selectNode:d.proxy(this.selectNode,this),unselectNode:d.proxy(this.unselectNode,this),toggleNodeSelected:d.proxy(this.toggleNodeSelected,this),collapseAll:d.proxy(this.collapseAll,this),collapseNode:d.proxy(this.collapseNode,this),expandAll:d.proxy(this.expandAll,this),expandNode:d.proxy(this.expandNode,this),toggleNodeExpanded:d.proxy(this.toggleNodeExpanded,this),revealNode:d.proxy(this.revealNode,this),checkAll:d.proxy(this.checkAll,this),checkNode:d.proxy(this.checkNode,this),uncheckAll:d.proxy(this.uncheckAll,this),uncheckNode:d.proxy(this.uncheckNode,this),toggleNodeChecked:d.proxy(this.toggleNodeChecked,this),disableAll:d.proxy(this.disableAll,this),disableNode:d.proxy(this.disableNode,this),enableAll:d.proxy(this.enableAll,this),enableNode:d.proxy(this.enableNode,this),toggleNodeDisabled:d.proxy(this.toggleNodeDisabled,this),search:d.proxy(this.search,this),clearSearch:d.proxy(this.clearSearch,this)}};b.prototype.init=function(i){this.tree=[],this.nodes=[],this.initialized=!1,this.options=d.extend({},a.settings,i),this.destroy(),this.subscribeEvents(),this.triggerEvent("loading",null,a.options);this.load(i).then(d.proxy(function(j){return this.tree=d.extend(true,[],j)},this),d.proxy(function(j){this.triggerEvent("loadingFailed",j,a.options)},this)).then(d.proxy(function(j){return this.setInitialStates({nodes:j},0)},this)).then(d.proxy(function(){this.render()},this))},b.prototype.load=function(i){var j=new d.Deferred();if(i.data){this.loadLocalData(i,j)}else{if(i.dataUrl){this.loadRemoteData(i,j)}}return j.promise()},b.prototype.loadRemoteData=function(i,j){d.ajax(d.extend(true,{},a.dataUrl,i.dataUrl)).done(function(k){j.resolve(k)}).fail(function(l,k,m){j.reject(m)})},b.prototype.loadLocalData=function(i,j){j.resolve((typeof i.data==="string")?d.parseJSON(i.data):d.extend(true,[],i.data))},b.prototype.reload=function(){this.load(this.options).then(d.proxy(function(i){return this.tree=d.extend(true,[],i)},this),d.proxy(function(i){this.triggerEvent("loadingFailed",i,a.options)},this)).then(d.proxy(function(i){return this.setInitialStates({nodes:i},0)},this)).then(d.proxy(function(){this.render()},this))},b.prototype.remove=function(){this.destroy(),d.removeData(this,h),d("#"+this.styleId).remove()},b.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},b.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("loading"),this.$element.off("loadingFailed"),this.$element.off("initialized"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeDisabled"),this.$element.off("nodeEnabled"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},b.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",d.proxy(this.clickHandler,this)),"function"==typeof this.options.onLoading&&this.$element.on("loading",this.options.onLoading),"function"==typeof this.options.onLoadingFailed&&this.$element.on("loadingFailed",this.options.onLoadingFailed),"function"==typeof this.options.onInitialized&&this.$element.on("initialized",this.options.onInitialized),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},b.prototype.triggerEvent=function(k,i,j){if(j&&!j.silent){this.$element.trigger(k,d.extend(1,{},i))}},b.prototype.setInitialStates=function(i,j){if(i.nodes){j+=1;var k=i,l=this;d.each(i.nodes,function(m,n){n.nodeId=l.nodes.length,n.parentId=k.nodeId,n.hasOwnProperty("selectable")||(n.selectable=!0),n.state=n.state||{},n.state.hasOwnProperty("checked")||(n.state.checked=!1),n.state.hasOwnProperty("disabled")||(n.state.disabled=!1),n.state.hasOwnProperty("expanded")||(!n.state.disabled&&j0?n.state.expanded=!0:n.state.expanded=!1),n.state.hasOwnProperty("selected")||(n.state.selected=!1),l.nodes.push(n),n.nodes&&l.setInitialStates(n,j)})}},b.prototype.clickHandler=function(i){this.options.enableLinks||i.preventDefault();var j=d(i.target),k=this.findNode(j);if(k&&!k.state.disabled){var l=j.attr("class")?j.attr("class").split(" "):[];-1!==l.indexOf("expand-icon")?(this.toggleExpandedState(k,a.options),this.render()):-1!==l.indexOf("check-icon")?(this.toggleCheckedState(k,a.options),this.render()):(k.selectable?this.toggleSelectedState(k,a.options):this.toggleExpandedState(k,a.options),this.render())}},b.prototype.findNode=function(j){var k=j.closest("li.list-group-item").attr("data-nodeid"),i=this.nodes[k];return i||console.log("Error: node does not exist"),i},b.prototype.toggleExpandedState=function(i,j){i&&this.setExpandedState(i,!i.state.expanded,j)},b.prototype.setExpandedState=function(i,j,k){j!==i.state.expanded&&(j&&i.nodes?(i.state.expanded=!0,k.silent||this.$element.trigger("nodeExpanded",d.extend(!0,{},i))):j||(i.state.expanded=!1,k.silent||this.$element.trigger("nodeCollapsed",d.extend(!0,{},i)),i.nodes&&!k.ignoreChildren&&d.each(i.nodes,d.proxy(function(l,m){this.setExpandedState(m,!1,k)},this))))},b.prototype.toggleSelectedState=function(i,j){i&&this.setSelectedState(i,!i.state.selected,j)},b.prototype.setSelectedState=function(i,j,k){j!==i.state.selected&&(j?(this.options.multiSelect||d.each(this.findNodes("true","g","state.selected"),d.proxy(function(l,m){this.setSelectedState(m,!1,k)},this)),i.state.selected=!0,k.silent||this.$element.trigger("nodeSelected",d.extend(!0,{},i))):(i.state.selected=!1,k.silent||this.$element.trigger("nodeUnselected",d.extend(!0,{},i))))},b.prototype.toggleCheckedState=function(i,j){i&&this.setCheckedState(i,!i.state.checked,j)},b.prototype.setCheckedState=function(i,j,k){j!==i.state.checked&&(j?(i.state.checked=!0,k.silent||this.$element.trigger("nodeChecked",d.extend(!0,{},i))):(i.state.checked=!1,k.silent||this.$element.trigger("nodeUnchecked",d.extend(!0,{},i))))},b.prototype.setDisabledState=function(i,j,k){j!==i.state.disabled&&(j?(i.state.disabled=!0,this.setExpandedState(i,!1,k),this.setSelectedState(i,!1,k),this.setCheckedState(i,!1,k),k.silent||this.$element.trigger("nodeDisabled",d.extend(!0,{},i))):(i.state.disabled=!1,k.silent||this.$element.trigger("nodeEnabled",d.extend(!0,{},i))))},b.prototype.render=function(){this.initialized||(this.$element.addClass(h),this.$wrapper=d(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},b.prototype.buildTree=function(i,j){if(i){j+=1;var k=this;d.each(i,function(p,l){for(var m=d(k.template.item).addClass("node-"+k.elementId).addClass(l.state.checked?"node-checked":"").addClass(l.state.disabled?"node-disabled":"").addClass(l.state.selected?"node-selected":"").addClass(l.searchResult?"search-result":"").attr("data-nodeid",l.nodeId).attr("style",k.buildStyleOverride(l)),n=0;j-1>n;n++){m.append(k.template.indent)}var o=[];if(l.nodes?(o.push("expand-icon"),o.push(l.state.expanded?k.options.collapseIcon:k.options.expandIcon)):o.push(k.options.emptyIcon),m.append(d(k.template.icon).addClass(o.join(" "))),k.options.showIcon){var o=["node-icon"];o.push(l.icon||k.options.nodeIcon),l.state.selected&&(o.pop(),o.push(l.selectedIcon||k.options.selectedIcon||l.icon||k.options.nodeIcon)),m.append(d(k.template.icon).addClass(o.join(" ")))}if(k.options.showCheckbox){var o=["check-icon"];o.push(l.state.checked?k.options.checkedIcon:k.options.uncheckedIcon),m.append(d(k.template.icon).addClass(o.join(" ")))}return m.append(k.options.enableLinks?d(k.template.link).attr("href",l.href).append(l.text):l.text),k.options.showTags&&l.tags&&d.each(l.tags,function(r,q){m.append(d(k.template.badge).append(q))}),k.$wrapper.append(m),l.nodes&&l.state.expanded&&!l.state.disabled?k.buildTree(l.nodes,j):void 0})}},b.prototype.buildStyleOverride=function(j){if(j.state.disabled){return""}var k=j.color,i=j.backColor;return this.options.highlightSelected&&j.state.selected&&(this.options.selectedColor&&(k=this.options.selectedColor),this.options.selectedBackColor&&(i=this.options.selectedBackColor)),this.options.highlightSearchResults&&j.searchResult&&!j.state.disabled&&(this.options.searchResultColor&&(k=this.options.searchResultColor),this.options.searchResultBackColor&&(i=this.options.searchResultBackColor)),"color:"+k+";background-color:"+i+";"},b.prototype.injectStyle=function(){this.options.injectStyle&&!f.getElementById(this.styleId)&&d('").appendTo("head")},b.prototype.buildStyle=function(){var i=".node-"+this.elementId+"{";return this.options.color&&(i+="color:"+this.options.color+";"),this.options.backColor&&(i+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(i+="border:1px solid "+this.options.borderColor+";"):i+="border:none;",i+="}",this.options.onhoverColor&&(i+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+i},b.prototype.template={list:'
          ',item:'
        • ',indent:'',icon:'',link:'',badge:''},b.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",b.prototype.getNode=function(i){return this.nodes[i]},b.prototype.getParent=function(i){var j=this.identifyNode(i);return this.nodes[j.parentId]},b.prototype.getSiblings=function(k){var l=this.identifyNode(k),i=this.getParent(l),j=i?i.nodes:this.tree;return j.filter(function(m){return m.nodeId!==l.nodeId})},b.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},b.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},b.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},b.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},b.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},b.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},b.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},b.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},b.prototype.selectNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setSelectedState(k,!0,l)},this)),this.render()},b.prototype.unselectNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setSelectedState(k,!1,l)},this)),this.render()},b.prototype.toggleNodeSelected=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.toggleSelectedState(k,l)},this)),this.render()},b.prototype.collapseAll=function(i){var j=this.findNodes("true","g","state.expanded");this.forEachIdentifier(j,i,d.proxy(function(k,l){this.setExpandedState(k,!1,l)},this)),this.render()},b.prototype.collapseNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setExpandedState(k,!1,l)},this)),this.render()},b.prototype.expandAll=function(i){if(i=d.extend({},a.options,i),i&&i.levels){this.expandLevels(this.tree,i.levels,i)}else{var j=this.findNodes("false","g","state.expanded");this.forEachIdentifier(j,i,d.proxy(function(k,l){this.setExpandedState(k,!0,l)},this))}this.render()},b.prototype.expandNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setExpandedState(k,!0,l),k.nodes&&l&&l.levels&&this.expandLevels(k.nodes,l.levels-1,l)},this)),this.render()},b.prototype.expandLevels=function(i,j,k){k=d.extend({},a.options,k),d.each(i,d.proxy(function(l,m){this.setExpandedState(m,j>0?!0:!1,k),m.nodes&&this.expandLevels(m.nodes,j-1,k)},this))},b.prototype.revealNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(l,m){for(var k=this.getParent(l);k;){this.setExpandedState(k,!0,m),k=this.getParent(k)}},this)),this.render()},b.prototype.toggleNodeExpanded=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.toggleExpandedState(k,l)},this)),this.render()},b.prototype.checkAll=function(i){var j=this.findNodes("false","g","state.checked");this.forEachIdentifier(j,i,d.proxy(function(k,l){this.setCheckedState(k,!0,l)},this)),this.render()},b.prototype.checkNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setCheckedState(k,!0,l)},this)),this.render()},b.prototype.uncheckAll=function(i){var j=this.findNodes("true","g","state.checked");this.forEachIdentifier(j,i,d.proxy(function(k,l){this.setCheckedState(k,!1,l)},this)),this.render()},b.prototype.uncheckNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setCheckedState(k,!1,l)},this)),this.render()},b.prototype.toggleNodeChecked=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.toggleCheckedState(k,l)},this)),this.render()},b.prototype.disableAll=function(i){var j=this.findNodes("false","g","state.disabled");this.forEachIdentifier(j,i,d.proxy(function(k,l){this.setDisabledState(k,!0,l)},this)),this.render()},b.prototype.disableNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setDisabledState(k,!0,l)},this)),this.render()},b.prototype.enableAll=function(i){var j=this.findNodes("true","g","state.disabled");this.forEachIdentifier(j,i,d.proxy(function(k,l){this.setDisabledState(k,!1,l)},this)),this.render()},b.prototype.enableNode=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setDisabledState(k,!1,l)},this)),this.render()},b.prototype.toggleNodeDisabled=function(i,j){this.forEachIdentifier(i,j,d.proxy(function(k,l){this.setDisabledState(k,!k.state.disabled,l)},this)),this.render()},b.prototype.forEachIdentifier=function(i,j,k){j=d.extend({},a.options,j),i instanceof Array||(i=[i]),d.each(i,d.proxy(function(l,m){k(this.identifyNode(m),j)},this))},b.prototype.identifyNode=function(i){return"number"==typeof i?this.nodes[i]:i},b.prototype.search=function(i,j){j=d.extend({},a.searchOptions,j),this.clearSearch({render:!1});var k=[];if(i&&i.length>0){j.exactMatch&&(i="^"+i+"$");var l="g";j.ignoreCase&&(l+="i"),k=this.findNodes(i,l),d.each(k,function(m,n){n.searchResult=!0})}return j.revealResults?this.revealNode(k):this.render(),this.$element.trigger("searchComplete",d.extend(!0,{},k)),k},b.prototype.clearSearch=function(i){i=d.extend({},{render:!0},i);var j=d.each(this.findNodes("true","g","searchResult"),function(k,l){l.searchResult=!1});i.render&&this.render(),this.$element.trigger("searchCleared",d.extend(!0,{},j))},b.prototype.findNodes=function(i,j,k){j=j||"g",k=k||"text";var l=this;return d.grep(this.nodes,function(m){var n=l.getNodeValue(m,k);return"string"==typeof n?n.match(new RegExp(i,j)):void 0})},b.prototype.getNodeValue=function(k,m){var j=m.indexOf(".");if(j>0){var l=k[m.substring(0,j)],i=m.substring(j+1,m.length);return this.getNodeValue(l,i)}return k.hasOwnProperty(m)?k[m].toString():g};var c=function(i){e.console&&e.console.error(i)};d.fn[h]=function(i,j){var k;return this.each(function(){var l=d.data(this,h);"string"==typeof i?l?d.isFunction(l[i])&&"_"!==i.charAt(0)?(j instanceof Array||(j=[j]),k=l[i].apply(l,j)):c("No such method : "+i):c("Not initialized, can not call method : "+i):"boolean"==typeof i?k=l:d.data(this,h,new b(this,d.extend(!0,{},i)))}),k||this}}(jQuery,window,document); diff --git a/public/js/bootstrap-treeview.js b/public/js/bootstrap-treeview.js index 7a82a2eeb..4960dbfb5 100644 --- a/public/js/bootstrap-treeview.js +++ b/public/js/bootstrap-treeview.js @@ -60,6 +60,9 @@ multiSelect: false, // Event handlers + onLoading: undefined, + onLoadingFailed: undefined, + onInitialized: undefined, onNodeChecked: undefined, onNodeCollapsed: undefined, onNodeDisabled: undefined, @@ -83,6 +86,12 @@ revealResults: true }; + _default.dataUrl = { + method: 'GET', + dataType: 'json', + cache: false + }; + var Tree = function (element, options) { this.$element = $(element); @@ -100,6 +109,9 @@ init: $.proxy(this.init, this), remove: $.proxy(this.remove, this), + // Reload method + reload: $.proxy(this.reload, this), + // Get methods getNode: $.proxy(this.getNode, this), getParent: $.proxy(this.getParent, this), @@ -150,20 +162,74 @@ this.tree = []; this.nodes = []; - - if (options.data) { - if (typeof options.data === 'string') { - options.data = $.parseJSON(options.data); - } - this.tree = $.extend(true, [], options.data); - delete options.data; - } + this.initialized = false; this.options = $.extend({}, _default.settings, options); this.destroy(); this.subscribeEvents(); - this.setInitialStates({ nodes: this.tree }, 0); - this.render(); + this.triggerEvent('loading', null, _default.options); + + this.load(options) + .then($.proxy(function (data) { + // load done + return this.tree = $.extend(true, [], data); + }, this), $.proxy(function (error) { + // load fail + this.triggerEvent('loadingFailed', error, _default.options); + }, this)) + .then($.proxy(function (treeData) { + // initialize data + return this.setInitialStates({ nodes: treeData }, 0); + }, this)) + .then($.proxy(function () { + // render to DOM + this.render(); + }, this)); + }; + + Tree.prototype.load = function (options) { + var done = new $.Deferred(); + if (options.data) { + this.loadLocalData(options, done); + } else if (options.dataUrl) { + this.loadRemoteData(options, done); + } + return done.promise(); + }; + + Tree.prototype.loadRemoteData = function (options, done) { + $.ajax($.extend(true, {}, _default.dataUrl, options.dataUrl)) + .done(function (data) { + done.resolve(data); + }) + .fail(function (xhr, status, error) { + done.reject(error); + }); + }; + + Tree.prototype.loadLocalData = function (options, done) { + done.resolve((typeof options.data === 'string') ? + $.parseJSON(options.data) : + $.extend(true, [], options.data)); + }; + + Tree.prototype.reload = function () { + this.load(this.options) + .then($.proxy(function (data) { + // load done + return this.tree = $.extend(true, [], data); + }, this), $.proxy(function (error) { + // load fail + this.triggerEvent('loadingFailed', error, _default.options); + }, this)) + .then($.proxy(function (treeData) { + // initialize data + return this.setInitialStates({ nodes: treeData }, 0); + }, this)) + .then($.proxy(function () { + // render to DOM + this.render(); + }, this)); }; Tree.prototype.remove = function () { @@ -189,6 +255,9 @@ Tree.prototype.unsubscribeEvents = function () { this.$element.off('click'); + this.$element.off('loading'); + this.$element.off('loadingFailed'); + this.$element.off('initialized'); this.$element.off('nodeChecked'); this.$element.off('nodeCollapsed'); this.$element.off('nodeDisabled'); @@ -207,6 +276,18 @@ this.$element.on('click', $.proxy(this.clickHandler, this)); + if (typeof (this.options.onLoading) === 'function') { + this.$element.on('loading', this.options.onLoading); + } + + if (typeof (this.options.onLoadingFailed) === 'function') { + this.$element.on('loadingFailed', this.options.onLoadingFailed); + } + + if (typeof (this.options.onInitialized) === 'function') { + this.$element.on('initialized', this.options.onInitialized); + } + if (typeof (this.options.onNodeChecked) === 'function') { this.$element.on('nodeChecked', this.options.onNodeChecked); } @@ -248,6 +329,12 @@ } }; + Tree.prototype.triggerEvent = function (event, data, options) { + if (options && !options.silent) { + this.$element.trigger(event, $.extend(true, {}, data)); + } + }; + /* Recurse the tree structure and ensure all nodes have valid initial states. User defined states will be preserved. @@ -321,7 +408,7 @@ var target = $(event.target); var node = this.findNode(target); if (!node || node.state.disabled) return; - + var classList = target.attr('class') ? target.attr('class').split(' ') : []; if ((classList.indexOf('expand-icon') !== -1)) { @@ -329,12 +416,12 @@ this.render(); } else if ((classList.indexOf('check-icon') !== -1)) { - + this.toggleCheckedState(node, _default.options); this.render(); } else { - + if (node.selectable) { this.toggleSelectedState(node, _default.options); } else { @@ -516,7 +603,7 @@ .addClass(node.state.checked ? 'node-checked' : '') .addClass(node.state.disabled ? 'node-disabled': '') .addClass(node.state.selected ? 'node-selected' : '') - .addClass(node.searchResult ? 'search-result' : '') + .addClass(node.searchResult ? 'search-result' : '') .attr('data-nodeid', node.nodeId) .attr('style', _this.buildStyleOverride(node)); @@ -548,13 +635,13 @@ // Add node icon if (_this.options.showIcon) { - + var classList = ['node-icon']; classList.push(node.icon || _this.options.nodeIcon); if (node.state.selected) { classList.pop(); - classList.push(node.selectedIcon || _this.options.selectedIcon || + classList.push(node.selectedIcon || _this.options.selectedIcon || node.icon || _this.options.nodeIcon); } @@ -569,7 +656,7 @@ var classList = ['check-icon']; if (node.state.checked) { - classList.push(_this.options.checkedIcon); + classList.push(_this.options.checkedIcon); } else { classList.push(_this.options.uncheckedIcon); @@ -935,7 +1022,7 @@ this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleExpandedState(node, options); }, this)); - + this.render(); }; @@ -1085,7 +1172,7 @@ $.each(identifiers, $.proxy(function (index, identifier) { callback(this.identifyNode(identifier), options); - }, this)); + }, this)); }; /* @@ -1156,9 +1243,9 @@ }); if (options.render) { - this.render(); + this.render(); } - + this.$element.trigger('searchCleared', $.extend(true, {}, results)); }; diff --git a/src/js/bootstrap-treeview.js b/src/js/bootstrap-treeview.js index 6d377252e..4960dbfb5 100644 --- a/src/js/bootstrap-treeview.js +++ b/src/js/bootstrap-treeview.js @@ -109,6 +109,9 @@ init: $.proxy(this.init, this), remove: $.proxy(this.remove, this), + // Reload method + reload: $.proxy(this.reload, this), + // Get methods getNode: $.proxy(this.getNode, this), getParent: $.proxy(this.getParent, this), @@ -210,6 +213,25 @@ $.extend(true, [], options.data)); }; + Tree.prototype.reload = function () { + this.load(this.options) + .then($.proxy(function (data) { + // load done + return this.tree = $.extend(true, [], data); + }, this), $.proxy(function (error) { + // load fail + this.triggerEvent('loadingFailed', error, _default.options); + }, this)) + .then($.proxy(function (treeData) { + // initialize data + return this.setInitialStates({ nodes: treeData }, 0); + }, this)) + .then($.proxy(function () { + // render to DOM + this.render(); + }, this)); + }; + Tree.prototype.remove = function () { this.destroy(); $.removeData(this, pluginName); diff --git a/tests/lib/bootstrap-treeview.js b/tests/lib/bootstrap-treeview.js index 6d377252e..4960dbfb5 100644 --- a/tests/lib/bootstrap-treeview.js +++ b/tests/lib/bootstrap-treeview.js @@ -109,6 +109,9 @@ init: $.proxy(this.init, this), remove: $.proxy(this.remove, this), + // Reload method + reload: $.proxy(this.reload, this), + // Get methods getNode: $.proxy(this.getNode, this), getParent: $.proxy(this.getParent, this), @@ -210,6 +213,25 @@ $.extend(true, [], options.data)); }; + Tree.prototype.reload = function () { + this.load(this.options) + .then($.proxy(function (data) { + // load done + return this.tree = $.extend(true, [], data); + }, this), $.proxy(function (error) { + // load fail + this.triggerEvent('loadingFailed', error, _default.options); + }, this)) + .then($.proxy(function (treeData) { + // initialize data + return this.setInitialStates({ nodes: treeData }, 0); + }, this)) + .then($.proxy(function () { + // render to DOM + this.render(); + }, this)); + }; + Tree.prototype.remove = function () { this.destroy(); $.removeData(this, pluginName);