在文本区域中替换所选文本

24

什么是在jQuery中完成此操作的最佳方法?这应该是一个相当常见的用例。

  1. 用户选择文本区域中的文本
  2. 他单击链接
  3. 链接中的文本替换文本区域中所选的文本

任何代码将不胜感激-我在第三部分遇到了一些问题。


1
现在,您只需要使用textareainput的属性selectionStartselectionEnd。将其与输入元素值上的slice方法相结合即可。 - caw
2个回答

33
以下是如何在所有主流浏览器中实现此功能的方法。我还有一个包含此功能的jQuery插件(http://code.google.com/p/rangyinputs)。使用该插件,代码如下:
$("your_textarea_id").replaceSelectedText("NEW TEXT");

这里提供了一个完整的独立解决方案:

function getInputSelection(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();

        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;

                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }

    return {
        start: start,
        end: end
    };
}

function replaceSelectedText(el, text) {
    var sel = getInputSelection(el), val = el.value;
    el.value = val.slice(0, sel.start) + text + val.slice(sel.end);
}

var el = document.getElementById("your_textarea");
replaceSelectedText(el, "[NEW TEXT]");

@TimDown 这是一段很棒的代码,但为什么这不早就被包含在 jQuery 库中了呢?我和 Ming 一样,认为这是一个相当常见的用例。 - Ads
1
@广告:他们喜欢保持核心的简洁。我能理解这一点。 - Tim Down
将以下内容添加到replaceSelectedText()函数的末尾,以确保插入文本后光标正确地放置在其末尾:el.selectionStart = sel.start + text.length; el.selectionEnd = el.selectionStart; - Jim Carnicelli
@JimCarnicelli:对于旧版 IE,这也存在一些复杂性。请参见 https://dev59.com/0XA75IYBdhLWcg3wdIv7#3288215。 - Tim Down
请注意,链接的库尚未开源 - Flimm
显示剩余4条评论

2

在 caw 的基础上 comment,在2023年更容易实现:

link.onclick = () => {
  let first = textarea.value.slice(0, textarea.selectionStart);
  let rest = textarea.value.slice(textarea.selectionEnd, textarea.value.length);

  textarea.value = first + link.innerText + rest;

  // Bonus: place cursor behind replacement
  textarea.selectionEnd = (first + link.innerText).length;
};

它本质上就是 Tim Down的解决方案,只是缩减到在假设文本输入框上可用selectionStartselectionEnd时所需的部分。

我不确定你所说的“链接中的文本”是什么意思。暂时我使用link.innerText

我不知道为什么你需要jQuery,但你可以轻松地使用$(link).on('click', ...)或其他方式代替。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接