我正在尝试在内容可编辑 = true 的动态生成的 div 上“模拟”固定和不可编辑的页眉 和页脚。
首先,我尝试使用此 css 放置页眉和页脚:
.header{
/*margin:-100px 0px;*/
margin-left: -2cm;
background-color: red;
vertical-align:middle;
text-align:center;
}
.footer{
background-color: darkgray;
margin-top: 735px;
height: 100px;
margin-left: -2cm;
}
并尝试在第一页启用页眉,效果很好:
<div id="editor">
<div contenteditable="true" class="page" id="page-1">
<div class="header" contenteditable="false">
<img class="brasao" alt="brasao-rj*" src="https://i.imgur.com/ktmBQCS.png" />
<span>Procuradoria Geral do Estado do Rio de Janeiro</span>
</div>
<b>hello</b>
<div class="footer" contenteditable="false">
Rua Carmo do Cajuru 128
</div>
</div>
</div>
但是页脚没有按预期工作,因为用户可以向下推页脚,将更多内容放在 div 上。
在我目前的方法中,我尝试在调用 newPage.focus() 之前附加“header”div。但不幸的是,行为并不像预期的那样,允许用户同时按下页眉和页脚。
const getHeader = () => {
let header = document.createElement('div');
header.setAttribute('contenteditable', false);
header.setAttribute('class', 'header');
let imgBrasao = document.createElement('img');
imgBrasao.class = 'brasao';
imgBrasao.setAttribute('class', 'brasao');
imgBrasao.src = 'https://i.imgur.com/ktmBQCS.png';
let spanPGE = document.createElement('span');
spanPGE.textContent = 'Procuradoria Geral do Estado do Rio de Janeiro';
header.appendChild(imgBrasao);
header.appendChild(spanPGE);
return header;
};
const getFooter = () => {
let footer = document.createElement('div');
footer.setAttribute('contenteditable', false);
footer.setAttribute('class', 'footer');
let spanPGE = document.createElement('span');
spanPGE.textContent = 'Rua Carmo do Cajuru 128 - Centro RJ';
footer.appendChild(spanPGE);
return footer;
};
完整代码在这里:
(无页眉页脚版本:https://jsitor.com/9J30B6YfG)
那么,我怎样才能在那些内容可编辑的 div 上模拟页眉和页脚呢?
提前致谢!
最佳答案
我设法在没有 jQuery 的情况下做到了。这个概念是在您的内容周围添加一个包装器,并将事件添加到该包装器而不是页面。此外,我创建了一个模板 HTML 页面,这样代码就可以在不执行清理的情况下进行克隆。
为了将页脚放在底部,我将页面显示更改为 flex
并将 flex-direction
更改为 column
。然后为页脚设置 margin-top: auto
。
代码如下:
function redator(divId) {
const root = document.getElementById(divId)
const a4 = {
height: 830,
width: 595,
lineHeight: 30
};
const template = document.querySelector('#template');
const headerHeight = root.querySelector('#page-1 .header').offsetHeight;
const footerHeight = root.querySelector('#page-1 .footer').offsetHeight;
const getChildrenHeight = (element) => {
total = parseFloat(getComputedStyle(element).paddingBottom);
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;
};
const getPageHeight = (content) => {
const children = getChildrenHeight(content);
return children + headerHeight + footerHeight;
};
const setSelection = (node, offset) => {
let range = document.createRange();
let sel = window.getSelection();
range.setStart(node, offset);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
};
const addPage = () => {
const newPage = template.cloneNode(true);
const pages = root.getElementsByClassName('page');
newPage.id = 'page-' + (pages.length + 1);
newPage.className = 'page';
root.appendChild(newPage);
newPage.querySelector(".content").focus();
newPage.querySelector(".content").addEventListener('input', onInput);
newPage._emptyPage = true;
return newPage.querySelector(".content");
};
function onInput(e) {
const content = this;
const page = this.closest(".page")
const previousPage = page.previousElementSibling;
const nextPage = page.nextElementSibling;
const pageHeight = getPageHeight(content);
const lastChild = content.lastChild;
const cloneChild = lastChild.cloneNode(true);
const textContent = content.innerText;
if ((pageHeight === 0 || textContent.length <= 1) && !!previousPage && !page._emptyPage) {
page.remove();
previousPage.querySelector(".content").focus();
const lastChild = previousPage.querySelector(".content").lastChild;
setSelection(lastChild, lastChild.childNodes.length);
} else if (pageHeight > a4.height && !nextPage) {
lastChild.remove();
addPage().appendChild(cloneChild);
} else if (pageHeight > a4.height && nextPage) {
lastChild.remove();
nextPage.querySelector(".content").insertBefore(cloneChild, nextPage.querySelector(".content").firstChild);
let selection = getSelection().getRangeAt(0).startContainer.parentElement.closest('div');
if (selection === page.lastChild) {
setSelection(cloneChild, 0);
}
} else if (pageHeight < a4.height - a4.lineHeight && !!nextPage) {
let firstChildOfNextPage = nextPage.firstChild;
let clone = firstChildOfNextPage.cloneNode(true);
firstChildOfNextPage.remove();
page.appendChild(clone);
}
page._emptyPage = false;
}
document.execCommand("DefaultParagraphSeparator", false, "div");
root.querySelector('#page-1 .content').addEventListener('input', onInput);
}
document.addEventListener('DOMContentLoaded', function() {
redator('editor');
}, false);
redator('editor');
#editor {
background-color: gray;
border: 1px black;
padding: 1em 2em;
}
.page {
background-color: white;
border: solid black;
/*padding: 10em 2em;*/
width: 595px;
height: 841px;
display: flex;
flex-direction: column;
}
.content {
word-wrap: break-word;
overflow-wrap: break-word;
white-space: normal;
padding-left: 2cm;
padding-bottom: 2cm;
}
.header {
background-color: red;
text-align: center;
}
.footer {
background-color: darkgray;
margin-top: auto;
height: 100px;
}
.brasao {
height: 60px;
width: 60px;
}
#template {
display: none;
}
<h3>My Editor</h3>
<div id="editor">
<div class="page" id="page-1">
<div class="header">
<img class="brasao" alt="brasao-rj*" src="https://i.imgur.com/ktmBQCS.png" />
<span>Procuradoria Geral do Estado do Rio de Janeiro</span>
</div>
<div class='content' contenteditable="true">
<b>hello</b>
</div>
<div class="footer">
Rua Carmo do Cajuru 128
</div>
</div>
</div>
<div id="template">
<div class="header">
<img class="brasao" alt="brasao-rj*" src="https://i.imgur.com/ktmBQCS.png" />
<span>Procuradoria Geral do Estado do Rio de Janeiro</span>
</div>
<div class='content' contenteditable="true">
</div>
<div class="footer">
Rua Carmo do Cajuru 128
</div>
</div>
关于javascript - 如何在生成的 contentEditable div 的顶部和底部附加固定的不可编辑内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58961491/