David David - 1 month ago 9
HTML Question

Reproducing HTML text using saved indices

I'm not exactly sure how to entitle this question, but here it goes. I have an app which allows logged-in users to highlight regions of text. Given the text:


Lorem Ipsum is simply dummy text of the printing and typesetting
industry.


Assume this text is saved in a database and gets loaded when a user logs on. A user can also highlight regions in the text to create the following html:

<p>
<mark>Lorem Ipsum</mark> is simply dummy <mark>text of the printing</mark> and typesetting industry.
</p>


where "Lorem Ipsum" and "text of the printing" were both highlighted. I have the javascript working which injects the
<mark>
tags in the correct place, now I need to find a way to essentially recreate the highlighted regions when the user logs back on. One way is to save the entire html element with the
<mark>
tags, but since these paragraphs can get very long, this seems extremely inefficient to me, especially when you consider that many users will use this and you'll have to replicate so much content for each user.

I thought maybe another way is to save the indices of where the
<mark>
tags occur in the string, but this sounds tricky because the indices change once you insert
<mark>
tags into the string and the (very) original saved string doesn't have any html in it (in the database).

Is there a simpler way I'm not thinking of?

Answer

You can get the indices of each <mark>/</mark> pair like this:

var s = '<mark>Lorem Ipsum</mark> is simply dummy <mark>text of the printing</mark> and typesetting industry.';

var a = [];
while(/\<mark\>/.test(s)) {
  a.push(s.indexOf('<mark>'));
  s= s.replace('<mark>','');
  a.push(s.indexOf('</mark>'));
  s= s.replace('</mark>','');
}

Note how the tags are removed while we parse the string.

You can then restore the tags by iterating backwards through the array:

a.reverse().forEach(function(v, i) {
  if(i%2===0) {
    s = s.slice(0,v) + '</mark>' + s.slice(v);
  } else{
    s = s.slice(0,v) + '<mark>' + s.slice(v);
  }
});

This way, you can store only the array itself in the database and then restore the marks when the user reloads the page.

var s = '<mark>Lorem Ipsum</mark> is simply dummy <mark>text of the printing</mark> and typesetting industry.';

var a = [];
while(/\<mark\>/.test(s)) {
  a.push(s.indexOf('<mark>'));
  s= s.replace('<mark>','');
  a.push(s.indexOf('</mark>'));
  s= s.replace('</mark>','');
}
console.log('marks removed: ' + s);

a.reverse().forEach(function(v, i) {
  if(i%2===0) {
    s = s.slice(0,v) + '</mark>' + s.slice(v);
  } else{
    s = s.slice(0,v) + '<mark>' + s.slice(v);
  }
});
console.log('marks restored: ' + s);