4

I'm trying to detect a character in a text, and if found wrap the word before it in a HTML element, and remove that character.

Example:

Case:

becomes

<span class="th">Case</span>

Method

I can detect the presence of : using:

if (str.indexOf(':') > -1)

To get the word before I'm using:

var th = str.split(':')[0];

To wrap the word in an element I tried:

var th_wrap = "<span class='th'></span>";  
$(th).wrap(th_wrap);

Which doesn't work. To remove the : I tried:

th.replace(':', '');

Which also doesn't work.

To make it slightly more complicated, I want to catch any occurance of someword:, not just the first one.

I'd appreciate any pointers, cheers. (javascript or jQuery)

SNIPPET

var str = $('.target').html();
if (str.indexOf(':') > -1) {
  var th = str.split(':')[0];
  th.replace(':', '');
  var th_wrap = "<span class='th'></span>";
  $(th).wrap(th_wrap);
}
th { font-weight: bold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="target">
  Case 1:
  <br />some text
  <br />some more text
  <br />even more text
  <br />
  <br />Case 2:
  <br />some text
  <br />some more text
  <br />even more text
</p>
Mohammad
  • 21,175
  • 15
  • 55
  • 84
sol
  • 22,311
  • 6
  • 42
  • 59
  • th has to be a DOM element. not a string. If you ar trying to replace the first case with your desired ``, it's better to get the first child of `.target` and replace it – Mojtaba Jan 27 '17 at 17:42

2 Answers2

5

In your case the words Case 1: and Case 2: are text nodes.

So, you need to get all nodes under target: for this, use jQuery.contents().

The snippet:

$('.target').contents().each(function(idx, ele) {
  if (ele.nodeType == Node.TEXT_NODE &&
            ele.textContent.indexOf(':') > -1) {
    ele.textContent = ele.textContent.replace(':', '');
    $(ele).wrap($('<span/>', {
      class: 'th'
    }));

  }
});
.th {
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<p class="target">
    Case 1:
    <br />some text
    <br />some more text
    <br />even more text
    <br />
    <br />Case 2:
    <br />some text
    <br />some more text
    <br />even more text
</p>
gaetanoM
  • 41,594
  • 6
  • 42
  • 61
  • How does this code know what to wrap before the ':' ? For example, 'Case 2' - why does it not also wrap the words before 'Case'? – sol Jan 27 '17 at 22:15
  • 1
    Because before"Case 2" there is a tag (br). If, instead your format changes you may always use regex. In any case this approach gives you the possibility to act only on textNode. – gaetanoM Jan 28 '17 at 12:51
2

You can use regex to do this work. Use jquery .html(function) to change html of p. In function of callback use String.prototype.replace() to wrap target string in span.

$("p").html(function(i, html){
  return html.replace(/(\w+\s\d+):/g, "<span class='th'>$1</span>");
});
.th { color: red }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="target">
  Case 1:
  <br />some text
  <br />some more text
  <br />even more text
  <br />
  <br />Case 2:
  <br />some text
  <br />some more text
  <br />even more text
</p>
Mohammad
  • 21,175
  • 15
  • 55
  • 84
  • 1
    @ovokuro Yes, see https://jsfiddle.net/06oe5gn3/ .It work if br or any other element exist or doesn't exist in p. – Mohammad Jan 30 '17 at 12:42
  • Thanks. If a situation happens where another word exists before 'case' then it doesn't work. https://jsfiddle.net/sol_b/xpwbdzqg/1/ --- your solution is good for me if there is no br, but the other solution is better if there are extra words! I will have to find a compromise. Thanks for your help – sol Jan 30 '17 at 12:47