在可編輯div中插入文字或圖片的問題解決思路

來源:互聯網
上載者:User

 最近在網上碰到一個人問了我一個問題,在可編輯div中插入文字或者圖片。因為web線上編輯器我從來只是用,基本不會去研究原始碼。後來正好一個線上聊天web項目中也要用到這個功能,我就特地看看了代碼。

   基本上編輯器或者線上聊天web頁面,是不太可能用textarea在做輸入框的,因為我們可能要插入圖片或者超級連結,因此選擇在iframe或者div作為輸入框是必須的。

   我這裡用的是 div.

  要使div可編輯 必須 加入 contentEditable="true" 這個屬性。

  然後就是擷取游標位置(或者選擇文字位置)進行文字或者html的插入 。

 由於Firefox等標準瀏覽器支援getSelection方法,IE9以上也支援,但是萬惡的iE6-8不支援,因此要分兩部分代碼來寫。由於這些代碼很簡單,以下先貼一遍

function insertHTML(html)       {           var dthis=$("#div3")[0];//要插入內容的某個div,在標準瀏覽器中 無需這句話            var sel, range;            if (window.getSelection)             {                    // IE9 and non-IE                    sel = window.getSelection();                    if (sel.getRangeAt && sel.rangeCount) {                    range = sel.getRangeAt(0);                    range.deleteContents();                    var el = document.createElement('div');                    el.innerHTML = html;                    var frag = document.createDocumentFragment(), node, lastNode;                    while ( (node = el.firstChild) )                     {                        lastNode = frag.appendChild(node);                     }                                   range.insertNode(frag);                    if (lastNode) {                    range = range.cloneRange();                    range.setStartAfter(lastNode);                    range.collapse(true);                    sel.removeAllRanges();                    sel.addRange(range);                    }                   }            }             else if (document.selection && document.selection.type !='Control')             {                         $(dthis).focus(); //在非標準瀏覽器中 要先讓你需要插入html的div 獲得焦點 ierange= document.selection.createRange();//擷取游標位置ierange.pasteHTML(html);//在游標位置插入html 如果只是插入text 則就是fus.text="..."$(dthis).focus();                          }       }

  以上代碼基本 完成了 在可編輯div中 插入指定的html內容,這些代碼在baidu或者google中到處可以搜到,因此不再解釋為什麼這麼寫(太普遍了)

 執行後 會發現在IE或者非標準瀏覽器中 是正常的。在Firefox或者chrome中 就不正常了

譬如  以下頁面 ,我有 不定數量的div(可能是程式動態產生),我只需要其中某一個div進行html的插入,其他不需要。

.....其他html元素.....<div id="div1" contentEditable="true"  ></div><div id="div2" contentEditable="true" ></div> <div contentEditable="true"  id="div3"></div> <input type="button" id="cmdInsert" onclick="執行向div3插入html方法"/>
.....其他html元素.....

 如上頁面 我只需要div3 支援插入html 其他兩個 只是可編輯而已。

使用上述代碼會發現,如果最後一個失去焦點的是 div3 那麼一切正常 如果 不是div3 或者 我又點到頁面其他控制項或者空白處,會發現插入的html沒有插入到我們想要的div3中而是插入到了 其他地方。

   這其實不是bug,而是正常現象,getSelection 可以橫跨很多域,因此無法保證 獲得出來的range一定是你需要的div

 這裡我再次申明,我實在不想看(哪怕看一眼)國內的線上web編輯器是如何?的。經過我翻查了度娘和google發現有個思路可以解決。

  其實我們要解決的就是一件事情,每當頁面上的元素(包括div或者任意元素) 獲得焦點又失去後,我們只需獲得最後一個失去焦點的div是否是div3,如果是則執行上述代碼,如果不是直接在div3的內容後面加入要插入的html(寫入程式碼就可以。不要告訴我 不會)

     一開始我想到的辦法是對div3設定一個click事件以及focus事件,當滑鼠點進去或者獲得焦點時 把一個變數 譬如叫做isdiv3 設定為true,點其他地方設定為false(這個方法實際上是行不通的,這裡我就不多解釋為什麼行不通,有各種不同的情形可以導致即使獲得焦點,isdiv3依然不會被設定為true,而且需要對每個html元素設定事件讓isdiv3變為false,這是很恐怖的事情).

  這裡我放出一種比較通用和不容易被幹擾的解決辦法。

 首先在 頁面的 最頂部寫上

 <style>

 div:focus{z-index:100;}  // 這裡隨意你設定多少值,100隻是舉個列子

</style>

上面這個樣式告訴我們,當只有div 獲得焦點後 他會產生一個css屬性就是 z-index被設定成了100,以任何形式失去焦點 這個css屬性就沒了。當然你也可以設定其他的css屬性。因為我們在點button執行函數的時候,div3也會失去焦點(getSelection 依然存在)

以下思路就清晰了 我們再寫一個函數

var lastFocusID="";function getFocus()       {        var divlist = document.getElementsByTagName('div');        for(var i=0; i<divlist.length; i++)         {            var ta = divlist.item(i);            if (window.getComputedStyle(ta, null).zIndex!=null && window.getComputedStyle(ta, null).zIndex == 100) {              if(ta.id && ta.id!=null)               lastFocusID=ta.id.toString();               else                lastFocusID="";               break;            }            else             lastFocusID="";         }               } //再加入一個全屏事件
 $(window).click(function(e)          {            if (window.getSelection)            {                 var getevent=e.srcElement?e.srcElement:e.target;//不要告訴我不知道這句的意思                               if(getevent.tagName=="INPUT" && getevent.id!=null && getevent.id=="cmdInsert")                {                    //代表 點了插入html的按鈕                    //則不執行getFocus方法                 }                else                  getFocus();//除非點了那個插入html的按鈕 其他時候必須要執行getFocus來更新最後失去焦點的div            }                                })

  然後修改一下 insertHTML 這個方法

 function insertHTML(html)       {           var dthis=$("#div3")[0];            var sel, range;            if (window.getSelection)             {                if(lastFocusID!="div3")               {
                $("#div3).html(dthis.innerHTML+html)     ;//說明 使用者可能在其他控制項上 進行焦點或者其他動作 則

return;//後面不執行了
}

。。。。。。。。。。//其他代碼照舊

    這樣就解決Firefox或者chrome裡面 會出現亂插入內容的現象。

   當然這隻是一個思路, 歡迎大家提供更好的辦法和效能更高的思路。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.