javascript在textarea中捕获粘贴事件

时间:2010-07-13 16:17:38

标签: javascript events textarea paste

我目前有一个textarea,我需要控制已粘贴的文本,

基本上我需要能够将用户想要粘贴的任何内容粘贴到textarea中并将其放入变量中。

然后我将确定他们粘贴文本的位置和字符串的大小以将其从textarea中删除,

然后在最后以我自己的方式处理变量中的文本。

我的问题:如何在用户粘贴的变量中获取文本的副本?

感谢。

3 个答案:

答案 0 :(得分:2)

我几天前回答了一个类似的问题:Detect pasted text with ctrl+v or right click -> paste。这次我已经包含了一个很长的函数,可以准确地在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 :(得分:1)

您现在可以使用FilteredPaste.js(http://willemmulder.github.com/FilteredPaste.js/)代替。它可以让你控制哪些内容被粘贴到textarea或contenteditable,你将能够随意过滤/更改/提取内容。

答案 2 :(得分:0)

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

你也可以使用TinyMCE,因为它确实有大量不同的事件触发器。它是一个完整的文字处理器,但如果你愿意,你可以用它作为纯文本。虽然添加它可能有点太重了。例如,在启动时,它会将您的<textarea>转换为具有多个子的iFrame。但它会做你要求的。

- 戴夫