我會從定義高亮範圍作爲對象開始,然後從那裏開始工作。例如,
ranges = [{
"begin": 145,
"end": 155
}, {
"begin": 4,
"end": 18
}, {
"begin": 4,
"end": 18
}, {
"begin": 90,
"end": 102
}, {
"begin": 4,
"end": 41
}];
無論這些都是你的JS中定義,或者如果它們來自服務器API是由你和你如何設計程序。但是,一旦你有了這些定義,創建一個函數,將您的原始字符串和這個範圍的集合,並打破你的字符串(最好使用slice
)到一個字符串段的集合。然後,您可以遍歷您的細分,並根據需要附加<span>
和</span>
,然後將最終字符串放入DOM中。我無法從你的代碼中得知你從哪裏得到你的索引。但是如果你能把它們放在這樣一個乾淨的結構中,那麼你可以乾淨地打破你的絃樂。
在這裏要記住的一件事是,你可以有重疊跨度。如果發生這種情況,你需要將你的範圍變平。這裏有一組函數可以讓你得到你所需要的。請致電createHighlightedString
,並附上您的文字和高亮範圍列表。如有必要,它會將您的範圍變平,並給您一個清晰的結果。在這個底部有一個到工作樣品的鏈接。
//Your implementation would look "something" like this
nst = htmlentities(content);
var ranges = [];//??? - GET YOUR RANGES DEFINED CLEANLY HERE
var highlightedString = createHighlightedString(ranges,nst);
$("#l"+line).html(highlightedString);
function createHighlightedString(ranges, text) {
var flatRanges = flattenRanges(ranges);
var inflatedRanges = inflateRanges(flatRanges, text.length);
var filledRanges = fillRanges(inflatedRanges, text);
var str = "";
var index = 0;
for (var i in filledRanges) {
var range = filledRanges[i];
var begin = range.begin, end = range.end;
if (range.count > 0) {
str += "<span class='highlight'>" + range.text + "</span>";
} else {
str += range.text;
}
}
return str;
}
function flattenRanges(ranges) {
var points = [];
var flattened = [];
for (var i in ranges) {
if (ranges[i].end < ranges[i].begin) { //RE-ORDER THIS ITEM (BEGIN/END)
var tmp = ranges[i].end+1; //RE-ORDER BY SWAPPING
ranges[i].end = ranges[i].begin;
ranges[i].begin = tmp;
}
points.push(ranges[i].begin);
points.push(ranges[i].end);
}
//MAKE SURE OUR LIST OF POINTS IS IN ORDER
points.sort(function(a, b){return a-b});
//FIND THE INTERSECTING SPANS FOR EACH PAIR OF POINTS (IF ANY)
//ALSO MERGE THE ATTRIBUTES OF EACH INTERSECTING SPAN, AND INCREASE THE COUNT FOR EACH INTERSECTION
for (var i in points) {
if (i==0 || points[i]==points[i-1]) continue;
var includedRanges = ranges.filter(function(x){
return (Math.max(x.begin,points[i-1]) < Math.min(x.end,points[i]));
});
if (includedRanges.length > 0) {
var flattenedRange = {
begin:points[i-1],
end:points[i],
count:0
}
for (var j in includedRanges) {
var includedRange = includedRanges[j];
for (var prop in includedRange) {
if (prop != 'begin' && prop != 'end') {
if (!flattenedRange[prop]) flattenedRange[prop] = [];
flattenedRange[prop].push(includedRange[prop]);
}
}
flattenedRange.count++;
}
flattened.push(flattenedRange);
}
}
return flattened;
}
function inflateRanges(ranges, length=0) {
var inflated = [];
var lastIndex;
for (var i in ranges) {
if (i==0) {
//IF THERE IS EMPTY TEXT IN THE BEGINNING, CREATE AN EMPTY RANGE
if (ranges[i].begin > 0){
inflated.push({
begin:0,
end:ranges[i].begin-1,
count:0
});
}
inflated.push(ranges[i]);
} else {
if (ranges[i].begin == ranges[i-1].end) {
ranges[i-1].end--;
}
if (ranges[i].begin - ranges[i-1].end > 1) {
inflated.push({
begin:ranges[i-1].end+1,
end:ranges[i].begin-1,
count:0
});
}
inflated.push(ranges[i]);
}
lastIndex = ranges[i].end;
}
//FOR SIMPLICITY, ADD ANY REMAINING TEXT AS AN EMPTY RANGE
if (lastIndex+1 < length-1) {
inflated.push({
begin:lastIndex+1,
end:length-1,
count:0
})
}
return inflated;
}
function fillRanges(ranges, text) {
for (var i in ranges) {
ranges[i].text = text.slice(ranges[i].begin,ranges[i].end+1);
}
return ranges;
}
工作例如:https://jsfiddle.net/shfpxp82/10/
你試過[mark.js(https://markjs.io/)? – dude
是的,我做過了,但沒有按行列標記(或者我錯過了文檔中的那部分) – user2374726