Last active
August 9, 2025 07:49
-
-
Save theinvensi/e1aacc43bb5a3d852e2e85b08cf85c8a to your computer and use it in GitHub Desktop.
Revisions
-
theinvensi renamed this gist
Dec 15, 2021 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
theinvensi created this gist
Dec 15, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,130 @@ class RepeatTableHeadersHandler extends Paged.Handler { constructor(chunker, polisher, caller) { super(chunker, polisher, caller) this.splitTablesRefs = [] } afterPageLayout(pageElement, page, breakToken, chunker) { this.chunker = chunker this.splitTablesRefs = [] if (breakToken) { const node = breakToken.node const tables = this.findAllAncestors(node, "table") if (node.tagName === "TABLE") tables.push(node) if (tables.length > 0) { this.splitTablesRefs = tables.map(t => t.dataset.ref) let thead = node.tagName === "THEAD" ? node : this.findFirstAncestor(node, "thead") if (thead) { let lastTheadNode = thead.hasChildNodes() ? thead.lastChild : thead breakToken.node = this.nodeAfter(lastTheadNode, chunker.source) } this.hideEmptyTables(pageElement, node) } } } hideEmptyTables(pageElement, breakTokenNode) { this.splitTablesRefs.forEach(ref => { let table = pageElement.querySelector("[data-ref='" + ref + "']") if (table) { let sourceBody = table.querySelector("tbody > tr") if (!sourceBody || this.refEquals(sourceBody.firstElementChild, breakTokenNode)) { table.style.visibility = "hidden" table.style.position = "absolute" let lineSpacer = table.nextSibling if (lineSpacer) { lineSpacer.style.visibility = "hidden" lineSpacer.style.position = "absolute" } } } }) } refEquals(a, b) { return a && a.dataset && b && b.dataset && a.dataset.ref === b.dataset.ref } findFirstAncestor(element, selector) { while (element.parentNode && element.parentNode.nodeType === 1) { if (element.parentNode.matches(selector)) return element.parentNode element = element.parentNode } return null } findAllAncestors(element, selector) { const ancestors = [] while (element.parentNode && element.parentNode.nodeType === 1) { if (element.parentNode.matches(selector)) ancestors.unshift(element.parentNode) element = element.parentNode } return ancestors } layout(rendered, layout) { this.splitTablesRefs.forEach(ref => { const renderedTable = rendered.querySelector("[data-ref='" + ref + "']") if (renderedTable) { if (!renderedTable.getAttribute("repeated-headers")) { const sourceTable = this.chunker.source.querySelector("[data-ref='" + ref + "']") this.repeatColgroup(sourceTable, renderedTable) this.repeatTHead(sourceTable, renderedTable) renderedTable.setAttribute("repeated-headers", true) } } }) } repeatColgroup(sourceTable, renderedTable) { let colgroup = sourceTable.querySelectorAll("colgroup") let firstChild = renderedTable.firstChild colgroup.forEach((colgroup) => { let clonedColgroup = colgroup.cloneNode(true) renderedTable.insertBefore(clonedColgroup, firstChild) }) } repeatTHead(sourceTable, renderedTable) { let thead = sourceTable.querySelector("thead") if (thead) { let clonedThead = thead.cloneNode(true) renderedTable.insertBefore(clonedThead, renderedTable.firstChild) } } nodeAfter(node, limiter) { if (limiter && node === limiter) return let significantNode = this.nextSignificantNode(node) if (significantNode) return significantNode if (node.parentNode) { while ((node = node.parentNode)) { if (limiter && node === limiter) return significantNode = this.nextSignificantNode(node) if (significantNode) return significantNode } } } nextSignificantNode(sib) { while ((sib = sib.nextSibling)) { if (!this.isIgnorable(sib)) return sib } return null } isIgnorable(node) { return ( (node.nodeType === 8) || ((node.nodeType === 3) && this.isAllWhitespace(node)) ) } isAllWhitespace(node) { return !(/[^\t\n\r ]/.test(node.textContent)) } } Paged.registerHandlers(RepeatTableHeadersHandler)