Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add spans to characters in a string (in an HTML element)

I want to loop through the characters of a text in an element and add spans to the characters. This is pretty easy using jQuery.map():

$elem = $('h1');
var chars = jQuery.map($elem.text().split(''), function(c) {
  return '<span>' + c + '</span>';
});
$elem.html(chars.join('')); 

The above works great with a simple string, but now I want to change the function so that it also will handle more 'complex' contents like: <h1>T<em>e</em><b>st</b></h1>. Which should be translated to: <h1><span>T</span><em><span>e</span></em><b><span>s</span><span>t</span></b></h1>.

This means I cannot simply loop through all the characters in the element anymore. Is there something I can use to loop through the contents (characters) of an element as well as all children? Or is there another way of achieveing what I want?

like image 204
PeeHaa Avatar asked Dec 13 '25 01:12

PeeHaa


1 Answers

Overall idea:

You can recursively iterate over the child nodes. If you encounter an element node, you iterate over its children etc. If you encounter a text node, you are replacing it with a series of span elements.


jQuery

function wrapCharacters(element) {
    $(element).contents().each(function() {
        if(this.nodeType === 1) {
            wrapCharacters(this);
        }
        else if(this.nodeType === 3) {
            $(this).replaceWith($.map(this.nodeValue.split(''), function(c) {
               return '<span>' + c + '</span>';
            }).join(''));
        }
    });
}    

wrapCharacters($('h1')[0]);

DEMO


JavaScript (without jQuery)

The idea stays the same, and even without jQuery, wrapping each character is not very difficult:

var d_ = document.createDocumentFragment();

for(var i = 0, len = this.nodeValue.length; i < len; i++) {
    var span = document.createElement('span');
    span.innerHTML = this.nodeValue.charAt(i);
    d_.appendChild(span);
}
// document fragments are awesome :)
this.parentNode.replaceChild(d_, this);

Only iterating over the child nodes has to be done carefully because text nodes are getting removed during iteration.

Plain JavaScript example

like image 196
Felix Kling Avatar answered Dec 14 '25 20:12

Felix Kling



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!