32

I was directed to the Linkify project on GitHub (https://github.com/cowboy/javascript-linkify) for finding and "linkifying" URLs and domains just floating in text.

It's awesome! It totally works on text!

However, I'm not quite sure how to make it work on a textNode which has the text I want to Linkify.

I understand the textNode only has textContent since.. it's all text. Since this Linkify function returns HTML as text, is there a way to take a textNode and "rewrite" the HTML within it with the Linkify output?

I've been playing with it on JSFiddle here: http://jsfiddle.net/AMhRK/9/

function repl(node) {
  var nodes = node.childNodes;
  for (var i = 0, m = nodes.length; i < m; i++) {
    var n = nodes[i];
    if (n.nodeType == n.TEXT_NODE) {
      // do some swappy text to html here?
      n.textContent = linkify(n.textContent);
    } else {
      repl(n);
    }
  }
}
9
  • 1
    Your example code is so messy and so much, I don't even know where to begin! Can you clean it up a little bit, and just have a normal example, and the one you want with textNode? Commented Mar 21, 2013 at 16:50
  • 4
    jsfiddle.net/AMhRK/4 Commented Mar 21, 2013 at 17:05
  • @ryan it's close but you see it mangles the already properly hyperlinked URLs. Commented Mar 21, 2013 at 17:28
  • @HanletEscaño here's a "cleaned up" fiddle jsfiddle.net/AMhRK/6 Commented Mar 21, 2013 at 17:39
  • @Jippers did you try ryan's jsFiddle? It actually works. Commented Mar 21, 2013 at 17:40

4 Answers 4

35

You'll need to replace the textNode with an HTML element, like a span, and then set your linkified-text as that element's innerHTML.

var replacementNode = document.createElement('span');
replacementNode.innerHTML = linkify(n.textContent);
n.parentNode.insertBefore(replacementNode, n);
n.parentNode.removeChild(n);
Sign up to request clarification or add additional context in comments.

7 Comments

It's not that simple as a text node may contain a lot of "unlinkfied" elements
This seems to work! Here's a Fiddle fork with Will Scott's addition: jsfiddle.net/H2aHH
this maintains the user's Selection, where .replaceChild() does not!! brilliant
var replacementNode = document.createElement('span'); var newHtml = linkify(n.textContent); n.parentNode.insertBefore(replacementNode, n); n.parentNode.removeChild(n); replacementNode.outerHTML = newHtml;
@Gromo I like your solution since it doesn't end up leaving new span elements around.
|
11

Additionally to previous answer I propose more short way (based on jQuery):

$(n).replaceWith('Some text with <b>html</b> support');

where n - is textNode.

Or the native version

var txt = document.createElement("span");
txt.innerHTML = "Some text with <b>html</b> support";
node.replaceWith(txt);

where node is the textNode

2 Comments

replaceWith() is available as vanilla JavaScript on modern browsers (Chrome and Firefox; Edge is under development).
But in the vanilla version there is no HTML support. Tags just appear as text.
5

Build on @AlexJeffcott's answer: Perf optimized version utilizing DocumentFragment instead of messing around with <span>, innerHTML and childNodes😁

const enhanceNodes = (textNodes) => {
    textNodes.forEach((node) => {
        const oldText = node.textContent;
        const newText = fancyTextTranformation(oldText);
        const fragment = document.createRange().createContextualFragment(newText);
        node.replaceWith(fragment);
    })
}

Comments

1

Build on Will Scott's accepted answer, if you do not wish to have to wrap everything in a span, you could do the following:

const enhanceNodes = (textNodes) => {
    const renderNode = document.createElement('span');
    textNodes.forEach((node) => {
        const oldText = node.textContent;
        renderNode.innerHTML = fancyTextTranformation(oldText);
        node.replaceWith(...renderNode.childNodes);
    })
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.