Skip to content

Commit

Permalink
Merge pull request #124 from recurly/co-badge
Browse files Browse the repository at this point in the history
Add Dual/Co-Badged example
  • Loading branch information
chrissrogers authored Mar 11, 2024
2 parents 8e1e96f + 885bf6b commit a1b6502
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 0 deletions.
171 changes: 171 additions & 0 deletions public/coBadged/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Recurly.js Example: Co-Badged Support</title>
<script src="https://js.recurly.com/v4/recurly.js"></script>
<script src="/config"></script>
<link href="https://js.recurly.com/v4/recurly.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" />
<link href="/style.css" rel="stylesheet" />
</head>
<body>
<main>
<section>
<h1 class="logo">
<span class="price">$10</span>
<span class="term">monthly</span>
</h1>
</section>

<section id="errors" class="errors"></section>

<section>
<form method="post" action="/api/subscriptions/new">

<div>
<label for="first_name">First Name</label>
<input type="text" data-recurly="first_name" id="first_name" name="first-name">
</div>

<div>
<label for="last_name">Last Name</label>
<input type="text" data-recurly="last_name" id="last_name" name="last-name">
</div>

<div id="card-element-container">
<div data-my-js-ref="recurly-element-card"></div>
</div>

<button id="subscribe">Subscribe</button>

<input type="hidden" data-recurly="token" name="recurly-token">
</form>
</section>
</main>

<script>
recurly.configure(window.recurlyConfig.publicKey);
// Create a CardElement
const elements = recurly.Elements();
const cardElement = elements.CardElement({
style: {
fontFamily: 'Open Sans',
fontSize: '1rem',
fontWeight: 'bold',
fontColor: '#2c0730'
}
});
cardElement.attach('[data-my-js-ref="recurly-element-card"]');
// Listen for changes to the coBadge card details
cardElement.on('coBadge', handleCoBadge)

function handleCoBadge(coBadgeResults) {
// coBadgeResults is an object with the following properties:
// coBadgeSupport: boolean
// supportedBrands: array of strings (e.g. ['visa', 'cartes_bancaires'])
let coBadgeBrands = coBadgeResults.supportedBrands;
let targetEle = document.querySelector('#card-element-container');
let coBadgeContainer = document.querySelector('#co-badge-container');

if (!coBadgeContainer) {
if (!coBadgeResults.coBadgeSupport) { return; }
// create the coBadge div if it does not exist and the card has coBadge support
createCoBadge(coBadgeBrands, targetEle);
} else {
// remove the coBadge div if the card does not have coBadge support
if (!coBadgeResults.coBadgeSupport) { coBadgeContainer.remove(); return; }
// update the coBadge div if the card has coBadge support
updateCardBrandOptions(coBadgeBrands);
}
}

function createCoBadge(coBadgeBrands, target) {
// create an input for selecting the customer's card brand that is populated with the card's coBadge options
const coBadgeContainer = document.createElement('div');
coBadgeContainer.id = 'co-badge-container';
const coBadgeRadio = document.createElement('div');
coBadgeRadio.id = 'co-badge-radio';
coBadgeBrands.forEach((brand, idx) => {
let brandInput = document.createElement('input');
brandInput.type = 'radio';
brandInput.value = brand;
brandInput.className = 'co-badge-input';
brandInput.id = `co-badge-input-${idx}`;
brandInput.name = 'co-badge';
brandInput.setAttribute('data-recurly', 'card_network_preference');

let brandLabel = document.createElement('label');
brandLabel.textContent = formatBrand(brand);
brandLabel.id = `co-badge-label-${idx}`;
brandLabel.className = 'co-badge-label';

coBadgeRadio.appendChild(brandInput);
coBadgeRadio.appendChild(brandLabel);
});
coBadgeContainer.appendChild(coBadgeRadio);
target.after(coBadgeContainer);
};

function updateCardBrandOptions(coBadgeBrands) {
coBadgeBrands.forEach((brand, idx) => {
let brandInput = document.querySelector(`#co-badge-input-${idx}`);
brandInput.value = brand;

let brandLabel = document.querySelector(`#co-badge-label-${idx}`);
brandLabel.setAttribute('for', brand);
brandLabel.textContent = formatBrand(brand);
});
};

function formatBrand(brand) {
return brand.replace(/_/g, ' ');
};

// When a customer hits their 'enter' key while using the card element
cardElement.on('submit', function (event) {
document.querySelector('form').submit();
});

// On form submit, we stop submission to go get the token
document.querySelector('form').addEventListener('submit', function (event) {
console.log('form submit');
// Prevent the form from submitting while we retrieve the token from Recurly
event.preventDefault();

// Reset the errors display
document.querySelector('#errors').textContent = '';
document.querySelectorAll('input').forEach(input => input.classList.remove('error'));

// Disable the submit button
document.querySelector('button').disabled = true;

const form = this;

// Now we call recurly.token with the form. It goes to Recurly servers
// to tokenize the credit card information, then injects the token into the
// data-recurly="token" field above
recurly.token(elements, form, function (err, token) {
// send any errors to the error function below
if (err) error(err);

// Otherwise we continue with the form submission
else form.submit();

});
});

// A simple error handling function to expose errors to the customer
function error (err) {
document.querySelector('#errors').textContent = 'The following fields appear to be invalid: ' + err.fields.join(', ');
document.querySelector('button').disabled = false;
err.fields.forEach(field => {
document.querySelector(`[data-recurly=${field}]`).classList.add('error');
});
}

// runs some simple animations for the page
document.querySelector('body').classList.add('show');
</script>
</body>
</html>
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ <h1>Examples</h1>
<li><a href="auto-tab/index.html">Auto-tabbing</a></li>
<li><a href="alternative-payment-methods/boleto.html">Alternative Payment Methods - Boleto</a></li>
<li><a href="alternative-payment-methods/ideal.html">Alternative Payment Methods - iDEAL</a></li>
<li><a href="coBadged/index.html">Co-Badged</a></li>
</ul>
</main>
</body>
Expand Down

0 comments on commit a1b6502

Please sign in to comment.