Create pages dynamically in a GrapesJS editor

134 views Asked by At

I'd like to make my GrapesJS editor simulate pages, i.e. it creates a second page if the component placed in the first page doesn't have room in the first, a bit like any text editor, like Word or Google Docs. I've tried lots of things, to no avail. Do you have any ideas or is there a plugin for this that I haven't found? Thanks in advance

Here's what I've tried so far, creating a rectangle in the same colour as the background, trying to move the elements underneath but it's too complex for me.


const PAGE_HEIGHT = 1030; // Hauteur de la page sans les marges
const PDF_TOP_MARGIN = 10; // Ajustez en fonction des marges de votre PDF
const PDF_BOTTOM_MARGIN = 10; // Ajustez en fonction des marges de votre PDF

function simulatePagination() {
    const iframeBody = editor.Canvas.getBody();
    const components = editor.DomComponents.getWrapper().components();

    // Supprimer les séparateurs de page précédents pour recalculer
    iframeBody.querySelectorAll('.page-break').forEach(el => el.remove());

    let currentPage = 1;
    let cumulativeHeight = PDF_TOP_MARGIN; // Commencez avec la marge supérieure du PDF

    components.each((component) => {
        const componentEl = component.getEl();
        const style = window.getComputedStyle(componentEl);
        const componentHeight = componentEl.offsetHeight +
            parseFloat(style.marginTop) +
            parseFloat(style.marginBottom) +
            parseFloat(style.paddingTop) +
            parseFloat(style.paddingBottom);
        const componentTop = componentEl.offsetTop;
        const componentBottom = componentTop + componentHeight - cumulativeHeight;


        if (componentBottom > PAGE_HEIGHT - PDF_BOTTOM_MARGIN) {
            const pageBreakDiv = document.createElement('div');
            pageBreakDiv.classList.add('page-break');
            pageBreakDiv.style.width = '100%';
            pageBreakDiv.style.height = '10px';
            pageBreakDiv.style.backgroundColor = '#f2f2f2';
            pageBreakDiv.style.position = 'absolute';
            pageBreakDiv.style.top = `${PAGE_HEIGHT * currentPage - PDF_BOTTOM_MARGIN}px`;
            iframeBody.appendChild(pageBreakDiv);

            currentPage++;
            cumulativeHeight += PAGE_HEIGHT * (currentPage - 1) + PDF_TOP_MARGIN;
            console.log("======");
            console.log("cumulativeHeight: ", cumulativeHeight);


            //   Nouvelle marge supérieure pour positionner le composant en début de la prochaine page
            const newMarginTop = PAGE_HEIGHT - (componentBottom - componentHeight) + PDF_TOP_MARGIN;
            console.log("componentTop: ", componentTop);
            console.log("PAGE_HEIGHT: ", PAGE_HEIGHT);
            console.log("componentBottom: ", componentBottom);
            console.log("componentHeight: ", componentHeight);
            console.log("PDF_TOP_MARGIN: ", PDF_TOP_MARGIN);

            componentEl.style.marginTop = `${newMarginTop}px`;
            console.log("Nouvelle marge supérieure: ", newMarginTop);
            console.log("componentEl: ", componentEl);

            console.log("======");
        }
    });
}

//   Appeler simulatePagination lors du chargement initial
editor.on('load component:add', () => {
    if (window.innerWidth > 768) {
        console.log("window.innerWidth: ", window.innerWidth);
        simulatePagination();
    }
});

// Appeler simulatePagination lorsque les composants sont ajoutés ou mis à jour
editor.on('component:add', (component) => {
    // if (!component.parent() || component.parent().get('type') === 'wrapper') {
    if (window.innerWidth > 768) {
        simulatePagination();
        // }
    }
});
editor.on('component:update', simulatePagination);
0

There are 0 answers