【问题标题】:selecting text by ignoring inner Elements of div tag javascript通过忽略div标签javascript的内部元素来选择文本
【发布时间】:2011-02-26 08:40:02
【问题描述】:
<html>
<body>
<script language="javascript">
function getSelectionHTML()
{
    var div = document.getElementById("myDiv");

    if (document.createRange) { 
        var textNode=div.firstChild;
        var rangeObj=document.createRange();
        rangeObj.setStart(textNode,0);
        rangeObj.setEnd(textNode,5);
        div .innerHTML = div .innerHTML.replace(rangeObj.toString(), '<span style="background-color: lime">'+rangeObj.toString()+'</span>')
    }
}
</script>
<div id="myDiv">
asdf as<b>dfas df asf asdf sdfjk  dvh a sjkh jhcdjkv</b> iof scjahjkv ahsjv hdjk biud fcsvjksdhf k

</div>
<form name="aform">
<input type="button" value="Get selection" onclick="getSelectionHTML()">
</body>
</html>

好的。让我解释一下 -> getSelectionHTML() 方法用于选择从 0 到 10 的字符。我通过“myDiv”id 获取值。但是内部粗体、斜体和其他标签给我带来了麻烦。

简单来说,我只想选择“myDiv”标签中的前十个字符(并应用它们跨度标签)。

我到底错过了什么?

【问题讨论】:

  • 为什么要用两个局部变量来存储document.getElementById('myDiv')
  • @Marcel - 等待更正。请参阅 - 几秒钟后编辑的问题。
  • 嘿!注意这一点。我正在尝试这个链接 - help.dottoro.com/ljvfwqlq.php

标签: javascript html safari dhtml


【解决方案1】:

这在 IE 中使用 TextRange 更容易,它基于字符、单词和句子而不是节点和偏移量。在非 IE 浏览器中,您需要对 DOM 中的文本节点进行繁琐的手动遍历。但是,即使您要这样做以获取 &lt;div&gt; 中的前十个文本字符(即“asdf asdfa”),您的策略也是有缺陷的,因为您在 innerHTML 上使用了替换,这将尝试并且找不到“asdf asdfa”(innerHTML 将以“asdf as&lt;b&gt;dfa”开头,或者可能以“asdf as&lt;B&gt;”开头,具体取决于浏览器)。

我的建议是进行 DOM 遍历以查找 &lt;div&gt; 内的所有文本节点,并使用 &lt;span&gt;s 围绕您需要的文本节点部分,从而完全避免 Ranges,从而使这项工作在所有主要浏览器。

【讨论】:

    【解决方案2】:

    您正在尝试选择例如文本的第 1 到 10 个字符。但是当使用Range.setStart.endStart 时,第一个参数是包含您的文本的文本节点。如果您使用 Firebug(或 Web Inspector)浏览 DOM,您会注意到文本的第 10 个字符位于另一个元素(&lt;b&gt; 元素)中,具有自己的文本节点。

    顺便说一句,您遗漏了几个必需的元素/标签,这可能也是错误的来源。

    我更正的版本是

    <!DOCTYPE html>
    <html>
    <head>
      <title>Title element is required</title>
    <body>
    <script>
    function getSelectionHTML()
    {
        var div = document.getElementById("myDiv");
        var bEl = document.getElementById("bEl");
    
        if (document.createRange) {.
            var textNode=div.firstChild;
            var rangeObj=document.createRange();
            rangeObj.setStart(textNode,0);
            rangeObj.setEnd(bEl.firstChild,2);
            alert(rangeObj.toString());
    //        div.innerHTML = div.innerHTML.replace(rangeObj.toString(), '<span style="background-color: lime">'+rangeObj.toString()+'</span>');
        }
    }
    </script>
    <div id="myDiv">
    asdf as<b id="bEl">dfas df asf asdf sdfjk  dvh a sjkh jhcdjkv</b> iof scjahjkv ahsjv hdjk biud fcsvjksdhf k
    </div>
    <form name="aform">
      <input type="button" value="Get selection" onclick="getSelectionHTML()">
    </form>
    </body>
    </html>
    

    现在rangeObj 包含选定的文本,但您不能像尝试的那样简单地插入&lt;span&gt; 元素,因为元素不能以这种方式嵌套:

    <span>asdf as<b>dfa</span>s df asf…
    

    【讨论】:

    • 但这是静态解决方案,可能有粗体,也可能没有。其中可能有任何其他标签。我问忽略内部元素。
    • 如果你说它不能被嵌套——那这怎么可能? theSelection = document.selection.createRange().htmlText; document.selection.createRange().pasteHTML("" + theSelection + "");
    • @sugar:我已经担心你希望它适用于任何情况,无论是否有内部元素。不幸的是,您不能简单地忽略它们。您必须计算父元素中的字符数,然后遍历 DOM 以计算每个子元素中的字符数,直到获得所需的字符数。
    • @sugar:关于您的第二条评论:您几乎必须解析遇到的 HTML 并在每个元素中创建内部跨度(以便正确嵌套它们),例如 &lt;span&gt;bla&lt;/span&gt;&lt;b&gt;&lt;span&gt;blabla&lt;/span&gt;&lt;i&gt;&lt;span&gt;bl&lt;/span&gt;&lt;/i&gt;a&lt;/b&gt;
    • sugar:该问题的答案通过遍历所选范围内的文本节点并用跨度包围每个节点来起作用。
    猜你喜欢
    • 2020-06-20
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多