WoocommerceWordpress
[Woocommerce] Thêm Nút Xóa – Tăng Giảm Số Lượng Trong Trang Thanh Toán Woocommerce

Thêm nút xóa và tăng giảm số lượng sản phẩm trong trang thanh toán WooCommerce đối với các bạn sử dụng wordpress plugin Woocommerce
- Tăng giảm số lượng trực tiếp ở trang thanh toán cho từng sản phẩm
- Xóa từng sản phẩm đã thêm vào giỏ hàng ngay trực tiếp trang thanh toán
Cho code sau vào file funtion.php
function add_flatsome_product_controls_checkout_wat($product_subtotal, $cart_item, $cart_item_key) {
if (!is_checkout()) {
return $product_subtotal;
}
$quantity = $cart_item['quantity'];
$nonce = wp_create_nonce('woocommerce-cart');
// html
$controls_html = sprintf(
'<div class="checkout-product-controls_wat">
<div class="product-total-price-wat">%s</div>
<div class="product-controls-wrapper-wat">
<div class="quantity-controls flatsome-quantity-wat buttons_added">
<input type="button" value="-" class="minuswat button is-form" data-cart-key="%s">
<input type="number" class="quantity-input" value="%s" min="1" step="1" data-cart-key="%s">
<input type="button" value="+" class="pluswat button is-form" data-cart-key="%s">
</div>
<a href="%s" class="remove-product-wat remove" aria-label="%s" data-product_id="%s">×</a>
</div>
</div>',
$product_subtotal,
esc_attr($cart_item_key),
esc_html($quantity),
esc_attr($cart_item_key),
esc_attr($cart_item_key),
esc_url(wc_get_cart_remove_url($cart_item_key)),
esc_html__('Xóa sản phẩm này', 'flatsome'),
esc_attr($cart_item['product_id'])
);
// CSS styles
$style = '
<style>
/* Container cho tất cả controls */
.checkout-product-controls_wat {
display: flex;
flex-direction: column;
gap: 10px;
}
/* Style cho phần giá */
.product-total-price-wat {
margin-bottom: 5px;
}
/* Wrapper cho phần controls */
.product-controls-wrapper-wat {
display: flex;
gap: 10px;
align-items: center;
}
/* Style cho phần quantity controls */
.flatsome-quantity-wat {
display: inline-flex;
align-items: center;
border: 1px solid #ddd;
border-radius: 3px;
overflow-x: hidden;
}
.flatsome-quantity-wat .button.is-form {
border-radius: 0;
background-color: #f9f9f9;
border: none;
height: 25px;
width: 25px;
padding: 0;
margin: 0;
font-size: 14px;
}
/* Style cho input số lượng */
.flatsome-quantity-wat .quantity-input {
padding: 0 8px;
width: 35px;
text-align: center;
border: none;
background: #fff;
height: 20px;
line-height: 25px;
display: inline-block;
-moz-appearance: textfield;
box-shadow: none;
}
.flatsome-quantity-wat .quantity-input::-webkit-outer-spin-button,
.flatsome-quantity-wat .quantity-input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input.minuswat.button.is-form {
width: 20px;
}
input.pluswat.button.is-form {
width: 20px;
}
/* Style cho nút xóa */
.remove-product-wat {
display: flex;
align-items: center;
justify-content: center;
width: 25px;
height: 25px;
color: #ccc !important;
font-size: 20px !important;
font-weight: bold;
text-decoration: none;
border: 1px solid #ddd;
border-radius: 3px;
transition: all 0.2s;
}
.remove-product-wat:hover {
color: #334862 !important;
background-color: #f9f9f9;
}
/* Loading overlay */
.checkout-loading-overlay-wat {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.8);
z-index: 9999;
justify-content: center;
align-items: center;
}
.checkout-loading-overlay-wat.active {
display: flex;
}
.checkout-loading-spinner-wat {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #334862;
border-radius: 50%;
animation: spin 1s linear infinite;
}
/* Loading states */
.flatsome-quantity-wat.loading,
.remove-product-wat.loading {
opacity: 0.5;
pointer-events: none;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Responsive */
@media (max-width: 849px) {
.flatsome-quantity-wat .button.is-form,
.remove-product-wat {
height: 30px;
width: 30px;
}
}
</style>
';
// JavaScript
$script = '
<script>
jQuery(document).ready(function($) {
var ajaxUrl = "' . admin_url('admin-ajax.php') . '";
var nonce = "' . $nonce . '";
var isUpdating = false;
var updateTimeout;
// Thêm overlay loading vào body nếu chưa có
if (!$(".checkout-loading-overlay-wat").length) {
$("body").append(\'<div class="checkout-loading-overlay-wat"><div class="checkout-loading-spinner-wat"></div></div>\');
}
function showLoadingwat() {
$(".checkout-loading-overlay-wat").addClass("active");
}
function hideLoadingwat() {
$(".checkout-loading-overlay-wat").removeClass("active");
}
function updateQuantitywat(cartKey, newQuantity, element) {
if (isUpdating) return;
var controls = element.closest(".flatsome-quantity-wat");
var quantityInput = controls.find(".quantity-input");
// Kiểm tra giá trị tối thiểu
if (newQuantity < 1) {
newQuantity = 1;
quantityInput.val(1);
return;
}
isUpdating = true;
showLoadingwat();
controls.addClass("loading");
$.ajax({
url: ajaxUrl,
type: "POST",
data: {
action: "flatsome_update_quantity",
cart_key: cartKey,
quantity: newQuantity,
security: nonce
},
success: function(response) {
if(response.success) {
quantityInput.val(newQuantity);
$("body").trigger("update_checkout");
// Tính toán tổng số lượng mới
var totalQuantity = 0;
$(".quantity-input").each(function() {
totalQuantity += parseInt($(this).val());
});
// Cập nhật số lượng trực tiếp trên icon giỏ hàng
$(".icon-shopping-cart").attr("data-icon-label", totalQuantity);
} else {
alert("Không thể cập nhật số lượng. Vui lòng tải lại trang.");
quantityInput.val(newQuantity - 1);
}
},
error: function() {
alert("Có lỗi xảy ra. Vui lòng thử lại.");
quantityInput.val(newQuantity - 1);
},
complete: function() {
controls.removeClass("loading");
hideLoadingwat();
isUpdating = false;
}
});
}
// Xử lý nhập số lượng trực tiếp
$(document).on("input", ".quantity-input", function() {
var $this = $(this);
var cartKey = $this.data("cart-key");
var newQuantity = parseInt($this.val());
// Clear timeout cũ nếu có
if (updateTimeout) {
clearTimeout(updateTimeout);
}
// Đặt timeout mới
updateTimeout = setTimeout(function() {
if (!isNaN(newQuantity) && newQuantity > 0) {
updateQuantitywat(cartKey, newQuantity, $this);
}
}, 500); // Đợi 500ms sau khi người dùng ngừng nhập
});
// Ngăn chặn nhập các ký tự không phải số
$(document).on("keypress", ".quantity-input", function(e) {
if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) {
return false;
}
});
// Xử lý nút giảm
$(document).on("click", ".flatsome-quantity-wat .minuswat", function() {
if (isUpdating) return;
var cartKey = $(this).data("cart-key");
var quantityInput = $(this).siblings(".quantity-input");
var currentQty = parseInt(quantityInput.val());
if (currentQty > 1) {
updateQuantitywat(cartKey, currentQty - 1, $(this));
}
});
// Xử lý nút tăng
$(document).on("click", ".flatsome-quantity-wat .pluswat", function() {
if (isUpdating) return;
var cartKey = $(this).data("cart-key");
var quantityInput = $(this).siblings(".quantity-input");
var currentQty = parseInt(quantityInput.val());
updateQuantitywat(cartKey, currentQty + 1, $(this));
});
// Xử lý nút xóa cải tiến không reload trang
$(document).on("click", ".remove-product-wat", function(e) {
e.preventDefault();
if (isUpdating) return;
var link = $(this).attr("href");
var $this = $(this);
var $productRow = $this.closest("tr");
isUpdating = true;
showLoadingwat();
$this.addClass("loading");
$.ajax({
url: link,
type: "GET",
success: function() {
$productRow.fadeOut(300, function() {
$(this).remove();
$("body").trigger("update_checkout");
// Tính toán tổng số lượng mới sau khi xóa
var totalQuantity = 0;
$(".quantity-input").each(function() {
totalQuantity += parseInt($(this).val());
});
// Cập nhật số lượng trực tiếp trên icon giỏ hàng
$(".icon-shopping-cart").attr("data-icon-label", totalQuantity);
if ($(".checkout-product-controls_wat").length === 0) {
window.location.reload();
}
});
hideLoadingwat();
isUpdating = false;
},
error: function() {
alert("Có lỗi xảy ra. Vui lòng thử lại.");
hideLoadingwat();
$this.removeClass("loading");
isUpdating = false;
},
complete: function() {
$this.removeClass("loading");
}
});
});
// Xử lý blur input để cập nhật khi click ra ngoài
$(document).on("blur", ".quantity-input", function() {
var $this = $(this);
var cartKey = $this.data("cart-key");
var newQuantity = parseInt($this.val());
if (!isNaN(newQuantity) && newQuantity > 0) {
updateQuantitywat(cartKey, newQuantity, $this);
} else {
$this.val(1);
updateQuantitywat(cartKey, 1, $this);
}
});
});
</script>
';
if (!wp_script_is('flatsome-product-controls-wat', 'enqueued')) {
add_action('wp_footer', function() use ($style, $script) {
echo $style . $script;
});
wp_register_script('flatsome-product-controls-wat', null);
}
return $controls_html;
}
// Xử lý Ajax cho cập nhật số lượng
function handle_flatsome_quantity_update_wat() {
check_ajax_referer('woocommerce-cart', 'security');
$cart_key = sanitize_text_field($_POST['cart_key']);
$quantity = intval($_POST['quantity']);
$success = false;
if ($cart_key && $quantity > 0) {
$success = WC()->cart->set_quantity($cart_key, $quantity);
WC()->cart->calculate_totals();
}
wp_send_json(array('success' => $success));
}
// Đăng ký Ajax actions
add_action('wp_ajax_flatsome_update_quantity', 'handle_flatsome_quantity_update_wat');
add_action('wp_ajax_nopriv_flatsome_update_quantity', 'handle_flatsome_quantity_update_wat');
add_filter('woocommerce_cart_item_subtotal', 'add_flatsome_product_controls_checkout_wat', 10, 3);