Add element before/after text selection
Asked Answered
P

4

11

I'm looking for function which allows me to build some element before or after selected text. Something similar like this one javascript replace selection all browsers but for adding some content before or after selection instead of replacing it, like after() and before() jQuery methods. Should I use some DOM selection method, if yes which one? Or does exist something easier to carry it out?

Pentachlorophenol answered 27/11, 2011 at 9:19 Comment(1)
Not an answer, but: I bet you can do this pretty easily using Tim Down's Rangy library.Caruthers
P
14

Here's a pair of functions to do this.

Live example: http://jsfiddle.net/hjfVw/

Code:

var insertHtmlBeforeSelection, insertHtmlAfterSelection;

(function() {
    function createInserter(isBefore) {
        return function(html) {
            var sel, range, node;
            if (window.getSelection) {
                // IE9 and non-IE
                sel = window.getSelection();
                if (sel.getRangeAt && sel.rangeCount) {
                    range = window.getSelection().getRangeAt(0);
                    range.collapse(isBefore);

                    // Range.createContextualFragment() would be useful here but is
                    // non-standard and not supported in all browsers (IE9, for one)
                    var el = document.createElement("div");
                    el.innerHTML = html;
                    var frag = document.createDocumentFragment(), node, lastNode;
                    while ( (node = el.firstChild) ) {
                        lastNode = frag.appendChild(node);
                    }
                    range.insertNode(frag);
                }
            } else if (document.selection && document.selection.createRange) {
                // IE < 9
                range = document.selection.createRange();
                range.collapse(isBefore);
                range.pasteHTML(html);
            }
        }
    }

    insertHtmlBeforeSelection = createInserter(true);
    insertHtmlAfterSelection = createInserter(false);
})();
Profess answered 27/11, 2011 at 19:22 Comment(4)
This code / jsfiddle does not work at all in Chrome (Maybe it did in 2011) and it does not work as expected in IE.Accrual
@user1254723: It works fine in Chrome on my Mac. It also works fine in my IE 11.Profess
I am running "Version 73.0.3683.103 (Official Build) (64-bit)" on windows 10. I just double checked and when I click either button nothing happens. Weird there would be such a difference between windows and mac ? !Accrual
@user1254723: Works on Chrome on my Windows PC too. You have to place the cursor somewhere in the text or select some of the text before pressing one of the buttons; are you definitely doing that?Profess
S
2

In MSIE: collapse the given range and the use pasteHTML to insert the element

Others: Also collapse the given Range and insert the element via insertNode


Both collapse-methods accept an optional argument which defines to where you want to collapse to. If you want to put the element at the end, collapse to the end, otherwise to the start.

Sportive answered 27/11, 2011 at 9:35 Comment(0)
M
0
function yourFunction() {
    const sel = window.getSelection ? window.getSelection() : document.selection.createRange()
    if (!sel) return false

    if (sel.getRangeAt) {
        const range = sel.getRangeAt(0)
        const text = range.toString()
        console.log(text)
        range.deleteContents()
        range.insertNode(document.createTextNode(`before text${text}after`))
    } else {
        sel.pasteHTML(`[s=спойлер]${sel.htmlText}after`)
    }
}
Malynda answered 3/1, 2023 at 16:36 Comment(1)
Welcome to Stack Overflow! Please try to include some explanations or some comments on your code so that people are able to understand what it is doing.Maldonado
C
0

JS in 2024 Update

Use the .after() & before() method of your node. Here is an example:

const p = document.querySelector(".paragraph-1")
let container = document.createElement("div");
container.innerHTML = "NEWLY ADDED ELEMENT"
p.after(container)

Demo:

  function addElementAfter(){
    const span = document.querySelector(".selection")
    let container = document.createElement("div");
    container.innerHTML = "How are you doing?"
    span.after(container)
  }
 <div>
    <p>Hello <span class="selection">world!</span> </p>
</div>
<button onclick="addElementAfter()">Add content</button>

Documentation: https://developer.mozilla.org/en-US/docs/Web/API/Element/after

alternative method (insertAdjacentElement)

A second option is using the insertAdjacentElement(position, element) method: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement

<!-- beforebegin -->
<p>
  <!-- afterbegin -->
  foo
  <!-- beforeend -->
</p>
<!-- afterend -->
Clisthenes answered 25/6 at 11:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.