表单脚本相关08

富文本编辑

  • 富文本编辑,又称为WYSIWYG(What Tou See Is What You Get,所见即所得)。在网页中编辑富文本内容,是人们对web引用程序最大的期待之一。虽然也没有规范,但在IE最早引入的这一功能基础上,已经出现了事实标准。而且,Opera、Safari、Chrome、Firefox都已经支持这一功能。这一技术的本质,就是在页面中嵌入一个包含空HTML页面的iframe。通过设置designMode属性,这个空白的HTML页面可以被编辑,而编辑对象则是该页面<body>元素的HTML代码。designMode有两个可能的值:"off(默认值)"和"on"。在设置为"on"时,整个文档都会变得可以编辑(显示插入符号),然后就可以像使用字处理软件一样,通过键盘将文办内容加速,变成斜体,等等。
    可以给iframe指定一个非常简单的HTML页面作为其内容来源。例如:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Blank Page for Rich Text Editing</title>
</head>


<body>
</body>

</html>
  • 这个页面在iframe中可以像其他页面一样被加载。要让它可以编辑,必须要将designMode属性设置为on,但只有在页面完全加载之后才能设置这个属性。因此,在包含页面中,需要使用onload时间处理程序来在恰当的时刻设置designMode,如下面的例子所示:
    <iframe src="./demo1.html" style="width:100px;height:100px;" name="richedit"></iframe>


    <script>
        window.onload = function () {
            frames["richedit"].document.designMode = "on";
        }
    </script>
  • 等到以上代码执行以后,就会在页面看到一个类似文本框的可编辑区字段。这个区字段具有与其他网页先相同的默认样式;不过,通过为空白页面应用CSS样式,可以修改可编辑区字段的外观。
使用 contenteditable 属性
  • 另一种编辑富文本内容的方式是使用名为 contenteditable的特殊属性,这个属性也是由IE最早实现的。可以把contenteditable属性应用给页面中的任何元素,然后用户立即就可以编辑该元素。这种方法之所以受欢迎,是以为它不需要 iframe,空白页和 JavaScript,只要为元素设置contenteditable属性即可。
 <div class="editable" id="richedit" contenteditable></div>
image.png
  • 这样,元素中包含的任何文本内容就都可以编辑了,就好像这个元素变成了<textarea>元素一样。通过在这个元素上设置contenteditable属性,也能打开或关闭编辑模式
        var div = document.getElementById("richedit");
        div.contentEditable = "true"
  • contenteditable属性有三个可能的值:“true”表示打开,“false”表示关闭,“inherit”表示从父元素那里继承(因为可以在contenteditable元素中创建和删除元素)
操作富文本
  • 与富文本编辑器交互的主要方式,就是使用document.execCommand()。这个方法可以对文档执行预定义的命令,而且可以应用大多数格式。可以为document.execCommand()方法传递3个参数:要执行的命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值和执行命令必须的一个值(如果不需要值,则传递null)。为了确保跨浏览器的兼容性,第二个参数应该始终设置为false,因为Firefox会在该参数为true时抛出错误。
  • 不同的浏览器支持的预定义命令也不一样。下表列出了那些被支持最多的命令。
命令 值(第三个参数) 说明
backcolor 颜色字符串 设置文档的背景颜色
bold null 将选择的文本转换为粗体
copy null 将选择的文本复制到剪贴板
createlink URL字符串 将选择的文本转换成一个链接,指向指定的URL
cut null 将选择的文本复剪切到剪贴板
delete null 删除选择的文本
fontname 字体名称 将选择的文本修改为指定字体
fontsize 1~7 将选择的文本修改为指定字体大小
forecolor 颜色字符串 将选择的文本修改为指定的颜色
formatblock 要包围当前文本块的HTML标签;如<h1> 使用指定的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 移除插入光标所在文本块的块级格式。这是撤销formatblock命令的操作
selectall null 选择文档中的所有文本
underline null 为选择的文本添加下划线
unlink null 移除文本的链接。这是撤销createlink命令的操作
  • 其中,与剪贴板有关的命令在不同的浏览器中差异极大。Opera根本没有实现任何剪贴板命令,而Firefox在默认情况下会禁用它们(必须修改用户的首选项来启用它们)。Safari和Chrome实现了cut和copy,但是没有实现paste。不过,即使不能通过docuement.execCommand()来执行这些命令,但却可以通过相应的快捷键来实现同样的操作。
  • 可以在任何时候使用这些命令来修改富文本区域的外观,如下面例子:、
        //转换粗体文本
        frames["richedit"].document.execCommand("bold", false, null);

        //转换斜体文本
        frames["richedit"].document.execCommand("italic", false, null);

        //创建指向www.wrox.com的链接
        frames["richedit"].document.execCommand("createlink", false, "http://www.wrox.com");

        // 格式化为1级标题
        frames["richedit"].document.execCommand("formatblock", false, "<h1>");
  • 同样的方法也适用于页面中 contenteditable属性为 true的区块,只要把框架的引用替换为当前窗口的document对象即可。
        //转换粗体文本
        document.execCommand("bold", false, null);

        //转换斜体文本
        document.execCommand("italic", false, null);

        //创建指向www.wrox.com的链接
        document.execCommand("createlink", false, "http://www.wrox.com");

        // 格式化为1级标题
        document.execCommand("formatblock", false, "<h1>");
  • 需要注意的是,虽然所有浏览器都支持这些命令,但这些命令所产生的HTML仍然有很大不同。例如执行bold命令时,IE和Opera会使用<strong>标签包围文本,Safari和Chrome使用<b>标签,而firefox则使用<span>标签。由于各个浏览器实现命令的方式不同,加上它们通过innerHTML实现转换的方式也不一样,因此不能指望富文本编辑器会产生一致的HTML。
  • 除了命令之外,还有一些与命令相关的方法。第一个方法就是queryCommandEnabled(),可以用它来检测是否可以针对当前选择的文本,或者当前插入字符所在位置执行某个命令。这个方法接收一个参数,即要检测的命令。如果当前编辑区域允许执行传入的命令,这个方法返回true,否则返回false.例如:
var result = frames["richedit"].document.queryCommandEnabled("bold");
  • 如果能够对当前选择的文本执行"bold"命令,以上代码会返回true.需要注意的是,queryCommandEnabled()返回true,并不意味着实际上就可以执行相应命令,而只能说明对当前选择的文本执行相应命令是否合适。例如,Firefox在默认情况下会禁用剪切操作,但执行queryCommandEnabled("cut")也可能会返回true
  • 另外,queryCommandState()方法用于确定是否已经将指定命令应用到了选择的文本。例如,要确定当前选择的文本是否已经转换成了粗体,可以使用如下代码:
var isBold = frames["richedit"].document.queryCommandState("bold");
  • 如果此前已经对选择的文本执行了"bold"命令,那么上面的代码会返回true.一些功能全面的富文本编辑器,正式利用这个方法来更新粗体、斜体等按钮的状态的。
  • 最后一个方法是queryCommandValue,用于取得执行命令时传入的值(即前面例子中传给document.execCommand()的第三个参数)。例如,在对一段文本应用"fontsize"命令时如果传入了7,那么下面代码就会返回"7":
 var fontsize = frames["richedit"].document.queryCommandValue("fontsize");
  • 通过这个方法就可以确定某个命令时怎样应用到选择的文本的,可以据以确定再对其应用后续命令是否合适。

富文本选区

  • 在富文本编辑器中,使用框架(iframe)的getSelection()方法,可以确定实际选择的文本。这个方法是window对象和document对象的属性,调用它会返回一个表示当前选择文本的Selection对象。每个Selection对象都有下列属性。
属性 说明
anchorNode 选区起点所在的节点
anchorOffset 在到达选区起点位置之前跳过的anchorNode中的字符数量。
focusNode 选区终点所在的节点
focusOffset focusNode中包含在选区之内的字符数量
isCollapsed 布尔值,表示选区的起点和终点是否重合。
rangeCount 选区中包含的DOM范围的数量。
  • Selection对象的这些属性并没有包含多少有用的信息。还在,该对象的下列方法提供了更多信息,并且支持对选区的操作。
方法 说明
addRange(range) 将指定的DOM范围添加到选区中。
collapse(node,offset) 将选区折叠到指定节点中的相应的文本偏移位置。
collapseToEnd() 将选区折叠到终点的位置。
collapseToStart() 将选区折叠到起点的位置。
containsNode(node) 确定指定的节点是否包含在选区中。
deleteFromDocument() 从文档中删除选区中的文本,与document.execCommand('delete',false,null)命令的结果相同。
extend(node,offset) 通过将focusNode和focusOffset移动到指定的值来扩展选区。
getRangeAt(index) 返回索引对应的选区中的DOM范围
removeAllChildren(node) 从选区中移除所有的DOM范围。实际上,这样会移除选区,因为选区中至少要有一个范围。
removeRange(range) 从选区中移除指定的DOM范围。
selectAllChildren(node) 清除选区并选择指定节点的所有子节点
toString() 返回选区所包含的文本内容
  • Selection对象的这些方法都极为实用,他们利用了DOM范围来管理选区。由于可以直接操作选择文本的DOM表现,因此访问DOM范围与实用execCommand()相比,能够对富文本编辑器进行更加细化的控制。看下面例子:
        var selection = frames["richedit"].getSelection();

        //取得选择的文本
        var selectedText = selection.toString();

        //取得代表选区的范围
        var range = selection.getRangeAt(0);

        //突出显示选择的文本
        var span = frames["richedit"].document.createElement("span");
        span.style.backgroundColor = "yellow";
        range.surroundContents(span)
  • 以上代码会为富文本编辑器中被选择的文本添加黄色的背景。这里使用了默认选区中的DOM范围,通过surroundContents()方法将选区添加到了带有黄色背景的<span>元素中。

  • HTML5中将getSelection()方法纳入了标准,而且IE9,Firefox,Safari,Chrome,Opera8都实现了它。由于历史原因,在Firefox3.6+中调用document.getSelection()会返回一个字符串。为此,可以在Firefox3.6+中改作调用window.getSelection(),从而返回selection对象。Firefox8修复了document.getSelection()的bug,能返回与window.getSelection()相同的值。

  • IE8以及更早的版本不支持DOM范围,但我们可以通过它支持的selection对象操作选择的文本。IE中的selection对象是document的属性。前面讲过,要取得富文本编辑器中选择的文本,首先必须创建一个文本范围,然后再像下面这样访问其text属性。

        var range = frames["richedit"].document.selection.createRange();
        var selectedText = range.text;
  • 虽然使用IE的文本范围来执行HTML操作并不像使用DOM范围那么可靠,但也不失为一种有效的途径。要像前面使用DOM范围那样实现相同的文本高亮效果,可以组合使用htmlText属性和pasteHTML方法。
       var range = frames["richedit"].document.selection.createRange();
       range.pasteHTML("<span style=\"background-color:yellow\">" + range.htmlText + "</span>");
  • 以上代码通过htmlText取得了当前选区中的HTML,然后将其放在了一对<span>标签中,最后又使用pasteHTML()将结果重新插入到了选区中。
表单与富文本
  • 由于富文本编辑是使用iframe而非表单控件实现的,因此从技术上说,富文本编辑器并不属于表单。换句话说,富文本编辑器中的HTML不会被自动提交给服务器,而需要我们手工来提取并提交HTML。为此,通常可以添加一个隐藏的表单字段,让它的值等于从iframe中提取的HTML。具体来说,就是在提交表单之前,从iframe中提取出HTML,并将其插入到隐藏的字段中。下面就是通过表单的onsubmit事件处理程序实现上述操作的代码。
        EventUtil.addHandler(form, "submit", function (event) {
            event = EventUtil.getEvent(event);
            var target = EventUtil.getTarget(event);

            target.elements["comments"].value = frames["richedit"].document.body.innerHTML;
        })
  • 在此,我们通过文档主体的innerHTML属性取得了iframe中的HTML,然后将其插入到了名为"comments"的表单字段中。这样可以确保恰好在提交表单之前填充comments字段。如果想在代码中通过submit()来手工提交表单,那么一定不要忘记事先执行上面的操作。对于contenteditable元素,也可以执行类似的操作
        EventUtil.addHandler(form, "submit", function (event) {
            event = EventUtil.getEvent(event);
            var target = EventUtil.getTarget(event);

            target.elements["comments"].value = document.getElementById("#richedit").innerHTML;
        })
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容