localizing collapsed tabulator column headings; tabulator custom modules; debounce helper

This commit is contained in:
adisposkofh
2026-05-20 16:30:16 +02:00
parent e59bd51333
commit b9670f3f09
5 changed files with 118 additions and 18 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ Vue.$collapseFormatter = function (data) {
let item2 = document.createElement("div");
item2.classList.add("col-6");
item.innerHTML = "<strong class=\"collapsedColumnHeading\" tabulator-column-field=\"" + col.field + "\">placeholder</strong>";
item.innerHTML = "<strong class=\"collapsedColumnHeading\" tabulator-column-field=\"" + col.field + "\">...</strong>";
item2.innerHTML = col.value ? col.value : "-";
list.appendChild(item);
+31 -15
View File
@@ -22,6 +22,9 @@ import TableDownload from './Table/Download.js';
import collapseAutoClose from '../../directives/collapseAutoClose.js';
import moduleLayoutFitDataStretchFrozen from '../../tabulator/layouts/fitDataStretchFrozen.js';
import InternalToExternalEventBroadcastModule from "../../tabulator/customModules/InternalToExternalEventBroadcastModule.js"
import { debounce } from "../../helpers/DebounceHelper.js";
import ApiFilter from '../../api/factory/filter.js';
import ApiPhrases from '../../api/factory/phrasen.js';
@@ -123,6 +126,27 @@ export const CoreFilterCmpt = {
group: false,
page: false,
},
collapsedHeadingLocalizationTimer: null,
localizeCollapsedColumnHeadings:
debounce(
() => {
const columnHeadings = this.tabulator?.getLang()?.columns;
if (!columnHeadings) return;
this.$refs.table
.querySelectorAll(".collapsedColumnHeading")
.forEach((collapsedColumnHeadingElement) => {
const field =
collapsedColumnHeadingElement.getAttribute(
"tabulator-column-field",
);
if (!field?.length) return;
collapsedColumnHeadingElement.innerHTML =
columnHeadings[field];
});
}, 200)
,
};
},
computed: {
@@ -368,6 +392,11 @@ export const CoreFilterCmpt = {
this.localizeCollapsedColumnHeadings();
}
});
this.tabulator.on('layoutRefreshed', () => {
if (tabulatorOptions.locale && tabulatorOptions.responsiveLayoutCollapseFormatter) {
this.localizeCollapsedColumnHeadings();
}
});
},
async configureTabulatorLocalizations(tabulatorOptions) {
tabulatorOptions.locale = this.$p.user_language.value;
@@ -472,21 +501,6 @@ export const CoreFilterCmpt = {
return tabulatorOptions;
},
async localizeCollapsedColumnHeadings() {
const columnHeadings = this.tabulator?.getLang()?.columns;
if (!columnHeadings) return;
this.$refs.table
.querySelectorAll(".collapsedColumnHeading")
.forEach((collapsedColumnHeadingElement) => {
const field =
collapsedColumnHeadingElement.getAttribute("tabulator-column-field");
if (!field?.length) return;
collapsedColumnHeadingElement.innerHTML =
columnHeadings[field];
});
},
updateTabulator() {
if (this.tabulator) {
if (this.tableBuilt)
@@ -814,6 +828,8 @@ export const CoreFilterCmpt = {
alert('"nwNewEntry" listener is mandatory when sideMenu is true');
this.uuid = _uuid++;
this.$emit('uuidDefined', this.uuid)
Tabulator.registerModule(InternalToExternalEventBroadcastModule);
},
mounted() {
this.initTabulator().then(() => {
+7
View File
@@ -0,0 +1,7 @@
export const debounce = (callback, wait) => {
let timeoutId = null;
return (context) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => callback(), wait);
}
}
+47 -2
View File
@@ -1,4 +1,49 @@
export function capitalize(string) {
if (!string) return '';
if (!string) return "";
return string[0].toUpperCase() + string.slice(1);
}
}
export function convertCase(string, from, to) {
const possibleCases = ["kebab", "snake", "camel"];
if (
from === to ||
!possibleCases.includes(from) ||
!possibleCases.includes(to)
)
return string;
const individualWords =
from === "kebab"
? string.split("-")
: from === "snake"
? string.split("_")
: splitWordsInCamelCase(string);
const formattedIndividualWords = ["snake", "kebab"].includes(to)
? individualWords.map((word) => word.toLowerCase())
: individualWords.map((word, index) => {
if (!index) return word.toLowerCase();
return word.slice(0, 1).toUpperCase() + word.slice(1).toLowerCase();
});
const joinCharacter = to === "snake" ? "_" : to === "kebab" ? "-" : "";
return formattedIndividualWords.join(joinCharacter);
}
function splitWordsInCamelCase(string) {
const lastUpperCaseLetterIndex = string
.split("")
.findLastIndex((character) => {
return character.toUpperCase() === character;
});
if (lastUpperCaseLetterIndex < 1) {
return [string];
}
let splitWords = splitWordsInCamelCase(
string.slice(0, lastUpperCaseLetterIndex),
);
splitWords.push(string.slice(lastUpperCaseLetterIndex));
return splitWords;
}
@@ -0,0 +1,32 @@
// changes within tabulator are often not adequately broadcast to the external component
// this module exposes tabulator's internal events
// if external event name is not specified, the dispatched external event will be the camelCase version of the kebab-case internal event
import Module from "../../../../vendor/olifolkerd/tabulator5/src/js/core/Module.js";
import { convertCase } from "../../helpers/StringHelpers.js";
export default class InternalToExternalEventBroadcastModule extends Module {
static moduleName = "internalToExternalEventBroadcastModule";
static moduleInitNumber = 1;
constructor(table) {
super(table);
this.eventsToBroadcast = [
{
internal: "layout-refreshed",
external: null,
},
];
}
initialize() {
this.eventsToBroadcast.forEach((event) => {
this.subscribe(event.internal, () => {
this.dispatchExternal(event.external ?? convertCase(event.internal, "kebab", "camel"));
});
});
}
}