0

我的意思是,以下面的 HTML 代码为例,忽略空格。

<p>
  paragraph-text
  <span>
   span text
   <i>it</i>
  </span>
</p>

我有 pNode 对象和 pNode.innerHTML 中的“span text”中的“a”索引作为一个整体,这里是 23,因为 pNode.innerHTML="paragraph-text<span>span text<i>it</i ></span>”,开放跨度标签也应该被计算在内。

是否有一些现有的库可以像 transform(pElement, 23) 一样使用,这样我就可以获得“spanElement and 2”的预期元素和偏移量?

提前致谢。问候,

史蒂夫

4

2 回答 2

1

您也许可以通过获取innerHTML,更改您要查找的偏移量的字符,然后重新解析和比较结果文本节点以找到更改data结束的那个。

例如。

function findTextFromMarkupIndex(el1, ix) {
    // make comparison element
    var el2= document.createElement(el1.tagName);
    // replace any other use of * in its HTML out of the way
    var html= el1.innerHTML.split('*').join('x');
    // insert a * at the given index in HTML
    el2.innerHTML= html.substring(0, ix)+'*'+html.substring(ix);
    // search the resulting DOM for the * and return the matching descandent from the original
    return findTextInComparison(el1, el2, '*');
}

function findTextInComparison(el1, el2, text) {
    for (var i= 0; i<el1.childNodes.length; i++) {
        var child1= el1.childNodes[i];
        var child2= el2.childNodes[i];
        if (child2.nodeType===3) { // TEXT_NODE
            var ix= child2.data.indexOf(text);
            if (ix!==-1)
                return [child1, ix];
        } else if (child2.nodeType===1) { // ELEMENT_NODE
            var result= findTextInComparison(child1, child2, text);
            if (result!==null)
                return result;
        }
    }
    return null;
}

未经测试,但无论如何都应该适用于文本内容中的字符。如果需要,您可以扩展它以查看属性值,但您不能在标记(例如元素或实体/字符引用)内执行索引点。为此,您基本上需要编写一个完整的 HTML 解析器。

这听起来像是一个不寻常的要求,你到底想做什么?其中的索引innerHTML可能非常脆弱,因为此属性的标记输出的确切格式根本没有标准化。

于 2010-01-21T16:31:25.127 回答
1

您所说的听起来像是DOM Range,它在除 Internet Explorer 之外的所有主要浏览器中都实现了。根据 HTML 中的字符偏移量指定位置不是一个好主意,因为 innerHTML 的实现差异很大。DOM Range 有一个开始和结束边界,每个边界都根据一个节点和该节点内的偏移量来指定。在您的示例中,您可以创建一个表示位置的 Range:

var span = pNode.childNodes[1];
var spanText = span.firstChild;
var range = document.createRange();

// Next line takes into account whitespace at the start of the text node
range.setStart(spanText, 6); 

// For illustration, create a range that contains the letter "a" and selects it
range.setEnd(spanText, 7);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

一旦有了 Range,就可以将它用于各种事情,例如插入节点、定义用户选择以及对 Range 封装的内容应用格式。

IE 定义了一个完全不同的对象,称为TextRange,它具有完全不同的基于文本的方法,但用途大致相同。要获得与上一个示例等效的 TextRange,可以使用以下命令:

var textRange = document.body.createTextRange();
textRange.moveToElementText(pNode);
textRange.moveStart("character", 17);
textRange.collapse();

// For illustration, create a range that contains the letter "a" and selects it
textRange.moveEnd("character", 1);
textRange.select();
于 2010-01-21T16:34:03.597 回答