salix/front/core/components/treeview/index.js

266 lines
6.5 KiB
JavaScript

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.component('vnTreeview', {
template: require('./index.html'),
controller: Treeview,
bindings: {
rootLabel: '@',
data: '<?',
draggable: '<?',
droppable: '<?',
fetchFunc: '&',
removeFunc: '&?',
createFunc: '&?',
sortFunc: '&?',
readOnly: '<?'
},
transclude: true
});