一步步教你实现富本文编辑器(第一部分)
先打造好毛坯,添加上各位按钮与下拉选择框,如字体、字号、对齐、斜体、加粗、编号、缩进、背景色、前景色……为了方便我们按制样式,按钮是用span模拟的。
<! doctype html> < html dir="ltr" lang="zh-CN"> < head > < meta charset="utf-8"/> < meta http-equiv="X-UA-Compatible" content="IE=Edge"> < style type="text/css"> #editor{ float:left; width:380px;background:#D5F3F4;padding-left:10px; } #editor span.button{ display:block;float:left;border: 1px solid #CCC;margin:1px 5px 1px 0px ;color: #000; background: #D0E8FC;width:40px;height:20px;text-align:center; } #editor select{ display:block; float:left;height:20px;width:60px;margin-right:5px;} textarea {width:382px;height:100px;} </ style > < title >富文本编辑器</ title > </ head > < body > < div id="editor"> < span class="button">加粗</ span > < span class="button">斜体</ span > < span class="button">下划</ span > < span class="button">居中</ span > < span class="button">居左</ span > < span class="button">居右</ span > < span class="button">悬挂</ span > < span class="button">缩进</ span > < span class="button">无序</ span > < span class="button">有序</ span > < select > < option value="SimSun">宋体</ option > < option value="LiSu">隶书</ option > < option value="KaiTi_GB2312">楷体</ option > < option value="YouYuan">幼圆</ option > < option value="SimHei">黑体</ option > < option value="Microsoft YaHei">雅黑</ option > < option value="Comic Sans MS">Comic Sans MS</ option > </ select > < select > < option value="1">1</ option > < option value="2">2</ option > < option value="3">3</ option > < option value="4">4</ option > < option value="5">5</ option > </ select > < select > < option style="color:#000000" value="#000000">■■</ option > < option style="color:#FF8080" value="#FF8080">■■</ option > < option style="color:#FFFF00" value="#FFFF00">■■</ option > < option style="color:#80FF00" value="#80FF00">■■</ option > < option style="color:#00FFFF" value="#00FFFF">■■</ option > < option style="color:#0000FF" value="#0000FF">■■</ option > < option style="color:#FF00FF" value="#FF00FF">■■</ option > </ select > < select > < option style="color:#000000" value="#000000">■■</ option > < option style="color:#FF8080" value="#FF8080">■■</ option > < option style="color:#FFFF00" value="#FFFF00">■■</ option > < option style="color:#80FF00" value="#80FF00">■■</ option > < option style="color:#00FFFF" value="#00FFFF">■■</ option > < option style="color:#0000FF" value="#0000FF">■■</ option > < option style="color:#FF00FF" value="#FF00FF">■■</ option > </ select > </ div > < br style="clear:both"/> < textarea ></ textarea > </ body > </ html > |
然后我们就可以加入行为层代码了。富文本编辑器用到一个非常关键的脚本document.execCommand( command, showUI, value )。
我们把各命令的参数放到按钮的title中,并在onclick与onchange时调用它们。
<div id= "editor" > <span class= "button" title= "bold" >加粗</span> <span class= "button" title= "italic" >斜体</span> <span class= "button" title= "underline" >下划</span> <span class= "button" title= "justifycenter" >居中</span> <span class= "button" title= "justifyleft" >居左</span> <span class= "button" title= "justifyright" >居右</span> <span class= "button" title= "outdent" >悬挂</span> <span class= "button" title= "indent" >缩进</span> <span class= "button" title= "insertunorderedlist" >无序</span> <span class= "button" title= "insertorderedlist" >有序</span> <select title= "fontname" > <!-- 省略 --> </select> <select title= "fontsize" > <!-- 省略 --> </select> <select title= "forecolor" > <!-- 省略 --> </select> <select title= "backcolor" > <!-- 省略 --> </select> </div> |
window.onload = function (){ var editor = document.getElementById( "editor" ); var buttons = editor.getElementsByTagName( "span" ); var selects = editor.getElementsByTagName( "select" ); for ( var i = 0,l= buttons.length;i<l;i++){ buttons[i].onclick = new function (){ var button=buttons[i]; return function (){ document.getElementById( "exe" ).innerHTML = "调用了" +button.getAttribute( "title" )+ "命令" ; } }; }; for (i=0,l=selects.length;i<l;i++){ selects[i].onchange = new function (){ var select = selects[i]; return function (){ document.getElementById( "exe" ).innerHTML = "调用了" +select.getAttribute( "title" )+ "命令,并传入了" + select.options[select.selectedIndex].value+ "参数!" ; }; }; }; } |
好了,那么怎么样编辑文本区(textarea)的文字呢?错,文本区的文字本身就可以编辑,就是怎么也不可能显示其编辑后的效果。我们通常是在div与iframe中编辑。要想在DIV中编辑,设置其contentEditable = "true",若iframe,还可以用designMode="on"。通常人们都是用ifame,这样做当然有它的道理,但一开始,照顾初心者,我们用div实现一下吧。
< div id="workaround"> </ div > |
#workaround { width : 382px ; height : 100px ; border : 1px solid #0065FD ;} |
那么怎么获得我们选中的文字?不,这个提法也不对,我们不是对文字直接进行操作,而对能对这些文字进行操作的对象进行操作……实在太拗口了!这就是传说中的Range对象了!
var getRangeObject = function (){ if (document.implementation.hasFeature( "Range" , "2.0" )){ return document.createRange(); //W3C } else { return document.selection.createRange(); //IE } } |
但上面这个函数离我们的目标有些差距,无错,document.selection.createRange.execCommand('bold')就可以把我们选出中的文字加粗了,但火狐那边就不是这回事!这与它们的执行模式有关,当我们选中一段文字时,IE会立即把它们放进Range对象中,但符合W3C标准的游览器不会,它是空的,虽然我们手动加入……手动加入就手动加入吧,自己动手,丰衣足食!
var getRangeObject = function () { if (window.getSelection){ //W3C var range = document.createRange(), selection = window.getSelection(); range.setStart(selection.anchorNode, selection.anchorOffset); range.setEnd(selection.focusNode, selection.focusOffset); return range; } else { //IE return document.selection.createRange(); } } |
但是还是失败了,究其原因,标准的Range对象(有关Range的介绍)是没有execCommand()方法。而IE的Range对象,说到底是TextRange对象,两者有很大差别。那怎么办?先放一放它,先实现了IE的再说,以后我们用iframe的document来执行execCommand()便是!
window.onload = function (){ var editor = document.getElementById( "editor" ); var buttons = editor.getElementsByTagName( "span" ); var selects = editor.getElementsByTagName( "select" ); var workaround = document.getElementById( "workaround" ); workaround.contentEditable = "true" ; for ( var i = 0,l= buttons.length;i<l;i++){ buttons[i].onclick = new function (){ var command=buttons[i].getAttribute( "title" ); return function (){ document.selection.createRange().execCommand(command); //IE only } }; }; for (i=0,l=selects.length;i<l;i++){ selects[i].onchange = new function (){ var select = selects[i]; return function (){ var command = select.getAttribute( "title" ), value = select.options[select.selectedIndex].value; document.selection.createRange().execCommand(command, false ,value); //IE only }; }; }; } |
注意,我们在按扭上面绑定了一个IE私有属性unselectable,并设置为on,这是防止当我们点击按钮时,TextRange对象因为选择对象转移,把原来选择的文本丢失了。其他游览器也有相似的功能,如safari,chrome为onselectstart="return false;" ,火狐为 style="-moz-user-select:none;"。
虽然兼容火狐失败,但作为副产品,搞了这个
下一部分,我们将改用iframe实现富本编辑器,处理众多的兼容问题!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步