美文网首页web前端
可编辑div的光标定位问题

可编辑div的光标定位问题

作者: 姜治宇 | 来源:发表于2021-12-17 16:41 被阅读0次

上次分享了全局input增加敏感词检测的功能,有人私信我:如何解决光标漂移问题?
我们每次替换完文本,光标总是会飘到文本的最前面,而且不仅是input文本框,富文本编辑器(可编辑div)也有这个问题,如果直接用innerHTML方法直接替换内容的话,也会出现光标漂移的问题,如何解决呢?
我们先要搞清楚光标是个啥东西,其实光标这玩意本身就是一个js对象,其本身封装了一些属性和方法。
index.html:

    //================================过滤敏感词===================================================//
    document.addEventListener('input', debounce(handleWords, 800));
    function handleWords(e) {
      console.log('currentPos>>>', getCursorPos(e.target));
      let words = e.target.value;
      let wordType = '';
      if(e.target.nodeName === 'INPUT' && (!e.target.getAttribute('type') || e.target.getAttribute('type')=== 'text')) {
        console.log('text标签');
        wordType = 'input';
      }
      if (words && e.target.nodeName === 'TEXTAREA') {
        wordType = 'textarea';
      }
      if (!words && e.target.nodeName === 'DIV') {
        //可编辑文本框,包括富文本
        words = e.target.innerHTML;
        wordType = 'div';
      }
      //查询敏感词
      if (words && wordType) {
        //空白字符不做检测
        if(e.target.nodeName === 'DIV' && !e.target.innerText.replace(/\s+/g,'')){
          return false;
        }
        fetch(`/checkSensitiveWords`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          body: `words=${words}&wordtype=${wordType}`
        }).then(response => response.text()).then(res => {
          if (res) {
            if (wordType === 'input') {
              e.target.value = res;
              setCursorPos(e.target, getCursorPos(e.target));//设置光标位置
            } else if (wordType === 'div') {

              pasteHtmlAtCaret(e.target, res);//不可使用e.target.innerHTML,会有光标漂移问题
            }

            e.target.dispatchEvent(new Event('input'));//更新ngModel视图
          }


        })
      }
    }
    function pasteHtmlAtCaret(el, html, selectPastedContent) {//参数1为要插入的html //参数2为boolean 是否选中插入的html 默认为false
      var sel, range;
      if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
          range = sel.getRangeAt(0);
          range.deleteContents();

          // Range.createContextualFragment() would be useful here but is
          // only relatively recently standardized and is not supported in
          // some browsers (IE9, for one)

          el.innerHTML = html;
          var frag = document.createDocumentFragment(), node, lastNode;
          while ((node = el.firstChild)) {
            lastNode = frag.appendChild(node);
          }
          var firstNode = frag.firstChild;
          range.insertNode(frag);

          // Preserve the selection
          if (lastNode) {
            range = range.cloneRange();
            range.setStartAfter(lastNode);
            if (selectPastedContent) {
              range.setStartBefore(firstNode);
            } else {
              range.collapse(true);
            }
            sel.removeAllRanges();
            sel.addRange(range);
          }
        }
      } else if ((sel = document.selection) && sel.type != "Control") {
        // IE < 9
        var originalRange = sel.createRange();
        originalRange.collapse(true);
        sel.createRange().pasteHTML(html);
        if (selectPastedContent) {
          range = sel.createRange();
          range.setEndPoint("StartToStart", originalRange);
          range.select();
        }
      }
    }
    //获取光标位置,仅对input有效
    function getCursorPos(input) {
      var pos = 0;
      // IE Support
      if (document.selection) {
        input.focus();
        var sel = document.selection.createRange();
        var selLen = document.selection.createRange().text.length;
        sel.moveStart('character', -input.value.length);
        pos = sel.text.length - selLen;
      }
      // Firefox support
      else if (input.selectionStart || input.selectionStart == '0')
        pos = input.selectionStart;

      return pos;
    }
    //设置光标位置,仅对input有效
    function setCursorPos(obj, pos) {

      if (obj.setSelectionRange) {//Firefox/Safari/Chrome/Opera
        obj.focus();
        obj.setSelectionRange(pos, pos);
      } else if (obj.createTextRange) { // IE
        var range = obj.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
      }
    }
    //防抖
    function debounce(fn, delay) {
      var timer = null;
      return function (...args) {
        if (timer) {
          clearTimeout(timer)
        }
        timer = setTimeout(() => {
          fn.apply(this, args)
        }, delay)
      }
    }

后台代码:

    @ApiOperation({ summary: "过滤敏感词", description: "过滤敏感关键词和特殊字符" })
    @Post('checkSensitiveWords')
    async checkSensitiveWords(@Body() params): Promise<any> {
        let words = params.words;
        let wordType = params.wordtype;
        let newWords = words;

        if (words) {
            let sensitiveWords = sensitiveWordsFunc();
            if (Array.isArray(sensitiveWords)) {
                sensitiveWords.forEach(item => {

                    let stripSpecWords = words;
                    if(wordType === 'input') {
                        stripSpecWords = words.replace(/\s+/g, "");//获取字符串信息,清除所有空格
                        stripSpecWords = stripSpecWords.replace(/[\-\_\,\!\|\~\`\(\)\#\$\%\^\&\*\{\}\:\;\"\L\<\>\?]/g, '');
                    }
                    let reg = new RegExp(item,"ig");
                    if (item && reg.test(stripSpecWords)) {
                        
                        newWords = stripSpecWords.replace(reg, '囗'.repeat(item.length));
                    }

                });
                console.log('newords>>>', newWords);
                return newWords;
            }

        }
        return newWords;
    }

相关文章

  • 可编辑div的光标定位问题

    上次分享了全局input增加敏感词检测的功能,有人私信我:如何解决光标漂移问题?我们每次替换完文本,光标总是会飘到...

  • textarea高度自适应自动增高撑开

    方法一:div模拟textarea文本域实现高度自适应 div模拟textarea出现光标实现编辑功能,可添加此属...

  • 如何定位可编辑div光标的像素坐标

    在可编辑div里面,我们想要实现如下图一样的逻辑定位,就要知道光标在document或者父级的坐标。 我是利用添加...

  • 可编辑div问题总结(光标,显示等)

    背景:需要编写一个简单的文本输入框,要求可以添加超链接,并且超链接可以修改内容,超链接在文本框中只显示标题(类似在...

  • 关于firefox中可编辑div

    1.在可编辑的div中,若有绝对定位元素 和图标,点击时,周围会出现可缩放状态的边框,针对这种问题,可以修改布局 ...

  • 光标显示控制

    前言: 遇到一个需求:需要在可编辑的div有了内容后点击后光标出现在div的内容后面,'科学查询'了很多方法,最后...

  • Vim 常用命令整理

    编辑 / 打开文件 打开文件filename[,并将光标定位到n行]vim filename [+n] 其他命令:...

  • 解决百度编辑器ueditor默认有空格的问题

    问题: 引入百度编辑器之后,光标定位到如图所示的地方: 原因: 引入ueditor时JS代码有换行 解决方法: 去...

  • object元素覆盖div的处理

    解决div和object元素重叠时div被object覆盖的问题:在div内插入iframe元素,定位z-inde...

  • vi vim中常用命令

    开启编辑模式i: 在光标处开始编辑I: 在光标所在的行首开始编辑a: 在光标所在的下一个字符开始编辑A: 在光标所...

网友评论

    本文标题:可编辑div的光标定位问题

    本文链接:https://www.haomeiwen.com/subject/famifrtx.html