我正在尝试使用javascript解析W3c API JSON输出,并且考虑到它们的列(它们在字符串中的位置),我陷入了如何在某些关键字中放置一些跨度
我已经使用PHP重新组织了这些消息,因此我结束了以下内容:
$.each(data.messages,function(line,msgs) {
content = $("#l"+line).text();
offset = 0;
$.each(msgs,function(i,v) {
position = v.firstColumn+v.hiliteStart+offset;
length = v.hiliteLength;
if (isNaN(position)) {
position = v.lastColumn+v.hiliteStart;
}
content = content.substr(0, position)+'[span]'+content.substr(position, length)+'[/span]'+content.substr(position + length);
offset += 13; //offset compensates for [span] and [/span]
});
//htmlentites function from locutus.io
nst = htmlentities(content);
nst = nst.replace(/\[span\]/g,'<span>');
nst = nst.replace(/\[\/span\]/g,'</span>');
$("#l"+line).html(nst);
});
我的目标是在同一行HTML代码中突出显示几个错误和警告。
答案 0 :(得分:0)
我首先将高亮范围定义为对象,然后从那里开始工作。例如,
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;
}