2017-02-13 40 views
0

我試圖解析W3c API JSON輸出,javascript和我被困在如何某些跨度放置一些關鍵字裏面,因爲它們的列(它們在字符串中的位置)如何突出顯示多個項目的位置?

我已經重新組織了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

你試過[mark.js(https://markjs.io/)? – dude

+0

是的,我做過了,但沒有按行列標記(或者我錯過了文檔中的那部分) – user2374726

回答

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; 
} 

工作例如:https://jsfiddle.net/shfpxp82/10/

+0

謝謝。有效。我遇到了一些與"s;有關的問題(如果我首先選擇它們,它們會被視爲字符),但是我會使用一些BBCode來替換它,它會像我一樣滿意地工作。 :D – user2374726

+0

好聽。祝你好運! –