PageSourceSearch

https://www.pl-bioscience.com/wp-content/plugins/woocommerce-germa…/static/unit-price-observer.js?ver=4.1.3

js pl-bioscience.com collected 2026-09-29 16:11:26 UTC 20,990 bytes, 503 lines download raw bytes

1/******/ (() => { // webpackBootstrap
2let __webpack_exports__ = {};
3/*global wc_gzd_unit_price_observer_params, accounting */
4;
5(function ($, window, document, undefined) {
6  var GermanizedUnitPriceObserver = function ($wrapper) {
7    var self = this;
8    self.params = wc_gzd_unit_price_observer_params;
9    self.$wrapper = $wrapper.closest(self.params.wrapper);
10    self.$form = self.$wrapper.find('.variations_form, .cart').length > 0 ? self.$wrapper.find('.variations_form, .cart') : false;
11    self.isVar = self.$form ? self.$form.hasClass('variations_form') : false;
12    self.$product = self.$wrapper.closest('.product');
13    self.requests = [];
14    self.observer = {};
15    self.timeout = false;
16    self.priceData = false;
17    self.productId = 0;
18    if (self.$wrapper.length <= 0) {
19      self.$wrapper = self.$product;
20    }
21    self.replacePrice = self.$wrapper.hasClass('bundled_product') ? false : self.params.replace_price;
22    if ("MutationObserver" in window || "WebKitMutationObserver" in window || "MozMutationObserver" in window) {
23      self.$wrapper.addClass('has-unit-price-observer');
24      self.initObservers(self);
25      if (self.isVar && self.$form) {
26        self.productId = parseInt(self.$form.find('input[name=product_id]').length > 0 ? self.$form.find('input[name=product_id]').val() : self.$form.data('product_id'));
27        self.variationId = parseInt(self.$form.find('input[name=variation_id]').length > 0 ? self.$form.find('input[name=variation_id]').val() : 0);
28        if (self.$form.find('input[name=variation_id]').length <= 0) {
29          self.variationId = parseInt(self.$form.find('input.variation_id').length > 0 ? self.$form.find('input.variation_id').val() : 0);
30        }
31        self.$form.on('reset_data.unit-price-observer', {
32          GermanizedUnitPriceObserver: self
33        }, self.onResetVariation);
34        self.$form.on('found_variation.unit-price-observer', {
35          GermanizedUnitPriceObserver: self
36        }, self.onFoundVariation);
37      } else {
38        if (self.$form && self.$form.find('*[name=add-to-cart][type=submit]').length > 0) {
39          self.productId = parseInt(self.$form.find('*[name=add-to-cart][type=submit]').val());
40        } else if (self.$form && self.$form.data('product_id')) {
41          self.productId = parseInt(self.$form.data('product_id'));
42        } else {
43          var classList = self.$product.attr('class').split(/\s+/);
44
45          /**
46           * Check whether we may find the post/product by a class added by Woo, e.g. post-64
47           */
48          $.each(classList, function (index, item) {
49            if ('post-' === item.substring(0, 5)) {
50              var postId = parseInt(item.substring(5).replace(/[^0-9]/g, ''));
51              if (postId > 0) {
52                self.productId = postId;
53                return true;
54              }
55            }
56          });
57
58          /**
59           * Do only use the add to cart button attribute as fallback as there might be a lot of
60           * other product/add to cart buttons within a single product main product wrap (e.g. related products).
61           */
62          if (self.productId <= 0 && 1 === self.$product.find('a.ajax_add_to_cart[data-product_id], a.add_to_cart_button[data-product_id]').length) {
63            self.productId = parseInt(self.$product.find('a.ajax_add_to_cart, a.add_to_cart_button').data('product_id'));
64          }
65        }
66      }
67      if (self.productId <= 0) {
68        self.destroy(self);
69        return false;
70      }
71      if (self.params.refresh_on_load) {
72        /**
73         * Do not refresh variable products on single product pages
74         * as that leads to race conditions with the Woo Core.
75         */
76        if (self.isVar && self.$form) {
77          self.$form.on('show_variation.unit-price-observer', {
78            GermanizedUnitPriceObserver: self
79          }, function (event) {
80            var self = event.data.GermanizedUnitPriceObserver;
81            self.forceRefresh(self);
82          });
83          self.$form.on('reset_data.unit-price-observer', {
84            GermanizedUnitPriceObserver: self
85          }, function (event) {
86            var self = event.data.GermanizedUnitPriceObserver;
87            self.forceRefresh(self);
88          });
89        } else {
90          self.forceRefresh(self);
91        }
92      }
93    }
94    $wrapper.data('unitPriceObserver', self);
95  };
96  GermanizedUnitPriceObserver.prototype.destroy = function (self) {
97    self = self || this;
98    self.cancelObservers(self);
99    if (self.$form) {
100      self.$form.off('.unit-price-observer');
101    }
102    self.$wrapper.removeClass('has-unit-price-observer');
103  };
104  GermanizedUnitPriceObserver.prototype.getTextWidth = function ($element) {
105    var htmlOrg = $element.html();
106    var html_calc = '<span>' + htmlOrg + '</span>';
107    $element.html(html_calc);
108    var textWidth = $element.find('span:first').width();
109    $element.html(htmlOrg);
110    return textWidth;
111  };
112  GermanizedUnitPriceObserver.prototype.getPriceNode = function (self, priceSelector, isPrimarySelector, visibleOnly) {
113    isPrimarySelector = typeof isPrimarySelector === 'undefined' ? false : isPrimarySelector;
114    visibleOnly = typeof visibleOnly === 'undefined' ? true : visibleOnly;
115    let visibleSelector = visibleOnly ? ':visible' : '';
116    var $node = self.$wrapper.find(priceSelector + ':not(.price-unit)' + visibleSelector).not('.variations_form .single_variation .price').first();
117    if (isPrimarySelector && self.isVar && ($node.length <= 0 || !self.replacePrice)) {
118      $node = self.$wrapper.find('.woocommerce-variation-price span.price:not(.price-unit):last' + visibleSelector);
119    } else if (isPrimarySelector && $node.length <= 0) {
120      $node = self.$wrapper.find('.price:not(.price-unit):last' + visibleSelector);
121    }
122    if ($node.length <= 0 && self.$wrapper.hasClass('wc-block-product')) {
123      $node = self.$wrapper.find('.wc-block-grid__product-price');
124    }
125    return $node;
126  };
127  GermanizedUnitPriceObserver.prototype.getObserverNode = function (self, priceSelector, isPrimarySelector) {
128    var $node = self.getPriceNode(self, priceSelector, isPrimarySelector, false);
129    if (isPrimarySelector && self.isVar && !self.replacePrice) {
130      $node = self.$wrapper.find('.single_variation:last');
131    }
132    return $node;
133  };
134  GermanizedUnitPriceObserver.prototype.getUnitPriceNode = function (self, $price) {
135    if ($price.length <= 0) {
136      return [];
137    }
138    var $element = [];
139    var isSingleProductBlock = $price.parents('.wp-block-woocommerce-product-price[data-is-descendent-of-single-product-template]').length > 0;
140    var isProductGridBlock = self.$wrapper.hasClass('wc-block-product');
141    if ('SPAN' === $price[0].tagName) {
142      $element = self.$wrapper.find('.price-unit');
143    } else {
144      if (isSingleProductBlock) {
145        $element = self.$wrapper.find('.wp-block-woocommerce-gzd-product-unit-price[data-is-descendent-of-single-product-template] .price-unit');
146      } else if (isProductGridBlock) {
147        $element = self.$wrapper.find('.price-unit:not(.wc-gzd-additional-info-placeholder)');
148      } else {
149        $element = self.$wrapper.find('.price-unit:not(.wc-gzd-additional-info-placeholder, .wc-gzd-additional-info-loop)');
150      }
151    }
152
153    /**
154     * Check whether the unit price is empty - prevent refreshing empty prices.
155     */
156    if ($element.length > 0) {
157      if ($element.is(':empty') || $element.find('.wc-gzd-additional-info-placeholder').is(':empty')) {
158        $element = [];
159      }
160    }
161    return $element;
162  };
163  GermanizedUnitPriceObserver.prototype.stopObserver = function (self, priceSelector) {
164    var observer = self.getObserver(self, priceSelector);
165    if (observer) {
166      observer.disconnect();
167    }
168  };
169  GermanizedUnitPriceObserver.prototype.startObserver = function (self, priceSelector, isPrimary) {
170    var observer = self.getObserver(self, priceSelector),
171      $node = self.getObserverNode(self, priceSelector, isPrimary);
172    if (observer) {
173      self.stopObserver(self, priceSelector);
174      if ($node.length > 0) {
175        observer.observe($node[0], {
176          attributes: true,
177          childList: true,
178          subtree: true,
179          characterData: true,
180          attributeFilter: ['style', 'data-force-refresh']
181        });
182      }
183      return true;
184    }
185    return false;
186  };
187  GermanizedUnitPriceObserver.prototype.initObservers = function (self) {
188    if (Object.keys(self.observer).length !== 0) {
189      return;
190    }
191    $.each(self.params.price_selector, function (priceSelector, priceArgs) {
192      var isPrimary = priceArgs.hasOwnProperty('is_primary_selector') ? priceArgs['is_primary_selector'] : false,
193        $observerNode = self.getObserverNode(self, priceSelector, isPrimary),
194        currentObserver = false;
195      if ($observerNode.length > 0 && $observerNode.is(':visible')) {
196        // Callback function to execute when mutations are observed
197        var callback = function (mutationsList, observer) {
198          var $priceNode = self.getPriceNode(self, priceSelector, isPrimary);
199          for (let mutation of mutationsList) {
200            let $element = $(mutation.target);
201            if ($element.length > 0) {
202              let $priceElement;
203              if ($element.is(priceSelector)) {
204                $priceElement = $element;
205              } else {
206                $priceElement = $element.parents(priceSelector);
207              }
208              if ($priceElement.length > 0) {
209                $priceNode = $priceElement;
210              }
211            }
212          }
213
214          /**
215           * Clear the timeout and abort open AJAX requests as
216           * a new mutation has been observed
217           */
218          if (self.timeout) {
219            clearTimeout(self.timeout);
220          }
221          var $unitPrice = self.getUnitPriceNode(self, $priceNode),
222            hasRefreshed = false;
223          if ($priceNode.length <= 0) {
224            return false;
225          }
226          self.stopObserver(self, priceSelector);
227          if ($unitPrice.length > 0) {
228            self.setUnitPriceLoading(self, $unitPrice);
229
230            /**
231             * Need to use a tweak here to make sure our variation listener
232             * has already adjusted the variationId (in case necessary).
233             */
234            self.timeout = setTimeout(function () {
235              self.stopObserver(self, priceSelector);
236              $priceNode = self.getPriceNode(self, priceSelector, isPrimary); // Refresh dom instance as the price element may change during timeout
237
238              if ($priceNode.length > 0) {
239                var priceData = self.getCurrentPriceData(self, $priceNode, priceArgs['is_total_price'], isPrimary, priceArgs['quantity_selector']);
240                var isVisible = $priceNode.is(':visible');
241                if (priceData) {
242                  if (self.isRefreshingUnitPrice(self.getCurrentProductId(self))) {
243                    self.abortRefreshUnitPrice(self.getCurrentProductId(self));
244                  }
245                  hasRefreshed = true;
246                  self.refreshUnitPrice(self, priceData, priceSelector, isPrimary);
247                }
248                if (!hasRefreshed && $unitPrice.length > 0) {
249                  self.unsetUnitPriceLoading(self, $unitPrice);
250                  if (!isVisible && isPrimary) {
251                    $unitPrice.hide();
252                  }
253                }
254              }
255              self.startObserver(self, priceSelector, isPrimary);
256            }, 500);
257          }
258        };
259        if ("MutationObserver" in window) {
260          currentObserver = new window.MutationObserver(callback);
261        } else if ("WebKitMutationObserver" in window) {
262          currentObserver = new window.WebKitMutationObserver(callback);
263        } else if ("MozMutationObserver" in window) {
264          currentObserver = new window.MozMutationObserver(callback);
265        }
266        if (currentObserver) {
267          self.observer[priceSelector] = currentObserver;
268          self.startObserver(self, priceSelector, isPrimary);
269        }
270      }
271    });
272  };
273  GermanizedUnitPriceObserver.prototype.getObserver = function (self, priceSelector) {
274    if (self.observer.hasOwnProperty(priceSelector)) {
275      return self.observer[priceSelector];
276    }
277    return false;
278  };
279  GermanizedUnitPriceObserver.prototype.cancelObservers = function (self) {
280    for (var key in self.observer) {
281      if (self.observer.hasOwnProperty(key)) {
282        self.observer[key].disconnect();
283        delete self.observer[key];
284      }
285    }
286  };
287
288  /**
289   * Reset all fields.
290   */
291  GermanizedUnitPriceObserver.prototype.onResetVariation = function (event) {
292    var self = event.data.GermanizedUnitPriceObserver;
293    self.variationId = 0;
294  };
295  GermanizedUnitPriceObserver.prototype.forceRefresh = function (self) {
296    $.each(self.params.price_selector, function (priceSelector, priceArgs) {
297      var isPrimary = priceArgs.hasOwnProperty('is_primary_selector') ? priceArgs['is_primary_selector'] : false,
298        $price = self.getPriceNode(self, priceSelector, isPrimary),
299        $unitPrice = self.getUnitPriceNode(self, $price);
300
301      /**
302       * Do only refresh primary price nodes on load.
303       */
304      if (!isPrimary) {
305        return;
306      }
307      if ($unitPrice.length > 0) {
308        $price[0].setAttribute('data-force-refresh', 'yes');
309      }
310    });
311  };
312  GermanizedUnitPriceObserver.prototype.onFoundVariation = function (event, variation) {
313    var self = event.data.GermanizedUnitPriceObserver;
314    if (variation.hasOwnProperty('variation_id')) {
315      self.variationId = parseInt(variation.variation_id);
316    }
317    self.initObservers(self);
318  };
319  GermanizedUnitPriceObserver.prototype.getCurrentPriceData = function (self, priceSelector, isTotalPrice, isPrimary, quantitySelector) {
320    quantitySelector = quantitySelector && '' !== quantitySelector ? quantitySelector : self.params.qty_selector;
321    var $price = typeof priceSelector === 'string' || priceSelector instanceof String ? self.getPriceNode(self, priceSelector, isPrimary) : priceSelector;
322    if ($price.length > 0) {
323      // Add a tmp hidden class to detect hidden elements in cloned obj
324      $price.find(':hidden').addClass('wc-gzd-is-hidden');
325      var $unit_price = self.getUnitPriceNode(self, $price),
326        $priceCloned = $price.clone();
327
328      // Remove price suffix from cloned DOM element to prevent finding the wrong (sale) price
329      $priceCloned.find('.woocommerce-price-suffix').remove();
330      $priceCloned.find('.wc-gzd-is-hidden').remove();
331      var sale_price = '',
332        $priceInner = $priceCloned.find('.amount:first'),
333        $qty = $(self.params.wrapper + ' ' + quantitySelector + ':first'),
334        qty = 1,
335        is_range = false;
336      if ($qty.length > 0) {
337        qty = parseFloat($qty.val());
338      }
339
340      /**
341       * In case the price element does not contain the default Woo price structure
342       * search the whole element.
343       */
344      if ($priceInner.length <= 0) {
345        if ($priceCloned.find('.price').length > 0) {
346          $priceInner = $priceCloned.find('.price');
347        } else {
348          $priceInner = $priceCloned;
349        }
350      }
351      var price = self.getRawPrice($priceInner, self.params.price_decimal_sep);
352
353      /**
354       * Is sale?
355       */
356      if ($priceCloned.find('.amount').length > 1) {
357        // The second .amount element is the sale price
358        var $sale_price = $($priceCloned.find('.amount')[1]);
359        sale_price = self.getRawPrice($sale_price, self.params.price_decimal_sep);
360      }
361
362      /**
363       * Is price range, e.g. variable products
364       */
365      if (sale_price && $priceCloned.find('del').length <= 0) {
366        is_range = true;
367      }
368      $price.find('.wc-gzd-is-hidden').removeClass('wc-gzd-is-hidden');
369      if ($unit_price.length > 0 && price) {
370        if (isTotalPrice) {
371          price = parseFloat(price) / qty;
372          if (sale_price) {
373            sale_price = parseFloat(sale_price) / qty;
374          }
375        }
376        return {
377          'price': price,
378          'unit_price': $unit_price,
379          'sale_price': sale_price,
380          'quantity': qty,
381          'is_range': is_range
382        };
383      }
384    }
385    return false;
386  };
387  GermanizedUnitPriceObserver.prototype.getCurrentProductId = function (self) {
388    var productId = self.productId;
389    if (self.variationId > 0) {
390      productId = self.variationId;
391    }
392    return parseInt(productId);
393  };
394  GermanizedUnitPriceObserver.prototype.getRawPrice = function ($el, decimal_sep) {
395    var price_raw = $el.length > 0 ? $el.text() : '',
396      price = false;
397    try {
398      price = accounting.unformat(price_raw, decimal_sep);
399    } catch (e) {
400      price = false;
401    }
402    return price;
403  };
404  GermanizedUnitPriceObserver.prototype.setUnitPriceLoading = function (self, $unit_price) {
405    var unitPriceOrg = $unit_price.html();
406    if (!$unit_price.hasClass('wc-gzd-loading')) {
407      if ($unit_price.find('.wc-gzd-placeholder-loading').length <= 0) {
408        var textWidth = self.getTextWidth($unit_price),
409          textHeight = $unit_price.find('span').length > 0 ? $unit_price.find('span').innerHeight() : $unit_price.height();
410        /**
411         * @see https://github.com/zalog/placeholder-loading
412         */
413        $unit_price.html('<span class="wc-gzd-placeholder-loading"><span class="wc-gzd-placeholder-row" style="height: ' + $unit_price.height() + 'px;"><span class="wc-gzd-placeholder-row-col-4" style="width: ' + textWidth + 'px; height: ' + textHeight + 'px;"></span></span></span>');
414      }
415      $unit_price.addClass('wc-gzd-loading');
416    }
417    $unit_price.data('org-html', unitPriceOrg);
418    return unitPriceOrg;
419  };
420  GermanizedUnitPriceObserver.prototype.unsetUnitPriceLoading = function (self, $unit_price, newHtml) {
421    newHtml = newHtml || $unit_price.data('org-html');
422    $unit_price.html(newHtml);
423    if ($unit_price.hasClass('wc-gzd-loading')) {
424      $unit_price.removeClass('wc-gzd-loading');
425    }
426    if (typeof newHtml === "string" && newHtml.length > 0) {
427      $unit_price.show();
428    }
429  };
430  GermanizedUnitPriceObserver.prototype.isRefreshingUnitPrice = function (currentProductId) {
431    return germanized.unit_price_observer_queue.exists(currentProductId);
432  };
433  GermanizedUnitPriceObserver.prototype.abortRefreshUnitPrice = function (currentProductId) {
434    return germanized.unit_price_observer_queue.abort(currentProductId);
435  };
436  GermanizedUnitPriceObserver.prototype.refreshUnitPrice = function (self, priceData, priceSelector, isPrimary) {
437    germanized.unit_price_observer_queue.add(self, self.getCurrentProductId(self), priceData, priceSelector, isPrimary);
438  };
439
440  /**
441   * Function to call wc_gzd_variation_form on jquery selector.
442   */
443  $.fn.wc_germanized_unit_price_observer = function () {
444    if ($(this).data('unitPriceObserver')) {
445      $(this).data('unitPriceObserver').destroy();
446    }
447    new GermanizedUnitPriceObserver(this);
448    return this;
449  };
450  $(function () {
451    if (typeof wc_gzd_unit_price_observer_params !== 'undefined') {
452      const initObservations = function () {
453        $(wc_gzd_unit_price_observer_params.wrapper).each(function () {
454          if ($(this).is('body')) {
455            return;
456          }
457          $(this).wc_germanized_unit_price_observer();
458        });
459      };
460      initObservations();
461
462      /**
463       * Support (async) navigation for product collection block
464       */
465      if ($('.wp-block-woocommerce-product-collection').length > 0) {
466        let currentObserver = false;
467        const maybeInitObserver = function (mutationsList, observer) {
468          let needsInit = false;
469          for (let mutation of mutationsList) {
470            let $element = $(mutation.target);
471            if ($element.length > 0 && 'woocommerce/product-template' === $element.data('block-name')) {
472              needsInit = true;
473              break;
474            }
475          }
476          if (needsInit) {
477            initObservations();
478          }
479        };
480        if ("MutationObserver" in window) {
481          currentObserver = new window.MutationObserver(maybeInitObserver);
482        } else if ("WebKitMutationObserver" in window) {
483          currentObserver = new window.WebKitMutationObserver(maybeInitObserver);
484        } else if ("MozMutationObserver" in window) {
485          currentObserver = new window.MozMutationObserver(maybeInitObserver);
486        }
487        if (currentObserver) {
488          $('.wp-block-woocommerce-product-collection').each(function () {
489            let $node = $(this);
490            currentObserver.observe($node[0], {
491              childList: true,
492              subtree: true
493            });
494          });
495        }
496      }
497    }
498  });
499})(jQuery, window, document);
500window.germanized = window.germanized || {};
501((window.germanized = window.germanized || {})["static"] = window.germanized["static"] || {})["unit-price-observer"] = __webpack_exports__;
502/******/ })()
503;

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.