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;">×</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.