How to add div or span around substrings in text inside a div at specific indices?

644 views Asked by At

I have a div containing a string. For instance:

<div id='original'>A red chair that is on the left of another chair next to the door</div>

I have stored some user-selected substrings in the db with start and end indices. For example:

phrase: chair, start: 43, end: 48
phrase: the door, start: 58, end: 66

Now, I'd like to add a span or a div around the above two phrases in the 'original' div so that I can highlight these phrases.

Expected result:

<div id='original'>A red chair that is on the left of another <div style="display:inline; color:#ed3833; cursor:pointer;">chair</div> next to <div style="display:inline; color:#ed3833; cursor:pointer;">the door</div></div>

For one phrase, I'm able to insert div around it using the start and end index but for the subsequent inserts, it obviously fails because the index has now changed due to the addition of div around the first phrase. Could you please help me with this?

I don't know if it helps but for for the adding div around first phrase, I'm using the following logic:

str = $('#original').text()
var preStr = str.substring(0, startIdx);
var newStr = `<div style="display:inline; color:#ed3833; cursor:pointer;">${phrase}</div>`
var postStr = str.substring(endIdx, str.length);
result = preStr+newStr+postStr;

Let me know if you need more clarity I will try and explain a bit better.

5

There are 5 answers

4
Pranav Rustagi On BEST ANSWER

You can form arrays for indices and do that like this :

var str = $('#original').html();

var startInd = [43, 58];
var lastInd = [48, 66];
var count = startInd.length;

for (let i = 0; i < count; i++) {
  let pre = str.substring(0, startInd[i]);
  let post = str.substring(lastInd[i], str.length);
  let phrase = str.substring(startInd[i], lastInd[i]);

  let nextPhrase;

  if (i < count - 1) {
    nextPhrase = str.substring(startInd[i + 1], lastInd[i + 1]);
  }

  str = pre + `<div style='display:inline; color:#ed3833; cursor:pointer;'>${phrase}</div>` + post;

  if (i < count - 1) {
    startInd[i + 1] = str.indexOf(nextPhrase, startInd[i + 1]) - 1;
    lastInd[i + 1] = startInd[i + 1] + nextPhrase.length;
  }

}

$('#original').html(str);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id='original'>A red chair that is on the left of another chair next to the door</div>

1
Tobias Nickel On

is it important to you to use the indexes from db? what about this?

result = $('#original')
  .text()
  .split(phrase)
  .join(`<div ...>${phrase}</div>`);
1
Kresimir Pendic On

better yet is to make wrapping element as minimal you can, so I'd suggest to use css for style.

Also, there is native javascript regex that you we can use, and as example I've built little wrapper function as helper to wrap results in, also I'm using pure JS and not jQuery is needed

var el = document.getElementById('original') // target element
var ht = el.innerHTML // inner html

// helper wrapper function
function wrapper( match ){
  return '<span class="wrap">' + match + '</span>'
}

ht = ht.replace( /chair/g , wrapper );
ht = ht.replace( /the door/g , wrapper );

el.innerHTML = ht // write results in div

console.log( ht )
.wrap{
  display: inline;
  color:#ed3833; 
  cursor:pointer
}
<div id='original'>A red chair that is on the left of another chair next to the door</div>

0
Lupo On

i played around with it a little and maybe you find this approach useful: i split the string into words and calculate the words length in order to get the current position where the replacement would take place. then the manipulation is put on the single element - so the global order/position is not changed. its just a thought maybe you could use it in your project

    let input = 'A red chair that is on the left of another chair next to the door';
let phrases ={
    'chair' : {start: 43, end: 48},
    'the door': {start: 58, end: 66}
};
let words = input.split(' ');
let position = 0;
for (word of words) {
    position += word.length + 1 // add one extra for blank after a word;
    if (phrases.chair.start === position || phrases["the door"].start === position + 1) {
        word = "<div class='start highlight'>" + word;
    }
    if (phrases.chair.end === position || phrases["the door"].end === position) {
        word = word + "</div>";
    }
    console.log(word+" : " + position);
}
1
Julie On

You can do this :

str= $('#original').text();
str = str.replace(/(chair(?= next to)|the door)/g, '<div style="display:inline; color:#ed3833; cursor:pointer;">$&</div>');  
$('#result').html(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='original'>A red chair that is on the left of another chair next to the door</div>
<p id='result'></p>