从 span 的 innerHTML 获取`selectionStart`

Posted

技术标签:

【中文标题】从 span 的 innerHTML 获取`selectionStart`【英文标题】:Getting `selectionStart` from a span's innerHTML 【发布时间】:2012-12-02 14:04:24 【问题描述】:

我有一个你自己的文本编辑器,可以让你更改textarea 元素的一部分。我想调整它以使用跨度元素。我对跨度没有特别的依恋。目标只是让某人编辑 html 而不是 textarea。我在 IE 中运行良好,但在 Mozilla 中遇到了一些问题。

由于我使用的是跨度而不是表单输入,因此我使用的是innerHTML 而不是值。但是,我似乎无法让 selectionStartselectionEnd 函数在 innerHTML 上工作,而不是在 value 上工作。

这是运行良好的textarea 代码....

html

<textarea id="textarea>Some text goes here</textarea><a href="javascript:void() onclick="editText">edit</a>

JS

function editText() 
    var len = displaytext.value.length; 
    var start = displaytext.selectionStart; 
    var end = displaytext.selectionEnd; 
    var sel = displaytext.value.substring(start, end); returns selection ok
    alert(sel);

但是,下面的改编并不限制选择开始和结束。

html

<span id="textarea>Some text goes here</span><a href="javascript:void() onclick="editText">edit</a>

JS

function editText() 
    var len = displaytext.innerHTML.length; //works ok
    var start = displaytext.selectionStart; //does not seem to work
    var end = displaytext.selectionEnd; //does not seem to work
    var sel = displaytext.innerHTML.substring(start, end); //returns whole innerHTML not selection
    alert(sel);

innerHTML 上的selecionStart 有问题吗?解决方法?语法错误?感谢您的任何建议。

【问题讨论】:

innerHTMLvalue 会导致什么结果?您可以在警报中获取这些结果并将结果粘贴到此处吗? (或链接) 它返回未定义。认为我发现 selectionStart 仅适用于 textarea 和 text 元素。看起来我需要替代适用于跨度的 selectionStart 和 selectionEnd ... how to get span selected portion using Javascript 的可能副本看这里(第一个答案解释了它) 【参考方案1】:

首先,不要将innerHTML 用于此类事情。 textContent 是这里的路。

我假设这里是符合标准的浏览器或 IE9+。

首先要做的是获取文档选择。你可以这样做

var sel = getSelection();

现在,选择可以是空的,也可以在元素之外,所以检查一下:

var rng, startSel, endSel, sel;
if (!sel.rangeCount
        || displaytext.compareDocumentPosition((rng = sel.getRangeAt(0)).startContainer) === Node.DOCUMENT_POSITION_PRECEDING
        || displaytext.compareDocumentPosition(rng.endContainer) === Node.DOCUMENT_POSITION_FOLLOWING)
    sel = "";
else 
    ...

此时,rng 包含一个Range 对象,具有startOffsetendOffset 属性。该值是整数,分别表示startContainerendContainertextContent 属性的位置。

您有一个相当简单的案例,它是一个带有单个文本节点的&lt;span&gt; 元素。在这种情况下,rng.startContainerrng.endContainer 将始终是 displaytext,或者某个前面或后面的元素,但不是 displaytext 的后代。

    ...
else 
    startSel = displaytext.compareDocumentPosition(rng.startContainer) === Node.DOCUMENT_POSITION_FOLLOWING ? 0 : rng.startOffset;
    endSel = displaytext.compareDocumentPosition(rng.endContainer) === Node.DOCUMENT_POSITION_PRECEDING ? displaytext.textContent.length : rng.endOffset;
    sel = displaytext.textContent.substring(startSel, endSel);

如果displaytext 的结构更复杂,有子元素等等,事情就会变得有点棘手。您必须在 displaytext 的后代树中找到起始节点的文本偏移量,最好的方法是使用 TreeWalker 对象遍历文本节点:

var tw = document.createTreeWalker(displaytext, NodeFilter.SHOW_TEXT, null, null);

【讨论】:

嗨,textContent 工作得很好,但是,我没有让整个脚本工作......jsfiddle.net/u9Re7/2 我错过了什么吗?非常感谢。 @user1904273 是的,抱歉,第一个 if 语句中有一个额外的括号。为您修复了the fiddle。 没关系。让它工作。在 Preceding 之后有一个额外的右括号。再次感谢!

以上是关于从 span 的 innerHTML 获取`selectionStart`的主要内容,如果未能解决你的问题,请参考以下文章

js获取值,动态添加到span标签中

JS--innerHTML属性

7.操作div和span

javascript中的innerHTML,innerText,outerHTML的用法及其区别

JQ和Js获取span标签的内容

用点击的 span 标签的 innerHTML 替换占位符值