Javascript 反应:封装选择文本

Javascript 反应:封装选择文本,javascript,html,reactjs,Javascript,Html,Reactjs,我需要一些帮助。 在我的申请中,我有以下情况: Lorem ipsum只是印刷和排版行业的虚拟文本。Lorem Ipsum一直是业界的热门产品 当我选择文本时,我需要在短时间内将其封装,但不会丢失任何标签。例如,通过以下方式: >代码> >“IpSUM”,简单地说“,如果你看,中间是强的结束标记,那么你真的会选择以下内容:”IpSUP就是“ > 我需要通过javascript进行选择,文本只封装在span中,类似的内容仍然存在: Lorem ipsum只是印刷和排版行业的虚拟文本。Lor

我需要一些帮助。 在我的申请中,我有以下情况:

Lorem ipsum只是印刷和排版行业的虚拟文本。Lorem Ipsum一直是业界的热门产品

当我选择文本时,我需要在短时间内将其封装,但不会丢失任何标签。例如,通过以下方式:

<乱数假文> >代码> >“IpSUM”,简单地说“<乱数假文>,如果你看,中间是强的结束标记,那么你真的会选择以下内容:<代码>”IpSUP<强>就是“<代码> > 我需要通过javascript进行选择,文本只封装在span中,类似的内容仍然存在:

Lorem ipsum只是印刷和排版行业的虚拟文本。Lorem Ipsum一直是业界的热门产品

如您所见,在
中,它是一个被选中的文本,它在一个标记中,在
之外,还有另一个被选中的文本。 还有一点是,如果有多个段落,并且在这些段落之间选择了文本,则这些段落会被保留,但即使如此,所选文本也会被封装在一个
中,类似这样:

Lorem ipsum,absolem dut

阿门同侧疼痛

假设您选择以下选项:
“absolem dut Amen pain”
“absolem dut”
属于一个段落,而“Amen pain”属于另一个段落,这将产生如下结果:

Lorem ipsum,absolem dut

````
阿门痛```

我已经尝试使用窗口的getSelection属性中的getContains,但它不起作用,这会生成一个新段落。如果有人知道怎么做或者有想法​​如何使用JS节点或者如果问题有任何说明,我将非常感激


我找到了一个普通的解决方案,因为这个函数处于React

状态,所以经过多次尝试和错误,我相信我已经创建了一些解决您请求的问题的方法。如果没有,请尽快告诉我。在编写代码之前,请简要说明生产使用时需要修复的内容。

需要优化
  • 更改为编辑文档片段而不是范围,然后替换为一个操作
    • 基本上要做到这一点,您需要将replace-live转换为take-replace节点,或者更好地将整个编辑的块拉成一个片段,并在对象上而不是在DOM树上运行它。不过,我将把这件事留给你
  • 找出一个完全多平台的解决方案,虽然这在桌面上的firefox上有效,但我不能保证对于所有平台,对范围和选择Web API的支持都得到了充分的覆盖,特别是对于这里使用的功能。
  • 如果在React中使用了这一点,您可能需要使用state(钩子或类,我更喜欢钩子)跟踪所选内容。实际上,使用REF(可能是react REF,但可能不是,如果您有任何问题,请查看)来保存数组,或者应该使用组件本身中可以使用渲染道具引用的锚点或沿着这些线的东西来代替?我不确定,但也许这会有帮助
代码 首先,如果你想看到一个实时版本,请访问JSBin。我希望这里有足够的评论来解释到底发生了什么,我试着解释我自己,并保持这个版本的控制台整洁。这里是TL;博士执行日期:

  • 为文档对象上的
    selectstart
    添加事件侦听器(请将此限制为将使用此功能的容器)
  • 在偶数激发的情况下,为
    mouseup
    添加一个事件侦听器(这是多平台稍微中断的地方:/)
  • 如果按住Ctrl键(这可能也需要一些调整:/),则返回null并继续侦听mouseup,否则:
  • 设置计数器并开始执行
    do…while(count<[select].rangeCount)
  • 如果选择与其他元素交叉,则将抛出错误,如果未抛出错误,则使用
    [range].surroundWith([Node])
  • 如果抛出错误,则下一个爬虫程序将爬过这两个元素并执行HTML mutator函数
    replaceLive
    ,以更改HTML,请阅读注释中的警告
  • 如果没有更多的元素可以爬过,则删除事件侦听器(良好的实践,加上流氓侦听器从来都不是有趣的…)
  • 收听下一个选项
  • 功能删除(arr){
    用于(arr的常数){
    ele.replacetwith(ele.innerText);
    }
    }
    功能鼠标(e){
    //可能需要以不同的方式处理,只是现在更容易:/
    如果(e.ctrlKey==true){return;}
    让selectedText=document.querySelectorAll(“.selected text”);
    如果(已选择文本长度>0){
    删除(选择文本);
    }
    让selection=document.getSelection();
    //console.log(selection.anchorNode);
    让计数=0;
    做{
    const span=document.createElement(“span”);
    让range=selection.getRangeAt(计数);
    试一试{
    范围。周围内容物(跨度);
    span.classList.add(“所选文本”);
    }捕获(e){
    //控制台日志(e);
    //将HTML从所选内容提取到div中,遗憾的是没有
    //包括整个家长可能会写一些
    //通过startContainer和限制文本为您提供逻辑
    //HTML元素,如:p、span等(textarea和input do
    //不支持在firefox中根据mdn进行选择!)
    const div=document.createElement(“div”);
    div.append(范围