說說 JavaScript 表單指令碼之富文字編輯功能
富文字編輯,即所見即所得(What You See Is What You Get)。這個技術的本質是在頁面中嵌入一個包含空 HTML 頁面的 iframe。通過 designMode 屬性(設定為 on),這個頁面就可以被編輯,編輯物件是這個頁面的 <body>
元素的 HTML
程式碼。
iframe 中使用一個簡單的 HTML 頁面就可以作為內容:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Blank Page for Rich Text Editing</title >
</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>
開啟後會看到一個類似文字框的可編輯區域。
1 使用 contenteditable 屬性
把 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 也支援這個屬性。
2 操作富文字
使用 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 | 在游標處插入一個 <hr> 元素。 |
insertimage | 影象的 URL | 在游標處插入一個影象。 |
insertorderedlist | null | 在游標處插入一個<ol> 元素。 |
insertunorderedlist | null | 在游標處插入一個<ul> 元素。 |
insertparagraph | null | 在游標處插入一個<p> 元素。 |
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">
<!--<input type="button" value="Underline">-->
<!--<input type="button" value="Indent">-->
<!--<input type="button" value="Outdent">-->
<!--<input type="button" value="Copy">-->
<!--<input type="button" value="Cut">-->
<!--<input type="button" value="Paste">-->
</div>
<div id="richedit" style="height: 100px;width: 300px;border: dashed"
contenteditable></div>
<button type="sumbit">sumbit</button>
<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, "<h1>");
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 會使用 <strong>
標籤包圍文字,而 Safari 和 Chrome 使用的是 <b>
標籤,在 Firefox 中使用的是 <span>
標籤!
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);
上面這段程式碼會把被選擇的文字新增上黃色的背景:
4 表單和富文字
因為富文字編輯使用的是 iframe,所以它並不屬於表單。所以自然不會被自動提交給伺服器,因此需要手工處理。可以新增一個隱藏欄位,把它的值設定為從 iframe 中提取出的 富文字內容:
<input type="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);
})