159 lines
4.7 KiB
JavaScript
159 lines
4.7 KiB
JavaScript
(() => {
|
|
const PANEL_SELECTOR = '[data-refresh-url="data/cvp.php"]';
|
|
const TABLE_SELECTOR = '[data-boiler-section]';
|
|
const STORAGE_KEY = 'lasuca.boilerPanels';
|
|
|
|
const loadState = () => {
|
|
try {
|
|
const stored = window.localStorage.getItem(STORAGE_KEY);
|
|
if (!stored) {
|
|
return {};
|
|
}
|
|
const parsed = JSON.parse(stored);
|
|
return typeof parsed === 'object' && parsed !== null ? parsed : {};
|
|
} catch (error) {
|
|
console.warn('Unable to load boiler panel state from storage.', error);
|
|
return {};
|
|
}
|
|
};
|
|
|
|
const saveState = (state) => {
|
|
try {
|
|
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
|
|
} catch (error) {
|
|
console.warn('Unable to persist boiler panel state.', error);
|
|
}
|
|
};
|
|
|
|
const applyCollapsedState = (table, collapsed) => {
|
|
const rows = Array.from(table.rows).slice(1);
|
|
rows.forEach((row) => {
|
|
row.style.display = collapsed ? 'none' : '';
|
|
});
|
|
table.classList.toggle('is-collapsed', collapsed);
|
|
};
|
|
|
|
const formatSummary = (value, units) => {
|
|
if (value === undefined || value === null || value === '') {
|
|
return '';
|
|
}
|
|
|
|
const numeric = Number(value);
|
|
const formatted = Number.isFinite(numeric)
|
|
? numeric.toLocaleString(undefined, { maximumFractionDigits: 1 })
|
|
: value;
|
|
|
|
const unitPart = units ? ` ${units}` : '';
|
|
return `Steam Flow: ${formatted}${unitPart}`;
|
|
};
|
|
|
|
const initialiseTable = (table, state) => {
|
|
const id = table.dataset.boilerSection;
|
|
if (!id) {
|
|
return;
|
|
}
|
|
|
|
const headerRow = table.querySelector('tr');
|
|
const headerCell = headerRow ? headerRow.querySelector('td, th') : null;
|
|
if (!headerCell) {
|
|
return;
|
|
}
|
|
|
|
const title = (table.dataset.boilerTitle || headerCell.textContent || '').trim() || 'Boiler';
|
|
const steamValue = table.dataset.steamValue || '';
|
|
const steamUnits = table.dataset.steamUnits || '';
|
|
|
|
const targetId = table.id || `${id}-table`;
|
|
table.id = targetId;
|
|
|
|
let headerWrapper = headerCell.querySelector('.boiler-panel__header');
|
|
let toggleButton;
|
|
let summary;
|
|
|
|
if (!headerWrapper) {
|
|
headerWrapper = document.createElement('div');
|
|
headerWrapper.className = 'boiler-panel__header';
|
|
|
|
toggleButton = document.createElement('button');
|
|
toggleButton.type = 'button';
|
|
toggleButton.className = 'boiler-panel__toggle';
|
|
toggleButton.setAttribute('data-boiler-toggle', id);
|
|
toggleButton.setAttribute('aria-controls', targetId);
|
|
toggleButton.innerHTML = `
|
|
<span class="boiler-panel__title">${title}</span>
|
|
<span class="boiler-panel__indicator" aria-hidden="true"></span>
|
|
`;
|
|
|
|
summary = document.createElement('span');
|
|
summary.className = 'boiler-panel__summary';
|
|
summary.setAttribute('data-boiler-summary', '');
|
|
summary.textContent = formatSummary(steamValue, steamUnits);
|
|
|
|
headerWrapper.appendChild(toggleButton);
|
|
headerWrapper.appendChild(summary);
|
|
|
|
headerCell.innerHTML = '';
|
|
headerCell.appendChild(headerWrapper);
|
|
|
|
toggleButton.addEventListener('click', () => {
|
|
const nextCollapsed = !table.classList.contains('is-collapsed');
|
|
applyCollapsedState(table, nextCollapsed);
|
|
toggleButton.setAttribute('aria-expanded', (!nextCollapsed).toString());
|
|
state[id] = nextCollapsed;
|
|
saveState(state);
|
|
});
|
|
|
|
table.dataset.boilerInitialised = 'true';
|
|
} else {
|
|
toggleButton = headerWrapper.querySelector('.boiler-panel__toggle');
|
|
summary = headerWrapper.querySelector('[data-boiler-summary]');
|
|
}
|
|
|
|
if (toggleButton) {
|
|
toggleButton.setAttribute('aria-controls', targetId);
|
|
}
|
|
|
|
if (summary) {
|
|
summary.textContent = formatSummary(steamValue, steamUnits);
|
|
}
|
|
|
|
const collapsed = state[id] === true;
|
|
applyCollapsedState(table, collapsed);
|
|
if (toggleButton) {
|
|
toggleButton.setAttribute('aria-expanded', (!collapsed).toString());
|
|
}
|
|
};
|
|
|
|
const initialisePanel = (panel) => {
|
|
const state = loadState();
|
|
const tables = panel.querySelectorAll(TABLE_SELECTOR);
|
|
tables.forEach((table) => initialiseTable(table, state));
|
|
};
|
|
|
|
const handlePanelUpdate = (event) => {
|
|
if (!event || !event.currentTarget) {
|
|
return;
|
|
}
|
|
initialisePanel(event.currentTarget);
|
|
};
|
|
|
|
const setup = () => {
|
|
const panel = document.querySelector(PANEL_SELECTOR);
|
|
if (!panel) {
|
|
return;
|
|
}
|
|
|
|
panel.addEventListener('livepanel:updated', handlePanelUpdate);
|
|
|
|
if (panel.innerHTML.trim().length) {
|
|
initialisePanel(panel);
|
|
}
|
|
};
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', setup, { once: true });
|
|
} else {
|
|
setup();
|
|
}
|
|
})();
|