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

175 lines
4.0 KiB
JavaScript
Executable File

import ngModule from '../../module';
export default class Contextmenu {
constructor($element, $, $transclude) {
this.$element = $element;
this.element = $element[0];
this.$ = $;
this.$transclude = $transclude;
}
get targets() {
return this._targets;
}
set targets(value) {
this._targets = value;
if (!value) return;
for (let selector of value) {
const target = document.querySelector(selector);
if (!target) continue;
target.addEventListener('contextmenu', event => {
this.target = event.target;
if (!event.defaultPrevented)
event.preventDefault();
if (!this.isFilterEnabled()) return;
const parent = this.$.contextmenu;
parent.style.top = event.pageY + 'px';
parent.style.left = event.pageX + 'px';
this.$.menu.show(parent);
});
}
}
get row() {
if (!this.target) return null;
return this.target.closest('vn-tr, .vn-tr');
}
get rowIndex() {
if (!this.row) return null;
const table = this.row.closest('vn-table, .vn-table');
const tBody = table.querySelector('vn-tbody, .vn-tbody');
const rows = tBody.querySelectorAll('vn-tr, .vn-tr');
return Array.from(rows).findIndex(
rowItem => rowItem == this.row
);
}
get rowData() {
const model = this.model;
const rowData = model.data[this.rowIndex];
return rowData;
}
get cell() {
if (!this.target) return null;
return this.target.closest('vn-td, .vn-td');
}
get cellIndex() {
if (!this.row) return null;
const cells = this.row.querySelectorAll('vn-td, .vn-td');
return Array.from(cells).findIndex(
cellItem => cellItem == this.cell
);
}
get rowHeader() {
if (!this.row) return null;
const table = this.row.closest('vn-table, .vn-table');
const headerCells = table && table.querySelectorAll('vn-thead vn-th');
const headerCell = headerCells && headerCells[this.cellIndex];
return headerCell;
}
/**
* Selected model field name
*
* @return {string}
*/
get fieldName() {
if (!this.rowHeader) return null;
return this.rowHeader.getAttribute('field');
}
/**
* Selected field value
*
* @return {any}
*/
get fieldValue() {
return this.rowData[this.fieldName];
}
/**
* Returns true if filter is not disabled
*
* @return {Boolean}
*/
isFilterEnabled() {
if (!this.rowHeader) return true;
const isEnabled = this.rowHeader.getAttribute('filter-enabled');
return isEnabled != 'false';
}
/**
* Returns true if filter
* by selection is allowed
*
* @return {Boolean}
*/
isFilterAllowed() {
if (!this.target) return false;
const isTableCell = this.target.closest('vn-td, .vn-td');
return isTableCell && this.fieldName;
}
/**
* Filter by current field selection
*/
filterBySelection() {
const filter = {where: {}};
filter['where'][this.fieldName] = this.fieldValue;
this.model.addFilter(filter);
}
/**
* Exclude by current field selection
*/
excludeSelection() {
const filter = {where: {}};
filter['where'][this.fieldName] = {neq: this.fieldValue};
this.model.addFilter(filter);
}
/**
* Removes all applied filters
*/
removeFilter() {
this.model.removeFilter();
}
}
Contextmenu.$inject = ['$element', '$scope', '$transclude'];
ngModule.vnComponent('vnContextmenu', {
controller: Contextmenu,
template: require('./index.html'),
bindings: {
targets: '<?',
model: '<?'
},
transclude: {
menu: '?slotMenu'
}
});