在Javascript中计算嵌套元素中的文本选择偏移量

时间:2010-07-30 15:51:38

标签: javascript html dom

问题

我试图通过javascript找出特定节点的选择偏移量。

说我有以下HTML

<p>Hi there. This <strong>is blowing my mind</strong> with difficulty.</p>

如果我从 blow 中选择难度,它会向我提供#text<strong>节点的偏移量。我需要<p>的{​​{1}}的字符串偏移量和选择的长度。在这种情况下,偏移量为26,长度为40。

我的第一个想法是用字符串偏移等做一些事情,但你可以很容易地得到像

这样的东西
innerHTML

会破坏该方法,因为存在相同的节点。我还需要选择丢弃节点。说我有类似的东西

<p> Hi there. This <strong>is awesome</strong>. For real. It <strong>is awesome</strong>.</p>

我想在计算时抛出一个带<p>Hi there. <a href="#" rel="inserted">This <strong>is blowing</a> my mind</strong> with difficulty.</p> 的元素。我仍然想要26和40作为结果。

我正在寻找什么

解决方案需要递归。如果其中包含rel="inserted" <span>,则仍需要遍历<strong>

解决方案需要删除<p>的任何元素的长度。内容很重要,但标签本身不重要。所有其他标签都很重要。当我完成所有这些操作时,我强烈不希望从DOM中删除任何元素。

我正在使用rel="inserted"来获取选择对象。此解决方案只需在WebKit中工作。 jQuery是一个选项,但如果可能的话,我更愿意没有它。

非常感谢任何想法。

我无法控制HTML,而是完成了所有这些操作。

5 个答案:

答案 0 :(得分:3)

这种抵消实际上意味着什么?元素的innerHTML内的偏移量将非常脆弱:任何新节点的插入或更改为偏移量表示的文档中的点之前的元素的属性将使该偏移量无效。

我强烈建议以DOM Range的形式使用浏览器的内置支持。您可以按如下方式获取表示当前选择的范围:

var range = window.getSelection().getRangeAt(0);

如果您要根据所需的偏移量操作DOM,那么最好使用节点代替这些节点的字符串表示。

答案 1 :(得分:3)

我想我解决了我的问题。我没有像我原先计划的那样计算偏移量。我正在存储块中的“路径”(又名<p>)。这是代码:

function isChunk(node) {
  if (node == undefined || node == null) {
    return false;
  }
  return node.nodeName == "P";
}

function pathToChunk(node) {
  var components = new Array();

  // While the last component isn't a chunk
  var found = false;
  while (found == false) {
    var childNodes = node.parentNode.childNodes;
    var children = new Array(childNodes.length);
    for (var i = 0; i < childNodes.length; i++) {
      children[i] = childNodes[i];
    }        
    components.unshift(children.indexOf(node));

    if (isChunk(node.parentNode) == true) {
      found = true
    } else {
      node = node.parentNode;
    }
  }

  return components.join("/");
}

function nodeAtPathFromChunk(chunk, path) {
  var components = path.split("/");
  var node = chunk;
  for (i in components) {
    var component = components[i];
    node = node.childNodes[component];
  }
  return node;
}

所有这一切,你可以这样做:

var p = document.getElementsByTagName('p')[0];
var piece = nodeAtPathFromChunk(p, "1/0"); // returns desired node
var path = pathToChunk(piece); // returns "1/0"

现在我只需要扩展所有这些以支持选择的开始和结束。这是一个很好的构建块。

答案 2 :(得分:1)

您可以使用以下javascript代码:

var text = window.getSelection();
var start = text.anchorOffset;
alert(start);
var end = text.focusOffset - text.anchorOffset;
alert(end);

答案 3 :(得分:-1)

检查你选择的元素是否是一个段落,如果没有使用像Prototype的Element.up()方法那样选择第一段父句。

例如:

if(selected_element.nodeName != 'P') {
  parent_paragraph = $(selected_element).up('p');
}

然后找到parent_paragraph的文本偏移量和selected_element的文本偏移量之间的差异。

答案 4 :(得分:-3)

也许你可以使用jQuery选择器来忽略rel =“inserted”?

$('a[rel!=inserted]').doSomething();

http://api.jquery.com/attribute-not-equal-selector/

您现在使用哪些代码从难度进行选择?