UNPKG

liquor-tree

Version:
1,918 lines (1,512 loc) 80.1 kB
/*! * LiquorTree v0.2.70 * (c) 2019 amsik * Released under the MIT License. */ var NodeContent = { name: 'node-content', props: ['node'], render: function render (h) { var this$1 = this; var node = this.node; var vm = this.node.tree.vm; if (node.isEditing) { var nodeText = node.text; this.$nextTick(function (_) { this$1.$refs.editCtrl.focus(); }); return h('input', { domProps: { value: node.text, type: 'text' }, class: 'tree-input', on: { input: function input (e) { nodeText = e.target.value; }, blur: function blur () { node.stopEditing(nodeText); }, keyup: function keyup (e) { if (e.keyCode === 13) { node.stopEditing(nodeText); } }, mouseup: function mouseup (e) { e.stopPropagation(); } }, ref: 'editCtrl' }) } if (vm.$scopedSlots.default) { return vm.$scopedSlots.default({ node: this.node }) } return h('span', { domProps: { innerHTML: node.text } }) } }; function normalizeComponent(compiledTemplate, injectStyle, defaultExport, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, isShadowMode, createInjector, createInjectorSSR, createInjectorShadow) { if (typeof isShadowMode === 'function') { createInjectorSSR = createInjector; createInjector = isShadowMode; isShadowMode = false; } // Vue.extend constructor export interop var options = typeof defaultExport === 'function' ? defaultExport.options : defaultExport; // render functions if (compiledTemplate && compiledTemplate.render) { options.render = compiledTemplate.render; options.staticRenderFns = compiledTemplate.staticRenderFns; options._compiled = true; // functional template if (isFunctionalTemplate) { options.functional = true; } } // scopedId if (scopeId) { options._scopeId = scopeId; } var hook; if (moduleIdentifier) { // server build hook = function (context) { // 2.3 injection context = context || // cached call (this.$vnode && this.$vnode.ssrContext) || // stateful (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional // 2.2 with runInNewContext: true if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__; } // inject component styles if (injectStyle) { injectStyle.call(this, createInjectorSSR(context)); } // register component module identifier for async chunk inference if (context && context._registeredComponents) { context._registeredComponents.add(moduleIdentifier); } }; // used by ssr in case component is cached and beforeCreate // never gets called options._ssrRegister = hook; } else if (injectStyle) { hook = isShadowMode ? function () { injectStyle.call(this, createInjectorShadow(this.$root.$options.shadowRoot)); } : function (context) { injectStyle.call(this, createInjector(context)); }; } if (hook) { if (options.functional) { // register for functional component in vue file var originalRender = options.render; options.render = function renderWithStyleInjection(h, context) { hook.call(context); return originalRender(h, context); }; } else { // inject component registration as beforeCreate hook var existing = options.beforeCreate; options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; } } return defaultExport; } /* script */ var __vue_script__ = NodeContent; // For security concerns, we use only base name in production mode. See https://github.com/vuejs/rollup-plugin-vue/issues/258 NodeContent.__file = "NodeContent.vue"; /* template */ /* style */ var __vue_inject_styles__ = undefined; /* scoped */ var __vue_scope_id__ = undefined; /* module identifier */ var __vue_module_identifier__ = undefined; /* functional template */ var __vue_is_functional_template__ = undefined; /* style inject */ /* style inject SSR */ var NodeContent$1 = normalizeComponent( {}, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, undefined, undefined ); // var TreeNode = { name: 'Node', inject: ['tree'], props: ['node', 'options'], components: { NodeContent: NodeContent$1 }, watch: { node: function node() { this.node.vm = this; } }, data: function data() { this.node.vm = this; return { loading: false } }, computed: { padding: function padding() { return this.node.depth * (this.options.paddingLeft ? this.options.paddingLeft : this.options.nodeIndent) + 'px' }, nodeClass: function nodeClass() { var state = this.node.states; var hasChildren = this.hasChildren(); var classes = { 'has-child': hasChildren, 'expanded': hasChildren && state.expanded, 'selected': state.selected, 'disabled': state.disabled, 'matched': state.matched, 'dragging': state.dragging, 'loading': this.loading, 'draggable': state.draggable }; if (this.options.checkbox) { classes['checked'] = state.checked; classes['indeterminate'] = state.indeterminate; } return classes }, visibleChildren: function visibleChildren() { return this.node.children.filter(function(child) { return child && child.visible() }) } }, methods: { onNodeFocus: function onNodeFocus() { this.tree.activeElement = this.node; }, focus: function focus() { this.$refs.anchor.focus(); this.node.select(); }, check: function check() { if (this.node.checked()) { this.node.uncheck(); } else { this.node.check(); } }, select: function select(ref) { if ( ref === void 0 ) ref = evnt; var ctrlKey = ref.ctrlKey; var opts = this.options; var tree = this.tree; var node = this.node; tree.$emit('node:clicked', node); if (opts.editing && node.isEditing) { return } if (opts.editing && node.editable()) { return this.startEditing() } if (opts.checkbox && opts.checkOnSelect) { if (!opts.parentSelect && this.hasChildren()) { return this.toggleExpand() } return this.check(ctrlKey) } // 'parentSelect' behaviour. // For nodes which has a children list we have to expand/collapse if (!opts.parentSelect && this.hasChildren()) { this.toggleExpand(); } if (opts.multiple) { if (!node.selected()) { node.select(ctrlKey); } else { if (ctrlKey) { node.unselect(); } else { if (this.tree.selectedNodes.length != 1) { tree.unselectAll(); node.select(); } } } } else { if (node.selected() && ctrlKey) { node.unselect(); } else { node.select(); } } }, toggleExpand: function toggleExpand() { if (this.hasChildren()) { this.node.toggleExpand(); } }, hasChildren: function hasChildren() { return this.node.hasChildren() }, startEditing: function startEditing() { if (this.tree._editingNode) { this.tree._editingNode.stopEditing(); } this.node.startEditing(); }, stopEditing: function stopEditing() { this.node.stopEditing(); }, handleMouseDown: function handleMouseDown(event) { if (!this.options.dnd) { return } this.tree.vm.startDragging(this.node, event); } } }; var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); function createInjector(context) { return function (id, style) { return addStyle(id, style); }; } var HEAD = document.head || document.getElementsByTagName('head')[0]; var styles = {}; function addStyle(id, css) { var group = isOldIE ? css.media || 'default' : id; var style = styles[group] || (styles[group] = { ids: new Set(), styles: [] }); if (!style.ids.has(id)) { style.ids.add(id); var code = css.source; if (css.map) { // https://developer.chrome.com/devtools/docs/javascript-debugging // this makes source maps inside style tags work properly in Chrome code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; } if (!style.element) { style.element = document.createElement('style'); style.element.type = 'text/css'; if (css.media) { style.element.setAttribute('media', css.media); } HEAD.appendChild(style.element); } if ('styleSheet' in style.element) { style.styles.push(code); style.element.styleSheet.cssText = style.styles .filter(Boolean) .join('\n'); } else { var index = style.ids.size - 1; var textNode = document.createTextNode(code); var nodes = style.element.childNodes; if (nodes[index]) { style.element.removeChild(nodes[index]); } if (nodes.length) { style.element.insertBefore(textNode, nodes[index]); } else { style.element.appendChild(textNode); } } } } /* script */ var __vue_script__$1 = TreeNode; // For security concerns, we use only base name in production mode. See https://github.com/vuejs/rollup-plugin-vue/issues/258 TreeNode.__file = "TreeNode.vue"; /* template */ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{staticClass:"tree-node",class:_vm.nodeClass,attrs:{"data-id":_vm.node.id},on:{"mousedown":function($event){$event.stopPropagation();return _vm.handleMouseDown($event)}}},[_c('div',{staticClass:"tree-content",style:([_vm.options.direction == 'ltr' ? {'padding-left': _vm.padding} : {'padding-right': _vm.padding}]),on:{"click":function($event){$event.stopPropagation();return _vm.select($event)}}},[_c('i',{staticClass:"tree-arrow",class:[{'expanded': _vm.node.states.expanded, 'has-child': _vm.node.children.length || _vm.node.isBatch}, _vm.options.direction],on:{"click":function($event){$event.stopPropagation();return _vm.toggleExpand($event)}}}),_vm._v(" "),(_vm.options.checkbox)?_c('i',{staticClass:"tree-checkbox",class:{'checked': _vm.node.states.checked, 'indeterminate': _vm.node.states.indeterminate},on:{"click":function($event){$event.stopPropagation();return _vm.check($event)}}}):_vm._e(),_vm._v(" "),_c('span',{ref:"anchor",staticClass:"tree-anchor",attrs:{"tabindex":"-1"},on:{"focus":_vm.onNodeFocus,"dblclick":function($event){return _vm.tree.$emit('node:dblclick', _vm.node)}}},[_c('node-content',{attrs:{"node":_vm.node}})],1)]),_vm._v(" "),_c('transition',{attrs:{"name":"l-fade"}},[(_vm.hasChildren() && _vm.node.states.expanded)?_c('ul',{staticClass:"tree-children"},_vm._l((_vm.visibleChildren),function(child){return _c('node',{key:child.id,attrs:{"node":child,"options":_vm.options}})}),1):_vm._e()])],1)}; var __vue_staticRenderFns__ = []; /* style */ var __vue_inject_styles__$1 = function (inject) { if (!inject) { return } inject("data-v-20094490_0", { source: ".tree-node{white-space:nowrap;display:flex;flex-direction:column;position:relative;box-sizing:border-box}.tree-content{display:flex;align-items:center;padding:3px;cursor:pointer;width:100%;box-sizing:border-box}.tree-node:not(.selected)>.tree-content:hover{background:#f6f8fb}.tree-node.selected>.tree-content{background-color:#e7eef7}.tree-node.disabled>.tree-content:hover{background:inherit}.tree-arrow{flex-shrink:0;height:30px;cursor:pointer;margin-left:30px;width:0}.tree-arrow.has-child{margin-left:0;width:30px;position:relative}.tree-arrow.has-child:after{border:1.5px solid #494646;position:absolute;border-left:0;border-top:0;left:9px;top:50%;height:9px;width:9px;transform:rotate(-45deg) translateY(-50%) translateX(0);transition:transform .25s;transform-origin:center}.tree-arrow.has-child.rtl:after{border:1.5px solid #494646;position:absolute;border-right:0;border-bottom:0;right:0;top:50%;height:9px;width:9px;transform:rotate(-45deg) translateY(-50%) translateX(0);transition:transform .25s;transform-origin:center}.tree-arrow.expanded.has-child:after{transform:rotate(45deg) translateY(-50%) translateX(-5px)}.tree-checkbox{flex-shrink:0;position:relative;width:30px;height:30px;box-sizing:border-box;border:1px solid #dadada;border-radius:2px;background:#fff;transition:border-color .25s,background-color .25s}.tree-arrow:after,.tree-checkbox:after{position:absolute;display:block;content:\"\"}.tree-checkbox.checked,.tree-checkbox.indeterminate{background-color:#3a99fc;border-color:#218eff}.tree-checkbox.checked:after{box-sizing:content-box;border:1.5px solid #fff;border-left:0;border-top:0;left:9px;top:3px;height:15px;width:8px;transform:rotate(45deg) scaleY(0);transition:transform .25s;transform-origin:center}.tree-checkbox.checked:after{transform:rotate(45deg) scaleY(1)}.tree-checkbox.indeterminate:after{background-color:#fff;top:50%;left:20%;right:20%;height:2px}.tree-anchor{flex-grow:2;outline:0;display:flex;text-decoration:none;color:#343434;vertical-align:top;margin-left:3px;line-height:24px;padding:3px 6px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.tree-node.selected>.tree-content>.tree-anchor{outline:0}.tree-node.disabled>.tree-content>.tree-anchor{color:#989191;background:#fff;opacity:.6;cursor:default;outline:0}.tree-input{display:block;width:100%;height:24px;line-height:24px;outline:0;border:1px solid #3498db;padding:0 4px}.l-fade-enter-active,.l-fade-leave-active{transition:opacity .3s,transform .3s;transform:translateX(0)}.l-fade-enter,.l-fade-leave-to{opacity:0;transform:translateX(-2em)}.tree--small .tree-anchor{line-height:19px}.tree--small .tree-checkbox{width:23px;height:23px}.tree--small .tree-arrow{height:23px}.tree--small .tree-checkbox.checked:after{left:7px;top:3px;height:11px;width:5px}.tree-node.has-child.loading>.tree-content>.tree-arrow,.tree-node.has-child.loading>.tree-content>.tree-arrow:after{border-radius:50%;width:15px;height:15px;border:0}.tree-node.has-child.loading>.tree-content>.tree-arrow{font-size:3px;position:relative;border-top:1.1em solid rgba(45,45,45,.2);border-right:1.1em solid rgba(45,45,45,.2);border-bottom:1.1em solid rgba(45,45,45,.2);border-left:1.1em solid #2d2d2d;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);left:5px;-webkit-animation:loading 1.1s infinite linear;animation:loading 1.1s infinite linear;margin-right:8px}@-webkit-keyframes loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}", map: undefined, media: undefined }); }; /* scoped */ var __vue_scope_id__$1 = undefined; /* module identifier */ var __vue_module_identifier__$1 = undefined; /* functional template */ var __vue_is_functional_template__$1 = false; /* style inject SSR */ var TreeNode$1 = normalizeComponent( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__$1, __vue_script__$1, __vue_scope_id__$1, __vue_is_functional_template__$1, __vue_module_identifier__$1, createInjector, undefined ); // // // // // // var script = { name: 'DragNode', props: ['target'], computed: { style: function style() { if (undefined === this.target.top) { return 'display: none' } return ("top: " + (this.target.top) + "px; left: " + (this.target.left) + "px") } } }; /* script */ var __vue_script__$2 = script; // For security concerns, we use only base name in production mode. See https://github.com/vuejs/rollup-plugin-vue/issues/258 script.__file = "DraggableNode.vue"; /* template */ var __vue_render__$1 = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"tree-dragnode",style:(_vm.style)},[_vm._v("\n "+_vm._s(_vm.target.node.text)+"\n")])}; var __vue_staticRenderFns__$1 = []; /* style */ var __vue_inject_styles__$2 = function (inject) { if (!inject) { return } inject("data-v-7a41ac3e_0", { source: ".tree-dragnode{padding:10px;border:1px solid #e7eef7;position:fixed;border-radius:8px;background:#fff;transform:translate(-50%,-110%);z-index:10}", map: undefined, media: undefined }); }; /* scoped */ var __vue_scope_id__$2 = undefined; /* module identifier */ var __vue_module_identifier__$2 = undefined; /* functional template */ var __vue_is_functional_template__$2 = false; /* style inject SSR */ var DraggableNode = normalizeComponent( { render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }, __vue_inject_styles__$2, __vue_script__$2, __vue_scope_id__$2, __vue_is_functional_template__$2, __vue_module_identifier__$2, createInjector, undefined ); function recurseDown (obj, fn) { var res; if (Array.isArray(obj)) { return obj.map(function (node) { return recurseDown(node, fn); }) } res = fn(obj); // Recurse children if (res !== false && obj.children && obj.children.length) { res = recurseDown(obj.children, fn); } return res } function striptags (value) { // ssr fix if (!!document === false) { return value } if (!striptags.__element) { striptags.__element = document.createElement('div'); } striptags.__element.innerHTML = value; return striptags.__element.innerText } function finder (criteria) { return function (node) { return Object.keys(criteria).every(function (key) { if (key === 'text' || key === 'id') { var c = criteria[key]; var val = node[key]; // remove html tags val = striptags(val); if (isRegExp(c)) { return c.test(val) } else { return c === val } } var states = criteria[key]; // it is possible to pass 'states' or 'state' if (key === 'state') { key = 'states'; } return Object.keys(states).every(function (s) { return node[key][s] === states[s]; }) }) } } function isRegExp (val) { return val instanceof RegExp } function getAllChildren (source) { var result = []; source.forEach(function collect (node) { result.push(node); if (node.children) { node.children.forEach(collect); } }); return result } function find (source, criteria, deep) { if ( deep === void 0 ) deep = true; if (!source || !source.length || !criteria) { return null } if (deep) { source = getAllChildren(source); } // find by index if (typeof criteria === 'number') { return source[criteria] || null } if (typeof criteria === 'string' || criteria instanceof RegExp) { criteria = { text: criteria }; } if (typeof criteria !== 'function') { criteria = finder(criteria); } var result = source.filter(criteria); if (result.length) { return result } return null } // it is not genuine GUIDs function s4 () { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1) } function uuidV4 () { return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4() } function nodeIterator (context, method) { var args = [], len = arguments.length - 2; while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; context.forEach(function (node) { return node[method].apply(node, args); }); } var Selection = /*@__PURE__*/(function (Array) { function Selection (tree, items) { var ref; if ( items === void 0 ) items = []; /*eslint semi: 0 */ Array.call(this); this.tree = tree; (ref = this).push.apply(ref, items); } if ( Array ) Selection.__proto__ = Array; Selection.prototype = Object.create( Array && Array.prototype ); Selection.prototype.constructor = Selection; Selection.prototype.remove = function remove () { nodeIterator(this, 'remove'); return this }; Selection.prototype.expand = function expand () { nodeIterator(this, 'expand'); return this }; Selection.prototype.collapse = function collapse () { nodeIterator(this, 'collapse'); return this }; Selection.prototype.select = function select (extendList) { nodeIterator(this, 'select', extendList); return this }; Selection.prototype.unselect = function unselect () { nodeIterator(this, 'unselect'); return this }; Selection.prototype.check = function check () { if (this.tree.options.checkbox) { nodeIterator(this, 'check'); } return this }; Selection.prototype.uncheck = function uncheck () { if (this.tree.options.checkbox) { nodeIterator(this, 'uncheck'); } return this }; Selection.prototype.disable = function disable () { nodeIterator(this, 'disable'); return this }; Selection.prototype.enable = function enable () { nodeIterator(this, 'enable'); return this }; return Selection; }(Array)); var Node = function Node (tree, item) { if (!item) { throw new Error('Node can not be empty') } this.id = item.id || uuidV4(); this.states = item.state || {}; this.showChildren = true; this.children = item.children || []; this.parent = item.parent || null; this.isBatch = item.isBatch || false; this.isEditing = false; this.data = Object.assign({}, item.data || {}, { text: item.text }); if (!tree) { throw new Error('Node must have a Tree context!') } this.tree = tree; }; var prototypeAccessors = { key: { configurable: true },depth: { configurable: true },text: { configurable: true } }; Node.prototype.$emit = function $emit (evnt) { var ref; var args = [], len = arguments.length - 1; while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; (ref = this.tree).$emit.apply(ref, [ ("node:" + evnt), this ].concat( args )); }; Node.prototype.getPath = function getPath () { if (!this.parent) { return [this] } var path = [this]; var el = this; while ((el = el.parent) !== null) { path.push(el); } return path }; prototypeAccessors.key.get = function () { return this.id + this.text }; prototypeAccessors.depth.get = function () { var depth = 0; var parent = this.parent; if (!parent || this.showChildren === false) { return depth } do { depth++; } while (parent = parent.parent) return depth }; prototypeAccessors.text.get = function () { return this.data.text }; prototypeAccessors.text.set = function (text) { var oldText = this.text; if (oldText !== text) { this.data.text = text; this.$emit('text:changed', text, oldText); } }; Node.prototype.setData = function setData (data) { this.data = Object.assign({}, this.data, data); this.$emit('data:changed', this.data); return this.data }; Node.prototype.state = function state (name, value) { if (undefined === value) { return this.states[name] } // TODO: check if it for example `selectable` state it should unselect node this.states[name] = value; return this }; Node.prototype.recurseUp = function recurseUp (fn, node) { if ( node === void 0 ) node = this; if (!node.parent) { return } if (fn(node.parent) !== false) { return this.recurseUp(fn, node.parent) } }; Node.prototype.recurseDown = function recurseDown$1 (fn, ignoreThis) { if (ignoreThis !== true) { fn(this); } if (this.hasChildren()) { recurseDown(this.children, fn); } }; Node.prototype.refreshIndeterminateState = function refreshIndeterminateState () { if (!this.tree.options.autoCheckChildren) { return this } this.state('indeterminate', false); if (this.hasChildren()) { var childrenCount = this.children.length; var checked = 0; var indeterminate = 0; var disabled = 0; this.children.forEach(function (child) { if (child.checked()) { checked++; } if (child.disabled()) { disabled++; } if (child.indeterminate()) { indeterminate++; } }); if (checked > 0 && checked === childrenCount - disabled) { if (!this.checked()) { this.state('checked', true); this.tree.check(this); this.$emit('checked'); } } else { if (this.checked()) { this.state('checked', false); this.tree.uncheck(this); this.$emit('unchecked'); } this.state( 'indeterminate', indeterminate > 0 || (checked > 0 && checked < childrenCount) ); } } if (this.parent) { this.parent.refreshIndeterminateState(); } }; Node.prototype.indeterminate = function indeterminate () { return this.state('indeterminate') }; Node.prototype.editable = function editable () { return !this.state('disabled') && this.state('editable') }; Node.prototype.selectable = function selectable () { return !this.state('disabled') && this.state('selectable') }; Node.prototype.selected = function selected () { return this.state('selected') }; Node.prototype.select = function select (extendList) { if (!this.selectable() || this.selected()) { return this } this.tree.select(this, extendList); this.state('selected', true); this.$emit('selected'); return this }; Node.prototype.unselect = function unselect () { if (!this.selectable() || !this.selected()) { return this } this.tree.unselect(this); this.state('selected', false); this.$emit('unselected'); return this }; Node.prototype.checked = function checked () { return this.state('checked') }; Node.prototype.check = function check () { var this$1 = this; if (this.checked() || this.disabled()) { return this } if (this.indeterminate()) { return this.uncheck() } var checkDisabledChildren = this.tree.options.checkDisabledChildren; var targetNode = this; if (this.tree.options.autoCheckChildren) { this.recurseDown(function (node) { node.state('indeterminate', false); if (node.disabled() && !checkDisabledChildren) { return } if (!node.checked()) { this$1.tree.check(node); node.state('checked', true); node.$emit('checked', node.id === targetNode.id ? undefined : targetNode); } }); if (this.parent) { this.parent.refreshIndeterminateState(); } } else { this.tree.check(this); this.state('checked', true); this.$emit('checked'); } return this }; Node.prototype.uncheck = function uncheck () { var this$1 = this; if (!this.indeterminate() && !this.checked() || this.disabled()) { return this } var targetNode = this; if (this.tree.options.autoCheckChildren) { this.recurseDown(function (node) { node.state('indeterminate', false); if (node.checked()) { this$1.tree.uncheck(node); node.state('checked', false); node.$emit('unchecked', node.id === targetNode.id ? undefined : targetNode); } }); if (this.parent) { this.parent.refreshIndeterminateState(); } } else { this.tree.uncheck(this); this.state('checked', false); this.$emit('unchecked'); } return this }; Node.prototype.show = function show () { if (this.visible()) { return this } this.state('visible', true); this.$emit('shown'); return this }; Node.prototype.hide = function hide () { if (this.hidden()) { return this } this.state('visible', false); this.$emit('hidden'); return this }; Node.prototype.visible = function visible () { return this.state('visible') }; Node.prototype.hidden = function hidden () { return !this.state('visible') }; Node.prototype.enable = function enable () { if (this.enabled()) { return this } if (this.tree.options.autoDisableChildren) { this.recurseDown(function (node) { if (node.disabled()) { node.state('disabled', false); node.$emit('enabled'); } }); } else { this.state('disabled', false); this.$emit('enabled'); } return this }; Node.prototype.enabled = function enabled () { return !this.state('disabled') }; Node.prototype.disable = function disable () { if (this.disabled()) { return this } if (this.tree.options.autoDisableChildren) { this.recurseDown(function (node) { if (node.enabled()) { node.state('disabled', true); node.$emit('disabled'); } }); } else { this.state('disabled', true); this.$emit('disabled'); } return this }; Node.prototype.disabled = function disabled () { return this.state('disabled') }; Node.prototype.expandTop = function expandTop (ignoreEvent) { var this$1 = this; this.recurseUp(function (parent) { parent.state('expanded', true); if (ignoreEvent !== true) { this$1.$emit('expanded', parent); } }); }; Node.prototype.expand = function expand () { var this$1 = this; if (!this.canExpand()) { return this } if (this.isBatch) { this.tree.loadChildren(this).then(function (_) { this$1.state('expanded', true); this$1.$emit('expanded'); }); } else { this.state('expanded', true); this.$emit('expanded'); } return this }; Node.prototype.canExpand = function canExpand () { if (this.disabled() || !this.hasChildren()) { return false } return this.collapsed() && (!this.tree.autoDisableChildren || this.disabled()) }; Node.prototype.canCollapse = function canCollapse () { if (this.disabled() || !this.hasChildren()) { return false } return this.expanded() && (!this.tree.autoDisableChildren || this.disabled()) }; Node.prototype.expanded = function expanded () { return this.state('expanded') }; Node.prototype.collapse = function collapse () { if (!this.canCollapse()) { return this } this.state('expanded', false); this.$emit('collapsed'); return this }; Node.prototype.collapsed = function collapsed () { return !this.state('expanded') }; Node.prototype.toggleExpand = function toggleExpand () { return this._toggleOpenedState() }; Node.prototype.toggleCollapse = function toggleCollapse () { return this._toggleOpenedState() }; Node.prototype._toggleOpenedState = function _toggleOpenedState () { if (this.canCollapse()) { return this.collapse() } else if (this.canExpand()) { return this.expand() } }; Node.prototype.isDropable = function isDropable () { return this.enabled() && this.state('dropable') }; Node.prototype.isDraggable = function isDraggable () { return this.enabled() && this.state('draggable') && !this.isEditing }; Node.prototype.startDragging = function startDragging () { if (!this.isDraggable() || this.state('dragging')) { return false } // root element if (this.isRoot() && this.tree.model.length === 1) { return false } if (this.tree.options.store) { this.tree.__silence = true; } this.select(); this.state('dragging', true); this.$emit('dragging:start'); this.tree.__silence = false; return true }; Node.prototype.finishDragging = function finishDragging (destination, destinationPosition) { if (!destination.isDropable() && destinationPosition === 'drag-on') { return } var tree = this.tree; var clone = this.clone(); var parent = this.parent; clone.id = this.id; tree.__silence = true; this.remove(); if (destinationPosition === 'drag-on') { tree.append(destination, clone); } else if (destinationPosition === 'drag-below') { tree.after(destination, clone); } else if (destinationPosition === 'drag-above') { tree.before(destination, clone); } destination.refreshIndeterminateState(); parent && parent.refreshIndeterminateState(); tree.__silence = false; clone.state('dragging', false); this.state('dragging', false); // need to call emit on the clone, because we need to have node.parent filled in the event listener clone.$emit('dragging:finish', destination, destinationPosition); if (clone.state('selected')) { tree.selectedNodes.remove(this); tree.selectedNodes.add(clone); tree.vm.$set(this.state, 'selected', false); tree.vm.$set(clone.state, 'selected', true); } if (this.tree.options.store) { this.tree.vm.$emit('LIQUOR_NOISE'); } }; Node.prototype.startEditing = function startEditing () { if (this.disabled()) { return false } if (!this.isEditing) { this.tree._editingNode = this; this.tree.activeElement = this; this.isEditing = true; this.$emit('editing:start'); } }; Node.prototype.stopEditing = function stopEditing (newText) { if (!this.isEditing) { return } this.isEditing = false; this.tree._editingNode = null; this.tree.activeElement = null; var prevText = this.text; if (newText && newText !== false && this.text !== newText) { this.text = newText; } this.$emit('editing:stop', prevText); }; Node.prototype.index = function index (verbose) { return this.tree.index(this, verbose) }; Node.prototype.first = function first () { if (!this.hasChildren()) { return null } return this.children[0] }; Node.prototype.last = function last () { if (!this.hasChildren()) { return null } return this.children[this.children.length - 1] }; Node.prototype.next = function next () { return this.tree.nextNode(this) }; Node.prototype.prev = function prev () { return this.tree.prevNode(this) }; Node.prototype.insertAt = function insertAt (node, index) { var this$1 = this; if ( index === void 0 ) index = this.children.length; if (!node) { return } node = this.tree.objectToNode(node); if (Array.isArray(node)) { node .reverse() .map(function (n) { return this$1.insertAt(n, index); }); return new Selection(this.tree, [].concat( node )) } node.parent = this; this.children.splice( index, 0, node ); if (node.disabled() && node.hasChildren()) { node.recurseDown(function (child) { child.state('disabled', true); }); } if (!this.isBatch) { this.$emit('added', node); } return node }; Node.prototype.addChild = function addChild (node) { return this.insertAt(node) }; Node.prototype.append = function append (node) { return this.addChild(node) }; Node.prototype.prepend = function prepend (node) { return this.insertAt(node, 0) }; Node.prototype.before = function before (node) { return this.tree.before(this, node) }; Node.prototype.after = function after (node) { return this.tree.after(this, node) }; Node.prototype.empty = function empty () { var node; while (node = this.children.pop()) { node.remove(); } return this }; Node.prototype.remove = function remove () { return this.tree.removeNode(this) }; Node.prototype.removeChild = function removeChild (criteria) { var node = this.find(criteria); if (node) { return this.tree.removeNode(node) } return null }; Node.prototype.find = function find$1 (criteria, deep) { if (this.tree.isNode(criteria)) { return criteria } return find(this.children, criteria, deep) }; Node.prototype.focus = function focus () { if (this.vm) { this.vm.focus(); } }; Node.prototype.hasChildren = function hasChildren () { return this.showChildren && this.isBatch || this.children.length > 0 }; /** * Sometimes it's no need to have a parent. It possible to have more than 1 parent */ Node.prototype.isRoot = function isRoot () { return this.parent === null }; Node.prototype.clone = function clone () { return this.tree.objectToNode(this.toJSON()) }; Node.prototype.toJSON = function toJSON () { var this$1 = this; return { text: this.text, data: this.data, state: this.states, children: this.children.map(function (node) { return this$1.tree.objectToNode(node).toJSON(); }) } }; Object.defineProperties( Node.prototype, prototypeAccessors ); /** * Default Node's states */ var nodeStates = { selected: false, selectable: true, checked: false, expanded: false, disabled: false, visible: true, indeterminate: false, matched: false, editable: true, dragging: false, draggable: true, dropable: true }; function merge (state) { if ( state === void 0 ) state = {}; return Object.assign({}, nodeStates, state) } function objectToNode (tree, obj) { var node = null; if (obj instanceof Node) { return obj } if (typeof obj === 'string') { node = new Node(tree, { text: obj, state: merge(), id: uuidV4() }); } else if (Array.isArray(obj)) { return obj.map(function (o) { return objectToNode(tree, o); }) } else { node = new Node(tree, obj); node.states = merge(node.states); if (!node.id) { node.id = uuidV4(); } if (node.children.length) { node.children = node.children.map(function (child) { child = objectToNode(tree, child); child.parent = node; return child }); } } return node } var List = /*@__PURE__*/(function (Array) { function List () { Array.apply(this, arguments); } if ( Array ) List.__proto__ = Array; List.prototype = Object.create( Array && Array.prototype ); List.prototype.constructor = List; List.prototype.empty = function empty () { this.splice(0, this.length); return this }; List.prototype.has = function has (item) { return this.includes(item) }; List.prototype.add = function add () { var ref; var items = [], len = arguments.length; while ( len-- ) items[ len ] = arguments[ len ]; (ref = this).push.apply(ref, items); return this }; List.prototype.remove = function remove (item) { var index = this.indexOf(item); if (index === -1) { return this } this.splice(index, 1); return this }; List.prototype.removeAll = function removeAll (item) { while (this.includes(item)) { this.remove(item); } return this }; List.prototype.top = function top () { return this[this.length - 1] }; return List; }(Array)); /** Every Node has certain format: { id, // Unique Node id. By default it generates using uuidV4 text, // Node text children, // List of children. Each children has the same format parent, // Parent Node or null. The tree is able to have more than 1 root node state, // States of Node. Ex.: selected, checked and so on data // Any types of data. It is similar to `storage`. // Ex.: data: {myAwesomeProperty: 10}. To get this property you need: Node.data('myAwesomeProperty') } */ var defaultPropertyNames = { id: 'id', text: 'text', children: 'children', state: 'state', data: 'data', isBatch: 'isBatch' }; function convertNames (obj, names) { return { id: obj[names.id], text: obj[names.text], children: obj[names.children], state: obj[names.state], data: obj[names.data], isBatch: obj[names.isBatch] } } var TreeParser = { parse: function parse (data, tree, options) { if ( options === void 0 ) options = {}; if (typeof data === 'string') { data = JSON.parse(data); } if (!Array.isArray(data)) { data = [data]; } var p = Object.assign( {}, defaultPropertyNames, options ); var preparedItems = data.map(function converter (item) { var convertedItem = convertNames(item, p); // Possible to receive 1 child like a simple object. It must be converted to an array // We do not have checks on the correctness of the format. A developer should pass correct format if (convertedItem.children && !Array.isArray(convertedItem.children)) { convertedItem.children = [convertedItem.children]; } if (convertedItem.children) { convertedItem.children = convertedItem.children.map(converter); } return convertedItem }); return preparedItems.map(function (item) { return objectToNode(tree, item); }) } }; /*eslint no-undef: 0 */ function request (url) { return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.addEventListener('load', function (_) { try { var response = JSON.parse(xhr.response); resolve(response); } catch (e) { reject(e); } }); xhr.send(null); }) } function get (url) { return request(url) } function createTemplate (template) { return function (source) { var re = /{([^}]+)}/; var m; var result = template; while (m = re.exec(result)) { result = result.replace(m[0], source[m[1]]); } return result } } function orderAsc (node0, node1) { if (node0.text < node1.text) { return -1 } if (node0.text > node1.text) { return 1 } return 0 } function orderDesc (node0, node1) { if (node0.text < node1.text) { return 1 } if (node0.text > node1.text) { return -1 } return 0 } function getCompareFunction (order) { switch (order.toLowerCase()) { case 'asc': return orderAsc case 'desc': return orderDesc } } function sort (source, compareFunction) { if (typeof compareFunction === 'string') { compareFunction = getCompareFunction(compareFunction); } if (Array.isArray(source) && typeof compareFunction === 'function') { source.sort(compareFunction); } } function fetchDelay (ms) { return new Promise(function (resolve) { setTimeout(resolve, ms); }) } var Tree = function Tree (vm) { var this$1 = this; this.vm = vm; this.options = vm.opts; this.activeElement = null; // We have to convert 'fetchData' to function. It must return Promise always var fetchData = this.options.fetchData; if (typeof fetchData === 'string') { this.options.fetchData = (function (template) { var urlTemplate = createTemplate(template); return function (node) { return get(urlTemplate(node)).catch(this$1.options.onFetchError) } })(fetchData); } }; Tree.prototype.$on = function $on (name) { var ref; var args = [], len = arguments.length - 1; while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; (ref = this.vm).$on.apply(ref, [ name ].concat( args )); }; Tree.prototype.$once = function $once (name) { var ref; var args = [], len = arguments.length - 1; while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; (ref = this.vm).$once.apply(ref, [ name ].concat( args )); }; Tree.prototype.$off = function $off (name) { var ref; var args = [], len = arguments.length - 1; while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; (ref = this.vm).$off.apply(ref, [ name ].concat( args )); }; Tree.prototype.$emit = function $emit (name) { var ref; var args = [], len = arguments.length - 1; while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; if (this.__silence) { return } (ref = this.vm).$emit.apply(ref, [ name ].concat( args )); if (this.options.store) { this.vm.$emit('LIQUOR_NOISE'); } }; Tree.prototype._sort = function _sort (source, compareFn, deep) { if (deep !== false) { this.recurseDown(source, function (node) { if (node.hasChildren()) { sort(node.children, compareFn); } }); } sort(source, compareFn); }; Tree.prototype.sortTree = function sortTree (compareFn, deep) { this._sort(this.model, compareFn, deep); }; Tree.prototype.sort = function sort$$1 (query, compareFn, deep) { var this$1 = this; var targetNode = this.find(query, true); if (!targetNode || !compareFn) { return } targetNode.forEach(function (node) { this$1._sort(node.children, compareFn, deep); }); }; Tree.prototype.clearFilter = function clearFilter () { this.recurseDown(function (node) { node.state('matched', false); node.state('visible', true); node.state('expanded', node.__expanded); node.__expanded = undefined; node.showChildren = true; }); this.vm.matches.length = 0; this.vm.$emit('tree:filtered', [], ''); }; Tree.prototype.filter = function filter (query) { if (!query) { return this.clearFilter() } var matches = []; var predicate = this.options.filter.matcher; var ref = this.options.filter; var showChildren = ref.showChildren; var plainList = ref.plainList; // collect nodes this.recurseDown(function (node) { if (predicate(query, node)) { matches.push(node); } node.showChildren = true; // save prev `expanded` state if (undefined === node.__expanded) { node.__expanded = node.state('expanded'); } node.state('visible', false); node.state('matched', false); node.state('expanded', true); }); matches.reverse().forEach(function (node) { node.state('matched', true); node.state('visible', true); node.showChildren = !plainList; if (node.hasChildren()) { node.recurseDown(function (n) { n.state('visible', !!showChildren); }, true); } node.recurseUp(function (parent) { parent.state('visible', true); parent.state('expanded', true); }); if (node.hasChildren()) { node.state('expanded', false); } }); this.vm.matches = matches; this.vm.$emit('tree:filtered', matches, query); return matches }; Tree.prototype.selected = function selected () { return new (Function.prototype.bind.apply( Selection, [ null ].concat( [this], this.selectedNodes) )) }; Tree.prototype.checked = function checked () { if (!this.options.checkbox) { return null } return new (Function.prototype.bind.apply( Selection, [ null ].concat( [this], this.checkedNodes) )) }; Tree.prototype.loadChildren = function loadChildren (node) { var this$1 = this; if (!node) { return } this.$emit('tree:data:fetch', node); if (this.options.minFetchDelay > 0 && node.vm) { node.vm.loading = true; } var result = this.fetch(node) .then(function (children) { node.append(children); node.isBatch = false; if (this$1.options.autoCheckChildren) { if (node.checked()) { node.recurseDown(function (child) { child.state('checked', true); }); } node.refreshIndeterminateState(); } this$1.$emit('tree:data:received', node); }); return Promise.all([ fetchDelay(this.options.minFetchDelay), result ]).then(function (_) { if (node.vm) { node.vm.loading = false; } return result }) }; Tree.prototype.fetch = function fetch (node, parseData) { var this$1 = this; var result = this.options.fetchData(node); if (!result.then) { result = get(result) .catch(this.options.onFetchError); } if (parseData === false) { return result } return result .then(function (data) { try { return this$1.parse(data, this$1.options.modelParse) } catch (e) { throw new Error(e) } }) .catch(this.options.onFetchError) }; Tree.pr