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.