div-contenteditable
2023年09月07日
一、认识
<div contenteditable="true"></div>
借助 contenteditable
可已让 div
实现 input
或者 textarea
一样的编辑效果, 可以通过这个特性来模拟实现富文本编辑器。
二、编辑纯文本
<style>
/* 输入框 */
.div-rich-editor {
width: 400px;
height: 100px;
border-radius: 4px;
background-color: #f5f5f5;
}
/* 输入框为空时显示 placeholder */
.div-rich-editor:empty:before {
content: attr(placeholder);
color: red;
}
/* 输入框获取焦点时移除 placeholder */
.div-rich-editor:focus:before {
content: none;
}
</style>
<div
class="div-rich-editor"
contenteditable="true"
placeholder="请输入内容"
></div>
<script>
let isComposing = false;
const divRichEditor = document.querySelector(".div-rich-editor");
divRichEditor.addEventListener("blur", onBlur);
divRichEditor.addEventListener("input", onInput);
divRichEditor.addEventListener("onPaste", onPaste);
divRichEditor.addEventListener("keydown", onKeyDown);
divRichEditor.addEventListener("keypress", onKeyPress);
divRichEditor.addEventListener("compositionend", onCompositionEnd);
divRichEditor.addEventListener("compositionstart", onCompositionStart);
function onInput(event) {
if (isComposing) {
return;
}
const value = event.target.textContent;
console.log("onInput", value);
}
function onBlur(event) {
const value = event.target.textContent;
console.log("onBlur", value);
}
function onPaste(event) {
const value = event.originalEvent.clipboardData.getData("text");
console.log("onPaste", value);
}
function onKeyDown(event) {
const value = event.target.textContent;
console.log("onKeyDown", value);
}
function onKeyPress(event) {
const value = event.target.textContent;
console.log("onKeyPress", value);
}
function onCompositionStart(event) {
isComposing = true;
const value = event.target.textContent;
console.log("onCompositionStart", vlaue);
}
function onCompositionEnd(event) {
isComposing = false;
const value = event.target.textContent;
console.log("onCompositionEnd", value);
}
</script>
三、编辑纯文本,支持滚动
<style>
/* 输入框 */
.div-rich-editor {
width: 400px;
height: 100px;
border-radius: 4px;
resize: both;
overflow: auto;
background-color: #f5f5f5;
}
/* 输入框为空时显示 placeholder */
.div-rich-editor:empty:before {
content: attr(placeholder);
color: red;
}
/* 输入框获取焦点时移除 placeholder */
.div-rich-editor:focus:before {
content: none;
}
</style>
<div
class="div-rich-editor"
contenteditable="true"
placeholder="请输入内容"
></div>
<script>
let isComposing = false;
const divRichEditor = document.querySelector(".div-rich-editor");
divRichEditor.addEventListener("blur", onBlur);
divRichEditor.addEventListener("input", onInput);
divRichEditor.addEventListener("onPaste", onPaste);
divRichEditor.addEventListener("keydown", onKeyDown);
divRichEditor.addEventListener("keypress", onKeyPress);
divRichEditor.addEventListener("compositionend", onCompositionEnd);
divRichEditor.addEventListener("compositionstart", onCompositionStart);
function onInput(event) {
if (isComposing) {
return;
}
const value = event.target.textContent;
console.log("onInput", value);
}
function onBlur(event) {
const value = event.target.textContent;
console.log("onBlur", value);
}
function onPaste(event) {
const value = event.originalEvent.clipboardData.getData("text");
console.log("onPaste", value);
}
function onKeyDown(event) {
const value = event.target.textContent;
console.log("onKeyDown", value);
}
function onKeyPress(event) {
const value = event.target.textContent;
console.log("onKeyPress", value);
}
function onCompositionStart(event) {
isComposing = true;
const value = event.target.textContent;
console.log("onCompositionStart", vlaue);
}
function onCompositionEnd(event) {
isComposing = false;
const value = event.target.textContent;
console.log("onCompositionEnd", value);
}
</script>
四、编辑纯文本,限制高度
<style>
/* 输入框 */
.div-rich-editor {
width: 400px;
height: 100px;
border-radius: 4px;
background-color: #f5f5f5;
}
/* 输入框为空时显示 placeholder */
.div-rich-editor:empty:before {
content: attr(placeholder);
color: red;
}
/* 输入框获取焦点时移除 placeholder */
.div-rich-editor:focus:before {
content: none;
}
</style>
<div
class="div-rich-editor"
contenteditable="true"
placeholder="请输入内容"
></div>
<script>
let isComposing = false;
let composStartContent = "";
let composEndContent = "";
let range = document.createRange();
let selection = window.getSelection();
const divRichEditor = document.querySelector(".div-rich-editor");
divRichEditor.addEventListener("blur", onBlur);
divRichEditor.addEventListener("input", onInput);
divRichEditor.addEventListener("onPaste", onPaste);
divRichEditor.addEventListener("keydown", onKeyDown);
divRichEditor.addEventListener("keypress", onKeyPress);
divRichEditor.addEventListener("compositionend", onCompositionEnd);
divRichEditor.addEventListener("compositionstart", onCompositionStart);
function limitInput(params) {
const { e, prevContent } = params;
const clientHeight = divRichEditor.clientHeight;
const scrollHeight = divRichEditor.scrollHeight;
if (scrollHeight > clientHeight) {
e?.preventDefault?.();
divRichEditor.textContent =
prevContent || divRichEditor.textContent.slice(0, -1);
range.selectNodeContents(divRichEditor);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
}
function onInput(event) {
range = document.createRange();
selection = window.getSelection();
if (isComposing) {
return;
}
const value = event.target.textContent;
console.log("onInput", value);
limitInput({
e: event,
});
}
function onBlur(event) {
const value = event.target.textContent;
console.log("onBlur", value);
}
function onPaste(event) {
const value = event.originalEvent.clipboardData.getData("text");
console.log("onPaste", value);
}
function onKeyDown(event) {
const value = event.target.textContent;
console.log("onKeyDown", value);
}
function onKeyPress(event) {
const value = event.target.textContent;
console.log("onKeyPress", value);
}
function onCompositionStart(event) {
isComposing = true;
const value = event.target.textContent;
composStartContent = value;
console.log("onCompositionStart", value);
}
function onCompositionEnd(event) {
isComposing = false;
const value = event.target.textContent;
composEndContent = value;
console.log("onCompositionEnd", value);
limitInput({
e: event,
prevContent: composStartContent,
});
}
</script>