Last active
January 12, 2025 20:55
-
-
Save webantam43/a0a2439d2ecfdbc75b23a13a5defc1b5 to your computer and use it in GitHub Desktop.
Thêm nút xóa và tăng giảm số lượng, ảnh đại diện sản phẩm trong trang thanh toán WooCommerce cho Flatsome
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Thêm nút xóa và tăng giảm số lượng sản phẩm trong trang thanh toán WooCommerce cho Flatsome | |
| * Bổ sung thêm ảnh đại diện sản phẩm | |
| */ | |
| // Thêm ảnh sản phẩm vào trước tên sản phẩm | |
| function add_product_image_before_name_wat($product_name, $cart_item, $cart_item_key) { | |
| if (!is_checkout()) { | |
| return $product_name; | |
| } | |
| $product = $cart_item['data']; | |
| $thumbnail = $product->get_image(array(50, 50)); | |
| return sprintf( | |
| '<div class="checkout-product-info-wat"> | |
| <div class="checkout-product-image-container-wat"> | |
| <a href="%s" class="remove-product-wat remove" aria-label="%s" data-product_id="%s" data-cart-key="%s">×</a> | |
| <div class="checkout-product-image-wat">%s</div> | |
| </div> | |
| <div class="checkout-product-name-wat">%s</div> | |
| </div>', | |
| 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']), | |
| esc_attr($cart_item_key), | |
| $thumbnail, | |
| $product_name | |
| ); | |
| } | |
| 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> | |
| </div> | |
| </div>', | |
| $product_subtotal, | |
| esc_attr($cart_item_key), | |
| esc_html($quantity), | |
| esc_attr($cart_item_key), | |
| esc_attr($cart_item_key) | |
| ); | |
| // CSS styles | |
| $style = ' | |
| <style> | |
| /* Style cho container thông tin sản phẩm */ | |
| .checkout-product-info-wat { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .checkout-product-image-container-wat { | |
| position: relative; | |
| } | |
| .checkout-product-image-wat img { | |
| width: 50px; | |
| height: 50px; | |
| object-fit: cover; | |
| border-radius: 3px; | |
| } | |
| .checkout-product-name-wat { | |
| flex: 1; | |
| } | |
| /* Style cho nút xóa */ | |
| .remove-product-wat { | |
| position: absolute; | |
| top: -8px; | |
| left: -8px; | |
| display: flex !important; | |
| align-items: center; | |
| justify-content: center; | |
| width: 20px !important; | |
| height: 20px !important; | |
| color: #ccc !important; | |
| font-size: 16px !important; | |
| font-weight: bold !important; | |
| text-decoration: none; | |
| border-radius: 50% !important; | |
| transition: all 0.2s; | |
| z-index: 1; | |
| cursor: pointer; | |
| } | |
| .remove-product-wat:hover { | |
| background-color: #e21b1b !important; | |
| color: white !important; | |
| text-decoration: none; | |
| } | |
| /* Các styles hiện có */ | |
| .checkout-product-controls_wat { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .product-total-price-wat { | |
| margin-bottom: 5px; | |
| } | |
| .product-controls-wrapper-wat { | |
| display: flex; | |
| gap: 10px; | |
| align-items: center; | |
| } | |
| .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; | |
| } | |
| .flatsome-quantity-wat .quantity-input { | |
| padding: 0 4px; | |
| 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; | |
| } | |
| .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; | |
| } | |
| .flatsome-quantity-wat.loading, | |
| .remove-product-wat.loading { | |
| opacity: 0.5; | |
| pointer-events: none; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| @media (max-width: 849px) { | |
| .flatsome-quantity-wat .button.is-form { | |
| height: 30px; | |
| width: 30px; | |
| } | |
| .checkout-product-image-wat img { | |
| width: 40px; | |
| height: 40px; | |
| } | |
| .checkout-product-info-wat{ | |
| padding-left: 12px; | |
| } | |
| .remove-product-wat{ | |
| left: -11px !important; | |
| } | |
| } | |
| </style> | |
| '; | |
| // JavaScript | |
| $script = ' | |
| <script> | |
| jQuery(document).ready(function($) { | |
| var ajaxUrl = "' . admin_url('admin-ajax.php') . '"; | |
| var nonce = "' . $nonce . '"; | |
| var isUpdating = false; | |
| var updateTimeout; | |
| // Khởi tạo loading overlay một lần | |
| $("body").append(\'<div class="checkout-loading-overlay-wat"><div class="checkout-loading-spinner-wat"></div></div>\'); | |
| var $loadingOverlay = $(".checkout-loading-overlay-wat"); | |
| function showLoadingwat() { | |
| $loadingOverlay.addClass("active"); | |
| } | |
| function hideLoadingwat() { | |
| $loadingOverlay.removeClass("active"); | |
| } | |
| function updateQuantitywat(cartKey, newQuantity, element) { | |
| if (isUpdating) return; | |
| var controls = element.closest(".flatsome-quantity-wat"); | |
| var quantityInput = controls.find(".quantity-input"); | |
| 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"); | |
| var totalQuantity = 0; | |
| $(".quantity-input").each(function() { | |
| totalQuantity += parseInt($(this).val()); | |
| }); | |
| $(".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; | |
| } | |
| }); | |
| } | |
| $(document).on("input", ".quantity-input", function() { | |
| var $this = $(this); | |
| var cartKey = $this.data("cart-key"); | |
| var newQuantity = parseInt($this.val()); | |
| if (updateTimeout) { | |
| clearTimeout(updateTimeout); | |
| } | |
| updateTimeout = setTimeout(function() { | |
| if (!isNaN(newQuantity) && newQuantity > 0) { | |
| updateQuantitywat(cartKey, newQuantity, $this); | |
| } | |
| }, 500); | |
| }); | |
| $(document).on("keypress", ".quantity-input", function(e) { | |
| if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) { | |
| return false; | |
| } | |
| }); | |
| $(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)); | |
| } | |
| }); | |
| $(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ý sự kiện xóa sản phẩm | |
| $(document).on("click", ".remove-product-wat", function(e) { | |
| e.preventDefault(); | |
| if (isUpdating) return; | |
| var $link = $(this); | |
| var cartKey = $link.data("cart-key"); | |
| var $productRow = $link.closest("tr"); | |
| if (!cartKey || $link.hasClass("loading")) return; | |
| isUpdating = true; | |
| $link.addClass("loading"); | |
| // Ẩn sản phẩm ngay lập tức để tạo phản hồi nhanh | |
| $productRow.css("opacity", "0.5"); | |
| $.ajax({ | |
| url: ajaxUrl, | |
| type: "POST", | |
| data: { | |
| action: "remove_cart_item_wat", | |
| cart_key: cartKey, | |
| security: nonce | |
| }, | |
| success: function(response) { | |
| if (response.success) { | |
| $productRow.fadeOut(200, function() { | |
| $(this).remove(); | |
| $("body").trigger("update_checkout"); | |
| // Cập nhật số lượng giỏ hàng | |
| var totalQuantity = 0; | |
| $(".quantity-input").each(function() { | |
| totalQuantity += parseInt($(this).val() || 0); | |
| }); | |
| $(".icon-shopping-cart").attr("data-icon-label", totalQuantity); | |
| if ($(".checkout-product-controls_wat").length === 0) { | |
| window.location.reload(); | |
| } | |
| }); | |
| } else { | |
| $productRow.css("opacity", "1"); | |
| alert("Không thể xóa sản phẩm. Vui lòng thử lại."); | |
| } | |
| }, | |
| error: function() { | |
| $productRow.css("opacity", "1"); | |
| alert("Có lỗi xảy ra. Vui lòng thử lại."); | |
| }, | |
| complete: function() { | |
| isUpdating = false; | |
| $link.removeClass("loading"); | |
| } | |
| }); | |
| }); | |
| $(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)); | |
| } | |
| // Xử lý Ajax cho việc xóa sản phẩm | |
| function handle_remove_cart_item_wat() { | |
| check_ajax_referer('woocommerce-cart', 'security'); | |
| $cart_key = sanitize_text_field($_POST['cart_key']); | |
| $success = false; | |
| if ($cart_key && isset(WC()->cart->cart_contents[$cart_key])) { | |
| $success = WC()->cart->remove_cart_item($cart_key); | |
| WC()->cart->calculate_totals(); | |
| } | |
| wp_send_json(array('success' => $success)); | |
| } | |
| // Đăng ký các action và filter | |
| 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_action('wp_ajax_remove_cart_item_wat', 'handle_remove_cart_item_wat'); | |
| add_action('wp_ajax_nopriv_remove_cart_item_wat', 'handle_remove_cart_item_wat'); | |
| add_filter('woocommerce_cart_item_subtotal', 'add_flatsome_product_controls_checkout_wat', 10, 3); | |
| add_filter('woocommerce_cart_item_name', 'add_product_image_before_name_wat', 10, 3); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment