Количество товара (quantity) — один важнейших элементов функционала интернет-магазина (woocommerce в частности). Есть множество нюансов связанных с количеством товара, рассмотрим их.
Вывод количества в категориях товаров
По умолчанию в шаблоне вывода товаров параметр количество товара не выводится. Включить его можно функцией:
add_filter( 'woocommerce_loop_add_to_cart_link', 'quantity_inputs_for_woocommerce_loop_add_to_cart_link', 10, 2 );
function quantity_inputs_for_woocommerce_loop_add_to_cart_link( $html, $product ) {
if ( $product && $product->is_type( 'simple' ) && $product->is_purchasable() && $product->is_in_stock() && ! $product->is_sold_individually() ) {
$html = '<form action="' . esc_url( $product->add_to_cart_url() ) . '" class="cart" method="post" enctype="multipart/form-data">';
$html .= woocommerce_quantity_input( array(), $product, false );
$html .= '<button type="submit" class="button alt">' . esc_html( $product->add_to_cart_text() ) . '</button>';
$html .= '</form>';
}
return $html;
}
Поле Количество в шаблоне архива (Ajax)
Отличное решение на Ajax, работает с мини-корзиной.
function custom_quantity_field_archive() {
$product = wc_get_product( get_the_ID() );
if ( ! $product->is_sold_individually() && 'variable' != $product->product_type && $product->is_purchasable() && $product->is_in_stock() ) {
woocommerce_quantity_input( array( 'min_value' => 1, 'max_value' => $product->backorders_allowed() ? '' : $product->get_stock_quantity() ) );
}
}
add_action( 'woocommerce_after_shop_loop_item', 'custom_quantity_field_archive', 9 );
function custom_add_to_cart_quantity_handler() {
wc_enqueue_js( '
jQuery( ".product-type-simple" ).on( "click", ".quantity input", function() {
return false;
});
jQuery( ".product-type-simple" ).on( "change input", ".quantity .qty", function() {
var add_to_cart_button = jQuery( this ).parents( ".product" ).find( ".add_to_cart_button" );
// For AJAX add-to-cart actions
add_to_cart_button.data( "quantity", jQuery( this ).val() );
// For non-AJAX add-to-cart actions
add_to_cart_button.attr( "href", "?add-to-cart=" + add_to_cart_button.attr( "data-product_id" ) + "&quantity=" + jQuery( this ).val() );
});
' );
}
add_action( 'init', 'custom_add_to_cart_quantity_handler' );
Устанавливаем минимум и максимум
//Min and Max quantity
// Simple products
add_filter( 'woocommerce_quantity_input_args', 'jk_woocommerce_quantity_input_args', 10, 2 );
function jk_woocommerce_quantity_input_args( $args, $product ) {
if ( is_singular( 'product' ) ) {
$args['input_value'] = 1; // Starting value (we only want to affect product pages, not cart)
}
$args['max_value'] = 100; // Maximum value
$args['min_value'] = 1; // Minimum value
$args['step'] = 1; // Quantity steps
return $args;
}
// Variations
add_filter( 'woocommerce_available_variation', 'jk_woocommerce_available_variation' );
function jk_woocommerce_available_variation( $args ) {
$args['max_qty'] = 100; // Maximum value (variations)
$args['min_qty'] = 1; // Minimum value (variations)
return $args;
}
Изменение товара в мини-корзине
Если необходимо корректировать количество (+ -) товара в мини-корзине, то нужно сделать следующее:
1. Вставляем в шаблоне мини-корзины (cart/mini-cart.php) кнопки + и —
<a rel="nofollow" href="/?wc-ajax=add_to_cart&add-to-cart=<?php echo $cart_item['product_id'];?>" data-quantity="1" data-product_id="<?php echo $cart_item['product_id'];?>" data-product_sku="" class="button product_type_simple add_to_cart_button ajax_add_to_cart btnPlus">+</a>
<?php echo '<a class="button btnMinus" onClick="updateQty(\''.$cart_item_key.'\','.($cart_item['quantity']-1).')">–</a>'; ?>
2. Создаем шаблон php c названием template-setquantity.php и содержимым:
<?php
// Template Name: Request template for Set Quantity
?>
<?php
//the cart key stores information about cart
$cartKeySanitized = filter_var($_POST['cart_item_key'], FILTER_SANITIZE_STRING);
//the new qty you want for the product in cart
$cartQtySanitized = filter_var($_POST['cart_item_qty'], FILTER_SANITIZE_STRING);
//update the quantity
global $woocommerce;
ob_start();
$woocommerce->cart->set_quantity($cartKeySanitized,$cartQtySanitized);
ob_get_clean();
?>
3. Создаем новую страницу с названием Updatecart и выбираем шаблон Request template for Set Quantity
4. Добавляем скрипт (в файл с другими скриптами сайта)
function updateQty(key,qty){
url = 'https://bazabirs.ru/updatecart/';
data = "cart_item_key="+key+"&cart_item_qty="+qty;
jQuery.post( url, data ) .done(function( data ) {
//function updateCartFragment
updateCartFragment();
});
}
function updateCartFragment() {
$fragment_refresh = {
url: woocommerce_params.ajax_url,
type: 'POST',
data: { action: 'woocommerce_get_refreshed_fragments' },
success: function( data ) {
if ( data && data.fragments ) {
jQuery.each( data.fragments, function( key, value ) {
jQuery(key).replaceWith(value);
});
if ( $supports_html5_storage ) {
sessionStorage.setItem( "wc_fragments", JSON.stringify( data.fragments ) );
sessionStorage.setItem( "wc_cart_hash", data.cart_hash );
}
jQuery('body').trigger( 'wc_fragments_refreshed' );
}
}
};
//Always perform fragment refresh
jQuery.ajax( $fragment_refresh );
}
CSS стили кнопок + и —
.btnPlus {
background-color: #01a7e5;
padding: 7px;
width: 10px;
color: #fff;
}
.btnMinus {
background-color: #ff5722;
padding: 7px;
width: 10px;
color: #fff;
cursor: pointer;
}
Изменить вид quantity
Стандартный вид количества woocmmerce не очень удобен, доработаем его.
Изменим шаблон woocommerce global/quantity-input.php:
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
?>
<div class="quantity">
<input class="minus" type="button" value="-">
<input type="number" step="<?php echo esc_attr( $step ); ?>" min="<?php echo esc_attr( $min_value ); ?>" max="<?php echo esc_attr( $max_value ); ?>" name="<?php echo esc_attr( $input_name ); ?>" value="<?php echo esc_attr( $input_value ); ?>" title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ) ?>" class="input-text qty text" size="4" />
<input class="plus" type="button" value="+">
</div>
CSS
/* Количество */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
/* display: none; <- Crashes Chrome on hover */
-webkit-appearance: none;
margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
}
input[type="number"] { -moz-appearance: textfield;}
.quantity {margin: 0 auto; display: table;}
.minus {
border: none;
color: #fff;
background-color: rgba(140,215,32,0.7);
height: 30px;
width: 30px;
/*display: table-cell;*/
cursor: pointer;
}
.plus {
border: none;
color: #fff;
background-color: rgba(140,215,32,0.7);
height: 30px;
width: 30px;
/*display: table-cell;*/
cursor: pointer;
}
.minus:hover, .plus:hover {background-color: rgba(140,215,32,1);}
.qty {
border: none;
color: #111;
/* font-weight: bold; */
height: 30px;
display: table-cell;
box-sizing: border-box;
width: 20% !important;
}
И добавляем скрипт
// Скрипт для кнопок + и -
$(document).ready(function(){
$('.quantity').on('click', '.plus', function(e) {
$input = $(this).prev('input.qty');
var val = parseInt($input.val());
$input.val( val+1 ).change();
});
$('.quantity').on('click', '.minus', function(e) {
$input = $(this).next('input.qty');
var val = parseInt($input.val());
if (val > 1) {
$input.val( val-1 ).change();
}
});
});
В шаблоне архивов товаров, в карточке товаров, сопутствующих — метод работает отлично. В корзине не работает из-за обновления ajax.
Чтобы работал в корзине надо изменить .quantity на body. Но с body не работает в шаблоне архивов товаров.
// Скрипт для кнопок + и -
$(document).ready(function(){
$('body').on('click', '.plus', function(e) {
$input = $(this).prev('input.qty');
var val = parseInt($input.val());
$input.val( val+1 ).change();
});
$('body').on('click', '.minus', function(e) {
$input = $(this).next('input.qty');
var val = parseInt($input.val());
if (val > 1) {
$input.val( val-1 ).change();
}
});
});
if (val > 1) { — если это сравнение снизить до ноля, то можно в корзине, с помощью кнопки минус, фактически удалять товары.
Еще один важный момент! Если корзина обновляется автоматически, то при нажатии + или — минус в первый раз обновление срабатывает, а кнопка update_cart только становится активной (изначально у этого input стоит атрибут disabled), и только после второго нажатия срабатывает обновление. Исправляем это так — изначально «взводим» кнопку обновления, при этом изначально и при последующих обновлениях ajax.
//Кнопка Обновить в Корзине изначально активна
jQuery(document).bind('ready ajaxComplete', function(){
jQuery('[name="update_cart"]').attr("disabled",false);
});
Надо разделить вывод скрипта в корзине от скрипта в архивах.
При нажатии + или — происходит перезагрузка ajax, но пользователь, который хочет изменить количество на десятки единиц может этого не понять. Чтобы этот момент сгладить, надо в скрипте автоматического обновления корзины (при обновлении количества) добавить небольшую задержку:
setTimeout(function () { jQuery("[name='update_cart']").trigger("click"); }, 1000);
Возможные ошибки
В одном из проектов, при добавлении плагина с кнопками +/- они не работали по причине того что ранее я внедрил сам функционал в файл site-scripts.js, т.е. он дублировался и из-за этого работал не корректно.
Кнопка + может не работать из-за того что в input не прописывается значение max. В этом случае, нужно немного изменить скрипт:
jQuery('body').on('click', '.plus', function() {
var input = jQuery(this).prev('input.qty');
var val = parseFloat(input.val());
var step = parseFloat(input.attr('step'));
var max = parseFloat(input.attr('max'));
if (isNaN(max)) { var max = 999999; }
if (val < max) { input.val( val+step ).change(); }
});
[site-socialshare]
При нажатии на кнопку «добавить в корзину» все-равно добавляется в кол-ве 1 штука, а не столько, сколько было введено на карточке товара.
Кнопка «-» не работает в мини корзине
Когда вставляешь сами кнопки в шаблон WC миникорзины нужно кнопку «—» поставить перед полем количество, а кнопку «+» после.
У меня сделано так:
<td style="width: 20px;">
<?php echo '<a class="minus" onClick="updateQty(\''.$cart_item_key.'\','.($cart_item['quantity']-1).')">–</a>'; ?>
</td>
<td class="product-quantity">
<?php echo apply_filters( 'woocommerce_checkout_cart_item_quantity', ' <strong class="product-quantity">' . sprintf( '× %s', $cart_item['quantity'] ) . '</strong>', $cart_item, $cart_item_key ); ?>
</td>
<td style="width: 20px;">
<a rel="nofollow" href="/?wc-ajax=add_to_cart&add-to-cart=<?php echo $cart_item['product_id'];?>" data-quantity="1" data-product_id="<?php echo $cart_item['product_id'];?>" data-product_sku="" class="product_type_simple add_to_cart_button ajax_add_to_cart plus">+</a>
</td>
Какой то костыль получился по мини-корзине. Вот более наверное правильное решение https://gist.github.com/ashokmhrj/fda5a23f7bdfc55749bd2bd53c64a8ca