1/** 2 * @property {object} wdp_script_data_pro 3 * @property {string} wdp_script_data_pro.ajaxurl 4 * @property {string} wdp_script_data_pro.update_price_with_qty 5 * @property {string} wdp_script_data_pro.highlight_range_qty_changed 6 * @property {string} wdp_script_data_pro.higlight_background_color 7 * @property {string} wdp_script_data_pro.higlight_text_color 8 * @property {string} wdp_script_data_pro.js_init_trigger 9 * @property {boolean} wdp_script_data_pro.replace_variable_price 10 * @property {string} wdp_script_data_pro.variable_price_selector 11 * @property {object} wdp_script_data_pro.page_data 12 * @property {boolean} wdp_script_data_pro.create_on_load 13 * @property {boolean} wdp_script_data_pro.show_spinner 14 * @property {string} wdp_script_data_pro.security 15 * @property {string} wdp_script_data_pro.security_param 16 */ 17 18/** 19 * @class 20 */ 21var DynamicPrice = (function () { 22 /** 23 * @constructs DynamicPrice 24 * @param {jQuery} $form 25 * @param {object} $opts 26 */ 27 function DynamicPrice($form, $opts) { 28 /** 29 * @type {Boolean} 30 * @private 31 */ 32 this.__isEnable = false; 33 34 /** 35 * @type {Object} 36 * @private 37 */ 38 this.__pageData = {}; 39 40 /** 41 * @type {String} 42 * @private 43 */ 44 this.__ajaxUrl = ""; 45 46 /** 47 * @name DynamicPrice#form 48 * @type {jQuery} 49 */ 50 this.form = null; 51 52 /** 53 * @type {number} 54 * @private 55 */ 56 this.__inputTimerId = null; 57 58 /** 59 * @type {Array} 60 * @private 61 */ 62 this.__price_destinations = []; 63 64 /** 65 * @type {Array} 66 * @private 67 */ 68 this.__subtotal_destinations = []; 69 70 /** 71 * @type {Array} 72 * @private 73 */ 74 this.__total_price_destinations = []; 75 76 this.__priceHtmlTemplate = "{{price_html}}"; 77 78 this.__priceSuffix = ""; 79 80 // for input observing 81 this.__lastChange = null;
82 this.__lastValue = null; 83 84 /** 85 * @type {Boolean} 86 * @private 87 */ 88 this.__show_spinner = true; 89 90 if (typeof $opts === 'undefined') { 91 $opts = wdp_script_data_pro; 92 } 93 94 if (typeof $opts.price_html_template !== 'undefined') { 95 this.__priceHtmlTemplate = $opts.price_html_template; 96 } 97 98 if (typeof $opts.dynamic_price_enable !== 'undefined') { 99 this.__isEnable = !!$opts.dynamic_price_enable; 100 } else if (typeof $opts.update_price_with_qty !== 'undefined') { 101 this.__isEnable = $opts.update_price_with_qty === "1"; 102 } 103 if (typeof $opts.page_data !== 'undefined') { 104 this.__pageData = $opts.page_data; 105 } 106 107 if (typeof $opts.price_suffix !== 'undefined') { 108 this.__priceSuffix = $opts.price_suffix; 109 } 110 111 if (typeof $opts.ajaxurl !== 'undefined') { 112 this.__ajaxUrl = $opts.ajaxurl; 113 } else { 114 logError("Empty ajaxurl"); 115 return; 116 } 117 118 if (typeof $form !== 'undefined' && $form.is('form')) { 119 this.form = $form 120 } else { 121 logError("Incorrect form provided"); 122 } 123 124 this.clickableBulkRows(); 125 126 if (typeof $opts.show_spinner !== 'undefined') { 127 this.__show_spinner = !! $opts.show_spinner; 128 } 129 130 /** 131 * 132 * @returns {function(): {price: number, value: string}[]} 133 * @private 134 */ 135 this.__addons_supplier = function () { 136 return [] 137 }; 138 } 139 140 function getTimestamp() { 141 return Math.floor(Date.now() / 1000); 142 } 143 144 DynamicPrice.prototype.stopObserve = function () { 145 if (this.__inputTimerId) { 146 clearInterval(this.__inputTimerId); 147 } 148 }; 149 150 DynamicPrice.prototype.__getQty = function () { 151 var $input = this.form.find('input[name="quantity"]'); 152 if ($input.length === 0) { 153 $input = this.form.find('select[name="quantity"]'); 154 if ($input.length === 0) { 155 return 0; 156 } 157 } 158 159 return $input.val(); 160 }; 161 162 DynamicPrice.prototype.observe = function () { 163 this.stopObserve(); 164 165 this.__lastChange = null;
166 this.__lastValue = this.__getQty(); 167 168 this.__inputTimerId = setInterval(this.__watch.bind(this), 300); 169 170 if (document.getElementById('asnp_easy_product_bundle')) { 171 setTimeout(() => { 172 this.__update(this.__lastValue); 173 }, 500); 174 } 175 }; 176 177 DynamicPrice.prototype.__watch = function () { 178 var $qty = this.__getQty(); 179 180 if ($qty && this.__lastValue !== $qty) { 181 this.__lastValue = $qty; 182 this.__lastChange = getTimestamp(); 183 } else if (this.__lastValue && this.__lastValue === $qty && this.__lastChange) { 184 this.__lastChange = null; 185 this.__update(this.__lastValue); 186 } 187 }; 188 189 DynamicPrice.prototype.__getProductId = function () { 190 var variationIdEl = this.form.find('[name="variation_id"]'); 191 var productIdEl = this.form.find('[name="add-to-cart"]'); 192 193 if (variationIdEl.length) { 194 return parseInt(variationIdEl.val()); 195 } else if (productIdEl.length) { 196 return parseInt(productIdEl.val()); 197 } 198 199 return false; 200 }; 201 202 DynamicPrice.prototype.__getVariationAttributes = function () { 203 let attributes = {}; 204 205 this.form.find('select').each(function (index, item) { 206 if (jQuery(item).attr("data-attribute_name")) { 207 attributes[jQuery(item).attr("data-attribute_name")] = jQuery(this).val(); 208 } 209 }); 210 211 return attributes; 212 }; 213 214 /** 215 * 216 * @param {string} $qty 217 * @param {string|undefined} $customPrice 218 * @returns {jQuery|null} 219 * @private 220 */ 221 DynamicPrice.prototype.__update = function ($qty, $customPrice = undefined) { 222 223 if (typeof $qty === 'undefined' || !$qty) { 224 logError("Empty qty"); 225 return null; 226 } else { 227 $qty = parseFloat($qty); 228 } 229 230 if (wdp_script_data_pro.highlight_range_qty_changed) { 231 this.__highlightRange($qty); 232 } 233 234 if (!this.__isEnable) { 235 return null; 236 } 237 238 if (typeof $customPrice === 'undefined') { 239 $customPrice = null; 240 } 241 242 var $existTotalPriceDestinations = []; 243 jQuery.each(this.__total_price_destinations, function (_, $selector) { 244 var $el = jQuery($selector).first(); 245 if ($el.length !== 0) { 246 $existTotalPriceDestinations.push($el); 247 } 248 }); 249 250 251 var $productId = this.__getProductId(); 252 if (!$productId) { 253 replaceDestinations($existTotalPriceDestinations, ''); 254 255 logError("Empty product ID"); 256 return null; 257 } 258 259 var $existPriceDestinations = []; 260 jQuery.each(this.__price_destinations, function (_, $selector) { 261 var $el = jQuery($selector).first(); 262 if ($el.length !== 0) { 263 $existPriceDestinations.push($el); 264 } 265 }); 266 267 var $existSubtotalDestinations = []; 268 jQuery.each(this.__subtotal_destinations, function (_, $selector) { 269 var $el = jQuery($selector).first(); 270 if ($el.length !== 0) { 271 $existSubtotalDestinations.push($el); 272 } 273 }); 274 275 276 if ($existPriceDestinations.length === 0 && $existSubtotalDestinations.length === 0 && $existTotalPriceDestinations.length === 0) { 277 return null; 278 } 279 280 var data = { 281 action: 'get_price_product_with_bulk_table', 282 product_id: $productId, 283 attributes: this.__getVariationAttributes(), 284 qty: $qty, 285 page_data: this.__pageData, 286 ...jQuery('form.cart').triggerHandler('wdp_get_custom_data') 287 }; 288 289 data[wdp_script_data_pro.security_param] = wdp_script_data_pro.security; 290 291 var $spinner_price = "<div id=\"spinner_price\"><img class=\"spinner_img\"></div>"; 292 var pricePreloaded = false; 293 294 if ($customPrice !== null) { 295 data.custom_price = $customPrice; 296 } else { 297 var $price_html = this.__tryToGetPreLoadedPrice($productId, $qty); 298 if ($price_html) { 299 replaceDestinations($existPriceDestinations, $price_html); 300 301 if ($existSubtotalDestinations.length === 0 && $existTotalPriceDestinations.length === 0) { 302 return; 303 } 304 305 pricePreloaded = true; 306 } 307 } 308 309 if ( this.__show_spinner ) { 310 if (!pricePreloaded) { 311 replaceDestinations($existPriceDestinations, $spinner_price); 312 } 313 replaceDestinations($existSubtotalDestinations, $spinner_price); 314 replaceDestinations($existTotalPriceDestinations, $spinner_price); 315 } 316 317 data.addons = this.__addons_supplier(); 318 319 return jQuery.ajax({ 320 url: this.__ajaxUrl, 321 data: data, 322 dataType: 'json', 323 type: 'POST', 324 success: function (response) { 325 if (response.success) { 326 if ( !pricePreloaded ) { 327 replaceDestinations($existPriceDestinations, response.data.price_html); 328 } 329 replaceDestinations($existSubtotalDestinations, response.data.subtotal_html); 330 replaceDestinations($existTotalPriceDestinations, response.data.total_price_html); 331 332 if (response.data.external_plugins) { 333 response.data.external_plugins.forEach((external_plugin) => { 334 if (external_plugin.destination && external_plugin.html) 335 jQuery(external_plugin.destination).replaceWith(external_plugin.html); 336 }) 337 } 338 } else { 339 if ( !pricePreloaded ) { 340 clearDestinations($existPriceDestinations); 341 } 342 clearDestinations($existSubtotalDestinations); 343 clearDestinations($existTotalPriceDestinations); 344 } 345 }, 346 error: function (response) { 347 if ( !pricePreloaded ) { 348 clearDestinations($existPriceDestinations); 349 } 350 clearDestinations($existSubtotalDestinations); 351 clearDestinations($existTotalPriceDestinations); 352 } 353 }); 354 }; 355 356 DynamicPrice.prototype.__highlightRange = function ($qty) {
357 var $productContainer = this.form.closest('.product'); 358 var $table = $productContainer.find('.bulk_table .wdp_pricing_table tbody'); 359 if (!$table.length) return; 360 $qty = parseFloat($qty); 361 362 $table.find('tr td').each(function () { 363 this.style.setProperty('background-color', ''); 364 this.style.setProperty('color', ''); 365 }); 366 367 $table.find('tr').each(function () { 368 var $row = jQuery(this); 369 var rangeText = $row.find('td').first().text().trim(); 370 var match = rangeText.match(/(\d+)(?:\s*-\s*(\d+))?/); 371 372 if (match) { 373 var from = parseFloat(match[1]); 374 var to = match[2] ? parseFloat(match[2]) : Infinity; 375 376 if ($qty >= from && $qty <= to) { 377 $row.find('td').each(function () { 378 this.style.setProperty('background-color', wdp_script_data_pro.higlight_background_color, 'important'); 379 this.style.setProperty('color', wdp_script_data_pro.higlight_text_color, 'important'); 380 }); 381 } 382 } 383 }); 384 }; 385 386 DynamicPrice.prototype.__clearTotalPrice = function() { 387 var $existTotalPriceDestinations = []; 388 jQuery.each(this.__total_price_destinations, function (_, $selector) { 389 var $el = jQuery($selector).first(); 390 if ($el.length !== 0) { 391 $existTotalPriceDestinations.push($el); 392 } 393 }); 394 395 var $productId = this.__getProductId(); 396 397 if (!$productId) { 398 replaceDestinations($existTotalPriceDestinations, ''); 399 } 400 }; 401 402 DynamicPrice.prototype.__tryToGetPreLoadedPrice = function ($productId, $qty) { 403 if ( typeof wdp_script_data_pro.preLoaded === 'undefined' ) { 404 return null; 405 } 406 407 var $preLoaded = wdp_script_data_pro.preLoaded; 408 409 $qty = parseFloat($qty); 410 if ( ! $qty ) { 411 return null; 412 } 413 414 $productId = $productId.toString(); 415 416 var _this = this; 417 418 var $html = null; 419 jQuery.each($preLoaded, function ($preLoadedProductId, $data) { 420 if ( typeof $data.ranges === 'undefined' || typeof $data.price_html === 'undefined' || typeof $data.price_html_view === 'undefined' || typeof $data.index_number === 'undefined' ) { 421 return; // continue 422 } 423 var $ranges = $data.ranges; 424 var $price_html = $data.price_html; 425 var $current_qty = $data.index_number + $qty; 426 var $qty_already_in_cart = $data.qty_already_in_cart; 427 428 if ( $preLoadedProductId === $productId ) { 429 jQuery.each($ranges, function (_, $range) { 430 if (compareFloats($range['from'], '<=', $current_qty) && compareFloats($current_qty, '<=', $range['to']) 431 || (compareFloats($range['from'], '<=', $current_qty) && $range['to'] === "") 432 || ($range['from'] === "" && compareFloats($current_qty, '<=', $range['to'])) 433 ) { 434 $html = _this.__formatPriceHtml($range['striked_price_html'], $current_qty, $qty_already_in_cart, $range['regular_price_striked']); 435 return false; 436 } 437 }); 438 439 if ( ! $html ) { 440 if ( $current_qty === 1 ) { 441 $html = $data.price_html_view; 442 } else{ 443 $html = _this.__formatPriceHtml($price_html, $current_qty, $qty_already_in_cart, ""); 444 } 445 } 446 } 447 if ( $html ) { 448 return false; 449 } 450 }); 451 452 return $html; 453 }; 454 455 function compareFloats($a, $op, $b) { 456 $a = Math.floor(parseFloat($a) * 100); 457 $b = Math.floor(parseFloat($b) * 100); 458 459 switch ($op) { 460 case "=": 461 return $a === $b; 462 case ">": 463 return $a > $b; 464 case ">=": 465 return $a >= $b; 466 case "<": 467 return $a < $b; 468 case "<=": 469 return $a <= $b; 470 } 471 472 return null; 473 } 474 475 function replaceDestinations($targets, $priceHtml) { 476 jQuery.each($targets, function (_, $target) { 477 $target.html($priceHtml); 478 jQuery(document).trigger('wdp_price_product_updated', $priceHtml); 479 }) 480 } 481 482 DynamicPrice.prototype.clickableBulkRows = function () { 483 if (!wdp_script_data_pro.clickable_bulk_rows) { 484 return 485 } 486 487 let $table = jQuery('.bulk_table .wdp_pricing_table'); 488 let $input = jQuery('input[name="quantity"]'); 489 if (!$table || !$input || $table.data('measurement') !== 'qty' || $table.data('layout') !== 'verbose') return 490 491 // let $targets = $table.data('layout') === 'verbose' ? $table.find('tbody tr') : $table.find('thead td'); 492 let $targets = $table.find('tbody tr'); 493 494 $targets.addClass('clickable_bulk'); 495 $targets.css('--highlight-range-bg', wdp_script_data_pro.higlight_background_color); 496 $targets.css('--highlight-range-text', wdp_script_data_pro.higlight_text_color); 497 $targets.each((i) => { 498 jQuery($targets[i]).on('click', () => { 499 let min = jQuery($targets[i]).data('min'); 500 $input.val(min); 501 }) 502 }) 503 } 504 505 function clearDestinations($targets) { 506 jQuery.each($targets, function (_, $target) { 507 $target.html(""); 508 jQuery(document).trigger('wdp_price_product_updated', ""); 509 }) 510 } 511 512 DynamicPrice.prototype.addPriceDestination = function ($dest) { 513 if (typeof $dest === 'string') { 514 this.__price_destinations.push($dest); 515 } else if (Array.isArray($dest)) { 516 Array.prototype.push.apply(this.__price_destinations, $dest); 517 } 518 }; 519 520 DynamicPrice.prototype.addSubtotalDestination = function ($dest) { 521 if (typeof $dest === 'string') { 522 this.__subtotal_destinations.push($dest); 523 } else if (Array.isArray($dest)) { 524 Array.prototype.push.apply(this.__subtotal_destinations, $dest); 525 } 526 }; 527 528 DynamicPrice.prototype.addTotalPriceDestination = function ($dest) { 529 if (typeof $dest === 'string') { 530 this.__total_price_destinations.push($dest); 531 } else if (Array.isArray($dest)) { 532 Array.prototype.push.apply(this.__total_price_destinations, $dest); 533 } 534 }; 535 536 /** 537 * 538 * @param {function(): {price: number, value: string}[]} callback 539 */ 540 DynamicPrice.prototype.withAddonsSupplier = function (callback) { 541 this.__addons_supplier = callback; 542 }; 543
544 DynamicPrice.prototype.update = function ($args) { 545 var $qty = null; 546 var $customPrice = null; 547 548 if (typeof $args !== 'undefined') { 549 if (typeof $args.qty !== 'undefined') { 550 $qty = parseFloat($args.qty); 551 } else { 552 $qty = this.__getQty(); 553 } 554 555 if (typeof $args.custom_price !== 'undefined') { 556 $customPrice = $args.custom_price; 557 } 558 } 559 560 return this.__update($qty, $customPrice); 561 }; 562 563 564 DynamicPrice.prototype.disable = function () { 565 this.__isEnable = false; 566 }; 567 568 DynamicPrice.prototype.enable = function () { 569 this.__isEnable = true; 570 }; 571 572 DynamicPrice.prototype.__formatPriceHtml = function ($priceHtml, $indexNumber, $qtyAlreadyInCart, regularPriceStriked) { 573 return this.__priceHtmlTemplate 574 .replace("{{price_html}}", $priceHtml) 575 .replace("{{Nth_item}}", addSuffixOf($indexNumber)) 576 .replace("{{qty_already_in_cart}}", $qtyAlreadyInCart) 577 .replace("{{price_suffix}}", this.__priceSuffix) 578 .replace("{{regular_price_striked}}", regularPriceStriked); 579 }; 580 581 function addSuffixOf($value) { 582 var mod10 = $value % 10, 583 mod100 = $value % 100; 584 585 if (mod10 === 1 && mod100 !== 11) { 586 return $value + "st"; 587 } 588 if (mod10 === 2 && mod100 !== 12) { 589 return $value + "nd"; 590 } 591 if (mod10 === 3 && mod100 !== 13) { 592 return $value + "rd"; 593 } 594 return $value + "th"; 595 } 596 597 function logError($text) { 598 console.error("DynamicPrice error: %s", $text); 599 } 600 601 return DynamicPrice; 602})(); 603 604var dynamicPrices = []; 605 606function createDynamicPrice() { 607 var dynamicPrices = []; 608 609 jQuery('form.cart').each(function () { 610 var $form = jQuery(this); 611 var isVariation = $form.hasClass("variations_form"); 612 var $targets = []; 613 var $productId = $form.find('[name="add-to-cart"]').val(); 614 615 if (!$productId) { 616 return false; 617 } 618 619 if (isVariation) { 620 $targets.push('.product.post-' + $productId + ' .woocommerce-variation-price .price'); 621 622 if (wdp_script_data_pro.replace_variable_price) { 623 $targets.push('.product.post-' + $productId + ' ' + wdp_script_data_pro.variable_price_selector); 624 } 625 } else { 626 $targets.push('.product.post-' + $productId + ' .price'); 627 } 628 629 var optFirst = Object.assign({}, wdp_script_data_pro); 630 optFirst.dynamic_price_enable = true; 631 var dynamicPrice = new DynamicPrice($form, optFirst); 632 633 if ( optFirst.update_price_with_qty === "1" ) { 634 dynamicPrice.addPriceDestination($targets); 635 } 636 637 dynamicPrice.addTotalPriceDestination(["div.adp-total-price"]); 638 639 dynamicPrice.observe(); 640 dynamicPrices.push(dynamicPrice); 641 }); 642 643 return dynamicPrices; 644} 645 646if (wdp_script_data_pro.js_init_trigger) { 647 jQuery(document).on(wdp_script_data_pro.js_init_trigger, function () { 648 dynamicPrices = createDynamicPrice(); 649 }); 650} 651 652if (wdp_script_data_pro.create_on_load) { 653 jQuery(document).ready(function () { 654 dynamicPrices = createDynamicPrice(); 655 656 jQuery('.variations_form').on('found_variation', {variationForm: this}, 657 function (event, variation) { 658 if (typeof variation !== 'undefined') { 659 setTimeout(function () { 660 dynamicPrices.forEach(function (dynamicPrice) { 661 if (dynamicPrice.form[0] !== undefined && dynamicPrice.form[0] === event.target) { 662 dynamicPrice.__update(dynamicPrice.__getQty()) 663 } 664 }); 665 }, 0); 666 } 667 668 return true; 669 }); 670 671 jQuery('form.cart').on('adp_found_variation', function () { 672 setTimeout(function () { 673 dynamicPrices.forEach(function (dynamicPrice) { 674 if (dynamicPrice.form[0] !== undefined) { 675 dynamicPrice.__update(dynamicPrice.__getQty()) 676 } 677 }); 678 }, 0); 679 return true; 680 }); 681 682 jQuery('.variations_form').on('reset_data', {variationForm: this}, 683 function (event) { 684 setTimeout(function () {
685 dynamicPrices.forEach(function (dynamicPrice) { 686 if (dynamicPrice.form[0] !== undefined && dynamicPrice.form[0] === event.target) { 687 dynamicPrice.__clearTotalPrice(); 688 } 689 }); 690 691 }, 0); 692 693 return true; 694 }); 695 }); 696}
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.