Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
438 views
in Technique[技术] by (71.8m points)

javascript - Surrounding individual words inside HTML text with SPAN tags?

I need to surround individual words inside an HTML element with SPAN tags. So something like this:

Foo <span class="f1 b0">bar <b>baz</b> boo blah</span> lorem ipsum

Should become this:

<span>Foo</span> <span class="f1 b0"><span>bar</span> <b><span>baz</span></b>
<span>blah</span></span> <span>lorem</span> <span>ipsum</span>

The reason is that I want to be able to figure out what word, specifically is under the cursor using "document.elementFromPoint(X, Y)". I tried using a simple regex:

theElement.innerHTML.replace(/(w+)/g, "<span>$1</span>")

...but that won't work since the HTML element in question will most definitely have elements inside of it. I would just use that regex on the innerText instead of innerHTML but then I'd lose all existing formatting.

I have tried walking the children of the element, performing that regex replacement on each but sometimes the child elements have their own HTML tags within and I can't figure out how to perform a replacement of the text that comes before or after tags.

Anyone have a good solution?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To do this you will need to walk the DOM and understand how to process the individual nodes.

The basic walk code is this:

function walk(root)
{
    if (root.nodeType == 3) // text node
    {
        doReplace(root);
        return;
    }
    var children = root.childNodes;
    for (var i = children.length - 1 ; i >= 0 ; i--)
    {
        walk(children[i]);
    }
}

The walk function checks all the children of the input node and:

  • if it sees a text node it calls the replacement function
  • otherwise it recursively calls itself with the child node as the new input node.

Note that because the code in-place replaces nodes, the "children" node list will be affected by the replacement. To avoid this affecting the algorithm, the children are visited in reverse order.

The doReplace function is like this:

function doReplace(text)
{
    var div = document.createElement("div");
    div.innerHTML = text.nodeValue.replace(/(w+)/g, "<span>$1</span>");
    var parent = text.parentNode;
    var children = div.childNodes;
    for (var i = children.length - 1 ; i >= 0 ; i--)
    {
        parent.insertBefore(children[i], text.nextSibling);
    }
    parent.removeChild(text);
}

This creates a container node, then applies the regex and uses innerHTML to parse the result into a DOM fragment. The children of the div element can then replace the text node in the document. Again the moving of the nodes is done in reverse order so that the mutation of the source node list doesn't affect the loop.

Finally, the change can be applied by calling the walk function.

e.g.

window.onload = function() { walk(document.body); };

A complete working example can be found at http://www.alohci.net/text/html/wordwrapper.htm.ashx


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...