富文本编辑,即所见即所得(What You See Is What You Get)。这个技术的本质是在页面中嵌入一个包含空 HTML 页面的 iframe。通过 designMode 属性(设置为 on),这个页面就可以被编辑,编辑对象是这个页面的 元素的 HTML
代码。
iframe 中使用一个简单的 HTML 页面就可以作为内容:
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Blank Page for Rich Text Editingtitle>
head>
<body>
<script type="text/javascript">
script>
body>
html>
只有在页面完全加载后才能设置 designMode 属性,所以要使用 onload 事件来设置这一属性:
<iframe name="richedit" style="height: 100px;width:100px;" src="blank.htm">iframe>
<script type="text/javascript">
EventUtil.addHandler(window, "load", function () {
frames["richedit"].document.designMode = "on";
})
script>
打开后会看到一个类似文本框的可编辑区域。
把 contenteditable 属性设置给页面中的任何一个元素后,用户就可以立即编辑这个元素咯,是不是很方便呀:
<div class="editable" id="richedit" contenteditable>div>
在某个元素上设置 contenteditable 属性,也可以打开或关闭编辑模式:
var div = document.getElementById("richedit");
richedit.contenteditable = "true";
contenteditable 属性有三个值:
值 | 说明 |
---|---|
true | 打开 |
false | 关闭 |
inherit | 继承自父元素 |
五大浏览器都支持 contenteditable 属性。移动设备的浏览器中,iOS 5+ 的 Safari 和 Android 3+ 的 Webkit 也支持这个属性。
使用 document.execCommand() 可以与富文本编辑器进行交互。它接受 3 个参数:要执行的命令名称、是否为当前命令提供用户界面(为保证跨浏览器,通常设置为 false)以及命令参数。下面列出支持最多的命令:
命令 | 值(第 3 个参数) | 说明 |
---|---|---|
backcolor | 颜色字符串 | 设置文档的背景色。 |
bold | null | 将选择的文本转换为粗体。 |
copy | null | 将选择的文本复制到剪贴板。 |
createlink | URL 字符串 | 将选择的文本转换为链接,然后指向指定的 URL。 |
cut | null | 将选择的文本剪贴到剪贴板。 |
delete | null | 删除选择的文本。 |
fontname | 字体名称 | 将选择的文本改为指定的字体。 |
fontsize | 1 ~ 7 | 将选择的文本改为指定的字体大小。 |
forecolor | 颜色字符串 | 将选择的文本改为指定的颜色。 |
formatblock | 需要包围当前文本块的 HTML 标签 | 使用指定的 HTML 标签来包裹指定的文本块。 |
indent | null | 缩进文本。 |
inserthorizontalrule | null | 在光标处插入一个 元素。 |
insertimage | 图像的 URL | 在光标处插入一个图像。 |
insertorderedlist | null | 在光标处插入一个 元素。 |
insertunorderedlist | null | 在光标处插入一个 元素。 |
insertparagraph | null | 在光标处插入一个 元素。 |
italic | null | 将选择的文本改为斜体。 |
justifycenter | null | 在光标处的文本块居中对齐。 |
justifyleft | null | 在光标处的文本块左对齐。 |
outdent | null | 减少缩进。 |
paste | null | 将剪贴板中的内容粘贴到选择的文本。 |
removeformat | null | 移除包围当前文本块的 HTML 标签,这是撤销 formatblock 命令的操作。 |
selectall | null | 选中所有文本。 |
underline | null | 为选中的文本添加下划线。 |
unlink | null | 移除文本链接,这是撤销 createlink 命令的操作。 |
注意:与剪贴板相关的命令在不同的浏览器中差别很大!Opera 没有实现任何与剪贴板相关的命令,Firefox 会在默认情况下禁止这些命令。Safari 和 Chrome 实现了 cut 和 copy,但没有实现 paste。虽然不能使用 document.execCommand() 执行这些命令,但可以通过快捷键来实现同样的功能。
可以使用这些命令来改变富文本区域的外观:
<form method="post" action="javascript:alert('Form submitted!')" id="myForm">
<div id="divSimple">
<input type="button" value="Bold">
<input type="button" value="Italic">
<input type="button" value="createLink">
<input type="button" value="h1">
<input type="button" value="enabled">
<input type="button" value="state">
<input type="button" value="commandValue">
<input type="button" value="setBackground">
div>
<div id="richedit" style="height: 100px;width: 300px;border: dashed"
contenteditable>div>
<button type="sumbit">sumbitbutton>
<input type="hidden" id="comments">
form>
```
```
<script type="text/javascript">
(function () {
var simple = document.getElementById("divSimple");
EventUtil.addHandler(simple, "click", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.type = "button") {
switch (target.value) {
case "Bold"://粗体
// document.execCommand(target.value.toLowerCase(), false, null);
document.execCommand("bold", false, null);
break;
case "Italic"://斜体
document.execCommand("italic", false, null);
break;
case "createLink"://创建链接
document.execCommand("createlink", false, "http://www.163.com");
break;
case "h1"://格式化为 h1
document.execCommand("formatblock", false, ""
);
break;
case "enabled"://是否可以针对当前选择的文本执行某个命令
console.log(document.queryCommandEnabled("bold"));
break;
case "state"://是否已将指定命令应用到了选择的文本
console.log(document.queryCommandState("bold"));
break;
case "commandValue"://取得执行命令时传入的值
console.log(document.queryCommandValue("fontsize"));
break;
case "setBackground"://添加黄色背景(富文本选区操作)
var selection = document.getSelection();
//取得选择的文本
var selectedText = selection.toString();
//取得代表选区的范围
var range = selection.getRangeAt(0);
//突出显示已经选择的文本
var span = document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);
break;
}
}
});
})();
script>
注意:虽然所有的浏览器都支持这些命令,但它们生成的 HTML 文本并不相同!比如执行 bold 命令后,IE 和 Opera 会使用 标签包围文本,而 Safari 和 Chrome 使用的是
标签,在 Firefox 中使用的是
标签!
queryCommandEnabled() 方法是用来检查某个命令是否适用于当前选中的文本,或者是否能在当前光标处执行该命令。它接受一个参数,即要检测的命令。返回布尔值:
var result = frames["richedit"].document.queryCommandEnabled("bold");
这个命令其实并不可靠,比如在 Firefox 中禁用剪切操作的情况下,这个命令仍会返回 false。
queryCommandState() 方法用于确定某个命令是否已经应用到所选中的文本:
var result = frames["richedit"].document.queryCommandState("bold");
那些富文本编辑器就是根据这个方法返回的值来更新粗体、斜体的按钮状态的。
queryCommandValue() 可以取得执行命令时传入的值(就是 document.execCommand() 方法的第 3 个值):
var fontSize = frames["richedit"].document.queryCommandValue("fontsize");//7
# 3 富文本选区
使用 iframe 的 getSelection() 方法可以获取实际选中的文本。它会返回当前选中文本的 Selection 对象。每个 Selection 对象都有这些属性:
属性名 | 说明 |
---|---|
anchorNode | 选区起点所在的节点。 |
anchorOffset | 到达选区起点之前所跳过的 anchorNode 的字符数量。 |
focusNode | 选区终点所在的节点。 |
isCollapsed | 选区起点与终点是否重合。 |
rangeCount | 选区中包含的 DOM 范围的数量。 |
这些属性其实没有多少价值,我们再看看 Selection 对象所拥有的方法:
方法名 | 说明 |
---|---|
addRange(range) | 把指定的 DOM 范围添加到选区中。 |
collpase(node, offset) | 把选区折叠到指定节点中相应偏移量位置。 |
collapseToEnd() | 把选区折叠到终点。 |
collapseToStart() | 把选区折叠到起点。 |
deleteFromDocument() | 从文档中删除选区中的文本,这与 执行 document.execCommand(“delete”, false, null) 命令的结果相同。 |
extend(node offset) | 把 focusNode 和 focusOffset 移动到指定偏移量来扩展选区。 |
getRangeAt(index) | 返回索引对应选区中的 DOM 范围。 |
removeAllRanges() | 从选区中移除所有 DOM 范围,没有了范围,选区也会被移除。 |
removeRange(range) | 从选区中移除指定的 DOM 范围。 |
selectAllChildren(node) | 清除选区,然后选择指定节点的所有节点。 |
toString() | 返回选区所包含的文本内容。 |
这些方法很实用,可以使用它们来管理选区:
var selection = document.getSelection();
//取得选择的文本
var selectedText = selection.toString();
//取得代表选区的范围
var range = selection.getRangeAt(0);
//突出显示已经选择的文本
var span = document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);
上面这段代码会把被选择的文本添加上黄色的背景:
因为富文本编辑使用的是 iframe,所以它并不属于表单。所以自然不会被自动提交给服务器,因此需要手工处理。可以添加一个隐藏字段,把它的值设置为从 iframe 中提取出的 富文本内容:
"hidden" id="comments">
...
var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function (event) {//把富文本域的值添加到表单
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
target.elements["comments"].value = document.getElementById("richedit").innerHTML;
console.log(target.elements["comments"].value);
})