使用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>
$(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()},
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow