From b3ea37d36c6822328fe8e46c674cbe88abb9a134 Mon Sep 17 00:00:00 2001 From: Alexander Zodov Date: Mon, 18 Mar 2019 12:05:29 +0200 Subject: [PATCH 01/19] feat(tree-item): Expand timer Added expand timer logic; now on dragOver collapsed node - it will open in 1.5 sec. BREAKING CHANGE: Expand timer --- package.json | 4 +++- src/tree-item.vue | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 42da40b..1a19688 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,9 @@ "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, - "dependencies": {}, + "dependencies": { + "vue-timers": "^1.10.0" + }, "devDependencies": { "babel-core": "^6.0.0", "babel-loader": "^6.0.0", diff --git a/src/tree-item.vue b/src/tree-item.vue index b2ccc9d..32cc38d 100644 --- a/src/tree-item.vue +++ b/src/tree-item.vue @@ -49,8 +49,14 @@ -
+
+ +
diff --git a/package.json b/package.json index 1a19688..0c47c1e 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { + "lodash": "^4.17.11", + "underscore": "^1.9.1", "vue-timers": "^1.10.0" }, "devDependencies": { diff --git a/src/less/base.less b/src/less/base.less index a282104..a109068 100644 --- a/src/less/base.less +++ b/src/less/base.less @@ -31,5 +31,47 @@ .tree-anchor, .tree-icon { position:relative; } .tree-wholerow { width:100%; cursor:pointer; z-index: -1; position:absolute; left:0; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; } } +.drop-0 { background-color: inherit; } +.drop-1 { border-top: 2px solid #C9FDC9; } +.drop-2 { background-color: #C9FDC9 ! important;} +.drop-3 { border-bottom: 2px solid #C9FDC9; } + + +.not-allowed { + border-left-color: red ! important; + border-left-width: 0px ! important; +} +.tree-marker-1 { + top: 0; +} + +.tree-marker-2 { + top: 12px; +} + +.tree-marker-3 { + bottom: -5px; +} + +.tree-marker-1, +.tree-marker-2, +.tree-marker-3 { + color: rgb(9, 190, 9); + left: 0; + position: absolute; + margin: -7px 0 0 0; + padding: 0; + border-right: 0; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + border-left: 7px solid; + // width: 0; + // height: 0; + font-size: 0; + line-height: 0; + display: inline-block; + // border-left-color: #999; + background: transparent; +} diff --git a/src/less/main.less b/src/less/main.less index 7f0ddd8..1dd6309 100644 --- a/src/less/main.less +++ b/src/less/main.less @@ -1,6 +1,37 @@ .tree { text-align: left; + overflow-x: auto; + overflow-y: auto; + + max-width: 100%; + max-height: 600px; +} + + +@media screen and (max-width: 600px) { + + .tree { + text-align: left; + overflow-x: auto; + overflow-y: auto; + max-width: 100%; + max-height: 100px; + } + } + +@media screen and (max-height: 50%) { + + .tree { + text-align: left; + overflow-x: auto; + overflow-y: auto; + max-width: 100%; + max-height: 500px; + } + +} + .tree-@{theme-name} { .tree-node, .tree-icon { background-repeat:no-repeat; background-color:transparent; } @@ -9,7 +40,7 @@ .tree-wholerow { transition:background-color 0.15s, box-shadow 0.15s; } .tree-hovered { background:@hovered-bg-color; border: 0px; box-shadow:none; } .tree-context { background:@hovered-bg-color; border: 0px; box-shadow:none; } - .tree-selected { background:@clicked-bg-color; border: 0px; box-shadow:none; } + .tree-selected { background-color:#C9FDC9; font-weight:bold; } .tree-no-icons .tree-anchor > .tree-themeicon { display:none; } .tree-disabled { background:transparent; color:@disabled-color; @@ -18,7 +49,7 @@ > .tree-icon { opacity:0.8; filter: url("data:image/svg+xml;utf8,#tree-grayscale"); /* Firefox 10+ */ filter: gray; /* IE6-9 */ -webkit-filter: grayscale(100%); /* Chrome 19+ & Safari 6+ */ } } // search - .tree-search { font-style:italic; color:@search-result-color; font-weight:bold; } + .tree-search { color:@search-result-color; } // checkboxes .tree-no-checkboxes .tree-checkbox { display:none !important; } &.tree-checkbox-no-clicked { @@ -29,7 +60,7 @@ } > .tree-wholerow-ul .tree-wholerow-clicked { background:transparent; - &.tree-wholerow-hovered { background:@hovered-bg-color; } + } } // stripes @@ -39,7 +70,7 @@ > .tree-wholerow-ul .tree-selected { background:transparent; box-shadow:none; border-radius:0; } .tree-wholerow { -moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box; } .tree-wholerow-hovered { background:@hovered-bg-color; } - .tree-wholerow-clicked { background:@clicked-bg-color; } + .tree-wholerow-clicked { background:@clicked-bg-color; } } // theme variants @@ -57,4 +88,4 @@ .tree-theme(32px, "data:image/png;base64,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", 32px); &.tree-rtl .tree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); } &.tree-rtl .tree-last { background:transparent; } -} +} \ No newline at end of file diff --git a/src/less/mixins.less b/src/less/mixins.less index 011d2af..365927a 100644 --- a/src/less/mixins.less +++ b/src/less/mixins.less @@ -1,12 +1,20 @@ .tree-theme (@base-height, @image, @image-height) { @correction: (@image-height - @base-height) / 2; - .tree-node { min-height:@base-height; line-height:@base-height; margin-left:@base-height + 6; min-width:@base-height; } - .tree-anchor { line-height:@base-height; height:@base-height; } + .tree-node { + min-height:@base-height; + line-height:@base-height; + margin-left:@base-height + 6; + min-width:@base-height; + position: relative; + } + .tree-anchor { + width: 100%; + } .tree-icon { width:@base-height; height:@base-height; line-height:@base-height; } .tree-icon:empty { width:@base-height; height:@base-height; line-height:@base-height; } &.tree-rtl .tree-node { margin-right:@base-height; } - .tree-wholerow { height:@base-height; } + .tree-wholerow { height: 100%; } .tree-node, .tree-icon { background-image:url("@{image}"); } @@ -18,6 +26,18 @@ .tree-leaf > .tree-ocl { background-position:-(@image-height * 2 + @correction) -@correction; } .tree-themeicon { background-position:-(@image-height * 8 + @correction) -@correction; } + .tree-icon-folder { background-position:-(@image-height * 8 + @correction) -@correction; } + .tree-icon-file { background-position:-(@image-height * 3 + @correction) -(@image-height * 2 + @correction); } + .tree-icon-formselect { background-position:-(@image-height * 4 + @correction) -(@image-height * 2 + @correction); } + .tree-icon-forminput { background-position:-(@image-height * 5 + @correction) -(@image-height * 2 + @correction); } + .tree-icon-formpassword { background-position:-(@image-height * 6 + @correction) -(@image-height * 2 + @correction); } + .tree-icon-formdate { background-position:-(@image-height * 7 + @correction) -(@image-height * 2 + @correction); } + .tree-icon-formtabs { background-position:-(@image-height * 8 + @correction) -(@image-height * 2 + @correction); } + // background-position: -100px -69px; + .tree-icon-prep { width: 24px; height: 24px; line-height: 24px; display: inline-block; margin: 0; + padding: 0; + vertical-align: top; + text-align: center;} > .tree-no-dots { .tree-node, @@ -76,16 +96,66 @@ .tree-node.tree-loading{background: none;} + .tree-node.tree-search-result{background-color: #C9FDC9 ! important; } + > .tree-container-ul .tree-loading > .tree-ocl { background:url("data:image/gif;base64,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") center center no-repeat; } .tree-file { background:url("@{image}") -(@image-height * 3 + @correction) -(@image-height * 2 + @correction) no-repeat; } .tree-folder { background:url("@{image}") -(@image-height * 8 + @correction) -(@correction) no-repeat; } - > .tree-container-ul > .tree-node { margin-left:0; margin-right:0; } + > .tree-container-ul > .tree-node { + margin-left:0; + margin-right:0; + } // ellipsis .tree-ellipsis { overflow: hidden; } // base height + PADDINGS! .tree-ellipsis .tree-anchor { width: calc(100% ~"-" (@base-height + 5px)); text-overflow: ellipsis; overflow: hidden; } .tree-ellipsis.tree-no-icons .tree-anchor { width: calc(100% ~"-" 5px); } -} + + .treeitem-text { + position: relative; + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + width: auto; + box-sizing: border-box; + -moz-box-sizing: border-box; + overflow: auto; + } + .treeitem-actions { + float: right; + visibility: hidden; + display: inline-block; + position: relative; + margin: 0 30px 0 0; + } + .treeitem-actions button { + cursor:pointer; + -webkit-border-radius: 4; + -moz-border-radius: 4; + border-radius: 4px; + color: #ffffff; + font-size: 12px; + // background: #3498db; + padding: 3px 5px 3px 5px; + margin: 0 3px 0 0; + text-decoration: none; + border: solid #3498db 0px; + } + + .treeitem-actions button:hover { + background: #3cb0fd; + text-decoration: none; + } + .treeitem-actions button:active { + outline: none; + border: none; + } + .tree-hovered .treeitem-actions { + visibility: visible; + } +} \ No newline at end of file diff --git a/src/tree-item.vue b/src/tree-item.vue index 02fd5cc..c3a1834 100644 --- a/src/tree-item.vue +++ b/src/tree-item.vue @@ -3,14 +3,15 @@ :class="classes" :draggable="draggable" @dragstart.stop="onItemDragStart($event, _self, _self.model)" - @dragend.stop.prevent="onItemDragEnd($event, _self, _self.model)" - @dragover.stop.prevent="isDragEnter = true" - @dragenter.stop.prevent="isDragEnter = true" - @dragleave.stop.prevent="isDragEnter = false" + @dragend.stop.prevent="onThisItemDragEnd($event, _self, _self.model)" + @dragover.stop.prevent="onItemDragOver($event, _self, _self.model)" + @dragenter.stop.prevent="onDragState(true)" + @dragleave.stop.prevent="onDragState(false)" @drop.stop.prevent="handleItemDrop($event, _self, _self.model)">
 
+
-
+
@@ -53,6 +54,12 @@ +
diff --git a/package.json b/package.json index 0c47c1e..1a19688 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,6 @@ "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { - "lodash": "^4.17.11", - "underscore": "^1.9.1", "vue-timers": "^1.10.0" }, "devDependencies": { diff --git a/src/less/main.less b/src/less/main.less index 1dd6309..43984bb 100644 --- a/src/less/main.less +++ b/src/less/main.less @@ -8,30 +8,6 @@ } -@media screen and (max-width: 600px) { - - .tree { - text-align: left; - overflow-x: auto; - overflow-y: auto; - max-width: 100%; - max-height: 100px; - } - -} - -@media screen and (max-height: 50%) { - - .tree { - text-align: left; - overflow-x: auto; - overflow-y: auto; - max-width: 100%; - max-height: 500px; - } - -} - .tree-@{theme-name} { .tree-node, .tree-icon { background-repeat:no-repeat; background-color:transparent; } diff --git a/src/tree.vue b/src/tree.vue index f29150d..3f591c8 100644 --- a/src/tree.vue +++ b/src/tree.vue @@ -71,10 +71,7 @@ expandTimer:{type: Boolean, default: false}, expandTimerTimeOut:{type: Number, default: 1500}, - - orderFieldName: {type: String, default: ''}, - - executeSiblingMovement:{type: Boolean, default:false} + executeSiblingMovement:{type: Boolean, default:false}, }, data() { return { @@ -86,8 +83,6 @@ classes() { return [ {'tree': true}, - 'mt-3', - 'mb-3', {'tree-default': !this.size}, {[`tree-default-${this.size}`]: !!this.size}, {'tree-checkbox-selection': !!this.showCheckbox}, @@ -283,114 +278,18 @@ if (position === '2' && oriItem.canDrop === false) return false if (this.draggedItem.parentItem === oriItem.children || this.draggedItem.item === oriItem || - // (oriItem.children && oriItem.children.indexOf(this.draggedItem.item) !== -1) || (this.draggedItem.item.children && this.draggedItem.item.children.indexOf(oriItem) !== -1)) { return false } return true }, - replaceDataItem (item, replacement) { - var id = item[this.childrenFieldName] - var index = _.indexOf(this.data, _.find(this.data, { [this.childrenFieldName]: id })) - if (!Object.isFrozen(this.data)) { - this.loadDataOnWatch = false - if (index !== -1) { - this.data.splice(index, 1, _.merge({}, this.data[index], replacement)) - } else if (item.item) { - delete item.item.addToDataBefore - delete item.item.addToDataAfter - var newItem = _.merge({}, item.item, replacement) - this.data.push(newItem) - } - } - }, - getOrderNextVal (startFrom) { - if (startFrom) { - let fromStr = startFrom.split('') - let aChar = fromStr[0] ? fromStr[0].charCodeAt(0) : 34 - let bChar = fromStr[1] ? fromStr[1].charCodeAt(0) : 34 - if (aChar > this.orderChars[0]) this.orderChars[0] = aChar - if (bChar > this.orderChars[1]) this.orderChars[1] = bChar - } - this.orderChars[0] = this.orderChars[0] + 1 - if (this.orderChars[0] === 126) { - this.orderChars[1] = this.orderChars[1] + 1 - this.orderChars[0] = 34 - } - return String.fromCharCode(this.orderChars[0]) + String.fromCharCode(this.orderChars[1]) - }, - getOrderMidVal (aWord, bWord) { - console.log(aWord, bWord); - if (aWord === null || aWord === '') aWord = '!!' - let aChars = aWord.split('') - let bChars = bWord.split('') - var cWord = '' - let charCount = aChars.length > bChars.length ? aChars.length : bChars.length - for (var i = 0; i < charCount + 1; i++) { - let aChar = aChars[i] ? aChars[i].charCodeAt(0) : 33 - let bChar = bChars[i] ? bChars[i].charCodeAt(0) : 126 - let cChar = Math.floor((aChar + bChar) / 2) - cWord += String.fromCharCode(cChar) - if (cChar !== aChar && cChar !== bChar) { - i = charCount + 1 - } - } - return cWord - }, - getOrder (oriNode, oriItem, position) { - var newOrder = 'AA' - if (this.orderFieldName !== '') { - if (position === '2') { - if (oriItem.children.length > 0) { - var lastItem = oriItem.children[oriItem.children.length - 1] - if (lastItem[this.orderFieldName]) { - newOrder = this.getOrderNextVal(lastItem[this.orderFieldName]) - } - } else { - newOrder = this.getOrderNextVal() - } - } else if (oriNode && oriNode.parentItem) { - // Find position of destination item in the parent group - var oriIndex = oriNode.parentItem.indexOf(oriItem) - if (position === '1') { - // Figure out position - if (oriIndex === 0) { - // Droped on the top of the list. Get order based on existing first item - newOrder = this.getOrderMidVal(null, oriItem[this.orderFieldName]) - } else { - // Droped on item between first and last. Use above and below item order to calculate new order - var itemAbove2 = oriNode.parentItem[oriIndex - 1] - var itemBelow2 = oriNode.parentItem[oriIndex] - newOrder = this.getOrderMidVal(itemAbove2[this.orderFieldName], itemBelow2[this.orderFieldName]) - } - } else if (position === '3') { - // Figure out position - if (oriIndex === oriNode.parentItem.length - 1) { - // Droped at the end of the list. Get order based on existing last item - var endItem = oriNode.parentItem[oriNode.parentItem.length - 1] - if (endItem[this.orderFieldName]) { - newOrder = this.getOrderNextVal(endItem[this.orderFieldName]) - } - } else { - // Droped on item between first and last. Use above and below item order to calculate new order - var itemAbove = oriNode.parentItem[oriIndex] - var itemBelow = oriNode.parentItem[oriIndex + 1] - newOrder = this.getOrderMidVal(itemAbove[this.orderFieldName], itemBelow[this.orderFieldName]) - } - } - } else if (oriItem) { - newOrder = this.getOrderNextVal(null, oriItem[this.orderFieldName]) - } - } - return newOrder - }, onItemDrop(e, oriNode, oriItem, position) { if (!this.draggable) return false if (this.draggedItem && oriItem[this.childrenFieldName] !== this.draggedItem.item[this.childrenFieldName]) { - var newOrder = this.getOrder(oriNode, oriItem, position) + var newParent = '' if (position === '2') { /** Item is droped on the other item (folder) ****/ @@ -405,7 +304,7 @@ }) - this.$emit('item-drop', oriNode, oriItem, this.draggedItem.item, changeObj,e) + this.$emit('item-drop', oriNode, oriItem, this.draggedItem.item, e) } @@ -434,25 +333,9 @@ } - // If order is changed, update item - var changeObj = {} - if (this.orderFieldName !== '' && newOrder !== '') { - - if (this.draggedItem.item[this.childrenFieldName]) this.mapCollapsed[this.draggedItem.item[this.childrenFieldName]][this.orderFieldName] = newOrder - changeObj[this.orderFieldName] = newOrder - } - if (newParent !== '') { - - changeObj[this.parentFieldName] = newParent - } - - - this.$emit('item-drop-sibling'+anchor_modificator, oriNode, oriItem, this.draggedItem.item, changeObj,oriIndex,e) + this.$emit('item-drop-sibling'+anchor_modificator, oriNode, oriItem, this.draggedItem.item, oriIndex,e) - _.assign(this.draggedItem.item, changeObj) - this.replaceDataItem(this.draggedItem.item, changeObj) - this.draggedItem.item.obj = _.merge({}, this.draggedItem.item.obj, changeObj) } } From f0902762f1503b8e81688c0124096bdf6438fb55 Mon Sep 17 00:00:00 2001 From: Alexander Zodov Date: Tue, 19 Mar 2019 11:58:20 +0200 Subject: [PATCH 08/19] style(main.less): Remove user-specific attributes from .tree class Leave in .tree class only text-align attribute; --- src/less/main.less | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/less/main.less b/src/less/main.less index 43984bb..aa83c00 100644 --- a/src/less/main.less +++ b/src/less/main.less @@ -1,10 +1,6 @@ .tree { text-align: left; - overflow-x: auto; - overflow-y: auto; - max-width: 100%; - max-height: 600px; } From 76ad262701db3cc85e03edb446184f6f1a30e61d Mon Sep 17 00:00:00 2001 From: Alexander Zodov Date: Tue, 19 Mar 2019 12:35:08 +0200 Subject: [PATCH 09/19] feat(tree.vue): multiTree feature Add multiTree feature - drag-and-drop between two(and more) instances of tree component; Control by boolean prop multiTree; Update README.md; BREAKING CHANGE: multiTree --- App.vue | 2 +- README.md | 5 ++++- src/tree.vue | 39 +++++++++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/App.vue b/App.vue index 4370385..2dc0e19 100644 --- a/App.vue +++ b/App.vue @@ -18,7 +18,7 @@ expand-timer :expand-timer-time-out="5000" execute-sibling-movement - + multi-tree @item-click="itemClick" @item-drag-start="itemDragStart" @item-drag-end="itemDragEnd" diff --git a/README.md b/README.md index a347994..e764199 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ A tree plugin for vue2 ## Usage ```html - + new Vue({ data: { @@ -150,6 +150,7 @@ A tree plugin for vue2 | expand-timer | Boolean | false | prop to control expanding of nodes during dragOver | | expand-timer-time-out | Number | 1500 | prop to control duration of expanding timer | | execute-siblings-movement | Boolean | false | prop to control siblings movement: if true -> move node and emit event, false -> just emit event, and let user decide what to do with it | +| multi-tree | Boolean | false | prop to define in which mode tree is working - usual or multiTree | ## Methods in node.model @@ -186,6 +187,8 @@ A tree plugin for vue2 **@item-drop-sibling-right**: move dragged node to right of target +**@item-drop-multi-tree**: dropped on node in multiTree mode + ## Data Item Optional Properties | Name | Type | Default | Describe | diff --git a/src/tree.vue b/src/tree.vue index 3f591c8..6914796 100644 --- a/src/tree.vue +++ b/src/tree.vue @@ -72,6 +72,7 @@ expandTimer:{type: Boolean, default: false}, expandTimerTimeOut:{type: Number, default: 1500}, executeSiblingMovement:{type: Boolean, default:false}, + multiTree: {type: Boolean, default: false}, }, data() { return { @@ -253,18 +254,30 @@ } }, onItemDragStart(e, oriNode, oriItem) { + if (!this.draggable || oriItem.dragDisabled) return false - e.dataTransfer.effectAllowed = "move" - e.dataTransfer.setData('text', null) - this.draggedElm = e.target - this.draggedItem = { - item: oriItem, - parentItem: oriNode.parentItem, - index: oriNode.parentItem.findIndex(t => t.id === oriItem.id) + if(this.multiTree){ + + this.draggedItem = { + item: oriItem, + parentItem: oriNode.parentItem, + index: oriNode.parentItem.findIndex(t => t.id === oriItem.id) + } + }else{ + + e.dataTransfer.effectAllowed = "move" + e.dataTransfer.setData('text', null) + this.draggedElm = e.target + this.draggedItem = { + item: oriItem, + parentItem: oriNode.parentItem, + index: oriNode.parentItem.findIndex(t => t.id === oriItem.id) + } + } + this.$emit("item-drag-start", oriNode, oriItem,this.draggedItem, e) - this.$emit("item-drag-start", oriNode, oriItem, e) }, onItemDragEnd(e, oriNode, oriItem) { this.draggedItem = undefined @@ -287,8 +300,12 @@ onItemDrop(e, oriNode, oriItem, position) { if (!this.draggable) return false - if (this.draggedItem && oriItem[this.childrenFieldName] !== this.draggedItem.item[this.childrenFieldName]) { - + if(this.multiTree){ + //for multiTree case - emit drop node, item, and event, emitting even on left/right drop position + this.$emit('item-drop-multi-tree', oriNode, oriItem, e); + } + else{ + if (this.draggedItem && oriItem[this.childrenFieldName] !== this.draggedItem.item[this.childrenFieldName]) { var newParent = '' if (position === '2') { @@ -340,6 +357,8 @@ } + } + } }, created() { From f151ded3ef37024e55f4376c322ae6a10bb31d33 Mon Sep 17 00:00:00 2001 From: Alexander Zodov Date: Tue, 19 Mar 2019 13:07:08 +0200 Subject: [PATCH 10/19] perf(App.vue): Checkbox for multiTree Add checkBox to enable/disable multiTree logic; BREAKING CHANGE: Checkbox for multiTree --- App.vue | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/App.vue b/App.vue index 2dc0e19..695968a 100644 --- a/App.vue +++ b/App.vue @@ -18,7 +18,7 @@ expand-timer :expand-timer-time-out="5000" execute-sibling-movement - multi-tree + :multi-tree="multiTree" @item-click="itemClick" @item-drag-start="itemDragStart" @item-drag-end="itemDragEnd" @@ -30,6 +30,10 @@ drag me to add new child ! + Enable multiTree
+