CSR-1390 dynamic resize of iFrame

Implement iFrameResizer node package.
This commit is contained in:
Bryan Mauger 2023-11-01 09:56:27 -04:00
parent 320638ec98
commit 595e97ea9f
5 changed files with 201 additions and 175 deletions

18
package-lock.json generated
View file

@ -14,6 +14,7 @@
"canvas-confetti": "^1.4.0", "canvas-confetti": "^1.4.0",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"http-status-codes": "^2.1.4", "http-status-codes": "^2.1.4",
"iframe-resizer": "^4.3.7",
"jest-junit": "^13.0.0", "jest-junit": "^13.0.0",
"maska": "^1.5.0", "maska": "^1.5.0",
"vee-validate": "^4.5.7", "vee-validate": "^4.5.7",
@ -11813,6 +11814,18 @@
"integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
"dev": true "dev": true
}, },
"node_modules/iframe-resizer": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.7.tgz",
"integrity": "sha512-a3EGVScU9NtUpj6lWvGhVw3EfOw5AopRs5xGsQU385kWdgQt++OsD6PCnTV+8YkgBu/g28rLIh0EztFg9UQr1Q==",
"engines": {
"node": ">=0.8.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/davidjbradshaw/iframe-resizer/blob/master/FUNDING.md"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@ -33845,6 +33858,11 @@
"integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
"dev": true "dev": true
}, },
"iframe-resizer": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.7.tgz",
"integrity": "sha512-a3EGVScU9NtUpj6lWvGhVw3EfOw5AopRs5xGsQU385kWdgQt++OsD6PCnTV+8YkgBu/g28rLIh0EztFg9UQr1Q=="
},
"ignore": { "ignore": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",

View file

@ -17,6 +17,7 @@
"canvas-confetti": "^1.4.0", "canvas-confetti": "^1.4.0",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"http-status-codes": "^2.1.4", "http-status-codes": "^2.1.4",
"iframe-resizer": "^4.3.7",
"jest-junit": "^13.0.0", "jest-junit": "^13.0.0",
"maska": "^1.5.0", "maska": "^1.5.0",
"vee-validate": "^4.5.7", "vee-validate": "^4.5.7",

View file

@ -75,14 +75,11 @@ body .creditCardSpecific div {
padding: 8px 0; padding: 8px 0;
} }
body .creditCardSpecific div .headerlinecontainer { body .creditCardSpecific div .headerlinecontainer {
padding: 0; display: none;
} }
body .creditCardSpecific div label { body .creditCardSpecific div label {
font-weight: 500; font-weight: 500;
} }
body .creditCardSpecific div:first-child {
display: none;
}
body .creditCardSpecific #infoRow2 { body .creditCardSpecific #infoRow2 {
margin-bottom: 0; margin-bottom: 0;
} }

View file

@ -88,14 +88,11 @@ body {
div { div {
padding: 8px 0; padding: 8px 0;
.headerlinecontainer { .headerlinecontainer {
padding: 0; display: none;
} }
label { label {
font-weight: 500; font-weight: 500;
} }
&:first-child {
display: none;
}
} }
#infoRow2 { #infoRow2 {
margin-bottom: 0; margin-bottom: 0;

View file

@ -12,178 +12,179 @@
<div class="col-md-6 col-xl-4 p-0"> <div class="col-md-6 col-xl-4 p-0">
<div id="card-container"> <div id="card-container">
<iframe <iframe
ref="paymentFrame" v-resize
class="hop-iframe payment-iframe" ref="paymentFrame"
name="card-frame" class="hop-iframe payment-iframe"
id="card-frame" name="card-frame"
seamless id="card-frame"
scrolling="no"> seamless
</iframe> scrolling="no">
</div> </iframe>
<div>{{ switchPaymentText }}</div>
<div>
<button
v-if="paymentType !== 'cc'"
ref="switchToCCButton"
type="button"
@mousedown="switchPIAMethod('cc')"
aria-label="Switch to Credit Card">
Switch to Credit Card
</button>
</div>
<div v-if="paymentType !== 'cc'">or</div>
<div>
<button
v-if="paymentType !== 'pp'"
ref="switchToPPButton"
type="button"
@mousedown="switchPIAMethod('pp')"
aria-label="Switch to PayPal">
Switch to PayPal
</button>
</div>
<div v-if="paymentType === 'cc'">or</div>
<div>
<button
v-if="paymentType !== 'ap'"
ref="switchToAPButton"
type="button"
@mousedown="switchPIAMethod('ap')"
aria-label="Switch to Afterpay">
Switch to Afterpay
</button>
</div>
<navbar
cmsWidgetName="FunnelFooterWidget"
isForwardActionDisabled="true"
:isBackButtonHidden="shouldHideBackButton"
isSubmitHidden="true"
@back-clicked="backButtonAction" />
</div> </div>
<div>{{ switchPaymentText }}</div>
<div>
<button
v-if="paymentType !== 'cc'"
ref="switchToCCButton"
type="button"
@mousedown="switchPIAMethod('cc')"
aria-label="Switch to Credit Card">
Switch to Credit Card
</button>
</div> </div>
<div v-if="paymentType !== 'cc'">or</div>
<div>
<button
v-if="paymentType !== 'pp'"
ref="switchToPPButton"
type="button"
@mousedown="switchPIAMethod('pp')"
aria-label="Switch to PayPal">
Switch to PayPal
</button>
</div> </div>
</Form> <div v-if="paymentType === 'cc'">or</div>
<div>
<button
v-if="paymentType !== 'ap'"
ref="switchToAPButton"
type="button"
@mousedown="switchPIAMethod('ap')"
aria-label="Switch to Afterpay">
Switch to Afterpay
</button>
</div>
<navbar
cmsWidgetName="FunnelFooterWidget"
isForwardActionDisabled="true"
:isBackButtonHidden="shouldHideBackButton"
isSubmitHidden="true"
@back-clicked="backButtonAction" />
</div>
</div>
</div>
</Form>
<form <form
ref="hopForm" ref="hopForm"
id="card-data" id="card-data"
:target="paypalPayment ? '_top' : 'card-frame'" :target="paypalPayment ? '_top' : 'card-frame'"
method="POST" method="POST"
:action="checkoutUrl"> :action="checkoutUrl">
<input type="hidden" name="paymentType" :value="paymentType" /> <input type="hidden" name="paymentType" :value="paymentType" />
<input type="hidden" name="sgSessionId" :value="authToken" /> <input type="hidden" name="sgSessionId" :value="authToken" />
<input type="hidden" name="sgAuthToken" :value="authToken" /> <input type="hidden" name="sgAuthToken" :value="authToken" />
<input type="hidden" name="sgSignaturePublic" :value="authSignature" /> <input type="hidden" name="sgSignaturePublic" :value="authSignature" />
<input type="hidden" name="sgSignatureStartDate" :value="authSignatureStart" /> <input type="hidden" name="sgSignatureStartDate" :value="authSignatureStart" />
<input type="hidden" name="referralSeqNum" :value="referralSequenceNumber" /> <input type="hidden" name="referralSeqNum" :value="referralSequenceNumber" />
<input type="hidden" name="sge_commerce_indicator_isinternet" value="true" /> <input type="hidden" name="sge_commerce_indicator_isinternet" value="true" />
<input type="hidden" name="sghopsource" value="Safelite.com" /> <input type="hidden" name="sghopsource" value="Safelite.com" />
<input type="hidden" name="sgHtmlStyle" value="ResourceSafeliteHtml" /> <input type="hidden" name="sgHtmlStyle" value="ResourceSafeliteHtml" />
<input type="hidden" name="sgErrorMessagesEmbedded" value="true" /> <input type="hidden" name="sgErrorMessagesEmbedded" value="true" />
<input type="hidden" name="sgNoKeystrokeProcessing" value="false" /> <input type="hidden" name="sgNoKeystrokeProcessing" value="false" />
<input type="hidden" name="maskCharacter" value="*" /> <input type="hidden" name="maskCharacter" value="*" />
<input type="hidden" name="styleSheetCode" :value="dynamicCSSUrl" /> <input type="hidden" name="styleSheetCode" :value="dynamicCSSUrl" />
<input type="hidden" name="styleSheetCode2" :value="dynamicHopCSSUrl" /> <input type="hidden" name="styleSheetCode2" :value="dynamicHopCSSUrl" />
<input type="hidden" name="sgReceiptResponseURL" :value="piaResponseUrl" /> <input type="hidden" name="sgReceiptResponseURL" :value="piaResponseUrl" />
<input type="hidden" name="sgDeclineResponseURL" :value="piaResponseUrl" /> <input type="hidden" name="sgDeclineResponseURL" :value="piaResponseUrl" />
<input type="hidden" name="sgErrorResponseURL" :value="piaResponseUrl" /> <input type="hidden" name="sgErrorResponseURL" :value="piaResponseUrl" />
<input type="hidden" name="sgheaderline1" :value="getHeaderLine1" /> <input type="hidden" name="sgheaderline1" :value="getHeaderLine1" />
<input type="hidden" name="sgHeader1subtitle" value="" /> <input type="hidden" name="sgHeader1subtitle" value="" />
<input type="hidden" name="sgheaderline2" :value="getHeaderLine2" /> <input type="hidden" name="sgheaderline2" :value="getHeaderLine2" />
<input type="hidden" name="sgheaderline3" value="" /> <input type="hidden" name="sgheaderline3" value="" />
<input type="hidden" name="sgheaderline4" value="" /> <input type="hidden" name="sgheaderline4" value="" />
<input type="hidden" name="sgheaderline5" value="*Required information" /> <input type="hidden" name="sgheaderline5" value="*Required information" />
<input type="hidden" name="billTo_firstName" :value="firstName" /> <input type="hidden" name="billTo_firstName" :value="firstName" />
<input type="hidden" name="billTo_firstNameShow" value="true" /> <input type="hidden" name="billTo_firstNameShow" value="true" />
<input type="hidden" name="sghopmiddleInitialShow" value="false" /> <input type="hidden" name="sghopmiddleInitialShow" value="false" />
<input type="hidden" name="billTo_lastName" :value="lastName" /> <input type="hidden" name="billTo_lastName" :value="lastName" />
<input type="hidden" name="billTo_lastNameShow" value="true" /> <input type="hidden" name="billTo_lastNameShow" value="true" />
<input type="hidden" name="billTo_street1" value="" /> <input type="hidden" name="billTo_street1" value="" />
<input type="hidden" name="billTo_street2" value="" /> <input type="hidden" name="billTo_street2" value="" />
<input type="hidden" name="billTo_city" value="" /> <input type="hidden" name="billTo_city" value="" />
<input type="hidden" name="billTo_state" value="" /> <input type="hidden" name="billTo_state" value="" />
<input type="hidden" name="billTo_postalCode" value="" /> <input type="hidden" name="billTo_postalCode" value="" />
<input type="hidden" name="billTo_postalCodeShow" value="true" /> <input type="hidden" name="billTo_postalCodeShow" value="true" />
<input type="hidden" name="billTo_postalCodeEnable" value="true" /> <input type="hidden" name="billTo_postalCodeEnable" value="true" />
<input type="hidden" name="sgLabelPostalCode" value="Billing ZIP" /> <input type="hidden" name="sgLabelPostalCode" value="Billing ZIP" />
<input type="hidden" name="sgtotalamount" :value="displayAmount" /> <input type="hidden" name="sgtotalamount" :value="displayAmount" />
<input type="hidden" name="totalAmountDecimal" :value="totalAmount" /> <input type="hidden" name="totalAmountDecimal" :value="totalAmount" />
<input type="hidden" name="lineItems" :value="piaLineItems" /> <input type="hidden" name="lineItems" :value="piaLineItems" />
<input type="hidden" name="sgdiscountstrikethruamount" value="" /> <input type="hidden" name="sgdiscountstrikethruamount" value="" />
<input type="hidden" name="callerDisplayText" value="" /> <input type="hidden" name="callerDisplayText" value="" />
<input <input
type="hidden" type="hidden"
name="sgtermsofusedisplaytext" name="sgtermsofusedisplaytext"
value="By selecting submit, I agree to Safelite's" /> value="By selecting submit, I agree to Safelite's" />
<input type="hidden" name="sgtermsofuseurl" value="http://www.safelite.com/terms-of-use/" /> <input type="hidden" name="sgtermsofuseurl" value="http://www.safelite.com/terms-of-use/" />
<input type="hidden" name="sgtermsofuselinkdisplaytext" value="terms of use" /> <input type="hidden" name="sgtermsofuselinkdisplaytext" value="terms of use" />
<input type="hidden" name="sgtermsofcancelrefunddisplaytext" value="and" /> <input type="hidden" name="sgtermsofcancelrefunddisplaytext" value="and" />
<input <input
type="hidden" type="hidden"
name="sgtermsofcancelrefundlinkdisplaytext" name="sgtermsofcancelrefundlinkdisplaytext"
value="cancellation and refund policy" /> value="cancellation and refund policy" />
<input <input
type="hidden" type="hidden"
name="sgtermsofcancelrefundurl" name="sgtermsofcancelrefundurl"
value="http://www.safelite.com/cancellation-refund-policy" /> value="http://www.safelite.com/cancellation-refund-policy" />
<input <input
type="hidden" type="hidden"
name="sgErrorMessageCardVerification" name="sgErrorMessageCardVerification"
value="Credit card could not be processed" /> value="Credit card could not be processed" />
<input <input
type="hidden" type="hidden"
name="sgErrorMessageTimeOut" name="sgErrorMessageTimeOut"
value="For your security, this transaction has been timed out." /> value="For your security, this transaction has been timed out." />
<input type="hidden" name="sgLabelCardNumber" value="" /> <input type="hidden" name="sgLabelCardNumber" value="" />
<input type="hidden" name="sgLabelAddressLine1" :value="address1" /> <input type="hidden" name="sgLabelAddressLine1" :value="address1" />
<input type="hidden" name="sgLabelAddressLine2" :value="address2" /> <input type="hidden" name="sgLabelAddressLine2" :value="address2" />
<input type="hidden" name="sgLabelCity" :value="city" /> <input type="hidden" name="sgLabelCity" :value="city" />
<input type="hidden" name="sgLabelState" :value="state" /> <input type="hidden" name="sgLabelState" :value="state" />
<input type="hidden" name="sgCtu" :value="ctu" /> <input type="hidden" name="sgCtu" :value="ctu" />
<input type="hidden" name="sgWorkOrder" :value="workOrderNumber" /> <input type="hidden" name="sgWorkOrder" :value="workOrderNumber" />
<input type="hidden" name="sgEmailAddress" :value="emailAddress" /> <input type="hidden" name="sgEmailAddress" :value="emailAddress" />
<input type="hidden" name="paypalInvoiceNumber" :value="invoiceNumber" /> <input type="hidden" name="paypalInvoiceNumber" :value="invoiceNumber" />
<input type="hidden" name="paypalSuccessUrl" :value="piaResponseUrl" /> <input type="hidden" name="paypalSuccessUrl" :value="piaResponseUrl" />
<input type="hidden" name="paypalCancelUrl" :value="piaCancelUrl" /> <input type="hidden" name="paypalCancelUrl" :value="piaCancelUrl" />
<input type="hidden" name="sgCCDeclineURL" :value="piaCancelUrl" /> <input type="hidden" name="sgCCDeclineURL" :value="piaCancelUrl" />
<input type="hidden" name="sgCCTimeoutURL" :value="piaCancelUrl" /> <input type="hidden" name="sgCCTimeoutURL" :value="piaCancelUrl" />
<input type="hidden" name="sgTransactionType" value="authorization" /> <input type="hidden" name="sgTransactionType" value="authorization" />
<input type="hidden" name="amount" :value="totalAmount" /> <input type="hidden" name="amount" :value="totalAmount" />
<input type="hidden" name="ctu" :value="ctu" /> <input type="hidden" name="ctu" :value="ctu" />
<input type="hidden" name="orderNumber" :value="workOrderNumber" /> <input type="hidden" name="orderNumber" :value="workOrderNumber" />
<input type="hidden" name="billTo_email" :value="emailAddress" /> <input type="hidden" name="billTo_email" :value="emailAddress" />
<input type="hidden" name="useDecisionManager" value="True" /> <input type="hidden" name="useDecisionManager" value="True" />
<input type="hidden" name="correlationId" :value="referralCorrelationId" /> <input type="hidden" name="correlationId" :value="referralCorrelationId" />
<input type="hidden" name="sgErrorMessageCard_CVN" value="Please enter a valid CVV" /> <input type="hidden" name="sgErrorMessageCard_CVN" value="Please enter a valid CVV" />
<input type="hidden" name="ship_to_address_line1" :value="address1" /> <input type="hidden" name="ship_to_address_line1" :value="address1" />
<input type="hidden" name="ship_to_address_line2" :value="address2" /> <input type="hidden" name="ship_to_address_line2" :value="address2" />
<input type="hidden" name="ship_to_address_city" :value="city" /> <input type="hidden" name="ship_to_address_city" :value="city" />
<input type="hidden" name="ship_to_address_state" :value="state" /> <input type="hidden" name="ship_to_address_state" :value="state" />
<input type="hidden" name="ship_to_address_country" value="US" /> <input type="hidden" name="ship_to_address_country" value="US" />
<input type="hidden" name="ship_to_address_postal_code" :value="zipCode" /> <input type="hidden" name="ship_to_address_postal_code" :value="zipCode" />
<input type="hidden" name="ship_to_phone" :value="phoneNumber" /> <input type="hidden" name="ship_to_phone" :value="phoneNumber" />
<input type="hidden" name="calling_application" value="NextGen" /> <input type="hidden" name="calling_application" value="NextGen" />
</form> </form>
</template> </template>
<script> <script>
@ -202,7 +203,7 @@ import { paymentMethods } from "@/constants/payment-method-constants";
import { AppointmentTypeStrings } from "@/constants/schedule-constants"; import { AppointmentTypeStrings } from "@/constants/schedule-constants";
import baseMixin from "@/mixins/base-mixin.js"; import baseMixin from "@/mixins/base-mixin.js";
// Validation import iframeResize from "../../../node_modules/iframe-resizer/js/iframeResizer.js";
export default { export default {
name: "payment", name: "payment",
@ -235,6 +236,18 @@ export default {
paypalPayment: this.isPaypal(), paypalPayment: this.isPaypal(),
}; };
}, },
directives: {
resize:{
mounted: function(el) {
el.addEventListener('load', () => {
iframeResize({ checkOrigin: false }, el);
});
},
unmounted: function (el) {
el.iFrameResizer.removeListeners();
}
}
},
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
@ -316,7 +329,7 @@ export default {
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE; const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
const serviceLocationReqs = const serviceLocationReqs =
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs); (isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
// Insurance // Insurance
const isInsuranceSet = store.getters.order.payment.isInsurance !== null; const isInsuranceSet = store.getters.order.payment.isInsurance !== null;
@ -341,8 +354,8 @@ export default {
); );
const paymentMethodReqs = const paymentMethodReqs =
store.getters.order.payment.isPia !== null && store.getters.order.payment.isPia !== null &&
(store.getters.order.payment.isPia || !!store.getters.order.payment.piaType); (store.getters.order.payment.isPia || !!store.getters.order.payment.piaType);
return ( return (
packageReqs && packageReqs &&
@ -370,39 +383,39 @@ export default {
}, },
getAddress1() { getAddress1() {
return store.getters.order.serviceLocation.address return store.getters.order.serviceLocation.address
? store.getters.order.serviceLocation.address ? store.getters.order.serviceLocation.address
: store.getters.order.serviceLocation.provider.address.streetAddress; : store.getters.order.serviceLocation.provider.address.streetAddress;
}, },
getAddress2() { getAddress2() {
return store.getters.order.serviceLocation.address2 return store.getters.order.serviceLocation.address2
? store.getters.order.serviceLocation.address2 ? store.getters.order.serviceLocation.address2
: null; : null;
}, },
getCity() { getCity() {
return store.getters.order.serviceLocation.city return store.getters.order.serviceLocation.city
? store.getters.order.serviceLocation.city ? store.getters.order.serviceLocation.city
: store.getters.order.serviceLocation.provider.address.city; : store.getters.order.serviceLocation.provider.address.city;
}, },
getState() { getState() {
return store.getters.order.serviceLocation.state return store.getters.order.serviceLocation.state
? store.getters.order.serviceLocation.state ? store.getters.order.serviceLocation.state
: store.getters.order.serviceLocation.provider.address.state; : store.getters.order.serviceLocation.provider.address.state;
}, },
getZipCode() { getZipCode() {
return store.getters.order.serviceLocation.zipCode return store.getters.order.serviceLocation.zipCode
? store.getters.order.serviceLocation.zipCode ? store.getters.order.serviceLocation.zipCode
: store.getters.order.serviceLocation.provider.address.zipCode; : store.getters.order.serviceLocation.provider.address.zipCode;
}, },
getPaymentType() { getPaymentType() {
switch (store.getters.order.payment.piaType) { switch (store.getters.order.payment.piaType) {
case paymentMethods.AFTERPAY: case paymentMethods.AFTERPAY:
return "ap"; return "ap";
case paymentMethods.CREDIT_CARD: case paymentMethods.CREDIT_CARD:
return "cc"; return "cc";
case paymentMethods.PAYPAL: case paymentMethods.PAYPAL:
return "pp"; return "pp";
default: default:
return store.getters.payment.piaType; return store.getters.payment.piaType;
} }
}, },
getPiaLineItems() { getPiaLineItems() {
@ -487,7 +500,7 @@ export default {
<style lang="scss"> <style lang="scss">
.hop-iframe { .hop-iframe {
position: relative; position: relative;
min-height: 1320px; min-height: 1120px;
width: 100%; width: 100%;
border: 0 none; border: 0 none;
} }