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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With