Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/413.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何正确捕获并重新触发表单提交事件,保证?_Javascript_Jquery_Forms_Event Handling - Fatal编程技术网

Javascript 如何正确捕获并重新触发表单提交事件,保证?

Javascript 如何正确捕获并重新触发表单提交事件,保证?,javascript,jquery,forms,event-handling,Javascript,Jquery,Forms,Event Handling,这可能不是您通常提出的“如何捕获表单提交事件?”问题 我试图准确地理解jQuery、vanilla Javascript和浏览器(IE/FF/Chrome/Safari/Opera)是如何处理表单提交事件的,以及它们之间的关系。()经过几个小时的谷歌搜索和实验,我仍然无法得出结论,要么是因为不一致,要么是因为含糊不清 我正在完成一个与网站表单集成的脚本,以便在AJAX请求返回之前无法提交表单 理想情况下: 用户填写表格 表单已提交,但除了我的事件处理程序外,没有调用以前绑定的事件处理程序 我的处

这可能不是您通常提出的“如何捕获表单提交事件?”问题

我试图准确地理解jQuery、vanilla Javascript和浏览器(IE/FF/Chrome/Safari/Opera)是如何处理表单提交事件的,以及它们之间的关系。()经过几个小时的谷歌搜索和实验,我仍然无法得出结论,要么是因为不一致,要么是因为含糊不清

我正在完成一个与网站表单集成的脚本,以便在AJAX请求返回之前无法提交表单

理想情况下:

  • 用户填写表格
  • 表单已提交,但除了我的事件处理程序外,没有调用以前绑定的事件处理程序
  • 我的处理程序发出API请求(当然是异步的)
  • 用户确认API响应的验证结果
  • 表单提交继续正常、自动地调用以前被抑制的其他处理程序
  • 我目前的理解是:(这些可能是错误的,如果是,请纠正我)

    • 直接在submit元素
      click
      上的事件处理程序首先执行事件(无论是在标记中,如
      onclick=“”
      ,还是使用jQuery绑定)
    • 接下来执行表单
      submit
      事件上的事件处理程序(无论是在
      onsubmit=”“
      这样的标记中还是使用jQuery绑定)
    • 调用
      $('[type=submit]')。单击()
      不会调用表单的
      submit
      事件,因此不会调用其处理程序
    • 调用
      $('form').submit()
      不会调用submit按钮的
      单击事件,因此不会调用其处理程序
    • 然而,不知何故,用户单击submit按钮最终调用绑定到表单的
      submit
      事件的处理程序。。。(但如上所述,调用“提交”按钮上的“单击”并不起同样的作用)
    • 事实上,用户提交表单的任何方式(通过提交按钮或按Enter键),与jQuery绑定到表单
      submit
      事件的处理程序都被称为
    现在,我是:

  • 将与jQuery绑定的处理程序解除绑定到submit按钮的
    click
    事件,同时保留对它们的引用
  • 将我自己的处理程序绑定到submit按钮的
    click
    事件,因此它首先执行
  • 使用
    onclick=“”
    onsubmit=“”
    (在它们各自的元素上)在标记中绑定任何处理程序,并使用jQuery重新绑定它们(因此它们在我之后执行),然后将属性设置为
    null
  • 重新绑定它们的处理程序(从步骤1开始),以便它们最后执行
  • 实际上,这在我自己的测试中非常有效,因此我的事件处理程序首先启动(基本)

    问题和我的问题:

    我的处理程序首先开火,正如预期的那样(到目前为止)。问题是我的处理程序是异步的,所以我必须抑制(prevendefault/stopPropagation/etc)表单
    submit
    或submit按钮
    单击调用它的事件。。。直到API请求完成。然后,当API请求返回时,一切正常,我需要重新调用表单submit自动提交。但是由于我上面的观察,我如何确保所有的事件处理程序都像自然表单一样被触发呢

    获取所有事件处理程序、首先放置我的事件处理程序、然后重新调用表单submit以便按正确顺序调用所有事件处理程序的最干净方法是什么

    如果有的话,
    $('form').submit()和
    $('form')[0].submit()之间有什么区别?(对于
    $('[type=submit]')也是如此。单击()
    $('[type=submit]')[0]。单击()

    tl;dr,关于Javascript/jQuery/browser表单提交事件处理的规范、清晰、一刀切的文档是什么?(我不是在寻找书籍推荐。)



    一些解释:我试图弥补购物车结帐页面中的大量Javascript,有时候只有当用户单击页面底部的按钮(而不是提交按钮)时才提交表单,或者存在其他棘手的场景。到目前为止,它相当成功,只是重新调用了提交,这才是真正的问题。

    使用jQuery绑定表单的提交处理程序并阻止默认操作,然后,当您想要提交表单时,直接在表单节点上触发它

    $("#formid").submit(function(e){
        // prevent submit
        e.preventDefault();
    
        // validate and do whatever else
    
    
        // ...
    
    
        // Now when you want to submit the form and bypass the jQuery-bound event, use 
        $("#formid")[0].submit();
        // or this.submit(); if `this` is the form node.
    
    });
    

    通过调用表单节点的
    submit
    方法,浏览器在不触发jQuery的提交处理程序的情况下进行表单提交。

    这两个函数可能会帮助您在jQuery队列的前端绑定事件处理程序。您仍然需要剥离内联事件处理程序(
    onclick
    onsubmit
    ),并使用jQuery重新绑定它们

    // prepends an event handler to the callback queue
    $.fn.bindBefore = function(type, fn) {
    
        type = type.split(/\s+/);
    
        this.each(function() {
            var len = type.length;
            while( len-- ) {
                $(this).bind(type[len], fn);
    
                var evt = $.data(this, 'events')[type[len]];
                evt.splice(0, 0, evt.pop());
            }
        });
    };
    
    // prepends an event handler to the callback queue
    // self-destructs after it's called the first time (see jQuery's .one())
    $.fn.oneBefore = function(type, fn) {
    
        type = type.split(/\s+/);
    
        this.each(function() {
            var len = type.length;
            while( len-- ) {
                $(this).one(type[len], fn);
    
                var evt = $.data(this, 'events')[type[len]];
                evt.splice(0, 0, evt.pop());
            }
        });
    };
    
    绑定执行ajax调用的提交处理程序:

    $form.bindBefore('submit', function(event) {
        if (!$form.hasClass('allow-submit')) {
            event.preventDefault();
            event.stopPropagation();
            event.stopImmediatePropagation();
    
            // perform your ajax call to validate/whatever
            var deferred = $.ajax(...);
            deferred.done(function() {
                $form.addClass('allow-submit');
            });
    
            return false;
        } else {
            // the submit event will proceed normally
        }
    });
    
    绑定一个单独的处理程序以阻止
    [type=“submit”]
    上的单击事件,直到准备就绪:

    $form.find('[type="submit"]').bindBefore('click', function(event) {
        if (!$form.hasClass('allow-submit')) {
            // block all handlers in this queue
            event.preventDefault();
            event.stopPropagation();
            event.stopImmediatePropagation();
            return false;
        } else {
            // the click event will proceed normally
        }
    });
    

    必须有很多方法来解决这个问题——这里有一个

    它将ajax函数(A)与所有其他函数(B、C、D等)分开,只将A放在标准的“提交”队列中,将B、C、D等放在自定义事件队列中。这避免了使B、C、D等依赖于A的异步响应所必需的复杂的诡计

    $(function(){
        var formSubmitQueue = 'formSubmitQueue';
    
        //Here's a worker function that performs the ajax.
        //It's coded like this to reduce bulk in the main supervisor Handler A.
        //Make sure to return the jqXHR object that's returned by $.ajax().
        function myAjaxHandler() {
            return $.ajax({
                //various ajax options here
                success: function(data, textStatus, jqXHR) {
                    //do whatever is necessary with the response here
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    //do whatever is necessary on ajax error here
                }
            });
        }
    
        //Now build a queue of other functions to be executed on ajax success.
        //These are just dummy functions involving a confirm(), which allows us to reject the master deferred passed into these handlers as a formal variable.
        $("#myForm").on(formSubmitQueue, function(e, def) {
            if(def.state() !== 'rejected') {
                if (!confirm('Handler B')) {
                    def.reject();
                }
            }
        }).on(formSubmitQueue, function(e, def) {
            if(def.state() !== 'rejected') {
                if (!confirm('Handler C')) {
                    def.reject();
                }
            }
        }).on(formSubmitQueue, function(e, def) {
            if(def.state() !== 'rejected') {
                if (!confirm('Handler D')) {
                    def.reject();
                }
            }
        });
    
        $("#myForm").on('submit', function(e) {
            var $form = $(this);
            e.preventDefault();
            alert('Handler A');
            myAjaxHandler().done(function() {
                //alert('ajax success');
                var def = $.Deferred().done(function() {
                    $form.get(0).submit();
                }).fail(function() {
                    alert('A handler in the custom queue suppressed form submission');
                });
                //add extra custom handler to resolve the Deferred.
                $form.off(formSubmitQueue+'.last').on(formSubmitQueue+'.last', function(e, def) {
                    def.resolve();
                });
                $form.trigger(formSubmitQueue, def);
            }).fail(function() {
                //alert('ajax failed');
            });
        });
    });
    
    (使用模拟ajax)

    作为额外的奖励,可以使自定义队列中的任何处理程序抑制任何/所有后续处理程序,和/或抑制表单提交。只需根据需要选择合适的模式:

    模式1: 仅当前面的所有处理程序未拒绝def时才执行其操作。并且可以抑制模式1和模式2的所有后续处理程序

    $("#myForm").on(formSubmitQueue, function(e, def) {
        if(def.state() !== 'rejected') {
            //actions as required here
            if (expression) {
                def.reject();
            }
        }
    });
    
    $("#myForm").on(formSubmitQueue, function(e, def) {
        //actions as required here
        if (expression) {
            def.reject();
        }
    });
    
    模式2: 仅当前面的所有处理程序未拒绝def时才执行其操作。但这并不是一个好主意
    $("#myForm").on(formSubmitQueue, function(e, def) {
        //actions as required here
        if (expression) {
            def.reject();
        }
    });
    
    $("#myForm").on(formSubmitQueue, function(e, def) {
        //actions as required here
    });
    
    var oldHandlers, eventsRef = $._data(this, 'events');
    
    // If there are previously-bound-event-handlers (from jQuery), get those.
    if (eventsRef && eventsRef.click && eventsRef.click.length > 0)
    {
        // Get a reference to the old handlers previously bound by jQuery
        oldHandlers = $.extend(true, [], eventsRef.click);
    }
    
    // Unbind them...
    $(this).unbind('click');
    
    // ... then bind ours first ...
    $(this).click({ form: f, invoke: this }, submitHandler);
    
    // ... then bind theirs last:
    // First bind their onclick="..." handles...
    if (typeof this.onclick === 'function')
    {
        var temp = this.onclick;
        this.onclick = null;
        $(this).click(temp);
    }
    
    // ... then finish up with their old jQuery handles.
    if (oldHandlers)
        for (var j = 0; j < oldHandlers.length; j++)
            $(this).click(oldHandlers[j].data, oldHandlers[j].handler);