获取 content editable innerHTML 的子内容

Get sub contents of content editable innerHTML

我想在按键时将 contenteditable 的内容分成两部分。

<div contenteditable="true">This is <b>my content</b></div>

我想得到这句话的子串(不带HTML)从0到10,即:

这是我的

有没有办法在 JS 中做到这一点,它知道关闭将被切断的标签?还是需要自己写一个函数判断节点然后手动关闭?

我想return:

This is <b>my</b>

<b> content</b>

这是检索插入符号左侧的代码:

traverse = ( node: Node, selectedNode: Node, offset, direction = 0, parent = true ) => {
    if ( node.nodeName === '#text' ) {
      if ( node.isEqualNode(  selectedNode ) ) {
        return [ node.textContent.substr( 0, offset  ), node.textContent.substr( offset  ) ];
      }
      return node.textContent;
    }
    if ( node.childNodes.length === 1 && node.childNodes[0].nodeType === 3 ) {
      if ( node.childNodes[0].isEqualNode(  selectedNode ) ) {
        const newNode1 = node.cloneNode();
        const newNode2 = node.cloneNode();
        newNode1.innerHTML = node.childNodes[0].textContent.substr( 0, offset  );
        newNode2.innerHTML = node.childNodes[0].textContent.substr( offset );
        return [ newNode1.outerHTML, newNode2.outerHTML ];
      }
      return node.outerHTML;
    }
    if ( node.childNodes.length > 1 ) {
      let content = '';
      let found = false;
      for ( let x = 0; node.childNodes[x] && !found; x++ ) {
        let resp = this.traverse(  node.childNodes[x], selectedNode, offset, direction, false );
        if ( Array.isArray( resp ) ) {
          content += resp[0];
          found = true;
        } else {
          content += resp;
        }
      }
      if ( !parent ) {
        const newNode = node.cloneNode();
        newNode.innerHTML = content;
        return newNode.outerHTML;
      } else {
        return content;
      }
    }
  }

好吧,经过反复试验,我想通了。此函数接受一个元素或节点、所选节点和所选节点的偏移量,并将 return 两个 HTML 字符串用正确关闭的标签分成两半。

traverse = ( node: Node, selectedNode: Node, offset, parent = true ) => {
    let found = false;
    if ( node.nodeName === '#text' ) {
      if ( node.isEqualNode(  selectedNode ) ) {
        return [ node.textContent.substr( 0, offset  ), node.textContent.substr( offset  ) ];
      }
      return node.textContent;
    }
    if ( node.childNodes.length === 1 && node.childNodes[0].nodeType === 3 ) {
      if ( node.childNodes[0].isEqualNode(  selectedNode ) ) {
        const newNode1 = node.cloneNode();
        const newNode2 = node.cloneNode();
        newNode1.innerHTML = node.childNodes[0].textContent.substr( 0, offset  );
        newNode2.innerHTML = node.childNodes[0].textContent.substr( offset );
        return [ newNode1.outerHTML, newNode2.outerHTML ];
      }
      return node.outerHTML;
    }
    if ( node.childNodes.length > 1 ) {
      let content = ['', ''];
      for ( let x = 0; node.childNodes[x]; x++ ) {
        const resp = this.traverse(  node.childNodes[x], selectedNode, offset, false );
        if ( Array.isArray( resp ) ) {
          content[0] += resp[0];
          content[1] += resp[1];
          found = true;
        } else {
          if ( found ) {
            content[1] += resp;
          } else {
            content[0] += resp;
          }
        }
      }
      if ( !parent ) {
        const newNode1 = node.cloneNode();
        const newNode2 = node.cloneNode();
        newNode1.innerHTML = content[0];
        newNode2.innerHTML = content[1];
        if ( found ) {
          return [ newNode1.outerHTML, newNode2.outerHTML ];
        } else {
          return newNode1.outerHTML;
        }
      } else {
        if ( found ) {
          return content;
        } else {
          return content[0];
        }
      }
    }
  }