Skip to main content
Stack Overflow
  1. About
  2. For Teams

You are not logged in. Your edit will be placed in a queue until it is peer reviewed.

We welcome edits that make the post easier to understand and more valuable for readers. Because community members review edits, please try to make the post substantially better than how you found it, for example, by fixing grammar or adding additional resources and hyperlinks.

Required fields*

Required fields*

How to split a DOM node around a selection?

I have a contenteditable div, and I want to split a node around a selection. Using execCommand(), I can toggle "bold" on or off for a selection, so if I have:

<b>ABCDEFGHI</b>

and select DEF, toggling "bold" gives me

<b>ABC</b>DEF<b>GHI</b>

where the <b> node has been split into two <b> nodes with a text node in between.

I want to be able to do the same with other elements not supported by execCommand(), for example <bdi>. In other words, if I start with

<bdi>ABCDEFGHI</bdi>

and select DEF, I want to end up with

<bdi>ABC</bdi>DEF<bdi>GHI</bdi>

I can test if the selection is contained in a surrounding <bdi> tag using range.commonAncestorContainer() and if not wrap the range in a <bdi> tag. However, what I want is the opposite: if there is an enclosing <bdi> node, I want to split it into (a) a well-formed <bdi> node before the selection, (b) a well-formed selection with no enclosing <bdi>, and (c) another well-formed <bdi> node after the selection, and then reassemble them. How can I do this?

EDIT: it seems that everyone believes I am trying to wrap a selection, but I'm not. Sergey's response below shows how to wrap some plain text, but I want something else.

Trying for a minimal reproducible example, consider the following:

<html>
<head></head>
<body>
 <b>This text is <i>marked as 
 bold
 with</i> some italic text too.</b>
</body>
</html>

Now what I want is to UNMARK the text "bold" so that the final result is:

<html>
<head></head>
<body>
 <b>This text is <i>marked as</i></b>
 <i>bold</i>
 <b><i>with</i> some italic text too.</b>
</body>
</html>

Note that the text includes <i>...</i>, which must also be split. This is trivially easy with execCommand(), but I can't figure out how to do it without execCommand() (and hence do it for tags like <bdi> as well). I'm looking for a vanilla JS solutsion, not jQuery or Rangy please.

Answer*

Draft saved
Draft discarded
Cancel
12
  • thanks, but this is wrapping, not unwrapping: ABCDEFGHI to ABC<bdi>DEF</bdi>GHI or whatever. I'm trying to go from <bdi>ABCDEFGHI</bdi> to <bdi>ABC</bdi>DEF<bdi>GHI</bdi>. Commented Jan 22, 2025 at 16:52
  • @user1636349 — I wanted just to give you the idea on one sample, as simple as possible. You have everything to complete the code according to your a bit more complicated requirement. Are you saying that this conversion should happen if the selection is DEF? Could you do it yourself, or do you need a more complicated code sample? This is not hard to do, but it takes more time. Don't you think my demo is all you need to complete it? Commented Jan 22, 2025 at 16:59
  • @user1636349 — Okay, please see a more complicated code sample, in the section Added. Commented Jan 22, 2025 at 17:37
  • What happens if the selection is not just plain text, though? See my edited version of the original question where the html is <bdi...<i>...</i>...</bdi> and I want to extract part of the text inside <i>...</i> from the BDI element. You are extracting the text and splitting that, rather than splitting the DOM tree, which is what I require. Notice how my question asks how you split it into WELL-FORMED chunks. Commented Jan 22, 2025 at 19:20
  • "What happens if the selection is not just plain text, though?" I already answered. I added all you need to understand at the end of the recent revision of my solution. The main thing to understand is this: I already answered your question, and even a lot more, described all aspects. I won't be able to literally work for you more and more, you need to catch up and continue yourself. However, I question the merits of your requirements. At the same time, I'm ready to answer your further questions. Commented Jan 22, 2025 at 20:58

lang-js

AltStyle によって変換されたページ (->オリジナル) /