Bootstrap Tree View简单而优雅的树结构组件实例解析
a simple and elegant solution to displaying hierarchical tree structures (i.e. a tree view) while leveraging the best that twitter bootstrap has to offer.
这是bootstrap tree view在上的简介。
注意simple、elegant,简单而优雅,我喜欢这两个词。
那么今天的实例是通过bootstrap tree view来制作一款省市级菜单的应用。
一、效果图
二、应用
①、首先,项目需要引入bootstrap.css、jquery.js、bootstrap-treeview.js
<link type="text/css" rel="stylesheet" href="${ctx}/components/bootstrap/css/bootstrap.min.css" rel="external nofollow" /> <script type="text/javascript" src="${ctx}/components/jquery/jquery-1.10.1.min.js"></script> <script type="text/javascript" src="${ctx}/components/treeview/js/bootstrap-treeview.js"></script>
②、接下来,页面上需要放一个dom元素。
<div id="procitytree" style="height: 400px;overflow-y :scroll;"></div>
通过设置height和overflow-y,使treeview能够在垂直方向上出现滚动条。
③、由于省市级数据一般都是固定不变的,那么页面初次加载时,我们把省市级数据先拿到。
java端非常简单:
@requestmapping(value = "loadprocitysinfo") public void loadprocitysinfo(httpservletresponse response) { logger.debug("获取所有省市"); try { list<provincial> provincials = provincialservice.getprovincials(); for (provincial provincial : provincials) { list<city> citys = cityservice.getcitysbyprovincialid(provincial.getid()); provincial.setcitys(citys); } renderjsondone(response, provincials); } catch (exception e) { logger.error(e.getmessage(), e); logger.error(e.getmessage()); renderjsonerror(response, constants.server_error); } }
这段代码需要优化,通过mybatis其实可以一次就获得省级和市级的集合。
获取数据后,通过json写入到response中。
protected void renderjsondone(httpservletresponse response, final object value) { map<string, object> map = new hashmap<string, object>(); map.put("statuscode", 200); map.put("result", value); string jsontext = json.tojsonstring(map); printwriter writer = null; try { response.setheader("pragma", "no-cache"); response.setheader("cache-control", "no-cache"); response.setdateheader("expires", 0); response.setcontenttype(contenttype); writer = response.getwriter(); writer.write(jsontext); writer.flush(); } catch (ioexception e) { throw new orderexception(e.getmessage()); } finally { if (writer != null) writer.close(); } }
前端通过ajax对数据进行组装保存。
jquery.ajax({ url : common.ctx + "/procity/loadprocitysinfo", // 请求的url datatype : 'json', async : false, timeout : 50000, cache : false, success : function(response) { var json = yunm.jsoneval(response); if (json[yunm.keys.statuscode] == yunm.statuscode.ok) { var records = json[yunm.keys.result]; if (!json) return; // 城市列表都存在 if (records != null && records.length > 0) { // 遍历子节点 $.each(records, function(index, value) { var pronode = {}; // text是显示的内容 pronode["text"] = value.proname; pronode["id"] = value.id; pronode["procode"] = value.procode; // 节点不可选中 pronode["selectable"] = false; // 初始化市级节点 pronode["nodes"] = []; $.each(value.citys, function(index, value) { var citynode = {}; citynode["text"] = value.cname; citynode["id"] = value.id; citynode["proid"] = value.proid; citynode["code"] = value.code; // 节点不可选中 citynode["selectable"] = false; pronode["nodes"].push(citynode); }); // 保存页面端对象中 //yunm._set.procitytreedata的数据结构就是二维数组。 yunm._set.procitytreedata.push(pronode); }); } } } });
④、拿到数据之后,就可以对treeview进行初始化了。
这里,我们讲一点更复杂的应用,如下图。
如果用户已经保存过一部分节点,那么初次展示的时候就需要通过treeview展示出来了。
我们定一些规则:
节点全部选中时color为red,check框选中。
节点未全部选中时color为red,check框未选中。
节点一个也没选中时color为默认,check框未选中。
为此,我们需要增加一点css。
/* 树形省市 */ .treeview .list-group-item.node-checked { color: red; } .treeview .list-group-item.node-selected { color: red; }
有了这个规则,我们在初次展开treeview的时候,就需要重新制定以下数据规则。
// 省市级数据 var procitytreedata = yunm._set.procitytreedata; // 用户已经选中的城市,比如河南洛阳。 var init_code = $this.next("input[name=area]").val(); // 如果用户有选中项,则对选中项进行规则展示 if (init_code) { // 初始化选中项目 $.each(procitytreedata, function(index, value) { // 通过i和省级的节点length进行对比,判断是否全选、未全选、全未选三种状态 var i = 0; $.each(value.nodes, function(index1, value1) { if (init_code.indexof(value1.code) != -1) { // 选中时先初始化state,再把state.checked设为true value1["state"] = {}; value1["state"]["checked"] = true; i++; } else { // 否则重置state,保证procitytreedata数据的不被更改 // 这个地方其实有待优化,由于js我还不算精通,所以不知道怎么把数组复制到一个新数组里,保证原始属于不被更改 value1["state"] = {}; } }); value["state"] = {}; // 市级节点有选中,那么省级节点的状态需要变化,根据上面制定的规则来 if (i > 0) { // 市级全选,那么此时省级节点打钩 if (value.nodes.length == i) { value["state"]["checked"] = true; } // 根据selected来设定颜色 value["state"]["selected"] = true; } else { value["state"]["selected"] = false; } }); }
让treeview和我们打个招呼吧!
$("#procitytree").treeview({ data : procitytreedata,// 赋值 highlightselected : false,// 选中项不高亮,避免和上述制定的颜色变化规则冲突 multiselect : false,// 不允许多选,因为我们要通过check框来控制 showcheckbox : true,// 展示checkbox }).treeview('collapseall', {// 节点展开 silent : true });
⑤、节点onnodechecked、onnodeunchecked的应用
不要⑤就够了吗?
不够,我们还要控制节点选择框的变化。
就像效果图中那样。
onnodechecked : function(event, node) { yunm.debug("选中项目为:" + node); // 省级节点被选中,那么市级节点都要选中 if (node.nodes != null) { $.each(node.nodes, function(index, value) { $this.treeview('checknode', value.nodeid, { silent : true }); }); } else { // 市级节点选中的时候,要根据情况判断父节点是否要全部选中 // 父节点 var parentnode = $this.treeview('getparent', node.nodeid); var isallchecked = true; // 是否全部选中 // 当前市级节点的所有兄弟节点,也就是获取省下面的所有市 var siblings = $this.treeview('getsiblings', node.nodeid); for ( var i in siblings) { // 有一个没选中,则不是全选 if (!siblings[i].state.checked) { isallchecked = false; break; } } // 全选,则打钩 if (isallchecked) { $this.treeview('checknode', parentnode.nodeid, { silent : true }); } else {// 非全选,则变红 $this.treeview('selectnode', parentnode.nodeid, { silent : true }); } } }, onnodeunchecked : function(event, node) { yunm.debug("取消选中项目为:" + node); // 选中的是省级节点 if (node.nodes != null) { // 这里需要控制,判断是否是因为市级节点引起的父节点被取消选中 // 如果是,则只管取消父节点就行了 // 如果不是,则子节点需要被取消选中 if (silentbychild) { $.each(node.nodes, function(index, value) { $this.treeview('unchecknode', value.nodeid, { silent : true }); }); } } else { // 市级节点被取消选中 var parentnode = $this.treeview('getparent', node.nodeid); var isallunchecked = true; // 是否全部取消选中 // 市级节点有一个选中,那么就不是全部取消选中 var siblings = $this.treeview('getsiblings', node.nodeid); for ( var i in siblings) { if (siblings[i].state.checked) { isallunchecked = false; break; } } // 全部取消选中,那么省级节点恢复到默认状态 if (isallunchecked) { $this.treeview('unselectnode', parentnode.nodeid, { silent : true, }); $this.treeview('unchecknode', parentnode.nodeid, { silent : true, }); } else { silentbychild = false; $this.treeview('selectnode', parentnode.nodeid, { silent : true, }); $this.treeview('unchecknode', parentnode.nodeid, { silent : true, }); } } silentbychild = true; },
到这里,treeview的应用已经算是非常全面了
以上所述是小编给大家介绍的bootstrap tree view简单而优雅的树结构组件实例解析,希望对大家有所帮助