1/** 2 * BOGO public side JS file. 3 * Free product selection functionality. 4 * 5 * @since 3.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 var attributes = {}; 18 var 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 const coupon_id = parent.closest( '.wbte_sc_bogo_products' ).attr( 'coupon' ); 25 26 if ( "" == $( this ).val() ) { 27 parent.find( 'input[name="variation_id"]' ).val( 0 ); 28 parent.find( 'input[name="wt_variation_options"]' ).val( JSON.stringify( attributes ) ); 29 return false; 30 } 31 32 var stop_checking = false; 33 $.each( 34 attributes, 35 function ( key, value ) { 36 if ( value == '' ) { 37 stop_checking = true; 38 return false; 39 } 40 } 41 ); 42 if ( stop_checking ) { /** Not every attributes selected. */ 43 return; 44 } 45 46 var product_id = parent.attr( 'product-id' ); 47 48 var data = { 49 'attributes' : attributes, 50 'product' : product_id, 51 '_wpnonce' : WTSmartCouponOBJ.nonces.public, 52 'coupon_id' : coupon_id 53 }; 54 55 $( '.wbte_sc_bogo_add_to_cart, .checkout-button, .wbte_sc_bogo_proceed_checkout' ).prop( 'disabled', true ).css( {'opacity':.5, 'cursor':'not-allowed'} ); 56 jQuery.ajax( 57 { 58 type: "POST", 59 async: true, 60 url: WTSmartCouponOBJ.wc_ajax_url + 'update_variation_id_on_choose', 61 data: data, 62 dataType: 'json', 63 success:function (response) { 64 const productList = parent.closest( '.wbte_sc_bogo_products' ); 65 if ( true === response.status ) { 66 parent.find( 'input[name="variation_id"]' ).val( response.variation_id ); 67 parent.find( 'input[name="wt_variation_options"]' ).val( JSON.stringify( attributes ) ); 68 parent.find('.wbte_sc_bogo_variation_error').remove(); 69 wbteScUpdateSelectedCount( productList ); 70 if ( response.img_url && '' !== response.img_url ) { 71 parent.find( '.wbte_product_image img' ).attr( 'src', response.img_url ); 72 } 73 if ( response.price && '' !== response.price && response.discount && '' !== response.discount ) { 74 parent.find( '.wbte_sc_bogo_product_price' ).html( response.price ); 75 parent.find( '.wbte_sc_bogo_product_discount_price' ).html( response.price - response.discount ); 76 } 77 if ( response.discount && '' !== response.discount ) { 78 parent.find( '.wbte_sc_bogo_product_discount_price' ).html( response.discount ); 79 } 80 } else { 81 wbteScUpdateSelectedCount( productList ); 82 parent.find( 'input[name="variation_id"]' ).val( 0 ); 83 84 if (false !== response.status_msg && "" !== response.status_msg.trim()) { /* check message was disabled or not */ 85 alert( response.status_msg ); 86 } 87 } 88 }, 89 error:function () { 90 parent.find( 'input[name="variation_id"]' ).val( 0 ); 91 $( '.wbte_sc_bogo_add_to_cart, .checkout-button, .wbte_sc_bogo_proceed_checkout' ).prop( 'disabled', false ).css( {'opacity':1, 'cursor':'pointer'} ); 92 $( '.wbte_get_away_product' ).css( {'opacity':1, 'cursor':'default'} ); 93 alert( WTSmartCouponOBJ.labels.error ); 94 } 95 } 96 ); 97 } 98 ); 99 100 $( document ).ready( function() { 101 /** Show popup when clicking the button */ 102 $( document ).on( 'click', '.wbte_sc_bogo_popup_btn', function( e ) { 103 e.preventDefault(); 104 $( '.wbte_sc_giveaway_popup' ).fadeIn( 300 ); 105 $( 'body' ).addClass( 'wbte_sc_popup_open' ); 106 } ); 107 108 /** Close popup when clicking outside */ 109 $( document ).on( 'click', '.wbte_sc_giveaway_popup', function( e ) { 110 if ( $( e.target ).hasClass( 'wbte_sc_giveaway_popup' ) ) { 111 $( '.wbte_sc_giveaway_popup' ).fadeOut( 300 ); 112 $( 'body' ).removeClass( 'wbte_sc_popup_open' ); 113 } 114 } ); 115 116 /** Close popup when clicking close button */ 117 $( document ).on( 'click', '.wbte_sc_giveaway_popup_close', function( e ) { 118 e.preventDefault(); 119 $( '.wbte_sc_giveaway_popup' ).fadeOut( 300 ); 120 $( 'body' ).removeClass( 'wbte_sc_popup_open' ); 121 } ); 122 123 /** Handle product selection */ 124 $( document ).on( 'click', '.wbte_get_away_product', function( e ) { 125 if ( $( e.target ).is( 'select, input, option' ) || $( e.target ).closest( 'select, input' ).length ) { 126 return; 127 } 128 129 const parent = $( this ); 130 const productList = parent.closest( '.wbte_sc_bogo_products' ); 131 const isAnyCondition = 'any' === productList.data( 'condition' ); 132 const totalQty = Number.parseInt( productList.closest( '.wbte_sc_bogo_giveaway_products_container' ).find( '.giveaway-title' ).attr( 'data-total-qty' ) ); 133 134 if ( '1' === parent.attr( 'data-is_purchasable' ) ) { 135 const currentSelectedQty = wbteScGetSelectedQuantityTotal( productList ); 136 137 if ( ! parent.hasClass( 'selected' ) ) { 138 if ( currentSelectedQty >= totalQty ) { 139 return; 140 } 141
142 parent.find( 'input[name="wbte_sc_bogo_quantity"]' ).val( 1 ); 143 144 if ( isAnyCondition ) { 145 /** For 'any' condition, deselect any previously selected product */ 146 productList.find( '.wbte_get_away_product.selected' ).each( function() { 147 $( this ).removeClass( 'selected' ); 148 } ); 149 150 parent.find( 'input[name="wbte_sc_bogo_quantity"]' ).val( totalQty ); 151 } 152 153 if ( 0 < parent.attr( 'data-free-qty-on-select' ) ) { 154 parent.find( 'input[name="wbte_sc_bogo_quantity"]' ).val( parent.attr( 'data-free-qty-on-select' ) ); 155 } 156 157 } 158 159 parent.toggleClass( 'selected' ); 160 161 const variation_id = parent.find( '[name="variation_id"]' ).val() || 0; 162 if ( 0 < parent.find( '.wbte_give_away_product_attr' ).length && ( '' === variation_id || '0' === variation_id ) ) { 163 164 parent.find( '.wbte_sc_bogo_variation_error' ).remove(); 165 166 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>'; 167 parent.find( '.wt_variations' ).after( errorHtml ); 168 } 169 170 if ( ! parent.hasClass( 'selected' ) ) { 171 parent.find( '.wbte_sc_bogo_variation_error' ).remove(); 172 } 173 174 updateDisabledState( productList, isAnyCondition ); 175 wbteScUpdateSelectedCount( productList ); 176 } 177 } ); 178 179 /** Handle quantity change */ 180 $( document ).on( 'change', 'input[name="wbte_sc_bogo_quantity"]', function() { 181 const input = $( this ); 182 const parent = input.closest( '.wbte_get_away_product' ); 183 const productList = parent.closest( '.wbte_sc_bogo_products' ); 184 const totalQty = Number.parseInt( productList.closest( '.wbte_sc_bogo_giveaway_products_container' ) 185 .find( '.giveaway-title' ).attr( 'data-total-qty' ) ); 186 187 let newQty = Number.parseInt( input.val() ) || 0; 188 const maxQty = Number.parseInt( input.attr( 'max' ) ) || 0; 189 190 /** First ensure we don't exceed individual product's max quantity */ 191 if ( newQty > maxQty ) { 192 newQty = maxQty; 193 input.val( newQty ); 194 } 195 196 /** Calculate total quantity excluding current product's quantity completely */ 197 let otherProductsQty = 0; 198 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() { 199 otherProductsQty += Number.parseInt( $( this ).val() ) || 0; 200 } ); 201 202 /** Ensure total quantity doesn't exceed limit */ 203 if ( ( otherProductsQty + newQty ) > totalQty ) { 204 newQty = totalQty - otherProductsQty; 205 input.val( newQty ); 206 } 207 208 /** Update selected state based on quantity */ 209 parent.toggleClass( 'selected', newQty > 0 ); 210 211 updateDisabledState( productList, 'any' === productList.data( 'condition' ) ); 212 wbteScUpdateSelectedCount( productList ); 213 } ); 214 215 function updateDisabledState( productList, isAnyCondition ) { 216 const totalQty = Number.parseInt( productList.closest( '.wbte_sc_bogo_giveaway_products_container' ) 217 .find( '.giveaway-title' ).attr( 'data-total-qty' ) ); 218 const currentQty = wbteScGetSelectedQuantityTotal( productList ); 219 220 productList.find( '.wbte_get_away_product' ).each( function() { 221 const product = $( this ); 222 if ( ! product.hasClass( 'selected' ) ) { 223 if ( isAnyCondition && 0 < productList.find( '.selected' ).length ) { 224 product.addClass( 'disabled' ); 225 } else { 226 product.toggleClass( 'disabled', currentQty >= totalQty ); 227 } 228 } 229 } ); 230 } 231 232 /** When adding product from details page, because of reload, the popup is not shown. */ 233 $('form.cart').on('submit', function() { 234 if( ! WTSmartCouponOBJ?.bogo_popup_ajax_required ) return; 235 sessionStorage.setItem( 'wbte_sc_bogo_shop_form_submitted', true ); 236 }); 237 238 /** Update popup visibility when cart changes */ 239 $( document.body ).on( 'added_to_cart removed_from_cart wc_fragments_refreshed', function() { 240 241 if( ! WTSmartCouponOBJ?.bogo_popup_ajax_required ) return; 242 243 let applied_bogo_coupons = WTSmartCouponOBJ.applied_bogo_coupons; 244 $.ajax( { 245 url: WTSmartCouponOBJ.wc_ajax_url + 'wbte_sc_show_bogo_popup', 246 type: 'POST', 247 data: { 248 _wpnonce: WTSmartCouponOBJ.nonces.public 249 }, 250 success: function( response ) { 251 if ( response.has_free_products ) { 252 if ( $( '.wbte_sc_giveaway_popup' ).length ) { 253 $( '.wbte_sc_giveaway_popup, .wbte_sc_bogo_popup_btn' ).remove(); 254 } 255 $( 'body' ).append( response.button_html ); 256 257 let new_applied_bogo_coupons = response.applied_bogo_coupons; 258 259 if ( 260 ( Object.keys( applied_bogo_coupons ).length !== Object.keys( new_applied_bogo_coupons ).length ) 261 || ( sessionStorage.getItem( 'wbte_sc_bogo_shop_form_submitted' ) && Object.keys( new_applied_bogo_coupons ).length > 0 ) 262 ) { 263 264 wbte_sc_show_notice_on_popup( new_applied_bogo_coupons, applied_bogo_coupons, response.apply_msg ); 265 266 $( '.wbte_sc_bogo_popup_btn' ).trigger( 'click' ); 267 } 268 WTSmartCouponOBJ.applied_bogo_coupons = new_applied_bogo_coupons; 269 } else { 270 $( '.wbte_sc_giveaway_popup, .wbte_sc_bogo_popup_btn' ).remove(); 271 } 272 sessionStorage.removeItem( 'wbte_sc_bogo_shop_form_submitted' ); 273 } 274 } ); 275 } ); 276 } ); 277 278 /** Add this handler after the existing click handlers */ 279 $( document ).on( 'click', '.wbte_sc_bogo_add_to_cart, .wbte_sc_bogo_proceed_checkout', function( e ) { 280 e.preventDefault(); 281 282 const productList = $( '.wbte_sc_bogo_products' ); 283 const selectedProducts = productList.find( '.wbte_get_away_product.selected' ); 284 const proceedCheckout = $( this ).hasClass( 'wbte_sc_bogo_proceed_checkout' ); 285 286 if ( 0 === selectedProducts.length ) { 287 return; 288 } 289 290 let hasError = false;
291 const products = []; 292 293 $( '.wbte_sc_bogo_variation_error' ).remove(); 294 295 selectedProducts.each( function() { 296 const parent_obj = $( this ); 297 298 /** Check if product is purchasable */ 299 if ( '1' !== parent_obj.attr( 'data-is_purchasable' ) ) { 300 return; 301 } 302 303 /** Handle variation if exists */ 304 let variation_id = 0; 305 const variation_id_obj = parent_obj.find( '[name="variation_id"]' ); 306 if ( 0 < variation_id_obj.length ) { 307 if ( '' === variation_id_obj.val().trim() || '0' === variation_id_obj.val().trim() ) { 308 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>'; 309 parent_obj.find( '.wt_variations' ).after( errorHtml ); 310 hasError = true; 311 return false; 312 } 313 variation_id = variation_id_obj.val(); 314 } 315 316 const coupon_id = parent_obj.closest( '.wbte_sc_bogo_products' ).attr( 'coupon' ); 317 const product_id = parent_obj.attr( 'product-id' ); 318 const free_qty = parent_obj.find( 'input[name="wbte_sc_bogo_quantity"]' ).val(); 319 const triggered_item_key = parent_obj.attr( 'data-triggered-item-key' ); 320 const variation_attributes = parent_obj.find( 'input[name="wt_variation_options"]' ).length > 0 321 ? JSON.parse( parent_obj.find( 'input[name="wt_variation_options"]' ).val() ) 322 : ''; 323 324 if ( free_qty > 0 ) { 325 products.push( { 326 'product_id': product_id, 327 'variation_id': variation_id, 328 'attributes': variation_attributes, 329 'coupon_id': coupon_id, 330 'free_qty': free_qty, 331 'triggered_item_key': triggered_item_key 332 } ); 333 } 334 } ); 335 336 if ( hasError || 0 === products.length ) { 337 return; 338 } 339 340 const data = { 341 '_wpnonce': WTSmartCouponOBJ.nonces.public, 342 'products': products 343 }; 344 345 var html_back = $( this ).html(); 346 $( this ).html( WTSmartCouponOBJ.labels.please_wait ); 347 348 var all_btn_elms = $( '.wbte_sc_bogo_add_to_cart, .wbte_sc_bogo_proceed_checkout' ); 349 all_btn_elms.prop( 'disabled', true ); 350 351 if ( ! $( '.woocommerce-notices-wrapper' ).length ) { 352 $( '#main' ).prepend( '<div class="woocommerce-notices-wrapper"></div>' ); 353 } 354 355 $( '.woocommerce-notices-wrapper' ).html( '' ); 356 357 jQuery.ajax( { 358 type: 'POST', 359 async: true, 360 url: WTSmartCouponOBJ.wc_ajax_url + 'wbte_choose_multiple_free_products', 361 data: data, 362 success: function( response ) { 363 if ( response ) { 364 if ( proceedCheckout ) { 365 globalThis.location.href = WTSmartCouponOBJ.checkout_url; 366 } else { 367 location.reload(); 368 } 369 } else { 370 $( '.woocommerce-notices-wrapper' ).html( response ); 371 $( 'html, body' ).stop( true, true ).animate( { scrollTop: ( $( '.woocommerce-notices-wrapper' ).offset().top - 70 ) }, 500 ); 372 373 $( this ).html( html_back ); 374 all_btn_elms.prop( 'disabled', false ); 375 } 376 }, 377 error: function() { 378 $( this ).html( html_back ); 379 all_btn_elms.prop( 'disabled', false ); 380 alert( WTSmartCouponOBJ.labels.error ); 381 } 382 } ); 383 } ); 384 } 385); 386 387/** Update selected count */ 388const wbteScUpdateSelectedCount = ( function($){ 389 return function( productList ){ 390 const selectedQty = wbteScGetSelectedQuantityTotal( productList ); 391 const qtySpan = productList.closest( '.wbte_sc_bogo_giveaway_products_container' ) 392 .find( '.wbte_sc_bogo_products_selected_qty' ); 393 394 qtySpan.text( selectedQty ); 395 396 /** Disable/enable buttons based on selection */ 397 let totalSelectedQty = 0; 398 $( '.wbte_sc_bogo_products .wbte_get_away_product.selected' ).each( function() { 399 totalSelectedQty += Number.parseInt( $( this ).find( 'input[name="wbte_sc_bogo_quantity"]' ).val() ) || 0; 400 } ); 401 const buttons = $( '.wbte_sc_bogo_add_to_cart, .wbte_sc_bogo_proceed_checkout' ); 402 if ( totalSelectedQty > 0 && 0 === $( '.wbte_sc_bogo_variation_error' ).length ) { 403 buttons.prop( 'disabled', false ).css( { 'opacity': 1, 'cursor': 'pointer' } ); 404 } else { 405 buttons.prop( 'disabled', true ).css( { 'opacity': 0.5, 'cursor': 'not-allowed' } ); 406 } 407 } 408} )(jQuery); 409 410/** Calculate total selected quantity */ 411const wbteScGetSelectedQuantityTotal = ( function($){ 412 return function( productList ){ 413 let total = 0;
414 productList.find( 'input[name="wbte_sc_bogo_quantity"]' ).closest( '.wbte_get_away_product.selected' ).find( 'input[name="wbte_sc_bogo_quantity"]' ).each( function() { 415 total += Number.parseInt( $( this ).val() ) || 0; 416 } ); 417 return total; 418 } 419} )(jQuery); 420 421const wbte_sc_get_notice_for_popup = ( function($){ 422 return function( bogo_name, apply_msg ){ 423 const applied_notice = '<div class="wc-block-components-notice-banner is-info" role="status">' + 424 '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">' + 425 '<path d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z"></path>' + 426 '</svg>' + 427 '<div class="wc-block-components-notice-banner__content">' + 428 apply_msg + 429 '</div>' + 430 '</div>'; 431 432 return applied_notice.replace( '{bogo_title}', bogo_name ); 433 } 434} )(jQuery); 435 436const wbte_sc_show_notice_on_popup = ( function($){ 437 return function( new_applied_bogo_coupons, applied_bogo_coupons, bogo_apply_msg ){ 438 let popup_coupons = {}; 439 440 for ( const key of Object.keys( new_applied_bogo_coupons ) ) { 441 if ( ! ( key in applied_bogo_coupons ) ) { 442 popup_coupons[ key ] = new_applied_bogo_coupons[ key ]; 443 } 444 } 445 446 for ( const key of Object.keys( popup_coupons ) ) { 447 let notice = wbte_sc_get_notice_for_popup( popup_coupons[ key ], bogo_apply_msg ); 448 $('.wbte_sc_giveaway_popup_body ul.wbte_sc_bogo_products[coupon="' + key + '"]').before(notice); 449 } 450 451 $( '.wbte_sc_giveaway_popup_content .wc-block-components-notice-banner' ).attr( 'style', 'padding: 10px !important' ); 452 } 453} )(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.