富文本编辑器(Rich Text Editor)是在网页上应用的一种所见即所得的文本编辑器,是 Web 利用开发中很常见的需要。
富文本实现
在 HTML 文档上共有 2 中形式实现富文本编辑器。一种是应用 iframe
,另一种是应用 contenteditable
属性指定 HTML 文档元素。
iframe
第一种形式是应用 iframe
标签。
在空白的 HTML 文档中嵌入一个 iframe
,并将 designMode
属性设置为 "on"
,文档就会变成可编辑的,理论编辑的则是 <body>
元素的 HTML,默认值是 "off"
。文档变成可编辑后,就能够像应用文字处理程序一样编辑文本,通过键盘将文本标记为粗体、斜体等等。
作为 iframe
源的是一个非常简单的空白 HTML 页面。上面是一个例子:
<!DOCTYPE html>
<html>
<head>
<title>Blank Page for Rich Text Editing</title>
</head>
<body>
</body>
</html>
这个页面会像其余任何页面一样加载到 iframe
里。为了能够编辑,必须将文档的 designMode
属性设置为 "on"
。不过,只有在文档齐全加载之后能够设置。在这个蕴含页面内,须要应用 onload
事件处理程序在适当机会设置 designMode
,如上面的例子所示:
<iframe name="editor" style="height: 100px; width: 100px"></iframe>
<script>
window.addEventListener("load", () => {frames["editor"].document.designMode = "on";
});
</script>
以上代码加载之后,能够在页面上看到一个相似文本框的区域。这个框的款式具备网页默认款式,不过能够通过 CSS
调整。
contenteditable
第二种形式是应用 contenteditable
属性指定 HTML 文档中的元素。该形式是 IE 最早实现的。应用形式是在一个元素上增加 contenteditable
属性并设置为 true
或者空字符串""
,而后该元素会立刻被用户编辑。如下所示:
<div class="editor" id="editorId" contenteditable="true"></div>
元素中蕴含的任何文本都会主动被编辑,元素自身相似于<textarea>
元素。通过设置contentEditable
属性,也能够随时切换元素的可编辑状态:
let div = document.getElementById("editorId");
richedit.contentEditable = "true";
contentEditable
属性有 3 个可能的值:"true"
示意开启,"false"
示意敞开,"inherit"
示意继承父元素的设置。支流浏览器都反对 contentEditable
属性。
留神:contenteditable
是一个十分多才多艺的属性。比方,拜访伪 URL data:text/html
, <html contenteditable>
能够把浏览器窗口转换为一个记事本。这是因为这样会长期创立 DOM
树并将整个文档变成可编辑区域。
与富文本交互
下面讲到了如何在 HTML 文档中实现富文本编辑器,而当初须要理解要应用什么形式与富文本编辑器交互。document
提供了 execCommand()
办法,该办法会影响应用 contentEditable
属性实现可编辑区域的元素。办法阐明如下所示:
execCommand(commandId: string, showUI?: boolean, value?: string): boolean;
commandId
:参数是string
值,示意要执行的命令。上面会列出可用命令。showUI
:参数是boolean
的可选值,示意浏览器是否为命令提供用户界面,个别为false
。为兼容的话,该参数须要始终为false
,因为 Mozilla 没有实现,会在其为true
时抛出谬误。value
:参数是string
的可选值,是一些命令须要额定的参数,默认为null
。
该办法执行后,会返回 boolean
值,如果是 false
,示意操作不被反对或未被启用。
留神:在调用一个命令前,不要尝试应用返回值去校验浏览器的兼容性
不同浏览器反对的命令也不一样。下标列出了最罕用的命令。
命令 | 作用 | 可选值 |
---|---|---|
backColor | 设置文档背景色彩。在 styleWithCss 模式下,则只影响容器元素的背景色彩。 |
色彩值 <color> 字符串(IE 应用这个命令设置文本背景色) |
bold | 切换选中文本的粗体款式 | null |
copy | 将选中内容复制到剪贴板 | null |
createLink | 将选中内容转换为指向给定 URL 的链接 | URL 链接值,至多蕴含一个字符 |
cut | 将选中内容剪切到剪贴板 | null |
delete | 删除选中的内容 | null |
fontName | 将选中文本改为应用指定字体 | 字体名(例如:”Arial”) |
fontSize | 将选中文本改为指定字体大小 | 提供 HTML 字体尺寸(1-7) |
foreColor | 将选中文本改为指定色彩 | 色彩值 <color> 字符串 |
formatBlock | 将选中文本蕴含在指定的 HTML 标签中 | 提供 HTML 标签,如<h1> |
indent | 缩进文本 | null |
insertHorizontalRule | 在光标地位插入 <hr> 元素 |
null |
insertImage | 在光标地位插入图片 | 图片的 URL 链接 |
insertOrderedList | 在光标地位插入 <ol> 元素 |
null |
insertunorderedlist | 在光标地位插入 <ul> 元素 |
null |
insertParagraph | 在光标地位插入 <p> 元素 |
null |
italic | 切换选中文本的斜体款式 | null |
justifyCenter | 在光标地位或者所选内容进行文字居中 | null |
justifyFull | 在光标地位或者所选内容进行文本对齐 | null |
justifyLeft | 在光标地位或者所选内容进行左对齐 | null |
justifyRight | 在光标地位或者所选内容进行右对齐 | null |
outdent | 减小缩进 | null |
paste | 在光标地位粘贴剪贴板内容,如果有被选中的内容,会被替换 | null |
redo | 重做被撤销的操作 | null |
removeFormat | 对所选内容去除 HTML 格局。这是 formatBlock 的反操作 | null |
selectAll | 选中编辑区里的全部内容 | null |
strikeThrough | 切换删除线 | null |
subscript | 切换下角标 | null |
superscript | 切换上角标 | null |
underline | 切换下划线 | null |
undo | 撤销最近执行的命令 | null |
unlink | 取出所选链接的 <a> 标签 |
null |
styleWithCSS | 用这个取代 useCSS 命令。切换应用 HTML tags 还是 CSS 来生成标记。 | Boolean 值,false 应用 CSS,true 应用 HTML |
剪贴板相干的命令与浏览器关系密切。尽管这些命令并不都能够通过 document.execCommand()
应用,但相应的键盘快捷键都是能够用的。
这些命令能够用于批改 iframe
中富文本区域的外观,如上面的例子所示:
// 在内嵌窗格中切换粗体文本款式
frames["editor"].document.execCommand("bold", false, null);
// 在内嵌窗格中切换斜体文本款式
frames["editor"].document.execCommand("italic", false, null);
// 在内嵌窗格中创立指向 www.wrox.com 的链接
frames["editor"].document.execCommand("createlink", false, "http://www.wrox.com");
// 在内嵌窗格中为内容增加 <h1> 标签
frames["editor"].document.execCommand("formatblock", false, "<h1>");
同样的办法也能够用于页面中增加了 contenteditable
属性的元素,只不过要应用以后窗口而不是内嵌窗格中的 document
对象:
// 切换粗体文本款式
document.execCommand("bold", false, null);
// 切换斜体文本款式
document.execCommand("italic", false, null);
// 创立指向 www.wrox.com 的链接
document.execCommand("createlink", false, "http://www.wrox.com");
// 为内容增加 <h1> 标签
document.execCommand("formatblock", false, "<h1>");
留神:应用 bold
的命令在浏览器中生成的 HTML 差异很大。如在 IE 和 Opera 中应用 <strong>
标签,在 Safari 和 Chrome 中应用 <b>
标签,在 Firefox 中应用 <span>
标签。
document
中提供了 queryCommandEnabled()
办法:
queryCommandEnabled(commandId: string): boolean;
commandId
:接管string
类型参数,是待查问是否可用的命令。
该办法用于确定对以后选中文本或光标所在位置是否能够执行相干命令。true
指令可用,false
不可用。如下所示:
let result = document.queryCommandEnabled("selectAll");
但要留神,返回 true
并不代表容许执行相干命令,只代表以后选区适宜执行相干命令。在 Firefox 中,queryCommandEnabled("cut")
即便默认不容许剪切也会返回 true
。
document
还提供 queryCommandState()
办法:
queryCommandState(commandId: string): boolean;
commandId
:参数是要确定的命令。
该办法用于确定相干命令是否利用到了以后文本选区。如下所示:
let isBold = document.queryCommandState("selectAll");
富文本编辑器能够利用这个办法更新粗体、斜体等按钮。
在介绍一下 queryCommandValue()
办法:
queryCommandValue(commandId: string): string;
这个办法用于返回执行命令时应用的值,参考 execCommand()
办法应用的第三个参数。如下所示,如果一段选中文本利用了值为 5 的 "fontsize"
命令,应用该办法会返回 5:
let fontSize = document.queryCommandValue("fontsize");
这个办法可用于确定如何将命令利用于文本选区,从而进一步决定是否须要执行下一个命令。
富文件选区
Selection
对象示意用户选中的文本范畴或光标的地位,它代表页面中的文本选区。能够应用 window
或 document
对象调用 getSelection()
办法获取文本选区。Selection
对象领有以下属性。
anchorNode
:只读属性,形容选区终点所在的节点。anchorOffset
:只读属性,返回的是选区终点在anchorNode
中的地位偏移量。focusNode
:只读属性,返回选区起点所在的节点。focusOffset
:只读属性,返回的是选区起点在focusNode
中的地位偏移量。isCollapsed
:只读属性,返回boolean
值,用来示意选区终点和起点是否在同一个地位。rangeCount
:只读属性,返回选区所蕴含的DOM
范畴数量。
Selection
的属性并没有蕴含很多有用的信息。好在它的以下办法提供了更多信息,并容许操作选区。
addRange(range)
:把给定的DOM
范畴增加到选区。collapse(node, offset)
:将选区折叠到给定节点中给定的文本偏移处。collapseToEnd()
:将选区折叠到起点。collapseToStart()
:将选区折叠到终点。containsNode(node)
:判断给定节点是否蕴含在选区中。deleteFromDocument()
:从文档中删除选区内容。与执行execCommand("delete", false, null)
命令后果雷同。extend(node, offset)
:通过将focusNode
和focusOffset
挪动到指定值来扩大选区。getRangeAt(index)
:返回选区中指定索引处的DOM
范畴。removeAllRanges()
:将所有的区域都从选区中移除。removeRange(range)
:从选区中移除指定的DOM
范畴。selectAllChildren(node)
:革除选区并抉择给定节点的所有子节点。toString()
:返回选区中的纯文本内容。
上面介绍一个例子,是应用 Selection
对象实现选中文本高亮:
function highlight() {let selection = document.getSelection();
// 获得示意选区的范畴
let range = selection.getRangeAt(0);
// 高亮选中的文本
let span = document.createElement("span");
span.style.backgroundColor = "yellow";
// 给选中文本增加背景为黄色的 <span> 标签
range.surroundContents(span);
}
成果如下:
通过表单提交富文本
因为富文本编辑不是在表单控件中实现,这意味着要将富文本编辑后果提交给服务器,就要手动进行。咱们会在表单中增加一个 type="hidden"
的字段,在提交表单时,通过监听器,从元素中提取出 HTML 并插入暗藏字段中。如下所示:
// form 实例是 `<form>` 元素,能够应用 DOM 获取
form.addEventListener("submit", (event) => {
let target = event.target;
target.elements["content"].value = frames["editor"].document.body.innerHTML;
});
上述从编辑器中获取了 HTML 后,将其插入名为 content
的字段中。上面是对于 contenteditable
元素实现的形式:
这里,代码应用文档主体的 innerHTML
属性获得了 iframe
的 HTML,而后将其插入名为 "comments"
的表单字段中。这样做能够确保在提交表单之前给表单字段赋值。如果应用 submit()
办法手工提交表单,那么要留神在提交前先执行上述操作。对于 contenteditable
元素,执行这一操作的代码是相似的:
// form 实例是 `<form>` 元素,能够应用 DOM 获取
form.addEventListener("submit", (event) => {
let target = event.target;
target.elements["content"].value = document.getElementsByClassName("editor")[0].innerHTML;
});
总结
本文介绍了实现富文本编辑器有两种形式:应用 iframe
和 contenteditable
属性。介绍了应用 document.execCommand()
办法来实现加粗、斜体款式等性能,还有一些相应的性能。而且富文本编辑的内容要上传到服务器,还要将内容先复制到表单中的一个字段上,而后在提交。
更多内容请关注公众号「海人为记」