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 { Tooltip } from './tooltips/tooltips';
|
||||||
import { CourseTeaser } from './course-teaser/course-teaser';
|
import { CourseTeaser } from './course-teaser/course-teaser';
|
||||||
import { NavbarUtils } from './navbar/navbar';
|
import { NavbarUtils } from './navbar/navbar';
|
||||||
|
import { HideColumns } from './hide-columns/hide-columns';
|
||||||
|
|
||||||
export const Utils = [
|
export const Utils = [
|
||||||
Alerts,
|
Alerts,
|
||||||
@ -27,4 +28,5 @@ export const Utils = [
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
CourseTeaser,
|
CourseTeaser,
|
||||||
...NavbarUtils,
|
...NavbarUtils,
|
||||||
|
HideColumns,
|
||||||
];
|
];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user