1var ppecHandler = function( data ) { 2 this.data = data; 3 this.actions = {}; 4 5 var parent = this; 6 7 this.processPayment = function( payment, action ) { 8 jQuery.post( ppecFrontVars.ajaxUrl, { 9 'action': action, 10 wp_ppdg_payment: payment, 11 data: parent.data, 12 nonce: parent.data.nonce 13 } ) 14 .done( function( data ) { 15 parent.completePayment( data ); 16 } ); 17 }; 18 19 this.completePayment = function( data ) { 20 var ret = true; 21 var dlgTitle = ppecFrontVars.str.paymentCompleted; 22 var dlgMsg = ppecFrontVars.str.redirectMsg; 23 if ( data.redirect_url ) { 24 var redirect_url = data.redirect_url; 25 } else { 26 dlgTitle = ppecFrontVars.str.errorOccurred; 27 dlgMsg = data; 28 ret = false; 29 } 30 jQuery( '.wp-ppec-overlay[data-ppec-button-id="' + parent.data.id + '"]' ).hide(); 31 var dialog = jQuery( '<div id="wp-ppdg-dialog-message" title="' + dlgTitle + '"><p id="wp-ppdg-dialog-msg">' + dlgMsg + '</p></div>' ); 32 jQuery( '#' + parent.data.id ).before( dialog ).fadeIn(); 33 if ( redirect_url ) { 34 location.href = redirect_url; 35 } 36 return ret; 37 }; 38 39 this.ValidatorTos = function( input ) { 40 return input.prop( 'checked' ) !== true ? ppecFrontVars.str.acceptTos : null; 41 }; 42 43 this.ValidatorBilling = function( input ) { 44 var val = input.attr( 'type' ) === 'checkbox' ? input.prop( 'checked' ) === true : input.val(); 45 return input.is( ':visible' ) && !val ? ppecFrontVars.str.required : null; 46 }; 47 48 this.isValidTotal = function() { 49 parent.calcTotal(); 50 return !!parent.data.total; 51 }; 52 53 this.ValidatorQuantity = function( input ) { 54 var val_orig = input.val(); 55 var val = parseInt( val_orig ); 56 var error = false; 57 if ( isNaN( val ) || ( val_orig % 1 !== 0 ) || val <= 0 ) { 58 error = ppecFrontVars.str.enterQuantity; 59 } else if ( parent.data.stock_enabled && val > parent.data.stock_items ) { 60 error = ppecFrontVars.str.stockErr.replace( '%d', parent.data.stock_items ); 61 } else { 62 parent.data.quantity = val; 63 } 64 return error; 65 }; 66 67 this.ValidatorAmount = function( input ) { 68 var val_orig = input.val(); 69 var val = parseFloat( val_orig ); 70 var min_val = input.attr( 'min' ); 71 var error = false; 72 var errMsg = ppecFrontVars.str.enterAmount; 73 if ( !isNaN( val ) && min_val <= val ) { 74 parent.data.orig_price = val; 75 parent.data.price = parent.applyVariations( val ); 76 } else { 77 error = errMsg; 78 } 79 return error; 80 }; 81 82 if ( this.data.btnStyle.layout === 'horizontal' ) { 83 this.data.btnStyle.tagline = false; 84 } 85 86 this.clientVars = {}; 87 88 this.clientVars[ this.data.env ] = this.data.client_id; 89 90 this.inputs = []; 91 92 this.validateInput = function( input, validator ) { 93 if ( 1 > input.length ) { 94 return false; 95 } 96 97 this.inputs.push( [ input, validator ] ); 98 99 input.change( function() { 100 parent.displayInputError( jQuery( this ), validator ); 101 parent.validateOrder(); 102 } ); 103 }; 104 105 this.validateOrder = function() { 106 var enable_actions = true; 107 108 jQuery( '#wpec_billing_' + parent.data.id + ', #place-order-' + parent.data.id ).toggle( !parent.isValidTotal() ); 109 jQuery( '#' + parent.data.id ).toggle( !jQuery( '#place-order-' + parent.data.id ).is( ':visible' ) ); 110 111 parent.inputs.forEach( function( inputArr ) { 112 var input = inputArr[ 0 ]; 113 var validator = inputArr[ 1 ]; 114 if ( validator( input ) ) { 115 enable_actions = false; 116 } 117 } ); 118 119 if ( !parent.isValidTotal() ) { 120 enable_actions = false; 121 } 122 123 if ( enable_actions ) { 124 parent.actions.enable(); 125 } else { 126 parent.actions.disable(); 127 } 128 129 parent.updateAllAmounts(); 130 jQuery( document ).trigger( 'wpec_validate_order', [ parent ] ); 131 }; 132 133 this.displayInputError = function( input, validator ) { 134 var error = validator( input ); 135 var errMsgCont = input.is( ':checkbox' ) || input.attr( 'type' ) === 'number' ? input.parent().siblings( '.wp-ppec-form-error-msg' ) : input.siblings( '.wp-ppec-form-error-msg' ); 136 input.toggleClass( 'hasError', !!error ); 137 errMsgCont.html( error ); 138 if ( error && errMsgCont.length ) { 139 errMsgCont.fadeIn( 'slow' ); 140 } else { 141 errMsgCont.fadeOut( 'fast' ); 142 } 143 }; 144 145 this.displayErrors = function() {
146 parent.inputs.forEach( function( input ) { 147 parent.displayInputError( input[ 0 ], input[ 1 ] ); 148 } ); 149 }; 150 151 this.scCont = jQuery( '.wp-ppec-shortcode-container[data-ppec-button-id="' + parent.data.id + '"]' ); 152 153 this.buttonArgs = { 154 env: parent.data.env, 155 client: parent.clientVars, 156 style: parent.data.btnStyle, 157 commit: true, 158 onInit: function( data, actions ) { 159 parent.actions = actions; 160 parent.validateInput( jQuery( '#wpec-tos-' + parent.data.id ), parent.ValidatorTos ); 161 parent.validateInput( jQuery( '#wp-ppec-custom-quantity[data-ppec-button-id="' + parent.data.id + '"]' ), parent.ValidatorQuantity ); 162 parent.validateInput( jQuery( '#wp-ppec-custom-amount[data-ppec-button-id="' + parent.data.id + '"]' ), parent.ValidatorAmount ); 163 jQuery( '#wpec_billing_' + parent.data.id + ' .wpec_required' ).each( function() { 164 parent.validateInput( jQuery( this ), parent.ValidatorBilling ); 165 } ); 166 parent.data.orig_price = parseFloat( parent.data.price ); 167 parent.scCont.find( 'select.wpec-product-variations-select, input.wpec-product-variations-select-radio' ).change( function() { 168 var grpId = jQuery( this ).data( 'wpec-variations-group-id' ); 169 var varId = jQuery( this ).val(); 170 if ( Object.getOwnPropertyNames( parent.data.variations ).length !== 0 ) { 171 if ( !parent.data.variations.applied ) { 172 parent.data.variations.applied = []; 173 } 174 parent.data.variations.applied[ grpId ] = varId; 175 parent.data.price = parent.applyVariations( parent.data.orig_price ); 176 parent.validateOrder(); 177 } 178 } ); 179 parent.scCont.find( 'select.wpec-product-variations-select, input.wpec-product-variations-select-radio:checked' ).change(); 180 181 parent.scCont.find( '.wpec_product_shipping_enable' ).change( function() { 182 parent.scCont.find( '.wpec_shipping_address_container' ).toggle(); 183 parent.scCont.find( '.wpec_address_wrap' ).toggleClass( 'shipping_enabled' ); 184 } ); 185 186 jQuery( '#place-order-' + parent.data.id ).click( function() { 187 parent.buttonArgs.onClick(); 188 } ); 189 190 jQuery( '#wpec-redeem-coupon-btn-' + parent.data.id ).click( function( e ) { 191 e.preventDefault(); 192 var couponCode = jQuery( this ).siblings( '#wpec-coupon-field-' + parent.data.id ).val(); 193 if ( couponCode === '' ) { 194 return false; 195 } 196 var wpecCouponBtn = jQuery( this ); 197 var wpecCouponSpinner = wpecCouponBtn.find( 'svg' ); 198 wpecCouponBtn.prop( 'disabled', true ); 199 wpecCouponSpinner.show(); 200 var ajaxData = { 201 'action': 'wpec_check_coupon', 202 'product_id': parent.data.product_id, 203 'coupon_code': couponCode, 204 'curr': parent.data.currency, 205 /*'amount': parent.data.item_price, 206 'tax': parent.data.tax, 207 'shipping': parent.data.shipping*/ 208 }; 209 jQuery.post( ppecFrontVars.ajaxUrl, ajaxData, function( response ) { 210 if ( response.success ) { 211 parent.data.discount = response.discount; 212 parent.data.discountType = response.discountType; 213 parent.data.couponCode = response.code; 214 215 jQuery( '#wpec-coupon-info-' + parent.data.id ).html( '<span class="wpec_coupon_code">' + response.discountStr + '</span> <button class="wpec_coupon_apply_btn" id="wpec-remove-coupon-' + parent.data.id + '" title="' + ppecFrontVars.str.strRemoveCoupon + '">' + ppecFrontVars.str.strRemove + '</button>' ); 216 jQuery( '#wpec-redeem-coupon-btn-' + parent.data.id ).hide(); 217 jQuery( '#wpec-coupon-field-' + parent.data.id ).hide(); 218 var totalCont = parent.getPriceContainer(); 219 var totCurr; 220 var totNew; 221 var priceCurr; 222 var priceNew; 223 if ( totalCont.find( '.wpec_price_full_total' ).length !== 0 ) { 224 totCurr = totalCont.children().find( 'span.wpec_tot_current_price' ).addClass( 'wpec_line_through' ); 225 totNew = totalCont.children().find( 'span.wpec_tot_new_price' ); 226 } else { 227 totCurr = totalCont.find( 'span.wpec_price_amount' ).addClass( 'wpec_line_through' ); 228 totNew = totalCont.find( 'span.wpec_new_price_amount' ); 229 } 230 priceCurr = totalCont.find( 'span.wpec-price-amount' ).addClass( 'wpec_line_through' ); 231 priceNew = totalCont.find( 'span.wpec-new-price-amount' ); 232 parent.validateOrder(); 233 jQuery( '#wpec-remove-coupon-' + parent.data.id ).on( 'click', function( e ) { 234 e.preventDefault(); 235 jQuery( '#wpec-coupon-info-' + parent.data.id ).html( '' ); 236 jQuery( '#wpec-coupon-field-' + parent.data.id ).val( '' ); 237 jQuery( '#wpec-coupon-field-' + parent.data.id ).show(); 238 jQuery( '#wpec-redeem-coupon-btn-' + parent.data.id ).show(); 239 totCurr.removeClass( 'wpec_line_through' ); 240 priceCurr.removeClass( 'wpec_line_through' ); 241 totNew.html( '' ); 242 priceNew.html( '' ); 243 delete parent.data.discount; 244 delete parent.data.discountType; 245 delete parent.data.couponCode; 246 delete parent.data.discountAmount; 247 delete parent.data.newPrice; 248 parent.validateOrder(); 249 } ); 250 } else { 251 jQuery( '#wpec-coupon-info-' + parent.data.id ).html( response.msg ); 252 } 253 wpecCouponSpinner.hide(); 254 wpecCouponBtn.prop( 'disabled', false ); 255 } ); 256 } ); 257 258 jQuery( '#wpec-coupon-field-' + parent.data.id ).keydown( function( e ) { 259 if ( e.keyCode === 13 ) { 260 e.preventDefault(); 261 jQuery( '#wpec-redeem-coupon-btn-' + parent.data.id ).click(); 262 return false;
263 } 264 } ); 265 266 parent.validateOrder(); 267 268 if ( parent.data.errors ) { 269 var errorEl = jQuery( '<div class="wp-ppec-form-error-msg">' + parent.data.errors + '</div>' ); 270 parent.scCont.append( errorEl ); 271 errorEl.show(); 272 } 273 274 jQuery( '.wpec-button-placeholder' ).remove(); 275 }, 276 onClick: function() { 277 jQuery("#place-order-"+parent.data.id).find("button>svg").show(); 278 jQuery("#place-order-"+parent.data.id).find("button").attr("disabled",true); 279 280 parent.displayErrors(); 281 var errInput = parent.scCont.find( '.hasError' ).first(); 282 if ( errInput.length > 0 ) { 283 284 285 errInput.focus(); 286 errInput.trigger( 'change' ); 287 288 jQuery("#place-order-"+parent.data.id).find("button>svg").hide(); 289 jQuery("#place-order-"+parent.data.id).find("button").attr("disabled",false); 290 } else if ( !parent.data.total ) { 291 292 parent.processPayment( { 293 payer: { 294 name: { 295 given_name: jQuery( '#wpec_billing_first_name-' + parent.data.id ).val(), 296 surname: jQuery( '#wpec_billing_last_name-' + parent.data.id ).val() 297 }, 298 email_address: jQuery( '#wpec_billing_email-' + parent.data.id ).val(), 299 address: { 300 address_line_1: jQuery( '#wpec_billing_address-' + parent.data.id ).val(), 301 admin_area_1: jQuery( '#wpec_billing_state-' + parent.data.id ).val(), 302 admin_area_2: jQuery( '#wpec_billing_city-' + parent.data.id ).val(), 303 postal_code: jQuery( '#wpec_billing_postal_code-' + parent.data.id ).val(), 304 country_code: jQuery( '#wpec_billing_country-' + parent.data.id ).val() 305 }, 306 shipping_address: { 307 address_line_1: jQuery( '#wpec_shipping_address-' + parent.data.id ).val(), 308 admin_area_1: jQuery( '#wpec_shipping_state-' + parent.data.id ).val(), 309 admin_area_2: jQuery( '#wpec_shipping_city-' + parent.data.id ).val(), 310 postal_code: jQuery( '#wpec_shipping_postal_code-' + parent.data.id ).val(), 311 country_code: jQuery( '#wpec_shipping_country-' + parent.data.id ).val() 312 } 313 } 314 }, 'wpec_process_empty_payment' ); 315 } 316 }, 317 createOrder: async function( data, actions ) { 318 parent.calcTotal(); 319 320 //We need to round to 2 decimal places to make sure that the API call will not fail. 321 let itemTotalValueRounded = (parent.data.price * parent.data.quantity).toFixed(2); 322 let itemTotalValueRoundedAsNumber = parseFloat(itemTotalValueRounded); 323 //console.log('Item total value rounded: ' + itemTotalValueRoundedAsNumber); 324 //console.log(parent.data); 325 326 // Checking if shipping will be required 327 let shipping_pref = 'NO_SHIPPING'; // Default value 328 if (parent.data.shipping !== "" || parent.data.shipping_enable === true) { 329 console.log("The physical product checkbox is enabled or there is shipping value has been configured. Setting the shipping preference to collect shipping."); 330 shipping_pref = 'GET_FROM_FILE'; 331 } 332 333 // Create order_data object to be sent to the server. 334 var order_data = { 335 intent: 'CAPTURE', 336 payment_source: { 337 paypal: { 338 experience_context: { 339 payment_method_preference: 'IMMEDIATE_PAYMENT_REQUIRED', 340 shipping_preference: shipping_pref, 341 user_action: 'PAY_NOW', 342 } 343 } 344 }, 345 purchase_units: [ { 346 amount: { 347 value: parent.data.total, 348 currency_code: parent.data.currency, 349 breakdown: { 350 item_total: { 351 currency_code: parent.data.currency, 352 value: itemTotalValueRoundedAsNumber 353 } 354 } 355 }, 356 items: [ { 357 name: parent.data.name, 358 quantity: parent.data.quantity, 359 unit_amount: { 360 value: parent.data.price, 361 currency_code: parent.data.currency 362 } 363 } ] 364 } ] 365 }; 366 367 if ( parent.data.tax ) { 368 order_data.purchase_units[ 0 ].amount.breakdown.tax_total = { 369 currency_code: parent.data.currency, 370 value: parent.PHP_round( parent.data.tax_amount * parent.data.quantity, parent.data.dec_num ) 371 }; 372 order_data.purchase_units[ 0 ].items[ 0 ].tax = { 373 currency_code: parent.data.currency, 374 value: parent.data.tax_amount 375 }; 376 } 377 if ( parent.data.shipping ) { 378 order_data.purchase_units[ 0 ].amount.breakdown.shipping = { 379 currency_code: parent.data.currency, 380 value: parent.getTotalShippingCost(), 381 }; 382 } 383 if ( parent.data.discount ) { 384 order_data.purchase_units[ 0 ].amount.breakdown.discount = { 385 currency_code: parent.data.currency, 386 value: parseFloat( parent.data.discountAmount ) 387 }; 388 } 389 console.log('Order data: ' + JSON.stringify(order_data)); 390 //End of create order_data object. 391 392 let nonce = wpec_create_order_vars.nonce; 393 394 let wpec_data_for_create = parent.data;//parent.data is the data object that was passed to the ppecHandler constructor. 395 console.log('WPEC data for create-order: ' + JSON.stringify(wpec_data_for_create)); 396 397 let post_data = 'action=wpec_pp_create_order&data=' + encodeURIComponent(JSON.stringify(order_data)) + '&wpec_data=' + encodeURIComponent(JSON.stringify(wpec_data_for_create)) + '&_wpnonce=' + nonce; 398 try { 399 // Using fetch for AJAX request. This is supported in all modern browsers.
400 const response = await fetch( ppecFrontVars.ajaxUrl, { 401 method: "post", 402 headers: { 403 'Content-Type': 'application/x-www-form-urlencoded' 404 }, 405 body: post_data 406 }); 407 408 const response_data = await response.json(); 409 410 if (response_data.order_id) { 411 console.log('Create-order API call to PayPal completed successfully.'); 412 return response_data.order_id; 413 } else { 414 const error_message = response_data.err_msg 415 console.error('Error occurred during create-order call to PayPal. ' + error_message); 416 throw new Error(error_message);//This will trigger the alert in the "catch" block below. 417 } 418 } catch (error) { 419 console.error(error.message); 420 alert('Could not initiate PayPal Checkout...\n\n' + error.message); 421 } 422 }, 423 onApprove: async function( data, actions ) { 424 jQuery( 'div.wp-ppec-overlay[data-ppec-button-id="' + parent.data.id + '"]' ).css( 'display', 'flex' ); 425 426 console.log('Setting up the AJAX request for capture-order call.'); 427 428 // Create the data object to be sent to the server. 429 let pp_bn_data = {}; 430 pp_bn_data.order_id = data.orderID;//The orderID is the ID of the order that was created in the createOrder method. 431 let wpec_data = parent.data;//parent.data is the data object that was passed to the ppecHandler constructor. 432 //console.log('WPEC data (JSON): ' + JSON.stringify(wpec_data)); 433 434 let nonce = wpec_on_approve_vars.nonce; 435 let post_data = 'action=wpec_pp_capture_order&data=' + encodeURIComponent(JSON.stringify(pp_bn_data)) + '&wpec_data=' + encodeURIComponent(JSON.stringify(wpec_data)) + '&_wpnonce=' + nonce; 436 try { 437 const response = await fetch( ppecFrontVars.ajaxUrl, { 438 method: "post", 439 headers: { 440 'Content-Type': 'application/x-www-form-urlencoded' 441 }, 442 body: post_data 443 }); 444 445 const response_data = await response.json(); 446 447 console.log('Capture-order API call to PayPal completed successfully.'); 448 449 // Call the completePayment method to do any redirection or display a message to the user. 450 parent.completePayment(response_data); 451 452 } catch (error) { 453 console.error(error); 454 alert('PayPal returned an error! Transaction could not be processed. Enable the debug logging feature to get more details...\n\n' + JSON.stringify(error)); 455 } 456 457 }, 458 onError: function( err ) { 459 460 jQuery("#place-order-"+parent.data.id).find("button>svg").hide(); 461 jQuery("#place-order-"+parent.data.id).find("button").attr("disabled",false); 462 463 alert( err ); 464 } 465 }; 466 467 this.formatMoney = function( n ) { 468 var decimalPlaces = isNaN(decimalPlaces = Math.abs(parent.data.dec_num)) ? 2 : parent.data.dec_num; 469 var decimalSeparator = parent.data.dec_sep || "."; 470 var thousandSeparator = parent.data.thousand_sep || ","; 471 var sign = n < 0 ? "-" : ""; 472 var integerPart = String(parseInt(n = Math.abs(Number(n) || 0).toFixed(decimalPlaces))); 473 var integerPartLength = integerPart.length; 474 var remainderLength = integerPartLength > 3 ? integerPartLength % 3 : 0; 475 476 var formattedIntegerPart = sign + 477 (remainderLength ? integerPart.substr(0, remainderLength) + thousandSeparator : "") + 478 integerPart.substr(remainderLength).replace(/(\d{3})(?=\d)/g, "$1" + thousandSeparator) + 479 (decimalPlaces ? decimalSeparator + Math.abs(n - integerPart).toFixed(decimalPlaces).slice(2) : ""); 480 481 var formats = { 482 left: '{symbol}{price}', 483 left_space: '{symbol} {price}', 484 right: '{price}{symbol}', 485 right_space: '{price} {symbol}' 486 }; 487 488 var formattedPrice = formats[parent.data.curr_pos] 489 .replace('{symbol}', parent.data.currency_symbol) 490 .replace('{price}', formattedIntegerPart); 491 492 return formattedPrice; 493 }; 494 495 this.getPriceContainer = function() { 496 return jQuery( '.' + parent.scCont.data( 'price-class' ) ); 497 }; 498 499 this.updateAllAmounts = function() { 500 parent.calcTotal(); 501 var price_cont = parent.getPriceContainer(); 502 if ( price_cont.length > 0 ) { 503 var price = price_cont.find( '.wpec-price-amount' ); 504 if ( price.length > 0 ) { 505 price.html( parent.formatMoney( parent.data.price ) ); 506 } 507 if ( parent.data.quantity > 1 ) { 508 price_cont.find( '.wpec-quantity' ).show(); 509 price_cont.find( '.wpec-quantity-val' ).html( parent.data.quantity ); 510 } else { 511 price_cont.find( '.wpec-quantity' ).hide(); 512 } 513 var total = price_cont.find( '.wpec_tot_current_price' ); 514 var tot_new = price_cont.find( '.wpec_tot_new_price' ); 515 var price_new = price_cont.find( '.wpec-new-price-amount' ); 516 var shipping_new = price_cont.find( '.wpec_price_shipping_amount' ); 517 if ( typeof parent.data.discountAmount !== "undefined" ) { 518 price_new.html( parent.formatMoney( parent.data.newPrice ) ); 519 tot_new.html( parent.formatMoney( parent.data.total ) ); 520 total.html( parent.formatMoney( parent.data.subtotal ) ); 521 } else if ( total.length > 0 ) { 522 total.html( parent.formatMoney( parent.data.total ) ); 523 } 524 525 // Update the total shipping cost. 526 shipping_new.html(parent.formatMoney(parent.getTotalShippingCost())); 527 528 var tax_val = price_cont.find( '.wpec-tax-val' ); 529 if ( tax_val.length > 0 ) { 530 tax_val.html( parent.formatMoney( parent.data.tax_amount * parent.data.quantity ) ); 531 } 532 } 533 534 jQuery( document ).trigger( 'wpec_after_update_all_amounts', [ parent ] ); 535 }; 536 537 this.calcTotal = function() { 538 var itemSubt = parseFloat( parent.data.price ); 539 var quantity = parseInt( parent.data.quantity ); 540 var tAmount = itemSubt * quantity; 541 //We need to round to 2 decimal places to make sure that the API call will not fail. 542 let roundedTotal = tAmount.toFixed(2);//round to 2 decimal places 543 let roundedTotalAsNumber = parseFloat(roundedTotal);//convert to number 544 tAmount = roundedTotalAsNumber; 545 var subtotal = tAmount; 546 547 parent.data.newPrice = itemSubt; 548 549 if ( typeof parent.data.discount !== "undefined" ) { 550 var discountAmount = 0; 551 if ( parent.data.discountType === 'perc' ) { 552 discountAmount = parent.PHP_round( tAmount * parent.data.discount / 100, parent.data.dec_num ); 553 } else { 554 discountAmount = data.discount; 555 } 556 if ( discountAmount > tAmount ) { 557 discountAmount = tAmount; 558 } 559 tAmount = tAmount - discountAmount; 560 parent.data.discountAmount = parent.PHP_round( discountAmount, parent.data.dec_num ); 561 parent.data.newPrice = parent.PHP_round( itemSubt - discountAmount / quantity, parent.data.dec_num ); 562 } 563 564 if ( parent.data.tax ) { 565 var tax = parent.PHP_round( tAmount / quantity * parent.data.tax / 100, parent.data.dec_num ); 566 parent.data.tax_amount = tax; 567 tAmount += tax * parent.data.quantity; 568 subtotal += parent.PHP_round( subtotal / quantity * parent.data.tax / 100, parent.data.dec_num ) * parent.data.quantity; 569 } 570 571 const totalShippingCost = parent.getTotalShippingCost(); 572 if ( totalShippingCost ) { 573 tAmount += parseFloat( totalShippingCost ); 574 subtotal += parseFloat( totalShippingCost ); 575 } 576 parent.data.total = parent.PHP_round( tAmount, parent.data.dec_num ); 577 parent.data.subtotal = parent.PHP_round( subtotal, parent.data.dec_num ); 578 }; 579 580 this.PHP_round = function( num, dec ) { 581 return Math.round( num * Math.pow( 10, dec ) ) / Math.pow( 10, dec ); 582 }; 583 584 this.applyVariations = function( amount ) { 585 var grpId; 586 if ( parent.data.variations.applied ) { 587 for ( grpId = 0; grpId < parent.data.variations.applied.length; ++grpId ) { 588 var variation = parent.data.variations[ grpId ]; 589 amount = amount + parseFloat( variation.prices[ parent.data.variations.applied[ grpId ] ] ); 590 } 591 } 592 return parent.PHP_round( amount, parent.data.dec_num ); 593 }; 594 595 /** 596 * Calculates the total shipping cost. 597 * It calculates the per quantity shipping cost along with the base shipping cost of that product. 598 * 599 * @returns {float} The total shipping cost in float of two decimal places. 600 */ 601 this.getTotalShippingCost = function() { 602 let total = 0; 603 const quantity = parent.data.quantity ? parseInt(parent.data.quantity) : 1; 604 const baseShipping = parent.data.shipping ? parseFloat( parent.data.shipping ) : 0; 605 const shippingPerQuantity = parent.data.shipping_per_quantity ? parseFloat( parent.data.shipping_per_quantity ) : 0; 606 607 total = baseShipping + (shippingPerQuantity * quantity); 608 // Round to 2 decimal places. 609 total = parseFloat(total.toFixed(2)) 610 return total; 611 } 612 613 jQuery( document ).trigger( 'wpec_before_render_button', [ this ] ); 614 615 paypal.Buttons( this.buttonArgs ).render( '#' + parent.data.id ); 616}; 617 618var wpecModal = function( $ ) { 619 var openModalId = false;
620 621 $( '.wpec-modal-open, .wpec-modal-overlay, .wpec-modal-close' ).on( 'click', function( e ) { 622 e.preventDefault(); 623 toggleModal( $( this ).data( 'wpec-modal' ) ); 624 } ); 625 626 document.onkeydown = function( evt ) { 627 evt = evt || window.event; 628 var isEscape = false; 629 if ( "key" in evt ) { 630 isEscape = ( evt.key === "Escape" || evt.key === "Esc" ); 631 } else { 632 isEscape = ( evt.keyCode === 27 ); 633 } 634 if ( isEscape && openModalId ) { 635 toggleModal(); 636 } 637 }; 638 639 function toggleModal( modalId ) { 640 modalId = modalId ? modalId : openModalId; 641 openModalId = modalId; 642 var modal = document.getElementById( modalId ); 643 modal.classList.toggle( 'wpec-opacity-0' ); 644 modal.classList.toggle( 'wpec-pointer-events-none' ); 645 } 646 647 $( '.wpec-custom-number-input button' ).on( 'click', function() { 648 var increment = $( this ).data( 'action' ) === 'increment' ? 1 : -1; 649 var input = $( this ).parent().find( 'input' ); 650 var step = input.attr( 'step' ) ? Number( input.attr( 'step' ) ) : 1; 651 input.val( Number( input.val() ) + increment * step ).change(); 652 } ); 653 654 //shortcode_wpec_show_all_products 655 $("#wpec-sort-by").change(function(){ 656 $("#wpec-sort-by-form").submit(); 657 }); 658}; 659 660jQuery( wpecModal );
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.