Search code examples
domrangy

Rangy - Closing Parent Element before insertElement


I have a text like

<AnyTag>here is a sample test text and more text</AnyTag>.

Now I am selecting "test" and clicking an italic button in my page and it creates a new element <span class="ItalicClass"> and it surroundContents(). This woks fine.

Now I have text like

<AnyTag>here is a <i>sample test text</i> and more text</AnyTag>.

Now if I select "test" it does the same but I would like to close the parent first and then insert the new element. I know the parentNode hence I can insert a new class in the span element. Same way I need to open the same parent after the end of new element. The the final line should be

<AnyTag>here is a <i>sample </i><span class="ClassB">test</span><i> text</i> and more text</AnyTag>

If I select the word "more" then

<AnyTag>here is a <i>sample test text</i> and <span class="ClassA">more</span> text</AnyTag>.

Appreciate any pointers in this regard.

Regards Dominic


Solution

  • First, you'll need to split the text node containing 'sample test text' at two indexes so that you have three side by side text nodes: 'sample ', 'test', and ' text'. (Note the spaces in sample and text).

    Second, create a range that encompasses the start of the parent node to the end of 'sample ' text node. Extract the contents.

    var range, frag;
    range = rangy.createRange();
    range.setStartBefore(parent); //your 'i' tag
    range.setEndBefore(textNode); //your text node 'sample '
    frag = range.extractContents(); //extract a document fragment - removes items from dom
    parent.parentNode.insertBefore(frag, parent); //place the fragment before the parent node
    

    Repeat those same steps, this time creating a range from the start of the text node ' text' to the end of the parent.

    var range, frag;
    range = rangy.createRange();
    range.setStartAfter(textNode); //your text node ' text'
    range.setEndAfter(parent); //your 'i' tag
    frag = range.extractContents(); //extract a document fragment - removes items from dom
    parent.parentNode.insertBefore(frag, parent.nextSibling); //place the fragment after the parent node
    

    Finally, the unwrap the contents of the original parent node 'i' and re-wrap it with your new tag.

    If any of this isn't clear, let me know. I've been building a WYSIWYG editor and have tested this idea thoroughly.