zoukankan      html  css  js  c++  java
  • cke点击时初始化编辑器后光标恢复的方法

    业务场景

    1、使用了CKEDITOR编辑器
    2、文本是使用contenteditable="true"的div容器
    3、点击文本时才初始化编辑器
    4、问题:编辑器初始化后光标会重置到开始处,如何将光标重置到点击处

    解决方案

    1、在点击文本的时候,在点击文本的时候,获取range信息和 endContainerendOffset;

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

    2、坑:直接点击图片,无法获取到range,需要把图片加入到range中;

           // 把图片加进选区
            if (e.target.nodeName === 'IMG') {
              var range2 = document.createRange();
              var selectTion = window.getSelection();
              selectTion.removeAllRanges();
              range2.selectNode(e.target);
              selectTion.addRange(range2);          
            }
    
    

    3、在初始化编辑器后,在它的instanceReady方法回调中进行光标恢复操作

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

    听起来很美好,对不对,但是在实际操作中发现,之前存储的endContainer已经被替换成新的range信息了。如何获取我们原来存储的endContainer呢?博主试了深拷贝,浅拷贝都不行,于是才用了遍历寻找的方法~~~

    4、找到原来的endContainer 的方法

    // 获取新的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;
      }
    

    5、恢复光标:这里需要再加个延迟,不然光标还没有初始化到开头处

    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)
              });
    

    6、坑:到这里,我们已经实现了光标恢复,但是会发现光标会现在起始处闪一下,再闪到我们点击处。作为有强迫症的前端肯定不能容忍这种操作了,这个我们使用样式就可以处理了:在开始点击的时候给目标div添加一个隐藏光标的样式,然后恢复光标的时候移除即可。

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

    让我们再看下效果:

    结束语

    至此,完成了我们的业务需求,当然第一次点击的时候会有不可见的1-2s的延迟,但是没办法,编辑器的初始化就需要1s多的时间。如果你有更好的想法,希望能跟我留言~

  • 相关阅读:
    【python】turtle龟绘制开了花朵的树,程序画图
    【python】一行代码,使用pychorus提取音乐高潮部分
    【python】自动打开指定软件
    【VBA】用excel玩游戏,俄罗斯方块
    【python】3行代码搞定音频剪辑,入门版
    【python】3分钟搞定音频剪辑,进阶版
    【python】一键生成漂亮的节日快乐词云图
    【python】python学习之循环语句,小实验:九九乘法表
    【python】python学习之条件语句,小实验:商品打折后价格
    【python】使用webdriver在网页输入关键词并截屏
  • 原文地址:https://www.cnblogs.com/webhmy/p/14638319.html
Copyright © 2011-2022 走看看