UNPKG

sl-vue-tree

Version:

draggable tree vue component

245 lines (196 loc) 6.08 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>sl-vue-tree</title> <link rel="stylesheet" href="../dist/sl-vue-tree-dark.css"> <link href="https://use.fontawesome.com/releases/v5.0.8/css/all.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> <script src="../dist/sl-vue-tree.js"></script> </head> <body> <div id="app" @click="contextMenuIsVisible = false"> <h2> Sl-vue-tree - custom dark theme and events handlers</h2> <a href="./dark-theme.html" target="_blank">Source code</a> <br><br> <div class="last-event row"> Last event: {{ lastEvent }} </div> <div class="row"> <div class="tree-container"> <sl-vue-tree v-model="nodes" ref="slVueTree" :allow-multiselect="true" @select="nodeSelected" @drop="nodeDropped" @toggle="nodeToggled" @nodecontextmenu="showContextMenu" > <template slot="title" slot-scope="{ node }"> <span class="item-icon"> <i class="fa fa-file" v-if="node.isLeaf"></i> <i class="fa fa-folder" v-if="!node.isLeaf"></i> </span> {{ node.title }} </template> <template slot="toggle" slot-scope="{ node }"> <span v-if="!node.isLeaf"> <i v-if="node.isExpanded" class="fa fa-chevron-down"></i> <i v-if="!node.isExpanded" class="fa fa-chevron-right"></i> </span> </template> <template slot="sidebar" slot-scope="{ node }"> <span class="visible-icon" @click="event => toggleVisibility(event, node)"> <i v-if="!node.data || node.data.visible !== false" class="fa fa-eye"></i> <i v-if="node.data && node.data.visible === false" class="fa fa-eye-slash"></i> </span> </template> <template slot="draginfo"> {{selectedNodesTitle}} </template> </sl-vue-tree> </div> <div class="json-preview"> <pre>{{ JSON.stringify(nodes, null, 4)}}</pre> </div> <div class="contextmenu" ref="contextmenu" v-show="contextMenuIsVisible"> <div @click="removeNode">Remove</div> </div> </div> </div> <script> var nodes = [ {title: 'Item1', isLeaf: true}, {title: 'Item2', isLeaf: true, data: { visible: false }}, {title: 'Folder1'}, { title: 'Folder2', isExpanded: true, children: [ {title: 'Item3', isLeaf: true}, {title: 'Item4', isLeaf: true}, { title: 'Folder3', children: [ {title: 'Item5', isLeaf: true} ] } ] }, {title: 'Folder5', isExpanded: false}, {title: 'Item6', isLeaf: true}, {title: 'Item7', isLeaf: true, data: { visible: false }}, { title: 'Folder6', children: [ { title: 'Folder7', children: [ {title: 'Item8', isLeaf: true}, {title: 'Item9', isLeaf: true} ] } ] } ]; new Vue({ el: '#app', components: { SlVueTree }, data: function () { return { nodes: nodes, contextMenuIsVisible: false, lastEvent: 'No last event', selectedNodesTitle: '', } }, mounted() { // expose instance to the global namespace window.slVueTree = this.$refs.slVueTree; }, methods: { toggleVisibility: function (event, node) { const slVueTree = this.$refs.slVueTree; event.stopPropagation(); const visible = !node.data || node.data.visible !== false; slVueTree.updateNode(node.path, {data: { visible: !visible}}); this.lastEvent = `Node ${node.title} is ${ visible ? 'visible' : 'invisible'} now`; }, nodeSelected(nodes, event) { this.selectedNodesTitle = nodes.map(node => node.title).join(', '); this.lastEvent = `Select nodes: ${this.selectedNodesTitle}`; }, nodeToggled(node, event) { this.lastEvent = `Node ${node.title} is ${ node.isExpanded ? 'expanded' : 'collapsed'}`; }, nodeDropped(nodes, position, event) { this.lastEvent = `Nodes: ${nodes.map(node => node.title).join(', ')} are dropped ${position.placement} ${position.node.title}`; }, showContextMenu(node, event) { event.preventDefault(); this.contextMenuIsVisible = true; const $contextMenu = this.$refs.contextmenu; $contextMenu.style.left = event.clientX + 'px'; $contextMenu.style.top = event.clientY + 'px'; }, removeNode() { this.contextMenuIsVisible = false; const $slVueTree = this.$refs.slVueTree; const paths = $slVueTree.getSelected().map(node => node.path); $slVueTree.remove(paths); } } }) </script> <style> body { background: #050d12; font-family: Arial; color: rgba(255, 255, 255, 0.5); } a { color: #bbb; } .row { display: flex; margin-bottom: 10px; } .contextmenu { position: absolute; background-color: white; color: black; border-radius: 2px; cursor: pointer; } .contextmenu > div { padding: 10px; } .contextmenu > div:hover { background-color: rgba(100, 100, 255, 0.5); } .last-event { color: white; background-color: rgba(100, 100, 255, 0.5); padding: 10px; border-radius: 2px; } .tree-container { flex-grow: 1; } .sl-vue-tree.sl-vue-tree-root { flex-grow: 1; overflow-x: hidden; overflow-y: auto; height: 300px; } .json-preview { flex-grow: 1; margin-left: 10px; background-color: #13242d; border: 1px solid black; padding: 10px; } .item-icon { display: inline-block; text-align: left; width: 20px; } </style> </body> </html>