创建内联编辑器需要付出努力。input您首先使用或textarea字段切换要编辑的元素。为了获得无缝的用户体验,您可能还必须使用一些 CSS 来将交换元素的样式与原始样式相匹配。用户完成编辑后,您将不得不在将所有内容复制到原始内容后再次切换元素。
该contentEditable属性使这项任务变得容易得多。您所要做的就是将此属性设置为true,标准 HTML5 元素将变得可编辑。在本教程中,我们将基于此功能创建一个内联富文本编辑器。
基础知识
此属性可以采用三个有效值。这些true是false和inherit。该值true指示该元素是可编辑的。空字符串也将评估为真。false表示该元素不可编辑。该值inherit是默认值。inherit指示如果元素的直接父元素是可编辑的,则该元素将是可编辑的。这意味着如果您使一个元素可编辑,那么它的所有子元素(而不仅仅是直接子元素)也将变为可编辑的,除非您将它们的contentEditable属性显式设置为false.
您可以使用 JavaScript 动态更改这些值。如果新值不是三个有效值中的任何一个,则它会引发SyntaxError异常。
创建编辑器
要创建内联编辑器,您需要能够在contentEditable用户决定编辑某些内容时更改属性的值。
在切换contentEditable属性时,有必要知道该属性当前持有什么值。为此,您可以使用该isContentEditable属性。如果isContentEditable返回true一个元素,则该元素当前是可编辑的,否则不是。我们将很快使用此属性来确定文档中各种元素的状态。
首先,我们需要创建一个名为contenteditable-editor的目录。在其中,创建一个名为 index.html的新文件。您可以将其用作 HTML 文件的框架。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Text Editor</title></head><body></body></html>
构建编辑器的第一步是创建一个按钮来切换编辑和一些可编辑元素。在<body>元素里面,放这个:
<button id="editBtn" type="button">Edit Document</button><div id="editor"><h1 id="title">A Nice Heading.</h1><p>Last Edited By - <span id="author">Monty Shokeen</span></p><p id="content">Some content that needs correction.</p></div>
我们打算保持可编辑的每个元素都需要有自己的独特性Id。当我们必须保存更改或稍后检索它们以替换每个元素内的文本时,这将很有帮助。
以下 JavaScript 代码处理所有编辑和保存。
const editBtn = document.getElementById('editBtn');const editables = document.querySelectorAll('#title, #author, #content')editBtn.addEventListener('click', function(e) {if (!editables[0].isContentEditable) {editables[0].contentEditable = 'true';editables[1].contentEditable = 'true';editables[2].contentEditable = 'true';editBtn.innerHTML = 'Save Changes';editBtn.style.backgroundColor = '#6F9';} else {// Disable Editingeditables[0].contentEditable = 'false';editables[1].contentEditable = 'false';editables[2].contentEditable = 'false';// Change Button Text and ColoreditBtn.innerHTML = 'Enable Editing';editBtn.style.backgroundColor = '#F96';// Save the data in localStoragefor (var i = 0; i < editables.length; i++) {localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML);}}});
您可以将此代码放在<script>标签底部的<body>标签中。我们使用querySelectorAll()将所有可编辑元素存储在一个变量中。此方法返回一个NodeList包含我们文档中由指定选择器匹配的所有元素的 a。这样,使用一个变量就更容易跟踪可编辑元素。例如,我们的文档的标题可以通过使用来访问editables[0],这就是我们接下来要做的。
接下来,我们为按钮的单击事件添加一个事件***器。每次用户单击“编辑文档”按钮时,我们都会检查标题是否可编辑。如果它不可编辑,我们将contentEditable每个可编辑元素的属性设置为true. 此外,文本'Edit Document'更改为'Save Changes'。用户进行一些编辑后,他们可以单击'Save Changes'按钮,所做的更改可以永久保存。
如果标题是可编辑的,我们将contentEditable每个可编辑元素的属性设置为 false。此时,我们还可以将文档的内容保存在服务器上以供以后检索或将更改同步到其他地方存在的副本。在本教程中,我将保存所有内容localStorage。将值保存在 中时localStorage,我使用Id每个元素的 来确保不会覆盖任何内容。
See the Pen Basic Inline Editor by Envato Tuts+ (@tutsplus) on CodePen.
检索保存的内容
如果您对上一个演示中的任何元素进行更改并重新加载页面,您会注意到您所做的更改已经消失。这是因为没有代码可以检索保存的数据。内容保存在 中后localStorage,我们需要稍后在用户再次访问该网页时检索它。
if (typeof(Storage) !== "undefined") {if (localStorage.getItem('title') !== null) {editables[0].innerHTML = localStorage.getItem('title');}if (localStorage.getItem('author') !== null) {editables[1].innerHTML = localStorage.getItem('author');}if (localStorage.getItem('content') !== null) {editables[2].innerHTML = localStorage.getItem('content');}}
上面的代码检查标题、作者或内容是否已经存在于localStorage. 如果是这样,我们将innerHTML各个元素的 设置为检索到的值。
See the Pen localStorage Inline Editor by Envato Tuts+ (@tutsplus) on CodePen.
自动保存
为了使编辑器更加用户友好,我们应该添加自动保存。第一种方法每五秒钟自动保存一次您的工作。
setInterval(function() {for (var i = 0; i < editables.length; i++) {localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML);}}, 5000);您还可以保存每个keydown事件的更改。
document.addEventListener('keydown', function(e) {for (var i = 0; i < editables.length; i++) {localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML);}});
在本教程中,我坚持使用后一种方法。您可以根据项目中似乎合适的任何事件自由触发自动保存。
See the Pen Complete contentEditable Inline Editor by Envato Tuts+ (@tutsplus) on CodePen.
创建工具栏
现在,我们需要让人们更容易插入新的标题和其他格式元素。为此,让我们添加一个工具栏。首先,我们需要添加一些 HTML。将此代码段添加到<body>标记的顶部。
<div id="toolbar"><button id="addh1">H1</button><button id="addh2">H2</button></div>
现在,让我们让它真正做点什么。我们需要添加一个click将标题插入内容块的事件。
document.querySelector("#addh1").addEventListener("click", function (e) {const text = prompt("What text do you want the heading to have?","Heading");editables[2].innerHTML = editables[2].innerHTML + `<h1>${text}</h1>`;});
这会将一个事件附加click到 H1 按钮,提示您使用该prompt()函数输入文本并将该文本放在内容块内的标题中。如果需要,您还可以像普通文本一样编辑标题。要为 H2 添加此功能,您只需更改元素选择器和插入的 HTML。
document.querySelector("#addh2").addEventListener("click", function (e) {const text = prompt("What text do you want the heading to have?","Heading");editables[2].innerHTML = editables[2].innerHTML + `<h2>${text}</h2>`;});
您可以轻松地将其扩展到其他元素,如粗体文本和下划线,只需创建一个新行和上述代码的一个版本,并插入新的选择器和不同的 HTML 标记。
See the Pen ContentEditable Editor with Toolbar by Envato Tuts+ (@tutsplus) on CodePen.
样式化编辑器
目前,编辑器没有 CSS。您可以随心所欲地设计它,但我们也为您准备了一种风格。如果您想要与我在代码笔中使用的样式相同的样式,则可以使用此 CSS。
body {font-family: Arial;font-size: 1.3em;line-height: 1.6em;}.headline {font-size: 2em;text-align: center;}#wrapper {width: 600px;background: #fff;padding: 1em;margin: 1em auto;box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);border-radius: 3px;}button {border: none;padding: 0.8em;background: #f96;border-radius: 3px;color: white;font-weight: bold;margin: 0 0 1em;}button:hover,button:focus {cursor: pointer;outline: none;}#editor {padding: 1em;background: #e6e6e6;border-radius: 3px;}
测试
要测试您的工作,您可以使用类似serve. 要使用 serve,您只需运行npm i -g serve,然后serve在包含您的工作的目录中运行。serve将自动启动一个包含您的 HTML 文件的网络服务器,您可以通过单击打印的链接导航到该文件。
使用设计模式编辑整个页面
contentEditable当您必须编辑网页上的一些元素时非常有用。当需要更改网页上所有或几乎所有元素的内容时,可以使用该designMode属性。此属性适用于整个文档。要转动它on和off,请分别使用document.designMode = 'on';和document.designMode = 'off';。
在您是设计师而其他人是内容创建者的情况下,这将证明是有价值的。您为他们提供设计和一些虚拟文本。稍后,他们可以用真实内容替换它。要查看designMode实际情况,请在浏览器的开发人员工具中打开控制台选项卡。在控制台中输入document.designMode = 'on';并按Enter。此页面上的所有内容现在都应该是可编辑的。
最后的想法
该contentEditable属性在快速编辑文章或使用户能够通过单击编辑他们的评论等情况下很方便。此功能首先由 IE 5.5 实现。后来,它被WHATWG标准化。浏览器支持也很好。除 Opera Mini 以外的所有主流浏览器都支持此属性。
发表评论