1/** 2 * Single product JS 3 * 4 * @package Buy Once or Subscribe for WooCommerce Subscriptions 5 * @since 1.0.0 6 */ 7 8jQuery( 9 function ($) { 10 let bos4w_plan_select = $('.bos4w-buy-type'); 11 let bos4w_button_text = $('.single_add_to_cart_button'); 12 let bos4w_variable_product = $('form.variations_form'); 13 let bos4w_display_dropdown_wrap = $('.bos4w-display-wrap'); 14 let bos4w_display_dropdown = $('#bos4w-dropdown-plan'); 15 let bos4w_select_options = $('.bos4w-select-options'); 16 let bos4w_block_white = {message: null, overlayCSS: {background: '#fff', opacity: 0.6}}; 17 18 if (wpr_bos4w_js.bos4w_is_product) { 19 // bos4w_button_text.html( wpr_bos4w_js.bos4w_buy_now ); 20 } 21 22 if (bos4w_variable_product.length > 0) { 23 bos4w_display_dropdown_wrap.hide(); 24 } 25 26 let bos4w_plan_options_cache = []; 27 if ($('form.cart').hasClass('bundle_form') || $('form.cart').hasClass('composite_form')) { 28 $('#bos4w-dropdown-plan').find('option').each(function () { 29 let el = this; 30 bos4w_plan_options_cache.push({ 31 value: el.value, 32 dataPrice: el.getAttribute('data-price') || '', 33 dataDiscount: el.getAttribute('data-discount') || '', 34 dataType: el.getAttribute('data-type') || '', 35 text: el.text || $(el).text() || '' 36 }); 37 }); 38 } 39 40 function bos4w_repopulate_plan_dropdown_if_empty($dropdown) { 41 if (!$dropdown || !$dropdown.is('select') || $dropdown.find('option').length > 0) { 42 return; 43 } 44 if (bos4w_plan_options_cache.length === 0) { 45 return; 46 } 47 bos4w_plan_options_cache.forEach(function (item) { 48 $dropdown.append( 49 $('<option></option>') 50 .attr('value', item.value) 51 .attr('data-price', item.dataPrice) 52 .attr('data-discount', item.dataDiscount) 53 .attr('data-type', item.dataType) 54 .text(item.text) 55 ); 56 }); 57 } 58 59 if ($('form.cart').hasClass('bundle_form')) { 60 jQuery(document.body).on( 61 'woocommerce-bundled-item-totals-changed', 62 function (event, bundle) { 63 setTimeout(function () { 64 let $dropdown = $('#bos4w-dropdown-plan'); 65 bos4w_repopulate_plan_dropdown_if_empty($dropdown); 66 67 let bundle_price_html = bundle.get_bundle().get_price_html(), 68 bundle_price_inner_html = $(bundle_price_html).html(); 69 70 let the_price = bundle_price_inner_html.match(/\d+/g); 71 let bundle_price = the_price[0] + '.' + the_price[1]; 72 73 if (the_price[2] && the_price[3]) { 74 bundle_price = the_price[2] + '.' + the_price[3]; 75 } 76 77 bundle_price = parseFloat(bundle_price); 78 79 const isSelect = $dropdown.is('select'); 80 const planCount = isSelect 81 ? $dropdown.children('option').length 82 : ($dropdown.length ? 1 : 0); 83 84 bos4w_display_dropdown_wrap.show(); 85 86 if ( 1 === planCount ) { 87 $('#bos4w-dropdown-plan').hide(); 88 $('.bos4w-one-plan-only').show(); 89 } else { 90 $('#bos4w-dropdown-plan').show(); 91 $('.bos4w-one-plan-only').hide(); 92 } 93 94 $dropdown.find('option').each(function (index, element) { 95 let text = element.text || $(this).text() || ''; 96 let discount_amount = element.dataset.discount; 97 let data_type = element.dataset.type; 98 let bmult = 0; 99 100 if ('fixed_price' === data_type) { 101 bmult = parseFloat(discount_amount) || 0; 102 } else { 103 let dec = (parseFloat(discount_amount) || 0) / 100; 104 bmult = bundle_price * dec; 105 } 106 107 let new_price = bundle_price - bmult; 108 let rounded_price = Math.round(new_price * 100) / 100; 109 110 element.dataset.price = rounded_price.toFixed(2); 111 let formattedNewPrice = addZeroes(rounded_price.toFixed(2)); 112 113 let priceMatch = text.match(/[\£\$â¬]\s*[\d.,]+/); 114 if (priceMatch) { 115 let currencyChar = priceMatch[0].charAt(0); 116 text = text.replace(/[\£\$â¬]\s*[\d.,]+/, currencyChar + formattedNewPrice); 117 } 118 if (text) { 119 $(this).text(text); 120 $('.bos4w-one-plan-only').text(text); 121 } 122 }); 123 124 $('#bos4w-selected-price').val($dropdown.find("option:selected").attr("data-price")); 125 126 }, 500); 127 } 128 ); 129 } else if ($('form.cart').hasClass('composite_form')) { 130 $('.composite_data').on('wc-composite-initializing', function (event, composite) { 131 composite.actions.add_action('component_totals_changed', function () { 132 let $dropdown = $('#bos4w-dropdown-plan'); 133 bos4w_repopulate_plan_dropdown_if_empty($dropdown); 134 135 let composite_price_html = composite.composite_price_view.get_price_html(), 136 composite_price_inner_html = $(composite_price_html).html(); 137 138 let the_price = composite_price_inner_html.match(/\d+/g); 139 let composite_price = the_price[0] + '.' + the_price[1]; 140 141 if (the_price[2] && the_price[3]) { 142 composite_price = the_price[2] + '.' + the_price[3]; 143 } 144 145 composite_price = parseFloat(composite_price); 146 147 const isSelect = $dropdown.is('select'); 148 const planCount = isSelect 149 ? $dropdown.children('option').length 150 : ($dropdown.length ? 1 : 0); 151 152 bos4w_display_dropdown_wrap.show(); 153 154 if ( 1 === planCount ) { 155 $('#bos4w-dropdown-plan').hide(); 156 $('.bos4w-one-plan-only').show(); 157 } else { 158 $('#bos4w-dropdown-plan').show(); 159 $('.bos4w-one-plan-only').hide(); 160 } 161 162 $dropdown.find('option').each(function (index, element) { 163 let text = element.text || $(this).text() || ''; 164 let discount_amount = element.dataset.discount; 165 let data_type = element.dataset.type; 166 let mult = 0; 167 168 if ('fixed_price' === data_type) { 169 mult = parseFloat(discount_amount) || 0; 170 } else { 171 let dec = (parseFloat(discount_amount) || 0) / 100; 172 mult = composite_price * dec; 173 } 174 175 let new_price = composite_price - mult;
176 let rounded_price = Math.round(new_price * 100) / 100; 177 178 element.dataset.price = rounded_price.toFixed(2); 179 let formattedNewPrice = addZeroes(rounded_price.toFixed(2)); 180 181 let priceMatch = text.match(/[\£\$â¬]\s*[\d.,]+/); 182 if (priceMatch) { 183 let currencyChar = priceMatch[0].charAt(0); 184 text = text.replace(/[\£\$â¬]\s*[\d.,]+/, currencyChar + formattedNewPrice); 185 } 186 if (text) { 187 $(this).text(text); 188 $('.bos4w-one-plan-only').text(text); 189 } 190 }); 191 192 setTimeout(function () { 193 $('#bos4w-selected-price').val($dropdown.find("option:selected").attr("data-price")); 194 }, 500); 195 }, 51, this); 196 }); 197 } else { 198 $('.single_variation_wrap').on( 199 'show_variation', 200 function (event, variation) { 201 updateSubscriptionPlans(variation); 202 } 203 ); 204 } 205 206 $(document).on('change', '[name^=bos4w_cart_item]', function () { 207 let bos4w_cart_item = $(this).val(); 208 let bos4w_cart_item_discount = $(this).data('discount'); 209 let bos4w_cart_item_price = $(this).data('price'); 210 let bos4w_cart_item_type = $(this).data('type'); 211 let bos4w_cart_item_key = $(this).data('key'); 212 213 if (bos4w_cart_item) { 214 215 $.ajax( 216 { 217 url: wpr_bos4w_js.ajax_url, 218 type: 'post', 219 data: { 220 action: 'bos4w_update_cart_item', 221 nonce: wpr_bos4w_js.nonce, 222 bos4w_cart_item: bos4w_cart_item, 223 bos4w_cart_item_discount: bos4w_cart_item_discount, 224 bos4w_cart_item_price: bos4w_cart_item_price, 225 bos4w_cart_item_type: bos4w_cart_item_type, 226 bos4w_cart_item_key: bos4w_cart_item_key 227 }, 228 complete: function () { 229 230 }, 231 success: function (response) { 232 if (response.success) { 233 $(document.body).trigger('wc_fragment_refresh'); 234 $(document.body).trigger('updated_cart_totals'); 235 236 if ($('form.woocommerce-cart-form').length > 0) { 237 const updateButton = $('form.woocommerce-cart-form').find('[name="update_cart"]'); 238 239 updateButton.prop('disabled', false); 240 updateButton.removeAttr('aria-disabled'); 241 } 242 } else { 243 console.error('Error:', response.data); 244 } 245 }, 246 error: function (XMLHttpRequest, textStatus, errorThrown) { 247 if (XMLHttpRequest.status == 0) { 248 console.error('Network connectivity error.'); 249 } else { 250 console.error(XMLHttpRequest.responseText); 251 } 252 } 253 } 254 ); 255 } 256 }); 257 258 bos4w_display_dropdown.on('change', function () { 259 $('#bos4w-selected-price').val($(this).find(":selected").attr("data-price")); 260 }); 261 262 bos4w_plan_select.on( 263 'click', 264 function () { 265 let bos4w_select = $(this).val(); 266 if ('1' === bos4w_select) { 267 $('.bos4w-display-dropdown').show('slow'); 268 } else { 269 $('.bos4w-display-dropdown').hide('slow'); 270 } 271 272 if (wpr_bos4w_js.bos4w_is_product) { 273 if ('1' === bos4w_select) { 274 bos4w_button_text.html(wpr_bos4w_js.bos4w_subscribe); 275 } else { 276 bos4w_button_text.html(wpr_bos4w_js.bos4w_buy_now); 277 } 278 } 279 } 280 ); 281 282 function updateSubscriptionPlans(variation) { 283 let variationTitle = variation.bos4w_subscription_title || wpr_bos4w_js.bos4w_display_text; 284 let discountText = variation.bos4w_discount_text || ''; 285 286 if (discountText) { 287 $('.bos-display-save-up-to').html(discountText); 288 } 289 290 // Update the display title 291 $('.bos4w-display-plan-text').text(variationTitle); 292 293 // Update the dropdown with the plans for the selected variation 294 bos4w_display_dropdown.empty(); 295 296 let plans = variation.bos4w_discounted_price; 297 298 if (plans && plans.length > 0) { 299 bos4w_display_dropdown_wrap.show(); 300 // Do NOT force "Subscribe" when a variation is selected. 301 // Preserve current selection / backend default selection behavior. 302 const selectedType = ($('input[name="bos4w-purchase-type"]:checked').val() || '0').toString(); 303 if ('1' === selectedType) { 304 $('.bos4w-display-dropdown').show('slow'); 305 } else { 306 $('.bos4w-display-dropdown').hide('slow'); 307 } 308 309 if (wpr_bos4w_js.bos4w_is_product) { 310 bos4w_button_text.html('1' === selectedType ? wpr_bos4w_js.bos4w_subscribe : wpr_bos4w_js.bos4w_buy_now); 311 } 312 313 if ( 1 === plans.length ) { 314 $('#bos4w-dropdown-plan').hide(); 315 $('.bos4w-one-plan-only').show(); 316 } else { 317 $('#bos4w-dropdown-plan').show(); 318 $('.bos4w-one-plan-only').hide(); 319 } 320 321 $.each(plans, function (index, plan) { 322 let cleanDiscountedPrice = $(plan.discounted_price).text(); 323 let bos_type = plan.subscription_price ? 'fixed_price' : 'percentage_price'; 324 let display_discount = ''; 325 if (plan.display_discount && plan.display_discount.trim() !== '') { 326 display_discount = ` (${plan.display_discount})`; 327 } 328 329 let optionText = htmlspecialchars_decode(plan.display); 330 let planLength = plan.subscription_length ? plan.subscription_length : 0; 331 let optionValue = `${plan.subscription_period_interval}_${plan.subscription_period}_${planLength}_${bos_type === 'fixed_price' ? plan.subscription_price : plan.subscription_discount}`; 332 let optionData = { 333 'value': optionValue, 334 'data-discount': bos_type === 'fixed_price' ? plan.subscription_price : plan.subscription_discount, 335 'data-price': plan.float_discounted, 336 'data-type': bos_type 337 }; 338 let $option = $('<option>', optionData).text(optionText); 339 bos4w_display_dropdown.append($option); 340 $('.bos4w-one-plan-only').text(optionText); 341 }); 342 343 // Ensure the first option is selected by default 344 if (bos4w_display_dropdown.length && bos4w_display_dropdown.is('select')) { 345 bos4w_display_dropdown.val(bos4w_display_dropdown.find('option:first').val()); 346 } 347 } else { 348 bos4w_display_dropdown_wrap.hide(); 349 // Uncheck subscribe and check one-time when no plans are available 350 $('#bos4w-one-time').prop('checked', true); 351 $('.bos4w-display-dropdown').hide('slow'); 352 353 if (wpr_bos4w_js.bos4w_is_product) { 354 bos4w_button_text.html(wpr_bos4w_js.bos4w_buy_now); 355 } 356 } 357 358 setTimeout(function () { 359 $('#bos4w-selected-price').val($("#bos4w-dropdown-plan option:selected").attr("data-price")); 360 }, 500); 361 } 362 363 function addZeroes(num) { 364 let value, res; 365 366 num.toString(); 367 368 if (',' === wpr_bos4w_js.decimal_separator) { 369 res = num.split(","); 370 } else { 371 res = num.split("."); 372 } 373 374 value = Number(num); 375 if (isNaN(Number(num))) { 376 value = num; 377 } 378 379 if (res.length === 1 || res[1].length < 3) { 380 if (undefined === res[1]) { 381 value = res[0] + '.00'; 382 } else { 383 value = res[0] + '.' + res[1]; 384 } 385 386 value = Number(value).toFixed(2); 387 } 388 389 if (',' === wpr_bos4w_js.decimal_separator) {
390 value = String(value).replace('.', ','); 391 } 392 393 return value; 394 } 395 396 function htmlspecialchars_decode(str) { 397 return $('<div>').html(str).text(); 398 } 399 } 400);
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.