2014-06-19 56 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' } 
    } 
] 

,将让你的索引成整数字符位置每一行,并在与相关的样式为对象沿位置获得字符。