PageSourceSearch

https://metonymypress.com/wp-content/plugins/wt-smart-coupons-for-…/bogo-public/assets/script.js?ver=2.3.2

js metonymypress.com collected 2026-09-25 23:44:22 UTC 12,672 bytes, 346 lines download raw bytes

1/**
2 * BOGO public side JS file.
3 * Free product selection functionality.
4 *
5 * @since 2.0.0
6 * @package Wt_Smart_Coupon
7 */
8
9jQuery(
10	function ($) {
11		"use strict";
12
13		$( document ).on(
14			'change',
15			'.wbte_give_away_product_attr',
16			function () {
17				let attributes = {};
18				const parent     = $( this ).closest( '.wbte_get_away_product' );
19				parent.find( '.wbte_give_away_product_attr' ).each(
20					function (index) {
21						attributes[$( this ).attr( 'data-attribute_name' )] = $( this ).val();
22					}
23				);
24
25				const coupon_id = parent.closest( '.wbte_sc_bogo_products' ).attr( 'coupon' );
26
27				if ( "" == $( this ).val() ) {
28					parent.find( 'input[name="variation_id"]' ).val( 0 );
29					parent.find( 'input[name="wt_variation_options"]' ).val( JSON.stringify( attributes ) );
30					return false;
31				}
32
33				let stop_checking = false;
34				$.each(
35					attributes,
36					function ( key, value ) {
37						if ( '' === value ) {
38							stop_checking = true;
39							return false;
40						}
41					}
42				);
43				if ( stop_checking ) { /** Not every attributes selected. */
44					return;
45				}
46
47				const product_id = parent.attr( 'product-id' );
48
49				const data = {
50					'attributes'    : attributes,
51					'product'       : product_id,
52					'_wpnonce'      : WTSmartCouponOBJ.nonces.public,
53					'coupon_id'     : coupon_id
54				};
55
56				$( '.wbte_sc_bogo_add_to_cart, .checkout-button' ).prop( 'disabled', true ).css( {'opacity':.5, 'cursor':'not-allowed'} );
57				jQuery.ajax(
58					{
59						type: "POST",
60						async: true,
61						url: WTSmartCouponOBJ.wc_ajax_url + 'update_variation_id_on_choose',
62						data: data,
63						dataType: 'json',
64						success:function (response) {
65							const productList = parent.closest( '.wbte_sc_bogo_products' );
66							if ( true === response.status ) {
67								parent.find( 'input[name="variation_id"]' ).val( response.variation_id );
68								parent.find( 'input[name="wt_variation_options"]' ).val( JSON.stringify( attributes ) );
69								parent.find('.wbte_sc_bogo_variation_error').remove();
70								wbteScUpdateSelectedCount( productList );
71								if ( response.img_url && '' !== response.img_url ) {
72									parent.find( '.wbte_product_image img' ).attr( 'src', response.img_url );
73								}
74								if ( response.price && '' !== response.price && response.discount && '' !== response.discount ) {
75									parent.find( '.wbte_sc_bogo_product_price' ).html( response.price );
76									parent.find( '.wbte_sc_bogo_product_discount_price' ).html( response.price - response.discount );
77								}
78								if ( response.discount && '' !== response.discount ) {
79									parent.find( '.wbte_sc_bogo_product_discount_price' ).html( response.discount );
80								}
81							} else {
82								wbteScUpdateSelectedCount( productList );
83								parent.find( 'input[name="variation_id"]' ).val( 0 );
84
85								if (false !== response.status_msg && "" !== response.status_msg.trim()) { /* check message was disabled or not */
86									alert( response.status_msg );
87								}
88							}
89						},
90						error:function () {
91							parent.find( 'input[name="variation_id"]' ).val( 0 );
92							$( '.wbte_sc_bogo_add_to_cart, .checkout-button' ).prop( 'disabled', false ).css( {'opacity':1, 'cursor':'pointer'} );
93							$( '.wbte_get_away_product' ).css( {'opacity':1, 'cursor':'default'} );
94							alert( WTSmartCouponOBJ.labels.error );
95						}
96					}
97				);
98			}
99		);
100
101		$( document ).ready( function() {
102
103			/** Handle product selection */
104			$( document ).on( 'click', '.wbte_get_away_product', function( e ) {
105				if ( $( e.target ).is( 'select, input, option' ) || $( e.target ).closest( 'select, input' ).length ) {
106					return;
107				}
108				
109				const parent = $( this );
110				const productList = parent.closest( '.wbte_sc_bogo_products' );
111				const isAnyCondition = 'any' === productList.data( 'condition' );
112				const totalQty = Number.parseInt( productList.closest( '.wbte_sc_bogo_giveaway_products_container' ).find( '.giveaway-title' ).attr( 'data-total-qty' ) );
113				
114				if ( '1' === parent.attr( 'data-is_purchasable' ) ) {
115					const currentSelectedQty = wbteScGetSelectedQuantityTotal( productList );
116					
117					if ( ! parent.hasClass( 'selected' ) ) {
118						if ( currentSelectedQty >= totalQty ) {
119							return; 
120						}
121						
122						parent.find( 'input[name="wbte_sc_bogo_quantity"]' ).val( 1 );
123
124						if ( isAnyCondition ) {
125							/** For 'any' condition, deselect any previously selected product */
126							productList.find( '.wbte_get_away_product.selected' ).each( function() {
127								$( this ).removeClass( 'selected' );
128							} );
129
130							parent.find( 'input[name="wbte_sc_bogo_quantity"]' ).val( totalQty );
131						}
132
133						if ( 0 < parent.attr( 'data-free-qty-on-select' ) ) {
134							parent.find( 'input[name="wbte_sc_bogo_quantity"]' ).val( parent.attr( 'data-free-qty-on-select' ) );
135						}
136					}
137					
138					parent.toggleClass( 'selected' );
139
140					const variation_id = parent.find( '[name="variation_id"]' ).val() || 0;
141					if ( 0 < parent.find( '.wbte_give_away_product_attr' ).length && ( '' === variation_id || '0' === variation_id ) ) {
142						
143						parent.find( '.wbte_sc_bogo_variation_error' ).remove();
144						
145						const errorHtml = '<div class="wbte_sc_bogo_variation_error" style="color: #dc3545; margin-top: 10px;"><i class="fas fa-exclamation-circle"></i> ' + WTSmartCouponOBJ.labels.choose_variation + '</div>';
146						parent.find( '.wt_variations' ).after( errorHtml );
147					}
148					
149					if ( ! parent.hasClass( 'selected' ) ) {
150						parent.find( '.wbte_sc_bogo_variation_error' ).remove();
151					}
152					
153					updateDisabledState( productList, isAnyCondition );
154					wbteScUpdateSelectedCount( productList );
155				}
156			} );
157
158			/** Handle quantity change */
159			$( document ).on( 'change', 'input[name="wbte_sc_bogo_quantity"]', function() {
160				const input = $( this );
161				const parent = input.closest( '.wbte_get_away_product' );
162				const productList = parent.closest( '.wbte_sc_bogo_products' );
163				const totalQty = Number.parseInt( productList.closest( '.wbte_sc_bogo_giveaway_products_container' )
164					.find( '.giveaway-title' ).attr( 'data-total-qty' ) );
165				
166				let newQty = Number.parseInt( input.val() ) || 0;
167				const maxQty = Number.parseInt( input.attr( 'max' ) ) || 0;
168				
169				/** First ensure we don't exceed individual product's max quantity */
170				if ( newQty > maxQty ) {
171					newQty = maxQty;
172					input.val( newQty );
173				}
174				
175				/** Calculate total quantity excluding current product's quantity completely */
176				let otherProductsQty = 0;
177				productList.find( 'input[name="wbte_sc_bogo_quantity"]' ).closest( '.wbte_get_away_product.selected' ).find( 'input[name="wbte_sc_bogo_quantity"]' ).not( input ).each( function() {
178					otherProductsQty += Number.parseInt( $( this ).val() ) || 0;
179				} );
180				
181				/** Ensure total quantity doesn't exceed limit */
182				if ( ( otherProductsQty + newQty ) > totalQty ) {
183					newQty = totalQty - otherProductsQty;
184					input.val( newQty );
185				}
186				
187				/** Update selected state based on quantity */
188				parent.toggleClass( 'selected', newQty > 0 );
189				
190				updateDisabledState( productList, 'any' === productList.data( 'condition' ) );
191				wbteScUpdateSelectedCount( productList );
192			} );
193
194			function updateDisabledState( productList, isAnyCondition ) {
195				const totalQty = Number.parseInt( productList.closest( '.wbte_sc_bogo_giveaway_products_container' )
196					.find( '.giveaway-title' ).attr( 'data-total-qty' ) );
197				const currentQty = wbteScGetSelectedQuantityTotal( productList );
198				
199				productList.find( '.wbte_get_away_product' ).each( function() {
200					const product = $( this );
201					if ( ! product.hasClass( 'selected' ) ) {
202						if ( isAnyCondition && 0 < productList.find( '.selected' ).length ) {
203							product.addClass( 'disabled' );
204						} else {
205							product.toggleClass( 'disabled', currentQty >= totalQty );
206						}
207					}
208				} );
209			}
210
211			/** Add this handler after the existing click handlers */
212			$( document ).on( 'click', '.wbte_sc_bogo_add_to_cart', function( e ) {
213				e.preventDefault();
214				
215				const productList = $( '.wbte_sc_bogo_products' );
216				const selectedProducts = productList.find( '.wbte_get_away_product.selected' );
217				
218				if ( 0 === selectedProducts.length ) {
219					return;
220				}
221
222				let hasError = false;
223				const products = [];
224
225				$( '.wbte_sc_bogo_variation_error' ).remove();
226
227				selectedProducts.each( function() {
228					const parent_obj = $( this );
229					
230					/** Check if product is purchasable */
231					if ( '1' !== parent_obj.attr( 'data-is_purchasable' ) ) {
232						return;
233					}
234
235					/** Handle variation if exists */
236					let variation_id = 0;
237					const variation_id_obj = parent_obj.find( '[name="variation_id"]' );
238					if ( 0 < variation_id_obj.length ) {
239						if ( '' === variation_id_obj.val().trim() || '0' === variation_id_obj.val().trim() ) {
240							const errorHtml = '<div class="wbte_sc_bogo_variation_error" style="color: #dc3545; margin-top: 10px;"><i class="fas fa-exclamation-circle"></i> ' + WTSmartCouponOBJ.labels.choose_variation + '</div>';
241							parent_obj.find( '.wt_variations' ).after( errorHtml );
242							hasError = true;
243							return false;
244						}
245						variation_id = variation_id_obj.val();
246					}
247
248					const coupon_id  = parent_obj.closest( '.wbte_sc_bogo_products' ).attr( 'coupon' );
249					const product_id = parent_obj.attr( 'product-id' );
250					const free_qty   = parent_obj.find( 'input[name="wbte_sc_bogo_quantity"]' ).val() || 1;
251					const variation_attributes = parent_obj.find( 'input[name="wt_variation_options"]' ).length > 0 
252						? JSON.parse( parent_obj.find( 'input[name="wt_variation_options"]' ).val() ) 
253						: '';
254
255					if ( free_qty > 0 ) {
256						products.push( {
257							'product_id'  : product_id,
258							'variation_id': variation_id,
259							'attributes'  : variation_attributes,
260							'coupon_id'   : coupon_id,
261							'free_qty'    : free_qty
262						} );
263					}
264				} );
265
266				if ( hasError || 0 === products.length ) {
267					return;
268				}
269
270				const data = {
271					'_wpnonce': WTSmartCouponOBJ.nonces.public,
272					'products': products
273				};
274
275				const html_back = $( this ).html();
276				$( this ).html( WTSmartCouponOBJ.labels.please_wait );
277
278				const all_btn_elm = $( '.wbte_sc_bogo_add_to_cart' );
279				all_btn_elm.prop( 'disabled', true );
280
281				if ( ! $( '.woocommerce-notices-wrapper' ).length ) {
282					$( '#main' ).prepend( '<div class="woocommerce-notices-wrapper"></div>' );
283				}
284
285				$( '.woocommerce-notices-wrapper' ).html( '' );
286
287				jQuery.ajax( {
288					type: 'POST',
289					async: true,
290					url: WTSmartCouponOBJ.wc_ajax_url + 'wbte_choose_multiple_free_products',
291					data: data,
292					success: function( response ) {
293						if ( response ) {
294							globalThis.location.replace(globalThis.location.href.split('#')[0]);
295						} else {
296							$( '.woocommerce-notices-wrapper' ).html( response );
297							$( 'html, body' ).stop( true, true ).animate( { scrollTop: ( $( '.woocommerce-notices-wrapper' ).offset().top - 70 ) }, 500 );
298
299							$( this ).html( html_back );
300							all_btn_elm.prop( 'disabled', false );
301						}
302					},
303					error: function() {
304						$( this ).html( html_back );
305						all_btn_elm.prop( 'disabled', false );
306						alert( WTSmartCouponOBJ.labels.error );
307					}
308				} );
309			} );
310		} );
311	}
312);
313
314/** Update selected count */
315const wbteScUpdateSelectedCount = ( function($){
316	return function( productList ){
317		const selectedQty = wbteScGetSelectedQuantityTotal( productList );
318		const qtySpan = productList.closest( '.wbte_sc_bogo_giveaway_products_container' )
319			.find( '.wbte_sc_bogo_products_selected_qty' );
320		
321		qtySpan.text( selectedQty );
322
323		/** Disable/enable buttons based on selection */
324		let totalSelectedQty = 0;
325		$( '.wbte_sc_bogo_products .wbte_get_away_product.selected' ).each( function() {
326			totalSelectedQty += Number.parseInt( $( this ).find( 'input[name="wbte_sc_bogo_quantity"]' ).val() ) || 0;
327		} );
328		const button = $( '.wbte_sc_bogo_add_to_cart' );
329		if ( totalSelectedQty > 0 && 0 === $( '.wbte_sc_bogo_variation_error' ).length ) {
330			button.prop( 'disabled', false ).css( { 'opacity': 1, 'cursor': 'pointer' } );
331		} else {
332			button.prop( 'disabled', true ).css( { 'opacity': 0.5, 'cursor': 'not-allowed' } );
333		}
334	}
335} )(jQuery);
336
337/** Calculate total selected quantity */
338const wbteScGetSelectedQuantityTotal = ( function($){
339	return function( productList ){
340		let total = 0;
341		productList.find( 'input[name="wbte_sc_bogo_quantity"]' ).closest( '.wbte_get_away_product.selected' ).find( 'input[name="wbte_sc_bogo_quantity"]' ).each( function() {
342			total += Number.parseInt( $( this ).val() ) || 0;
343		} );
344		return total;
345	}
346} )(jQuery);

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.