Skip to content

Commit

Permalink
rewrite tree
Browse files Browse the repository at this point in the history
Signed-off-by: zhanghua <[email protected]>
  • Loading branch information
zdy1988 committed Aug 27, 2017
1 parent 55a0b75 commit a102a0f
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 412 deletions.
35 changes: 22 additions & 13 deletions App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div>
<div style="width:840px; margin: 0 auto;">
<div style="width:49%; display:inline-block; vertical-align: top;">
<tree :data="data" show-checkbox multiple allow-batch whole-row @item-click="itemClick"></tree>
<tree :data="data" show-checkbox multiple allow-batch whole-row draggable @item-click="itemClick" ref="tree"></tree>
</div>
<div style="width:50%; display:inline-block;">
<textarea style="height:300px; width:100%;">
Expand All @@ -33,6 +33,7 @@

<script>
import Tree from './src/tree.vue'
export default {
name: 'app',
data () {
Expand All @@ -41,7 +42,6 @@
data: [
{
"text": "Same but with checkboxes",
"opened": true,
"children": [
{
"text": "initially selected",
Expand Down Expand Up @@ -110,22 +110,31 @@
}
],
asyncData: [],
loadData: (parent) => {
var tag = !!parent && !!parent.id ? parent.id : ''
return [
{
"text": "New Item 1..." + tag
},
{
"text": "New Item 2..." + tag
loadData: (oriNode, resolve) => {
var id = !!oriNode && !!oriNode.model ? oriNode.model.id : 0
setTimeout(() => {
let data = []
if (id > 20) {
data = []
}
else {
data = [
{
"text": "New Item 1..." + id
},
{
"text": "New Item 2..." + id
}
]
}
]
resolve(data)
}, 500)
}
}
},
methods: {
itemClick (item) {
console.log(item.text + ' clicked !')
itemClick (node) {
console.log(node.model.text + ' clicked !')
}
},
components: {
Expand Down
12 changes: 4 additions & 8 deletions src/less/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@
.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-clicked { background:@clicked-bg-color; border: 0px; box-shadow:none; }
.tree-selected { background:@clicked-bg-color; border: 0px; box-shadow:none; }
.tree-no-icons .tree-anchor > .tree-themeicon { display:none; }
.tree-disabled {
background:transparent; color:@disabled-color;
&.tree-hovered { background:transparent; box-shadow:none; }
&.tree-clicked { background:@disabled-bg-color; }
&.tree-selected { background:@disabled-bg-color; }
> .tree-icon { opacity:0.8; filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'tree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#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; }
// checkboxes
.tree-no-checkboxes .tree-checkbox { display:none !important; }
&.tree-checkbox-no-clicked {
.tree-clicked {
.tree-selected {
background:transparent;
box-shadow:none;
&.tree-hovered { background:@hovered-bg-color; }
Expand All @@ -36,7 +36,7 @@
> .tree-striped { min-width:100%; display:inline-block; background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==") left top repeat; }
// wholerow
> .tree-wholerow-ul .tree-hovered,
> .tree-wholerow-ul .tree-clicked { background:transparent; box-shadow:none; border-radius:0; }
> .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; }
Expand All @@ -58,7 +58,3 @@
&.tree-rtl .tree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); }
&.tree-rtl .tree-last { background:transparent; }
}

.tree-@{theme-name}-responsive when (@responsive = true) {
@import "responsive.less";
}
4 changes: 2 additions & 2 deletions src/less/mixins.less
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
&.tree-hovered {
background:transparent;
}
&.tree-clicked {
&.tree-selected {
background:#efefef;
}
}
Expand All @@ -41,7 +41,7 @@
&:hover { background-position:-(@image-height * 5 + @correction) -(@image-height * 1 + @correction); }
}

&.tree-checkbox-selection .tree-clicked, .tree-checked {
&.tree-checkbox-selection .tree-selected, .tree-checked {
> .tree-checkbox {
background-position:-(@image-height * 7 + @correction) -@correction;
&:hover { background-position:-(@image-height * 7 + @correction) -(@image-height * 1 + @correction); }
Expand Down
67 changes: 0 additions & 67 deletions src/less/responsive.less

This file was deleted.

184 changes: 184 additions & 0 deletions src/tree-item.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<template>
<li role="treeitem"
:class="classes"
:draggable="draggable"
@dragstart.stop="onItemDragStart($event, _self, _self.model)"
@dragend.stop.prevent="onItemDragEnd($event, _self, _self.model)"
@dragover.stop.prevent="() => false"
@dragenter.stop.prevent="isDragEnter = true"
@dragleave.stop.prevent="isDragEnter = false"
@drop.stop.prevent="handleItemDrop($event, _self, _self.model)">
<div role="presentation" :class="wholeRowClasses" v-if="isWholeRow">&nbsp;</div>
<i class="tree-icon tree-ocl" role="presentation" @click="handleItemToggle"></i>
<div :class="anchorClasses" @click="handleItemClick" @mouseover="isHover=true" @mouseout="isHover=false">
<i class="tree-icon tree-checkbox" role="presentation" v-if="showCheckbox && !model.loading"></i>
<i :class="themeIconClasses" role="presentation" v-if="!model.loading"></i>
{{model.text}}
</div>
<ul role="group" ref="group" class="tree-children" v-if="isFolder">
<tree-item v-for="(child, index) in model.children"
:key="index"
:model="child"
:whole-row="wholeRow"
:show-checkbox="showCheckbox"
:height= "height"
:parent-item="model.children"
:draggable="draggable"
:on-item-click="onItemClick"
:on-item-toggle="onItemToggle"
:on-item-drag-start="onItemDragStart"
:on-item-drag-end="onItemDragEnd"
:on-item-drop="onItemDrop">
</tree-item>
</ul>
</li>
</template>
<script>
export default {
name: 'TreeItem',
props: {
model: {type: Object, required: true},
multiple: {type: Boolean, default: false},
wholeRow: {type: Boolean, default: false},
showCheckbox: {type: Boolean, default: false},
height: {type: Number, default: 24},
parentItem: {type: Array},
draggable: {type: Boolean, default: false},
onItemClick: {
type: Function, default: () => false
},
onItemToggle: {
type: Function, default: () => false
},
onItemDragStart: {
type: Function, default: () => false
},
onItemDragEnd: {
type: Function, default: () => false
},
onItemDrop: {
type: Function, default: () => false
},
klass: String
},
data () {
return {
isHover: false,
isDragEnter: false,
child: this.model.children
}
},
watch: {
isDragEnter (newValue) {
if (newValue) {
this.$el.style.backgroundColor = "#C9FDC9"
} else {
this.$el.style.backgroundColor = "inherit"
}
}
},
computed: {
isFolder () {
return this.model.children && this.model.children.length
},
classes () {
return [
{'tree-node': true},
{'tree-open': this.model.opened},
{'tree-closed': !this.model.opened},
{'tree-leaf': !this.isFolder},
{'tree-loading': !!this.model.loading},
{'tree-drag-enter': this.isDragEnter},
{[this.klass]: !!this.klass}
]
},
anchorClasses () {
return [
{'tree-anchor': true},
{'tree-disabled': this.model.disabled},
{'tree-selected': this.model.selected},
{'tree-hovered': this.isHover}
]
},
wholeRowClasses () {
return [
{'tree-wholerow': true},
{'tree-wholerow-clicked': this.model.selected},
{'tree-wholerow-hovered': this.isHover}
]
},
themeIconClasses () {
return [
{'tree-icon': true},
{'tree-themeicon': true},
{[this.model.icon]: !!this.model.icon},
{'tree-themeicon-custom': !!this.model.icon}
]
},
isWholeRow () {
if (this.wholeRow) {
if (this.$parent.model === undefined) {
return true
} else if (this.$parent.model.opened === true) {
return true
} else {
return false
}
}
}
},
methods: {
handleRecursionNodeParents(node, func) {
if (node.$parent) {
func(node.$parent)
this.handleRecursionNodeParents(node.$parent, func)
}
},
handleItemToggle () {
if (this.isFolder) {
this.model.opened = !this.model.opened
this.onItemToggle(this, this.model)
this.handleSetGroupMaxHeight()
}
},
handleGroupMaxHeight () {
let length = 0
let childHeight = 0
if (this.model.opened) {
length = this.$children.length
for (let children of this.$children) {
childHeight += children.handleGroupMaxHeight()
}
}
return length * this.height + childHeight
},
handleSetGroupMaxHeight () {
if (this.$refs.group) {
this.$refs.group.style.maxHeight = this.handleGroupMaxHeight() + 'px'
}
var self = this
this.$nextTick(() => {
this.handleRecursionNodeParents(self, node => {
if (node.$refs.group) {
node.$refs.group.style.maxHeight = node.handleGroupMaxHeight() + 'px'
}
})
})
},
handleItemClick () {
if (this.model.disabled) return
this.model.selected = !this.model.selected
this.onItemClick(this, this.model)
},
handleItemDrop (e, oriNode, oriItem) {
this.$el.style.backgroundColor = "inherit"
this.onItemDrop(e, oriNode, oriItem)
}
},
mounted () {
this.handleSetGroupMaxHeight()
}
}
</script>
Loading

0 comments on commit a102a0f

Please sign in to comment.