2014-10-01 132 views
7

我一直在寻找几天,但我还没有答案。基本上,我试图用ajax调用取代woocommerce标准“更新购物车”按钮,当数量发生变化时,会自动更新订单总价。 这是我的HTMLWooCommerce - 数量改变时自动更新总价格

<div class="cart_item"> 
    <div class="product-thumbnail"> 
     <a href="http://example.com"><img width="90" height="90" src="path to thumbnail"/></a> 
    </div> 

    <div class="product-name"> 
     <a class="cart-page-product__title" href="http://example.com">Product1 name</a> 
    </div> 

    <div class="product-quantity"> 
     <div class="quantity"> 
      <input type="number" step="1" name="cart[some_security_key][qty]" value="1" class="input-text qty text" size="4"/> 
     </div> 
    </div> 

    <div class="product-subtotal"><span class="amount">2 000</span></div> 
     <div class="product-remove"> 
      <a class="product-remove_link" href="http://example.com/?remove_item">&times;</a> 
     </div> 
</div> 
<div class="cart_item"> 
    <div class="product-thumbnail"> 
     <a href="http://example.com"><img width="90" height="90" src="path to thumbnail"/></a> 
    </div> 

    <div class="product-name"> 
     <a class="cart-page-product__title" href="http://example.com">Product2 name</a> 
    </div> 

    <div class="product-quantity"> 
     <div class="quantity"> 
      <input type="number" step="1" name="cart[some_security_key][qty]" value="1" class="input-text qty text" size="4"/> 
     </div> 
    </div> 

    <div class="product-subtotal"><span class="amount">2 000</span></div> 
     <div class="product-remove"> 
      <a class="product-remove_link" href="http://example.com/?remove_item">&times;</a> 
     </div> 
</div> 

在functions.php的我有更新汇总功能:

public function update_total_price() { 
     check_ajax_referer('update_total_price', 'security'); 

     if (! defined('WOOCOMMERCE_CART')) { 
      define('WOOCOMMERCE_CART', true); 
     } 

     $cart_updated = false; 
      $cart_totals = isset($_POST['cart']) ? $_POST['cart'] : ''; 

      if (sizeof(WC()->cart->get_cart()) > 0) { 
       foreach (WC()->cart->get_cart() as $cart_item_key => $values) { 
        $_product = $values['data']; 

        // Skip product if no updated quantity was posted 
        if (! isset($_POST['quantity'])) { 
        // if (! isset($cart_totals[ $cart_item_key ]['qty'])) { 
         continue; 
        } 

        // Sanitize 
        $quantity = apply_filters('woocommerce_stock_amount_cart_item', apply_filters('woocommerce_stock_amount', preg_replace("/[^0-9\.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT))), $cart_item_key); 
        // $quantity = apply_filters('woocommerce_stock_amount_cart_item', apply_filters('woocommerce_stock_amount', preg_replace("/[^0-9\.]/", '', $cart_totals[ $cart_item_key ]['qty'])), $cart_item_key); 

        if ('' === $quantity || $quantity == $values['quantity']) 
         continue; 

        // Update cart validation 
        $passed_validation = apply_filters('woocommerce_update_cart_validation', true, $cart_item_key, $values, $quantity); 

        // is_sold_individually 
        if ($_product->is_sold_individually() && $quantity > 1) { 
         wc_add_notice(sprintf(__('You can only have 1 %s in your cart.', 'woocommerce'), $_product->get_title()), 'error'); 
         $passed_validation = false; 
        } 

        if ($passed_validation) { 
         WC()->cart->set_quantity($cart_item_key, $quantity, false); 
        } 

        $cart_updated = true; 
       } 
      } 

      // Trigger action - let 3rd parties update the cart if they need to and update the $cart_updated variable 
      $cart_updated = apply_filters('woocommerce_update_cart_action_cart_updated', $cart_updated); 

      if ($cart_updated) { 
       // Recalc our totals 
       WC()->cart->calculate_totals(); 
       woocommerce_cart_totals(); 
       exit; 
      } 

    } 

和jQuery代码:

jQuery(function($) { 

    // wc_cart_params is required to continue, ensure the object exists 
    if (typeof wc_cart_params === 'undefined') { 
     return false; 
    } 

    // Cart price update depends on quantity 
    //$(document).on('click', '.quantity', function() { 


    $(document).on('change', '.quantity, input[type=number]', function() { 
     var qty = $(this).val(); 
     var currentVal = parseFloat(qty); 

     $('div.cart_totals').block({ message: null, overlayCSS: { background: '#fff url(' + wc_cart_params.ajax_loader_url + ') no-repeat center', backgroundSize: '16px 16px', opacity: 0.6 } }); 

     var data = { 
      action: 'rf_update_total_price', 
      security: rf_cart_params.rf_update_total_price_nonce, 
      quantity: currentVal 
     }; 

     $.post(rf_cart_params.ajax_url, data, function(response) { 

      $('div.cart_totals').replaceWith(response); 
      $('body').trigger('rf_update_total_price'); 

     }); 
     return false; 
    }); 
}); 

如果只有上面的代码的伟大工程一个产品在购物车中。 enter image description here

但是当我添加其他产品并更改其中一个产品的数量时,我的所有产品的功能都使用最后一个数量值。

enter image description here

例如,总价格了第二图像必须是7000(2000 * 1 + 2500 * 2),但它是9000(2000 * 2 + 2500 * 2)。 我是新来的ajax和jQuery,所以很感谢任何帮助。

回答

5

这是因为您正在更新所有的购物车,而不仅仅是一个产品。

首先,你需要发送的项目车哈希(这不是一个安全散列,但所有的产品差异化的产品散列)上的JavaScript脚本:

var item_hash = $(this).attr('name').replace(/cart\[([\w]+)\]\[qty\]/g, "$1"); 
var data = { 
     action: 'rf_update_total_price', 
     security: rf_cart_params.rf_update_total_price_nonce, 
     quantity: currentVal, 
     hash : item_hash 
    }; 

然后你可以编辑你function update_total_price,我简化;)

function update_total_price() { 

    // Skip product if no updated quantity was posted or no hash on WC_Cart 
    if(!isset($_POST['hash']) || !isset($_POST['quantity'])){ 
     exit; 
    } 

    $cart_item_key = $_POST['hash']; 

    if(!isset(WC()->cart->get_cart()[ $cart_item_key ])){ 
     exit; 
    } 

    $values = WC()->cart->get_cart()[ $cart_item_key ]; 

    $_product = $values['data']; 

    // Sanitize 
    $quantity = apply_filters('woocommerce_stock_amount_cart_item', apply_filters('woocommerce_stock_amount', preg_replace("/[^0-9\.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT))), $cart_item_key); 

    if ('' === $quantity || $quantity == $values['quantity']) 
     exit; 

    // Update cart validation 
    $passed_validation = apply_filters('woocommerce_update_cart_validation', true, $cart_item_key, $values, $quantity); 

    // is_sold_individually 
    if ($_product->is_sold_individually() && $quantity > 1) { 
     wc_add_notice(sprintf(__('You can only have 1 %s in your cart.', 'woocommerce'), $_product->get_title()), 'error'); 
     $passed_validation = false; 
    } 

    if ($passed_validation) { 
     WC()->cart->set_quantity($cart_item_key, $quantity, false); 
    } 

    // Recalc our totals 
    WC()->cart->calculate_totals(); 
    woocommerce_cart_totals(); 
    exit; 
} 
+0

XcID,它工作的很棒!非常感谢你! – grimasa 2014-11-26 10:13:44

+0

这里缺少的是,如何设置'rf_cart_params' ..?如果我调用上面的jQuery函数,我得到一个'ReferenceError:rf_cart_params没有定义'。也许原因是,我甚至没有加载购物车页面,我在产品存档页面上显示购物车(实际上,我检查了它,当我尝试了原始购物车页面上的代码时,它也出现了相同的问题。 )。所以我如何获取脚本加载/变量设置..? – honk31 2016-04-22 18:59:31

+0

实际上在购物车页面上,我现在找到了该对象,但其名为'wc_cart_params'。将尝试enque那些在我的档案页面。 – honk31 2016-04-22 19:06:04

3

这是一个简单的方法来实现这一点。所有功劳都归功于Reigel Gallarde

// we are going to hook this on priority 31, so that it would display below add to cart button. 
add_action('woocommerce_single_product_summary', 'woocommerce_total_product_price', 31); 
function woocommerce_total_product_price() { 
    global $woocommerce, $product; 
    // let's setup our divs 
    echo sprintf('<div id="product_total_price" style="margin-bottom:20px;display:none">%s %s</div>',__('Product Total:','woocommerce'),'<span class="price">'.$product->get_price().'</span>'); 
    echo sprintf('<div id="cart_total_price" style="margin-bottom:20px;display:none">%s %s</div>',__('Cart Total:','woocommerce'),'<span class="price">'.$product->get_price().'</span>'); 
    ?> 
     <script> 
      jQuery(function($){ 
       var price = <?php echo $product->get_price(); ?>, 
        current_cart_total = <?php echo $woocommerce->cart->cart_contents_total; ?>, 
        currency = '<?php echo get_woocommerce_currency_symbol(); ?>'; 

       $('[name=quantity]').change(function(){ 
        if (!(this.value < 1)) { 
         var product_total = parseFloat(price * this.value), 
         cart_total = parseFloat(product_total + current_cart_total); 

         $('#product_total_price .price').html(currency + product_total.toFixed(2)); 
         $('#cart_total_price .price').html(currency + cart_total.toFixed(2)); 
        } 
        $('#product_total_price,#cart_total_price').toggle(!(this.value <= 1)); 

       }); 
      }); 
     </script> 
    <?php 
} 
+0

这个答案并没有真正做任何事情的问题。虽然它可能会正确计算价格,但此工具仅用于计算产品页面上的价格,而问题与购物车页面有关。当您在购物车页面上更改数量并且不提交给wc时,价格可能会改变,但购物车不会。 – honk31 2016-04-24 13:53:15

+0

@ honk31你是对的!没有注意到。我想这仍然值得留在这里,因为它可能会在未来帮助某人 – adamj 2016-04-26 04:17:54