菜单管理功能实现-treegrid行编辑以及拖拽效果_treegrid 可编辑行_xiaozaq的博客-程序员秘密

技术标签: easyui  

使用easyui的treegrid实现行编辑和拖拽效果。

下面是demo界面。可以拖拽菜单(放在tr上,则拖拽到目标的子目录,放在边框上则是拖拽到同级目录)


具体实现代码:

menuList.jsp


<html>
<head>
	<title>菜单列表</title>
	
<base href="http://localhost:8080/mysys/">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="easyui/themes/icon.css">
<script type="text/javascript" src="easyui/jquery.min.js"></script>
<script type="text/javascript" src="easyui/jquery.easyui.min.js"></script>
<script src="easyui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="js/js.js"></script>

<link rel="stylesheet" type="text/css" href="css/icon.css">
	<script type="text/javascript" src="ms/menuList.js?d=4"></script>
	<style type="text/css">
	.fitem{
		margin: 5px;
	}
	.fitem label{
		display:inline-block;
		width: 70px;	
		text-align: right;	
	}
	.panel.datagrid{
		margin: 0 auto;
	}
/* 	修改表格表头里面字体大小  */
	.datagrid-header .datagrid-cell span{
		font-size: 18px;
	}
/* 	修改表格里面字体大小 */
	.datagrid-cell{
		font-size: 16px;
	}
/* 	修改表格行高 */
	.datagrid-row {
        height: 40px;
    }
    td[field="enable"] td{
    	 text-align: center;
    }
	</style>
	<style type="text/css">
/* 		treegrid拖动效果 */
		.row-top td{
			border-top:1px solid red;
			background:#fff;
		}
		.row-bottom td{
			border-bottom:1px solid red;
			background:#fff;
		}
		.row-append td{
			border:0;
			background:#FBEC88;
		}
	</style>
</head>
<body>
	<!-- 	数据网格 -->
	<table id="tg" title="菜单列表" 
		style="width:100%;height:auto;margin:0 auto;">
	</table>
</body>
</html>


menuList.js

$(function() {
	query();
})
function query() {
//	$('#tg').treegrid("options")
	$('#tg').treegrid({
	    url:'menu/list',
	    idField:'id',
	    treeField:'name',
	    rownumbers:true,//第一列显示序号
	    fitColumns:true,//列宽按比例扩展到最大
	    onDblClickRow:function(row){edit()},
	    onLoadSuccess: function(row){
            //$(this).treegrid('enableDnd', row?row.id:null);
           //上面的代码是demo中的,但是对于要保存更改到数据库显然走不通,需要向其他办法
           //启用拖动排序
            enableDnd($('#tg'));
        },
	    columns:[[
	        {field:'name',title:'name',width:100,align:'left', halign: 'center',editor:"text"},
	        {field:'url',title:'url',width:100,align:'center',editor:"text"},
	        {field:'icon',title:'icon',width:160,align:'center',editor:"text"},
	        {field:'seq',title:'seq',width:160,align:'center',editor:"numberbox" }
	    ]],
	    toolbar: [
		    	  { text: '添加子菜单', iconCls: 'icon-add', handler: function () {
		    		  append();
		    		}
		    	  }, '-',
		    	  { text: '删除', iconCls: 'icon-remove', handler: function () {
		    		  remove();
		    		}
		    	  }, '-',
		    	  { text: '编辑', iconCls: 'icon-edit', handler: function () {
		    		  edit();
		    		}
		    	  }, '-',
		    	  { text: '保存', iconCls: 'icon-save', handler: function () {
		    		  save();
		    		}
		    	  }, '-',
		    	  { text: '取消编辑', iconCls: 'icon-undo', handler: function () {
		    		  cancelEdit();
		    		}
		    	  }, '-',
		    	  { text: '刷新', iconCls: 'icon-reload', handler: function () {
		    		  query();
		    		}
		    	  }, '-',
		    	  { text: '更新到数据库', iconCls: 'icon-save', handler: function () {
		    		  saveToDB();
		    		}
		    	  }, '-']
	});
}

var editingId;
function append(){
	var node = $('#tg').treegrid('getSelected');
	if(node){
		var obj = {
				id: -1*Math.random(),
				name:'新建菜单',
				parent:{id:node.id},
				left:true,
				visible:true,
				seq:99
			};
		$('#tg').treegrid('append',{
			parent: node.id,  // the node has a 'id' value that defined through 'idField' property
			data: [obj]
		});
		enableDnd($('#tg'));
		params_data.add.push($('#tg').treegrid('find', obj.id));
	}
}
function insert(){
	var node = $('#tg').treegrid('getSelected');
	if (node){
		var obj = {
				id: -1*Math.random(),
				name:'新建菜单',
				parent:node.parent,
				left:true,
				visible:true,
				seq:99
			};
		$('#tg').treegrid('insert', {
			after: node.id,
			data: obj
		});
		enableDnd($('#tg'));
		params_data.add.push($('#tg').treegrid('find', obj.id));
	}
	
}
function edit(){
	if (editingId != undefined){
		save();
	}
	var row = $('#tg').treegrid('getSelected');
	if (row){
		editingId = row.id
		$('#tg').treegrid('beginEdit', editingId);
		//解决添加拖拽功能后无法编辑问题
		/*
		var eds = $('#tg').treegrid('getEditors',editingId);
		for(var i=0;i<eds.length;i++){
			$(eds[i].target).bind('mousedown',function(e){
				e.stopPropagation();
			});
		}*/
		$(".datagrid-row-editing input").each(function(){
			$(this).bind('mousedown',function(e){
				e.stopPropagation();
			});
		});
		
	}
}
function save(){
	if (editingId != undefined){
		$('#tg').treegrid('endEdit', editingId);
		var row = $('#tg').treegrid('find', editingId);
		if(row.id > 0){
			params_data.update.push(row);
		}
		editingId = undefined;
	}
}
function remove(){
	var node = $('#tg').treegrid('getSelected');
	if (node){
		$('#tg').treegrid('remove', node.id);
		if(editingId != undefined && editingId == node.id){
			editingId = undefined;
		}
		if(node.id > 0){
			params_data.delete.push(node);
		}else{
			var idx = params_data.add.indexOf(node);
			params_data.add.remove(idx);
		}
	}
}
function cancelEdit(){
	if (editingId != undefined){
		$('#tg').treegrid('cancelEdit', editingId);
		editingId = undefined;
	}
}
/**保存到数据库*/
var params_data = {add: [],update: [],delete: []};
function saveToDB(){
	save();
	var data = {
            add: [],
            update: [],
            delete: []
    };
    for(var i=0;i<params_data.add.length;i++){
    	delete params_data.add[i]._parentId;
    	delete params_data.add[i].checkState;
    	delete params_data.add[i].checked;
    	delete params_data.add[i].state;
    }
    for(var i=0;i<params_data.update.length;i++){
    	delete params_data.update[i]._parentId;
    	delete params_data.update[i].checkState;
    	delete params_data.update[i].checked;
    	delete params_data.update[i].state;
    }
    for(var i=0;i<params_data.update.length;i++){
    	delete params_data.update[i]._parentId;
    	delete params_data.update[i].checkState;
    	delete params_data.update[i].checked;
    	delete params_data.update[i].state;
    }
    var req_data = {};
    req_data.add = JSON.stringify(params_data.add);
    req_data.update = JSON.stringify(params_data.update);
    req_data.delete = JSON.stringify(params_data.delete);
    $.ajax({
        type: "POST",
        url: 'menu/save',
        dataType: "json",
        data: req_data,
        success: function (rarg) {
            if (rarg.err == undefined) {
                $.messager.show({ title: '提示',
                    msg: '保存成功.',
                    timeout: 3000,
                    showType: 'slide'
                });
                params_data = {add: [],update: [],delete: []};
                query();
            }
            else $.messager.alert('提示', rarg.err); 
            //refreshTab();
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            $.messager.alert('提示', '保存失败,系统繁忙,请稍后再试!');
        }
    });
}

function enableDnd(t){
	var nodes = t.treegrid('getPanel').find('tr[node-id]');
	nodes.find('span.tree-hit').bind('mousedown.treegrid',function(){
		return false;
	});
	nodes.draggable({
		disabled:false,
		revert:true,
		cursor:'pointer',
		proxy: function(source){
			var p = $('<div class="tree-node-proxy tree-dnd-no"></div>').appendTo('body');
			p.html($(source).find('.tree-title').html());
			p.hide();
			return p;
		},
		deltaX: 15,
		deltaY: 15,
		onBeforeDrag:function(){
			$(this).next('tr.treegrid-tr-tree').find('tr[node-id]').droppable({accept:'no-accept'});
		},
		onStartDrag:function(){
			$(this).draggable('proxy').css({
				left:-10000,
				top:-10000
			});
		},
		onDrag:function(e){
			$(this).draggable('proxy').show();
			this.pageY = e.pageY;
		},
		onStopDrag:function(){
			$(this).next('tr.treegrid-tr-tree').find('tr[node-id]').droppable({accept:'tr[node-id]'});
		}
	}).droppable({
		accept:'tr[node-id]',
		onDragOver:function(e,source){
			var pageY = source.pageY;
			var top = $(this).offset().top;
			var bottom = top + $(this).outerHeight();
			$(source).draggable('proxy').removeClass('tree-dnd-no').addClass('tree-dnd-yes');
			$(this).removeClass('row-append row-top row-bottom');
			if (pageY > top + (bottom - top) / 2){
				if (bottom - pageY < 5){
					$(this).addClass('row-bottom');
				} else {
					$(this).addClass('row-append');
				}
			} else {
				if (pageY - top < 5){
					$(this).addClass('row-top');
				} else {
					$(this).addClass('row-append');
				}
			}
		},
		onDragLeave:function(e,source){
			$(source).draggable('proxy').removeClass('tree-dnd-yes').addClass('tree-dnd-no');
			$(this).removeClass('row-append row-top row-bottom');
		},
		onDrop:function(e,source){
			var action,point;
			if ($(this).hasClass('row-append')){
				action = 'append';
			} else {
				action = 'insert';
				point = $(this).hasClass('row-top') ? 'top' : 'bottom';
			}
			$(this).removeClass('row-append row-top row-bottom');
			//alert(action+":"+point);
			// your logic code here
			// do append or insert action and reload the treegrid data
			var src  = t.treegrid('find', $(source).attr('node-id'));
            var dest = t.treegrid('find', $(this).attr('node-id'));
            //alert(src.name+","+dest.name);
            if (src){
            	t.treegrid('remove', src.id);
            }
            if(action == "append"){
            	src.parent = {};
            	src.parent.id = dest.id;
            	t.treegrid('append',{
            		parent: dest.id,  // the node has a 'id' value that defined through 'idField' property
            		data: [src]
            	});
            }else if(action == "insert"){
            	src.parent = dest.parent;
            	var obj = {
                		before: dest.id,
                		after: dest.id,
                		data: src
                }
            	if(point == "top"){
            		delete obj.after;
            	}else{
            		delete obj.before;
            	}
            	t.treegrid('insert', obj);
            }
            if(src.id > 0){
            	params_data.update.push(src);
            }
            
            enableDnd(t);
            /*
            $.ajax({
                url: 'updateCatalogList',
                dataType: 'json',
                type:'post',
                data: {
                    "srcId": src.id,
                    "destId": dest.id
                },
                success:function(data){
                    if(data.result)
                    {
                        $('#tt').treegrid('reload');    //重新加载treegrid        
                   }
                }
            
            });
            */
		}
	});
}

MenuAction.java

@RequestMapping(value = "list")
	@ResponseBody
	public List<Menu> list(@RequestParam Map map) {
		List<Menu> list = menuService.list(map);
		return list;
	}
	@RequestMapping(value = "save")
	@ResponseBody
	public Map save(@RequestParam String add
			,@RequestParam String delete
			,@RequestParam String update) {
		JSONArray addArr = JSONArray.fromObject(add);
		JSONArray deleteArr = JSONArray.fromObject(delete);
		JSONArray updateArr = JSONArray.fromObject(update);
		List<Menu> addlist = (List) JSONArray.toCollection(addArr,  
				Menu.class); 
		List<Menu> deletelist = (List) JSONArray.toCollection(deleteArr,  
				Menu.class); 
		List<Menu> updatelist = (List) JSONArray.toCollection(updateArr,  
				Menu.class); 
		menuService.saveAll(addlist,deletelist,updatelist);
		Map map = new HashMap();
		return map;
	}

访问menu/list的结果:

[{"id":3,"parent":null,"name":"系统设置","url":null,"visible":true,"leaf":true,"seq":1,"roles":[],"children":[],"icon":null},{"id":6,"parent":null,"name":"基础数据","url":null,"visible":true,"leaf":true,"seq":2,"roles":[],"children":[],"icon":null},{"id":7,"parent":null,"name":"权限管理","url":null,"visible":true,"leaf":true,"seq":3,"roles":[],"children":[{"id":9,"parent":{"id":7,"parent":null,"name":null,"url":null,"visible":false,"leaf":false,"seq":0,"roles":[],"children":[],"icon":null},"name":"用户管理","url":"user/list","visible":true,"leaf":true,"seq":1,"roles":[],"children":[],"icon":"3"},{"id":10,"parent":{"id":7,"parent":null,"name":null,"url":null,"visible":false,"leaf":false,"seq":0,"roles":[],"children":[],"icon":null},"name":"角色管理","url":"role/list","visible":true,"leaf":true,"seq":2,"roles":[],"children":[],"icon":"2"},{"id":11,"parent":{"id":7,"parent":null,"name":null,"url":null,"visible":false,"leaf":false,"seq":0,"roles":[],"children":[],"icon":null},"name":"菜单管理","url":"menu/list","visible":true,"leaf":true,"seq":3,"roles":[],"children":[],"icon":null}],"icon":null},{"id":8,"parent":null,"name":"订单管理","url":null,"visible":true,"leaf":true,"seq":4,"roles":[],"children":[],"icon":null}]


主要难点:

1.结点的新增、删除、修改。editingId是使用treegrid控件后创建的一个全局变量。

2.实现拖拽功能。调用方法:enableDnd($('#tg'));

3.拖拽功能导致编辑器无法正常工作。解决方法是在edit()中执行下面代码:

$(".datagrid-row-editing input").each(function(){
			$(this).bind('mousedown',function(e){
				e.stopPropagation();
			});
		});
4.主要使用的到api:

$('#tg').treegrid('append', {parent: node.id,data: [obj]});

$('#tg').treegrid('insert', {before: node.id,data: obj});

$('#tg').treegrid('insert', {after: node.id,data: obj});

$('#tg').treegrid('beginEdit', editingId);

$('#tg').treegrid('endEdit', editingId);

var row = $('#tg').treegrid('find', editingId);

var node = $('#tg').treegrid('getSelected');

$('#tg').treegrid('cancelEdit', editingId);


onDblClickRow:function(row){edit()},


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaozaq/article/details/52870209

智能推荐

移动端关于点击输入框,因字体变化,导致布局变形的问题_luckSll的博客-程序员秘密

$(function(){        var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';        var _orig_font = document.documentElement.style.fontSize;        $(window).on(resizeEv

javascript判断页面是否在iframe中_weixin_34192993的博客-程序员秘密

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

JMeter相关使用_jmeter请使用微信_流墨馨的博客-程序员秘密

今天学习下压力测试工具JMeter的使用,参照教学视频进行记录,仅供今后学习使用,欢迎指导!提及压力测试,就忍不住想到性能测试、负载测试,关于这三者之间的关系,本人目前是这样粗略理解的(对,没错,就是粗略):首先,性能测试指的是通过自动化测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标做测试。负载测试和压力测试都是属于性能测试,有关性能测试的还有时间性能测试、空间性能测试、一般性能测试、稳定性测试等。负载测试注重的是在测试系统时系统各项性能指标的变化情况,测试的是整个变化的过程,而压力测试

【Linux】软链接、硬链接_weixin_34032827的博客-程序员秘密

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

java nio为什么是非阻塞_JAVA NIO 不是同步非阻塞I/O吗,为什么说JAVA NIO提供了基于Selector的异步网络I/O?..._fifizoo的博客-程序员秘密

java nio的io模型是同步非阻塞,这里的同步异步指的是真正io操作(数据内核态用户态的拷贝)是否需要进程参与。而说java nio提供了异步处理,这个异步应该是指编程模型上的异步。基于reactor模式的事件驱动,事件处理器的注册和处理器的执行是异步的。JAVA NIO是同步非阻塞io。同步和异步说的是消息的通知机制,阻塞非阻塞说的是线程的状态 。下面说说我的理解,client和服务器建立了...

随便推点

MATLAB处理excel表格中数据(一)读取和写入数据_matlab如何处理excel数据_向兴的博客-程序员秘密

1,在matlab中对应的文件夹内,存有一个excel表格。demo11.xlsx表格中的数据,如下图所示。2,在matlab界面中,读取数据。读取函数,xlsread。利用,data=xlsread('demo11.xlsx'),就可读取出demo11.xlsx文件夹中的数据。但是,data只能读取demo.xlsx中的数据。如下图所示。除了读取数据,字符串也读取出来,如下图所示。3,在matlab中写入数据到demo11.xlsx表格中去。首先,输入要添.

1.HTML概述_码小余の博客的博客-程序员秘密

HTML概述导读:本小节主要讲解 HTML 的基本信息,其中包含 HTML 概念、HTML 发展历程和 HTML 标准版本的发展历程。通过本小节的学习可以对 HTML 的含义有个初步的理解,为后续进一步学习 HTML 相关概念打下基础。什么是HTMLHTML 是个缩写形式,其全称为 Hyper Text Markup Language,翻译成中文的含义为超文本标记语言。HTML 不是一门编程...

EasyUI-DataGrid编辑时出现下拉列表框选择,同时修改其它列的值_easyui表格修改editor字典值和显示值修改时下拉框显示字典值_秋冬瓜的博客-程序员秘密

首先是进行表格式的初始化,主要是为了可以进行编辑//初始化表格$.extend($.fn.datagrid.methods, { editCell: function (jq, param) { return jq.each(function () { var opts = $(this).datagrid('options');

2021华为Java面试真题解析mysql慢查询日志分析_前端框架资料大全的博客-程序员秘密

第一个暴击:Spring上一份Spring的手绘思维脑图(就像是个知识大纲总结),预览一下Spring的知识点,心里有个谱。不过这边我是采用的截图方式,为了把全部的内容都截取出来,所以整个就比较小,可能不是很清晰。Spring面试真题(七大模块:一般问题+IOC+Beans+注解+数据访问+AOP+MVC)一般问题1. 不同版本的 Spring Framework 有哪些主要功能?2. 什么是 Spring Framework?3. 列举 Spring Framework 的优点4.

8.5.1类型擦除_doujingjie的博客-程序员秘密

8.5泛型代码和虚拟机虚拟机中并不存在泛型类型的对象——虚拟机中所有的对象都是普通类类型的。下面讲解编译器是如何“擦除”类型参数的,类型擦除又对我们程序员有什么影响。8.5.1 类型擦除当你定义一个泛型类型的时候,一个对应的原始类型(raw type)会自动生成。这个原始类型跟对应的泛型类型①名称相同,②删除了类型参数,③类型变量被替换成它的边界列表中的第一个边界(无边界的类型变量被替换为O...

推荐文章

热门文章

相关标签