如何在不计算扩展实体的情况下找到标签(元素)的字符串索引?

我有一大段文本,我希望能够选择,通过startindexendindex存储选定的部分。 (例如,选择orword会给我startindex 1和endindex 2

这一切都正常,但我有一个HTML实体的问题,如& (&符号)。

我已经创建了一个问题所在的小案例。 您可以在下面的小提琴中看到,如果您选择&之外的任何内容,则startIndex膨胀,因为它不会将&计为单个字符,而是将5个字符统计为&

有没有办法让它能够正确计算像&符号这样的特殊字符,而不会搞砸索引?

http://jsfiddle.net/Eqct4/

JavaScript的


 $(document).ready(function() { $('#textBlock').mouseup(function() { var selectionRange = window.getSelection(); if (!selectionRange.isCollapsed) { selectedText = selectionRange.getRangeAt(0).toString(); } document.getElementById('textBlock').setAttribute('contenteditable', true); document.execCommand('strikethrough', false); var startIndex = $('#textBlock').html().indexOf(''); $('#startindex').html('the startindex is: ' + startIndex); done(); }); }); function done() { document.getElementById('textBlock').setAttribute('contenteditable', false); document.getSelection().removeAllRanges(); removeStrikeFromElement($('#textBlock')); } function removeStrikeFromElement (element) { element.find('strike').each(function() { jQuery(this).replaceWith(removeStrikeFromElement(jQuery(this))); }); return element.html(); } 

我认为/知道它与$('#textBlock').html()用于执行indexOf而不是text() 。 获取startendindex的最佳方法是通过所选文本 ,因为execCommand让我这样做,它是一个从未在应用程序中使用的HTML标记。

如果你真的想要使用你的代码并稍微修改一下你可以用可见的等价替换所有特殊字符,同时保留html标签…将startIndex的声明更改为:

 var startIndex = $('#textBlock').html().replace(/&/g, "&").replace(/"/g, "\"").indexOf(''); 

您可以将replaceces()函数与您想要计为普通字符而不是HTML版本的其他特殊字符一起追加。 在我的例子中,我替换了&和“字符。

您的代码中可以使用更多优化方法,这是解决问题的简单方法。

希望这有点帮助,请看这里的分叉小提琴http://jsfiddle.net/vQNyv/

问题

使用html()返回:

 This is a cool test & stuff like that 

但是,使用text()会返回:

 This is a cool test & stuff like that 

因此, html()是必要的,以便查看字符串 ,但当然所有特殊实体都是转义的,它们应该是。 有很多方法可以解决这个问题,但想象一下,如果文本描述HTML本身会发生什么:

 Use the  tags to strike out text. 

在这种情况下,你想要解释,

 Use the <strike></strike> tag to strike out text. 

这就是为什么唯一正确的方法是迭代DOM节点。


jQuery / DOM解决方案

这是我的解决方案的jsFiddle ,这是代码:

 jQuery.fn.indexOfTag = function (tag) { var nodes = this[0].childNodes; var chars = 0; for (var i = 0; nodes && i < nodes.length; i++) { var node = nodes[i]; var type = node.nodeType; if (type == 3 || type == 4 || type == 5) { // alert('advancing ' + node.nodeValue.length + ' chars'); chars += node.nodeValue.length; } else if (type == 1) { if (node.tagName == tag.toUpperCase()) { // alert('found <' + node.tagName + '> at ' + chars + ', returning'); return chars; } else { // alert('found <' + node.tagName + '>, recursing'); var subIndexOfTag = $(node).indexOfTag(tag); if (subIndexOfTag == -1) { // alert('did not find <' + tag.toUpperCase() + '> in <' + node.tagName + '>'); chars += $(node).text().length; } else { // alert('found <' + tag.toUpperCase() + '> in <' + node.tagName + '>'); chars += subIndexOfTag; return chars; } } } } return -1; } 

取消注释alert()以深入了解正在发生的事情。 这是 nodeType的参考 。


计算outerHTML的jQuery / DOM解决方案

根据您的评论,我认为您说您确实想要计算HTML标签(按字符计算),但不是HTML实体。 这是函数本身的一个新的jsFiddle ,这里有一个适用于你的问题的新jsFiddle 。