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

Top comments (0)