PageSourceSearch

https://pizzabytango.ro/wp-content/plugins/horeka-core/assets/js/woocommerce/rpd-custom-code.min.js?ver=1.7.2

js pizzabytango.ro collected 2026-10-02 02:06:46 UTC 24,372 bytes, 545 lines download raw bytes

1jQuery(function ($) {
2  // Shorthand for document ready and self-executing anonymous function
3
4  /* ========================================================================
5   * Utility Functions
6   * ======================================================================== */
7
8  // --- Cookie Functions (Defined Once) ---
9  function setCookie(cname, cvalue, exdays) {
10    var d = new Date();
11    d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
12    var expires = 'expires=' + d.toUTCString();
13    // Added Secure and SameSite=Lax for better security
14    document.cookie =
15      cname + '=' + encodeURIComponent(cvalue) + ';' + expires + ';path=/;SameSite=Lax' + (window.location.protocol === 'https:' ? ';Secure' : '');
16  }
17
18  function getCookie(cname) {
19    var name = cname + '=';
20    var decodedCookie = '';
21    try {
22      decodedCookie = decodeURIComponent(document.cookie);
23    } catch (e) {
24      console.error('Error decoding cookie:', e);
25      return '';
26    }
27    var ca = decodedCookie.split(';');
28    for (var i = 0; i < ca.length; i++) {
29      var c = ca[i];
30      while (c.charAt(0) == ' ') {
31        c = c.substring(1);
32      }
33      if (c.indexOf(name) == 0) {
34        return c.substring(name.length, c.length);
35      }
36    }
37    return '';
38  }
39
40  /* ========================================================================
41   * Function to change text color based on background (Currently Commented Out)
42   * ======================================================================== */
43  /*
44    function changeTextColor(obj) {
45        if (!obj || obj.length === 0) return; // Exit if element doesn't exist
46        var rgb = obj.css('background-color');
47
48        if (typeof rgb === 'undefined' || !rgb || rgb === 'transparent') {
49            // console.log('Background color not defined or transparent for element:', obj);
50            return; // Exit if background is not set or transparent
51        }
52
53        var pattern;
54        var matches;
55        if (rgb.startsWith("rgba")) {
56            pattern = /^rgba\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([0-1]?\.?\d*)\)$/;
57            matches = rgb.match(pattern);
58        } else if (rgb.startsWith("rgb")) {
59            pattern = /^rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)$/;
60            matches = rgb.match(pattern);
61        } else {
62             // Handle other formats like hex if needed, or ignore
63             // console.log('Color format not recognized:', rgb);
64             return;
65        }
66
67
68        if (!matches) {
69            // console.log('Color format could not be parsed:', rgb);
70            return;
71        }
72
73        var red = parseInt(matches[1], 10);
74        var green = parseInt(matches[2], 10);
75        var blue = parseInt(matches[3], 10);
76        // Alpha is 1 if not specified (rgb) or if explicitly 1 in rgba
77        var alpha = (matches[4] !== undefined) ? parseFloat(matches[4]) : 1;
78
79        // If alpha is too low, text is likely readable with default dark color
80        if (alpha < 0.5) {
81            // console.log("RGBA Alpha too low", alpha);
82            obj.css('color', '#444444'); // Use CSS classes preferably
83            return;
84        }
85
86        // Calculate perceived brightness (Luma formula)
87        var colorValue = Math.round(((red * 299) + (green * 587) + (blue * 114)) / 1000);
88
89        // Determine text color based on brightness
90        if (colorValue > 125) { // Background is light
91            // console.log("Light background", colorValue);
92            obj.css('color', '#444444'); // Dark text
93        } else { // Background is dark
94            // console.log("Dark background", colorValue);
95            obj.css('color', 'white'); // Light text
96        }
97    }
98
99    // --- Apply text color changes (Currently Commented Out) ---
100    // Consider applying these via CSS based on a class added by this function instead of inline styles
101    // changeTextColor($(".single_add_to_cart_button"));
102    // changeTextColor($("#backtotop"));
103    // changeTextColor($(".btn-primary-slide"));
104    // changeTextColor($(".cart_trigger .counter"));
105    // changeTextColor($(".btnMinus"));
106    // changeTextColor($(".btnPlus"));
107    // changeTextColor($(".woocommerce-mini-cart__buttons a.button"));
108    // changeTextColor($(".best_selling_custom .btn_order_now a"));
109    // changeTextColor($(".slide_button .btn-primary-slide"));
110    // changeTextColor($(".rezervare-section a"));
111    // changeTextColor($(".inner-menu-box a"));
112
113    // Apply on checkout update for place order button
114    // $('body').on('updated_checkout checkout_error', function () {
115    //     changeTextColor($("#place_order"));
116    // });
117    */
118
119  /* ========================================================================
120   * Checkout Error Handling & UI
121   * ======================================================================== */
122
123  // --- Add dismiss button to WC Blocks notices and handle general checkout state ---
124  $('body').on('updated_checkout checkout_error', function () {
125    // Stop animations on checkout update/error (use with caution)
126    if ($('body').hasClass('woocommerce-checkout') || $('body').hasClass('woocommerce-cart')) {
127      // $('html, body').stop(); // Can interfere with legitimate scrolling/animations
128    }
129
130    // Add dismiss 'x' to specific error banners (targets WC Blocks structure)
131    var $errorBanners = $(
132      '.wc-block-components-notice-banner.is-error, .woocommerce-NoticeGroup-checkout .is-error .wc-block-components-notice-banner__content'
133    );
134    $errorBanners.each(function () {
135      if ($(this).find('.dismiss_error').length === 0) {
136        $(this).append(
137          '<span class="dismiss_error" title="Dismiss" style="cursor:pointer; float:right; padding: 0 5px; font-weight:bold;">&times;</span>'
138        ); // Simple X
139      }
140    });
141
142    // Auto-check terms checkbox? (Consider removing - bad practice)
143    $('#terms_declaration_nutritional').prop('checked', true);
144  });
145
146  // --- Handle dismiss button click ---
147  // Targets standard WC notice group and the custom dismiss span
148  $(document).on('click', '.dismiss_error', function () {
149    $(this).closest('.woocommerce-NoticeGroup, .wc-block-components-notice-banner').fadeOut(200); // Hide the notice
150  });
151
152  /* ========================================================================
153   * General UI Interactions
154   * ======================================================================== */
155
156  // --- Tab Block Functionality ---
157  $(document).on('click', '.tab_block_main ul li a', function (e) {
158    e.preventDefault();
159    var $link = $(this);
160    var $tabBlockMain = $link.closest('.tab_block_main'); // Find parent container
161    var curTabContentId = $link.attr('href');
162
163    // Update active states for links and content
164    $tabBlockMain.find('ul li a').removeClass('active');
165    $link.addClass('active');
166    $tabBlockMain.find('.tab_content .tab_block').removeClass('active');
167    $(curTabContentId).addClass('active');
168  });
169
170  // --- Billing Phone Validation ---
171  var $billingPhone = $('#billing_phone');
172  if ($billingPhone.length) {
173    // Only run if the field exists
174    var invalid_number_message = 'Introdu un numar valid.'; // Define the invalid message
175    var max_length_message = 'Numarul de telefon trebuie să fie de cel mult 15 cifre.'; // Define the max length message
176    var $phoneErrorSpan = $('<span class="phone-error" style="color:red; display:none; width: 100%; font-size: 0.9em;"></span>'); // Create error span
177
178    // Insert error span after the input field if it doesn't exist
179    if ($billingPhone.next('.phone-error').length === 0) {
180      $billingPhone.after($phoneErrorSpan);
181    }
182
183    // Attach blur event listener
184    $billingPhone.on('blur', function () {
185      var phoneNumber = $(this).val();
186      var isValid = true;
187      var message = '';
188
189      // Check max length first
190      if (phoneNumber.length > 15) {
191        message = max_length_message;
192        isValid = false;
193      }
194      // Check format only if length is okay and field is not empty
195      else if (phoneNumber.length > 0 && !validatePhoneNumber(phoneNumber)) {
196        message = invalid_number_message;
197        isValid = false;
198      }
199
200      // Show/hide error message
201      if (!isValid) {
202        $phoneErrorSpan.text(message).show();
203      } else {
204        $phoneErrorSpan.hide();
205      }
206    });
207
208    // Custom phone number validation function
209    function validatePhoneNumber(phoneNumber) {
210      // Allow optional '+' at the beginning, then digits, min length depends on format
211      // Romanian specific + general international
212      var roLocalPattern = /^07\d{8}$/; // 07xxxxxxxx
213      var roInternationalPattern = /^(?:\+4|4)07\d{8}$/; // +407xxxxxxxx or 407xxxxxxxx
214      var internationalPattern = /^\+\d{9,14}$/; // Allows + followed by 9 to 14 digits (adjust range if needed)
215
216      return roLocalPattern.test(phoneNumber) || roInternationalPattern.test(phoneNumber) || internationalPattern.test(phoneNumber);
217    }
218  } // end if billing_phone exists
219
220  // --- Fetch Google API Key via AJAX ---
221  function getGoogleApiKeyFct() {
222    // Check if key already exists to avoid redundant calls
223    if (getCookie('defaultGoogleKey')) {
224      return;
225    }
226    // URL and key should ideally come from wp_localize_script
227    var apiKeyFromCookie = getCookie('geoloc_k'); // Unsecure way to get initial key
228    if (!apiKeyFromCookie) return; // Don't run if prerequisite cookie is missing
229
230    var getGoogleApiKeySettings = {
231      url: 'https://api.rpd.roweb.ro/api/venue/integration/wordpress/getvenuedetails', // Hardcoded URL
232      method: 'POST',
233      timeout: 5000, // Added timeout
234      headers: {
235        ApiKey: apiKeyFromCookie, // Key from cookie
236        Origin: document.location.origin,
237      },
238    };
239
240    $.ajax(getGoogleApiKeySettings)
241      .done(function (response) {
242        if (response && response.data && response.data.defaultGoogleKey) {
243          setCookie('defaultGoogleKey', response.data.defaultGoogleKey, 365); // Store fetched key
244        } else {
245          console.error('Could not retrieve defaultGoogleKey from API response.');
246        }
247      })
248      .fail(function (jqXHR, textStatus, errorThrown) {
249        console.error('Failed to fetch Google API Key:', textStatus, errorThrown);
250      });
251  }
252  // Fetch the key on load
253  getGoogleApiKeyFct();
254
255  // --- Custom Tooltip Implementation ---
256  var targets = $('[rel~=tooltip]'); // Target elements with rel="tooltip"
257  var tooltipVisible = false; // Flag to manage tooltip state
258  var hideTooltipTimeout; // Timeout reference
259
260  targets.on('mouseenter focus', function () {
261    // Trigger on focus too for accessibility
262    if (tooltipVisible) return; // Prevent multiple tooltips
263
264    var $target = $(this);
265    var tip = $target.attr('title');
266    if (!tip || tip === '') return false; // Exit if no title
267
268    tooltipVisible = true;
269    $target.data('original-title', tip).removeAttr('title'); // Store original title
270
271    var $tooltip = $('<div id="tooltip"></div>').html(tip).appendTo('body');
272
273    function positionTooltip() {
274      if (!$tooltip) return; // Exit if tooltip was removed
275
276      var targetWidth = $target.outerWidth();
277      var targetHeight = $target.outerHeight();
278      var targetLeft = $target.offset().left;
279      var targetTop = $target.offset().top;
280      var tooltipWidth = $tooltip.outerWidth();
281      var tooltipHeight = $tooltip.outerHeight();
282      var windowWidth = $(window).width();
283      var scrollY = $(window).scrollTop();
284
285      // Default position above the target
286      var pos_left = targetLeft + targetWidth / 2 - tooltipWidth / 2;
287      var pos_top = targetTop - tooltipHeight - 10; // 10px spacing
288
289      // Adjust horizontal position if out of bounds
290      if (pos_left < 0) {
291        pos_left = 5; // Add some padding from edge
292        $tooltip.addClass('left-arrow'); // Add class for arrow styling
293      } else {
294        $tooltip.removeClass('left-arrow');
295      }
296      if (pos_left + tooltipWidth > windowWidth) {
297        pos_left = windowWidth - tooltipWidth - 5;
298        $tooltip.addClass('right-arrow');
299      } else {
300        $tooltip.removeClass('right-arrow');
301      }
302
303      // Adjust vertical position if out of bounds (prefer below if no space above)
304      if (pos_top < scrollY) {
305        // Check against scroll position
306        pos_top = targetTop + targetHeight + 10;
307        $tooltip.addClass('top-arrow'); // Actually means arrow points up now
308      } else {
309        $tooltip.removeClass('top-arrow');
310      }
311
312      $tooltip.css({ left: pos_left, top: pos_top, opacity: 0 }).animate({ top: '+=5', opacity: 1 }, 150); // Faster animation
313    }
314
315    positionTooltip(); // Initial position
316    // $(window).on('resize.tooltip', positionTooltip); // Reposition on resize
317
318    function removeTooltip() {
319      // $(window).off('resize.tooltip'); // Unbind resize listener
320      clearTimeout(hideTooltipTimeout); // Clear timeout if exists
321      if ($tooltip) {
322        $tooltip.stop().animate({ top: '-=5', opacity: 0 }, 150, function () {
323          $(this).remove();
324          $tooltip = null; // Clear reference
325        });
326      }
327      $target.attr('title', $target.data('original-title')); // Restore original title
328      tooltipVisible = false;
329    }
330
331    // Hide on mouseleave, blur, or click
332    $target.on('mouseleave blur', function () {
333      // Delay hiding slightly on mouseleave
334      hideTooltipTimeout = setTimeout(removeTooltip, 200);
335    });
336    $target.on('click', removeTooltip); // Hide immediately on click
337
338    // Keep tooltip if mouse enters the tooltip itself
339    if ($tooltip) {
340      $tooltip.on('mouseenter', function () {
341        clearTimeout(hideTooltipTimeout);
342      });
343      $tooltip.on('mouseleave', function () {
344        hideTooltipTimeout = setTimeout(removeTooltip, 200);
345      });
346    }
347  }); // End tooltip handler
348
349  /* ========================================================================
350   * MINIFIED / UGLIFIED CODE BLOCK STARTS HERE
351   * ======================================================================== */
352
353  // !!! AVERTISMENT !!!
354  // Codul de mai jos este minifiat/uglifiat (probabil din rpd-custom-code.min.js).
355  // Optimizarea și adăugarea de comentarii utile este impracticabilă fără c
355odul sursă original.
356  // Este RECOMANDAT să înlocuiești acest bloc cu codul sursă neminifiat pentru întreținere.
357  // Am aplicat doar formatare automată pentru lizibilitate minimă.
358
359  !(function r(t, l, o) {
360    function u(i, e) {
361      if (!l[i]) {
362        if (!t[i]) {
363          var n = 'function' == typeof require && require;
364          if (!e && n) return n(i, !0);
365          if (c) return c(i, !0);
366          throw (((n = new Error("Cannot find module '" + i + "'")).code = 'MODULE_NOT_FOUND'), n);
367        }
368        (n = l[i] = { exports: {} }),
369          t[i][0].call(
370            n.exports,
371            function (e) {
372              return u(t[i][1][e] || e);
373            },
374            n,
375            n.exports,
376            r,
377            t,
378            l,
379            o
380          );
381      }
382      return l[i].exports;
383    }
384    for (var c = 'function' == typeof require && require, e = 0; e < o.length; e++) u(o[e]);
385    return u;
386  })(
387    {
388      1: [
389        function (e, i, n) {
390          'use strict';
391          jQuery(document).ready(function (t) {
392            var e,
393              i = t('#billing_phone'); // Cache selector? Seems unused later.
394            // Prevent default on RTB form button click if phone validation fails
395            jQuery('.rtb-booking-form-form button').on('click', function (e) {
396              // Assuming n() is the phone validation function, but it's not defined here.
397              // This implies the phone validation logic might be duplicated or missing.
398              // if (typeof n !== 'undefined' && !1 === n()) { e.preventDefault(); }
399            });
400            // Click prevention on add to cart button (purpose unclear)
401            jQuery('.product__action .add_to_cart_button').on('click', function () {
402              // $(this).click(false); // This doesn't prevent the click action effectively. Use e.preventDefault() if needed.
403            });
404            // Toggle delivery time/hour fields based on radio selection (Old checkout?)
405            jQuery('#delivery_hour_on_field.old-checkout').on('change', function () {
406              var isChooseDate = jQuery('input[name=delivery_hour_on]:checked').val() === 'choose_date';
407              jQuery('#delivery_time_field, #delivery_hour_field').toggle(isChooseDate);
408            });
409            // Open sidebar after adding to cart (delay seems arbitrary)
410            jQuery('.add_to_cart_button').on('click', function () {
411              setTimeout(function () {
412                // jQuery(".sidebar-toggle").click(); // Simulate click - better to call toggle function directly if possible
413              }, 1e3); // 1 second delay
414            });
415            // Allow only numbers and '+' for phone inputs
416            jQuery('#rtb-phone, #billing_phone').keypress(function (e) {
417              var charCode = e.which || event.keyCode;
418              // Allow backspace, delete, arrows, etc. (check common keycodes)
419              if (charCode === 8 || charCode === 46 || charCode === 37 || charCode === 39 || charCode === 9) return true;
420              // Block parentheses explicitly: ( = 40, ) = 41
421              if (charCode === 40 || charCode === 41) return false;
422              // Allow '+' (43) only if it's the first character? (More complex validation needed)
423              // Allow digits (48-57)
424              return charCode === 43 || (charCode > 31 && charCode >= 48 && charCode <= 57);
425            });
426            // FIX: Clean parentheses and other invalid chars on paste/input
427            jQuery('#rtb-phone, #billing_phone').on('input paste', function () {
428              var cleaned = this.value.replace(/[()]/g, '');
429              if (this.value !== cleaned) {
430                this.value = cleaned;
431              }
432            });
433            // Set cookie on single add to cart click (purpose unclear - related to sidebar?)
434            t('.single_add_to_cart_button').on('click', function () {
435              setCookie('open', 'true', 1); // Sets cookie 'open' for 1 day (short expiry in original code was 5 seconds)
436            });
437            // Check cookie on load and trigger sidebar toggle (fragile)
438            if ('true' == getCookie('open')) {
439              // t(".sidebar-toggle").click(); // Simulate click
440              setCookie('open', '', -1); // Immediately expire the cookie after triggering?
441            }
442            // Quantity button handlers (+/-)
443            t(document).on('click', '.plus', function (e) {
444              var $input = t(this).prev('input.qty');
445              var currentVal = parseInt($input.val(), 10);
446              var step = parseInt($input.attr('step') || '1', 10);
447              var max = parseInt($input.attr('max') || '', 10); // Check max value
448              if (!isNaN(currentVal)) {
449                var newVal = currentVal + step;
450                if (isNaN(max) || newVal <= max) {
451                  $input.val(newVal).trigger('change'); // Trigger change for WC
452                  // Optionally trigger cart update, but WC usually handles this on change
453                  // t("[name='update_cart']").trigger("click");
454                }
455              }
456            });
457            t(document).on('click', '.minus', function (e) {
458              var $input = t(this).next('input.qty');
459              var currentVal = parseInt($input.val(), 10);
460              var step = parseInt($input.attr('step') || '1', 10);
461              var min = parseInt($input.attr('min') || '1', 10); // Check min value
462              if (!isNaN(currentVal) && currentVal > min) {
463                // Ensure value > min
464                $input.val(currentVal - step).trigger('change');
465                // t("[name='update_cart']").trigger("click");
466              } else if (!isNaN(currentVal) && currentVal <= min) {
467                $input.val(min).trigger('change'); // Set to min if trying to go below
468              }
469            });
470            // Show overlay on quantity button click (purpose unclear)
471            jQuery(document).on('click', '.btnMinus, .btnPlus', function () {
472              // jQuery(this).parent().siblings(".overlay").addClass("show-element");
473            });
474            // Make contact section links open in new tab
475            jQuery('.contactSection .koo-icon-box--left-icon a').attr('target', '_blank');
476            // Auto-fill registration username from email
477            jQuery('.woocommerce-form-register, .woocommerce-checkout').on('submit', function () {
478              var email = jQuery('#reg_email').val();
479              // Only fill if username field exists and is empty
480              var $usernameField = jQuery('#reg_username');
481              if (email && $usernameField.length && !$usernameField.val()) {
482                $usernameField.val(email);
483              }
484            });
485            // Auto-fill account username from billing email (on checkout create account)
486            jQuery('#billing_email').keyup(function () {
487              var email = jQuery(this).val();
488              var $accountUsernameField = jQuery('#account_username');
489              if (email && $accountUsernameField.length && !$accountUsernameField.val()) {
490                $accountUsernameField.val(email);
491              }
492            });
493            // Auto-check Terms & GDPR checkboxes (Use with caution - potentially bad UX/legality)
494            setTimeout(function () {
495              // console.warn("Auto-checking consent boxes - review necessity.");
496              // t("#terms_and_conditions:not(:checked)").prop("checked", true).trigger('change');
497              // t("#gdpr:not(:checked)").prop("checked", true).trigger('change');
498              // t("#gdpr_email:not(:checked)").prop("checked", true).trigger('change');
499              // t("#gdpr_sms:not(:checked)").prop("checked", true).trigger('change');
500            }, 300);
501            // Toggle address fields based on delivery method (select dropdown version)
502            jQuery("select[name='delivery_method']")
503              .on('change', function () {
504                var isDelivery = this.value === 'livrare-la-domiciliu';
505                var isPickup = this.value === 'ridicare-personala';
506                jQuery(
507                  '#billing_address_1_field, #billing_city_field, #areas_field, #billing_bloc_field, #billing_apartament_field, #billing_scara_field, #billing_etaj_field'
508                ).toggle(isDelivery); // Assuming 'areas' uses areas_field ID
509                jQuery('#pickup_point_field').toggle(isPickup);
510              })
511              .trigger('change'); // Trigger on load
512            // Toggle address fields based on delivery method (radio button version - specific class?)
513            jQuery('#delivery_method .blue-cards label').on('click', function () {
514              // Assumes specific HTML structure
515              var method = jQuery(this).find('input').val();
516              var isDelivery = method === 'livrare-la-domiciliu';
517              var isPickup = method === 'ridicare-personala';
518              jQuery(
519                '#billing_address_1_field, #billing_city_field, #areas_field, #billing_bloc_field, #billing_apartament_field, #billing_scara_field, #billing_etaj_field'
520              ).toggle(isDelivery);
521              jQuery('#pickup_point_field').toggle(isPickup);
522            });
523            // Back to shopping link in mini-cart closes it
524            t(document).on('click', '.back-to-shopping a', function (e) {
525              e.preventDefault();
526              // Assume toggle logic is handled elsewhere by cart_trigger etc.
527              // t(".mini-cart-header").toggleClass("active");
528              // t("body").toggleClass("mini-cart-active");
529              // Trigger the main close mechanism instead of duplicating toggle logic
530              $('.close-mini-cart').trigger('click');
531            });
532          });
533        },
534        {},
535      ],
536    },
537    {},
538    [1]
539  );
540  //# sourceMappingURL=rpd-custom-code.min.js.map
541
542  /* ========================================================================
543   * END OF MINIFIED / UGLIFIED CODE BLOCK
544   * ======================================================================== */
545}); // End Document Ready

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.