先截個圖看看效果:
前面講過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元素而已,在此不再贅述。