prima bozza sito sindacato

This commit is contained in:
vecna 2026-04-20 18:33:22 +02:00
commit 59ef4db64f
31 changed files with 1576 additions and 0 deletions

153
assets/js/csv-tables.js Normal file
View file

@ -0,0 +1,153 @@
(function () {
'use strict';
function parseCsv(text) {
var rows = [];
var row = [];
var field = '';
var i = 0;
var inQuotes = false;
while (i < text.length) {
var ch = text[i];
if (inQuotes) {
if (ch === '"') {
if (text[i + 1] === '"') {
field += '"';
i += 2;
continue;
}
inQuotes = false;
i += 1;
continue;
}
field += ch;
i += 1;
continue;
}
if (ch === '"') {
inQuotes = true;
i += 1;
continue;
}
if (ch === ',') {
row.push(field);
field = '';
i += 1;
continue;
}
if (ch === '\n') {
row.push(field);
rows.push(row);
row = [];
field = '';
i += 1;
continue;
}
if (ch === '\r') {
i += 1;
continue;
}
field += ch;
i += 1;
}
if (field.length > 0 || row.length > 0) {
row.push(field);
rows.push(row);
}
return rows.filter(function (r) {
return r.length > 1 || (r.length === 1 && r[0].trim() !== '');
});
}
function buildTable(headers, dataRows) {
var table = document.createElement('table');
table.className = 'csv-table__table';
var thead = document.createElement('thead');
var headRow = document.createElement('tr');
headers.forEach(function (h) {
var th = document.createElement('th');
th.textContent = h;
headRow.appendChild(th);
});
thead.appendChild(headRow);
table.appendChild(thead);
var tbody = document.createElement('tbody');
dataRows.forEach(function (r) {
var tr = document.createElement('tr');
headers.forEach(function (_, idx) {
var td = document.createElement('td');
td.textContent = r[idx] !== undefined ? r[idx] : '';
tr.appendChild(td);
});
tbody.appendChild(tr);
});
table.appendChild(tbody);
return table;
}
function renderCsvTable(container) {
var src = container.getAttribute('data-src');
var countEl = container.querySelector('[data-csv-count]');
var statusEl = container.querySelector('[data-csv-status]');
var viewport = container.querySelector('[data-csv-viewport]');
if (!src || !viewport || !statusEl || !countEl) {
return;
}
fetch(src)
.then(function (response) {
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
return response.text();
})
.then(function (csvText) {
var rows = parseCsv(csvText);
if (rows.length === 0) {
statusEl.textContent = 'CSV vuoto.';
countEl.textContent = 'Righe: 0';
return;
}
var headers = rows[0];
var dataRows = rows.slice(1);
var table = buildTable(headers, dataRows);
viewport.innerHTML = '';
viewport.appendChild(table);
countEl.textContent = 'Righe: ' + dataRows.length;
})
.catch(function (error) {
statusEl.textContent = 'Impossibile caricare il CSV (' + error.message + ').';
countEl.textContent = 'Righe: n/d';
});
}
function initCsvTables() {
var containers = document.querySelectorAll('[data-csv-table]');
containers.forEach(renderCsvTable);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCsvTables);
} else {
initCsvTables();
}
})();

106
assets/js/sidenotes.js Normal file
View file

@ -0,0 +1,106 @@
/**
* sidenotes.js
* Takes Hugo-rendered Goldmark footnotes and repositions them
* as margin notes alongside the text that references them.
*
* Hugo/Goldmark renders footnotes as:
* - References: <sup id="fnref:N"><a href="#fn:N">N</a></sup>
* or <sup id="fnref1:N"><a href="#fn:N">N</a></sup> (for duplicate refs)
* - Section: <section class="footnotes"> <ol> <li id="fn:N"> </li> </ol> </section>
*/
(function () {
'use strict';
const MARGIN_TOP_PX = 12; // minimum vertical gap between sidenotes
function initSidenotes() {
const container = document.querySelector('.sidenote-layout .content-body');
if (!container) return;
const footnotesSection = container.querySelector('.footnotes, section.footnotes');
if (!footnotesSection) return;
// Collect all footnote reference <sup> elements
const refs = container.querySelectorAll('sup[id^="fnref"]');
if (refs.length === 0) return;
// Check viewport: skip sidenote placement on narrow screens
if (window.innerWidth < 900) {
container.classList.add('sidenotes-fallback');
footnotesSection.style.display = '';
return;
}
let lastBottom = 0;
refs.forEach(function (sup) {
// Get the footnote id from the <a> inside the <sup>
const anchor = sup.querySelector('a[href^="#fn"]');
if (!anchor) return;
const fnId = anchor.getAttribute('href').replace('#', '');
const footnoteLi = footnotesSection.querySelector('#' + CSS.escape(fnId));
if (!footnoteLi) return;
// Extract footnote content (skip the back-reference link)
const clone = footnoteLi.cloneNode(true);
const backlinks = clone.querySelectorAll('.footnote-backref, a[href^="#fnref"]');
backlinks.forEach(function (bl) { bl.remove(); });
const noteHTML = clone.innerHTML.trim();
// Extract footnote number from the sup text
const noteNumber = anchor.textContent.trim();
// Create sidenote element
const sidenote = document.createElement('span');
sidenote.className = 'sidenote';
sidenote.setAttribute('role', 'note');
sidenote.innerHTML =
'<span class="sidenote-number">' + noteNumber + '.</span> ' + noteHTML;
// Append to content-body (absolutely positioned)
container.appendChild(sidenote);
// Position vertically aligned with the reference
const containerRect = container.getBoundingClientRect();
const supRect = sup.getBoundingClientRect();
let desiredTop = supRect.top - containerRect.top;
// Prevent overlap with previous sidenote
if (desiredTop < lastBottom + MARGIN_TOP_PX) {
desiredTop = lastBottom + MARGIN_TOP_PX;
}
sidenote.style.top = desiredTop + 'px';
// Track the bottom of this sidenote for collision avoidance
lastBottom = desiredTop + sidenote.offsetHeight;
});
// Hide the original footnotes section
footnotesSection.style.display = 'none';
}
// Run on load
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initSidenotes);
} else {
initSidenotes();
}
// Re-run on resize (debounced)
let resizeTimer;
window.addEventListener('resize', function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
// Remove existing sidenotes and re-init
document.querySelectorAll('.sidenote').forEach(function (el) { el.remove(); });
const fs = document.querySelector('.sidenote-layout .content-body .footnotes, .sidenote-layout .content-body section.footnotes');
if (fs) fs.style.display = '';
var fb = document.querySelector('.sidenotes-fallback');
if (fb) fb.classList.remove('sidenotes-fallback');
initSidenotes();
}, 250);
});
})();