前言javascript
富文本编辑器,Rich Text Editor, 简称 RTE, 是一种可内嵌于浏览器,所见即所得的文本编辑器。html
方式
iframe
页面中嵌入一个包含空HTML页面的iframe。设置designMode属性,使空白页面HTML的body能够被编辑。前端
designMode:off/onjava
* 页面加载完才能够设置designMode属性,因此须要使用onload事件。node
<iframe name="demoDesignMode" src="demoDesignMode.html" style="height: 100px;width: 100px;"></iframe> <script> window.onload= function(){ frames['demoDesignMode'].document.designMode = 'on'; } </script>
contenteditable
contenteditable='true'设置元素和它包含的元素能够编辑。web
* 区分contenteditable和contentEditable。contenteditable是元素的特性,而contentEditable是对象的属性。浏览器
<div id="box" style="height: 100px;width: 100px; border:1px solid black"></div> <button id="btn1">打开富文本编辑</button> <button id="btn2">关闭富文本编辑</button> <script> btn1.onclick = function(){box.contentEditable = true;} btn2.onclick = function(){box.contentEditable = false;} </script>
命令
document.execCommand()对文档执行预约义的命令。微信
document.execCommand(String aCommandName, Boolean aShowDefaultUI, String aValueArgument):编辑器
aCommandName测试
一个 DOMString ,命令的名称。可用命令列表请参阅 命令 。
aShowDefaultUI
一个 Boolean, 是否展现用户界面,通常为 false。Mozilla 没有实现。
aValueArgument
一些命令(例如insertImage)须要额外的参数(insertImage须要提供插入image的url),默认为null。
* 由于浏览器兼容性问题,第二个参数要为false,firefox在该参数为true时抛出错误。
格式段落
居中 document.execCommand('justifyCenter');
左对齐 document.execCommand('justifyLeft');
右对齐 document.execCommand('justifyRight');
添加缩进 document.execCommand('indent');
去掉缩进 document.execCommand('outdent');
文本格式
字体类型 document.execCommand('fontname',false,sFontName)
字体大小 document.execCommand('fontsize',false,sFontSize)
字体颜色 document.execCommand('forecolor',false,sFontColor)
背景色 document.execCommand('backColor',false,sBackColor)
加粗 document.execCommand('bold');
斜体 document.execCommand('italic');
下划线 document.execCommand('underline');
编辑
复制 document.execCommand('copy');
剪切 document.execCommand('cut');
粘贴 document.execCommand('paste');(经测试无效)
全选 document.execCommand('selectAll');
删除 document.execCommand('delete');
后删除 document.execCommand('forwarddelete');
清空格式 document.execCommand('removeFormat');
前进一步 document.execCommand('redo');
后退一步 document.execCommand('undo');
打印 document.execCommand('print');(对firefox无效)
插入
插入标签 document.execCommand('formatblock',false,elementName);
插入<hr>
document.execCommand('inserthorizontalrule');
插入<ol>
document.execCommand('insertorderedlist');
插入<ul>
document.execCommand('insertunorderedlist');
插入<p>
document.execCommand('insertparagraph');
插入图像 document.execCommand('insertimage',false,URL);
增长连接 document.execCommand('createlink',false,URL);
删除连接 document.execCommand('unlink');
选区
getSelection()方法
属性
anchorNode:选区起点所在的节点
anchorOffset:在到达选区起点位置以前跳过的anchorNode中的字符数量
focusNode:选区终点所在的节点
focusOffset:focusNode中包含在选区以内的字符数量
isCollapsed:布尔值,表示选区的起点和终点是否重合
rangeCount:选区中包含的DOM范围的数量
方法
addRange(range):将指定的DOM范围添加到选区中
collapse(node,offset):将选区折叠到指定节点中的相应的文本偏移位置
collapseToEnd():将选区折叠到终点位置
collapseToStart():将选区折叠到起点位置
containsNode(node):肯定指定的节点是否包含在选区中
deleteFromDocument():从文档中删除选区中的文本,与document.execCommand("delete",false,null)命令的结果相同
extend(node,offset):经过将focusNode和focusOffset移动到指定的值来扩展选区
getRangeAt(index):返回索引对应的选区中的DOM范围
removeAllRanges():从选区中移除全部DOM范围。实际上,这样会移除选区,由于选区中至少要有一个范围
reomveRange(range):从选区中移除指定的DOM范围
selectAllChildren(node):清除选区并选择指定节点的全部子节点
toString():返回选区所包含的文本内容
* IE8-浏览器不支持,我试了IE8以上也不支持
selection对象
术语
anchor:选中区域的“起点”。
focus:选中区域的“结束点”。
range:是一种fragment(HTML片段),它包含了节点或文本节点的一部分。
属性
anchorNode:返回包含“起点”的节点。
anchorOffset:“起点”在anchorNode中的偏移量。
focusNode:返回包含“结束点”的节点。
focusOffset:“结束点”在focusNode中的偏移量。
isCollapsed:“起点”和“结束点”是否重合。
rangeCount:返回selection中包含的range对象的数目,通常存在一个range,Ctrl健配合使用能够有多个。
方法
getRangeAt(index):从当前selection对象中得到一个range对象。
collapse(parentNode, offset):将开始点和结束点合并到指定节点(parentNode)的相应(offset)位置。
extend(parentNode, offset): 将“结束点”移动到指定节点(parentNode)的指定位置(offset)。
modify(alter, direction, granularity): 改变焦点的位置,或扩展|缩小selection的大小。
collapseToStart():将“结束点”移动到,selction的“起点”,多个range时也是如此。
collapseToEnd():将“起点”移动到,selction的“结束点”,多个range时也是如此。
selectAllChildren(parentNode):将parentNode的全部后代节点(parentNode除外)变为selection,页面中原来的selection将被抛弃。
apRange(range):将range添加到selection当中,因此一个selection中能够有多个range。
removeRange(range):从当前selection移除range对象,返回值undefined。
removeAllRanges():移除selection中全部的range对象,执行后anchorNode、focusNode被设置为null,不存在任何被选中的内容。
toString():返回selection的纯文本,不包含标签。
containsNode(aNode, aPartlyContained): 判断一个节点是不是selction的一部分。
表单提交
富文本编辑不是使用表单控件实现的,而须要手工来提取并提交HTML。为此,一般能够添加一个隐藏的表单字段,就是在提交表单以前提取出HTML,并将其插入到隐藏的字段中。
iframe
form.onsubmit = function(e){ e = e || event; var target = e.target || e.srcElement; target.elements["comments"].value = frames["richedit"].document.body.innerHTML; }
contenteditable
form.onsubmit = function(e){ e = e || event; var target = e.target || e.srcElement; target.elements["comments"].value = document.getElementById('wysiwyg').innerHTML; }
实战
结构
<div id="editor-box"> <div id="editor-icon"> <div class="icon-box"> <span class="glyphicon glyphicon-bold" data-role="bold">加粗</span> <span class="glyphicon glyphicon-italic" data-role="italic">斜体</span> <span class="glyphicon glyphicon-align-center" data-role="justifyCenter">居中</span> <span class="glyphicon glyphicon-align-left" data-role="justifyLeft">左对齐</span> <span class="glyphicon glyphicon-align-right" data-role="justifyRight">右对齐</span> <span class="glyphicon" data-role="indent">添加缩进</span> <span class="glyphicon" data-role="outdent">去掉缩进</span> <span class="glyphicon" data-role="h1">h1</span> <span class="glyphicon" data-role="h2">h2</span> <span class="glyphicon" data-role="p">p</span> </div> </div> <div id="editor" contenteditable="true"> </div> </div>
js
$(document).ready(function(e) { $('.icon-box span').click(function(e) { $('#editor').focus(); getC($('#editor')) switch($(this).data('role')) { case 'h1': case 'h2': case 'p': document.execCommand('FormatBlock', false, '<' + $(this).data('role') + '>'); console.log($(this).data('role')); break; default: document.execCommand($(this).data('role'), false, null); break; } }) }); function getC(that){ if(document.all){ that.range=document.selection.createRange(); that.range.select(); that.range.moveStart("character",-1); }else{ that.range=window.getSelection().getRangeAt(0); that.range.setStart(that.range.startContainer, that.range.startContainer.length); } }
总结
实现一个富文本编辑器没有想的那么容易哦,这个只是简单的实践,实际是一个大工程哦。请看这个文章:
https://www.zhihu.com/question/38699645?sort=created
推荐几个编辑器:
widgEditor
wangeditor
ueditor
-------------------------------------
长按二维码或搜索 fewelife 关注咱们哦
本文分享自微信公众号 - 云前端(fewelife)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。