feat(hide-columns): first stub of hide-column util with manual styling
This commit is contained in:
parent
1023240136
commit
111821dcad
149
frontend/src/utils/hide-columns/hide-columns.js
Normal file
149
frontend/src/utils/hide-columns/hide-columns.js
Normal file
@ -0,0 +1,149 @@
|
||||
import { Utility } from '../../core/utility';
|
||||
import { StorageManager } from '../../lib/storage-manager/storage-manager';
|
||||
|
||||
const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns';
|
||||
const TABLE_HEADER_IDENT = 'hide-column-header';
|
||||
|
||||
const TABLE_UTILS_ATTR = 'table-utils';
|
||||
const TABLE_UTILS_CONTAINER_SELECTOR = `[${TABLE_UTILS_ATTR}]`;
|
||||
|
||||
|
||||
const HIDER_TEXT_ATTR = 'header-text';
|
||||
|
||||
const HIDE_BUTTON_FADE_DELAY = 3000;
|
||||
|
||||
@Utility({
|
||||
selector: `[${HIDE_COLUMNS_CONTAINER_IDENT}] table`,
|
||||
})
|
||||
export class HideColumns {
|
||||
|
||||
_storageManager = new StorageManager('uw-hide-columns');
|
||||
|
||||
_element;
|
||||
_tableUtilContainer;
|
||||
|
||||
constructor(element) {
|
||||
if (!element) {
|
||||
throw new Error('Hide Columns utility cannot be setup without an element!');
|
||||
}
|
||||
|
||||
// do not provide hide-column ability in tables inside modals or async forms with response
|
||||
if (element.closest('[uw-modal], .async-form__response')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._element = element;
|
||||
|
||||
const hideColumnsContainer = this._element.closest(`[${HIDE_COLUMNS_CONTAINER_IDENT}]`);
|
||||
if (!hideColumnsContainer) {
|
||||
throw new Error('Hide Columns utility needs to be setup on a table inside a hide columns container!');
|
||||
}
|
||||
|
||||
// get or create table utils container
|
||||
this._tableUtilContainer = hideColumnsContainer.querySelector(TABLE_UTILS_CONTAINER_SELECTOR);
|
||||
if (!this._tableUtilContainer) {
|
||||
this._tableUtilContainer = document.createElement('div');
|
||||
this._tableUtilContainer.setAttribute(TABLE_UTILS_ATTR, '');
|
||||
const tableContainer = this._element.closest(`[${HIDE_COLUMNS_CONTAINER_IDENT}] > *`);
|
||||
hideColumnsContainer.insertBefore(this._tableUtilContainer, tableContainer);
|
||||
}
|
||||
|
||||
this._element.querySelectorAll('th').forEach(th => {
|
||||
const storageKey = this.getStorageKey(th);
|
||||
const previouslyHidden = this._storageManager.load(storageKey);
|
||||
this.setupHideButton(th, previouslyHidden);
|
||||
});
|
||||
}
|
||||
|
||||
setupHideButton(th, prevHidden) {
|
||||
console.log('setupHideButton', th, prevHidden);
|
||||
|
||||
const hider = document.createElement('button');
|
||||
hider.setAttribute(HIDER_TEXT_ATTR, th.innerText);
|
||||
|
||||
hider.addEventListener('click', (event) => {
|
||||
console.log('click', th.cellIndex, hider, th.innerText);
|
||||
event.preventDefault();
|
||||
this.toggleColumnVisibility(th, hider);
|
||||
});
|
||||
|
||||
// TODO fade in / fade out animation in css
|
||||
th.addEventListener('mouseover', () => {
|
||||
hider.style.display = '';
|
||||
});
|
||||
th.addEventListener('mouseout', () => {
|
||||
setTimeout(() => {
|
||||
if (hider.style.position === 'absolute') hider.style.display = 'none';
|
||||
}, HIDE_BUTTON_FADE_DELAY);
|
||||
});
|
||||
|
||||
this.updateColumnDisplay(th.cellIndex, prevHidden);
|
||||
this.updateHider(hider, prevHidden);
|
||||
|
||||
this._tableUtilContainer.appendChild(hider);
|
||||
}
|
||||
|
||||
// TODO better name
|
||||
toggleColumnVisibility(th, hider) {
|
||||
const storageKey = this.getStorageKey(th);
|
||||
|
||||
const hidden = !this._storageManager.load(storageKey);
|
||||
|
||||
// hide/unhide column
|
||||
this.updateColumnDisplay(th.cellIndex, hidden);
|
||||
|
||||
// tweak hider button
|
||||
this.updateHider(hider, hidden);
|
||||
|
||||
// persist new hidden setting for column
|
||||
this._storageManager.save(storageKey, hidden);
|
||||
}
|
||||
|
||||
// TODO better name
|
||||
updateColumnDisplay(columnIndex, hidden) {
|
||||
this._element.getElementsByTagName('tr').forEach(row => {
|
||||
if (row.cells[columnIndex]) {
|
||||
row.cells[columnIndex].style.display = hidden ? 'none' : '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO better name
|
||||
updateHider(hider, hidden) {
|
||||
// TODO set css classes instead
|
||||
if (hidden) {
|
||||
hider.innerHTML = hider.getAttribute(HIDER_TEXT_ATTR);
|
||||
hider.style.position = 'relative';
|
||||
} else {
|
||||
hider.innerHTML = 'hide';
|
||||
hider.style.position = 'absolute';
|
||||
hider.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
getStorageKey(th) {
|
||||
// get handler name
|
||||
const handlerIdent = document.querySelector('[uw-handler]').getAttribute('uw-handler');
|
||||
|
||||
// get hide-columns container ident (if not present, use table index in document as fallback)
|
||||
let tIdent = th.getAttribute(TABLE_HEADER_IDENT);
|
||||
if (!tIdent) {
|
||||
const tablesInDocument = document.getElementsByTagName('TABLE');
|
||||
for (let i = 0; i < tablesInDocument.length; i++) {
|
||||
if (tablesInDocument[i] === this._element) {
|
||||
tIdent = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for unique table header ident from backend (if not present, use cell index as fallback)
|
||||
let thIdent = th.getAttribute(TABLE_HEADER_IDENT);
|
||||
if (!thIdent) {
|
||||
thIdent = th.cellIndex;
|
||||
}
|
||||
|
||||
return `${handlerIdent}-${tIdent}-${thIdent}`;
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,6 +11,7 @@ import { Modal } from './modal/modal';
|
||||
import { Tooltip } from './tooltips/tooltips';
|
||||
import { CourseTeaser } from './course-teaser/course-teaser';
|
||||
import { NavbarUtils } from './navbar/navbar';
|
||||
import { HideColumns } from './hide-columns/hide-columns';
|
||||
|
||||
export const Utils = [
|
||||
Alerts,
|
||||
@ -27,4 +28,5 @@ export const Utils = [
|
||||
Tooltip,
|
||||
CourseTeaser,
|
||||
...NavbarUtils,
|
||||
HideColumns,
|
||||
];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user