我想编写一个脚本来删除所选文本的格式,例如 document.execCommand('removeFormat') 但本质上没有这种已弃用的方法。我想知道这背后的算法是什么。 例如我有 html。
<body>
1.
<div>
<h1>hello world</h1>
<span>
<b style="background-color: green">bold text</b>
</span>
<p style="background-color: red">1234</p>
</div>
</body>
我选择了从“你好”到“12”的文本 预期的输出可能是
<body>
1.
hello world bold text 12
<p style="background-color: red">34</p>
</div>
</body>
第一步。使用 window.getSelection() 和 window.getSelection().getRangeAt(0) 我们可以找到开始文本节点“hello world”和结束文本节点“12”(如果我们将文本节点“1234”拆分为两个文本节点“12”“34”,则可能会发生这种情况)。
使用开始文本节点和结束文本节点,我们可以获取之间的所有文本节点,但它如何帮助我。 看来我们需要删除“hello world”之前的所有标签,直到我们命中非空文本节点,并且结束文本节点也是如此。我们从开头删除所有 html 标签,直到看到“1”。但最后我们看到了“34”,所以我关闭了 div 标签而没有打开 div 标签。
看来我可以用
let selection = window.getSelection();
selection.deleteFromDocument();
但它留下了空标签
<div>
<h1></h1><p style="background-color: red">34</p>
</div>
然后使用selection.toString()以某种方式添加文本
有很多边缘情况,我很难理解正确的方法。
此代码可以解决您的问题,但您必须选择整个部分,包括部分编号。
function removeFormattingFromSelection() {
const selection = window.getSelection();
if (!selection.rangeCount) return;
const range = selection.getRangeAt(0);
const text = range.toString();
const textNode = document.createTextNode(text);
range.deleteContents();
range.insertNode(textNode);
selection.removeAllRanges();
const newRange = document.createRange();
newRange.selectNodeContents(textNode);
newRange.collapse(false);
selection.addRange(newRange);
}
body {
font-family: Arial, sans-serif;
padding: 20px;
}
.content {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
background-color: #f9f9f9;
}
h1 {
color: darkblue;
}
b {
font-weight: bold;
background-color: green;
color: white;
}
p {
color: red;
padding: 5px;
}
<div class="content" id="content">
1.
<div>
<h1>hello world</h1>
<span><b style="background-color: green">bold text</b></span>
<p>1234</p>
</div>
2.
<div>
<h1>hello world</h1>
</div>
</div>
<button onclick="removeFormattingFromSelection()">Remove Formatting</button>