先截个图看看效果:
前面讲过execCommand以及光标选区操作,富文本中核心应用便是如此。
大体思路就是根据浏览器兼容性利用execCommand以及选区去在可编辑话的iframe中进行插入代码以及样式。我们来一步步实现:
第一步:首先建立一个html文档
<body>
<div id='container'>
<div id="editor">
<span class=" editStr curr0" title='加粗' unselectable='on' range='bold'></span>
<span class="editStr curr1" title='斜体' unselectable='on' range='italic'></span>
<span class="editStr curr2" title='下划' unselectable='on' range='underline'></span>
<select title='fontname'>
<option >字体样式</option>
<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 title='fontsize'>
<option value="0">字体大小</option>
<option value="1">很小</option>
<option value="2">小</option>
<option value="3">中</option>
<option value="4">大</option>
<option value="5">很大</option>
<option value="6">特大</option>
</select>
<select title='forecolor'>
<option >字体颜色</option>
<option style="color:#000000" value="#000000">■■</option>
<option style="color:#990" value="#990">■■</option>
<option style="color:#cc6600" value="#cc6600">■■</option>
<option style="color:#cc9933" value="#cc9933">■■</option>
<option style="color:#999900" value="#999900">■■</option>
<option style="color:#009900" value="#009900">■■</option>
<option style="color:#3333ff" value="#3333ff">■■</option>
<option style="color:#6600cc" value="#6600cc">■■</option>
<option style="color:#993399" value="#993399">■■</option>
</select>
<select title='backcolor'>
<option >背景颜色</option>
<option style="color:#000000" value="#000000">■■</option>
<option style="color:#990" value="#990">■■</option>
<option style="color:#cc6600" value="#cc6600">■■</option>
<option style="color:#cc9933" value="#cc9933">■■</option>
<option style="color:#999900" value="#999900">■■</option>
<option style="color:#009900" value="#009900">■■</option>
<option style="color:#3333ff" value="#3333ff">■■</option>
<option style="color:#6600cc" value="#6600cc">■■</option>
<option style="color:#993399" value="#993399">■■</option>
</select>
<span class="editStr curr3"title='居中' unselectable='on' range='justifycenter'></span>
<span class="editStr curr4"title='居左' unselectable='on' range='justifyleft'></span>
<span class="editStr curr5"title='居右' unselectable='on' range='justifyright'></span>
<span class="editStr curr6"title='减少缩进' unselectable='on' range='outdent'></span>
<span class="editStr curr7"title='增加缩进' unselectable='on' range='indent'></span>
<span class="editStr curr8"title='无序' unselectable='on' range='insertunorderedlist'></span>
<span class="editStr curr9"title='有序' unselectable='on' range='insertorderedlist'></span>
<span class="editStr curr12"title='表格' unselectable='on' range='table'></span>
<span class="editStr curr10"title='超链接' unselectable='on' range='createlink'></span>
<span class="editStr curr11"title='图片' unselectable='on' range='insertimage'></span>
<span class="editStr curr13"title='表情' unselectable='on' range='faceImage'></span>
<span class="checkEdit"title='html' unselectable='on' range='html'><input type='checkBox' id='checkEdit'><p >查看源码</p></span>
</div>
<textarea id='myTextArea' disabled></textarea>
</div>
</body>
其中span类型的都把值放入自定义属性range中,select类型例如颜色字体放入select中值为value。以备后用.
第二步:
我们新建iframe以及将textArea隐藏,便于在源码以及编辑进行切换。iframe以及div都是可以操作的,在这里我们选取iframe并将其designMode属性设为on即开启编辑模式,
代码如下:
var editor = document.getElementById("editor");
var spans = editor.getElementsByTagName("span");
var selects = editor.getElementsByTagName("select");
var textarea = document.getElementById("myTextArea");
textarea.style.display = "none";
var iframe = document.createElement("iframe");
iframe.style.width = "1198px";
iframe.style.height = "380px";
iframe.frameBorder=0;
iframe.scrolling="no";
iframe.style.border='0px';
textarea.parentNode.insertBefore(iframe,textarea);
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
var iframeWindow=iframe.contentWindow;
iframeDocument.designMode = "on";
iframeDocument.write('<html><head></head><body ></body></html>');
var editMode=true;
var faceCreater,tableCreator;
第三步:
之后我们循环页面的span以及select,先将这些execCommand支持command加入我们的富文本编辑器中,只需要iframeDocument.execCommand(command,false,value)即可,
对于span来说value值没有可选性就置为空,对于html编辑状态源码之间切换以及table插入以及表情插入我们另说。先看基本功能。这里没有什么需要着重注意的,直接看代码:
for(var i = 0,l= spans.length;i<l;i++){
spans[i].onclick = (function(i){
var command=spans[i].getAttribute("range");
return function(){
if(command == 'createlink' || command == 'insertimage'){
var value =command=='createlink'? prompt('请输入超链接:', 'http://'):prompt('请选择图片:', 'http://');
iframeDocument.execCommand(command,false,value);
}else if(command=='html'){
if(editMode){//切换到textarea
iframe.style.display = "none";
textarea.style.display = "block";
textarea.value = iframeDocument.body.innerHTML;
//textarea.focus();
editMode = false;
document.getElementById('checkEdit').checked=true;
}else{//切换到iframe
iframe.style.display = "block";
textarea.style.display = "none";
iframeDocument.body.innerHTML = textarea.value;
iframe.contentWindow.focus();
editMode = true;
document.getElementById('checkEdit').checked=false;
}
}
else if(command=='table'){
//稍后另说
}
else if(command=='faceImage'){
}
else{
iframeDocument.execCommand(command,false,'');
}
}
})(i);
};
for(i=0,l=selects.length;i<l;i++){
selects[i].onchange = (function(i){
var select = selects[i];
return function(){
var command = select.getAttribute("title"),
value = select.options[select.selectedIndex].value;
if(command == 'backcolor' && window.navigator.userAgent.toLowerCase().indexOf("Firefox")){
iframeDocument.execCommand('hilitecolor',false,value);
}else{
iframeDocument.execCommand(command,false,value);
};
}
})(i);
};
补充一句这里的背景色在火狐中默认将背景色填充满整个iframe,所以做一下兼容处理。
第四步:
我们来额外处理table,由于execCommand中没有对table的支持,所以我们需要手动去实现:
实现思路我们首先要建立一个可以选择table的列以及行的选择框
1.
建立弹出层以供选择创建行列数:
tableCreator = document.createElement('div');
tableCreator.className = 'tablecreator';
editor.appendChild(tableCreator);
tableCreator.innerHTML = editTable();//生成弹出层内容代码函数
tableCreator.style.display='none';
2.
生成完之后样式如下图:
自定义行列之后点击确定
html = createTable(rows, cols, width);//创建自定义表格
insertHtml(html);
tableCreator.style.display = "none";
3.
最重要一步就是把生成表格置到我们的编辑器中也就是上述的insertHtml方法,这个方法接受的一个参数就是根据我们自定义的行列所生成的表格。
function insertHtml(html){
iframe.contentWindow.focus();
if(isIe){
if(lessThenIE9){
iframeDocument.selection.createRange().pasteHTML(html);
}
else{
iframeDocument.selection.createRange().pasteHTML(html);
//解决iframe无光标
var span=iframeDocument.createElement('span');
span.innerHTML=' ';
iframeDocument.body.appendChild(span);
}
}else{
iframeDocument.execCommand('inserthtml',false,html);
iframe.contentWindow.focus();
}
}
首先我们先对iframe获得焦点,对于ie来说以下不支持execCommand的inserthtml,不过可以根据ie特有的document.selection.createRange()选区操作去创建html(忘记的看这里),
并且利用其pasteHTML方法去方便的创建(不得不说其实ie还是有很多优秀的前瞻性的值得借鉴地方),
对于非ie浏览器就应用execCommand即可实现。
经过测试对于ie9,10来说生成表格之后都有一个bug,就是生成完表格之后光标无法从表格内部移除,也就使得无法继续对iframe进行富文本编辑。
这个里面的光标是无法移出来的。
为解决这个问题,我生成了一个空的span,并将其插入到iframe中,这样一来默认生成完html之后光标会落到最后,以解决iframe焦点问题。
这样以来整个流程就跑通了,并且任何浏览器都会兼容。
对于表情插入来说跟table插入是大同小异的,只不过插入的是一个带有选中表情图片url的img元素而已,在此不再赘述。