0

我修改了 Magento 处理类别的方式,允许用户通过将添加到购物车 url 的 ajax 请求链接在一起,从类别页面一次添加多个可配置产品。

基本上,用户选择他们想要添加的项目的复选框,这使<li>产品处于“活动”类中。这个 jQuery 抓取每<li>一个有一个活动的类,然后从变量 theLink 中的选定下拉列表中抓取“添加到购物车 URL”。

$j('li.active').each(function(){
            var theLink = $j(this).find('.shopthislookpageselect').val();
            var successString = "was added to your shopping cart."
            $j.ajax({
                beforeSend: function(){$j('#modalBackground').show();},
                type:"POST",
                url: theLink,
                success: function(data){
                    var returnPage = data;
                    var exists = (returnPage.indexOf(successString) !== -1);
                    if (exists) {$j('.col-main').prepend('<ul class="messages"><li class="success-msg"><ul><li><span>The items selected were added to your shopping cart. View your cart <a href="https://www.culturekings.com.au/checkout/cart/">HERE</a></span></li></ul></li></ul>'); $j("html, body").animate({ scrollTop: 0 }, "slow"); }
                    else {alert ('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.')}
                    },
                error: function(){alert('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.');},
                complete: function(){$j('#modalBackground').fadeOut(200);}
            });
});

divmodalBackground是一个透明的全宽和全高覆盖,它有一个加载 gif,它应该在每个 ajax 调用开始时显示,并在结束时隐藏。

问题是 modalBackground 在第一个 ajax 调用开始时显示并在结束时隐藏,但之后的任何其他调用都不会再次显示。我可以看到这个函数仍在运行,因为我可以计算每次成功调用成功函数结束时显示的成功消息。

beforeSend 只触发一次吗?如果是,为什么?或者我应该对叠加层进行不同的处理。

请注意,如果不更改 Magneto 的添加到购物车控制器中的大事,它就无法一次处理添加所有产品,所以我被困在执行这些多个 Ajax 请求。

4

2 回答 2

3

这是一种方法:

// this will store the ajax requests with are jQuery.Deferred()
var promises = [];

// ajaxSettings.beforeSend is actually better to use to modify the xhr.
// You can just do this beforehand.
$j('#modalBackground').show();
$j('li.active').each(function(){
   // all your other stuff
   // success and error callbacks will still run for each one.
   promises.push($j.ajax({
       type:"POST",
       url: theLink,
       success: function(data){
           var returnPage = data;
           var exists = (returnPage.indexOf(successString) !== -1);
           if (exists) {$j('.col-main').prepend('<ul class="messages"><li class="success-msg"><ul><li><span>The items selected were added to your shopping cart. View your cart <a href="https://www.culturekings.com.au/checkout/cart/">HERE</a></span></li></ul></li></ul>'); $j("html, body").animate({ scrollTop: 0 }, "slow"); }
           else {alert ('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.')}
       },
       error: function(){alert('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.');}
    }));
});

// What this does is gathers all those jQuery.Deferred and when
// all of them are done, runs the done callback.
$j.when.apply($, promises).done(function() {
    $j('#modalBackground').fadeOut(200);
});

这一切都会发生在同一个函数中,所以不管你怎么称呼它,都一起做。

要了解有关 Deferred() 的更多信息:http: //api.jquery.com/category/deferred-object/

于 2013-07-04T06:19:18.863 回答
0

在我看来,您正在处理与此操作的异步性质相关的时间问题。我建议解雇你的 $j('#modalBackground').show(); 命令一次并且只淡化一次。所以本质上你会想做更多类似的事情:

$j('li.active').each(function(index){
            if(index===0) {
                $j('#modalBackground').show();
            }
            var theLink = $j(this).find('.shopthislookpageselect').val();
            var successString = "was added to your shopping cart."
            $j.ajax({
                type:"POST",
                url: theLink,
                success: function(data){
                    var returnPage = data;
                    var exists = (returnPage.indexOf(successString) !== -1);
                    if (exists) {$j('.col-main').prepend('<ul class="messages"><li class="success-msg"><ul><li><span>The items selected were added to your shopping cart. View your cart <a href="https://www.culturekings.com.au/checkout/cart/">HERE</a></span></li></ul></li></ul>'); $j("html, body").animate({ scrollTop: 0 }, "slow"); }
                    else {alert ('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.')}
                    },
                error: function(){alert('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.');},
                complete: function(){
                    if(index===($j('li.active').length-1)) {
                        $j('#modalBackground').fadeOut(200);
                    }
                }
            });
});

此代码将防止不必要的显示和隐藏相互冲突,我想这是手头的问题。

请记住,beforeSend 将在完成事件后立即触发,而完成事件根据响应的延迟具有任意触发时间。

于 2013-07-04T06:21:38.793 回答