1jQuery(document).ready(function ($) { 2 3 /** 4 * WordPress hooks API (WCPA add-on integration). Safe when wp-hooks is not loaded. 5 */ 6 function awdpHasWpHooks() { 7 return typeof wp !== 'undefined' && wp.hooks && typeof wp.hooks.addFilter === 'function'; 8 } 9 10 function awdpTriggerWcpaPriceUpdate(price) { 11 if ( ! awdpHasWpHooks() ) { 12 return; 13 } 14 wp.hooks.addFilter('wcpa_product_price', 'wcpa', function () { 15 return price; 16 }, 10); 17 document.dispatchEvent(new Event('wcpaTrigger', { bubbles: true })); 18 } 19 20 /** 21 * Only override WCPA price when AWDP actually applied a discount. 22 * Empty/catalog echoes would zero formula/lookup prices. 23 */ 24 function awdpShouldApplyWcpaPriceOverride(data) { 25 if ( data == null ) { 26 return false; 27 } 28 if ( typeof data === 'string' ) { 29 try { 30 data = JSON.parse(data); 31 } catch (e) { 32 return false; 33 } 34 } 35 if ( typeof data !== 'object' ) { 36 return false; 37 } 38 if ( data.hasDiscount === false ) { 39 return false; 40 } 41 if ( data.price === '' || data.price === null || typeof data.price === 'undefined' ) { 42 return false; 43 } 44 if ( Object.prototype.hasOwnProperty.call(data, 'originalPrice') 45 && Number(data.price) === Number(data.originalPrice) ) { 46 return false; 47 } 48 return data.hasDiscount === true 49 || ( Object.prototype.hasOwnProperty.call(data, 'originalPrice') 50 && Number(data.price) !== Number(data.originalPrice) ); 51 } 52 53 var $wdpTable = $('.wdp_table'); 54 var $dynamicPricing = typeof awdajaxobject !== 'undefined' ? awdajaxobject.dynamicPricing : false; 55 56 // Function to check if a string is Base64-encoded 57 function isBase64(str) { 58 try { 59 return btoa(atob(str)) == str; 60 } catch (e) { 61 return false; 62 } 63 } 64 65 if ( awdpHasWpHooks() && typeof awdajaxobject !== 'undefined' ) { 66 // wp.hooks.addFilter('wcpa_product_price', 'wcpa', (productPrice, product_id, variation_id) => { 67 // $.ajax({ url: awdajaxobject.url, data: {action: 'wdpDiscountedPrice', prodID: product_id, varID: variation_id} }).done(function(data) { 68 // productPrice = data ? data : productPrice; 69 // return productPrice; 70 // }).fail(function(data){ 71 // return productPrice; 72 // }); 73 // }, 10); 74 // document.dispatchEvent(new Event("wcpaTrigger", {bubbles: true})); 75 // $( '.variations_form' ).on( 'woocommerce_variation_select_change', function() { 76 // wp.hooks.addFilter('wcpa_product_price', 'wcpa', (productPrice, product_id, variation_id) => { 77 // $.ajax({ url: awdajaxobject.url, data: {action: 'wdpDiscountedPrice', prodID: product_id, varID: variation_id} }).done(function(data) { 78 // productPrice = data ? data : productPrice; 79 // return productPrice; 80 // }).fail(function(data){ 81 // return productPrice; 82 // }); 83 // }, 10); 84 // document.dispatchEvent(new Event("wcpaTrigger", {bubbles: true})); 85 // }); 86 // $('form.cart').find('[name=quantity]').on('change input', function(){ 87 // let qn = $(this).parents('form.cart').find('input[name="quantity"]').val(); 88 // wp.hooks.addFilter('wcpa_product_price', 'wcpa', (productPrice, product_id, variation_id) => { 89 // $.ajax({ url: awdajaxobject.url, data: {action: 'wdpDiscountedPrice', prodID: product_id, varID: variation_id} }).done(function(data) { 90 // productPrice = data ? qn * data : qn * productPrice; 91 // return productPrice; 92 // }).fail(function(data){ 93 // return qn * productPrice; 94 // }); 95 // }, 10); 96 // document.dispatchEvent(new Event("wcpaTrigger", {bubbles: true})); 97 // }); 98 99 $('form.cart').find('[name=quantity]').on('change input', function() { 100 let qnty = $(this).parents('form.cart').find('input[name="quantity"]').val(); 101 let product_id = $(this).parents('form.cart').find('button[name="add-to-cart"]').val(); 102 let variation_id = $(this).parents('form.cart').find('input[name="variation_id"]').val(); 103 $.ajax({ 104 dataType : "json", 105 url : awdajaxobject.url, 106 data : { 107 action: 'wdpDynamicDiscount', 108 nonce: awdajaxobject.nonce, 109 prodID: product_id, 110 varID: variation_id, 111 proCount: qnty 112 }, 113 success: function(response) { 114 if ( awdpShouldApplyWcpaPriceOverride(response) ) { 115 awdpTriggerWcpaPriceUpdate(response); 116 } 117 } 118 }); 119 120 $.ajax({ 121 dataType : "json", 122 url : awdajaxobject.url, 123 data : { 124 action: 'wcpaQunantity_Discount', 125 nonce: awdajaxobject.nonce, 126 proCount: qnty 127 }, 128 success: function(response) { 129 if ( response == null ) { 130 return; 131 } 132 function modifyDiscountRule() { 133 return response; 134 } 135 wp.hooks.addFilter('wcpa_discount_rule', 'wcpa', modifyDiscountRule, 10); 136 } 137 }); 138 }); 139 } 140 141 if ( $wdpTable.length > 0 ) { 142 143 /** 144 * Per-table rule payload. Prefer the table's own data-table so later 145 * variation updates are not stuck on the first table captured at load. 146 */ 147 function awdpGetTableDisData($table) { 148 var encoded = $table.attr('data-table') || ''; 149 if ( encoded && isBase64(encoded) ) { 150 try { 151 return atob(encoded); 152 } catch (e) { 153 return encoded; 154 } 155 } 156 return encoded; 157 } 158 159 function awdpSettingEnabled(value) { 160 return value === true || value === 1 || value === '1'; 161 } 162 163 var awdpDynamicPricing = awdpSettingEnabled($dynamicPricing); 164 var awdpTableRequest = 0; 165 var awdpPriceRequest = 0; 166 167 function awdpGetLiveTables() { 168 var $tables = $('.wdp_table'); 169 return $tables.length ? $tables : $wdpTable; 170 } 171 172 function awdpEnsureTableOriginals($table) { 173 if ( $table.data('awdpOriginalPrice') === undefined ) { 174 $table.data('awdpOriginalPrice', $table.attr('data-price') || ''); 175 } 176 if ( $table.data('awdpOriginalBody') === undefined ) { 177 $table.data('awdpOriginalBody', $table.find('tbody').html()); 178 } 179 } 180 181 awdpGetLiveTables().each(function () { 182 awdpEnsureTableOriginals($(this)); 183 }); 184 185 /** 186 * Resolve a numeric variation display price from WooCommerce's variation object. 187 * Prefer display_price (wc_get_price_to_display); fall back to parsing price_html. 188 */ 189 function awdpResolveVariationPrice(variation) { 190 if ( variation && variation.display_price !== undefined && variation.display_price !== null && variation.display_price !== '' ) { 191 var direct = Number(variation.display_price); 192 if ( ! isNaN(direct) && direct > 0 ) { 193 return direct; 194 } 195 } 196 197 if ( ! variation || ! variation.price_html ) { 198 return 0; 199 } 200 201 var $tmp = $('<div class="wdpHiddenPriceParse" />').html(variation.price_html); 202 var raw = $tmp.find('del').length 203 ? $tmp.find('ins .amount').first().text() 204 : $tmp.find('.amount').first().text(); 205 206 if ( ! raw ) { 207 return 0; 208 } 209 210 if ( typeof awdajaxobject !== 'undefined' && awdajaxobject.thousandSeparator == "," && awdajaxobject.decimalSeparator == "." ) { 211 raw = raw.replace(/[^\d\.]/g, ''); 212 } else { 213 raw = raw.replace(/^[^\d]*/, '').replace(/\./g, '').replace(',', '.'); 214 } 215 216 var parsed = parseFloat(raw); 217 return ( ! isNaN(parsed) && parsed > 0 ) ? parsed : 0; 218 } 219 220 function awdpFindVariationFromForm($form, variationId) { 221 variationId = parseInt(variationId, 10); 222 if ( ! variationId ) { 223 return null; 224 } 225 var variations = $form.data('product_variations'); 226 if ( ! $.isArray(variations) ) { 227 return null; 228 } 229 var found = null; 230 $.each(variations, function (i, variation) { 231 if ( parseInt(variation.variation_id, 10) === variationId ) { 232 found = variation; 233 return false;
234 } 235 }); 236 return found; 237 } 238 239 function awdpFindTablesForForm($form) { 240 var productId = $form.data('product_id') || $form.find('input[name="product_id"]').val() || ''; 241 var $tables = $(); 242 243 awdpGetLiveTables().each(function () { 244 var $table = $(this); 245 awdpEnsureTableOriginals($table); 246 var tableProduct = $table.attr('data-product') || ''; 247 if ( ! productId || ! tableProduct || String(tableProduct) === String(productId) ) { 248 $tables = $tables.add($table); 249 } 250 }); 251 252 return $tables.length ? $tables : awdpGetLiveTables(); 253 } 254 255 function awdpGetDynamicBox($table) { 256 var $outter = $table.closest('.wdp_table_outter'); 257 var $dynamic = $(); 258 if ( $outter.length ) { 259 $dynamic = $outter.nextAll('.wdpDynamicValue').first(); 260 if ( ! $dynamic.length ) { 261 $dynamic = $outter.siblings('.wdpDynamicValue').first(); 262 } 263 if ( ! $dynamic.length ) { 264 $dynamic = $outter.parent().find('.wdpDynamicValue').first(); 265 } 266 } 267 if ( ! $dynamic.length ) { 268 $dynamic = $('.wdpDynamicValue').first(); 269 } 270 return $dynamic; 271 } 272 273 function awdpGetProductForm($table) { 274 var productId = $table.attr('data-product') || ''; 275 var $form = $('form.variations_form, form.cart').filter(function () { 276 var id = $(this).data('product_id') || $(this).find('input[name="product_id"], button[name="add-to-cart"], input[name="add-to-cart"]').first().val(); 277 return ! productId || ! id || String(id) === String(productId); 278 }).first(); 279 return $form.length ? $form : $('form.cart').first(); 280 } 281 282 function awdpGetCurrentQty($table) { 283 var qty = parseFloat(awdpGetProductForm($table).find('input[name="quantity"]').val()); 284 return ( ! isNaN(qty) && qty > 0 ) ? qty : 1; 285 } 286 287 function awdpGetSelectedVariationId($table) { 288 var variationId = parseInt(awdpGetProductForm($table).find('input[name="variation_id"], input.variation_id').val(), 10); 289 return ( variationId > 0 ) ? variationId : 0; 290 } 291 292 function awdpAbortTableRequest($table) { 293 var xhr = $table.data('awdpTableXhr'); 294 if ( xhr && xhr.readyState !== 4 ) { 295 xhr.abort(); 296 } 297 } 298 299 function awdpAbortPriceRequest($table) { 300 var xhr = $table.data('awdpPriceXhr'); 301 if ( xhr && xhr.readyState !== 4 ) { 302 xhr.abort(); 303 } 304 } 305 306 function awdpFormatFallbackPrice(amount) { 307 var decimals = ( typeof awdajaxobject !== 'undefined' && awdajaxobject.priceDecimals !== undefined ) 308 ? parseInt(awdajaxobject.priceDecimals, 10) 309 : 2; 310 if ( isNaN(decimals) || decimals < 0 ) { 311 decimals = 2; 312 } 313 var n = Number(amount); 314 if ( isNaN(n) ) { 315 n = 0; 316 } 317 var formatted = n.toFixed(decimals); 318 var decimalSep = ( typeof awdajaxobject !== 'undefined' && awdajaxobject.decimalSeparator ) 319 ? awdajaxobject.decimalSeparator 320 : '.'; 321 if ( decimalSep !== '.' ) { 322 formatted = formatted.replace('.', decimalSep); 323 } 324 var symbol = ( typeof awdajaxobject !== 'undefined' && awdajaxobject.currencySymbol ) 325 ? awdajaxobject.currencySymbol 326 : ''; 327 return symbol + formatted; 328 } 329 330 function awdpPaintDynamicPrice($dynamic, unit, qty) { 331 qty = parseFloat(qty); 332 if ( isNaN(qty) || qty < 0 ) { 333 qty = 0; 334 } 335 unit = parseFloat(unit); 336 if ( isNaN(unit) ) { 337 unit = 0; 338 } 339 $dynamic.find('.wdpPrice').html(awdpFormatFallbackPrice(unit)); 340 $dynamic.find('.wdpTotal').html(awdpFormatFallbackPrice(unit * qty)); 341 $dynamic.show(); 342 } 343 344 function awdpRefreshDynamicPrice($table, qty) { 345 if ( ! awdpDynamicPricing ) { 346 return; 347 } 348 if ( $table.attr('data-product') === '' ) { 349 return; 350 } 351 352 var loader = '<div class="wdpLoader"><span></span><span></span><span></span></div>'; 353 var requestId = ++awdpPriceRequest; 354 var $dynamic = awdpGetDynamicBox($table); 355 var variationId = awdpGetSelectedVariationId($table); 356
357 if ( typeof qty === 'undefined' || qty === null || qty === '' ) { 358 qty = awdpGetCurrentQty($table); 359 } else { 360 qty = parseFloat(qty); 361 if ( isNaN(qty) || qty <= 0 ) { 362 qty = awdpGetCurrentQty($table); 363 } 364 } 365 366 $dynamic.show(); 367 $dynamic.find('.wdpPrice').html(loader); 368 $dynamic.find('.wdpTotal').html(loader); 369 370 awdpAbortPriceRequest($table); 371 var xhr = $.post(awdajaxobject.url, { 372 action: 'wdpAjax', 373 nonce: awdajaxobject.nonce, 374 type: 'update', 375 ProdID: $table.attr('data-product'), 376 DisData: awdpGetTableDisData($table), 377 ProdPrice: $table.attr('data-price'), 378 ProdVarPrice: $table.attr('data-var-price'), 379 ProdQty: qty, 380 variation_id: variationId 381 }, function (response) { 382 if ( requestId !== awdpPriceRequest ) { 383 return; 384 } 385 if ( ! response ) { 386 awdpPaintDynamicPrice($dynamic, $table.attr('data-price'), qty); 387 return; 388 } 389 if ( typeof response === 'string' ) { 390 try { 391 response = JSON.parse(response); 392 } catch (e) { 393 awdpPaintDynamicPrice($dynamic, $table.attr('data-price'), qty); 394 return; 395 } 396 } 397 398 if ( response.price_html && response.total_html ) { 399 $dynamic.find('.wdpPrice').html(response.price_html); 400 $dynamic.find('.wdpTotal').html(response.total_html); 401 } else { 402 $dynamic.find('.wdpPrice').html(awdpFormatFallbackPrice(response.price)); 403 $dynamic.find('.wdpTotal').html(awdpFormatFallbackPrice(response.total)); 404 } 405 $dynamic.show(); 406 }).fail(function (jqXHR, textStatus) { 407 if ( textStatus === 'abort' || requestId !== awdpPriceRequest ) { 408 return; 409 } 410 awdpPaintDynamicPrice($dynamic, $table.attr('data-price'), qty); 411 }); 412 $table.data('awdpPriceXhr', xhr); 413 } 414 415 function awdpResetQuantityTable($table) { 416 var variationId = awdpGetSelectedVariationId($table); 417 418 // A variation is still selected (add-to-cart / fragment refresh). Keep its prices. 419 if ( variationId > 0 ) { 420 var $form = awdpGetProductForm($table); 421 var variation = awdpFindVariationFromForm($form, variationId); 422 if ( variation && parseInt($table.data('awdpAppliedVariation'), 10) !== variationId ) { 423 awdpApplyVariationToTable($table, variation, $form); 424 return; 425 } 426 awdpRefreshDynamicPrice($table, awdpGetCurrentQty($table)); 427 return; 428 } 429 430 awdpTableRequest++; 431 awdpPriceRequest++; 432 awdpAbortTableRequest($table); 433 awdpAbortPriceRequest($table); 434 $table.removeData('awdpTableXhr'); 435 $table.removeData('awdpPriceXhr'); 436 $table.removeData('awdpAppliedVariation'); 437 $table.attr('data-price', $table.data('awdpOriginalPrice') || ''); 438 var originalBody = $table.data('awdpOriginalBody'); 439 if ( originalBody ) { 440 $table.find('tbody').html(originalBody); 441 } 442 awdpRefreshDynamicPrice($table, awdpGetCurrentQty($table)); 443 } 444 445 function awdpApplyVariationToTable($table, variation, $form) { 446 if ( ! variation ) { 447 return; 448 } 449 450 var variationId = parseInt(variation.variation_id, 10) || 0; 451 var varPrice = awdpResolveVariationPrice(variation); 452 var qty = parseFloat($form.find('input[name="quantity"]').val()); 453 var requestId; 454 455 if ( isNaN(qty) || qty <= 0 ) { 456 qty = 1; 457 } 458 459 $table.data('awdpAppliedVariation', variationId); 460 461 if ( varPrice > 0 ) { 462 $table.attr('data-price', varPrice); 463 } 464 465 if ( $('.wdpHiddenPrice').length ) { 466 $('.wdpHiddenPrice').html(variation.price_html || ''); 467 } 468 469 requestId = ++awdpTableRequest; 470 $table.find('tbody td').html('<div class="wdpLoader"><span></span><span></span><span></span></div>'); 471 472 awdpAbortTableRequest($table); 473 var xhr = $.post(awdajaxobject.url, { 474 action: 'wdpAjax', 475 nonce: awdajaxobject.nonce, 476 type: 'change', 477 attributes: variation.attributes, 478 price: varPrice, 479 variation_id: variation.variation_id, 480 DisData: awdpGetTableDisData($table), 481 Rule: $table.attr('data-rule') 482 }, function (response) { 483 if ( requestId !== awdpTableRequest ) { 484 return; 485 } 486 if ( response ) { 487 if ( varPrice > 0 ) { 488 $table.attr('data-price', varPrice); 489 } 490 $table.find('tbody').html(response); 491 } 492 awdpRefreshDynamicPrice($table, qty); 493 }).fail(function (jqXHR, textStatus) { 494 if ( textStatus === 'abort' ) { 495 return; 496 } 497 if ( requestId !== awdpTableRequest ) { 498 return; 499 } 500 var originalBody = $table.data('awdpOriginalBody'); 501 if ( originalBody ) { 502 $table.find('tbody').html(originalBody); 503 } 504 awdpRefreshDynamicPrice($table, qty); 505 }); 506 $table.data('awdpTableXhr', xhr); 507 } 508 509 function awdpSyncSelectedVariation($form) { 510 var variationId = parseInt($form.find('input[name="variation_id"], input.variation_id').val(), 10); 511 if ( ! ( variationId > 0 ) ) { 512 return; 513 } 514 var variation = awdpFindVariationFromForm($form, variationId); 515 awdpFindTablesForForm($form).each(function () { 516 var $table = $(this); 517 if ( parseInt($table.data('awdpAppliedVariation'), 10) === variationId ) { 518 return; 519 } 520 if ( variation ) { 521 awdpApplyVariationToTable($table, variation, $form); 522 } else { 523 awdpRefreshDynamicPrice($table, awdpGetCurrentQty($table)); 524 } 525 }); 526 } 527 528 // WooCommerce fires found_variation on form.variations_form (not the wrap). 529 $(document.body).on('found_variation', 'form.variations_form', function (event, variation) { 530 if ( ! variation ) { 531 return; 532 } 533 var $form = $(this); 534 awdpFindTablesForForm($form).each(function () { 535 awdpApplyVariationToTable($(this), variation, $form); 536 }); 537 }); 538 539 // Woo inits the variation form after a 100ms timeout. If found_variation 540 // already applied this variation, skip; otherwise catch a missed init. 541 $(document.body).on('wc_variation_form', 'form.variations_form', function () { 542 awdpSyncSelectedVariation($(this)); 543 }); 544 545 // Restore the range table when attributes are cleared. Keep Your Price 546 // visible using the current qty and catalog/min price (or the still- 547 // selected variation after add-to-cart). 548 $(document.body).on('reset_data', 'form.variations_form', function () { 549 awdpFindTablesForForm($(this)).each(function () { 550 awdpResetQuantityTable($(this)); 551 }); 552 }); 553 554 $(document.body).on('added_to_cart', function () { 555 awdpGetLiveTables().each(function () { 556 var $table = $(this); 557 awdpEnsureTableOriginals($table); 558 awdpRefreshDynamicPrice($table, awdpGetCurrentQty($table)); 559 }); 560 }); 561 562 if ( awdpDynamicPricing ) { 563 $(document.body).on('change input', 'form.cart [name="quantity"]', function (e) { 564 var $form = $(this).closest('form.cart'); 565 var $table = awdpFindTablesForForm($form).first(); 566 if ( ! $table.length ) { 567 $table = awdpGetLiveTables().first(); 568 } 569 // WooCommerce programmatically triggers quantity `change` while matching 570 // a variation, before our found_variation handler can set data-price. 571 if ( e.type === 'change' && ! e.originalEvent && $form.find('input[name="variation_id"], input.variation_id').val() ) { 572 return; 573 } 574 awdpRefreshDynamicPrice($table, $(this).val()); 575 }); 576 577 awdpGetLiveTables().each(function () { 578 awdpRefreshDynamicPrice($(this), awdpGetCurrentQty($(this))); 579 }); 580 581 $('form.variations_form').each(function () { 582 awdpSyncSelectedVariation($(this)); 583 }); 584 } 585 } 586});
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.