cke點擊時初始化編輯器後光標恢復的方法

業務場景

一、使用了CKEDITOR編輯器
二、文本是使用contenteditable="true"的div容器
三、點擊文本時才初始化編輯器
四、問題:編輯器初始化後光標會重置到開始處,如何將光標重置到點擊處
前端

解決方案

一、在點擊文本的時候,在點擊文本的時候,獲取range信息和 endContainerendOffset;node

try {
          range = window.getSelection().getRangeAt(0);
          var endContainer = range.endContainer;
          var endOffset = range.endOffset;         
        } catch (e) {
          console.log(e);
        }

二、坑:直接點擊圖片,沒法獲取到range,須要把圖片加入到range中;編輯器

// 把圖片加進選區
        if (e.target.nodeName === 'IMG') {
          var range2 = document.createRange();
          var selectTion = window.getSelection();
          selectTion.removeAllRanges();
          range2.selectNode(e.target);
          selectTion.addRange(range2);          
        }

三、在初始化編輯器後,在它的instanceReady方法回調中進行光標恢復操做ide

CKEDITOR.instances[id].once('instanceReady', () => {
 ...          
});

聽起來很美好,對不對,可是在實際操做中發現,以前存儲的endContainer已經被替換成新的range信息了。如何獲取咱們原來存儲的endContainer呢?博主試了深拷貝,淺拷貝都不行,因而才用了遍歷尋找的方法~~~spa

四、找到原來的endContainer 的方法code

// 獲取新的endContainer
  getEndContainer(endContainer, tag, endContainer2) {
    let childNodes = self.getAllChildNodes(tag);
    if (childNodes && childNodes.length > 0) {
      for (let i = 0, len = childNodes.length; i < len; i++) {
        let item = childNodes[i];
        if (
          (item.data && item.data === endContainer.data) ||
          (item.wholeText && item.wholeText === endContainer.wholeText) ||
          (item.innerHTML && item.innerHTML === endContainer.innerHTML)
        ) {
          // 爲了不有重複片斷,必須其父親也要相同,我這裏的每行父級元素都有類名cut-check
          let $endContainerParent = $(endContainer).hasClass('cut-check') ? $(endContainer) : $(endContainer).parents('.cut-check');
          let $itemParent = $(item).hasClass('cut-check') ? $(item) : $(item).parents('.cut-check');

          if ($endContainerParent.attr('data-value') === $itemParent.attr('data-value')) {
            endContainer2 = item;
            break;
          }
        }
      }
    }
    return endContainer2;
  }

五、恢復光標:這裏須要再加個延遲,否則光標尚未初始化到開頭處blog

CKEDITOR.instances[id].once('instanceReady', () => {
            setTimeout(() => {
              try {
                var newRange = document.createRange();
                var set = window.getSelection();

                // 找到與 endContainer 同樣的節點
                let endContainer2 = null;
                endContainer2 = self.getEndContainer(endContainer, tag, endContainer2);
                newRange.setEnd(endContainer2, endOffset);
                newRange.collapse(false);
                set.removeAllRanges();
                set.addRange(newRange);    
                
              } catch (e) {
                console.log(e)
              }              
            }, 500)
          });

六、坑:到這裏,咱們已經實現了光標恢復,可是會發現光標會如今起始處閃一下,再閃到咱們點擊處。做爲有強迫症的前端確定不能容忍這種操做了,這個咱們使用樣式就能夠處理了:在開始點擊的時候給目標div添加一個隱藏光標的樣式,而後恢復光標的時候移除便可。
圖片

.hide-caret {
  caret-color: transparent;
}

讓咱們再看下效果:
rem

結束語

至此,完成了咱們的業務需求,固然第一次點擊的時候會有不可見的1-2s的延遲,可是沒辦法,編輯器的初始化就須要1s多的時間。若是你有更好的想法,但願能跟我留言~get

相關文章
相關標籤/搜索