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