PageSourceSearch

https://beautyandshop.es/wp-content/plugins/advanced-dynamic-prici…/assets/js/dynamic-price.js?ver=4.10.1

js beautyandshop.es collected 2026-10-01 10:39:20 UTC 21,096 bytes, 665 lines download raw bytes

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.