JavaScript上下文菜单点击事件/检测 - 过滤粘贴内容

17

场景:我想拦截文本框/输入框内的粘贴事件,并过滤粘贴的内容。

Webkit/IE 处理得相当好,因为我可以将代码附加到 onpaste 事件上,然后从剪贴板读取被粘贴的内容。有很多相关的例子

对于 Gecko 来说,情况比较棘手,因为据我所知,在 Firefox 上无法读取剪贴板内容 (除非有人知道解决方法?)
对于这种情况,我只能使用输入框置换技巧来实现。

但是在 Opera 中会让人感到烦恼。我可以捕获 CTRL+VSHIFT+INS,但没有 onpaste 事件。
更不用说任何剪贴板交互了,似乎都不行。

所以,我的问题是:

我能检测到用户是否在 Opera 的上下文菜单中点击了 粘贴 吗?还有其他检测事件的方法吗?

编辑:

感谢大家的回答-尽管没有确定性的解决方案,但它们都提供了很好的参考。
如果必须选择一个答案,我会选择唯一一个试图回答原始问题并且如果不是太过于 hack ,那么它可能会起作用。

注意事项(有关输入过滤的):

  • 可以捕获拖动的内容:mouseup+setTimeout 在几乎所有情况下都能完美解决。
  • 没有Flash,除了轮询,可能没有其他解决方案。即使使用Flash,它也不是完全可靠的解决方案。支持100%的情况需要付出太多努力。

  • 4
    谢谢你教我如何使用 <kbd> 标签来突出显示键盘操作。+1 - James Wiseman
    在没有“粘贴”事件的浏览器中,无论是否有赏金,答案都是否定的。 - Tim Down
    我见过一些非常聪明的黑客技巧,实现了大多数人认为不可能的事情。以cufon为例,或者其他几十种解决方法,它们实现了我们现在认为理所当然的功能。实现我所要求的功能的一种方法是轮询输入,但这是我宁愿避免的解决方案,因此我提出了这个问题(和悬赏),看看是否有人能想出更好的方法。 - Razor
    我理解你的观点,但Cufon并不真正可与此相比较。针对你所提出的问题,答案仍然是否定的。如果在上下文菜单中用户点击“粘贴”时没有触发任何事件(例如,在Firefox 2中就没有),那么就没有任何东西可以用来检测粘贴操作。你唯一能够依靠的就是轮询输入框的值。 - Tim Down
    5个回答

    9

    去年我遇到过这个问题。简而言之,不行。

    最终我使用了一个onchange处理程序,在文本框中粘贴内容后对其进行过滤。


    1
    没有什么回复比肯定回答更受欢迎了,加1支持正确的翻译。 - Tim Down

    6
    您可以使用jQuery的 bind('paste', function() {}); 拦截粘贴事件,比较粘贴前后的字符串并应用您的格式。以下内容已在IE7/FF3.6/Chrome/Safari 5中测试通过。
    $("#textarea").bind('paste', function(e){ 
        // Do whatever you needed to do with the code here.
    });
    

    实时例子 http://jsfiddle.net/VSrTg/2/

    编辑 一个可行的方法可能是这样的:

    $("#textarea").bind('paste', function(e){ 
        var oldText = this.value;
        setTimeout(function() { 
            // Compare oldText to $("#textarea").val() and format accordingly.
        }, 1000);
    });
    
    编辑2 根据您对原帖的修改,如果您担心 Opera 占据了巨大的市场份额,那么您需要使用setInterval()监测文本框的值,并将其与自身进行比较以检测更改。 最终总会有办法绕过您的脚本,即使上面的示例也容易受到从另一个文本框(或地址栏)中拖动文本而不触发上述paste事件的影响。

    我已经知道gecko/IE/webkit有一个onpaste事件,如果你读了我的问题和链接页面,你会清楚地看到我已经明确说明了。我正在尝试找到一种方法来解决在opera中的这个问题(在那里你的代码根本不起作用)。 - Razor
    在你的帖子中,你说你在使用IE/WebKit时没问题,但在使用Gecko时有问题,这个可以在Gecko上工作。Opera是一个不同的东西,我不相信你可以以任何方式挂钩粘贴事件。你可以使用Firebug并使用console.log(e)来查看在粘贴时转储的内容,但对于Opera来说似乎没有什么有用的东西。 - Robert
    Firefox 2同样没有粘贴事件。 - Tim Down

    3

    我想指出DOJO菜单小部件,可以在不同的浏览器中完美创建上下文菜单。http://www.dojotoolkit.org/reference-guide/dijit/Menu.html#dijit-menu

    你可以检测支持粘贴事件的浏览器,并覆盖不支持此事件的浏览器中的上下文菜单,例如Opera。

    一旦创建了自己的上下文菜单,就可以添加复制粘贴菜单项或使用CSS创建类似于默认菜单的上下文菜单。

    编辑 有些浏览器可能不允许我们获取剪贴板内容,在这种情况下,我们总是可以借用Flash的一些跨浏览器功能。请参见我在评论中发布的几个链接。

    完整的实现可能会比预期更具问题,但这是可能的,我们总是可以尝试一下(我肯定会尝试)。


    不是很有用:浏览器通常不允许JavaScript触发粘贴。用户必须使用内置的浏览器机制(键盘快捷方式、上下文菜单、编辑菜单)显式地执行粘贴。因此,无法从Dojo伪造的上下文菜单触发粘贴。 - Tim Down
    1
    这绝对是可能的,除了从剪贴板获取文本是棘手的部分,但可以查看 http://ericphan.info/blog/2008/12/17/cross-browser-copy-and-paste-with-jquerycopy.html 和 http://code.google.com/p/yii-blogdemo-extended/source/browse/trunk/app/js/jquery.clipboard-2.0.1/jquery.clipboard.js?r=22 - Ayaz Alavi
    我不赞成使用Flash,这也是你提供的两个解决方案所采用的。 - Tim Down
    1
    Flash可以使应用程序更加稳定,具备跨浏览器技术的优势,在这种特殊情况下几乎是必需的。 - Ayaz Alavi

    2
    回答这个问题很简单,没有paste事件的主要浏览器是最近版本的Opera和Firefox 2。鉴于没有paste事件,您需要找到替代事件或一组事件来检测从上下文菜单中实际发生的粘贴。您可以为每个事件添加处理程序(我已经做过了),但在用户通过上下文菜单触发粘贴时,在相关浏览器中根本不会得到任何东西。
    这只留下了定期轮询文本输入的值,这并不是同样的事情。您可以跟踪按键并在轮询代码中观察到文本输入的值已经通过某种方式而不是键盘输入而改变,并进行差异比较,但这是hacky和不可靠的。

    0

    我使用setTimeout来处理粘贴事件。但是对于上面提到的上下文菜单选择,似乎没有任何作用。我将mousemove绑定到输入表单上,以触发更新函数。然后解除绑定/重新绑定,以避免它们堆叠。

    这可以处理上下文菜单选择和将值拖动到输入字段中。

    如果您的表单很小,例如只有一个输入字段,并且鼠标在从上下文菜单中选择后不会停留在其上,请绑定到表单的父级或文档。当然,它必须等待鼠标移动,但这是选择上下文菜单后一般用户的操作。

    运行良好。


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