求助:如何移除选中文本的<b>标签,避免误删父级<div>节点
Let's fix your bold toggle functionality properly—your current issue with deleting the parent <div> happens because range.commonAncestorContainer targets the lowest shared parent of your selected content, not the <b> tag itself. Here's a robust solution to handle both adding and removing <b> tags correctly:
Step-by-Step Solution
First, replace your existing click handler with a dedicated toggleBold() function that checks if the selected text is already wrapped in <b> before deciding to add or remove the tag:
Full Working Code
function toggleBold() { const selection = window.getSelection(); if (!selection.rangeCount) return; // Exit if no text is selected const range = selection.getRangeAt(0); let targetBold = null; // Check if the entire selection is wrapped in a single <b> tag const anchorBold = selection.anchorNode?.parentElement?.closest('B'); const focusBold = selection.focusNode?.parentElement?.closest('B'); // Ensure both ends of the selection are in the same <b> tag if (anchorBold && focusBold && anchorBold === focusBold) { targetBold = anchorBold; } if (targetBold) { // Remove the <b> tag (unwrap the text) const parent = targetBold.parentNode; // Move all child nodes out of the <b> tag into its parent while (targetBold.firstChild) { parent.insertBefore(targetBold.firstChild, targetBold); } // Delete the empty <b> tag parent.removeChild(targetBold); // Restore the selection to the original text selection.removeAllRanges(); selection.addRange(range); } else { // Add the <b> tag to the selected text const boldNode = document.createElement('b'); try { // Use surroundContents if selection is a single contiguous node range.surroundContents(boldNode); } catch (err) { // Handle cases where selection spans multiple nodes (surroundContents fails here) const selectedContent = range.extractContents(); boldNode.appendChild(selectedContent); range.insertNode(boldNode); // Update selection to the newly bolded text selection.removeAllRanges(); const newRange = document.createRange(); newRange.selectNodeContents(boldNode); selection.addRange(newRange); } } }
Update your HTML to use this new function:
<div contenteditable="true" id="input" class="inputblock" onclick="toggleBold()" onkeypress="changeNodeType(event)" data-text="Please paste your text here."></div>
Key Fixes & Explanations
Why Your Original Remove Code Failed
Your use ofrange.commonAncestorContainerreturns the lowest parent element that contains the entire selection. If you selected text directly inside the<div contenteditable>, this container is the<div>itself—so callingremove()deleted the whole parent instead of the<b>tag.Targeting the Correct Tag
We useElement.closest('B')to traverse up from the selected text's nodes and find the nearest wrapping<b>tag. We verify both ends of the selection are in the same<b>to ensure we only unwrap the intended bolded content.Safe Unwrapping
Instead of deleting nodes blindly, we move all text/content inside the<b>tag up to its parent, then remove the now-empty<b>element. This preserves the text while removing the formatting.Robust Bold Addition
We added a try/catch block to handle cases where the selection spans multiple nodes (e.g., text across line breaks or other inline elements). The fallback usesextractContents()to safely wrap non-contiguous selections in<b>.
Optional Enhancement
If you need to handle selections that span multiple <b> tags, you can extend the code to iterate over all <b> elements in the selection range and unwrap each one individually.
内容的提问来源于stack exchange,提问作者Junge

