2014-10-01 19 views
7

Ho cercato per diversi giorni, ma non ho ancora risposta. Fondamentalmente, sto provando a sostituire woocommerce standart "Aggiorna carrello" pulsante con una chiamata ajax, che aggiorna automaticamente il prezzo totale dell'ordine quando la quantità cambiata. Questo è il mio htmlWooCommerce - aggiornamento automatico prezzo totale in caso di variazione della quantità

<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> 

In functions.php Ho una funzione per i totali aggiornamento:

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; 
      } 

    } 

E il codice 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; 
    }); 
}); 

Il codice di cui sopra funziona alla grande se solo un prodotto è nel carrello. enter image description here

Ma quando aggiungo qualche altro prodotto e cambio quantità di uno di essi la mia funzione utilizza l'ultimo valore di quantità per tutti i miei prodotti.

enter image description here

Ad esempio, il prezzo totale per la seconda immagine deve essere 7000 (2000 * 1 + 2500 * 2), ma è 9000 (2000 * 2 + 2500 * 2). Sono nuovo ad ajax e jquery quindi apprezzo qualsiasi aiuto.

risposta

5

È perché si aggiorna tutto il carrello, non solo un prodotto.

Per prima cosa è necessario inviare la voce di spesa hash (non è un hash di sicurezza, ma l'hash prodotto con tutte le variazioni del prodotto) sullo script 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 
    }; 

quindi è possibile modificare il vostro function update_total_price, io semplicato;)

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, funziona benissimo! Grazie mille! – grimasa

+0

ciò che manca è, come viene impostato 'rf_cart_params'? se chiamo la funzione jQuery di cui sopra, ottengo un 'ReferenceError: rf_cart_params non è definito'. forse la causa è che non ho nemmeno caricato la pagina del carrello, mostro il carrello sulla pagina dei prodotti-archivio (in realtà l'ho verificato, quando provo il codice sulla pagina del carrello originale, è lo stesso problema ..). quindi come faccio a caricare gli script/impostare le variabili ..? – honk31

+0

in realtà sulla pagina del carrello ho trovato l'oggetto, ma è chiamato 'wc_cart_params'. cercherò di avviarli nella mia pagina di archivio .. – honk31

3

Ecco un modo più semplice per raggiungere questo obiettivo. Tutto il merito va a 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

questa risposta non ha davvero nulla a che fare con la domanda. mentre potrebbe calcolare correttamente il prezzo, questo strumento è solo per calcolare il prezzo sulla pagina di produzione, mentre la domanda riguarda la pagina del carrello. quando cambi la quantità sulla pagina del carrello e non la presenti a wc, il prezzo potrebbe cambiare, ma il carrello no. – honk31

+0

@ honk31 hai ragione! non l'avevo notato Immagino valga la pena tenerlo qui perché potrebbe aiutare qualcuno in futuro – adamj

Problemi correlati