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>
      

Run code


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>
      

Run code


Does any of you know how I can achieve this?

+3


source to share


1 answer


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.

+4


source







All Articles