SO-33588235

by David Thomas

HTML

<div class="newsitem_text">
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pellentesque urna eu pulvinar maximus. Sed elit nunc, vestibulum ut eros vitae, pellentesque rhoncus ipsum. In et metus non diam porttitor maximus iaculis nec lectus. Quisque sodales scelerisque auctor. Nam rutrum venenatis eros, eu condimentum erat placerat ut. Pellentesque sed tempus sem, eu viverra ipsum. Vestibulum nec turpis convallis, dapibus massa vitae, posuere mauris. Suspendisse mattis tincidunt lorem. Aliquam erat volutpat. Nullam at tincidunt erat, maximus laoreet ipsum.</div>

CSS

span {
    color: #f90;
}
div {
    margin-left: auto;
    margin-right: auto;
}
.newlyAdded {
    background-color: #ffa;
}

JavaScript

function getActualWords(node) {
    return node.textContent.split(/\s+/).filter(function (word) {
        return word.trim().length;
    });
}

function insertElemAfterNthWord(opts) {
    var defaults = {
        'nth': 5,
            'elemText': 'new element',
            'elemTag': 'div'
    };

    for (var prop in opts) {
        if (opts.hasOwnProperty(prop)) {
            defaults[prop] = opts[prop];
        }
    }

    var d = defaults,
        tag = d.elemTag.replace(/<|>/g, ''),
        elem = document.createElement(tag);

    elem.textContent = d.elemText;

    d.nth = parseInt(d.nth, 10);

    if (d.node) {
        var n = d.node.firstChild,
            words = getActualWords(n),
            wordCount = words.length;

        while ((n.nodeType !== 3 || d.nth > wordCount) && n.nextSibling) {

            n = n.nextSibling;
            words = getActualWords(n);
            wordCount = words.length;
        }
        if (getActualWords(n).length < d.nth) {
            return;
        } else {
            var w = getActualWords(n).slice(0, d.nth).pop(),
                i = n.textContent.indexOf(w);
            n.splitText(i + w.length);
            n.parentNode.insertBefore(elem, n.nextSibling);
            n.parentNode.insertBefore(document.createTextNode(' '), n.nextSibling);
            n.parentNode.normalize();

            return elem;
        }
    }
}


insertElemAfterNthWord({
    'nth': 10,
        'elemTag': 'span',
        'elemText': 'this is the newly-added text inside the newly-added element!',
        'node': document.querySelector('div > div')
}).classList.add('newlyAdded');