1

我有一大段文本希望能够选择,通过它的startindex和存储选定的部分endindex。(例如,选择orinword会给我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('<strike>');
         $('#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(). start获得和的最佳方式endindex<strike>通过选定的文本,因为execCommand让我这样做,它是应用程序中从未使用过的 HTML 标记。

4

2 回答 2

3

如果您真的想使用您的代码并且只是稍微修改它,您可以用可见的等效字符替换所有特殊字符,同时保留 html 标签...将您的 startIndex 声明更改为:

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

您可以将 replaces() 函数附加到您想算作普通字符而不是它们的 HTML 版本的其他特殊字符。在我的示例中,我替换了 & 和 " 字符。

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

希望这会有所帮助,请参阅此处的分叉小提琴 http://jsfiddle.net/vQNyv/

于 2013-05-03T13:11:21.250 回答
1

问题

使用html()回报:

This is a cool test &amp; <strike>stuff like</strike> that

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

This is a cool test & stuff like that

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

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

在这种情况下,您需要解释,

Use the &lt;strike&gt;&lt;/strike&gt; 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()s 以深入了解正在发生的事情。这是关于nodeTypes 的参考。


jQuery/DOM 解决方案计数 outerHTML

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

于 2013-05-03T13:55:08.373 回答