2014-10-01 55 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