Files
Tectum/js/core/pdf-sheet.js
T

134 lines
4.7 KiB
JavaScript

/*!
* Tectum
* Copyright © 2026 Machiel Heinen.
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
* Zie LICENTIE.md.
*/
window.PdfSheet = (() => {
const COLORS = { RED: [190, 25, 25], BLUE: [25, 50, 180], BLACK: [0, 0, 0], GREY: [130, 130, 130] };
const PROJECT_DOM_IDS = {
naam: 'inp-proj-naam', plaats: 'inp-proj-plaats', straat: 'inp-proj-straat', nummer: 'inp-proj-nummer',
tekenaar: 'inp-proj-tekenaar', titel: 'inp-proj-titel', element: 'inp-proj-element', opmerking: 'inp-proj-opmerking'
};
// generate() is synchroon: afbeeldingen vooraf laden met preloadImage.
const imageCache = {};
function preloadImage(url) {
if (!url || url in imageCache || typeof Image === 'undefined' || typeof document === 'undefined') return;
imageCache[url] = null;
const img = new Image();
img.onload = () => {
try {
const c = document.createElement('canvas');
c.width = img.naturalWidth; c.height = img.naturalHeight;
c.getContext('2d').drawImage(img, 0, 0);
imageCache[url] = c.toDataURL('image/png');
} catch (e) { }
};
img.src = url;
}
const imageData = (url) => (url && imageCache[url]) || null;
function createDoc() {
const { jsPDF } = window.jspdf;
return new jsPDF({ orientation: 'landscape', unit: 'mm', format: 'a3' });
}
function readProjectFromDom() {
const project = {};
Object.entries(PROJECT_DOM_IDS).forEach(([key, id]) => {
const el = document.getElementById(id);
project[key] = (el && el.value) || '';
});
return project;
}
const DIM_TICK = 1.5;
function dimLine(doc, x1, y1, x2, y2) {
doc.line(x1, y1, x2, y2);
const dx = x2 - x1, dy = y2 - y1;
const len = Math.hypot(dx, dy) || 1;
const tx = (-dy / len) * (DIM_TICK / 2), ty = (dx / len) * (DIM_TICK / 2);
doc.line(x1 - tx, y1 - ty, x1 + tx, y1 + ty);
doc.line(x2 - tx, y2 - ty, x2 + tx, y2 + ty);
}
function titleBlock(doc, project, opts) {
const { BLACK, GREY } = COLORS;
const p = project || {};
const o = opts || {};
const tbW = 118, tbH = 36;
const tbX0 = 290, tbY0 = 289 - tbH;
doc.setDrawColor(...BLACK);
doc.setLineWidth(0.25);
doc.rect(tbX0, tbY0, tbW, tbH, 'S');
const today = new Date().toLocaleDateString('nl-NL');
const columns = [
[['Projectnaam:', p.naam], ['Plaats:', p.plaats], ['Straat:', p.straat], ['Projectnummer:', p.nummer], ['Tekenaar:', p.tekenaar]],
[['Titel:', o.titel], ['Element nummer:', o.element], ['Datum getekend:', today], ['Schaal:', '1:1'], ['Opmerking:', p.opmerking]]
];
const colW = tbW / 2, labelW = 19;
doc.setFontSize(6.2);
columns.forEach((rows, c) => {
const x = tbX0 + 3 + c * colW;
let rowY = tbY0 + 5;
rows.forEach(([label, value]) => {
doc.setTextColor(...GREY);
doc.text(label, x, rowY);
doc.setTextColor(...BLACK);
const text = String(value || '-');
doc.text(doc.splitTextToSize(text, colW - labelW - 5)[0], x + labelW, rowY);
rowY += 4.2;
});
});
const stripY = tbY0 + 25;
doc.setDrawColor(...GREY);
doc.setLineWidth(0.15);
doc.line(tbX0, stripY, tbX0 + tbW, stripY);
if (o.blad) {
doc.setTextColor(...GREY);
doc.setFontSize(6);
doc.text('Blad ' + o.blad, tbX0 + 3, tbY0 + tbH - 3.5);
}
const logoH = 7.5, logoW = logoH * (window.TECTUM_LOGO ? window.TECTUM_LOGO.aspect : 4.55);
if (window.TECTUM_LOGO) {
doc.addImage(window.TECTUM_LOGO.png, 'PNG', tbX0 + tbW - 3 - logoW, tbY0 + tbH - 2 - logoH, logoW, logoH, 'tectum-logo', 'FAST'); // alias: logo 1x in het bestand
} else {
doc.setTextColor(...GREY);
doc.setFontSize(6);
doc.text('Van Emous Mantelzorgwoningen', tbX0 + tbW - 3, tbY0 + tbH - 3.5, { align: 'right' });
}
}
function table(doc, x, y, colX, headers, rows, opts) {
const { BLACK, GREY } = COLORS;
const o = opts || {};
const rowH = o.rowH || 4.3;
doc.setTextColor(...BLACK);
if (o.title) {
doc.setFontSize(o.titleSize || 9);
doc.text(o.title, x, y);
y += 6;
}
doc.setFontSize(o.fontSize || 6.5);
headers.forEach((h, i) => doc.text(h, x + colX[i], y));
y += 1.5;
doc.setDrawColor(...GREY);
doc.setLineWidth(0.15);
doc.line(x, y, x + colX[colX.length - 1] + (o.lastColW || 14), y);
y += 4;
rows.forEach(r => {
if (o.maxY && y > o.maxY) return;
r.forEach((v, i) => doc.text(String(v), x + colX[i], y, i > 0 && o.alignRight ? { align: 'right' } : undefined));
y += rowH;
});
return y;
}
return { COLORS, preloadImage, imageData, createDoc, readProjectFromDom, dimLine, titleBlock, table };
})();