javascript 如何查找contenteditable=true标记的当前插入符号/光标索引< p>

niwlg2el  于 2023-04-10  发布在  Java
关注(0)|答案(1)|浏览(211)

我真的很难找到适合我的用例的答案。
标记光标/插入符号。
我试过各种解决方案,总是得到相同的问题,插入符号解决方案等于0。
这是一个沙盒示例。如果我能让它在这里工作,我就能让它在我的实际应用程序中工作。
需要的任何协助:

import { Component, h } from '@stencil/core'

@Component({
  tag: 'my-editable-component',
  styleUrl: 'my-editable-component.css',
  shadow: true,
})
export class MyEditableComponent {
  editableRef: HTMLParagraphElement

  getCaretPosition() {
    const selection = window.getSelection()
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0)
      const preCaretRange = range.cloneRange()
      preCaretRange.selectNodeContents(this.editableRef)
      preCaretRange.setEnd(range.endContainer, range.endOffset)
      return preCaretRange.toString().length
    }
    return 0
  }

  handleInput = () => {
    console.log('Caret position:', this.getCaretPosition())
  }

  render() {
    return (
      <div>
        <p ref={el => (this.editableRef = el as HTMLParagraphElement)} contentEditable onInput={this.handleInput}>
          Click to edit text and log caret position
        </p>
      </div>
    )
  }
}

第一次编辑

在对这个问题给出第一个答案之后,我想围绕我的用例和到目前为止我所看到的问题提供一些更多的上下文。
我正在构建一个文档编辑应用程序。对于本次讨论的范围,用户只需要能够编辑段落。到目前为止一切顺利。
我觉得我已经撞上了一堵砖墙,因为我已经开始尝试与插入符号互动。
我的应用程序的基本架构:

<document-editor >
 <document-paragraph />
</document-editor>

大部分的功能都存在于文档编辑器中,并在必要的时候传递给子级。状态管理也是如此。
父模具组件和子模具组件都有shadow: true
我面临的一个主要问题是,我无法访问HTMLElement.shadowRoot.getSelection()上的getSelection(),因为我遇到了一个编译器问题。
我相信这是根据MDN标记为非标准API的一部分。
我将在下面添加一些更详细的代码片段。请注意,在写这篇文章的时候,它们不应该工作,并且是对这篇文章的第一个答案的最新合成。这里的一个阻碍是上面链接的非标准API问题。
我用来返回当前插入符号位置的函数作为一个prop传递给子文档段落,在那里它被onKeyUp调用。
下面是函数:

getCurrentCaretIndex = (): number => {
// return (this.blockRefs.get(`block-id-${this.blocks[this.currentBlockIndex].id}`).querySelector('#editable-content') as HTMLTextAreaElement).selectionStart
// const documentParagraph = this.blockRefs.get(`block-id-${this.blocks[this.currentBlockIndex].id}`) as HTMLElement

const thisComponent = this.el

const documentComponent = this.blockRefs.get(`block-id-${this.blocks[this.currentBlockIndex].id}`)

const element = documentComponent.shadowRoot.querySelector('#editable-content') as HTMLElement

const selection = documentComponent.shadowRoot.getSelection()

let pos = selection.rangeCount
if (pos) {
  let range = selection.getRangeAt(0)
  let cloneRange = range.cloneRange()
  cloneRange.selectNodeContents(element)
  cloneRange.setEnd(range.endContainer, range.endOffset)
  pos = cloneRange.toString().length
}

return pos

}
我的TS编译器在使用shadowRoot.getSelection()x1c 0d1x时遇到了问题
因此,至少在我当前的配置中,我无法访问ID为editable-content的documentComponent元素上的shadowRoot.selection。
这真的很烦人,因为插入符号显然对文档编辑器至关重要。
我还尝试使用textarea代替,在那里我访问selection属性没有问题,但textarea不支持富文本:/
我错过什么了吗?

0wi1tuuw

0wi1tuuw1#

看起来你复制了一个ChatGPT答案,没有问正确的问题。
window.getSelection()但是你的DOM元素在它的shadowRoot中:

**注意:**扩展 * 自定义内置 * 元素,如HTMLParagraphElement,在Apple/Safari中无法使用。所有浏览器支持:extends HTMLElement

customElements.define("editable-p", class extends HTMLElement {
  constructor() {
    super().attachShadow({mode: "open"})
           .innerHTML = `<p><b></b> <span contenteditable></span></p>`;
  }
  getCaretPosition(el = this.shadowRoot.querySelector("[contenteditable]")) {
    let selection = this.shadowRoot.getSelection(); // here ChatGPT got it wrong
    let pos = selection.rangeCount;
    if (pos) {
      let range = selection.getRangeAt(0);
      let cloneRange = range.cloneRange();
      cloneRange.selectNodeContents(el);
      cloneRange.setEnd(range.endContainer, range.endOffset);
      pos = cloneRange.toString().length;
    }
    this.shadowRoot.querySelector("b").innerHTML = pos;
    return pos;
  }
  connectedCallback() {
    this.onkeyup = (evt) => this.getCaretPosition();
    this.onfocus = (evt) => setTimeout(()=>this.getCaretPosition());
    this.onclick = (evt) => setTimeout(()=>this.getCaretPosition());
    setTimeout(()=>this.shadowRoot.querySelector("[contenteditable]").innerHTML = this.innerHTML);
  }
});
<editable-p>Hello Web Component!</editable-p>
<editable-p>Hello Web Component World!</editable-p>

相关问题