import ngModule from '../../module'; import Component from '../../lib/component'; import './style.scss'; import './childs'; import './child'; /** * Treeview */ export default class Treeview extends Component { constructor($element, $scope, $transclude, $window) { super($element, $scope); this.$transclude = $transclude; this.$window = $window; this.readOnly = true; this.element.addEventListener('dragstart', event => this.dragStart(event)); this.element.addEventListener('dragend', event => this.dragEnd(event)); this.element.addEventListener('dragover', event => this.dragOver(event)); this.element.addEventListener('drop', event => this.drop(event)); this.element.addEventListener('dragenter', event => this.dragEnter(event)); this.element.addEventListener('dragleave', event => this.dragLeave(event)); this.dropCount = 0; } undrop() { if (!this.dropping) return; this.dropping.classList.remove('dropping'); this.dropping = null; } findDroppable(event) { let element = event.target; while (element != this.element && !element.droppable) element = element.parentNode; if (element == this.element) return null; return element; } dragOver(event) { this.dragClientY = event.clientY; // Prevents page reload event.preventDefault(); } onDragInterval() { if (this.dragClientY > 0 && this.dragClientY < 75) this.$window.scrollTo(0, this.$window.scrollY - 25); } dragStart(event) { event.target.classList.add('dragging'); event.dataTransfer.setData('text', event.target.id); const element = this.findDroppable(event); this.dragging = element; this.interval = setInterval(() => this.onDragInterval(), 100); } dragEnd(event) { event.target.classList.remove('dragging'); this.undrop(); this.dropCount = 0; this.dragging = null; clearInterval(this.interval); } dragEnter(event) { let element = this.findDroppable(event); if (element) this.dropCount++; if (element != this.dropping) { this.undrop(); if (element) element.classList.add('dropping'); this.dropping = element; } } dragLeave(event) { let element = this.findDroppable(event); if (element) { this.dropCount--; if (this.dropCount == 0) this.undrop(); } } drop(event) { event.preventDefault(); this.element.classList.remove('dropping'); const $dropped = this.dropping.$ctrl.item; const $dragged = this.dragging.$ctrl.item; if ($dropped != $dragged.parent) this.emit('drop', {$dropped, $dragged}); } get data() { return this._data; } set data(value) { this._data = value; const sons = value.length; const rootElement = [{ childs: value, active: true, sons: sons }]; this.setParent(rootElement[0], value); this.items = rootElement; } fetch() { return this.fetchFunc().then(res => this.data = res ); } setParent(parent, childs) { childs.forEach(child => { child.parent = parent; if (child.childs) this.setParent(parent, child.childs); }); } onToggle(event, item) { let ignoreEvent = event.defaultPrevented || event == this.lastActionEvent || !item.sons; if (ignoreEvent) return; if (item.active) this.fold(item); else this.unfold(item); } fold(item) { item.childs = undefined; item.active = false; } unfold(item) { return this.fetchFunc({$item: item}).then(newData => { this.setParent(item, newData); const childs = item.childs; if (childs) { childs.forEach(child => { let index = newData.findIndex(newChild => { return newChild.id == child.id; }); newData[index] = child; }); } if (this.sortFunc) { item.childs = newData.sort((a, b) => this.sortFunc({$a: a, $b: b}) ); } }).then(() => item.active = true); } onRemove(event, item) { this.lastActionEvent = event; if (this.removeFunc) this.removeFunc({$item: item}); } remove(item) { const parent = item.parent; let childs = parent.childs; if (!childs) childs = []; let index = childs.indexOf(item); childs.splice(index, 1); if (parent) parent.sons--; } onCreate(event, parent) { this.lastActionEvent = event; if (this.createFunc) this.createFunc({$parent: parent}); } create(item) { const parent = item.parent; let childs = parent.childs; if (!childs) childs = []; if (!parent.active) this.unfold(parent); else childs.push(item); if (this.sortFunc) { childs = childs.sort((a, b) => this.sortFunc({$a: a, $b: b}) ); } if (parent) parent.sons++; } move(item, newParent) { if (newParent == item) return; if (item.parent) { const parent = item.parent; const childs = parent.childs; const index = childs.indexOf(item); parent.sons--; childs.splice(index, 1); } item.parent = newParent; if (!newParent.active) { this.unfold(newParent).then(() => { item.parent.sons++; }); } else this.create(item); } } Treeview.$inject = ['$element', '$scope', '$transclude', '$window']; ngModule.vnComponent('vnTreeview', { template: require('./index.html'), controller: Treeview, bindings: { rootLabel: '@', data: '