当内容超过 x 高度时,如何将节点从 contentEditable div 动态移动到另一个?
How to move nodes from a contentEditable div to another dynamically when its content exceed a x height?
我正在尝试制作一个简单的 wyswyg 原型,它使用 contentEditable div 模拟 A4 页面的概念。
所以我当前的代码是这样的:
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);
}
}
});
不幸的是,结果并不如我所料。
当超过一页的高度时,第一页的所有内容都会被删除,不像我想的那样:
- 超出部分移至下一页。
- 并且当页面缺少子项时,将被删除。
类似于非常非常原始的 Microsoft Word 多页编辑器。
怎么做?
提前致谢
塞尔索
您的代码是一个良好的开端,但还有一些问题需要解决:
- 您正在尝试使用 for..in 循环遍历 HTMLCollection,这将访问集合中的
length
、item
和 namedItem
(只需尝试 for(let i in document.getElementsByClassName('page')) console.log(i);
在控制台中)
您正尝试在 offsetHeight
为 0 时删除空白页,请尝试 childrenHeight
你可以用 if 语句交换 while 循环
- 您还必须检查当前页面上是否有足够的空间,以便从下一页拉回行
- 此外,您必须手动处理分页符上的光标位置
我做了一个 codepen 来演示我建议的更改。它远非完美,但可以处理页面删除和多余删除。
我正在尝试制作一个简单的 wyswyg 原型,它使用 contentEditable div 模拟 A4 页面的概念。 所以我当前的代码是这样的:
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);
}
}
});
不幸的是,结果并不如我所料。 当超过一页的高度时,第一页的所有内容都会被删除,不像我想的那样:
- 超出部分移至下一页。
- 并且当页面缺少子项时,将被删除。
类似于非常非常原始的 Microsoft Word 多页编辑器。
怎么做? 提前致谢 塞尔索
您的代码是一个良好的开端,但还有一些问题需要解决:
- 您正在尝试使用 for..in 循环遍历 HTMLCollection,这将访问集合中的
length
、item
和namedItem
(只需尝试for(let i in document.getElementsByClassName('page')) console.log(i);
在控制台中) 您正尝试在
offsetHeight
为 0 时删除空白页,请尝试childrenHeight
你可以用 if 语句交换 while 循环
- 您还必须检查当前页面上是否有足够的空间,以便从下一页拉回行
- 此外,您必须手动处理分页符上的光标位置
我做了一个 codepen 来演示我建议的更改。它远非完美,但可以处理页面删除和多余删除。