Entalpia Entalpia - 14 days ago 6
HTML Question

Wrap every character with span, but keep HTML formatting

I'm trying to wrap every character inside the string in spans, but keep the formatting. I'm pretty much there, but with the below solution the punctuation characters right behind the tags don't get included anywhere. Another problem I'm facing is the regex picking up only the first word inside the tag if there are more than one.

Please have a look below (and at the JS Fiddle: https://jsfiddle.net/um650ma0/4/).

HTML
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc rhoncus ante a cursus porta. Curabitur egestas urna eu arcu tristique, nec malesuada est efficitur.

JS

$('p.home strong').each(function () {
var strong = $(this).html();
$(this).empty();
for (var i = 0; i < strong.length; i++) {
$(this).append('<span>' + strong[i] + '</span>');
}
})
var str = $('p.home').html();
var intro = str.match(/(?:<(\w+)[^>]*>(?:[\w+]+(?:(?!<).*?)<\/\1>?)[^\s\w]?|[^\s]+)/g);
$('p.home').empty();
for (var i = 0; i < intro.length; i++) {
var str = intro[i];
if (str.indexOf('<') !== -1) {
$('p.home').append(intro[i] + ' ')
}
else {
var substr = str.split('');
for (var j = 0; j < substr.length; j++) {
$('p.home').append('<span>' + substr[j] + '</span>')
}
$('p.home').append(' ');
}
}


Any suggestions how to update the regex to get the right result?

Thanks,
E.

Answer

The issue with you code is when there are more than one word inside the strong element, in this case a whitespace will be encountered while traversing the inner string and browser will close the parent tag (strong). You need to do specific handling for that in your code.

The other issue of punctuation character missing after tag can also be handled with below logic. Not very elegant but will do the work

        var str = $('p.home').html();
        var intro = str.match(/(?:<(\w+)[^>]*>(?:[\w+]+(?:(?!<).*?)<\/\1>?)[^\s\w]?|[^\s]+)/g);


        $('p.home').empty();
        for (var i = 0; i < intro.length; i++) {
            var str = intro[i];
            if (str.indexOf('<') !== -1) {

                if(str.indexOf(',') === str.length -1)
                {
                   $('p.home').append(str.substr(0, str.length - 1));
                   $('p.home').append('<span>,</span>' + ' ')
                }
                else if(str.indexOf('.') === str.length -1)
                {
                   $('p.home').append(str.substr(0, str.length - 1));
                   $('p.home').append('<span>.</span>' + ' ')
                }
                else
                {
                       $('p.home').append(intro[i] + ' ');
                }



            }
            else {
                var substr = str.split('');
                for (var j = 0; j < substr.length; j++) {

                    $('p.home').append('<span>' + substr[j] + '</span>')
                }
                $('p.home').append(' ');
            }        
        }

         $('p.home strong').each(function () {
            var strong = $(this).html();



            $(this).empty();
            for (var i = 0; i < strong.length; i++) {
                if($.trim(strong[i]) === "")
                {
                       $(this).append("&nbsp;");
                }
                else
                { 
                     $(this).append('<span>' + strong[i] + '</span>');
                }
            }

        })

Updated Fiddle : https://jsfiddle.net/LkqL0b4x/

Comments