Reputation: 2695
I am new to webDevelopment
. I have string which has some text.Now I want to highlight some words from that text file . So, Here I am using this logic
$scope.highlightHTML = function (content,startoffset,endoffset,color) {
var className = 'mark';
console.log(content.substring(startoffset, endoffset));
return content.replace(content.substring(startoffset, endoffset), '<span class="' + className + '">$&</span>');
}
Now this is working fine. But Now what happens is when first word gets highlighted and then when It tries to highlight the second word then the strings offsets are getting changed because of this replacing . It takes tag as well so, now offsets are getting changed. now when I highlight some text then next time it should not take offsets of start and end offset of the span tag . SO, How can I do this ?
Its like , "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged"
I have this string. Now, I want to highlight when an unknown printer took a galley of
Now, for this I use substring because I get the start and end from back-end itself. I replace only that string with mark tag.
Now The problem is after this immediately,If I want to highlight but also the leap into electronic typesetting
, Then the offset which I got from the backend will not be useful because while replacing the first string I added span tag, so it is taking the span tag offsets as well. So, Its not getting me the exact string by providing the offsets as well. It gives me some another string because offsets has changed. Now, whil highlighting the offsets should not get changed by adding the span tag.
Ajax call -
jsonDataArray.forEach(function (item) {
responseData = $scope.highlightHTML(responseData,item.startOffset,item.endOffset,item.color);
$rootScope.data.htmlDocument = responseData.replace(/\n/g, "</br>");;
});
Upvotes: 0
Views: 2322
Reputation: 342
Can you keep the original content to the global variable ?
So you don't need to worry about offset changed by added span tag.
updated code
var responseData;
function readFile() {
responseData = 'Lorem ipsum dolor sit amet, consectetur .....'
}
var highlightNeeded = []
jsonDataArray.forEach(function (item) {
var actualText = responseData.substring(item.startOffset, item.endOffset)
highlightNeeded.push(highlightNeeded)
});
// call this after foreach finished
var tmpData = $scope.highlightHTML(responseData, highlightNeeded, item.color);
$rootScope.data.htmlDocument = tmpData.replace(/\n/g, "</br>");;
$scope.highlightHTML = function (content, listOfText, color) {
var className = 'mark';
listOfText.forEach(function (text) {
var regex = new RegExp(text, 'gi')
content.replace(regex, '<span class="' + className + '">$&</span>');
})
}
Upvotes: 0
Reputation: 1001
You can achieve this by using the length of the string using below logic.
I'm adding span to 'simply dummy', 'and typesetting', 'Ipsum has been'
in your text.
what i have done is after the text has been updated after the function call, i am adding the difference between the initial text length and updated text length to the offeset which calling the function again which gives me the exact offsets of the words.
Please let me know whether its works for you.
Updated ajax :
var initialLength = responseData.length;
var updatedLength = 0;
jsonDataArray.forEach(function(item, index) {
if (index == 0)
responseData = $scope.highlightHTML(responseData, parseInt(item.startOffset), parseInt(item.endOffset), item.color);
else
$scope.highlightHTML(responseData, parseInt(item.startOffset) + (updatedLength - initialLength), parseInt(item.endOffset) + (updatedLength - initialLength), item.color);
updatedLength = responseData.length;
$rootScope.data.htmlDocument = responseData.replace(/\n/g, "</br>");;
});
$(document).ready(function() {
var text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged";
var initialLength = text.length;
var updatedLength = 0;
var startoffset1 = 15;
var endoffset1 = 27;
var startoffset2 = 49;
var endoffset2 = 64;
var startoffset3 = 81;
var endoffset3 = 95;
console.log(text.substring(startoffset1, endoffset1));
console.log(text.substring(startoffset2, endoffset2));
console.log(text.substring(startoffset3, endoffset3));
text = highlightHTML(text, startoffset1, endoffset1, 'green');
updatedLength = text.length;
text = highlightHTML(text, startoffset2 + (updatedLength - initialLength), endoffset2 + (updatedLength - initialLength), 'green');
updatedLength = text.length;
text = highlightHTML(text, startoffset3 + (updatedLength - initialLength), endoffset3 + (updatedLength - initialLength), 'green');
console.log(text);
});
function highlightHTML(content, startoffset, endoffset, color) {
var className = 'mark';
console.log('Inside Function: ' + content.substring(startoffset, endoffset));
return content.replace(content.substring(startoffset, endoffset), '<span class="' + className + '">$&</span>');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 1
Reputation: 13162
Sometimes it's cool to keep it cryptic and concise for no reasons...It can still be less cryptic at end!
So here my version using the html <mark>
and <wbr>
tags.
There is not so much need to melt non related functions from my view, it loose all the versatility/portability.
let ߐ = document.body
function check(_ૐ){
ߐ.innerHTML=ߐ.innerHTML.replace(_ૐ,"<mark>"+_ૐ+"</mark>")
}
check("when an unknown printer took a galley of")
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
The mark
tag suits very well for highlighting,as it is made for that, there is some special wizardry with the wbr
.
wbr: On UTF-8 encoded pages, behaves like the U+200B ZERO-WIDTH SPACE code point. In particular, it behaves like a Unicode bidi BN code point, meaning it has no effect on bidi-ordering: 123,456 displays, when not broken on two lines, 123,456 and not 456,123.
For the same reason, the element does not introduce a hyphen at the line break point. To make a hyphen appear only at the end of a line, use the soft hyphen character entity () instead.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr
Here the marking will disappear after 8s, without breaking the text.
let ߐ = document.body
function check(_ૐ){
ߐ.innerHTML=ߐ.innerHTML.replace(_ૐ,"<mark>"+_ૐ+"</mark>")
window.setTimeout(Ώ,8000)}
function Ώ(){
ߐ.innerHTML=ߐ.innerHTML.replace("mark","wbr")}
check("when an unknown printer took a galley of")
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
Source: https://codepen.io/Nico_KraZhtest/pen/mEjBdj
For you exact enquiry, it can then look like this:
jsonDataArray.forEach(function (item) {
responseData = $scope.highlightHTML(responseData,item.startOffset,item.endOffset,item.color);
$rootScope.data.htmlDocument = responseData.replace("when an unknown printer took a galley of","<mark>"+"when an unknown printer took a galley of"+"</mark>")
});
Or, more nicely:
let search = "when an unknown printer took a galley of"
jsonDataArray.forEach(function (item, search) {
responseData = $scope.highlightHTML(responseData,item.startOffset,item.endOffset,item.color)
$rootScope.data.htmlDocument = responseData.replace(search,"<mark>"+search+"</mark>")
})
Upvotes: 0