diff --git a/dev/App.vue b/dev/App.vue index fc7b3bf..c77b2af 100644 --- a/dev/App.vue +++ b/dev/App.vue @@ -6,6 +6,9 @@ @change-name="onChangeName" @delete-node="onDel" @add-node="onAddNode" + @drop="drop" + @drop-before="dropBefore" + @drop-after="dropAfter" :model="data" default-tree-node-name="new node" default-leaf-node-name="new leaf" @@ -81,6 +84,18 @@ console.log(params) }, + drop: function ({node, src, target}) { + console.log('drop', node, src, target) + }, + + dropBefore: function ({node, src, target}) { + console.log('drop-before', node, src, target) + }, + + dropAfter: function ({node, src, target}) { + console.log('drop-after', node, src, target) + }, + addNode () { var node = new TreeNode({ name: 'new node', isLeaf: false }) if (!this.data.children) this.data.children = [] diff --git a/dist/vue-tree-list.min.js b/dist/vue-tree-list.min.js index 0d928d2..71faf52 100644 --- a/dist/vue-tree-list.min.js +++ b/dist/vue-tree-list.min.js @@ -1 +1 @@ -!function(A,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.VueTreeList=t():A.VueTreeList=t()}(this,function(){return function(A){function t(i){if(e[i])return e[i].exports;var M=e[i]={exports:{},id:i,loaded:!1};return A[i].call(M.exports,M,M.exports,t),M.loaded=!0,M.exports}var e={};return t.m=A,t.c=e,t.p="",t(0)}([function(A,t,e){"use strict";t.VueTreeList=e(1),t.TreeNode=e(13).TreeNode,t.Tree=e(13).Tree},function(A,t,e){e(2);var i=e(11)(e(12),e(15),null,null);A.exports=i.exports},function(A,t,e){var i=e(3);"string"==typeof i&&(i=[[A.id,i,""]]),i.locals&&(A.exports=i.locals);e(9)("a44a901e",i,!0)},function(A,t,e){t=A.exports=e(4)(),t.push([A.id,"@font-face{font-family:icomoon;src:url("+e(5)+");src:url("+e(5)+'#iefix) format("embedded-opentype"),url('+e(6)+') format("truetype"),url('+e(7)+') format("woff"),url('+e(8)+'#icomoon) format("svg");font-weight:400;font-style:normal}.vtl-icon{font-family:icomoon!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.vtl-icon.vtl-menu-icon{margin-right:4px}.vtl-icon.vtl-menu-icon:hover{color:inherit}.vtl-icon:hover{color:blue}.vtl-icon-file:before{content:"\\E906"}.vtl-icon-folder:before{content:"\\E907"}.vtl-icon-caret-down:before{content:"\\E901"}.vtl-icon-caret-right:before{content:"\\E900"}.vtl-icon-edit:before{content:"\\E902"}.vtl-icon-folder-plus-e:before{content:"\\E903"}.vtl-icon-plus:before{content:"\\E904"}.vtl-icon-trash:before{content:"\\E905"}.vtl-border{height:5px}.vtl-border.vtl-up{margin-top:-5px}.vtl-border.vtl-bottom,.vtl-border.vtl-up{background-color:transparent}.vtl-border.vtl-active{border-bottom:3px dashed blue}.vtl-tree-node{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;padding:5px 0 5px 1rem}.vtl-tree-node .vtl-input{border:none;max-width:150px;border-bottom:1px solid blue}.vtl-tree-node:hover{background-color:#f0f0f0}.vtl-tree-node.vtl-active{outline:2px dashed pink}.vtl-tree-node .vtl-caret{margin-left:-1rem}.vtl-tree-node .vtl-operation{margin-left:2rem;letter-spacing:1px}.vtl-item{cursor:pointer}.vtl-tree-margin{margin-left:2em}',""])},function(A,t){A.exports=function(){var A=[];return A.toString=function(){for(var A=[],t=0;te.parts.length&&(i.parts.length=e.parts.length)}else{for(var n=[],M=0;M0&&this.initNode(n,o.children),A.addChildren(n)}},t.Tree=e,t.TreeNode=i},function(A,t){"use strict";var e;t.addHandler=function(A,t,i){e=i,A.addEventListener?A.addEventListener(t,i,!1):A.attachEvent?A.attachEvent("on"+t,i):A["on"+t]=i},t.removeHandler=function(A,t){A.removeEventListener?A.removeEventListener(t,e,!1):A.detachEvent?A.detachEvent("on"+t,e):A["on"+t]=null}},function(A,t){A.exports={render:function(){var A=this,t=A.$createElement,e=A._self._c||t;return e("div",{staticClass:"vtl"},["root"!==A.model.name?e("div",[e("div",{staticClass:"vtl-border vtl-up",class:{"vtl-active":A.isDragEnterUp},on:{drop:A.dropUp,dragenter:A.dragEnterUp,dragover:A.dragOverUp,dragleave:A.dragLeaveUp}}),A._v(" "),e("div",{class:A.treeNodeClass,attrs:{id:A.model.id,draggable:!A.model.dragDisabled},on:{dragstart:A.dragStart,dragover:A.dragOver,dragenter:A.dragEnter,dragleave:A.dragLeave,drop:A.drop,dragend:A.dragEnd,mouseover:A.mouseOver,mouseout:A.mouseOut,click:function(t){return t.stopPropagation(),A.click(t)}}},[A.model.children&&A.model.children.length>0?e("span",{staticClass:"vtl-caret vtl-is-small"},[e("i",{staticClass:"vtl-icon",class:A.caretClass,on:{click:function(t){return t.preventDefault(),t.stopPropagation(),A.toggle(t)}}})]):A._e(),A._v(" "),A.model.isLeaf?e("span",[A._t("leafNodeIcon",[e("i",{staticClass:"vtl-icon vtl-menu-icon vtl-icon-file"})])],2):e("span",[A._t("treeNodeIcon",[e("i",{staticClass:"vtl-icon vtl-menu-icon vtl-icon-folder"})])],2),A._v(" "),A.editable?e("input",{ref:"nodeInput",staticClass:"vtl-input",attrs:{type:"text"},domProps:{value:A.model.name},on:{input:A.updateName,blur:A.setUnEditable}}):e("div",{staticClass:"vtl-node-content"},[A._v("\n "+A._s(A.model.name)+"\n ")]),A._v(" "),e("div",{directives:[{name:"show",rawName:"v-show",value:A.isHover,expression:"isHover"}],staticClass:"vtl-operation"},[A.model.isLeaf||A.model.addTreeNodeDisabled?A._e():e("span",{attrs:{title:"add tree node"},on:{click:function(t){return t.stopPropagation(),t.preventDefault(),A.addChild(!1)}}},[A._t("addTreeNode",[e("i",{staticClass:"vtl-icon vtl-icon-folder-plus-e"})])],2),A._v(" "),A.model.isLeaf||A.model.addLeafNodeDisabled?A._e():e("span",{attrs:{title:"add leaf node"},on:{click:function(t){return t.stopPropagation(),t.preventDefault(),A.addChild(!0)}}},[A._t("addLeafNode",[e("i",{staticClass:"vtl-icon vtl-icon-plus"})])],2),A._v(" "),A.model.editNodeDisabled?A._e():e("span",{attrs:{title:"edit"},on:{click:function(t){return t.stopPropagation(),t.preventDefault(),A.setEditable(t)}}},[A._t("editNode",[e("i",{staticClass:"vtl-icon vtl-icon-edit"})])],2),A._v(" "),A.model.delNodeDisabled?A._e():e("span",{attrs:{title:"delete"},on:{click:function(t){return t.stopPropagation(),t.preventDefault(),A.delNode(t)}}},[A._t("delNode",[e("i",{staticClass:"vtl-icon vtl-icon-trash"})])],2)])]),A._v(" "),A.model.children&&A.model.children.length>0&&A.expanded?e("div",{staticClass:"vtl-border vtl-bottom",class:{"vtl-active":A.isDragEnterBottom},on:{drop:A.dropBottom,dragenter:A.dragEnterBottom,dragover:A.dragOverBottom,dragleave:A.dragLeaveBottom}}):A._e()]):A._e(),A._v(" "),A.isFolder?e("div",{directives:[{name:"show",rawName:"v-show",value:"root"===A.model.name||A.expanded,expression:"model.name === 'root' || expanded"}],class:{"vtl-tree-margin":"root"!==A.model.name}},A._l(A.model.children,function(t){return e("item",{key:t.id,attrs:{"default-tree-node-name":A.defaultTreeNodeName,"default-leaf-node-name":A.defaultLeafNodeName,"default-expanded":A.defaultExpanded,model:t}},[A._t("addTreeNode",null,{slot:"addTreeNode"}),A._v(" "),A._t("addLeafNode",null,{slot:"addLeafNode"}),A._v(" "),A._t("editNode",null,{slot:"editNode"}),A._v(" "),A._t("delNode",null,{slot:"delNode"})],2)}),1):A._e()])},staticRenderFns:[]}}])}); \ No newline at end of file +!function(A,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueTreeList=e():A.VueTreeList=e()}(this,function(){return function(A){function e(i){if(t[i])return t[i].exports;var M=t[i]={exports:{},id:i,loaded:!1};return A[i].call(M.exports,M,M.exports,e),M.loaded=!0,M.exports}var t={};return e.m=A,e.c=t,e.p="",e(0)}([function(A,e,t){"use strict";e.VueTreeList=t(1),e.TreeNode=t(13).TreeNode,e.Tree=t(13).Tree},function(A,e,t){t(2);var i=t(11)(t(12),t(15),null,null);A.exports=i.exports},function(A,e,t){var i=t(3);"string"==typeof i&&(i=[[A.id,i,""]]),i.locals&&(A.exports=i.locals);t(9)("a44a901e",i,!0)},function(A,e,t){e=A.exports=t(4)(),e.push([A.id,"@font-face{font-family:icomoon;src:url("+t(5)+");src:url("+t(5)+'#iefix) format("embedded-opentype"),url('+t(6)+') format("truetype"),url('+t(7)+') format("woff"),url('+t(8)+'#icomoon) format("svg");font-weight:400;font-style:normal}.vtl-icon{font-family:icomoon!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.vtl-icon.vtl-menu-icon{margin-right:4px}.vtl-icon.vtl-menu-icon:hover{color:inherit}.vtl-icon:hover{color:blue}.vtl-icon-file:before{content:"\\E906"}.vtl-icon-folder:before{content:"\\E907"}.vtl-icon-caret-down:before{content:"\\E901"}.vtl-icon-caret-right:before{content:"\\E900"}.vtl-icon-edit:before{content:"\\E902"}.vtl-icon-folder-plus-e:before{content:"\\E903"}.vtl-icon-plus:before{content:"\\E904"}.vtl-icon-trash:before{content:"\\E905"}.vtl-border{height:5px}.vtl-border.vtl-up{margin-top:-5px}.vtl-border.vtl-bottom,.vtl-border.vtl-up{background-color:transparent}.vtl-border.vtl-active{border-bottom:3px dashed blue}.vtl-tree-node{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;padding:5px 0 5px 1rem}.vtl-tree-node .vtl-input{border:none;max-width:150px;border-bottom:1px solid blue}.vtl-tree-node:hover{background-color:#f0f0f0}.vtl-tree-node.vtl-active{outline:2px dashed pink}.vtl-tree-node .vtl-caret{margin-left:-1rem}.vtl-tree-node .vtl-operation{margin-left:2rem;letter-spacing:1px}.vtl-item{cursor:pointer}.vtl-tree-margin{margin-left:2em}',""])},function(A,e){A.exports=function(){var A=[];return A.toString=function(){for(var A=[],e=0;et.parts.length&&(i.parts.length=t.parts.length)}else{for(var n=[],M=0;M0&&this.initNode(n,o.children),A.addChildren(n)}},e.Tree=t,e.TreeNode=i},function(A,e){"use strict";var t;e.addHandler=function(A,e,i){t=i,A.addEventListener?A.addEventListener(e,i,!1):A.attachEvent?A.attachEvent("on"+e,i):A["on"+e]=i},e.removeHandler=function(A,e){A.removeEventListener?A.removeEventListener(e,t,!1):A.detachEvent?A.detachEvent("on"+e,t):A["on"+e]=null}},function(A,e){A.exports={render:function(){var A=this,e=A.$createElement,t=A._self._c||e;return t("div",{staticClass:"vtl"},["root"!==A.model.name?t("div",[t("div",{staticClass:"vtl-border vtl-up",class:{"vtl-active":A.isDragEnterUp},on:{drop:A.dropBefore,dragenter:A.dragEnterUp,dragover:A.dragOverUp,dragleave:A.dragLeaveUp}}),A._v(" "),t("div",{class:A.treeNodeClass,attrs:{id:A.model.id,draggable:!A.model.dragDisabled},on:{dragstart:A.dragStart,dragover:A.dragOver,dragenter:A.dragEnter,dragleave:A.dragLeave,drop:A.drop,dragend:A.dragEnd,mouseover:A.mouseOver,mouseout:A.mouseOut,click:function(e){return e.stopPropagation(),A.click(e)}}},[A.model.children&&A.model.children.length>0?t("span",{staticClass:"vtl-caret vtl-is-small"},[t("i",{staticClass:"vtl-icon",class:A.caretClass,on:{click:function(e){return e.preventDefault(),e.stopPropagation(),A.toggle(e)}}})]):A._e(),A._v(" "),A.model.isLeaf?t("span",[A._t("leafNodeIcon",[t("i",{staticClass:"vtl-icon vtl-menu-icon vtl-icon-file"})])],2):t("span",[A._t("treeNodeIcon",[t("i",{staticClass:"vtl-icon vtl-menu-icon vtl-icon-folder"})])],2),A._v(" "),A.editable?t("input",{ref:"nodeInput",staticClass:"vtl-input",attrs:{type:"text"},domProps:{value:A.model.name},on:{input:A.updateName,blur:A.setUnEditable}}):t("div",{staticClass:"vtl-node-content"},[A._v("\n "+A._s(A.model.name)+"\n ")]),A._v(" "),t("div",{directives:[{name:"show",rawName:"v-show",value:A.isHover,expression:"isHover"}],staticClass:"vtl-operation"},[A.model.isLeaf||A.model.addTreeNodeDisabled?A._e():t("span",{attrs:{title:"add tree node"},on:{click:function(e){return e.stopPropagation(),e.preventDefault(),A.addChild(!1)}}},[A._t("addTreeNode",[t("i",{staticClass:"vtl-icon vtl-icon-folder-plus-e"})])],2),A._v(" "),A.model.isLeaf||A.model.addLeafNodeDisabled?A._e():t("span",{attrs:{title:"add leaf node"},on:{click:function(e){return e.stopPropagation(),e.preventDefault(),A.addChild(!0)}}},[A._t("addLeafNode",[t("i",{staticClass:"vtl-icon vtl-icon-plus"})])],2),A._v(" "),A.model.editNodeDisabled?A._e():t("span",{attrs:{title:"edit"},on:{click:function(e){return e.stopPropagation(),e.preventDefault(),A.setEditable(e)}}},[A._t("editNode",[t("i",{staticClass:"vtl-icon vtl-icon-edit"})])],2),A._v(" "),A.model.delNodeDisabled?A._e():t("span",{attrs:{title:"delete"},on:{click:function(e){return e.stopPropagation(),e.preventDefault(),A.delNode(e)}}},[A._t("delNode",[t("i",{staticClass:"vtl-icon vtl-icon-trash"})])],2)])]),A._v(" "),A.model.children&&A.model.children.length>0&&A.expanded?t("div",{staticClass:"vtl-border vtl-bottom",class:{"vtl-active":A.isDragEnterBottom},on:{drop:A.dropAfter,dragenter:A.dragEnterBottom,dragover:A.dragOverBottom,dragleave:A.dragLeaveBottom}}):A._e()]):A._e(),A._v(" "),A.isFolder?t("div",{directives:[{name:"show",rawName:"v-show",value:"root"===A.model.name||A.expanded,expression:"model.name === 'root' || expanded"}],class:{"vtl-tree-margin":"root"!==A.model.name}},A._l(A.model.children,function(e){return t("item",{key:e.id,attrs:{"default-tree-node-name":A.defaultTreeNodeName,"default-leaf-node-name":A.defaultLeafNodeName,"default-expanded":A.defaultExpanded,model:e}},[A._t("addTreeNode",null,{slot:"addTreeNode"}),A._v(" "),A._t("addLeafNode",null,{slot:"addLeafNode"}),A._v(" "),A._t("editNode",null,{slot:"editNode"}),A._v(" "),A._t("delNode",null,{slot:"delNode"})],2)}),1):A._e()])},staticRenderFns:[]}}])}); \ No newline at end of file diff --git a/package.json b/package.json index fd79b64..4a360fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-tree-list", - "version": "1.3.1", + "version": "1.3.2", "description": "A vue component for tree structure. Support adding treenode/leafnode, editing node's name and dragging.", "main": "dist/vue-tree-list.min.js", "scripts": { diff --git a/readme.md b/readme.md index 3f25cba..6df8e42 100644 --- a/readme.md +++ b/readme.md @@ -188,8 +188,9 @@ click | TreeNode | Trigger when clicking a tree node change-name | {'id', 'oldName', 'newName'} | Trigger after changing a node's name delete-node | TreeNode | Trigger when clicking `delNode` button. You can call `remove` of `TreeNode` to remove the node. add-node | TreeNode | Trigger after adding a new node -drop | {'node', 'oldParent'} | Trigger after dropping a node into another -drop-up | {'node', 'oldParent'} | Trigger after extracting a node from another +drop | {node, src, target} | Trigger after dropping a node into another. node: the draggable node, src: the draggable node's parent, target: the node that draggable node will drop into +drop-before | {node, src, target} | Trigger after dropping a node before another. node: the draggable node, src: the draggable node's parent, target: the node that draggable node will drop before +drop-after | {node, src, target} | Trigger after dropping a node after another. node: the draggable node, src: the draggable node's parent, target: the node that draggable node will drop after # customize operation icons The component has default icons for `addTreeNode`, `addLeafNode`, `editNode`, `delNode` button, but you can also customize them: diff --git a/src/VueTreeList.vue b/src/VueTreeList.vue index d01cd0f..1cd55fb 100644 --- a/src/VueTreeList.vue +++ b/src/VueTreeList.vue @@ -2,7 +2,7 @@
@@ -63,7 +63,7 @@
@@ -89,7 +89,7 @@ import { Tree, TreeNode } from './Tree.js' import { addHandler, removeHandler } from './tools.js' - let fromComp = null + let compInOperation = null export default { data: function () { @@ -219,7 +219,7 @@ dragStart(e) { if (!(this.model.dragDisabled || this.model.disabled)) { - fromComp = this + compInOperation = this // for firefox e.dataTransfer.setData("data","data"); e.dataTransfer.effectAllowed = 'move' @@ -228,14 +228,14 @@ return false }, dragEnd(e) { - fromComp = null + compInOperation = null }, dragOver(e) { e.preventDefault() return true }, dragEnter(e) { - if (!fromComp) return + if (!compInOperation) return if (this.model.isLeaf) return this.isDragEnterNode = true }, @@ -243,16 +243,16 @@ this.isDragEnterNode = false }, drop(e) { - if (!fromComp) return - const oldParent = fromComp.model.parent; - fromComp.model.moveInto(this.model) + if (!compInOperation) return + const oldParent = compInOperation.model.parent; + compInOperation.model.moveInto(this.model) this.isDragEnterNode = false var node = this.getRootNode(); - node.$emit('drop', {node: fromComp.model, oldParent: oldParent}) + node.$emit('drop', {target: this.model, node: compInOperation.model, src: oldParent}) }, dragEnterUp () { - if (!fromComp) return + if (!compInOperation) return this.isDragEnterUp = true }, dragOverUp (e) { @@ -260,20 +260,20 @@ return true }, dragLeaveUp () { - if (!fromComp) return + if (!compInOperation) return this.isDragEnterUp = false }, - dropUp () { - if (!fromComp) return - const oldParent = fromComp.model.parent; - fromComp.model.insertBefore(this.model) + dropBefore () { + if (!compInOperation) return + const oldParent = compInOperation.model.parent; + compInOperation.model.insertBefore(this.model) this.isDragEnterUp = false var node = this.getRootNode(); - node.$emit('drop-up', {node: fromComp.model, oldParent: oldParent}) + node.$emit('drop-before', {target: this.model, node: compInOperation.model, src: oldParent}) }, dragEnterBottom () { - if (!fromComp) return + if (!compInOperation) return this.isDragEnterBottom = true }, dragOverBottom (e) { @@ -281,16 +281,16 @@ return true }, dragLeaveBottom () { - if (!fromComp) return + if (!compInOperation) return this.isDragEnterBottom = false }, - dropBottom () { - if (!fromComp) return - const oldParent = fromComp.model.parent; - fromComp.model.insertAfter(this.model) + dropAfter () { + if (!compInOperation) return + const oldParent = compInOperation.model.parent; + compInOperation.model.insertAfter(this.model) this.isDragEnterBottom = false var node = this.getRootNode(); - node.$emit('drop-bottom', {node: fromComp.model, oldParent: oldParent}) + node.$emit('drop-after', {target: this.model, node: compInOperation.model, src: oldParent}) }, getRootNode() { var node = this.$parent