2014-06-19 57 views
5

我正在研究一個簡單的文本屏幕/終端仿真器(類似於JQuery終端插件,但沒有RPC內容和窗口功能)。 屏幕的每一行都是一個表格行(一個HTML字符串),打印命令可以插入帶有一些屬性(例如前景色和背景色)的文本。每個打印的文本 都包含一個帶有樣式屬性的跨度,例如:獲取HTML字符串中封閉標籤的屬性

<span style="color:#000000;background-color:#111111">A</span><span style="color:#222222;background-color:#333333>BC</span> 

這可以正常工作。現在,我想添加一個函數,該函數在給定的屏幕位置上給出了字符的所有屬性, 上面的行中,位置0(A)處的字符的顏色爲#000000。 所以我必須計算不屬於span標籤的字符並獲取最後的前面的樣式。我的第一個比較容易出錯的解決方案是:

function getAttr(line, position) { 
    var result = {foreground:'', background:''}, 
     ch = '', i, j = -1, tag = false; 

    // Count characters 
    for (i = 0; i < line.length && j < position; i++) { 
     ch = line.charAt(i); 

     if (ch == '<') { 
      tag = true; 
     } 

     if (ch == '>') { 
      tag = false; 
     } 
     else if (!tag) { 
      j++; 
     } 
    } 

    i--; 

    // Find styles 
    while (i > 0 && line.charAt(i) != '<') { 
     if (line.substr(i, 6) == 'color:') { 
      result.foreground = line.substr(i + 6, 7); 
     } 
     if (line.substr(i, 17) == 'background-color:') { 
      result.background = line.substr(i + 17, 7); 
     } 
     i--; 
    } 

    return result; 
} 

有沒有計算字符(也許JQuery的或正則表達式)一個簡單的解決方案?

這與 Get parent element of a selected text 類似,但我不需要選擇,只是一個字符索引。

回答

0

我會離開解析HTML到瀏覽器的任務,只使用生成的DOM樹。以下是一些基於使用DOM樹的想法可以使用的僞代碼:

function getAttr(lineNumber, position) { 
    var lineDom = getDOMContainerForLineNumber(lineNumber); 
    var current = 0; // the current character position 

    function getAttrRec(elems, foreground, background) { 
    for(elem in elems) { 
     if(elem is <span>) { 
     var res = getAttrRec(elem.children, elem.foregroundColor, elem.backgroundColor); 
     if(res != null) 
      return res; 
     } else if(elem is TEXT) { 
     current += elem.textLength; 
     if(current >= position) 
      return {foreground: foreground, background: background}; 
     } 
    } 
    return null; 
    } 

    return getAttrRec(lineDom.children, black, black); 
} 

儘管這只是一個非常粗略的草圖。尤其是你必須留意空格 - 它們被瀏覽器非常精密地剝離。所以直接依靠文本長度可能不適用於你的情況。您也可能想要處理span標籤不包含前景色或背景色信息的情況。

1

處理構建數據結構的一種可能方法是,可以使用以下代碼段爲每行創建索引每行並獲取字符及其相關樣式的數據結構。這是假設您正在生成上面顯示的HTML的標記是相當穩定以及(如果需要的話,你可以考慮在正則表達式的變化):

var tagre = /\<span style="([^"]+)"\>([A-Za-z]+)\<\/span\>/ig, 
    s = '<span style="color:#000000;background-color:#111111">A</span><span style="color:#222222;background-color:#333333">BC</span>'; 

var matches, 
    positions = []; 

while (matches = tagre.exec(s)) { 
    var len = matches[2].length, 
     chars = matches[2], 
     styles = {}; 

    matches[1].split(';').forEach(function(o) { 
     var _s = o.split(':'), 
      key = _s[0], 
      val = _s[1]; 
     styles[key] = val; 
    }); 

    for (var i=0; i < len; i++) { 
     var char = chars[i]; 
     positions.push({ 'char': char, 'styles': styles }); 
    } 
} 
console.log("positions=%o", positions); 

這將使你的每一個看起來像線陣列以下內容:

[ 
    { char: 'A', 
    styles: { 'background-color': '#111111', 'color': '#000000' } 
    }, 
    { char: 'B', 
    styles: { 'background-color': '#333333', 'color': '#222222' } 
    }, 
    { char: 'C', 
    styles: { 'background-color': '#333333', 'color': '#222222' } 
    } 
] 

,將讓你的索引成整數字符位置每一行,並在與相關的樣式爲對象沿位置獲得字符。