PageSourceSearch

https://www.orbitresearch.com/wp-content/plugins/quick-buy-now-but…/build/frontend.js?ver=1.1.7

js orbitresearch.com collected 2026-09-24 17:40:42 UTC 18,632 bytes, 579 lines download raw bytes

1/******/ (() => { // webpackBootstrap
2/******/ 	// The require scope
3/******/ 	var __webpack_require__ = {};
4/******/ 	
5/************************************************************************/
6/******/ 	/* webpack/runtime/make namespace object */
7/******/ 	(() => {
8/******/ 		// define __esModule on exports
9/******/ 		__webpack_require__.r = (exports) => {
10/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
11/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
12/******/ 			}
13/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
14/******/ 		};
15/******/ 	})();
16/******/ 	
17/************************************************************************/
18var __webpack_exports__ = {};
19// This entry needs to be wrapped in an IIFE because it needs to be isolated against other entry modules.
20(() => {
21/*!****************************!*\
22  !*** ./src/js/frontend.js ***!
23  \****************************/
24/* global wbnb_params */
25
26(function ($) {
27  'use strict';
28
29  /**
30   * Initialize on document ready
31   */
32  $(document).ready(function () {
33    handleAjaxAddToCart();
34    handleBuyNowButtons();
35    WBNB_Popup.init();
36    $('button.wc-buy-now-btn-single').on('click', function (e) {
37      // Check if a valid variation is selected before proceeding buy now button
38      if (!validateVariation($(this), e)) {
39        return;
40      }
41
42      // To fix other plugins ajax trigger on buy now button
43      if (!wbnb_params.is_popup) {
44        e.stopImmediatePropagation();
45      }
46    });
47  });
48
49  /**
50   * Check if a valid variation is selected before proceeding
51   * @return {boolean} false if validation failed (event stopped), true otherwise
52   */
53  function validateVariation($button, e) {
54    if ($button.is('.disabled')) {
55      e.preventDefault();
56      e.stopImmediatePropagation();
57      if ($button.is('.wc-variation-is-unavailable')) {
58        window.alert(wbnb_params.i18n_unavailable_text);
59      } else if ($button.is('.wc-variation-selection-needed')) {
60        window.alert(wbnb_params.i18n_make_a_selection_text);
61      }
62      return false;
63    }
64    return true;
65  }
66
67  /**
68   * Data collector for form data
69   */
70  const DataCollector = {
71    /**
72     * Collect variation attributes from form
73     */
74    collectVariations($form) {
75      const variation = {};
76      $form.find('select[name^="attribute_"], input[name^="attribute_"]').each(function () {
77        const name = $(this).attr('name');
78        variation[name] = $(this).val();
79      });
80      return variation;
81    },
82    /**
83     * Collect group product quantities
84     */
85    collectQuantities($form) {
86      const quantities = {};
87      $form.find('input[name^="quantity"]').each(function () {
88        const matches = $(this).attr('name').match(/^quantity\[(\d+)]$/);
89        if (matches?.[1]) {
90          quantities[matches[1]] = parseInt($(this).val(), 10) || 0;
91        }
92      });
93      return quantities;
94    },
95    /**
96     * Get product ID from form
97     */
98    getProductId($form, isBuyNow = false, $button = null) {
99      if (isBuyNow && $button) {
100        return $button.val();
101      }
102      return $form.find('button[name="add-to-cart"], input[name="add-to-cart"], input[name="product_id"]').val();
103    },
104    /**
105     * Collect all form data for cart action
106     */
107    collectFormData($form, isBuyNow = false, $button = null) {
108      const productId = this.getProductId($form, isBuyNow, $button);
109      const quantity = $form.find('input[name="quantity"]').val() || 1;
110      const variationId = $form.find('input[name="variation_id"]').val() || 0;
111      const variation = this.collectVariations($form);
112      const quantities = this.collectQuantities($form);
113      return {
114        productId,
115        quantity,
116        variationId,
117        variation,
118        quantities
119      };
120    }
121  };
122
123  /**
124   * Handle AJAX cart operations
125   */
126  const AjaxCartHandler = {
127    /**
128     * Send ajax add to cart request
129     */
130    sendRequest(data, $button, isBuyNow, isPopup) {
131      $button.addClass('loading');
132      return $.post(wbnb_params.ajax_url, data).done(response => this.handleSuccess(response, $button, isBuyNow, isPopup)).fail(response => this.handleError(response)).always(() => $button.removeClass('loading'));
133    },
134    /**
135     * Handle successful AJAX response
136     */
137    handleSuccess(response, $button, isBuyNow, isPopup) {
138      if (!response.success) {
139        this.handleError(response, $button);
140        return;
141      }
142      const {
143        fragments = {},
144        cart_hash = '',
145        redirect_url = '',
146        checkout_template = '',
147        notices = ''
148      } = response.data || {};
149
150      // Trigger standard WC events (classic theme)
151      $(document.body).trigger('added_to_cart', [fragments, cart_hash, $button]);
152
153      // Trigger WooCommerce Blocks native event for the Mini Cart block
154      document.body.dispatchEvent(new CustomEvent('wc-blocks_added_to_cart', {
155        bubbles: true,
156        cancelable: true,
157        detail: {
158          fragments,
159          cart_hash
160        }
161      }));
162      if (isBuyNow) {
163        this.handleBuyNowRedirect(isPopup, checkout_template, redirect_url);
164      } else {
165        // Standard Add to Cart: Stay on page
166        $(document.body).trigger('wc_fragment_refresh');
167
168        // Inject WC notices ("Product added to cart [View Cart]").
169        // Handles FSE themes where the fragment system returns no notices.
170        this.injectWooCommerceNotices(notices);
171      }
172    },
173    /**
174     * Handle buy now redirect or popup
175     */
176    handleBuyNowRedirect(isPopup, checkoutTemplate, redirectUrl) {
177      if (isPopup) {
178        const hasPopup = $('#wbnb-popup-overlay').length > 0;
179        if (hasPopup && checkoutTemplate) {
180          WBNB_Popup.open(checkoutTemplate);
181        } else {
182          window.location.href = redirectUrl || wbnb_params.checkout_url;
183        }
184      } else {
185        window.location.href = redirectUrl;
186      }
187    },
188    /**
189     * Inject WooCommerce notices HTML into the page.
190     *
191     * In classic themes, the "Product added to cart [View Cart]" notice is included
192     * in cart fragments and injected automatically. In FSE themes the fragment system
193     * is empty (no widget areas registered), so we receive the notices HTML from the
194     * PHP response and inject it ourselves.
195     *
196     * Creates .woocommerce-notices-wrapper at the top of <main> (or <body> as fallback)
197     * if it does not already exist, matching WooCommerce's own DOM convention.
198     * Auto-hides success notices after 5 s, mirroring WooCommerce JS behaviour.
199     *
200     * Safe to call with an empty string — returns immediately without DOM changes.
201     */
202    injectWooCommerceNotices(noticesHtml) {
203      if (!noticesHtml) {
204        return;
205      }
206
207      // Find or create the notices wrapper
208      let $wrapper = $('.woocommerce-notices-wrapper').first();
209      if (!$wrapper.length) {
210        $wrapper = $('<div class="woocommerce-notices-wrapper"></div>');
211        // Prefer injecting at the top of <main>, fall back to after <body> open
212        const $main = $('main').first();
213        if ($main.length) {
214          $main.prepend($wrapper);
215        } else {
216          $('body').prepend($wrapper);
217        }
218      }
219      $wrapper.html(noticesHtml);
220
221      // Auto-dismiss success messages after 5 s (matches WooCommerce default JS)
222      setTimeout(() => {
223        $wrapper.find('.woocommerce-message').fadeOut(400, function () {
224          $(this).remove();
225        });
226      }, 5000);
227    },
228    /**
229     * Handle AJAX errors
230     */
231    handleError(response) {
232      const message = response.data?.message;
233      if (message) {
234        alert(message);
235      } else {
236        console.log(response);
237      }
238    }
239  };
240
241  /**
242   * Popup manager
243   */
244  const WBNB_Popup = {
245    isOpen: false,
246    isLoading: false,
247    /**
248     * Initialize popup event listeners
249     */
250    init() {
251      $(document).on('click', '.wbnb-popup-close, #wbnb-popup-overlay', e => {
252        if ($(e.target).is('#wbnb-popup-overlay') || $(e.target).hasClass('wbnb-popup-close')) {
253          this.close();
254        }
255      });
256      $(document).on('keyup', e => {
257        if (this.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
258          this.close();
259        }
260      });
261
262      // Prevent closing when clicking inside content
263      $(document).on('click', '#wbnb-popup-content', e => {
264        e.stopPropagation();
265      });
266    },
267    /**
268     * Open popup with optional HTML content
269     */
270    open(html) {
271      if (this.isOpen || this.isLoading) {
272        return;
273      }
274      this.isOpen = true;
275      this.isLoading = true;
276      const $overlay = $('#wbnb-popup-overlay');
277      const $inner = $overlay.find('.wbnb-popup-inner');
278      $overlay.addClass('wbnb-show');
279      if (html) {
280        $inner.html(html);
281        this.initWooCommerceCheckout();
282      } else {
283        $inner.html('<div class="wbnb-loader">Loading Checkout...</div>');
284      }
285      this.isLoading = false;
286    },
287    /**
288     * Initialize WooCommerce checkout in popup
289     */
290    initWooCommerceCheckout() {
291      if (typeof wc_checkout_params === 'undefined') {
292        return;
293      }
294      const $popupContent = $('#wbnb-popup-content');
295      const $checkoutForm = $popupContent.find('form.checkout');
296      if (!$checkoutForm.length) {
297        return;
298      }
299
300      // Trigger standard WC checkout initialization
301      $(document.body).trigger('init_checkout');
302      $(document.body).trigger('update_checkout');
303
304      // Intercept form submission to handle errors in popup
305      $checkoutForm.off('submit.wbnb_popup').on('submit.wbnb_popup', function (e) {
306        const $form = $(this);
307        if ($form.is('.processing')) {
308          return false;
309        }
310
311        // Get payment method
312        const paymentMethod = $form.find('input[name="payment_method"]:checked').val();
313
314        // Let payment gateways do their thing
315        if ($form.triggerHandler('checkout_place_order') !== false && $form.triggerHandler('checkout_place_order_' + paymentMethod) !== false) {
316          $form.addClass('processing');
317
318          // Block the form
319          $form.block({
320            message: null,
321            overlayCSS: {
322              background: '#fff',
323              opacity: 0.6
324            }
325          });
326
327          // Submit via AJAX
328          $.ajax({
329            type: 'POST',
330            url: wc_checkout_params.checkout_url,
331            data: $form.serialize(),
332            dataType: 'json',
333            success: function (result) {
334              try {
335                if ('success' === result.result) {
336                  // Successful order - redirect
337                  if (-1 === result.redirect.indexOf('https://') || -1 === result.redirect.indexOf('http://')) {
338                    window.location = result.redirect;
339                  } else {
340                    window.location = decodeURI(result.redirect);
341                  }
342                } else if ('failure' === result.result) {
343                  throw 'Result failure';
344                } else {
345                  throw 'Invalid response';
346                }
347              } catch (err) {
348                // Reload page if requested
349                if (true === result.reload) {
350                  window.location.reload();
351                  return;
352                }
353
354                // Trigger update in case we need a fresh nonce
355                if (true === result.refresh) {
356                  $(document.body).trigger('update_checkout');
357                }
358
359                // Display errors in popup
360                if (result.messages) {
361                  WBNB_Popup.showCheckoutError(result.messages, $form);
362                } else {
363                  WBNB_Popup.showCheckoutError('<div class="woocommerce-error">' + wc_checkout_params.i18n_checkout_error + '</div>', $form);
364                }
365              }
366            },
367            error: function (jqXHR, textStatus, errorThrown) {
368              WBNB_Popup.showCheckoutError('<div class="woocommerce-error">' + errorThrown + '</div>', $form);
369            }
370          });
371        }
372        return false;
373      });
374    },
375    /**
376     * Show checkout error in popup
377     */
378    showCheckoutError(error_message, $form) {
379      const $popupContent = $('#wbnb-popup-content');
380
381      // Remove existing errors
382      $popupContent.find('.woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message, .is-error, .is-success').remove();
383
384      // Add error to form
385      $form.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + error_message + '</div>');
386
387      // Unblock and remove processing class
388      $form.removeClass('processing').unblock();
389      $form.find('.input-text, select, input:checkbox').trigger('validate').trigger('blur');
390
391      // Scroll to error
392      this.scrollToNotices();
393
394      // Focus on error
395      $form.find('.woocommerce-error[tabindex="-1"]').focus();
396
397      // Trigger event
398      $(document.body).trigger('checkout_error', [error_message]);
399    },
400    /**
401     * Scroll to error notices within popup
402     */
403    scrollToNotices() {
404      const $popupContent = $('#wbnb-popup-content');
405      const $scrollElement = $popupContent.find('.woocommerce-NoticeGroup-checkout, .woocommerce-error').first();
406      if ($scrollElement.length) {
407        const scrollTop = $scrollElement.position().top - 20;
408        $popupContent.animate({
409          scrollTop: scrollTop
410        }, 500);
411      }
412    },
413    /**
414     * Close popup
415     */
416    close() {
417      // Remove form submission handler
418      $('#wbnb-popup-content form.checkout').off('submit.wbnb_popup');
419      this.isOpen = false;
420      $('#wbnb-popup-overlay').removeClass('wbnb-show');
421    }
422  };
423
424  /**
425   * Event handler for standard add to cart
426   */
427  function handleAjaxAddToCart() {
428    if (!wbnb_params.is_ajax) {
429      return;
430    }
431    $(document).on('click', '.single_add_to_cart_button:not([data-wc-buy-now="true"], .disabled)', function (e) {
432      const $button = $(this);
433      const $form = $button.closest('form.cart');
434      if ($form.length === 0) {
435        return;
436      }
437
438      // Check if the product type is supported for this specific form/button
439      let productType = $button.data('product_type') || $form.data('product_type');
440      if (!productType) {
441        // Fallback detection
442        if ($form.hasClass('variations_form')) {
443          productType = 'variable';
444        } else if ($form.find('.grouped_form').length || $form.find('table.group_table').length) {
445          productType = 'grouped';
446        } else {
447          // Fallback to body class for standard single product pages
448          const bodyClasses = $('body').attr('class') || '';
449          const match = bodyClasses.match(/product-type-([^\s]+)/);
450          productType = match ? match[1] : 'simple';
451        }
452      }
453      if (wbnb_params.product_types && !wbnb_params.product_types.includes(productType)) {
454        return; // Let WooCommerce handle it (standard form submit)
455      }
456      e.preventDefault();
457      const {
458        productId,
459        quantity,
460        variationId,
461        variation,
462        quantities
463      } = DataCollector.collectFormData($form);
464
465      // Validate group product quantities
466      if ($form.find('input[name^="quantity"]').length > 1 && Object.values(quantities).every(q => q === 0)) {
467        alert('Please choose the quantity of items you wish to add to your cart.');
468        return;
469      }
470      const data = {
471        action: 'wbnb_add_to_cart',
472        is_buy_now: false,
473        product_id: productId,
474        quantity,
475        quantities,
476        variation_id: variationId,
477        variation,
478        nonce: wbnb_params.nonce
479      };
480      $(document.body).trigger('adding_to_cart', [$button, data]);
481      AjaxCartHandler.sendRequest(data, $button, false, false);
482    });
483  }
484
485  /**
486   * Event handler for buy now buttons
487   */
488  function handleBuyNowButtons() {
489    $(document).on('click', '.wc-buy-now-btn[data-redirect-location="popup-checkout"]', function (e) {
490      const $this = $(this);
491
492      // Variation validation (same as WooCommerce's Add to Cart)
493      if (!validateVariation($this, e)) {
494        return;
495      }
496
497      // Check for product type support
498      const productType = $this.data('product_type') || $this.closest('form').data('product_type') || 'simple';
499      if (wbnb_params.product_types && !wbnb_params.product_types.includes(productType)) {
500        return; // Let browser handle it naturally
501      }
502
503      // Only handle with JavaScript if it's a buy now button with popup-checkout
504      e.preventDefault();
505      e.stopImmediatePropagation();
506      if (!wbnb_params.is_popup) {
507        // Let browser handle it naturally (form submit or link navigation)
508        return;
509      }
510
511      // Handle button submit
512      if ($this.is('button[type="submit"]') || $this.is('input[type="submit"]')) {
513        handleButtonSubmitForPopup($this);
514      }
515      // Handle link click
516      else if ($this.is('a')) {
517        handleLinkClickForPopup($this);
518      }
519    });
520  }
521
522  /**
523   * Handle button submit for popup checkout
524   */
525  function handleButtonSubmitForPopup($button) {
526    const $form = $button.closest('form');
527    if ($form.length === 0) {
528      return;
529    }
530    const {
531      productId,
532      quantity,
533      variationId,
534      variation
535    } = DataCollector.collectFormData($form, true, $button);
536    const data = {
537      action: 'wbnb_add_to_cart',
538      product_id: productId,
539      is_buy_now: true,
540      quantity,
541      variation_id: variationId,
542      variation,
543      nonce: wbnb_params.nonce
544    };
545    AjaxCartHandler.sendRequest(data, $button, true, true);
546  }
547
548  /**
549   * Handle link click for popup checkout from archive pages
550   */
551  function handleLinkClickForPopup($link) {
552    const productId = $link.data('product_id');
553    const quantity = $link.data('quantity') || 1;
554    const data = {
555      action: 'wbnb_add_to_cart',
556      product_id: productId,
557      is_buy_now: true,
558      quantity,
559      nonce: wbnb_params.nonce
560    };
561    AjaxCartHandler.sendRequest(data, $link, true, true);
562  }
563})(jQuery);
564})();
565
566// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
567(() => {
568"use strict";
569/*!********************************!*\
570  !*** ./src/scss/frontend.scss ***!
571  \********************************/
572__webpack_require__.r(__webpack_exports__);
573// extracted by mini-css-extract-plugin
574
575})();
576
577/******/ })()
578;
579//# sourceMappingURL=frontend.js.map

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.