【问题标题】:Javascript Intercepted "Ctrl+O" Does Not Open My File DialogJavascript 拦截“Ctrl+O”不打开我的文件对话框
【发布时间】:2015-09-11 00:18:39
【问题描述】:

我的 HTML 中有一个 <input type="file" id="browse-button"/> 文件浏览器输入。

我还有另一个 ID 为 choose-file-button 的按钮,单击该按钮时会调用 document.getElementById("browse-button").click();。单击此按钮时,它会正确单击#browse-button 并打开文件对话框。

现在,我从this answer 获取代码来拦截Ctrl+O 按键并打开我的文件对话框,所以我有这个:

$(window).bind('keydown', function(e)
{
    if (e.ctrlKey || e.metaKey)
    {
        switch (String.fromCharCode(e.which).toLowerCase())
        {
            case 's':
                e.preventDefault();
                // doesn't matter for this question
                return false;
            case 'o':
                e.preventDefault();
                document.getElementById("choose-file-button").click();
                return false;
        }
    }
    return true;
});

如您所见,当我拦截 Ctrl+O 时,我单击了 #choose-file-button 按钮,该按钮在其 onclick 处理程序中调用 document.getElementById("browse-button");。我在这个点击处理程序中放了一个断点,当我按下Ctrl+O 时,它确实到达了这个断点。但是,文件对话框永远不会出现。

通过调试,我发现如果我在#choose-file-button click() 行后面加上一个alert(...);,那么警报就会出现并且会出现正常的页面“打开文件”对话框(不是我的文件对话框)。但是,如果我没有此警报,则根本不会显示任何内容。

这是一个错误吗?如何修复它并通过截获的Ctrl+O 显示我的文件对话框?

编辑:我刚刚在 Chrome 中进行了测试,它运行良好。但是,它仍然无法在 Firefox 中运行。

【问题讨论】:

  • 您是否尝试过使用 JQuery 通过 $("#choose-file-button").click() 而不是使用 getElementById 来触发您的点击?
  • @Osuwariboy 我现在有了,但它并没有改变任何东西。
  • 您的问题似乎与此类似:override ctrl+s。也许你可以试试他们的一些建议?
  • @Osuwariboy 当然可以,但我根本不想要任何警报,即使是延迟警报。
  • 你的大写锁定了吗?

标签: javascript jquery html dialog


【解决方案1】:

这里有一些浏览器安全魔法。当使用超时或间隔或我尝试的任何其他方法时,代码照常进行,但浏览器只是拒绝打开文件上传对话框。这可能是故意的,以阻止恶意 JS 在未经同意的情况下尝试抓取用户的文件。但是,如果您绑定到链接上的单击事件,则可以使用 jQuery 或常规 JS 完美运行。

编辑:正如怀疑的那样,大多数浏览器会根据事件的类型以及它是由用户创建还是以编程方式生成来跟踪事件是否可信。请参阅this answer 了解详细信息。如您所见,由于键盘事件不在列表中,因此它们永远不能被信任。

Test JSFiddle

<form action="#" method="post">
    <div>
        <input type="file" id="myfile" name="myfile" /> <a href="#" id="mylink" accesskey="o">Click me</a>
    </div>
</form>

$("#mylink").click(function () {
    $("#myfile").click();
});

$(window).bind('keydown', function (e) {
    if (e.ctrlKey || e.metaKey) {
        switch (String.fromCharCode(e.which).toLowerCase()) {
            case 'o':
                e.preventDefault();
                console.log("1a");

                $("#myfile").click();
                //alert("hello");

                console.log("1b");
                return false;
        }
    }
    return true;
});

我认为这里只有两个选项,它们都是变通方法,而不是解决方案。

  • 一种是使用链接触发文件上传对话框,并要求人们使用 ALT+SHIFT+O 而不是 CTRL+O(因为我在示例中的链接中添加了accesskey attribute)。
  • 另一种选择是为drag-drop file uploading 使用新的HTML5 JavaScript API 之一。

附录:我还尝试在 Firefox 中使用纯 JavaScript 来获取点击事件,并使用 isTrusted 属性检查它是否受信任。对于链接的点击,它返回true。但是,尝试在其他地方存储和重用该事件是行不通的,因为在您获得对它的引用时它已经被分派了。此外,毫不奇怪,创建一个新事件并尝试设置 isTrusted = true 也不起作用,因为它是只读的。

【讨论】:

  • @guest271314 不错的链接!我非常怀疑浏览器可以区分真正的点击和程序化点击。
  • @BoffinbraiN 感谢您的详细回复,很抱歉我没有早点来这里提问/给出答案/投票...我不在城里。无论如何,我可能会检查 HTML5 API,但如果它看起来太难使用,我会坚持不使用文件 IO 的键盘快捷键(因为网页上仍有按钮可以正常工作)。
【解决方案2】:

浏览器将许多 Ctrl+ 快捷键映射到自己的命令,例如 CTRL+O 打开文件(在 firefox 中)。

同时,当您尝试在 javascript 中覆盖此类快捷方式时,浏览器的行为会有所不同。有些浏览器允许您这样做,有些则不允许,有时默认浏览器操作可能会与您的 javascript 操作一起弹出。

这是另一个讨论这个topic的线程。

你能做的最好的可能就是选择一个不同的快捷方式。

【讨论】:

    【解决方案3】:

    您可以尝试使用 Mousetrap 库。它覆盖了关键捕获带来的大多数问题。 官网及完整参考:

    https://craig.is/killing/mice

    祝你好运

    【讨论】:

    • 在这里澄清一下,OP想要覆盖组合键Ctrl+O,而不是设置点击事件,实现起来很简单。
    • Mousetrap 库不是设置点击事件,是为了对面,是为了避免鼠标使用,都是带键盘的。
    • 啊哈……我明白了。一个不错的实用程序,但由于我的回答中提到的问题,没有 JS 库可以绕过浏览器的安全预防措施。我用 Fiddle here 试了一下。
    【解决方案4】:

    您不能在所有浏览器中都这样做,就我而言,只有 IE 允许这样做。我猜这是由于安全问题,因此程序员无法自动在 HTML File 元素上设置文件名(未经客户端许可)。

    查看此链接了解更多详情:

    In JavaScript can I make a "click" event fire programmatically for a file input element?

    Show input file dialog on load?

    【讨论】:

      猜你喜欢
      • 2014-07-07
      • 2012-01-28
      • 2013-11-11
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多