Folder reorganize 1
This commit is contained in:
158
assets/js/boiler-panels.js
Normal file
158
assets/js/boiler-panels.js
Normal file
@@ -0,0 +1,158 @@
|
||||
(() => {
|
||||
const PANEL_SELECTOR = '[data-refresh-url="data/boilers.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 'Steam Flow: —';
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user