package.src.vaadin-grid-active-item-mixin.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grid Show documentation
Show all versions of grid Show documentation
A free, flexible and high-quality Web Component for showing large amounts of tabular data
/**
* @license
* Copyright (c) 2016 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
/**
* @param {!Element} target
* @return {boolean}
* @protected
*/
export const isFocusable = (target) => {
if (!target.parentNode) {
return false;
}
const focusables = Array.from(
target.parentNode.querySelectorAll(
'[tabindex], button, input, select, textarea, object, iframe, a[href], area[href]',
),
).filter((element) => {
const part = element.getAttribute('part');
return !(part && part.includes('body-cell'));
});
const isFocusableElement = focusables.includes(target);
return (
!target.disabled && isFocusableElement && target.offsetParent && getComputedStyle(target).visibility !== 'hidden'
);
};
/**
* @polymerMixin
*/
export const ActiveItemMixin = (superClass) =>
class ActiveItemMixin extends superClass {
static get properties() {
return {
/**
* The item user has last interacted with. Turns to `null` after user deactivates
* the item by re-interacting with the currently active item.
* @type {GridItem}
*/
activeItem: {
type: Object,
notify: true,
value: null,
sync: true,
},
};
}
/** @protected */
ready() {
super.ready();
this.$.scroller.addEventListener('click', this._onClick.bind(this));
this.addEventListener('cell-activate', this._activateItem.bind(this));
this.addEventListener('row-activate', this._activateItem.bind(this));
}
/** @private */
_activateItem(e) {
const model = e.detail.model;
const clickedItem = model ? model.item : null;
if (clickedItem) {
this.activeItem = !this._itemsEqual(this.activeItem, clickedItem) ? clickedItem : null;
}
}
/**
* Checks whether the click event should not activate the cell on which it occurred.
*
* @protected
*/
_shouldPreventCellActivationOnClick(e) {
const { cell } = this._getGridEventLocation(e);
return (
// Something has handled this click already, e. g.,
e.defaultPrevented ||
// No clicked cell available
!cell ||
// Cell is a details cell
cell.getAttribute('part').includes('details-cell') ||
// Cell content is focused
cell._content.contains(this.getRootNode().activeElement) ||
// Clicked on a focusable element
this._isFocusable(e.target) ||
// Clicked on a label element
e.target instanceof HTMLLabelElement
);
}
/**
* @param {!MouseEvent} e
* @protected
*/
_onClick(e) {
if (this._shouldPreventCellActivationOnClick(e)) {
return;
}
const { cell } = this._getGridEventLocation(e);
if (cell) {
this.dispatchEvent(
new CustomEvent('cell-activate', {
detail: {
model: this.__getRowModel(cell.parentElement),
},
}),
);
}
}
/**
* @param {!Element} target
* @return {boolean}
* @protected
*/
_isFocusable(target) {
return isFocusable(target);
}
/**
* Fired when the `activeItem` property changes.
*
* @event active-item-changed
*/
/**
* Fired when the cell is activated with click or keyboard.
*
* @event cell-activate
*/
};