How to move nodes from a contentEditable div to another dynamically when its content exceed a x height?
Tags: javascript, html
Published: 2019-11-06 14:27:16

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