富文本編輯器開發簡介


前言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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索