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

相关文章
相关标签/搜索