jquery - Woocommerce:有什么方法可以绕过和替换结帐表单验证吗?

标签 jquery wordpress validation woocommerce authorize.net

默认情况下,Woocommerce 会在结帐页面上的字段模糊后立即对其进行验证。因此,如果有人错误地单击进入某个字段,然后单击退出,则即使尚未提交任何内容,该字段也会显示为“无效”。我们发现这种情况对用户来说很烦人,而且可能会给用户带来压力。

我们想要做的是更改验证,以便仅在单击“下订单”按钮(或通常提交表单)时才会启动。但是,我们不能完全删除 checkout.min.js,因为我们可能希望保留与字段验证无关的其他脚本。

我尝试过这种 hacky 方法来删​​除默认验证: jQuery(document.body).on('init_checkout', 函数 (事件) { 设置超时(函数(){ jQuery('.validate-required').removeClass('validate-required woocommerce-invalid woocommerce-invalid-required-field'); }, 1000); });

虽然这可以防止字段在模糊时变成红色,但页面仍然滚动到顶部并在单击“下订单”时显示错误,因此必须有其他内容进行验证。不过,顶部的错误仅涉及信用卡字段...我们正在使用 Woocommerce Authorize.NET AIM 插件,因此可能与此有关。

有人做过类似的事情并且运气好吗?

最佳答案

好吧,我想出了一个很好的方法来做到这一点,以供将来引用。

首先,将 checkout.js 从 WooCommerce javascript 文件夹复制到主题的 js 文件夹。

然后将其添加到主题的 functions.php 中,取消注册默认脚本并将其替换为您的自定义版本:

add_action( 'wp_enqueue_scripts', 'kg_replace_wc_scripts', 99 );
function kg_replace_wc_scripts(){
    if( is_checkout() ){
        $path = get_template_directory_uri() . '/js/checkout.js';
        $time = filemtime($path);
        wp_deregister_script('wc-checkout');
        wp_register_script('wc-checkout', $path, 
        array( 'jquery', 'woocommerce', 'wc-country-select', 'wc-address-i18n' ), $time, TRUE);
        wp_enqueue_script('wc-checkout');
    }
}

(可以选择使用 WC 版本作为版本字符串,但我喜欢使用 filemtime,因此每次修改文件时,它都会在实时站点上更新,而无需清除缓存)

然后在新的 checkout.js 中,注释掉或删除此行(此版本中的第 35 行):

this.$checkout_form.on( 'input blur change', '.input-text, select, input:checkbox', this.validate_field );

这将为用户提供休息时间,并防止字段在填写完毕之前进行验证。

现在您需要向 wc_checkout_form 添加一个新函数来一次处理所有字段的验证,这是我的:

validate_all_fields: function() {
            var any_invalid = false;
            var ship_to_diff = $('#ship-to-different-address input').is(':checked');

            $('.kg-invalid-msg').fadeOut(500, function() {
                $(this).remove();
            });

            $('.woocommerce-invalid').removeClass('woocommerce-invalid woocommerce-invalid-required-field');

            $('.validate-required').each(function() {
                var $this             = $(this).find('input[type=checkbox],select,.input-text'),
                    $parent           = $this.closest( '.form-row' ),
                    validated         = true,
                    validate_required = $parent.is( '.validate-required' ),
                    validate_email    = $parent.is( '.validate-email' );

                if (!ship_to_diff && $this.parents('.woocommerce-shipping-fields').length) {
                    return true;
                }

                if ( validate_required ) {
                    if ( 'checkbox' === $this.attr( 'type' ) && ! $this.is( ':checked' ) ) {
                        $parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-required-field' );
                        validated = false;
                        any_invalid = true;
                    } else if ( $this.val() === '' ) {
                        $parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-required-field' );
                        validated = false;
                        any_invalid = true;
                    }
                }

                if ( validate_email ) {
                    if ( $this.val() ) {
                        /* https://stackoverflow.com/questions/2855865/jquery-validate-e-mail-address-regex */
                        var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);

                        if ( ! pattern.test( $this.val()  ) ) {
                            $parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-email' );
                            validated = false;
                            any_invalid = true;
                        }
                    }
                }

                if ( validated ) {
                    $parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email' ).addClass( 'woocommerce-validated' );
                }
            });

            if (any_invalid) {
                // Scroll to first invalid input
                var $first_invalid = $('.woocommerce-invalid:first');

                var $msg = $('<div class="kg-invalid-msg">Please check your info</div>').appendTo($first_invalid);
                $('html,body').animate({
                    scrollTop: $first_invalid.offset().top - 70
                }, 1000);

                $first_invalid.find('input,select').on('input change', function() {
                    $msg.fadeOut(500, function() {
                        $msg.remove();
                    });
                });

                $('.woocommerce-invalid').find('input,select').on('input change', function() {
                    $(this).closest('.form-row').removeClass('woocommerce-invalid woocommerce-invalid-required-field');
                });
            }
        }

当表单验证失败时,这将滚动到第一个无效输入(而不是一直滚动到顶部),并向第一个无效输入添加注释,同时将所有无效输入着色为红色。您可以很容易地对其进行修改,使其按照您想要的方式工作。

最后,您只需将此行添加到 wc_checkout_formsubmit 函数中即可在提交时触发此函数:

wc_checkout_form.validate_all_fields();

现在,结帐字段将让您保持安静,直到您点击“下订单”,之后验证才会开始。

关于jquery - Woocommerce:有什么方法可以绕过和替换结帐表单验证吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46852660/

相关文章:

javascript - KnockoutJS - 使用内部函数更新对象

php - WordPress、重定向和 WPML

javascript - 将 Angular 验证指令与 Breeze 一起使用会阻止任何无效输入

ios - 在 iOS 中用于密码验证的 UITextfield 输入中的密码验证

javascript - 如何通过元素宽度替换 URL 参数

javascript - 将数组元素值放入 span jquery

javascript - jquery 工具提示抛出错误 : function not defined

php - 使用 PHP 运行 WP-CLI

php - 为什么我不能在使用 WordPress 的 if 语句中使用 the_time() 函数?

javascript - 我想知道如何在 javascript 中进行表单验证