基于ani2.11的treeselect树选择弹窗改造成下拉树
宁长空/ty
VIP3
2018-08-29 00:51:53
最后修改:2018-08-29 00:58:55
收藏
注意:以下代码在谷歌浏览器下的dialog风格均经过严格参数,其他浏览器或者form风格都没有经过测试。
改造后下拉树与树选择弹窗使用同样的参数(只增加一个openLevel参数,后面详细说明),从树选择弹窗切换到下拉树非常简单。
1、在webapp/WEB-INF/tags/sys下新增treeselect2.tag,并复制以下代码:
[pre]
<%@tag language="java" pageEncoding="UTF-8"%>
<%@include file="/webpage/include/taglib.jsp"%>
<%@include file="/webpage/include/treeview.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="false" description="隐藏域值(ID)"%>
<%@ attribute name="labelName" type="java.lang.String" required="false" description="输入框名称(Name)"%>
<%@ attribute name="labelValue" type="java.lang.String" required="false" description="输入框值(Name)"%>
<%@ attribute name="title" type="java.lang.String" required="false" description="选择框标题"%>
<%@ attribute name="url" type="java.lang.String" required="true" description="树结构数据地址"%>
<%@ attribute name="checked" type="java.lang.Boolean" required="false" description="是否显示复选框"%>
<%@ 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="不允许选择父节点,checked为true时无效"%>
<%@ attribute name="allowSearch" type="java.lang.Boolean" required="false" description="是否允许搜索"%>
<%@ 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="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=""%>
<%@ attribute name="openLevel" type="java.lang.String" required="false" description="展开层级,0表示不展开只显示跟节点,不填默认1"%>
<input id="${id}Id" name="${name}" class="${cssClass} form-control" type="hidden" value="${value}"/>
<div id="${id}JstreeInput" class="input-group" style="width:100%;">
<input id="${id}Name" name="${labelName}" ${allowInput?'':'readonly="readonly"'} type="text" value="${labelValue}" data-msg-required="${dataMsgRequired}"
class="${cssClass}" style="${cssStyle}"/>
<span class="input-group-btn">
<button type="button" id="${id}Button" class="btn <c:if test="${fn:contains(cssClass, 'input-sm')}"> btn-sm </c:if><c:if test="${fn:contains(cssClass, 'input-lg')}"> btn-lg </c:if> btn-primary ${disabled} ${hideBtn ? 'hide' : ''}"><i class="fa fa-search"></i>
</button>
<c:if test="${allowClear}">
<button type="button" id="${id}DelButton" class="close" data-dismiss="alert" style="position: absolute; top: 5px; right: 53px; z-index: 10; display: block;">×</button>
</c:if>
</span>
</div>
<div id="${id}JstreeWrap" style="background-color: #fff;border: 1px solid #66afe9;display:none;position: absolute;z-index: 999;">
<c:if test="${allowSearch}">
<!-- 搜索 -->
<div class="input-search" style="margin: 5px 20px;">
<button type="submit" class="input-search-btn">
<i class="fa fa-search" aria-hidden="true"></i></button>
<input id="${id}Search_q" type="text" class="form-control input-sm" name="" placeholder="请输入关键词...">
</div>
</c:if>
<div id="${id}Jstree" ></div>
</div>
<label id="${id}Name-error" class="error" for="${id}Name" style="display:none"></label>
<script type="text/javascript">
//监听窗口大小变化时隐藏下拉树
window.addEventListener('resize',function(){
$("#${id}JstreeWrap").slideUp(100);
},false);
$(document).ready(function(){
$("#${id}JstreeWrap").parent().css('position','relative');
//点击按钮、输入框、下拉树以外的地方隐藏下拉树
$(document).click(function(e){
if($(e.target).closest("#${id}Button").length == 0 && $(e.target).closest("#${id}Name").length == 0
&& $(e.target).closest("#${id}JstreeWrap").length == 0 ){
$("#${id}JstreeWrap").slideUp(100);
}
});
//单击输入框、单击输入框右边按钮
$("#${id}Button, #${id}Name").click(function(){
// 是否限制选择
if ($("#${id}Button").hasClass("disabled")){
return true;
}
//设置宽度后再切换显示隐藏,以在显示隐藏过程中下拉树与输入框保持一致的宽度
$("#${id}JstreeWrap").css("width",$("#${id}JstreeWrap").prev(".input-group").width());
$("#${id}JstreeWrap").slideToggle(100,function(){
//切换完成后再次设置宽度,以修复显示隐藏完成后由于下拉树的显示隐藏造成垂直滚动条的产生或隐藏而引起输入框的宽度变化
$("#${id}JstreeWrap").css("width",$("#${id}JstreeWrap").prev(".input-group").width());
});
});
//单击清除按钮
$("#${id}DelButton").click(function(){
// 是否限制选择
if ($("#${id}Button").hasClass("disabled")){
return true;
}
// 清除
$("#${id}Id").val("");
$("#${id}Name").val("");
$("#${id}Name").focus();
});
})
</script>
<script type="text/javascript">
var ${id}tree;
$(document).ready(function(){
/**
* jstree初始化
* 建议对代码生成器生成的后台代码的treeData方法进行改造:
* 1、原对extId(排除掉的编号)进行过滤处理,客户体验不好,应修改为设置state的disabled为true,即设置extId为显示但不可选节点
* 2、原默认展开第一层级,应增加对openLevel的处理,按openLevel进行展开设置
*
* //TODO 1、待完善BUG:多选模式下,选中父节点时被禁用的子节点也会选中
* 解决方案:将jstree升级到v3.3.4及以上,并按http://www.php.cn/js-tutorial-383370.html完善。
* 因目前经过jeeplus作者深度定制的jstree版本为3.3.3,为不影响其他应用,待作者升级jstree后再完善
*/
$('#${id}Jstree').jstree({
'core' : {
'multiple' : true,
'animation' : 0,
'themes' : { 'icons':true ,'stripes':false},
'data' : {
'url' : '${ctx}${url}${fn:indexOf(url,"?")==-1?"?":"&"}&extId=${extId}&isAll=${isAll}&openLevel=${not empty openLevel?openLevel:1}&t='+ new Date().getTime(),
'dataType' : 'json'
}
},
'plugins' : ['types' ,"search", <c:if test="${checked==true}">'checkbox',</c:if> 'wholerow'],
'types':{
'default' : { 'icon' : 'fa fa-folder' },
'1' : {'icon' : 'fa fa-home'},
'2' : {'icon' : 'fa fa-umbrella' },
'3' : { 'icon' : 'fa fa-group'},
'4' : { 'icon' : 'fa fa-eur' },
'btn': {'icon' : 'fa fa-square'}
}
}).on('select_node.jstree', function (e, data) {
}).on("loaded.jstree", function (event, data) {
//以下两行是在loaded所有节点后,再做默认选中操作
//取消选中
$("#${id}Jstree").jstree("deselect_all",true);
//第二个参数为默认选中的节点id(“,”隔开),第三个true为不触发默认的select_node.change事件
$('#${id}Jstree').jstree('select_node',$("#${id}Id").val().split(","),true);
});
${id}tree = $('#${id}Jstree').jstree(true);
//单击jstree选项
$('#${id}Jstree').on('changed.jstree',function(e,data){
e.stopPropagation();
var ids = [], names = [], nodes = [];
if ("${checked}" == "true"){
nodes = ${id}tree.get_checked(true);
}else{
nodes = ${id}tree.get_selected(true);
}
for(var i=0; i<nodes.length; i++) {
if ("${checked}" == "true" && nodes[i].children.length > 0){
continue;
}
if ("${notAllowSelectParent}" == "true" && nodes[i].children.length > 0){
top.layer.msg("不能选择父节点("+nodes[i].text+")请重新选择。", {icon: 0});
return false;
}
if ("${notAllowSelectRoot}" == "true" && nodes[i].parent == "#"){
top.layer.msg("不能选择根节点("+nodes[i].text+")请重新选择。", {icon: 0});
return false;
}
ids.push(nodes[i].id);
names.push(nodes[i].text);
if ("${checked}" != "true") {
break;
}
}
$("#${id}Id").val(ids.join(",").replace(/u_/ig,""));
$("#${id}Name").val(names.join(","));
$("#${id}Name").focus();
});
//查找功能
var to = false;
$('#${id}Search_q').keyup(function () {
if(to) { clearTimeout(to); }
to = setTimeout(function () {
var v = $('#${id}Search_q').val();
$('#${id}Jstree').jstree(true).search(v);
}, 250);
});
});
</script>
[/pre]
2、在使用sys:treeselect的地方修改为sys:treeselect2即可,搞定!
3、如果您想要对树的展开层级进行设置,或者根据extId参数设置选项不可选择(代码生成器生成的代码是根据extId过滤不显示),请参照以下代码修改代码生成器生成的后台代码:
[pre]
public List<Map<String, Object>> treeData(@RequestParam(required=false) String extId,
@RequestParam(required=false) String openLevel,
HttpServletResponse response) {
List<Map<String, Object>> mapList = Lists.newArrayList();
List<Category> list = categoryService.findList(new Category());
Category e;
int level;
int parentLevel;
String parentIds;
String[] extIds;
Pattern pattern = Pattern.compile("[0-9]*");
if(StringUtils.isNotBlank(openLevel) && pattern.matcher(openLevel).matches()){
level = Integer.valueOf(openLevel);
}else{
level = 1;
}
for (int i=0; i<list.size(); i++){
e = list.get(i);
Map<String, Object> map = Maps.newHashMap();
map.put("id", e.getId());
map.put("text", e.getName());
map.put("parent", StringUtils.isBlank(e.getParentId()) || "0".equals(e.getParentId()) ? "#" : e.getParentId());
Map<String, Object> state = Maps.newHashMap();
parentIds = e.getParentIds();
//去掉父节点全路径最后一个“,”字符
parentLevel = parentIds.substring(0,parentIds.length()>2?parentIds.length()-2:1).split(",").length;
if(parentLevel <= level){
state.put("opened", true);
}
extIds = extId.split(",");
for(String ext : extIds){
//如果节点的全路径包含排除的id
if(StringUtils.isNotBlank(ext) && (","+e.getParentIds()+e.getId()+",").contains(","+ext+",")){
state.put("disabled", true);
break;
}
}
map.put("state", state);
mapList.add(map);
}
return mapList;
}
[/pre]