JavaScript如何捕获textarea文本框的粘贴事件?

6
我目前有一个文本区域,需要控制已粘贴的文本。基本上,我需要能够将用户想要粘贴到文本区域中的任何内容放入变量中。然后,我将确定他们粘贴文本的位置和要从文本区域中删除的字符串大小,最后按照自己的方式处理变量中的文本。我的问题是:我该如何获取用户刚刚粘贴的文本的副本放入变量中?谢谢。
4个回答

3
我几天前回答过类似的问题:检测使用ctrl+v或右键粘贴的文本。这次我包含了一个相当长的函数,可以准确地获取IE textarea中的选择边界;其余部分相对简单。
您可以使用粘贴事件来检测大多数浏览器中的粘贴操作(特别是不支持Firefox 2)。在处理粘贴事件时,记录当前选择,然后设置一个简短的计时器,在粘贴完成后调用一个函数。这个函数可以通过比较长度来知道要查找粘贴的内容的位置。类似以下内容:
function getSelectionBoundary(el, start) {
    var property = start ? "selectionStart" : "selectionEnd";
    var originalValue, textInputRange, precedingRange, pos, bookmark, isAtEnd;

    if (typeof el[property] == "number") {
        return el[property];
    } else if (document.selection && document.selection.createRange) {
        el.focus();

        var range = document.selection.createRange();
        if (range) {
            // Collapse the selected range if the selection is not a caret
            if (document.selection.type == "Text") {
                range.collapse(!!start);
            }

            originalValue = el.value;
            textInputRange = el.createTextRange();
            precedingRange = el.createTextRange();
            pos = 0;

            bookmark = range.getBookmark();
            textInputRange.moveToBookmark(bookmark);

            if (/[\r\n]/.test(originalValue)) {
                // Trickier case where input value contains line breaks

                // Test whether the selection range is at the end of the
                // text input by moving it on by one character and
                // checking if it's still within the text input.
                try {
                    range.move("character", 1);
                    isAtEnd = (range.parentElement() != el);
                } catch (ex) {
                    log.warn("Error moving range", ex);
                    isAtEnd = true;
                }
                range.moveToBookmark(bookmark);

                if (isAtEnd) {
                    pos = originalValue.length;
                } else {
                    // Insert a character in the text input range and use
                    // that as a marker
                    textInputRange.text = " ";
                    precedingRange.setEndPoint("EndToStart", textInputRange);
                    pos = precedingRange.text.length - 1;

                    // Delete the inserted character
                    textInputRange.moveStart("character", -1);
                    textInputRange.text = "";
                }
            } else {
                // Easier case where input value contains no line breaks
                precedingRange.setEndPoint("EndToStart", textInputRange);
                pos = precedingRange.text.length;
            }
            return pos;
        }
    }
    return 0;
}

function getTextAreaSelection(textarea) {
    var start = getSelectionBoundary(textarea, true),
        end = getSelectionBoundary(textarea, false);

    return {
        start: start,
        end: end,
        length: end - start,
        text: textarea.value.slice(start, end)
    };
}

function detectPaste(textarea, callback) {
    textarea.onpaste = function() {
        var sel = getTextAreaSelection(textarea);
        var initialLength = textarea.value.length;
        window.setTimeout(function() {
            var val = textarea.value;
            var pastedTextLength = val.length - (initialLength - sel.length);
            var end = sel.start + pastedTextLength;
            callback({
                start: sel.start,
                end: end,
                length: pastedTextLength,
                text: val.slice(sel.start, end),
                replacedText: sel.text
            });
        }, 1);
    };
}

window.onload = function() {
    var textarea = document.getElementById("your_textarea");
    detectPaste(textarea, function(pasteInfo) {
        var val = textarea.value;

        // Delete the pasted text and restore any previously selected text
        textarea.value = val.slice(0, pasteInfo.start) +
            pasteInfo.replacedText + val.slice(pasteInfo.end);

        alert(pasteInfo.text);
    });
};

1

0

关于您获取粘贴内容的问题,您可以使用事件的 clipboardData 属性:

myTextArea.addEventListener("paste", (e) => {
    // Get new paste
    const paste = (e.clipboardData || window.clipboardData).getData("text");

    // Get "old" textarea content (without latest paste)
    const content = e.target.value;
});

0

快速搜索显示不同的浏览器有不同的方法。我不确定jQuery是否有解决方案。Prototype.js似乎没有一个。也许YUI可以为您做到这一点?

您还可以使用TinyMCE,因为它具有无数种不同的事件触发器。它是一个完整的文字处理器,但如果您想要,可以将其用作纯文本。不过,它可能会增加太多的负担。例如,在初始化时,它会将您的<textarea>转换为带有几个子元素的iFrame。但它会完成您所要求的。

--戴夫


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