跳到主要内容

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>