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

266 lines
6.5 KiB
JavaScript
Raw Normal View History

2018-11-12 10:31:58 +00:00
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
2019-10-02 07:54:52 +00:00
import './childs';
2019-10-16 06:56:13 +00:00
import './child';
2019-10-02 07:54:52 +00:00
2018-11-12 10:31:58 +00:00
/**
2019-04-29 09:49:43 +00:00
* Treeview
2018-11-12 10:31:58 +00:00
*/
export default class Treeview extends Component {
2019-10-16 06:56:13 +00:00
constructor($element, $scope, $transclude, $window) {
2018-11-12 10:31:58 +00:00
super($element, $scope);
2019-10-01 13:09:55 +00:00
this.$transclude = $transclude;
2019-10-16 06:56:13 +00:00
this.$window = $window;
2019-10-08 05:22:38 +00:00
this.readOnly = true;
2019-10-16 06:56:13 +00:00
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) {
2019-10-16 07:52:46 +00:00
this.dragClientY = event.clientY;
2019-10-16 06:56:13 +00:00
// Prevents page reload
event.preventDefault();
}
2019-10-16 07:52:46 +00:00
onDragInterval() {
if (this.dragClientY > 0 && this.dragClientY < 75)
this.$window.scrollTo(0, this.$window.scrollY - 25);
}
2019-10-16 06:56:13 +00:00
dragStart(event) {
event.target.classList.add('dragging');
event.dataTransfer.setData('text', event.target.id);
const element = this.findDroppable(event);
this.dragging = element;
2019-10-16 07:52:46 +00:00
this.interval = setInterval(() => this.onDragInterval(), 100);
2019-10-16 06:56:13 +00:00
}
dragEnd(event) {
event.target.classList.remove('dragging');
this.undrop();
this.dropCount = 0;
this.dragging = null;
2019-10-16 07:52:46 +00:00
clearInterval(this.interval);
2019-10-16 06:56:13 +00:00
}
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;
2019-10-17 09:08:40 +00:00
if ($dropped != $dragged.parent)
this.emit('drop', {$dropped, $dragged});
2018-11-12 10:31:58 +00:00
}
2019-10-08 05:22:38 +00:00
get data() {
return this._data;
2018-11-12 10:31:58 +00:00
}
2019-10-08 05:22:38 +00:00
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);
2019-01-21 10:45:53 +00:00
});
}
2019-10-24 08:17:32 +00:00
onToggle(event, item) {
let ignoreEvent = event.defaultPrevented
|| event == this.lastActionEvent
|| !item.sons;
if (ignoreEvent) return;
2019-10-04 05:41:24 +00:00
if (item.active)
this.fold(item);
else
this.unfold(item);
2019-01-21 10:45:53 +00:00
}
2019-10-04 05:41:24 +00:00
fold(item) {
item.childs = undefined;
item.active = false;
2019-03-12 14:04:09 +00:00
}
2019-10-04 05:41:24 +00:00
unfold(item) {
2019-10-08 05:22:38 +00:00
return this.fetchFunc({$item: item}).then(newData => {
this.setParent(item, newData);
2019-10-04 05:41:24 +00:00
2019-10-08 05:22:38 +00:00
const childs = item.childs;
if (childs) {
2019-10-04 05:41:24 +00:00
childs.forEach(child => {
let index = newData.findIndex(newChild => {
return newChild.id == child.id;
2019-02-18 07:37:26 +00:00
});
2019-10-04 05:41:24 +00:00
newData[index] = child;
});
}
2019-02-18 07:37:26 +00:00
2019-10-08 05:22:38 +00:00
if (this.sortFunc) {
item.childs = newData.sort((a, b) =>
this.sortFunc({$a: a, $b: b})
);
}
2019-10-04 05:41:24 +00:00
}).then(() => item.active = true);
2018-11-12 10:31:58 +00:00
}
2019-10-24 08:17:32 +00:00
onRemove(event, item) {
this.lastActionEvent = event;
2019-10-08 05:22:38 +00:00
if (this.removeFunc)
this.removeFunc({$item: item});
}
2019-10-02 12:12:17 +00:00
2019-10-08 05:22:38 +00:00
remove(item) {
const parent = item.parent;
let childs = parent.childs;
2019-10-02 12:12:17 +00:00
2019-10-08 05:22:38 +00:00
if (!childs) childs = [];
2019-10-02 12:12:17 +00:00
2019-10-08 05:22:38 +00:00
let index = childs.indexOf(item);
childs.splice(index, 1);
if (parent) parent.sons--;
2019-10-02 12:12:17 +00:00
}
2019-10-24 08:17:32 +00:00
onCreate(event, parent) {
this.lastActionEvent = event;
2019-10-16 07:52:46 +00:00
if (this.createFunc)
this.createFunc({$parent: parent});
2019-10-02 12:12:17 +00:00
}
2019-10-04 05:41:24 +00:00
2019-10-08 05:22:38 +00:00
create(item) {
const parent = item.parent;
let childs = parent.childs;
if (!childs) childs = [];
2019-10-04 05:41:24 +00:00
2019-10-16 07:52:46 +00:00
if (!parent.active)
this.unfold(parent);
else
childs.push(item);
2019-10-04 05:41:24 +00:00
2019-10-08 05:22:38 +00:00
if (this.sortFunc) {
childs = childs.sort((a, b) =>
this.sortFunc({$a: a, $b: b})
);
2019-10-04 05:41:24 +00:00
}
2019-10-08 05:22:38 +00:00
if (parent) parent.sons++;
}
2019-10-16 06:56:13 +00:00
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;
2019-10-16 07:52:46 +00:00
if (!newParent.active) {
this.unfold(newParent).then(() => {
item.parent.sons++;
});
} else
this.create(item);
2019-10-08 05:22:38 +00:00
}
2018-11-12 10:31:58 +00:00
}
2019-10-16 06:56:13 +00:00
Treeview.$inject = ['$element', '$scope', '$transclude', '$window'];
2018-11-12 10:31:58 +00:00
ngModule.component('vnTreeview', {
template: require('./index.html'),
controller: Treeview,
bindings: {
2019-10-08 05:22:38 +00:00
rootLabel: '@',
data: '<?',
2019-04-29 09:49:43 +00:00
draggable: '<?',
droppable: '<?',
2019-10-08 05:22:38 +00:00
fetchFunc: '&',
2019-10-02 12:12:17 +00:00
removeFunc: '&?',
2019-10-08 05:22:38 +00:00
createFunc: '&?',
sortFunc: '&?',
readOnly: '<?'
2019-10-01 13:09:55 +00:00
},
2019-10-02 07:54:52 +00:00
transclude: true
2018-11-12 10:31:58 +00:00
});