How can i wrap text before this symbol without destroying existing html

Viewed 52

Trying to wrap all words prior to the "," in each td cell. Note that words prior to "," in each cell will be different , so can not target a specific word per se

Existing html

<td class="name">
 <a href="" title="" class="">lastName, firstName</a>
</td>

Desired outcome

<td class="name">
 <a href="" title="" class=""><span>lastName</span>, firstName</a>
</td>

Attempts, all of which destroy the a href structure, I need to keep the a tag with class, title and href as is and just wrap the word/words prior to ","

$('td.name').each(function() {
  $(this).html($(this).text().replace(/,.*$/, '<span class="after">$&</span>'));
});

$('td.name').html(function(i, v) {
    return v.replace(/([^,]+)(,)/, '$1<span class="auther">$2</span>$3');
});

$('td.name').html(function (i, html) {
    return html.replace(/(.*?,)/, '<span>$1</span>')
});
2 Answers

You can create a TreeWalker for each <td> and use it to find all the text nodes, passing in a filter to locate only the ones containing commas.

From there, you can split the text into chunks and map each pre-comma chunk to a new <span> then replace the entire text node with the new set of nodes.

const createSpan = textContent => Object.assign(
  document.createElement("span"),
  { textContent }
)

const filter = {
  acceptNode: node =>
    node.data.includes(",") ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
}

document.querySelectorAll("td.name").forEach(td => {
  const treeWalker = document.createTreeWalker(
    td,
    NodeFilter.SHOW_TEXT, // select only text nodes
    filter,               // filter for content with commas
    false
  )
  
  let node
  
  while (node = treeWalker.nextNode()) {
    // split the text on comma, keeping the delimiter
    const chunks = node.data.split(/(?=,)/)
    
    // keep the last chunk as-is
    const last = chunks.pop()
    
    // replace the text node with the new node set
    node.replaceWith(...chunks.map(createSpan), last)
  }
})
span { color: red; }
<table border="1">
  <tr>
    <td class="name">
      <a href="" title="" class="">lastName, firstName</a>
    </td>
  </tr>
  <tr>
    <td class="name">
      <a href="" title="" class="">no commas</a>
    </td>
  </tr>
</table>

I really didn't see any use for jQuery here.

Glad you like jQuery, this few lines will get you going. Cheers!

$('.my_name').each(function() {
var my_text = $(this).find("a").text();
var my_wrap = my_text.replace(/[^,]*/, '<span class="my_class">$&</span>');
$(this).find("a:contains(',')").empty().append(my_wrap);
});
.my_class { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.min.js"></script>
<table>
  <tbody>
    <td class="my_name">
      <a href="my_href.com" title="" class="">lastName, firstName</a>
    </td>
    
    <td class="my_name">
      <a href="my_href.com" title="" class="">td 2 not affected</a>
    </td>
  </tbody>
</table>

//Output
<a href="my_href.com" title="" class=""><span class="my_class">lastName</span>, firstName</a>
Related