PageSourceSearch

https://www.businessqualifications.com/wp-content/plugins/woocommerce/assets/js/frontend/cart.js?ver=6.3.2

js businessqualifications.com collected 2026-10-08 04:31:20 UTC 16,305 bytes, 620 lines download raw bytes

1/* global wc_cart_params */
2jQuery( function( $ ) {
3
4	// wc_cart_params is required to continue, ensure the object exists
5	if ( typeof wc_cart_params === 'undefined' ) {
6		return false;
7	}
8
9	// Utility functions for the file.
10
11	/**
12	 * Gets a url for a given AJAX endpoint.
13	 *
14	 * @param {String} endpoint The AJAX Endpoint
15	 * @return {String} The URL to use for the request
16	 */
17	var get_url = function( endpoint ) {
18		return wc_cart_params.wc_ajax_url.toString().replace(
19			'%%endpoint%%',
20			endpoint
21		);
22	};
23
24	/**
25	 * Check if a node is blocked for processing.
26	 *
27	 * @param {JQuery Object} $node
28	 * @return {bool} True if the DOM Element is UI Blocked, false if not.
29	 */
30	var is_blocked = function( $node ) {
31		return $node.is( '.processing' ) || $node.parents( '.processing' ).length;
32	};
33
34	/**
35	 * Block a node visually for processing.
36	 *
37	 * @param {JQuery Object} $node
38	 */
39	var block = function( $node ) {
40		if ( ! is_blocked( $node ) ) {
41			$node.addClass( 'processing' ).block( {
42				message: null,
43				overlayCSS: {
44					background: '#fff',
45					opacity: 0.6
46				}
47			} );
48		}
49	};
50
51	/**
52	 * Unblock a node after processing is complete.
53	 *
54	 * @param {JQuery Object} $node
55	 */
56	var unblock = function( $node ) {
57		$node.removeClass( 'processing' ).unblock();
58	};
59
60	/**
61	 * Removes duplicate notices.
62	 *
63	 * @param {JQuery Object} notices
64	 */
65	var remove_duplicate_notices = function( notices ) {
66		var seen = [];
67		var new_notices = notices;
68
69		notices.each( function( index ) {
70			var text = $( this ).text();
71
72			if ( 'undefined' === typeof seen[ text ] ) {
73				seen[ text ] = true;
74			} else {
75				new_notices.splice( index, 1 );
76			}
77		} );
78
79		return new_notices;
80	};
81
82	/**
83	 * Update the .woocommerce div with a string of html.
84	 *
85	 * @param {String} html_str The HTML string with which to replace the div.
86	 * @param {bool} preserve_notices Should notices be kept? False by default.
87	 */
88	var update_wc_div = function( html_str, preserve_notices ) {
89		var $html       = $.parseHTML( html_str );
90		var $new_form   = $( '.woocommerce-cart-form', $html );
91		var $new_totals = $( '.cart_totals', $html );
92		var $notices    = remove_duplicate_notices( $( '.woocommerce-error, .woocommerce-message, .woocommerce-info', $html ) );
93
94		// No form, cannot do this.
95		if ( $( '.woocommerce-cart-form' ).length === 0 ) {
96			window.location.reload();
97			return;
98		}
99
100		// Remove errors
101		if ( ! preserve_notices ) {
102			$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
103		}
104
105		if ( $new_form.length === 0 ) {
106			// If the checkout is also displayed on this page, trigger reload instead.
107			if ( $( '.woocommerce-checkout' ).length ) {
108				window.location.reload();
109				return;
110			}
111
112			// No items to display now! Replace all cart content.
113			var $cart_html = $( '.cart-empty', $html ).closest( '.woocommerce' );
114			$( '.woocommerce-cart-form__contents' ).closest( '.woocommerce' ).replaceWith( $cart_html );
115
116			// Display errors
117			if ( $notices.length > 0 ) {
118				show_notice( $notices );
119			}
120
121			// Notify plugins that the cart was emptied.
122			$( document.body ).trigger( 'wc_cart_emptied' );
123		} else {
124			// If the checkout is also displayed on this page, trigger update event.
125			if ( $( '.woocommerce-checkout' ).length ) {
126				$( document.body ).trigger( 'update_checkout' );
127			}
128
129			$( '.woocommerce-cart-form' ).replaceWith( $new_form );
130			$( '.woocommerce-cart-form' ).find( ':input[name="update_cart"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true );
131
132			if ( $notices.length > 0 ) {
133				show_notice( $notices );
134			}
135
136			update_cart_totals_div( $new_totals );
137		}
138
139		$( document.body ).trigger( 'updated_wc_div' );
140	};
141
142	/**
143	 * Update the .cart_totals div with a string of html.
144	 *
145	 * @param {String} html_str The HTML string with which to replace the div.
146	 */
147	var update_cart_totals_div = function( html_str ) {
148		$( '.cart_totals' ).replaceWith( html_str );
149		$( document.body ).trigger( 'updated_cart_totals' );
150	};
151
152	/**
153	 * Shows new notices on the page.
154	 *
155	 * @param {Object} The Notice HTML Element in string or object form.
156	 */
157	var show_notice = function( html_element, $target ) {
158		if ( ! $target ) {
159			$target = $( '.woocommerce-notices-wrapper:first' ) ||
160				$( '.cart-empty' ).closest( '.woocommerce' ) ||
161				$( '.woocommerce-cart-form' );
162		}
163		$target.prepend( html_element );
164	};
165
166
167	/**
168	 * Object to handle AJAX calls for cart shipping changes.
169	 */
170	var cart_shipping = {
171
172		/**
173		 * Initialize event handlers and UI state.
174		 */
175		init: function( cart ) {
176			this.cart                       = cart;
177			this.toggle_shipping            = this.toggle_shipping.bind( this );
178			this.shipping_method_selected   = this.shipping_method_selected.bind( this );
179			this.shipping_calculator_submit = this.shipping_calculator_submit.bind( this );
180
181			$( document ).on(
182				'click',
183				'.shipping-calculator-button',
184				this.toggle_shipping
185			);
186			$( document ).on(
187				'change',
188				'select.shipping_method, :input[name^=shipping_method]',
189				this.shipping_method_selected
190			);
191			$( document ).on(
192				'submit',
193				'form.woocommerce-shipping-calculator',
194				this.shipping_calculator_submit
195			);
196
197			$( '.shipping-calculator-form' ).hide();
198		},
199
200		/**
201		 * Toggle Shipping Calculator panel
202		 */
203		toggle_shipping: function() {
204			$( '.shipping-calculator-form' ).slideToggle( 'slow' );
205			$( 'select.country_to_state, input.country_to_state' ).trigger( 'change' );
206			$( document.body ).trigger( 'country_to_state_changed' ); // Trigger select2 to load.
207			return false;
208		},
209
210		/**
211		 * Handles when a shipping method is selected.
212		 */
213		shipping_method_selected: function() {
214			var shipping_methods = {};
215
216			// eslint-disable-next-line max-len
217			$( 'select.shipping_method, :input[name^=shipping_method][type=radio]:checked, :input[name^=shipping_method][type=hidden]' ).each( function() {
218				shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
219			} );
220
221			block( $( 'div.cart_totals' ) );
222
223			var data = {
224				security: wc_cart_params.update_shipping_method_nonce,
225				shipping_method: shipping_methods
226			};
227
228			$.ajax( {
229				type:     'post',
230				url:      get_url( 'update_shipping_method' ),
231				data:     data,
232				dataType: 'html',
233				success:  function( response ) {
234					update_cart_totals_div( response );
235				},
236				complete: function() {
237					unblock( $( 'div.cart_totals' ) );
238					$( document.body ).trigger( 'updated_shipping_method' );
239				}
240			} );
241		},
242
243		/**
244		 * Handles a shipping calculator form submit.
245		 *
246		 * @param {Object} evt The JQuery event.
247		 */
248		shipping_calculator_submit: function( evt ) {
249			evt.preventDefault();
250
251			var $form = $( evt.currentTarget );
252
253			block( $( 'div.cart_totals' ) );
254			block( $form );
255
256			// Provide the submit button value because wc-form-handler expects it.
257			$( '<input />' ).attr( 'type', 'hidden' )
258							.attr( 'name', 'calc_shipping' )
259							.attr( 'value', 'x' )
260							.appendTo( $form );
261
262			// Make call to actual form post URL.
263			$.ajax( {
264				type:     $form.attr( 'method' ),
265				url:      $form.attr( 'action' ),
266				data:     $form.serialize(),
267				dataType: 'html',
268				success:  function( response ) {
269					update_wc_div( response );
270				},
271				complete: function() {
272					unblock( $form );
273					unblock( $( 'div.cart_totals' ) );
274				}
275			} );
276		}
277	};
278
279	/**
280	 * Object to handle cart UI.
281	 */
282	var cart = {
283		/**
284		 * Initialize cart UI events.
285		 */
286		init: function() {
287			this.update_cart_totals    = this.update_cart_totals.bind( this );
288			this.input_keypress        = this.input_keypress.bind( this );
289			this.cart_submit           = this.cart_submit.bind( this );
290			this.submit_click          = this.submit_click.bind( this );
291			this.apply_coupon          = this.apply_coupon.bind( this );
292			this.remove_coupon_clicked = this.remove_coupon_clicked.bind( this );
293			this.quantity_update       = this.quantity_update.bind( this );
294			this.item_remove_clicked   = this.item_remove_clicked.bind( this );
295			this.item_restore_clicked  = this.item_restore_clicked.bind( this );
296			this.update_cart           = this.update_cart.bind( this );
297
298			$( document ).on(
299				'wc_update_cart added_to_cart',
300				function() { cart.update_cart.apply( cart, [].slice.call( arguments, 1 ) ); } );
301			$( document ).on(
302				'click',
303				'.woocommerce-cart-form :input[type=submit]',
304				this.submit_click );
305			$( document ).on(
306				'keypress',
307				'.woocommerce-cart-form :input[type=number]',
308				this.input_keypress );
309			$( document ).on(
310				'submit',
311				'.woocommerce-cart-form',
312				this.cart_submit );
313			$( document ).on(
314				'click',
315				'a.woocommerce-remove-coupon',
316				this.remove_coupon_clicked );
317			$( document ).on(
318				'click',
319				'.woocommerce-cart-form .product-remove > a',
320				this.item_remove_clicked );
321			$( document ).on(
322				'click',
323				'.woocommerce-cart .restore-item',
324				this.item_restore_clicked );
325			$( document ).on(
326				'change input',
327				'.woocommerce-cart-form .cart_item :input',
328				this.input_changed );
329
330			$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true );
331		},
332
333		/**
334		 * After an input is changed, enable the update cart button.
335		 */
336		input_changed: function() {
337			$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', false ).attr( 'aria-disabled', false );
338		},
339
340		/**
341		 * Update entire cart via ajax.
342		 */
343		update_cart: function( preserve_notices ) {
344			var $form = $( '.woocommerce-cart-form' );
345
346			block( $form );
347			block( $( 'div.cart_totals' ) );
348
349			// Make call to actual form post URL.
350			$.ajax( {
351				type:     $form.attr( 'method' ),
352				url:      $form.attr( 'action' ),
353				data:     $form.serialize(),
354				dataType: 'html',
355				success:  function( response ) {
356					update_wc_div( response, preserve_notices );
357				},
358				complete: function() {
359					unblock( $form );
360					unblock( $( 'div.cart_totals' ) );
361					$.scroll_to_notices( $( '[role="alert"]' ) );
362				}
363			} );
364		},
365
366		/**
367		 * Update the cart after something has changed.
368		 */
369		update_cart_totals: function() {
370			block( $( 'div.cart_totals' ) );
371
372			$.ajax( {
373				url:      get_url( 'get_cart_totals' ),
374				dataType: 'html',
375				success:  function( response ) {
376					update_cart_totals_div( response );
377				},
378				complete: function() {
379					unblock( $( 'div.cart_totals' ) );
380				}
381			} );
382		},
383
384		/**
385		 * Handle the <ENTER> key for quantity fields.
386		 *
387		 * @param {Object} evt The JQuery event
388		 *
389		 * For IE, if you hit enter on a quantity field, it makes the
390		 * document.activeElement the first submit button it finds.
391		 * For us, that is the Apply Coupon button. This is required
392		 * to catch the event before that happens.
393		 */
394		input_keypress: function( evt ) {
395
396			// Catch the enter key and don't let it submit the form.
397			if ( 13 === evt.keyCode ) {
398				var $form = $( evt.currentTarget ).parents( 'form' );
399
400				try {
401					// If there are no validation errors, handle the submit.
402					if ( $form[0].checkValidity() ) {
403						evt.preventDefault();
404						this.cart_submit( evt );
405					}
406				} catch( err ) {
407					evt.preventDefault();
408					this.cart_submit( evt );
409				}
410			}
411		},
412
413		/**
414		 * Handle cart form submit and route to correct logic.
415		 *
416		 * @param {Object} evt The JQuery event
417		 */
418		cart_submit: function( evt ) {
419			var $submit  = $( document.activeElement ),
420				$clicked = $( ':input[type=submit][clicked=true]' ),
421				$form    = $( evt.currentTarget );
422
423			// For submit events, currentTarget is form.
424			// For keypress events, currentTarget is input.
425			if ( ! $form.is( 'form' ) ) {
426				$form = $( evt.currentTarget ).parents( 'form' );
427			}
428
429			if ( 0 === $form.find( '.woocommerce-cart-form__contents' ).length ) {
430				return;
431			}
432
433			if ( is_blocked( $form ) ) {
434				return false;
435			}
436
437			if ( $clicked.is( ':input[name="update_cart"]' ) || $submit.is( 'input.qty' ) ) {
438				evt.preventDefault();
439				this.quantity_update( $form );
440
441			} else if ( $clicked.is( ':input[name="apply_coupon"]' ) || $submit.is( '#coupon_code' ) ) {
442				evt.preventDefault();
443				this.apply_coupon( $form );
444			}
445		},
446
447		/**
448		 * Special handling to identify which submit button was clicked.
449		 *
450		 * @param {Object} evt The JQuery event
451		 */
452		submit_click: function( evt ) {
453			$( ':input[type=submit]', $( evt.target ).parents( 'form' ) ).removeAttr( 'clicked' );
454			$( evt.target ).attr( 'clicked', 'true' );
455		},
456
457		/**
458		 * Apply Coupon code
459		 *
460		 * @param {JQuery Object} $form The cart form.
461		 */
462		apply_coupon: function( $form ) {
463			block( $form );
464
465			var cart = this;
466			var $text_field = $( '#coupon_code' );
467			var coupon_code = $text_field.val();
468
469			var data = {
470				security: wc_cart_params.apply_coupon_nonce,
471				coupon_code: coupon_code
472			};
473
474			$.ajax( {
475				type:     'POST',
476				url:      get_url( 'apply_coupon' ),
477				data:     data,
478				dataType: 'html',
479				success: function( response ) {
480					$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
481					show_notice( response );
482					$( document.body ).trigger( 'applied_coupon', [ coupon_code ] );
483				},
484				complete: function() {
485					unblock( $form );
486					$text_field.val( '' );
487					cart.update_cart( true );
488				}
489			} );
490		},
491
492		/**
493		 * Handle when a remove coupon link is clicked.
494		 *
495		 * @param {Object} evt The JQuery event
496		 */
497		remove_coupon_clicked: function( evt ) {
498			evt.preventDefault();
499
500			var cart     = this;
501			var $wrapper = $( evt.currentTarget ).closest( '.cart_totals' );
502			var coupon   = $( evt.currentTarget ).attr( 'data-coupon' );
503
504			block( $wrapper );
505
506			var data = {
507				security: wc_cart_params.remove_coupon_nonce,
508				coupon: coupon
509			};
510
511			$.ajax( {
512				type:    'POST',
513				url:      get_url( 'remove_coupon' ),
514				data:     data,
515				dataType: 'html',
516				success: function( response ) {
517					$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
518					show_notice( response );
519					$( document.body ).trigger( 'removed_coupon', [ coupon ] );
520					unblock( $wrapper );
521				},
522				complete: function() {
523					cart.update_cart( true );
524				}
525			} );
526		},
527
528		/**
529		 * Handle a cart Quantity Update
530		 *
531		 * @param {JQuery Object} $form The cart form.
532		 */
533		quantity_update: function( $form ) {
534			block( $form );
535			block( $( 'div.cart_totals' ) );
536
537			// Provide the submit button value because wc-form-handler expects it.
538			$( '<input />' ).attr( 'type', 'hidden' )
539							.attr( 'name', 'update_cart' )
540							.attr( 'value', 'Update Cart' )
541							.appendTo( $form );
542
543			// Make call to actual form post URL.
544			$.ajax( {
545				type:     $form.attr( 'method' ),
546				url:      $form.attr( 'action' ),
547				data:     $form.serialize(),
548				dataType: 'html',
549				success:  function( response ) {
550					update_wc_div( response );
551				},
552				complete: function() {
553					unblock( $form );
554					unblock( $( 'div.cart_totals' ) );
555					$.scroll_to_notices( $( '[role="alert"]' ) );
556				}
557			} );
558		},
559
560		/**
561		 * Handle when a remove item link is clicked.
562		 *
563		 * @param {Object} evt The JQuery event
564		 */
565		item_remove_clicked: function( evt ) {
566			evt.preventDefault();
567
568			var $a = $( evt.currentTarget );
569			var $form = $a.parents( 'form' );
570
571			block( $form );
572			block( $( 'div.cart_totals' ) );
573
574			$.ajax( {
575				type:     'GET',
576				url:      $a.attr( 'href' ),
577				dataType: 'html',
578				success:  function( response ) {
579					update_wc_div( response );
580				},
581				complete: function() {
582					unblock( $form );
583					unblock( $( 'div.cart_totals' ) );
584					$.scroll_to_notices( $( '[role="alert"]' ) );
585				}
586			} );
587		},
588
589		/**
590		 * Handle when a restore item link is clicked.
591		 *
592		 * @param {Object} evt The JQuery event
593		 */
594		item_restore_clicked: function( evt ) {
595			evt.preventDefault();
596
597			var $a = $( evt.currentTarget );
598			var $form = $( 'form.woocommerce-cart-form' );
599
600			block( $form );
601			block( $( 'div.cart_totals' ) );
602
603			$.ajax( {
604				type:     'GET',
605				url:      $a.attr( 'href' ),
606				dataType: 'html',
607				success:  function( response ) {
608					update_wc_div( response );
609				},
610				complete: function() {
611					unblock( $form );
612					unblock( $( 'div.cart_totals' ) );
613				}
614			} );
615		}
616	};
617
618	cart_shipping.init( cart );
619	cart.init();
620} );

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.