捕捉粘贴输入


210

我正在寻找一种清理粘贴到浏览器中的输入的方法,这可能与jQuery有关吗?

到目前为止,我已经设法解决了这个问题:

$(this).live(pasteEventName, function(e) {
 // this is where i would like to sanitize my input
 return false;
}

不幸的是,由于这个“小问题”,我的发展陷入了停顿。如果有人能指出正确的方向,我真的会让我成为一个快乐的露营者。


6
请标记stackoverflow.com/a/1503425/749232作为使用其他遇到相同问题的人的答案。那为我解决了。
saji89'8

2
从jQuery 1.9开始不推荐使用.live(),而是建议使用.on()
Sameer Alibhai

Answers:


337

好吧,只是碰到了同样的问题..我走了很长一段路

$('input').on('paste', function () {
  var element = this;
  setTimeout(function () {
    var text = $(element).val();
    // do something with text
  }, 100);
});

直到.val()函数可以填充之前,只有一小段超时。

E.


20
如果文本区域中已经有文本并且您粘贴了,而您只想要粘贴的文本,该怎么办?
barfoon

39
完美的工作,谢谢。超时为0同样有效。该功能只需要推迟到下一个循环。
丹尼尔·刘易斯

4
刚刚处于类似情况。超时是因为有paste事件不是直接的,而是需要几毫秒到被粘贴剪贴板中的内容。
詹姆斯

8
@ user563811:请注意,HTML5中的官方最小超时为4ms。
pimvdb

4
如sharif所说,0ms仍将事件置于堆栈的底部。
BobRodes 2012年

67

实际上,您可以直接从事件中获取价值。虽然有点难为情。

如果您不希望它通过,则返回false。

$(this).on('paste', function(e) {

  var pasteData = e.originalEvent.clipboardData.getData('text')

});

2
这就是要走的路
DdW

1
即11:window.clipboardData.getData('text')
Wallstrider

4
但是,请注意,仅当您使用jQuery处理事件时才需要“ originalEvent”属性。您可以只e.clipboardData.getData('text')使用普通的JavaScript。
Asier Paz

最好的答案在这里!但是-我发现奇怪的是,绑定的简写版本对此不起作用,即,如果我尝试这样做,则会出错:$(this).paste(function(e){...});,甚至虽然这适用于快捷方式.on('click')等
。– HoldOffHunger

niggle:代码缺少结束括号。显然,更改幅度太小,无法让我对其进行修复。
约阿希姆·卢斯

42

为了实现跨平台兼容性,它应该处理oninput和onpropertychange事件:

$ (something).bind ("input propertychange", function (e) {
    // check for paste as in example above and
    // do something
})

2
精美的解决方案,可以同时粘贴和捕获事件。注意:如果突出显示输入内容,然后至少在IE8中键入某些内容,则由于某种原因,这将导致事件函数触发两次(在许多情况下不重要,但在其他情况下可能非常重要)。
baacke 2014年

不错!我不知道这一点,它完全符合我的需求!
Marc Brillault '16

18

我通过使用以下代码对其进行了修复:

$("#editor").live('input paste',function(e){
    if(e.target.id == 'editor') {
        $('<textarea></textarea>').attr('id', 'paste').appendTo('#editMode');
        $("#paste").focus();
        setTimeout($(this).paste, 250);
    }
});

现在,我只需要存储插入符号的位置并将其附加到该位置,即可完成所有工作...我认为:)


1
您如何存储插入符号的位置?
Petah

@Petah您可以检查哪个元素具有焦点.find(':focus'),并知道该元素确定其插入标记的位置。看到这个
2012年

请记住,不赞成使用“直播”,而建议使用“启用”
NBPalomino 2014年

input导致差异:)我通常有这些在我的文本框的事件keyup keydown paste input,但显然取决于你的动机是什么
皮埃尔·

10

嗯...我您可以e.clipboardData用来捕获正在粘贴的数据。如果没有成功,请在这里看看。

$(this).live("paste", function(e) {
    alert(e.clipboardData); // [object Clipboard]
});

2
当我在Safari中运行此代码时,我会得到“未定义” :(
Christoffer Winterkvist,2009年

1
剪贴板数据在大多数浏览器上都
带有

2
仅Internet Explorer!
Lodewijk 2014年

9

监听粘贴事件并设置一个keyup事件监听器。在keyup上,捕获值并删除keyup事件侦听器。

$('.inputTextArea').bind('paste', function (e){
    $(e.target).keyup(getInput);
});
function getInput(e){
    var inputText = $(e.target).val();
    $(e.target).unbind('keyup');
}

6
这非常好,但是不适用于右键单击粘贴。
Joseph Ravenwolfe 2012年

对于单击鼠标中键粘贴(X11)也不起作用,仅当他们使用键盘粘贴时才起作用。
Jasen 2015年


6

这越来越接近您想要的东西。

function sanitize(s) {
  return s.replace(/\bfoo\b/g, "~"); 
};

$(function() {
 $(":text, textarea").bind("input paste", function(e) {
   try {
     clipboardData.setData("text",
       sanitize(clipboardData.getData("text"))
     );
   } catch (e) {
     $(this).val( sanitize( $(this).val() ) );
   }
 });
});

请注意,当未找到剪贴板数据对象时(在IE以外的浏览器上),您当前正在获取元素的完整值+剪贴板的值。

如果您确实只是在将真正的数据真正粘贴到元素之后,可以在输入之前和输入之后执行一些额外的步骤来区分这两个值。



5

如何比较字段的原始值和字段的更改值,然后减去差异作为粘贴值?即使字段中存在现有的文本,这也会正确捕获粘贴的文本。

http://jsfiddle.net/6b7sK/

function text_diff(first, second) {
    var start = 0;
    while (start < first.length && first[start] == second[start]) {
        ++start;
    }
    var end = 0;
    while (first.length - end > start && first[first.length - end - 1] == second[second.length - end - 1]) {
        ++end;
    }
    end = second.length - end;
    return second.substr(start, end - start);
}
$('textarea').bind('paste', function () {
    var self = $(this);
    var orig = self.val();
    setTimeout(function () {
        var pasted = text_diff(orig, $(self).val());
        console.log(pasted);
    });
});

5

此代码对我有用,可以右键单击粘贴或直接复制粘贴

   $('.textbox').on('paste input propertychange', function (e) {
        $(this).val( $(this).val().replace(/[^0-9.]/g, '') );
    })

当我粘贴时,Section 1: Labour Cost它会出现1在文本框中。

为了只允许浮点值,我使用此代码

 //only decimal
    $('.textbox').keypress(function(e) {
        if(e.which == 46 && $(this).val().indexOf('.') != -1) {
            e.preventDefault();
        } 
       if (e.which == 8 || e.which == 46) {
            return true;
       } else if ( e.which < 48 || e.which > 57) {
            e.preventDefault();
      }
    });

4
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/html') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/html'));
        e.preventDefault();

        ...
    }
});

进一步:


text / html无效,只有url和text无效。
迈克(Mike)

@Mike我直接从参考文档中复制了代码段。
davidcondrey

我尝试了大约一天。text / html永远都行不通。我最终添加了一个0延迟的超时,并且能够从他们粘贴所在的div处获取html。也许我只是做错了……
Mike

3

请参见以下示例:http : //www.p2e.dk/diverse/detectPaste.htm

它本质上使用oninput事件跟踪每个更改,然后通过字符串比较检查是否为粘贴。哦,在IE中有一个onpaste事件。所以:

$ (something).bind ("input paste", function (e) {
    // check for paste as in example above and
    // do something
})

因此,仅在事件发生时获取粘贴文本是不可能的吗?
Christoffer Winterkvist,2009年

好吧,我想您将不得不自己处理它,例如,比较前后。它必须相当容易。但是,为什么不重新验证整个输入呢?慢?
伊利亚·伯曼

我只是认为可以这样做,但我想不可能,现在,我正在尝试另一种方法,将其粘贴到文本区域中,然后将其传输到最终目的地。我希望那可以。
Christoffer Winterkvist,2009年

您只需要在两个字符串的开头(之前和之后)中找到最大匹配的片段。从那里直到长度差异的所有内容都是粘贴的文本。
伊利亚·伯曼

@IlyaBirman不,不是:例如,粘贴的文本可能会替换原始文本的一部分(或全部)
Jasen 2015年

1

此方法使用jqueries contents()。unwrap()。

  1. 首先,检测粘贴事件
  2. 向要粘贴的元素中已经存在的标签添加一个唯一的类。
  3. 在给定的超时后,扫描不具有您先前设置的类的所有内容展开标签。注意:此方法不会删除自闭标签,例如
    参见下面的示例。

    //find all children .find('*') and add the class .within .addClass("within") to all tags
    $('#answer_text').find('*').each(function () {
    $(this).addClass("within");
    });
    setTimeout(function() {
    $('#answer_text').find('*').each(function () {
        //if the current child does not have the specified class unwrap its contents
        $(this).not(".within").contents().unwrap();
    });
    }, 0);

绝对是有史以来最好,最短和能说自己话的答案!!!非常感谢,您过
得很愉快

0

事实证明,这是非常虚幻的。在执行粘贴事件函数中的代码之前,不会更新输入的值。我尝试从粘贴事件函数中调用其他事件,但输入值仍未使用任何事件函数中的粘贴文本进行更新。那就是除按键之外的所有事件。如果您从粘贴事件功能中调用keyup,则可以从keyup事件功能中清除粘贴的文本。像这样...

$(':input').live
(
    'input paste',
    function(e)
    {
        $(this).keyup();
    }
);

$(':input').live
(
    'keyup',
    function(e)
    {
        // sanitize pasted text here
    }
);

这里有一个警告。在Firefox中,如果您重置每个键盘上的输入文本,如果文本长于输入宽度所允许的可视区域,则重置每个键盘上的值会破坏浏览器功能,该功能会自动将文本滚动到插入符号的插入位置。文字结尾。取而代之的是,文本会滚动回到开头,从而使插入符号不可见。


在粘贴内容之前将调用onpaste。您需要至少4ms的定时延迟才能创建自己的后粘贴功能,以清洗粘贴的结果。
DragonLord 2012年

-1

使用portlet-form-input-field类从所有字段中删除特殊字符的脚本:

// Remove special chars from input field on paste
jQuery('.portlet-form-input-field').bind('paste', function(e) {
    var textInput = jQuery(this);
    setTimeout(function() {
        textInput.val(replaceSingleEndOfLineCharactersInString(textInput.val()));
    }, 200);
});

function replaceSingleEndOfLineCharactersInString(value) {
    <%
        // deal with end-of-line characters (\n or \r\n) that will affect string length calculation,
        // also remove all non-printable control characters that can cause XML validation errors
    %>
    if (value != "") {
        value = value.replace(/(\x00|\x01|\x02|\x03|\x04|\x05|\x06|\x07|\x08|\x0B|\x0C|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F|\x7F)/gm,'');
        return value = value.replace(/(\r\n|\n|\r)/gm,'##').replace(/(\#\#)/gm,"\r\n");
    }
}

2
您能否添加有关消毒的描述,为什么它可以帮助解决张贴者的问题?仅仅提供一个代码块并不能真正帮助OP(或将来的搜索者)理解如何解决问题,而只是鼓励复制/粘贴被误解的代码。
Troy Alford

-2

这里有一个警告。在Firefox中,如果您重置每个键盘上的输入文本,如果文本长于输入宽度所允许的可视区域,则重置每个键盘上的值会破坏浏览器功能,该功能会自动将文本滚动到插入符号的插入位置。文字结尾。取而代之的是,文本会滚动回到开头,从而使插入符号不可见。

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.