October 21, 2024
Chicago 12, Melborne City, USA
HTML

Splitting one long page into multiple pages


I am working on documents that can be many pages long with many different formatting variables.
Most of the work is done in deeply nested OL tags and tables.
Some of the ol tags use classes to split between grid 2 (1fr 1fr) while some stay block level.
I need logic that can split the pages without overflow, while keeping a specified footer.
This is using Angular.

Note: The HTML is wrapped in the component, and passes ID number and rightstext (disclaimer) which is used as a ocnsistent footer across pages.

Ive attempted to use paginatino logic on a single page to split it across the same page.

import {
    Component,
    AfterViewInit,
    ElementRef,
    ViewChild,
    Input,
} from "@angular/core";

@Component({
    selector: "app-dynamic-form-page",
    templateUrl: "./dynamic-form-page.component.html",
    styleUrls: [
        "/src/assets/styles/forms.scss",
        "./dynamic-form-page.component.scss",
    ],
})
export class DynamicFormPageComponent implements AfterViewInit {
    @Input() formId: string = "";
    @Input() rightsText: string = ""; //For footers
    @ViewChild("fullContent", { static: false }) fullContent: ElementRef;

    constructor() {}
    pages: string[] = []; // Array to hold pages of content
    readonly totalPageHeight = 1056;
    readonly pagePadding = 192;
    readonly pageHeight = this.totalPageHeight - this.pagePadding;

    ngAfterViewInit() {
        this.paginateContent(); // Call the pagination logic after the view is initialized
    }

    paginateContent() {
        const contentElement = this.fullContent.nativeElement; // The content to paginate
        let currentPageContent = ""; // Store content for each page
        let currentHeight = 0; // Track the current page height
        const parentElement = document.createElement("div"); // Simulated page
        parentElement.style.width = "8.5in";
        parentElement.style.height = "11in";
        parentElement.style.position = "absolute"; // Off-screen element
        parentElement.style.visibility = "hidden";
        document.body.appendChild(parentElement); // Add off-screen for height calculations
        let tempContainer = document.createElement("div");
        tempContainer.innerHTML = contentElement.innerHTML; // Load all content into a temporary container
        while (tempContainer.firstChild) {
            const nextElement = tempContainer.firstChild;
            // Only handle element nodes
            if (nextElement.nodeType === 1) {
                const clonedElement = nextElement.cloneNode(true) as HTMLElement;
                parentElement.appendChild(clonedElement); // Add clone to simulate the page
                const elementHeight = clonedElement.offsetHeight; // Get height of the current element
                console.log(
                    "Current element:",
                    clonedElement.outerHTML.slice(0, 100),
                    "Height:",
                    elementHeight,
                );
                // Handle large elements: if an element is too big for the page, move it to the next page
                if (elementHeight > this.pageHeight) {
                    console.log("Large element detected. Moving it to the next page.");
                    this.pages.push(`${currentPageContent}`); // Push the current page content
                    currentPageContent = ""; // Start fresh for the next page
                    parentElement.innerHTML = ""; // Clear simulated container
                    currentHeight = 0; // Reset height
                    currentPageContent += (nextElement as HTMLElement).outerHTML; // Start the next page with this element
                    currentHeight = elementHeight; // Set the height for the new page
                    tempContainer.removeChild(nextElement); // Remove the processed element
                    continue;
                }
                // If adding this element exceeds the page height, create a new page
                if (currentHeight + elementHeight > this.pageHeight) {
                    this.pages.push(`${currentPageContent}`); // Save the content for this page
                    console.log(
                        `Page ${this.pages.length + 1} created. Content length: ${
                            currentPageContent.length
                        }`,
                    );
                    currentPageContent = ""; // Start fresh for the next page
                    parentElement.innerHTML = ""; // Clear the simulated page container
                    currentHeight = 0; // Reset height for the new page
                }
                // Accumulate the outerHTML of the current element into the page content
                currentPageContent += (nextElement as HTMLElement).outerHTML;
                currentHeight += elementHeight; // Update the current height
            }
            // Remove the processed element from tempContainer
            tempContainer.removeChild(nextElement); // Clean up the original content
        }
        // Ensure the final page is added, even if it's not a full page
        if (currentPageContent.trim().length > 0) {
            this.pages.push(`${currentPageContent}`); // Push the last page
            console.log(`Final page created. Total pages: ${this.pages.length}`);
        }
        // Remove the simulated element from the DOM
        document.body.removeChild(parentElement);
        // Add footers to all pages
        const totalPages = this.pages.length;
        this.pages = this.pages.map((pageContent, index) =>
            this.addFooter(pageContent, index, totalPages),
        );
    }

    addFooter(content: string, pageIndex: number, totalPages: number): string {
        return `
      <div class="page-content">
        ${content}
        <div class="dynamic-footer">
          <table>
            <tr>
              <td class="td2 left bold">${this.formId}</td>
              <td class="disclaimer td3">${this.rightsText}</td>
              <td class="td2 right bold">Page ${
                                pageIndex + 1
                            } of ${totalPages}</td>
            </tr>
          </table>
        </div>
      </div>
    `;
    }
}

The issue with this, even though the styling for the double list remains intact, is that the ol elements nested will overflow outside of the page.
I’ve attempted splitting the ol>li elements nested into their own elements, but that removed the needed styling and created some overflow on the pages still.



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video