初试富文本编辑器

都说富文本编辑器是天坑,我也去坑边看一眼

为什么都说富文本编辑器是天坑?。早就听说过富文本编辑器,一般看到这种标题都会让人有一种想去试试的冲动,至少也要去溜达一圈,就像地牢围攻1的绝望洞一样。于是我去MDN上找了找教程。原来现成的代码都有。

要尝试点什么?

  1. MDN的代码,无法实现光标位置变化之后,读取光标处的文本格式,并改变样式按钮状态的功能。比如word里面,光标处的文本是加粗的话,工具栏的加粗按钮就变成按下状态,离开这段区域之后又会变成未按下状态。要实现这个功能,基本思路就是利用点击和键盘事件加上queryCommandState,大致代码如下:

    var editor = document.getElementById('editor');
    editor.addEventListener('keyup', function() {
    statusCheck(buttons);
    });
    editor.addEventListener('mouseup', function() {
    statusCheck(buttons);
    });

    function statusCheck(buttons) {
    commands.forEach(function(command) {
    var state = document.queryCommandState(command.cmd);
    var className = buttons[command.cmd].className;
    if (state) {
    buttons[command.cmd].className = addClass(className, 'on');
    } else {
    buttons[command.cmd].className = removeClass(className, 'on');
    }
    });
    }

  2. 无法取得选中区域的文字。因为getSelection只返回选择的起始和结束的DOM元素及信息,如果想要取得所选文件,必须自己去遍历选中的DOM节点,取出其中的text节点。大致代码实现如下:

    function getSelectedText() {
    var selection = getSelection();

      // 取得开始的文字
      var anchorNode = selection.anchorNode;
      var anchorOffset = selection.anchorOffset;
      var focusNode = selection.focusNode;
      var focusOffset = selection.focusOffset;
    
      // 判断选择的方向
      var isForward = isNodeBefore(anchorNode, focusNode);
      var startNode;
      var endNode;
      var startOffset;
      var endOffset;
      if (isForward) {
          startNode = anchorNode;
          endNode = focusNode;
          startOffset = anchorOffset;
          endOffset = focusOffset;
      } else {
          startNode = focusNode;
          endNode = anchorNode;
          startOffset = focusOffset;
          endOffset = anchorOffset;
      }
    
      var text1 = '';
      if (startNode !== null) {
          var startText = startNode.data;
          text1 = startText.substring(startOffset);
      }
    
      // 取得结束的文字
    
      var text2 = '';
      if (endNode !== null) {
          var endText = endNode.data;
          text2 = endText.substring(0, endOffset);
      }
    
    
    
      //取得中间的文字
      var middleText = '';
      if (startNode !== null && endNode !== null) {
          middleText = getMiddleText(startNode, endNode);
      }
    
      return text1 + middleText + text2;

    }

    function getMiddleText(startNode, endNode) {
    if (startNode === null && endNode === null) {
    return;
    }

      var pivot = startNode;
      var middleText = '';
      var text;
      while(pivot !== endNode) {
          text = '';
          if (pivot.nextSibling === null) {
              if (pivot.parentNode === null) {
                  break;
              } else {
                  pivot = pivot.parentNode;
              }
          } else {
              pivot = pivot.nextSibling;
              text = traversal(pivot);
          }
          middleText += text;
      }
    
      return middleText;
    
      // 遍历节点选择文字
      function traversal(root) {
          if (pivot === endNode) {
              return '';
          }
          if (root.nodeType === 3) {
              return root.nodeValue;
          } else {
              var text = '';
              var childNodes = root.childNodes;
              for (var i = 0; i < childNodes.length; i++) {
                  if (childNodes[i] === endNode) {
                      pivot = endNode;
                      break;
                  }
                  text += traversal(childNodes[i]);
              }
              return text;
          }
      }

    }

    function isNodeBefore(startNode, endNode) {
    var startParents = getParents(startNode), endParents = getParents(endNode);
    var count = Math.min(startParents.length, endParents.length);
    var commonParent, startParent, endParent;
    for (var i = 0; i < count; i++) {
    startParent = startParents[startParents.length - i - 1];
    endParent = endParents[endParents.length - i - 1];
    if (startParent === endParent) {
    commonParent = startParent;
    } else {
    var startPos = convertToArray(commonParent.childNodes).indexOf(startParent);
    var endPos = convertToArray(commonParent.childNodes).indexOf(endParent);
    return startPos < endPos;
    }
    }
    return true;
    }

难得能用上一点点数据结构的知识

完整代码

尽管惨不忍睹,我还是献丑放上来。不被婊怎么进步,虽然我觉得也不会有人觉得值得花功夫婊。(以后再也不贴大段代码了,调格式好累。这次就当充数了。结果调格式的过程中自己给自己增加了点击量)

转载于:https://www.cnblogs.com/linden5/p/7580642.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值