2

I need to create a way to encapsulate all non-html words in a html page with html. An example:

<p id="paragraph"><a href="http://www.google.com">Google it!</a>But I <b>must</b> explain to you</p> 

should be changed to

<p id="paragraph"><a href="http://www.google.com"><span id="word1">Google</span> <span id="word2">it!</span></a><span id="word3">But</span> <span id="word4">I</span> <b><span id="word5">must</span></b> <span id="word6">explain</span> <span id="word7">to</span> <span id="word8">you</span></p> 

I have tried to extract all words:

group_text = $("#paragraph").text().trim().split(" ");

and then encapsulate each word with the selected html, but that removes all other existing html the document might have

for (var it = 0; it < group_text.length; it++) {
    group_text[it] = $('<span/>', {
        id: 'word' + (it+1),
        html: group_text[it]
    }).append(" ");
}

Any solution that might actually work?

abinop
  • 3,153
  • 5
  • 32
  • 46
  • maybe you could explain what your goal is. Why do you need to wrap each word in your paragraph's text within span elements? – stevebot Dec 03 '14 at 22:24
  • Could the element nesting go even deeper than what you've shown? This could get ugly fast. – j08691 Dec 03 '14 at 22:24
  • @stevebot I need to know when I have clicked a word and the sequence of that word – abinop Dec 03 '14 at 22:34
  • @j08691 What do you propose? I am not sure what you mean.I need to interact with each word of a text (making it bold) without ruining any other formatting. – abinop Dec 03 '14 at 22:37
  • oohhh you should do not do it in that way... you can us $(event.target) – ncubica Dec 03 '14 at 22:37
  • possible duplicate of [get word click in paragraphs](http://stackoverflow.com/questions/4643432/get-word-click-in-paragraphs) – webduvet Dec 03 '14 at 22:38
  • @ncubica and how would I which word would (1st,2nd,etc) I be clicking? I need to know that. – abinop Dec 03 '14 at 22:42
  • @abinop didnt understand you question at first. – ncubica Dec 04 '14 at 02:00

1 Answers1

4

You will need to write recursive function to handle nested texts. Maybe something like this:

function wrap($node) {
    $node.contents().each(function() {
        if (this.nodeType === 3) {
            $(this).replaceWith(this.nodeValue.trim().split(/\s+/).map(function(el) {
                return '<span class="word' + ++i + '">' + el + '</span>';
            }));
        }
        else if (this.nodeType === 1) {
            wrap($(this));
        }
    });
}

var i = 0;
wrap($('#paragraph'));

alert($('#paragraph').html())
span {
    border-bottom: 1px dashed #AAA;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="paragraph"><a href="http://www.google.com">Google it!</a>But I <b>must</b> explain to you</p>

If node type is 3 then you need to split text into individual words and wrap each into span. If node type is 1, then this is element node, - call wrap function on it again.

dfsq
  • 191,768
  • 25
  • 236
  • 258