捕获粘贴输入

219

我正在寻找一种方法来对我在浏览器中粘贴的输入进行消毒处理,使用jQuery能实现吗?

到目前为止,我已经想出了以下内容:

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

很不幸,我的开发因为这个“小”问题而陷入了僵局。如果有人能指点我正确的方向,我会非常高兴。


6
请将 https://dev59.com/-3RB5IYBdhLWcg3wN08P#1503425 标记为解决方案,以帮助其他遇到相同问题的人。这个方法对我很有效。 - saji89
2
.live() 已经在 jQuery 1.9 中被弃用,他们建议使用 .on() 代替。 - Sameer Alibhai
https://dev59.com/RXI95IYBdhLWcg3wvgl9#19269040 - Rajat Gupta
17个回答

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();

        ...
    }
});

更进一步:


文本/HTML无效,只接受URL和文本。 - Mike
@Mike 我直接从参考文档中复制了这个片段。 - davidcondrey
我尝试了一整天,但text/html始终无法正常工作。最终,我添加了一个0延迟的超时,并成功地从他们粘贴内容的div中获取了HTML。如果有人有一个可用的fiddle,那会很有帮助。也许我只是做错了什么... - Mike

4

请参考以下示例: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
好吧,我想你得自己处理它,比如说,比较一下之前和之后的情况。这应该相当容易。但是为什么不重新验证整个输入呢?慢吗? - Ilya Birman
我之前认为这是可能做到的,但现在看来不行。目前我正在尝试另一种方法,通过将其粘贴到文本区域中,然后将其传输到最终目的地。我希望这样能行。 - Christoffer Winterkvist
你只需要在两个字符串的开头找到最大匹配片段。从那里开始一直到长度差就是粘贴的文本。 - Ilya Birman
@IlyaBirman 不是这样的:例如,粘贴的文本可能会替换原始文本的一部分(或全部)。 - Jasen

1

这种方法使用jQuery的contents().unwrap()。

  1. 首先,检测粘贴事件
  2. 为已经存在于我们要粘贴的元素中的标签添加一个唯一的类。
  3. 在给定的超时时间后,扫描所有内容并取消包装不具有之前设置的类的标签。注意:此方法不会删除自闭合标签,如
    请参见下面的示例。

    //查找所有子元素 .find('*') 并将类 .within .addClass("within") 添加到所有标记中
    $('#answer_text').find('*').each(function () {
    $(this).addClass("within");
    });
    setTimeout(function() {
    $('#answer_text').find('*').each(function () {
        //如果当前子元素没有指定的类,则取消其内容的包装
        $(this).not(".within").contents().unwrap();
    });
    }, 0);
    

绝对是我见过的最好、最短和最自我表达的答案!!!非常感谢,你让我的一天变得美好 ;) - webprogrammer

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
能否请您添加一下相关的清洗描述以及为什么它可以帮助解决发帖者的问题?仅仅提供一个代码块并不能真正帮助发帖者(或未来的搜索者)理解如何解决问题——它只会鼓励复制/粘贴误解的代码。 - Troy Alford

0

这证明是相当难以捉摸的。在执行粘贴事件函数内部的代码之前,输入值并未更新。我尝试从粘贴事件函数内调用其他事件,但输入值仍未更新为任何事件函数中粘贴的文本。除了 keyup 事件外,所有事件都是如此。如果您从粘贴事件函数内调用 keyup,则可以在 keyup 事件函数内对粘贴的文本进行消毒。就像这样...

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

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

这里有一个需要注意的地方。在Firefox中,如果您在每个keyup事件中重置输入文本,且文本长度超过了输入框宽度所允许的可视区域,那么在每个keyup事件中重置值会破坏浏览器自动滚动文本到文本末尾插入符位置的功能。相反,文本会滚回到开头,使插入符不可见。

onpaste 在粘贴内容之前被调用。您需要至少 4 毫秒的定时延迟来创建自己的 afterpaste 函数,以清理粘贴的结果。 - DragonLord

-2
这里有一个注意点。在Firefox中,如果您在每次keyup事件中重置输入文本,并且文本长度超过了输入宽度所允许的可视区域,则在每次keyup事件中重置值会破坏浏览器功能,即自动滚动文本到文本末尾的插入符位置。相反,文本会滚动回到开头,将插入符留在视野之外。
function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}

这似乎完全不相关。 - duhaime
这是对James Tindall所给的答案做出的回应。本来应该是评论,但已经过去十年了,所以我认为时效已经过期了。 - lordcheeto

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