我的富文本編輯器

先截個圖看看效果:


前面講過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='&nbsp';

                    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元素而已,在此不再贅述。

下載完整代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章