diff options
Diffstat (limited to '')
-rw-r--r-- | public/js/layout-plugins/page-breaker.js | 44 | ||||
-rw-r--r-- | public/js/layout.js | 32 |
2 files changed, 76 insertions, 0 deletions
diff --git a/public/js/layout-plugins/page-breaker.js b/public/js/layout-plugins/page-breaker.js new file mode 100644 index 0000000..bdf04ec --- /dev/null +++ b/public/js/layout-plugins/page-breaker.js @@ -0,0 +1,44 @@ +/* Icinga PDF Export | (c) 2021 Icinga GmbH | GPLv2 */ + +"use strict"; + +(() => { + Layout.registerPlugin('page-breaker', () => { + let pageBreaksFor = document.querySelector('[data-pdfexport-page-breaks-at]'); + if (! pageBreaksFor) { + return; + } + + let pageBreaksAt = pageBreaksFor.dataset.pdfexportPageBreaksAt; + if (! pageBreaksAt) { + return; + } + + let contentHeight = document.body.dataset.contentHeight; + let items = Array.from(pageBreaksFor.querySelectorAll(':scope > ' + pageBreaksAt)); + + let remainingHeight = contentHeight; + items.forEach((item, i) => { + let requiredHeight; + if (i < items.length - 1) { + requiredHeight = items[i + 1].getBoundingClientRect().top - item.getBoundingClientRect().top; + } else { + requiredHeight = item.parentElement.getBoundingClientRect().bottom - item.getBoundingClientRect().top; + } + + if (remainingHeight < requiredHeight) { + if (!! item.previousElementSibling) { + item.previousElementSibling.style.pageBreakAfter = 'always'; + item.previousElementSibling.classList.add('page-break-follows'); + } else { + item.style.pageBreakAfter = 'always'; + item.classList.add('page-break-follows'); + } + + remainingHeight = contentHeight; + } + + remainingHeight -= requiredHeight; + }); + }); +})(); diff --git a/public/js/layout.js b/public/js/layout.js new file mode 100644 index 0000000..0ea5d64 --- /dev/null +++ b/public/js/layout.js @@ -0,0 +1,32 @@ +/* Icinga PDF Export | (c) 2021 Icinga GmbH | GPLv2 */ + +"use strict"; + +class Layout +{ + static #plugins = []; + + static registerPlugin(name, plugin) { + this.#plugins.push([name, plugin]); + } + + apply() { + for (let [name, plugin] of Layout.#plugins) { + try { + plugin(); + } catch (error) { + console.error('Layout plugin ' + name + ' failed to run: ' + error); + } + } + + this.finish(); + } + + finish() { + document.documentElement.dataset.layoutReady = 'yes'; + document.dispatchEvent(new CustomEvent('layout-ready', { + cancelable: false, + bubbles: false + })); + } +} |