175 lines
4.0 KiB
JavaScript
Executable File
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'
|
|
}
|
|
});
|