Wrap each char inside an <i>
I am trying to wrap every character from a given element in a <i></i>
. So far I've tried two methods, but each has some problems.
First method:
I am replacing every character of .html()
my element with its packed version. The problem is that it also treats tags as characters and wraps them too.
$(function() {
$(document).click(function(e) {
var element = e.target;
if ($(element).text() != '') { //Contains text
var txt = $(element).contents().filter(function() {
return this.nodeType === 3;
}).text();
if (txt != '') { //Text outside span
var chars = $(element).html().split('');
var newChars = '';
$.each(chars, function(i, el) {
newChars += "<i>" + el + "</i>";
});
$(element).html(newChars);
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
Lorem <span>teeest</span> ipsum dolor sit amet, consectetur adipisicing elit. Dolorem aspernatur ducimus autem eveniet porro vitae ratione illum totam voluptatem alias. Impedit deserunt maiores excepturi ab repellendus atque aperiam quisquam iste! Lorem
ipsum dolor sit amet, consectetur adipisicing elit. Saepe quasi mollitia perspiciatis explicabo, maxime quae</p>
Second method:
I tried a recursive approach that goes through my children and replaces the text inside each one. The problem is that my output text somehow doubles and the children end up out of place.
function recursiveReplace(element) {
if ($(element).children().length > 0) {
$(element).children().each(function() {
recursiveReplace($(this)[0]);
});
}
var chars = $(element).contents().filter(function() {
return this.nodeType === 3;
}).text().split('');
var newChars = '';
$.each(chars, function(i, el) {
newChars += "<i>" + el + "</i>";
});
console.log(newChars);
$(element).contents().filter(function() {
return this.nodeType === 3;
}).replaceWith(newChars);
}
$(function() {
$(document).click(function(e) {
var element = e.target;
if ($(element).text() != '') { //Contains text
var txt = $(element).contents().filter(function() {
return this.nodeType === 3;
}).text();
if (txt != '') { //Text outside span
recursiveReplace(element);
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
Lorem <span>teeest</span> ipsum dolor sit amet, consectetur adipisicing elit. Dolorem aspernatur ducimus autem eveniet porro vitae ratione illum totam voluptatem alias. Impedit deserunt maiores excepturi ab repellendus atque aperiam quisquam iste! Lorem
ipsum dolor sit amet, consectetur adipisicing elit. Saepe quasi mollitia perspiciatis expli</p>
Does any of you know how I can achieve this?
source to share
A recursive approach should work if you are processing each node text individually, rather than concatenating it the way you do (as a result of running text()
on a filtered collection)
function recursiveReplace(element){
$(element).children().each(function() {
recursiveReplace(this);
});
$(element).contents()
.filter(function(){ return this.nodeType === 3; })
.each(function(){
var wrapped = '<i>' + this.textContent.split('').join('</i><i>') + '</i>';
console.log(wrapped);
$(this).replaceWith(wrapped);
});
}
Note that I have also simplified your recursive call, there is no need to check if there are any children when using it each()
, and there is no point in a wrapper this
to expand it right away.
source to share