如何避免从部分选择中破坏块级HTML元素

How to avoid breaking block level HTML elements from partial selection?

本文关键字:HTML 元素 何避免 选择      更新时间:2023-09-26

简单地说,问题是:给定一个wysiwyg编辑器(CKEditor),你想制作一个进行文本转换的插件-选择一段文本并操作其中的文本(例如大写)。示例:

这是一段

这是第二段

如果粗体表示您的选择,则结果为

这是一段

THIS是的第二段

这里的问题是,即使选择不包含完整标记,选择也将是一个完整的HTML片段。所选HTML为:

<p>one</p> <p>this</p>

请注意第一个和最后一个<p>标记。当你在选择html中进行dom遍历时,应用文本转换并替换html,它将使用那些部分标记,所以你的结果变成:

这是段

一个

是第二段

我检查了是否有可能";合并";第一个和最后一个带有dom父对象的分部标记,但是选择对象是孤立的,它没有来自其原始上下文的兄弟姐妹或父对象。

还试图找到一个选项来检索没有这些自动固定标签的选择,但没有成功。

在CKEditor文档中,他们提到了一个walker对象,但它会自动从选择扩展到全封闭标记,这意味着选择仅用作最小边界。

另外,因为选择对象是孤立的,所以不可能只更改那里的dom节点文本值——需要替换原始的dom片段(至少在CKEditor的情况下是这样)。

我尽量不使用CKeditorapi,但在这一点上,我也看不到任何替代方案。这真的是个难题还是我遗漏了什么?

一种解决方案是使用浏览器引擎用标记(afaik是本机操作)标记所选区域。这和你把你的选择加粗或斜体是一样的——不过这里它只是一个临时包装。然后遍历DOM并替换临时标记中的内容,最后移除标记(保留内容)。

这确保了您可以将转换应用于精确的选择,并且通过移除标记,您不会破坏原始DOM。简而言之:

  1. 在选择时应用标记(使用浏览器或wysiwyg-api)
  2. 查找所有临时标签:
    • 递归遍历标记的子级
      • 如果标记是文本节点,则应用转换
      • 否则递归遍历
    • collect标记的左同级文本节点+标记的html+右同级文本节点
    • 用以前的编译替换标记的父html(=删除临时标记)

不太优雅却很管用。这是受@Andrew_Mast关于在跨度中包裹的想法的启发。

我会循环遍历所有单词,对于不同标签中的每组单词,用<span style="text-transform: uppercase;"></span> 将其包围