PageSourceSearch

https://www.architecturebois.fr/wp-content/themes/astra/assets/js/…/add-to-cart-quantity-btn.js?ver=4.14.0

js architecturebois.fr collected 2026-10-02 20:28:21 UTC 11,366 bytes, 286 lines download raw bytes

1/**
2 * WooCommerce quantity buttons.
3 *
4 * @since x.x.x
5 */
6
7window.addEventListener( "load", function(e) {
8    astrawpWooQuantityButtons();
9    quantityInput();
10});
11
12
13// Here we are selecting the node that will be observed for mutations.
14const astraminiCarttargetNodes = document.querySelectorAll(".ast-site-header-cart");
15
16astraminiCarttargetNodes.forEach(function(astraminiCarttargetNode) {
17    if (astraminiCarttargetNode != null) {
18        const config = { attributes: false, childList: true, subtree: true };
19
20        const astraMinicartObserver = () => {
21            astrawpWooQuantityButtons();
22            quantityInput();
23        };
24
25        const observer = new MutationObserver(astraMinicartObserver);
26        observer.observe(astraminiCarttargetNode, config);
27    }
28});
29
30/**This comment explains that in order to refresh the wc_fragments_refreshed event when an AJAX call is made, jQuery is used to update the quantity button.
31 * Here plain JavaScript may not be able to trigger the wc_fragments_refreshed event in the same way,
32 * hence the need to use jQuery
33*/
34jQuery( function( $ ) {
35    $( document.body ).on( 'wc_fragments_refreshed woosq_loaded', function() {
36        astrawpWooQuantityButtons();
37        quantityInput();
38    });
39});
40
41(function() {
42    // Delay the method override so that we do not interfere with the Metrix test.
43    setTimeout(() => {
44        var send = XMLHttpRequest.prototype.send
45        XMLHttpRequest.prototype.send = function() {
46            this.addEventListener('load', function() {
47                astrawpWooQuantityButtons();
48            })
49            return send.apply(this, arguments)
50        }
51    }, 2000);
52})();
53
54/**
55 * Astra WooCommerce Quantity Buttons.
56 */
57function astrawpWooQuantityButtons( $quantitySelector ) {
58
59    var $cart = document.querySelector( '.woocommerce div.product form.cart' );
60
61    if ( ! $quantitySelector ) {
62        $quantitySelector = '.qty';
63    }
64
65    $quantityBoxesWrap = document.querySelectorAll( 'div.quantity:not(.elementor-widget-woocommerce-cart .quantity):not(.buttons_added), td.quantity:not(.elementor-widget-woocommerce-cart .quantity):not(.buttons_added)' );
66
67    for ( var i = 0; i < $quantityBoxesWrap.length; i++ ) {
68
69        var e = $quantityBoxesWrap[i];
70
71        var $quantityBoxes = e.querySelector( $quantitySelector );
72
73        if ( $quantityBoxes && 'date' !== $quantityBoxes.getAttribute( 'type' ) && 'hidden' !== $quantityBoxes.getAttribute( 'type' ) ) {
74
75            // Add plus and minus icons.
76            $qty_parent = $quantityBoxes.parentElement;
77
78            // Remove existing plus and minus placeholders.
79            document.querySelectorAll( '.ast-qty-placeholder' )?.forEach( ( placeholder ) => placeholder?.remove() );
80
81            $qty_parent.classList.add( 'buttons_added' );
82
83            const minusBtn = `<span class="screen-reader-text">${ astra_qty_btn.minus_qty }</span><a href="javascript:void(0)" id="minus_qty-${ i }" class="minus %s">-</a>`;
84            const plusBtn = `<span class="screen-reader-text">${ astra_qty_btn.plus_qty }</span><a href="javascript:void(0)" id="plus_qty-${ i }" class="plus %s">+</a>`;
85
86            if ( 'vertical-icon' === astra_qty_btn.style_type ) {
87                $qty_parent.classList.add( 'ast-vertical-style-applied' );
88                $quantityBoxes.classList.add( 'vertical-icons-applied' );
89                $qty_parent.insertAdjacentHTML(
90                    'beforeend',
91                    minusBtn.replace( '%s', 'ast-vertical-icon' ) + plusBtn.replace( '%s', 'ast-vertical-icon' )
92                );
93            } else {
94                let styleTypeClass = '';
95                if ( 'no-internal-border' === astra_qty_btn.style_type ) {
96                    $quantityBoxes.classList.add( 'ast-no-internal-border' );
97                    styleTypeClass = 'no-internal-border';
98                }
99                $qty_parent.insertAdjacentHTML( 'afterbegin', minusBtn.replace( '%s', styleTypeClass ) );
100                $qty_parent.insertAdjacentHTML( 'beforeend', plusBtn.replace( '%s', styleTypeClass ) );
101            }
102            $quantityEach = document.querySelectorAll( 'input' + $quantitySelector + ':not(.product-quantity)' );
103
104            for ( var j = 0; j < $quantityEach.length; j++ ) {
105
106                var el = $quantityEach[j];
107
108                var $min = el.getAttribute( 'min' );
109
110                if ( $min && $min > 0 && parseFloat( el.value ) < $min ) {
111                    el.value = $min;
112                }
113            }
114
115            // Quantity input.
116            let objbody = document.getElementsByTagName('BODY')[0];
117            let cart = document.getElementsByClassName('cart')[0];
118
119            if (objbody.classList.contains('single-product') && cart && !cart.classList.contains('grouped_form')) {
120                let quantityInput = document.querySelector('.woocommerce input[type=number].qty');
121                // Check for single product page.
122                if (quantityInput) {
123                    quantityInput.addEventListener('keyup', function () {
124                        let qtyVal = quantityInput.value;
125                        quantityInput.value = qtyVal;
126                    });
127                }
128            }
129
130            var plus_minus_obj = e.querySelectorAll( '.plus, .minus' );
131
132            for ( var l = 0; l < plus_minus_obj.length; l++ ) {
133
134                var pm_el = plus_minus_obj[l];
135
136                pm_el.addEventListener( "click", function(ev) {
137
138
139                    // Quantity.
140                    var $quantityBox;
141
142                    $quantityBox = ev.target.parentElement.querySelector( $quantitySelector );
143
144                    // Get values.
145                    var $currentQuantity = parseFloat( $quantityBox.value ),
146                    $maxQuantity = parseFloat( $quantityBox.getAttribute( 'max' ) ),
147                    $minQuantity = parseFloat( $quantityBox.getAttribute( 'min' ) ),
148                    $step = parseFloat( $quantityBox.getAttribute( 'step' ) ),
149                    checkStepInteger = Number.isInteger( $step ),
150                    finalValue;
151
152                    // Fallback default values on falsy values like '' and NaN.
153                    if ( ! $currentQuantity ) {
154                        $currentQuantity = 0;
155                    }
156                    if ( ! $maxQuantity ) {
157                        $maxQuantity = '';
158                    }
159
160                    if ( ! $minQuantity ) {
161                        $minQuantity = 0;
162                    }
163                    if ( ! $step ) {
164                        $step = 1;
165                    }
166
167                    // Change the value.
168                    if ( ev.target.classList.contains( 'plus' ) ) {
169
170                        if ( $maxQuantity && ( $maxQuantity === $currentQuantity || $currentQuantity > Number( $maxQuantity ) ) ) {
171                            $quantityBox.value = $maxQuantity;
172                        } else {
173                            finalValue = $currentQuantity + parseFloat( $step );
174                            $quantityBox.value = checkStepInteger ? finalValue : ( finalValue ).toFixed(1);
175                        }
176
177                    } else {
178
179                        if ( $minQuantity && ( $minQuantity === $currentQuantity || $currentQuantity < $minQuantity ) ) {
180                            $quantityBox.value = $minQuantity;
181                        } else if ( $currentQuantity > 0 ) {
182                            finalValue = $currentQuantity - parseFloat( $step );
183                            $quantityBox.value = checkStepInteger ? finalValue : ( finalValue ).toFixed(1);
184                        }
185
186                    }
187
188                    // Trigger the change event on the input.
189                    var changeEvent = new Event('change', { bubbles: true });
190                    $quantityBox.dispatchEvent(changeEvent);
191
192                    // Trigger change event.
193                    var update_cart_btn = document.getElementsByName("update_cart");
194                    if (update_cart_btn.length > 0) {
195                        for ( var btn = 0; btn < update_cart_btn.length; btn++ ) {
196                            update_cart_btn[btn].disabled = false;
197                            update_cart_btn[btn].click();
198                        }
199                    }
200
201                    const quantity = $quantityBox.value;
202                    const itemHash = $quantityBox.getAttribute('name').replace(/cart\[([\w]+)\]\[qty\]/g, '$1');
203
204                    sendAjaxQuantityRequest(ev.currentTarget, quantity, itemHash)
205
206                }, false);
207            }
208        }
209    }
210}
211
212
213function sendAjaxQuantityRequest(currentTarget, quantity, itemHash ) {
214
215    // Send AJAX request from mini cart.
216    const miniCart = currentTarget.closest( '.woocommerce-mini-cart' );
217
218    if ( miniCart && astra && astra.single_product_qty_ajax_nonce && astra.ajax_url ) {
219
220        let qtyNonce = astra.single_product_qty_ajax_nonce;
221
222        miniCart.classList.add('ajax-mini-cart-qty-loading');
223
224        // Creating a XMLHttpRequest object.
225        let xhrRequest = new XMLHttpRequest();
226        xhrRequest.open( 'POST', astra.ajax_url, true );
227
228        // Send the proper header information along with the request
229        xhrRequest.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
230
231        xhrRequest.send( 'action=astra_add_cart_single_product_quantity&hash=' + itemHash + '&quantity=' + quantity + '&qtyNonce=' + qtyNonce );
232
233        xhrRequest.onload = function () {
234            if ( xhrRequest.readyState == XMLHttpRequest.DONE ) {   // XMLHttpRequest.DONE == 4
235                if ( 200 <= xhrRequest.status || 400 <= xhrRequest.status ) {
236                    // Trigger event so themes can refresh other areas.
237                    var event = document.createEvent( 'HTMLEvents' );
238                    event.initEvent( 'wc_fragment_refresh', true, false );
239                    document.body.dispatchEvent(event);
240
241                    setTimeout(() => {
242                        miniCart.classList.remove('ajax-mini-cart-qty-loading');
243                    }, 500);
244
245
246                    if ( typeof wc_add_to_cart_params === 'undefined' ) {
247                        return;
248                    }
249                }
250            }
251        };
252    }
253
254}
255
256
257
258let typingTimer; //timer identifier
259let doneTypingInterval = 500;
260
261function quantityInput() {
262    const quantityInputContainer = document.querySelector('.woocommerce-mini-cart');
263
264    if( quantityInputContainer ) {
265        const quantityInput = document.querySelectorAll('.input-text.qty');
266
267        quantityInput.forEach( single => {
268            single.addEventListener('keyup', (e) => {
269                if ( e.key === 'Tab' || e.keyCode === 9 ) {
270                    return;
271                }
272                clearTimeout(typingTimer);
273                if (single.value) {
274                    typingTimer = setTimeout(() => {
275                        const quantity = e.target.value;
276                        const itemHash = e.target.getAttribute('name').replace(/cart\[([\w]+)\]\[qty\]/g, '$1');
277
278                        if( quantity ) {
279                            sendAjaxQuantityRequest(e.target, quantity,itemHash);
280                        }
281                    }, doneTypingInterval);
282                }
283            });
284        });
285    }
286}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.