延迟表单提交,ajax和弹出窗口阻止程序



我的网站上有一个简单的注册表单,用户可以在其中输入他们的电子邮件和姓名。

为了避免出现双重注册错误,我进行了一个简单的Ajax调用,查看电子邮件是否已经存在。如果是,我什么都不做,如果不是,我提交表格。

我的问题是表单的目标是_blank,所以延迟提交调用会触发浏览器上的弹出窗口阻止程序。

现在,我知道了为什么会发生这种情况-我不再是可信点击事件中的一员。我将Ajax调用更改为同步调用,但收到一条警告,主线程上的同步Ajax调用已被弃用。

所以我目前的选择似乎是:

  • 无论如何都要使用syncAjax调用,但最终它将停止工作
  • 删除我表单上的目标_blank,使其在同一页面上重定向(糟糕的用户体验)

有没有更好的方法可以绕过弹出窗口阻止程序,将我延迟的表单提交为弹出窗口?

代码:

HTML:

<form action="//external-site.com" method="post" target="_blank" onsubmit="onSubmitSignupForm(event)">
    ...
</form>

JS:

function onSubmitSignupForm( e )
{
    e.preventDefault();
    var request = new XMLHttpRequest();
    request.open( 'POST', 'checkEmail.php', true );
    request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8' );
    request.onload = onLoad;
    request.onerror = onError;
    // NOTE: params = urlencoded params recovered from form
    request.send( params );
}
function onLoad( e )
{
    var request = e.target;
    if( request.status == 200 )
    {
        var data = JSON.parse( request.responseText ); 
        if( data != null && data.success )
        {
            onFinish( request, data );
            return;
        }
    }
    // if we get here, then it means that the request failed, or there was a problem
    onError( e );
}
function onError( e )
{
    var request = e.target;
    var data    = JSON.parse( request.responseText );
    onFinish( request, data );
}
function onFinish( request, data )
{
    var success = ( data != null ) ? data.success : false;
    if( !success )
        $form.submit(); // blocked by popup
}

好吧,所以我有一个解决方案,尽管它可能有点特定于我的情况,而且如果用户已经注册,我会重定向用户,这对我有所帮助。

当表单最初提交时,我基本上会打开一个新的中间页面(这样就可以绕过弹出问题,因为它是在一个受信任的事件中),并在该页面上填充一个隐藏的表单(如果用户愿意,可以使用手动提交的链接)。ajax调用被发送,根据结果,我要么在第2页提交表单,要么在他们已经注册的情况下重定向。

  1. 用户在第1页提交表单
  2. 停止事件,然后打开Page2,它具有相同的形式,尽管是隐藏的
  3. 使用第1页表单中的值填充第2页表单
  4. 在Page2上显示一条消息,说明我们正在处理它,并附上一个手动提交隐藏表单的链接(良好的用户体验)
  5. 在Page1上,激发Ajax请求以查看用户是否已经订阅
  6. 当Ajax结果出来时,可能会发生两件事
  7. (a) 用户未注册-第2页上的表单已提交(可以选择将第1页重定向到内容)
  8. (b) 用户已注册-将Page2重定向到内容

唯一需要注意的是,在填写表单和Ajax结果返回之前,确保Page2已完全加载。为此,我使用了一个带有onload事件的简单布尔系统。

它的代码看起来像这样:

function onSubmitSignupForm( e )
{
    e.preventDefault();
    var $form   = e.target;
    var name = ...; // get name value from form
    var email = ...; // get email value from form
    // open a new window that we'll be able to control and redirect in (otherwise, we'll
    // get stung with a trying to open a popup, as when we get the result, we'll no longer
    // be in the trusted click event)
    var win = window.open( '/signup/', '_blank' );
    win.onload = function() {
        win.setDetails( name, email ); // fill in the hidden form
    }
    // check if the email is already signed up
    // NOTE: result might be null if we couldn't reach the server
    checkEmail( name, email, function onFinish( result ){
        // set the result in the other window
        // NOTE: the window might not have loaded yet
        if( typeof win.setResult == 'undefined' )
        {
            var f       = win.onload; // replace the one we already have
            win.onload  = function(){
                if( f )
                    f();
                win.setResult( result );
            }
        }
        else
            win.setResult( result );
    });
}

setDetailssetResult都将尝试调用第三个函数handleResult,该函数将仅继续由两个函数设置的布尔值为true。

最新更新