简而言之,问题是:给定一个所见即所得编辑器(CKEditor),您想要制作一个执行文本转换的插件 - 选择一段文本并操作其中的文本(例如大写)。示例:
this is paragraph one
this is paragraph two
如果粗体代表您的选择,结果将是
this is paragraph ONE
THIS is paragraph two
这里的问题是,即使选择不包含完整标签,选择也将是完整的 HTML 片段。所选 HTML 为:
<p>one</p> <p>this</p>
注意第一个和最后一个 <p>
标签。当您在选择的 html 中进行 dom 遍历时,应用文本转换并替换 html,它将使用这些部分标签,因此您的结果将变为:
this is paragraph
ONE
THIS
is paragraph two
我检查了是否可以将第一个和最后一个部分标记与其 dom 父级“合并”,但是选择对象是隔离的,它没有来自原始上下文的兄弟级或父级。
还尝试找到一个选项来检索没有这些自动固定标签的选择,但没有运气。
在 CKEditor 文档中,他们提到了 walker object - 但是,它会自动从选择扩展到完整的封闭标记,这意味着选择仅用作最小边界。
此外,由于选择对象是隔离的,因此不可能仅更改其中的 dom 节点文本值 - 需要替换原始 dom 片段(至少在 CKEditor 的情况下)。
我尝试尽可能不坚持使用 CKEditor api,但目前我也没有看到任何替代方案。这真的是一个难题还是我遗漏了一些东西?
最佳答案
一种解决方案是使用浏览器引擎用标签来标记所选区域(据我所知,这是 native 操作)。这与您将选择设置为粗体或斜体相同 - 但这里它将是一个临时包装。然后你遍历 DOM 并替换临时标签中的内容 - 最后删除标签(保留内容)。
这确保您可以将转换应用到精确的选择上,并且通过删除标签,您不会破坏原始 DOM。步骤简而言之:
- 在选择上应用标记(使用浏览器或所见即所得 API)
- 查找所有临时标签:
- 递归遍历标签的子级
- 如果标签是文本节点,则应用转换
- 否则递归遍历
- 收集标签的左同级文本节点 + 标签的 html + 右同级文本节点
- 将标记的父级 html 替换为之前的编译内容(=删除临时标记)
- 递归遍历标签的子级
不太优雅但有效。这是受到 @Andrew_Mast 关于包裹在跨度中的想法的启发。
关于javascript - 如何避免部分选择破坏 block 级 HTML 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33684943/