{"id":33,"date":"2013-05-22T22:08:00","date_gmt":"2013-05-22T22:08:00","guid":{"rendered":"http:\/\/tpodolak.com.hostingasp.pl\/blog\/2013\/05\/22\/extjs-drag-and-drop-between-tables\/"},"modified":"2016-01-30T23:48:02","modified_gmt":"2016-01-30T23:48:02","slug":"extjs-drag-and-drop-between-tables","status":"publish","type":"post","link":"https:\/\/tpodolak.com\/blog\/2013\/05\/22\/extjs-drag-and-drop-between-tables\/","title":{"rendered":"Extjs &#8211; drag-and-drop between tables"},"content":{"rendered":"<p>Extjs framework provides us with two helper classes responsible for performing drag-drop operation:<br \/>\n<\/p>\n<ul>\n<li>Ext.dd.DragZone<\/li>\n<p>The most important element of this class is <i>getDragData<\/i> function, which provides data for drag operation.<br \/>\nIt is necessary for this method to return object with <i>ddel<\/i> property containing DOM element, from which draging operation was originated.<\/p>\n<li>Ext.dd.DropZone<\/li>\n<p>This class has two important methods. The first one is <i>getTargetFromEvent<\/i> which informs if drop operation should be performed. The other one is <i>onNodeDrop<\/i> which is responsible for actual drop operation.\n<\/ul>\n<p>\nHaving covered the basics, let&#8217;s try to implement drag-drop operation. Let&#8217;s start from creating simple container with two tables.<\/p>\n<pre lang=\"javascript\">\r\nExt.define('GeneralLearning.views.DragAndDropView', {\r\n    extend:'Ext.container.Container',\r\n    renderTpl:Ext.create('Ext.Template',\r\n     '<div id=\"table_container\">',\r\n        '<table id=\"leftTable\" style=\"margin: 20px 20px\">',\r\n             '<tr>',\r\n                '<th>a<\/th>',\r\n                '<th>b<\/th>',\r\n             '<\/tr>',\r\n            '<tr>',\r\n                '<td>1<\/td>',\r\n                '<td>2<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>4<\/td>',\r\n                '<td>9<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>16<\/td>',\r\n                '<td>25<\/td>',\r\n            '<\/tr>',\r\n        '<\/table>',\r\n        '<table id=\"rightTable\" style=\"margin: 20px 20px\">',\r\n             '<tr>',\r\n                '<th>a<\/th>',\r\n                '<th>b<\/th>',\r\n             '<\/tr>',\r\n             '<tr>',\r\n                '<td>1<\/td>',\r\n                '<td>2<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>4<\/td>',\r\n                '<td>9<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>16<\/td>',\r\n                '<td>25<\/td>',\r\n            '<\/tr>',\r\n        '<\/table>',\r\n    '<\/div>')\r\n})\r\n<\/pre>\n<p>In the next step we will create DragZone and DropZone.<\/p>\n<pre lang=\"javascript\">\r\n createDragDropZones:function () {\r\n        var me = this,\r\n            rightTable = me.el.select('#rightTable').first(),\r\n            leftTable = me.el.select('#leftTable').first();\r\n        Ext.create('Ext.dd.DragZone', rightTable, {\r\n            getDragData:function (e) {\r\n                if (e.target.nodeName == 'TD') {\r\n                    var sourceEl = e.target;\r\n                    var d = sourceEl.cloneNode(true);\r\n                    d.id = Ext.id();\r\n                    return {\r\n                        ddel:d,\r\n                        sourceEl:sourceEl,\r\n                        repairXY:Ext.fly(sourceEl).getXY()\r\n                    }\r\n                }\r\n\r\n            },\r\n            getRepairXY:function () {\r\n                return this.dragData.repairXY;\r\n            }\r\n        });\r\n\r\n        Ext.create('Ext.dd.DropZone', leftTable, {\r\n            getTargetFromEvent:function (e) {\r\n                if (e.target.nodeName == 'TD')\r\n                    return e.target;\r\n            },\r\n            onNodeEnter:function (target, dd, e, data) {\r\n                Ext.fly(target).addCls('drop-target-hover');\r\n            },\r\n            onNodeOut:function (target, dd, e, data) {\r\n                Ext.fly(target).removeCls('drop-target-hover');\r\n            },\r\n            onNodeOver:function (target, dd, e, data) {\r\n                return Ext.dd.DropZone.prototype.dropAllowed;\r\n            },\r\n            onNodeDrop:function (target, dd, e, data) {\r\n                target.parentNode.replaceChild(dd.dragData.ddel, target)\r\n                return true;\r\n            }\r\n        })\r\n    }\r\n<\/pre>\n<p>As You cas see <i>DragZone<\/i> was created on the right table. I want to be able to drag only <i>td<\/i> elements, that is why function <i>getDragData<\/i> returns null, if drag operation was originated from other HTML element. Extjs will take care of showing approperiate animation, if drag-drop is available. I also overrode <i>getRepairXY<\/i> method, which is responsible for providing <i>X<\/i> and <i>Y<\/i> coordinates for animation, which is fired in case of invalid drop off. The code responsible for handling drop operation is a little bit more complicated. After creating a <i>DropZone<\/i> from left table, I ovverode <i>getTargetFromEvent<\/i> method, so as to drop could be performed only to <i>td<\/i> elements of table. What is more, using <i>onNodeEnter<\/i> and <i>onNodeOut<\/i> methods I changed target elements of the drop, to show user where given element will be placed. Actual drop is performed in <i>onNodeDrop<\/i> method, in my case I just replace HTML node form original one to dropped.<br \/>\nHere is a result:<br \/>\n<a href=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2013\/05\/extjs-drag-and-drop-between-tables\/dragdrop.gif\" rel=\"attachment wp-att-347\"><img decoding=\"async\" src=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2013\/05\/extjs-drag-and-drop-between-tables\/dragdrop.gif\" alt=\"drag-and-drop\" width=\"500\" class=\"aligncenter size-full wp-image-347\" \/><\/a><br \/>\nEntire code listing looks like that:<\/p>\n<pre lang=\"css\">\r\n #table_container table { border: 1px solid black;float:left;width:400px;}\r\n #table_container td, #table_container th   { border: 1px solid black;}\r\n \r\n td.drop-target-hover {\r\n     border-color: yellow !important;\r\n     border-width: 3px !important;\r\n }\r\n<\/pre>\n<pre lang=\"javascript\">\r\nExt.define('GeneralLearning.views.DragAndDropView', {\r\n    extend:'Ext.container.Container',\r\n    renderTpl:Ext.create('Ext.Template',\r\n     '<div id=\"table_container\">',\r\n        '<table id=\"leftTable\" style=\"margin: 20px 20px\">',\r\n             '<tr>',\r\n                '<th>a<\/th>',\r\n                '<th>b<\/th>',\r\n             '<\/tr>',\r\n            '<tr>',\r\n                '<td>1<\/td>',\r\n                '<td>2<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>4<\/td>',\r\n                '<td>9<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>16<\/td>',\r\n                '<td>25<\/td>',\r\n            '<\/tr>',\r\n        '<\/table>',\r\n        '<table id=\"rightTable\" style=\"margin: 20px 20px\">',\r\n             '<tr>',\r\n                '<th>a<\/th>',\r\n                '<th>b<\/th>',\r\n             '<\/tr>',\r\n             '<tr>',\r\n                '<td>1<\/td>',\r\n                '<td>2<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>4<\/td>',\r\n                '<td>9<\/td>',\r\n            '<\/tr>',\r\n            '<tr>',\r\n                '<td>16<\/td>',\r\n                '<td>25<\/td>',\r\n            '<\/tr>',\r\n        '<\/table>',\r\n    '<\/div>'),\r\n\r\n    initComponent:function () {\r\n        var me = this;\r\n        me.callParent(arguments);\r\n        me.on('afterrender', me.createDragDropZones, me);\r\n    },\r\n\r\n    createDragDropZones:function () {\r\n        var me = this,\r\n            rightTable = me.el.select('#rightTable').first(),\r\n            leftTable = me.el.select('#leftTable').first();\r\n        Ext.create('Ext.dd.DragZone', rightTable, {\r\n            getDragData:function (e) {\r\n                if (e.target.nodeName == 'TD') {\r\n                    var sourceEl = e.target;\r\n                    var d = sourceEl.cloneNode(true);\r\n                    d.id = Ext.id();\r\n                    return {\r\n                        ddel:d,\r\n                        sourceEl:sourceEl,\r\n                        repairXY:Ext.fly(sourceEl).getXY()\r\n                    }\r\n                }\r\n            },\r\n            getRepairXY:function () {\r\n                return this.dragData.repairXY;\r\n            }\r\n        });\r\n\r\n        Ext.create('Ext.dd.DropZone', leftTable, {\r\n            getTargetFromEvent:function (e) {\r\n                if (e.target.nodeName == 'TD')\r\n                    return e.target;\r\n            },\r\n            onNodeEnter:function (target, dd, e, data) {\r\n                Ext.fly(target).addCls('drop-target-hover');\r\n            },\r\n            onNodeOut:function (target, dd, e, data) {\r\n                Ext.fly(target).removeCls('drop-target-hover');\r\n            },\r\n            onNodeOver:function (target, dd, e, data) {\r\n                return Ext.dd.DropZone.prototype.dropAllowed;\r\n            },\r\n            onNodeDrop:function (target, dd, e, data) {\r\n                target.parentNode.replaceChild(dd.dragData.ddel, target)\r\n                return true;\r\n            }\r\n        })\r\n    }\r\n})\r\n<\/pre>\n<p>Source code for this post can be found <a href=\"https:\/\/github.com\/tpodolak\/Blog\/tree\/master\/ExtjsDragDrop\">here<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Extjs framework provides us with two helper classes responsible for performing drag-drop operation: Ext.dd.DragZone The most important element of this class is getDragData function, which provides data for drag operation. It is necessary for this method to return object with ddel property containing DOM element, from which draging operation was originated. Ext.dd.DropZone This class has [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[68,67],"tags":[211,210],"class_list":["post-33","post","type-post","status-publish","format-standard","hentry","category-drag-and-drop","category-extjs-4-1-1","tag-drag-and-drop","tag-extjs-4-1-1"],"_links":{"self":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/33","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/comments?post=33"}],"version-history":[{"count":6,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/33\/revisions"}],"predecessor-version":[{"id":539,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/33\/revisions\/539"}],"wp:attachment":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/media?parent=33"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/categories?post=33"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/tags?post=33"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}