触发器在异步ajax done()上单击input = file

时间:2015-04-19 10:39:00

标签: jquery

我有一个包含一些数据并上传的表单。只有在成功接收和处理数据后才能启动上载。为此,我在

中进行ajax调用
  1. 发送数据,
  2. 检查结果,
  3. 触发click()打开文件对话框。
  4. click()的最后一件事不起作用,因为似乎异步调用阻止打开上传窗口。它仅在我设置async: false时才有效。

    我在文档和本网站中找不到任何内容,想知道那里有什么问题以及如何让它保持调用异步?

    示例:

    $.ajax({
        type: "POST",
        url: "/Save",
        data: jsonText,
        dataType: "json",
        //async: false            [1]
    }).done(function (msg) {    
        $("#upload").click();   
    });
    
    //$("#upload").click();       [2]
    

    演示:http://jsfiddle.net/c2v00uxn/

    注意:

    • 如果我取消注释[1]或[2],它确实有效(文件对话框按预期显示)。
    • 用触发器替换click()('click')不起作用
    • 用live()/ on()替换click()无效
    • 文件上传控件按示例显示(因此不是因为隐藏控件)
    • ajax的超时设置无济于事。

    更新

    这不是关于如何一般地进行“点击”,而是关于如何在异步ajax调用之后单击(截至目前,仅适用于非异步调用)。

3 个答案:

答案 0 :(得分:32)

由于w3c推荐的浏览器安全功能,现在无法从异步ajax回调打开文件弹出窗口。

在文件输入元素的激活行为中,它首先检查算法是否允许显示弹出窗口,如果没有,则在不执行任何其他操作的情况下中止后续步骤。来自w3c.org

如果满足以下任一条件,则允许算法显示弹出窗口:

  1. 正在运行算法的任务正在处理中 单击事件受信任的激活行为。(受信任事件:由用户代理生成的事件,作为用户交互的结果,或作为DOM更改的直接结果,是受信任的事件)由用户代理提供的权限不是由脚本通过DocumentEvent.createEvent("Event")方法生成的事件,使用Event.initEvent()方法修改的,或通过EventTarget.dispatchEvent()方法调度的。特权信任的isTrusted属性events的值为true,而不受信任的事件的isTrusted属性值为false。 除此以外。 http://www.w3.org/TR/2012/WD-DOM-Level-3-Events-20120614/#trusted-events。)
  2. 运行算法的任务当前正在运行 受信任事件的事件侦听器,其类型如下所示 列表:

    • 变化
    • 点击
    • DBLCLICK
    • 鼠标松开
    • 重置
    • 提交
  3. 算法运行的任务由一个队列排队 允许显示弹出窗口的算法,以及此类链 算法在用户代理定义的时间范围
  4. 内启动

    w3c.org

    在您的代码中,click事件不是由用户触发,而是由ajax完成回调触发。这里浏览器声明无法信任该事件以打开弹出窗口。在某些浏览器中,如果事件被声明为可信,则可以看到isTrusted属性设置为true。https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted

    注意

    不同的浏览器使用不同的方法捕获脚本激活的cick和真实用户之间的差异。

    在这种情况下,您可以执行的操作是禁用文件输入按钮(或整个表单),并在完成ajax后启用。这样,在ajax请求完成之前,用户不会单击上传按钮。截至目前,没有其他方法可以在一次点击中同时执行这两种操作,因为打开弹出窗口也有时间限制。当我签入chrome时,时间范围是1000ms。用户操作后1000ms,窗口将不会打开。

答案 1 :(得分:0)

JQuery本身说,触发器不适用于文件上传和锚点等元素。 (来源 - https://learn.jquery.com/events/triggering-event-handlers/

  

.trigger()函数不能用于模仿本机浏览器事件,   例如单击文件输入框或锚标记。这是   因为,没有使用jQuery事件附加事件处理程序   与这些事件相对应的系统。

因此,在这种情况下,您可能需要使用以下javascript函数手动创建事件。

  • document.createEvent
  • event.initMouseEvent
  • element.dispatchEvent

上述功能的示例代码+定义可以在Mozilla的开发者网站找到

https://developer.mozilla.org/samples/domref/dispatchEvent.html

也许,这会对你有帮助。

答案 2 :(得分:0)

我有一个现在有效的解决方案。这是一个黑客,所以它可能在不久的将来不起作用,因为它规避了上面Tkay提到的安全功能。

我引入了一个超时,等待ajax请求在启动文件浏览器对话框之前返回我想要检查的数据。

customFileUploadButton.addEventListener('click', function(e) {

    var returnValueToCheck; //Value we want to check against

    //reference to vanilla JS ajax function that takes callback
    ajax(function(ajaxData) { 
        returnValueToCheck = ajaxData;
    });

    setTimeout(function() {
        if (returnValueToCheck !== undefined) { //dummy check for example
            file.click();
        } else {
           console.log("Criteria not fulfilled");
        }
    }, 1000);//timer should be larger than AJAX timeout
});

说实话,我有点不确定为什么这项工作除了显然通过浏览器特定的测试通常禁止这种行为。因此我认为它是一个黑客。

我的例子是vanilla JS,但创建一个jQuery版本应该很容易。有关完整示例,请参阅此JSFiddle

(这是我第一次参与投稿,所以请评论潜在的错误和疏忽)