1// rmenu-cart.js 2jQuery(document).ready(function ($) { 3 "use strict"; 4 5 let updateCartContent_timer; 6 7 plugincydebugLog("Settings : ", onepaquc_rmsgValue.plugincy_all_settings); 8 9 function fcStr(key, fallback) { 10 var fc = (typeof onepaquc_rmsgValue !== 'undefined' && onepaquc_rmsgValue.floating_cart) ? onepaquc_rmsgValue.floating_cart : {}; 11 if (fc[key] !== undefined && fc[key] !== '') { 12 return fc[key]; 13 } 14 return fallback; 15 } 16 17 function formatSelectedCountLabel(count) { 18 var p = typeof onepaquc_wc_cart_params !== 'undefined' ? onepaquc_wc_cart_params : {}; 19 var suffix = (p.txt_selected) ? p.txt_selected : 'selected'; 20 return String(count) + ' ' + suffix; 21 } 22 23 const checkout_popup = $('.checkout-popup'); 24 var $isonepagewidget = (checkout_popup.length) ? checkout_popup.data('isonepagewidget') : false; 25 26 var checkoutIframe = $('<iframe>', { 27 src: onepaquc_rmsgValue.checkout_url + '?hide_header_footer=1', 28 id: 'checkout-iframe', 29 frameborder: 0, 30 style: 'width: 100%; min-height: 100%; height: 100%;' 31 }); 32 // append iframe 33 window.createCheckoutIframe = function () { 34 if (!$('form.checkout.woocommerce-checkout').length && checkout_popup.length && $(".checkout-popup #checkout-form").length && !$(".checkout-popup #checkout-form #checkout-iframe").length) { 35 // Show loading spinner before iframe loads 36 $('.checkout-popup #checkout-form').addClass('onepaquc-checkout-loading').html('<div class="plugincy_preloader"> <svg class="plugincy_cart" role="img" aria-label="Shopping plugincy_cart line animation" viewBox="0 0 128 128" width="128px" height="128px" xmlns="http://www.w3.org/2000/svg"> <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="8"> <g class="plugincy_cart__track" stroke="hsla(0,10%,10%,0.1)"> <polyline points="4,4 21,4 26,22 124,22 112,64 35,64 39,80 106,80" /> <circle cx="43" cy="111" r="13" /> <circle cx="102" cy="111" r="13" /> </g> <g class="plugincy_cart__lines" stroke="currentColor"> <polyline class="plugincy_cart__top" points="4,4 21,4 26,22 124,22 112,64 35,64 39,80 106,80" stroke-dasharray="338 338" stroke-dashoffset="-338" /> <g class="plugincy_cart__wheel1" transform="rotate(-90,43,111)"> <circle class="plugincy_cart__wheel-stroke" cx="43" cy="111" r="13" stroke-dasharray="81.68 81.68" stroke-dashoffset="81.68" /> </g> <g class="plugincy_cart__wheel2" transform="rotate(90,102,111)"> <circle class="plugincy_cart__wheel-stroke" cx="102" cy="111" r="13" stroke-dasharray="81.68 81.68" stroke-dashoffset="81.68" /> </g> </g> </g> </svg> <div class="plugincy_preloader__text"> <p class="plugincy_preloader__msg">' + fcStr('preloader_msg', 'Bringing you the goods\u2026') + '</p> <p class="plugincy_preloader__msg plugincy_preloader__msg--last">' + fcStr('preloader_slow', 'This is taking long. Something\u2019s wrong.') + '</p> </div> </div>'); 37 $('.checkout-popup #checkout-form').append(checkoutIframe); 38 39 $(".checkout-popup div#checkout-form").css("overflow", "hidden"); 40 41 // Remove spinner when iframe is loaded 42 checkoutIframe.on('load', function () { 43 $('.plugincy_preloader').remove(); 44 $('.checkout-popup #checkout-form').removeClass('onepaquc-checkout-loading'); 45 }); 46 47 checkoutIframe.on('error', function () { 48 $('.checkout-popup #checkout-form').removeClass('onepaquc-checkout-loading').html('<p>' + fcStr('iframe_error', 'Error loading checkout. Please try again.') + '</p>'); 49 }); 50 } 51 } 52 53 // Function to refresh iframe 54 window.refreshCheckoutIframe = function () { 55 if ($('#checkout-iframe').length) { 56 $('#checkout-iframe')[0].src = $('#checkout-iframe')[0].src; 57 } 58 }; 59 60 // Click event to close cart drawer and checkout popup 61 $(document).on('click', function (event) { 62 if (!$(event.target).closest('.cart-drawer, .rwc_cart-button, .checkout-popup').length) { 63 closeCartAndCheckout(); 64 } 65 }); 66 67 $(document).on('click', '.rwc_cart-button', function () { 68 openCartDrawer(); 69 }); 70 71 // Open the cart drawer 72 window.openCartDrawer = function () { 73 const cartDrawer = $('.cart-drawer');
74 const overlay = $('.overlay'); 75 if (cartDrawer && cartDrawer.length) { 76 cartDrawer.addClass('open'); 77 if (overlay) overlay.show(); 78 document.body.style.overflow = 'hidden'; 79 } 80 81 }; 82 83 // Close the checkout popup 84 window.closeCheckoutPopup = function () { 85 closeCartAndCheckout(); 86 }; 87 88 // Open the checkout popup 89 window.openCheckoutPopup = function () { 90 if (checkout_popup) checkout_popup.show(); 91 const cartDrawer = $('.cart-drawer'); 92 if (cartDrawer && cartDrawer.length) { 93 cartDrawer.removeClass('open'); 94 } 95 96 if ($('.checkout-popup iframe')) { 97 updateCartContent_timer = setInterval(() => { 98 window.updateCartContent(false); 99 }, 2000); 100 } 101 102 $('body').addClass('onepaquc-hide-cart-drawer'); 103 }; 104 105 // Function to close the cart drawer and checkout popup 106 function closeCartAndCheckout() { 107 if (!$isonepagewidget) { 108 if (checkout_popup) checkout_popup.hide(); 109 } 110 const cartDrawer = $('.cart-drawer'); 111 if (cartDrawer && cartDrawer.length) cartDrawer.removeClass('open'); 112 $('.overlay').hide(); // Hide overlay when cart is closed 113 document.body.style.overflow = ''; 114 $('body').removeClass('onepaquc-hide-cart-drawer'); 115 clearInterval(updateCartContent_timer); 116 } 117 118 // Select & select all functionality 119 120 $(document).on('change', '#select-all-items', function () { 121 $('.item-checkbox').prop('checked', this.checked); 122 updateSelectedCount(); 123 }); 124 125 // Individual item selection 126 $(document).on('change', '.item-checkbox', function () { 127 updateSelectedCount(); 128 updateSelectAllCheckbox(); 129 }); 130 131 // Update selected count 132 function updateSelectedCount() { 133 const checkedBoxes = document.querySelectorAll('.item-checkbox:checked'); 134 const selectedCountText = document.getElementById('selected-count-text'); 135 const removeSelectedButton = document.getElementById('remove-selected'); 136 const count = checkedBoxes.length; 137 if (selectedCountText) { 138 selectedCountText.textContent = formatSelectedCountLabel(count); 139 } 140 if (removeSelectedButton) { 141 removeSelectedButton.style.display = count > 0 ? 'inline-block' : 'none'; 142 } 143 } 144 145 // Update select all checkbox 146 function updateSelectAllCheckbox() { 147 const selectAllCheckbox = document.getElementById('select-all-items'); 148 if (!selectAllCheckbox) { 149 return; 150 } 151 const itemCheckboxes = document.querySelectorAll('.item-checkbox'); 152 const checkedBoxes = document.querySelectorAll('.item-checkbox:checked'); 153 selectAllCheckbox.checked = checkedBoxes.length === itemCheckboxes.length; 154 } 155 156 // Remove selected items 157 $(document).on('click', '#remove-selected', function () { 158 const checkedBoxes = $('.item-checkbox:checked'); 159 if (checkedBoxes.length === 0) return; 160 161 const cartItemKeys = []; 162 checkedBoxes.each(function () { 163 const cartItemKey = $(this).data('cart-item-key'); 164 cartItemKeys.push(cartItemKey); 165 const cartItem = $(this).closest('.cart-item'); 166 cartItem.addClass("removing"); 167 cartItem.css('transition', 'opacity 0.5s ease'); 168 cartItem.css('opacity', '0.5'); 169 }); 170 171 window.removecartitem(cartItemKeys); 172 }); 173 174 // Apply coupon 175 176 177 178 // Helper function to check applied coupons visibility 179 180 $(document).on('click', '#apply-coupon', function () { 181 const appliedCoupons = document.getElementById('applied-coupons'); 182 const couponInput = $('#coupon-code'); 183 const couponCode = couponInput.val().trim(); 184 if (!couponCode) return; 185 186 setLoadingState(this, true, fcStr('applying', 'Applying\u2026')); 187 showMessage(fcStr('applying_coupon', 'Applying coupon\u2026'), 'loading'); 188 189 const data = { 190 action: 'onepaquc_apply_coupon', 191 coupon_code: couponCode, 192 security: onepaquc_rmsgValue.apply_coupon 193 }; 194 195 jQuery.post(woocommerce_params.ajax_url, data, function (response) {
196 setLoadingState($('#apply-coupon')[0], false, fcStr('apply_coupon', 'Apply coupon')); 197 if (response.success) { 198 showMessage(fcStr('coupon_applied', 'Coupon applied successfully!'), 'success'); 199 window.updateCartTotals(response.data); 200 // Add to applied coupons list 201 if (appliedCoupons) { 202 appliedCoupons.style.display = "block"; 203 if (appliedCoupons.children.length <= 0) { 204 appliedCoupons.innerHTML = '<h4>' + fcStr('applied_coupons_heading', 'Applied Coupons:') + '</h4>'; 205 } 206 const couponElement = document.createElement('div'); 207 couponElement.className = 'applied-coupon'; 208 couponElement.innerHTML = ` 209 <span>${couponCode}</span> 210 <button class="remove-coupon" data-coupon="${couponCode}">${fcStr('remove', 'Remove')}</button> 211 `; 212 appliedCoupons.appendChild(couponElement); 213 } 214 215 // Clear input 216 couponInput.value = ''; 217 } else { 218 showMessage(response.data.message || fcStr('invalid_coupon', 'Invalid coupon code.'), 'error'); 219 } 220 }).fail(function () { 221 setLoadingState($('#apply-coupon')[0], false, fcStr('apply_coupon', 'Apply coupon')); 222 showMessage(fcStr('error_try_again', 'Something went wrong. Please try again.'), 'error'); 223 }); 224 }); 225 226 // Add event listener to remove button (using event delegation for dynamically added buttons) 227 228 $(document).on('click', '.remove-coupon', function (e) { 229 const couponCode = this.dataset.coupon; 230 removeCoupon(couponCode, this); 231 }); 232 233 // Remove coupon 234 function removeCoupon(couponCode, buttonElement) { 235 const appliedCoupons = document.getElementById('applied-coupons'); 236 // Show loading state for the specific remove button 237 setLoadingState(buttonElement, true, fcStr('removing', 'Removing\u2026')); 238 showMessage(fcStr('removing_coupon', 'Removing coupon\u2026'), 'loading'); 239 240 const data = { 241 action: 'onepaquc_remove_coupon', 242 coupon_code: couponCode, 243 security: onepaquc_rmsgValue.apply_coupon 244 }; 245 246 jQuery.post(woocommerce_params.ajax_url, data, function (response) { 247 if (response.success) { 248 // Remove coupon from DOM 249 const couponElement = buttonElement.parentElement; 250 if (couponElement) { 251 couponElement.remove(); 252 } 253 if (appliedCoupons.children.length <= 1) { 254 appliedCoupons.style.display = 'none'; // Hide the element 255 } 256 257 // Show success message 258 showMessage(fcStr('coupon_removed', 'Coupon removed successfully!'), 'success'); 259 260 // Update cart totals 261 window.updateCartTotals(response.data); 262 } else { 263 // Remove loading state if removal failed 264 setLoadingState(buttonElement, false, fcStr('remove', 'Remove')); 265 showMessage(fcStr('failed_remove_coupon', 'Failed to remove coupon. Please try again.'), 'error'); 266 } 267 }).fail(function () { 268 // Handle AJAX error 269 setLoadingState(buttonElement, false, fcStr('remove', 'Remove')); 270 showMessage(fcStr('error_try_again', 'Something went wrong. Please try again.'), 'error'); 271 }); 272 } 273 274 // Helper function to set loading state on buttons 275 function setLoadingState(button, isLoading, text) { 276 if (isLoading) { 277 button.disabled = true; 278 button.classList.add('loading'); 279 button.textContent = text; 280 // Add spinner if you have CSS for it 281 // button.innerHTML = `<span class="spinner"></span> ${text}`; 282 } else { 283 button.disabled = false; 284 button.classList.remove('loading'); 285 button.textContent = text; 286 } 287 } 288 289 // Helper function to show messages with auto-clear 290 function showMessage(message, type) { 291 const couponMessage = document.getElementById('coupon-message'); 292 if (couponMessage) { 293 couponMessage.textContent = message; 294 couponMessage.className = `coupon-message ${type}`; 295 couponMessage.style.display = "block"; 296 297 // Don't auto-clear loading messages 298 setTimeout(() => { 299 couponMessage.textContent = ''; 300 couponMessage.className = 'coupon-message';
301 couponMessage.style.display = "none"; 302 }, 3000); 303 } 304 } 305 306 // Update cart totals 307 window.updateCartTotals = function (data) { 308 $(document.body).trigger('update_checkout'); 309 // Update subtotal 310 const subtotalElement = document.querySelector('.summary-row:not(.discount):not(.total) span:last-child'); 311 if (subtotalElement) { 312 subtotalElement.innerHTML = data.subtotal; // Use innerHTML 313 } 314 315 // Update discount 316 const discountElement = document.querySelector('.summary-row.discount'); 317 if (discountElement) { 318 if (data.discount_total > 0) { 319 discountElement.style.display = 'flex'; 320 discountElement.innerHTML = '<span>' + fcStr('discount', 'Discount') + '</span><span>- ' + onepaquc_rmsgValue.currency_symbol + ' ' + data.discount_total + '</span>'; 321 } else { 322 discountElement.style.display = 'none'; 323 } 324 } 325 326 // Update total 327 const totalElement = document.querySelector('.summary-row.total span:last-child'); 328 if (totalElement) { 329 totalElement.innerHTML = data.total; // Use innerHTML 330 } 331 } 332 333 $(document).on('click', '.quantity-btn', function () { 334 const $input = $(this).siblings('.item-quantity'); 335 let currentValue = parseInt($input.val(), 10); 336 337 if ($(this).data('action') === 'plus') { 338 currentValue += 1; 339 } else if ($(this).data('action') === 'minus' && currentValue > 1) { 340 currentValue -= 1; 341 } 342 343 $input.val(currentValue); 344 $input.trigger('change'); // Trigger the change event to use your existing code 345 346 }); 347}); 348 349 350 351 352 353 354 355 356// variation selection handle 357 358jQuery(function ($) { 359 "use strict"; 360 361 // Keep overlays attached directly to .product 362 $('.overlay-variations').each(function () { 363 var $variations = $(this); 364 var $product = $variations.closest('.product'); 365 if ($product.length) { 366 $variations.detach().appendTo($product); 367 } 368 }); 369 370 // COMBINE clicks (unchanged) 371 $(document).on('click', '.variation-button', function () { 372 plugincydebugLog("clicked variation button combined: ", $(this)); 373 var $wrap = $(this).closest('.archive-variations-container'); 374 var id = $(this).data('id'); 375 plugincydebugLog("variation id: ", id); 376 $(this).addClass('selected').siblings().removeClass('selected'); 377 $wrap.find('input.variation_id').val(id); 378 $wrap.find('span.variation_id').text(id); 379 }); 380 381 // SEPARATE logic 382 $('.archive-variations-container[data-layout="separate"]').each(function () { 383 var $wrap = $(this); 384 var $box = $wrap.find('.separate-attrs'); 385 if (!$box.length) return; 386 387 var variations = []; 388 var attrKeys = []; 389 390 try { 391 variations = JSON.parse($box.attr('data-var-map') || '[]'); 392 } catch (e) { } 393 try { 394 attrKeys = JSON.parse($box.attr('data-attr-keys') || '[]'); 395 } catch (e) { } 396 397 var selected = {}; // attr_key => slug 398 399 function findVariationId() { 400 for (var i = 0; i < variations.length; i++) { 401 var v = variations[i], 402 ok = true; 403 404 for (var k = 0; k < attrKeys.length; k++) { 405 var a = attrKeys[k]; 406 if (!selected[a] || v.attrs[a] != selected[a]) { 407 ok = false; 408 break; 409 } 410 } 411 plugincydebugLog("possible variation id : ", v.id); 412 if (ok) return v.id; 413 } 414 return ''; 415 } 416 417 // (optional) compute enabled options based on partial selection 418 function refreshAvailability() { 419 // For each attribute, check which options are available given current selection 420 attrKeys.forEach(function(attr) { 421 $box.find('.var-attr-option[data-attr="' + attr + '"]').each(function() { 422 var $option = $(this); 423 var value = $option.data('value'); 424 var testSelection = Object.assign({}, selected); 425 testSelection[attr] = value; 426 427 // Check if any variation matches this partial selection 428 var available = variations.some(function(v) { 429 return attrKeys.every(function(a) { 430 // If attribute is selected, must match; if not selected, ignore 431 return !testSelection[a] || v.attrs[a] == testSelection[a]; 432 }); 433 }); 434 435 if (available) { 436 $option.removeClass('disabled'); 437 } else { 438 $option.addClass('disabled'); 439 } 440 }); 441 }); 442 } 443 444 $box.on('click', '.var-attr-option', function () { 445 plugincydebugLog("clicked variation button: ", $(this)); 446 var $btn = $(this); 447 var attr = $btn.data('attr'); 448 var value = $btn.data('value'); 449 450 // single-select per attribute 451 $btn.addClass('selected').siblings('[data-attr="' + attr + '"]').removeClass('selected'); 452 selected[attr] = value; 453 454 plugincydebugLog("selected: ", selected); 455 456 refreshAvailability(); 457 458 var id = findVariationId(); 459 plugincydebugLog("final variation id: ", id); 460 $wrap.find('input.variation_id').val(id); 461 $wrap.find('span.variation_id').text(id); 462 }); 463 }); 464});
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.