DEV Community

celsowm
celsowm

Posted on

How to move nodes from a contentEditable div to another dynamically when its content exceed a x height?

I am trying to prototype a simple wyswyg that emulate the concept of A4 pages using contentEditable divs.
So my current code is this:

HTML:

<div id="editor">
            <div contenteditable="true" class="page" id="page-1">
                <b>hello</b>
            </div>
        </div>

CSS:

#editor{
                background-color: gray;
                border: 1px black;
                padding: 1em 2em;
            }
            .page{
                background-color: white;
                border: solid black;
                padding: 1em 2em; 
                width:595px;
                height:841px;
                word-wrap: break-word;
                overflow-wrap: break-word;
                white-space: normal;
            }

JS:

//force br
document.execCommand("DefaultParagraphSeparator", false, "br");
const a4 = {
    height: 841,
    width: 595
};
document.getElementById('editor').addEventListener('input', function(e) {
    let getChildrenHeight = function(element) {
        total = 0;
        if (element.childNodes) {
            for (let child of element.childNodes) {
                switch (child.nodeType) {
                    case Node.ELEMENT_NODE:
                        total += child.offsetHeight;
                        break;
                    case Node.TEXT_NODE:
                        let range = document.createRange();
                        range.selectNodeContents(child);
                        rect = range.getBoundingClientRect();
                        total += (rect.bottom - rect.top);
                        break;
                }
            }
        }
        return total;
    };
    let pages = document.getElementsByClassName('page');
    for (let i in pages) {
        let page = pages[i];
        //remove empty page    
        if (page.offsetHeight == 0 && i > 1) {
            page.remove();
        }
        let childrenHeight = getChildrenHeight(page);
        while (childrenHeight > a4.height) {
            //recursively try to fit elements on max size 
            //removing/pushing excedents elements to the next div (aka page)
            let excedents = [];
            let children = page.childNodes;
            let children_length = children.length - 1;
            let backup = children[children_length].cloneNode(true);
            children[children_length].remove();
            if (pages.item(i + 1) === null) {
                var newPage = page.cloneNode(true);
                newPage.innerHTML = '';
                newPage.appendChild(backup);
                page.parentNode.appendChild(newPage);
            } else {
                page.item(i + 1).insertBefore(backup, page.item(i + 1).childNodes[0]);
            }
            //console.log(children[i].innerHTML);
        }
    }
});

Unfortunately, the result is not as I was expecting.
When the height of one page is exceeded, all content from the first page is removed, not like I would like:

  1. the excess to be moved to next page.
  2. and when a page is abscent of children, been removed.

Something like a very very primitive Microsoft Word multipages editor.

How to do that?
Thanks in advance
Celso

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay