【问题标题】:How to stop a form from submitting until an animation is complete如何在动画完成之前停止提交表单
【发布时间】:2014-11-15 08:16:07
【问题描述】:

我试图在用户单击提交按钮之后和提交之前在表单上运行动画。我确实在 stackoverflow 和其他网站上找到了解决方案,但它们要么导致表单在动画运行之前提交,要么动画会运行但表单不会提交。这只是为了我姐姐的婚礼网站,所以我的工作不会受到威胁,但让她的网站与众不同会很好。

请注意,开发者控制台不会返回任何错误。

这是我们开始使用的代码:Executing a form after animation is done JQuery。这是一个公认的答案,所以我假设它对某人有用,但我不明白当没有任何事件将事件传递给它时,preventDefault 函数应该如何工作。我也试过这个:Run an animation before I submit a form (and make sure it completes)

基本上,动画是一个滑入信封的信,信封折叠然后滑出屏幕。

这是表格。

<form method="post" action="index.php">
    <label>names</label>
    <input type="text" name="names" id="nameInput" placeholder="type here" />
    <label>food allergies</label>
    <input type="text" name="allergies" placeholder="type here" />
    <input type="submit" name="send" value="Send Email">
</form>

这里是 jQuery。 使用@Roamer-1888 的代码更新

var windowWidth = $(window).width();

var imgPosition = ($('.mobile_background').width() - windowWidth) / 2;
var centreTriangle = (windowWidth / 2) - 35;

function sendMail(e) {
    e.preventDefault();
    var form = e.target;

    var setTop = function () {
        return $('.letter').animate({top: 2}, 1000).promise();
    }
    var openEnvelope = function () {
        return $('.envelope_fold.top_up').slideUp().promise();
    }
    var insertContents = function () {
        return $('input').css('display', 'none');
        // you probably need also to do something here to prevent the inputs from showing again when the envelope is animated off screen. eg append the inputs to the envelope element. 
    }
    var closeEnvelope = function () {
        return        $('.envelope_fold.shaddow').add('.envelope_fold.top_down').slideDown(300).promise();
    }
    var sealEnvelope = function () {
        return $('#seal').css('display', 'block');
    }
    var exitStageRight = function () {
        return $('#envelope').animate({left: 3000}).promise();
    }
    var send = function () {
        form.submit();
    }

    if ($('#nameInput').val() == "") {
        alert('Please tell us your name');
    } else {
        $.when() //resolved promise to get the chain started
            .then(setTop)
            .then(openEnvelope)
            .then(insertContents)
            .then(closeEnvelope)
            .then(sealEnvelope)
            .then(exitStageRight)
            .then(send);
    }
}


function showMenu() {
    $('.navButton').css({
        right: '111px'
    });
    $('#menu').css({
        left: 0
    }, 300);
}

function hideMenu() {
    $('.navButton').css({
        right: '10px'
    }); 
    $('#menu').css({
        left: '100%'
    }, 300);
}

$(document).ready(function(){
    // styles
    $('#intro').css({
        'height': $(window).height()
    });

    $('.mobile_background').css({
        'right': -imgPosition
    });

    $('.triangle').css({
        'margin-left': centreTriangle
    });

    // countdown clock
    $('#count').countdown('2015/01/17 13:30:00', function(event) {
       $(this).html(event.strftime('<h3>%D<span>d</span> %H<span>h</span> %M<span>m</span</h3>'));
    });

    // form submit verification removal
    $('.success a').click(function(){
        $(this).parent().remove();
    });

    // Navigation
    $('.navButton').on('click', function(){
        showMenu();
    });

    $('body > div, #menu a').on('click', hideMenu);


    if (windowWidth > 1025) {
        $('nav').mouseenter(function(){
            showMenu();
        });
        $('nav').mouseleave(function(){
            hideMenu();
        });     
    }

    if (windowWidth <= 400) {
        $('.navButton').on('click', function(){
            showMenu();
            $('body > div').css({
                right: '101px'
            });
        });

        $('body > div + div, #menu a').on('click', function(){
            hideMenu();
            $('body > div').css({
                right: 0
            });
        });
    }

    // fire form animation
    $("form:eq(0)").on('submit', sendMail);
});

此外,我希望动画的第一步是让输入位于信封前面的后面,但它会阻止在此之后运行的所有函数工作。我必须首先将它们放在信封前,否则用户将无法输入文本。所以如果有人能弄清楚那也很棒。

滚动到本站底部查看表格:http://celinaanddavid.ca

感谢您的帮助。

【问题讨论】:

  • 您的网站出现 JavaScript 错误,当您点击发送按钮时,请尝试在表单上下文之外运行该函数(例如 onload)以进行调试。
  • 有了 submit 事件处理程序注释,您的下一行代码显然现在无效(因为不再为 e.preventDefault(); 定义 e)!最好先解决这个问题。
  • z-index 仅适用于定位元素。如果输入元素或信封未定位,则 z-index 将无效。
  • 好的,我已经进行了这些更改。动画现在正在运行,但表单仍然在动画之前提交。

标签: jquery forms animation submit preventdefault


【解决方案1】:

对于像这样的串行动画,您可以通过利用 jQuery 的承诺并编写一个友好的.then() 链来避免可怕的“末日金字塔”(深层嵌套回调)。

为了使代码更具可读性,将每个动画步骤编写为命名函数也是一个好主意。

你最终会得到这样的结果:

function sendMail(e) {
    e.preventDefault();
    var form = e.target;

    var setTop = function () {
        return $('.letter').animate({top: 2}, 1000).promise();
    }
    var openEnvelope = function () {
        return $('.envelope_fold.top_up').slideUp().promise();
    }
    var insertContents = function () {
        return $(form).find('input').css('z-index', 0);
        // you probably need also to do something here to prevent the inputs from showing again when the envelope is animated off screen. eg append the inputs to the envelope element. 
    }
    var closeEnvelope = function () {
        return $('.envelope_fold.shaddow').add('.envelope_fold.top_down').slideDown(300).promise();
    }
    var sealEnvelope = function () {
        return $('#seal').css('display', 'block');
    }
    var exitStageRight = function () {
        return $('#envelope').animate({left: 3000}).promise();
    }
    var send = function () {
        form.submit();
    }

    if ($('#nameInput').val() == "") {
        alert('Please tell us your name');
    } else {
        $.when() //resolved promise to get the chain started
            .then(setTop)
            .then(openEnvelope)
            .then(insertContents)
            .then(closeEnvelope)
            .then(sealEnvelope)
            .then(exitStageRight)
            .then(send);
    }
}

现在您需要做的就是附加sendMail 作为表单的 sumbit 处理程序,例如:

$("form:eq(0)").on('submit', sendMail);

【讨论】:

  • 感谢@Roamer-1888,该代码更好。不幸的是,它不起作用。单击提交按钮后,动画将执行,但表单未提交。它返回错误:TypeError: undefined is not an object (evalating 'e.preventDefault') TypeError: HTMLInputElement is not a function (evalating 'form.submit()')
  • 你是否像我说的那样附加sendMail() - 和$("form:eq(0)").on('submit', sendMail);
  • @EliseChant,我发现这种方法在语法上比自定义动画队列更清晰,自定义动画队列需要反直觉的 .dequeue() 来保持它的运行。如果需要,可以通过使用setTimeout() 编写自己的function delay(x){...} 来模拟.delay(),尽管您需要使用略显尴尬的语法.delay.bind(null,x) 进行调用。我确信自定义动画队列还有其他优势,但我想不出它们现在会是什么。
  • 有趣的开发 我做了最疯狂的事情,并用谷歌搜索“HTMLInputElement 不是函数错误”,发现这是我提交输入的结果,名称为“提交”。我删除了名称,然后动画和表单动作起作用了!唯一的问题是输入值没有通过表单提交传递,所以它基本上只是刷新了页面。但干得好@Roamer-1888。我会投票赞成你的答案,但我的名声不够。
  • 我只是在发送电子邮件后将验证文件重定向回索引文件并传递一个变量来确定表单是否已提交。奇迹般有效。再次感谢@Roamer-1888。
猜你喜欢
  • 1970-01-01
  • 2014-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
相关资源
最近更新 更多