1(function (window, document) {
4 if (!window.dbx) window.dbx = {};
6 /* =========================================================
8 ========================================================= */
10 dbx.print = function (configString) {
12 if (dbx._printing === true) {
13 dbx.log("warn", "[dbx.print] already printing");
17 if (!configString || typeof configString !== "string") {
18 dbx.log("warn", "[dbx.print] Missing selector");
22 const parsed = parseConfig(configString);
24 const original = document.querySelector(parsed.selector);
26 dbx.log("warn", "[dbx.print] Selector not found:", parsed.selector);
32 const clone = original.cloneNode(true);
33 clone.querySelectorAll(".noPrint").forEach(el => el.remove());
35 removeIfExists("dbx-print-root");
36 removeIfExists("dbx-print-style");
38 const root = document.createElement("div");
39 root.id = "dbx-print-root";
41 root.style.fontFamily = parsed.font;
42 root.style.fontSize = parsed.fontsize;
43 root.style.lineHeight = parsed.lineheight;
45 root.appendChild(clone);
46 document.body.appendChild(root);
48 document.body.classList.add("dbx-printing");
50 applyTableCompaction(root, parsed);
52 /* 🔥 APPLY DYNAMIC PAGE PADDING (PRINT) */
53 const pages = root.querySelectorAll(".print-page");
55 pages.forEach((page, index) => {
57 const parts = parsed.margin.split(" ");
59 let pt = parts[0] || "0";
60 let pr = parts[1] || parts[0] || "0";
61 let pb = parts[2] || parts[0] || "0";
62 let pl = parts[3] || parts[1] || parts[0] || "0";
68 page.style.paddingTop = pt;
69 page.style.paddingRight = pr;
70 page.style.paddingBottom = pb;
71 page.style.paddingLeft = pl;
74 const style = document.createElement("style");
75 style.id = "dbx-print-style";
76 style.media = "print";
80 size: ${parsed.format} ${parsed.orientation};
85 document.head.appendChild(style);
87 setTimeout(() => window.print(), 60);
89 const cleanup = function () {
91 document.body.classList.remove("dbx-printing");
93 removeIfExists("dbx-print-root");
94 removeIfExists("dbx-print-style");
96 dbx._printing = false;
98 window.removeEventListener("afterprint", cleanup);
101 window.addEventListener("afterprint", cleanup);
105 /* =========================================================
107 ========================================================= */
109 function applyScreenMode(parsed) {
111 const target = document.querySelector(parsed.selector);
114 target.classList.add("dbx-screen-preview");
116 target.style.fontFamily = parsed.font;
117 target.style.fontSize = parsed.fontsize;
118 target.style.lineHeight = parsed.lineheight;
120 applyTableCompaction(target, parsed);
122 target.querySelectorAll(".print-page").forEach(page => {
124 const parts = parsed.margin.split(" ");
126 page.style.paddingTop = parts[0] || "0";
127 page.style.paddingRight = parts[1] || parts[0] || "0";
128 page.style.paddingBottom = parts[2] || parts[0] || "0";
129 page.style.paddingLeft = parts[3] || parts[1] || parts[0] || "0";
131 page.classList.remove("a4","a5","portrait","landscape");
133 page.classList.add(parsed.format.toLowerCase());
134 page.classList.add(parsed.orientation.toLowerCase());
139 /* =========================================================
140 TABLE COMPACTION ENGINE
141 ========================================================= */
143 function applyTableCompaction(container, parsed) {
145 let fontSizePx = parseFloat(parsed.fontsize) || 10;
147 let padding = parsed.padding;
148 let rowheight = parsed.rowheight;
149 let lineheight = parsed.lineheight;
151 if (padding !== null) {
152 if (!String(padding).includes("px")) {
153 padding = padding + "px";
157 if (rowheight !== null && rowheight !== "auto") {
158 if (!String(rowheight).includes("px")) {
159 rowheight = rowheight + "px";
163 if (parsed.compact === true) {
165 padding = Math.max(0, Math.floor(fontSizePx * 0.15)) + "px";
167 rowheight = Math.floor(fontSizePx * 1.2) + "px";
170 if (rowheight === "auto") {
172 let lh = parseFloat(lineheight) || 1.2;
173 let pad = parseFloat(padding) || 0;
175 let calc = Math.ceil(fontSizePx * lh + (pad * 2));
177 rowheight = calc + "px";
181 container.querySelectorAll("tr").forEach(tr => {
182 tr.style.height = rowheight;
186 container.querySelectorAll("td, th").forEach(cell => {
188 if (padding !== null) {
189 cell.style.padding = padding;
193 cell.style.lineHeight = lineheight;
199 /* =========================================================
201 ========================================================= */
203 function parseConfig(configString) {
205 const parts = configString.split("|").map(p => p.trim());
206 const selector = parts[0];
210 orientation: "portrait",
225 for (let i = 1; i < parts.length; i++) {
227 const [key, value] = parts[i].split("=").map(p => p.trim());
230 switch (key.toLowerCase()) {
233 options.format = value.toUpperCase();
237 options.orientation = value.toLowerCase();
241 options.margin = value || "10mm";
245 options.margin_top = value;
249 options.margin_right = value;
252 case "margin_bottom":
253 options.margin_bottom = value;
257 options.margin_left = value;
261 options.font = (value || "").toLowerCase() === "ariel" ? "Arial" : value;
265 options.fontsize = value;
269 options.lineheight = value;
273 options.rowheight = value;
277 options.padding = value;
281 options.compact = value === "1" || value === "true";
285 options.screen = value === "1" || value === "true";
290 let marginFinal = options.margin;
293 options.margin_top !== null ||
294 options.margin_right !== null ||
295 options.margin_bottom !== null ||
296 options.margin_left !== null
298 const mt = options.margin_top || options.margin || "10mm";
299 const mr = options.margin_right || options.margin || "10mm";
300 const mb = options.margin_bottom || options.margin || "10mm";
301 const ml = options.margin_left || options.margin || "10mm";
303 marginFinal = `${mt} ${mr} ${mb} ${ml}`;
308 format: options.format,
309 orientation: options.orientation,
312 fontsize: options.fontsize,
313 lineheight: options.lineheight,
314 rowheight: options.rowheight,
315 padding: options.padding,
316 compact: options.compact,
317 screen: options.screen
321 function removeIfExists(id) {
322 const el = document.getElementById(id);
327 /* =========================================================
329 ========================================================= */
331 if (window.dbx && dbx.feature) {
333 dbx.feature.register("print", {
335 scope: "element", // 🔥 FIX
337 // 🔥 CSS über PREPARE
339 ['css', 'design', 'c-print.css']
349 el.__dbxInitialized = el.__dbxInitialized || {};
350 if (el.__dbxInitialized["print"]) return;
351 el.__dbxInitialized["print"] = true;
353 let target = config.target || config.selector;
356 const container = el.closest("[id]");
358 target = "#" + container.id;
363 dbx.warn("[dbx.print] No target defined.");
367 let configString = target;
369 Object.keys(config).forEach(function (key) {
371 if (key === "target" || key === "selector" || key === "id")
374 configString += "|" + key + "=" + config[key];
377 const parsed = parseConfig(configString);
379 if (parsed.screen === true) {
380 applyScreenMode(parsed);
383 el.addEventListener("click", function (e) {
385 dbx.print(configString);