1.自定义一个tag标签:treeselect.tag
<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
<%@ attribute name="id" type="java.lang.String" required="true" description="编号"%>
<%@ attribute name="name" type="java.lang.String" required="true" description="隐藏域名称(ID)"%>
<%@ attribute name="value" type="java.lang.String" required="true" description="隐藏域值(ID)"%>
<%@ attribute name="labelName" type="java.lang.String" required="true" description="输入框名称(Name)"%>
<%@ attribute name="labelValue" type="java.lang.String" required="true" description="输入框值(Name)"%>
<%@ attribute name="title" type="java.lang.String" required="true" description="选择框标题"%>
<%@ attribute name="url" type="java.lang.String" required="true" description="树结构数据地址"%>
<%@ attribute name="checked" type="java.lang.Boolean" required="false" description="是否显示复选框,如果不需要返回父节点,请设置notAllowSelectParent为true"%>
<%@ attribute name="extId" type="java.lang.String" required="false" description="排除掉的编号(不能选择的编号)"%>
<%@ attribute name="isAll" type="java.lang.Boolean" required="false" description="是否列出全部数据,设置true则不进行数据权限过滤(目前仅对Office有效)"%>
<%@ attribute name="notAllowSelectRoot" type="java.lang.Boolean" required="false" description="不允许选择根节点"%>
<%@ attribute name="notAllowSelectParent" type="java.lang.Boolean" required="false" description="不允许选择父节点"%>
<%@ attribute name="module" type="java.lang.String" required="false" description="过滤栏目模型(只显示指定模型,仅针对CMS的Category树)"%>
<%@ attribute name="selectScopeModule" type="java.lang.Boolean" required="false" description="选择范围内的模型(控制不能选择公共模型,不能选择本栏目外的模型)(仅针对CMS的Category树)"%>
<%@ attribute name="allowClear" type="java.lang.Boolean" required="false" description="是否允许清除"%>
<%@ attribute name="allowInput" type="java.lang.Boolean" required="false" description="文本框可填写"%>
<%@ attribute name="cssClass" type="java.lang.String" required="false" description="css样式"%>
<%@ attribute name="cssStyle" type="java.lang.String" required="false" description="css样式"%>
<%@ attribute name="smallBtn" type="java.lang.Boolean" required="false" description="缩小按钮显示"%>
<%@ attribute name="hideBtn" type="java.lang.Boolean" required="false" description="是否显示按钮"%>
<%@ attribute name="disabled" type="java.lang.String" required="false" description="是否限制选择,如果限制,设置为disabled"%>
<%@ attribute name="dataMsgRequired" type="java.lang.String" required="false" description=""%>
<div class="input-append">
<input id="${id}Id" name="${name}" class="${cssClass}" type="hidden" value="${value}"/>
<input id="${id}Name" name="${labelName}" ${allowInput?'':'readonly="readonly"'} type="text" value="${labelValue}" data-msg-required="${dataMsgRequired}"
class="${cssClass}" style="${cssStyle}"/><a id="${id}Button" href="javascript:" class="btn ${disabled} ${hideBtn ? 'hide' : ''}" style="${smallBtn?'padding:4px 2px;':''}"> <i class="icon-search"></i> </a>
</div>
<script type="text/javascript">
$("#${id}Button, #${id}Name").click(function(){
// 是否限制选择,如果限制,设置为disabled
if ($("#${id}Button").hasClass("disabled")){
return true;
}
// 正常打开
top.$.jBox.open("iframe:${ctx}/tag/treeselect?url="+encodeURIComponent("${url}")+"&module=${module}&checked=${checked}&extId=${extId}&isAll=${isAll}", "选择${title}", 300, 420, {
ajaxData:{selectIds: $("#${id}Id").val()},buttons:{"确定":"ok", ${allowClear?"\"清除\":\"clear\", ":""}"关闭":true}, submit:function(v, h, f){
if (v=="ok"){
var tree = h.find("iframe")[0].contentWindow.tree;//h.find("iframe").contents();
var ids = [], names = [], nodes = [];
if ("${checked}" == "true"){
nodes = tree.getCheckedNodes(true);
}else{
nodes = tree.getSelectedNodes();
}
for(var i=0; i<nodes.length; i++) {//<c:if test="${checked && notAllowSelectParent}">
if (nodes[i].isParent){
continue; // 如果为复选框选择,则过滤掉父节点
}//</c:if><c:if test="${notAllowSelectRoot}">
if (nodes[i].level == 0){
top.$.jBox.tip("不能选择根节点("+nodes[i].name+")请重新选择。");
return false;
}//</c:if><c:if test="${notAllowSelectParent}">
if (nodes[i].isParent){
top.$.jBox.tip("不能选择父节点("+nodes[i].name+")请重新选择。");
return false;
}//</c:if><c:if test="${not empty module && selectScopeModule}">
if (nodes[i].module == ""){
top.$.jBox.tip("不能选择公共模型("+nodes[i].name+")请重新选择。");
return false;
}else if (nodes[i].module != "${module}"){
top.$.jBox.tip("不能选择当前栏目以外的栏目模型,请重新选择。");
return false;
}//</c:if>
ids.push(nodes[i].id);
names.push(nodes[i].name);//<c:if test="${!checked}">
break; // 如果为非复选框选择,则返回第一个选择 </c:if>
}
$("#${id}Id").val(ids.join(",").replace(/u_/ig,""));
$("#${id}Name").val(names.join(","));
}//<c:if test="${allowClear}">
else if (v=="clear"){
$("#${id}Id").val("");
$("#${id}Name").val("");
}//</c:if>
if(typeof ${id}TreeselectCallBack == 'function'){
${id}TreeselectCallBack(v, h, f);
}
}, loaded:function(h){
$(".jbox-content", top.document).css("overflow-y","hidden");
}
});
});
</script>
2.tree显示以及数据选择:tagTreeselect.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
<html>
<head>
<title>数据选择</title>
<meta name="decorator" content="blank"/>
<%@include file="/WEB-INF/views/include/treeview.jsp" %>
<script type="text/javascript">
var key, lastValue = "", nodeList = [], type = getQueryString("type", "${url}");
var tree, setting = {view:{selectedMulti:false,dblClickExpand:false},check:{enable:"${checked}",nocheckInherit:true},
async:{enable:(type==3),url:"${ctx}/sys/user/treeData",autoParam:["id=officeId"]},
data:{simpleData:{enable:true}},callback:{<%--
beforeClick: function(treeId, treeNode){
if("${checked}" == "true"){
//tree.checkNode(treeNode, !node.checked, true, true);
tree.expandNode(treeNode, true, false, false);
}
}, --%>
onClick:function(event, treeId, treeNode){
tree.expandNode(treeNode);
},onCheck: function(e, treeId, treeNode){
var nodes = tree.getCheckedNodes(true);
for (var i=0, l=nodes.length; i<l; i++) {
tree.expandNode(nodes[i], true, false, false);
}
return false;
},onAsyncSuccess: function(event, treeId, treeNode, msg){
var nodes = tree.getNodesByParam("pId", treeNode.id, null);
for (var i=0, l=nodes.length; i<l; i++) {
try{tree.checkNode(nodes[i], treeNode.checked, true);}catch(e){}
//tree.selectNode(nodes[i], false);
}
selectCheckNode();
},onDblClick: function(){//<c:if test="${!checked}">
top.$.jBox.getBox().find("button[value='ok']").trigger("click");
//$("input[type='text']", top.mainFrame.document).focus();//</c:if>
}
}
};
function expandNodes(nodes) {
if (!nodes) return;
for (var i=0, l=nodes.length; i<l; i++) {
tree.expandNode(nodes[i], true, false, false);
if (nodes[i].isParent && nodes[i].zAsync) {
expandNodes(nodes[i].children);
}
}
}
$(document).ready(function(){
$.get("${ctx}${url}${fn:indexOf(url,'?')==-1?'?':'&'}&extId=${extId}&isAll=${isAll}&module=${module}&t="
+ new Date().getTime(), function(zNodes){
// 初始化树结构
tree = $.fn.zTree.init($("#tree"), setting, zNodes);
// 默认展开一级节点
var nodes = tree.getNodesByParam("level", 0);
for(var i=0; i<nodes.length; i++) {
tree.expandNode(nodes[i], true, false, false);
}
//异步加载子节点(加载用户)
var nodesOne = tree.getNodesByParam("isParent", true);
for(var j=0; j<nodesOne.length; j++) {
tree.reAsyncChildNodes(nodesOne[j],"!refresh",true);
}
selectCheckNode();
});
key = $("#key");
key.bind("focus", focusKey).bind("blur", blurKey).bind("change cut input propertychange", searchNode);
key.bind('keydown', function (e){if(e.which == 13){searchNode();}});
setTimeout("search();", "300");
});
// 默认选择节点
function selectCheckNode(){
var ids = "${selectIds}".split(",");
for(var i=0; i<ids.length; i++) {
var node = tree.getNodeByParam("id", (type==3?"u_":"")+ids[i]);
if("${checked}" == "true"){
try{tree.checkNode(node, true, true);}catch(e){}
tree.selectNode(node, false);
}else{
tree.selectNode(node, true);
}
}
}
function focusKey(e) {
if (key.hasClass("empty")) {
key.removeClass("empty");
}
}
function blurKey(e) {
if (key.get(0).value === "") {
key.addClass("empty");
}
searchNode(e);
}
//搜索节点
function searchNode() {
// 取得输入的关键字的值
var value = $.trim(key.get(0).value);
// 按名字查询
var keyType = "name";<%--
if (key.hasClass("empty")) {
value = "";
}--%>
// 如果和上次一次,就退出不查了。
if (lastValue === value) {
return;
}
// 保存最后一次
lastValue = value;
var nodes = tree.getNodes();
// 如果要查空字串,就退出不查了。
if (value == "") {
showAllNode(nodes);
return;
}
hideAllNode(nodes);
nodeList = tree.getNodesByParamFuzzy(keyType, value);
updateNodes(nodeList);
}
//隐藏所有节点
function hideAllNode(nodes){
nodes = tree.transformToArray(nodes);
for(var i=nodes.length-1; i>=0; i--) {
tree.hideNode(nodes[i]);
}
}
//显示所有节点
function showAllNode(nodes){
nodes = tree.transformToArray(nodes);
for(var i=nodes.length-1; i>=0; i--) {
/* if(!nodes[i].isParent){
tree.showNode(nodes[i]);
}else{ */
if(nodes[i].getParentNode()!=null){
tree.expandNode(nodes[i],false,false,false,false);
}else{
tree.expandNode(nodes[i],true,true,false,false);
}
tree.showNode(nodes[i]);
showAllNode(nodes[i].children);
/* } */
}
}
//更新节点状态
function updateNodes(nodeList) {
tree.showNodes(nodeList);
for(var i=0, l=nodeList.length; i<l; i++) {
//展开当前节点的父节点
tree.showNode(nodeList[i].getParentNode());
//tree.expandNode(nodeList[i].getParentNode(), true, false, false);
//显示展开符合条件节点的父节点
while(nodeList[i].getParentNode()!=null){
tree.expandNode(nodeList[i].getParentNode(), true, false, false);
nodeList[i] = nodeList[i].getParentNode();
tree.showNode(nodeList[i].getParentNode());
}
//显示根节点
tree.showNode(nodeList[i].getParentNode());
//展开根节点
tree.expandNode(nodeList[i].getParentNode(), true, false, false);
}
}
// 开始搜索
function search() {
$("#search").slideToggle(200);
$("#txt").toggle();
$("#key").focus();
}
</script>
</head>
<body>
<div style="position:absolute;right:8px;top:5px;cursor:pointer;" onclick="search();">
<i class="icon-search"></i><label id="txt">搜索</label>
</div>
<div id="search" class="form-search hide" style="padding:10px 0 0 13px;">
<label for="key" class="control-label" style="padding:5px 5px 3px 0;">关键字:</label>
<input type="text" class="empty" id="key" name="key" maxlength="50" style="width:110px;">
<button class="btn" id="btn" onclick="searchNode()">搜索</button>
</div>
<div id="tree" class="ztree" style="padding:15px 20px;"></div>
</body>
3.后台接收参数
/**
* 树结构选择标签(treeselect.tag)
*/
@RequiresPermissions("user")
@RequestMapping(value = "treeselect")
public String treeselect(HttpServletRequest request, Model model) {
model.addAttribute("url", request.getParameter("url")); // 树结构数据URL
model.addAttribute("extId", request.getParameter("extId")); // 排除的编号ID
model.addAttribute("checked", request.getParameter("checked")); // 是否可复选
model.addAttribute("selectIds", request.getParameter("selectIds")); // 指定默认选中的ID
model.addAttribute("isAll", request.getParameter("isAll")); // 是否读取全部数据,不进行权限过滤
model.addAttribute("module", request.getParameter("module")); // 过滤栏目模型(仅针对CMS的Category树)
return "modules/sys/tagTreeselect";
}
4.后台处理数据,并把参数返回给jsp
@ResponseBody
@RequestMapping(value = "treeSchool")
public List<Map<String, Object>> treeSchool(@RequestParam(required=false) String extId, @RequestParam(required=false) String type,
@RequestParam(required=false) Long grade, @RequestParam(required=false) Boolean isAll, HttpServletResponse response){
List<Map<String, Object>> mapList = Lists.newArrayList();
List<School> list = service.findlist();
for(int i = 0; i<list.size(); i++){
School school = list.get(i);
Map<String, Object> map = Maps.newHashMap();
map.put("id", school.getId());
map.put("pId", school.getParentId());
map.put("pIds", school.getParentIds());
map.put("name", school.getName());
mapList.add(map);
}
return mapList;
}
5.显示jsp
<body>
<li><label>学校职位:</label><sys:treeselect id="school" name="id" value="${school.id}" labelName="name" labelValue="${school.name}"
title="职位" url="/school/school/treeSchool" cssClass="input-small" allowClear="true"/></li>
</body>