Skip to content

Instantly share code, notes, and snippets.

@mattborn
Last active February 5, 2019 23:37
Show Gist options
  • Save mattborn/48a4320b4c32ee1142120cf3a5f6332f to your computer and use it in GitHub Desktop.
Save mattborn/48a4320b4c32ee1142120cf3a5f6332f to your computer and use it in GitHub Desktop.
Keen Pricing Tuner
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Keen Pricing Tuner</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<script src="https://unpkg.com/scrollreveal"></script>
</head>
<h1>Pricing Tuner</h1>
<h2>Dialed in for:</h2>
<input id="Slider" type="range" value="0">
<div id="SliderUI">
<button class="fas fa-chevron-left" id="SliderUI-Prev"></button>
<div id="SliderUI-Gauge">
<div id="SliderUI-Headline"></div>
<div id="SliderUI-Needle"></div>
</div>
<button class="fas fa-chevron-right" id="SliderUI-Next"></button>
</div>
<div id="Knobs">
<div class="Knobs-Knob" id="Knobs-1">
<div class="Knob-Value"><span class="interpolate">0.00</span>%</div>
<div class="Knob">
<div class="Knob-Circle"></div>
<div class="Knob-Dot Knob-Dot-1"><div></div></div>
<div class="Knob-Dot Knob-Dot-2"><div></div></div>
<div class="Knob-Dot Knob-Dot-3"><div></div></div>
<div class="Knob-Dot Knob-Dot-4"><div></div></div>
<div class="Knob-Dot Knob-Dot-5"><div></div></div>
<div class="Knob-Selection"><div></div></div>
</div>
<div class="Knob-Title">Inserted credit cards <i class="fas fa-info-circle" title="Standard percentage rate charged on inserted or swiped CREDIT cards"></i></div>
</div>
<div class="Knobs-Knob" id="Knobs-2">
<div class="Knob-Value"><span class="interpolate">0.00</span>%</div>
<div class="Knob">
<div class="Knob-Circle"></div>
<div class="Knob-Dot Knob-Dot-1"><div></div></div>
<div class="Knob-Dot Knob-Dot-2"><div></div></div>
<div class="Knob-Dot Knob-Dot-3"><div></div></div>
<div class="Knob-Dot Knob-Dot-4"><div></div></div>
<div class="Knob-Dot Knob-Dot-5"><div></div></div>
<div class="Knob-Selection"><div></div></div>
</div>
<div class="Knob-Title">Inserted debit cards <i class="fas fa-info-circle" title="Standard percentage rate charged on inserted or swiped DEBIT / CHECK CARDS (without a PIN entered)"></i></div>
</div>
<div class="Knobs-Knob" id="Knobs-3">
<div class="Knob-Value"><span class="interpolate">0.00</span>%</div>
<div class="Knob">
<div class="Knob-Circle"></div>
<div class="Knob-Dot Knob-Dot-1"><div></div></div>
<div class="Knob-Dot Knob-Dot-2"><div></div></div>
<div class="Knob-Dot Knob-Dot-3"><div></div></div>
<div class="Knob-Dot Knob-Dot-4"><div></div></div>
<div class="Knob-Dot Knob-Dot-5"><div></div></div>
<div class="Knob-Selection"><div></div></div>
</div>
<div class="Knob-Title">Keyed in credit cards <i class="fas fa-info-circle" title="Standard percentage rate charged on cards keyed in manually by merchant or client as opposed to swiping or inserting."></i></div>
</div>
<div class="Knobs-Knob" id="Knobs-4">
<div class="Knob-Value">$<span class="interpolate">0.00</span></div>
<div class="Knob">
<div class="Knob-Circle"></div>
<div class="Knob-Dot Knob-Dot-1"><div></div></div>
<div class="Knob-Dot Knob-Dot-2"><div></div></div>
<div class="Knob-Selection"><div></div></div>
</div>
<div class="Knob-Title">Flat transaction fee <i class="fas fa-info-circle" title="The flat transaction fee charged on each sale"></i></div>
</div>
<div class="Knobs-Knob" id="Knobs-5">
<div class="Knob-Value">$<span class="interpolate">0.00</span></div>
<div class="Knob">
<div class="Knob-Circle"></div>
<div class="Knob-Dot Knob-Dot-1"><div></div></div>
<div class="Knob-Dot Knob-Dot-2"><div></div></div>
<div class="Knob-Selection"><div></div></div>
</div>
<div class="Knob-Title">Monthly fee <i class="fas fa-info-circle" title="The flat fee charged monthly regardless of processing volume"></i></div>
</div>
<div class="Knobs-Knob" id="Knobs-6">
<div class="Knob-Value">Card Terminal</div>
<div class="Knob">
<div class="Knob-Circle"></div>
<div class="Knob-Dot Knob-Dot-1"><div></div></div>
<div class="Knob-Dot Knob-Dot-2"><div></div></div>
<div class="Knob-Dot Knob-Dot-3"><div></div></div>
<div class="Knob-Dot Knob-Dot-4"><div></div></div>
<div class="Knob-Selection"><div></div></div>
</div>
<div class="Knob-Title">Free equipment <i class="fas fa-info-circle" title="* THIS WILL BE SPECIFIC FOR EACH PIECE OF EQUIPMENT UPDATED SOON The physical or virtual method of processing we provide you with for card payments. Inquire for plans that combine multiple of these options."></i></div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.11/d3.min.js"></script>
<script src="scripts.js"></script>
</body>
</html>
const fadeUp = {
distance: '30%',
interval: 50,
origin: 'bottom'
};
ScrollReveal().reveal('h1', fadeUp);
ScrollReveal().reveal('h2', fadeUp);
ScrollReveal().reveal('#SliderUI', fadeUp);
ScrollReveal().reveal('.Knobs-Knob', fadeUp);
/* Starting with each of the possible content states because content is king. */
const states = [
{
headline: "Eliminate Processing Costs",
knob_1_credit: 0,
knob_2_debit: 0,
knob_3_typed: 0,
knob_4_flat: 0,
knob_5_monthly: 0,
knob_6_equipment: "All",
description: "With our “Cash Discount” Program merchants display a sign reading that all indicated prices have a percentage- based cash discount already applied. Clients lose that cash discount when they pay with a card and our equipment can automatically add that lost cash discount as a line item on the receipt.",
position: 0,
knob_1_position: 0,
knob_2_position: 0,
knob_3_position: 0,
knob_4_position: 0,
knob_5_position: 0,
knob_6_position: 3
},
{
headline: "Credit, Rewards, & Corporate Cards",
knob_1_credit: 1.09,
knob_2_debit: 1.09,
knob_3_typed: 2.39,
knob_4_flat: .2,
knob_5_monthly: 10,
knob_6_equipment: "All Except: 2 in 1 & Virtual Terminal",
description: "Merchants benefitting most from this plan swipe or insert almost all customer cards face to face, have a higher average transaction, don’t see many debit cards, and see a lot of rewards and/or corporate cards.",
position: 1,
knob_1_position: 1,
knob_2_position: 2,
knob_3_position: 1,
knob_4_position: 1,
knob_5_position: 1,
knob_6_position: 2
},
{
headline: "Mostly Debit / Check Cards",
knob_1_credit: 1.58,
knob_2_debit: .55,
knob_3_typed: 2.88,
knob_4_flat: .2,
knob_5_monthly: 10,
knob_6_equipment: "All Except: 2 in 1 & Virtual Terminal",
description: "Best for merchants whose clients use debit cards most of the time, even without a PIN. A sandwich shop near a university would be a good example.",
position: 2,
knob_1_position: 2,
knob_2_position: 1,
knob_3_position: 3,
knob_4_position: 1,
knob_5_position: 1,
knob_6_position: 2
},
{
headline: "Each Average Sale < $20",
knob_1_credit: 1.69,
knob_2_debit: 1.69,
knob_3_typed: 2.69,
knob_4_flat: 0,
knob_5_monthly: 10,
knob_6_equipment: "All Except: 2 in 1 & Virtual Terminal",
description: "If you’re a cafe selling $1 cups of coffee, wouldn’t you happily pay a half percent more to rid the $0.20 flat transaction fee? This plan is meant for merchants with typically small average transactions.",
position: 3,
knob_1_position: 3,
knob_2_position: 3,
knob_3_position: 2,
knob_4_position: 0,
knob_5_position: 1,
knob_6_position: 2
},
{
headline: "Simplicity & Startups",
knob_1_credit: 2.69,
knob_2_debit: 2.69,
knob_3_typed: 3.69,
knob_4_flat: 0,
knob_5_monthly: 0,
knob_6_equipment: "2 in 1 Bluetooth Reader",
description: "Our ‘Pay-As-You- Go’ plan for those just getting their feet wet. If you aren’t sure what demand you’ll have, escaping any monthly fee with this plan is the way to go!",
position: 4,
knob_1_position: 4,
knob_2_position: 4,
knob_3_position: 4,
knob_4_position: 0,
knob_5_position: 0,
knob_6_position: 1
},
{
headline: "No Face to Face Transactions",
knob_1_credit: -1,
knob_2_debit: -1,
knob_3_typed: 1.64,
knob_4_flat: .25,
knob_5_monthly: 15,
knob_6_equipment: "Online Methods",
description: "This is for merchants who either key every card number in themselves or their clients do it directly. It can integrate independently into your website, a shopping cart you already have, emailed invoices, virtual terminals, and more.",
position: 5,
knob_1_position: 0,
knob_2_position: 0,
knob_3_position: 0,
knob_4_position: 0,
knob_5_position: 0,
knob_6_position: 0
}
];
/* Using data above, use slider to set state. */
const Slider = document.getElementById('Slider');
const Knob = document.querySelector('.Knob');
const updateSliderAndKnobs = function (newValues) {
document.getElementById('SliderUI-Needle').style.left = (newValues.position * 57) +'px';
document.getElementById('SliderUI-Headline').innerHTML = newValues.headline;
document.querySelector('.Knob-Selection')
/* Loop through newValues. */
Object.keys(newValues).forEach(function (value) {
/* Select each knob component & pass value. */
});
const Knob1 = document.getElementById('Knobs-1');
const Knob2 = document.getElementById('Knobs-2');
const Knob3 = document.getElementById('Knobs-3');
const Knob4 = document.getElementById('Knobs-4');
const Knob5 = document.getElementById('Knobs-5');
const Knob6 = document.getElementById('Knobs-6');
/* Update red values above each knob. */
interpolate_number(Knob1.querySelector('.interpolate'), newValues.knob_1_credit.toFixed(2));
interpolate_number(Knob2.querySelector('.interpolate'), newValues.knob_2_debit.toFixed(2));
interpolate_number(Knob3.querySelector('.interpolate'), newValues.knob_3_typed.toFixed(2));
interpolate_number(Knob4.querySelector('.interpolate'), newValues.knob_4_flat.toFixed(2));
interpolate_number(Knob5.querySelector('.interpolate'), newValues.knob_5_monthly.toFixed(2));
Knob6.querySelector('.Knob-Value').innerHTML = newValues.knob_6_equipment;
/* Update white selection dot on each knob. */
Knob1.querySelector('.Knob-Selection').style.transform = 'rotate('+ (newValues.knob_1_position * 45) +'deg)';
Knob2.querySelector('.Knob-Selection').style.transform = 'rotate('+ (newValues.knob_2_position * 45) +'deg)';
Knob3.querySelector('.Knob-Selection').style.transform = 'rotate('+ (newValues.knob_3_position * 45) +'deg)';
Knob4.querySelector('.Knob-Selection').style.transform = 'rotate('+ (newValues.knob_4_position * 45) +'deg)';
Knob5.querySelector('.Knob-Selection').style.transform = 'rotate('+ (newValues.knob_5_position * 45) +'deg)';
Knob6.querySelector('.Knob-Selection').style.transform = 'rotate('+ (newValues.knob_6_position * 45) +'deg)';
};
function interpolate_number (selector, value) {
// for n/a values
if (value < 0) { selector.textContent = 'N/A '; }
// for all other numerical values
else {
if (selector.textContent === 'N/A ') {
selector.textContent = '0.00';
}
d3.select(selector)
.transition()
.duration(400)
.tween('interpolate_number', function () {
var current =+ this.textContent;
var interpolator = d3.interpolateNumber(current, value);
return function (t) {
this.textContent = interpolator(t).toFixed(2);
};
});
}
}
// $.getJSON('data.js', function (data) {
// states = data;
// Slider.max = states.length - 1;
// updateSliderAndKnobs(states[0]);
// });
Slider.max = states.length - 1;
updateSliderAndKnobs(states[0]);
Slider.oninput = function () {
// console.log('Slider.oninput', Slider.value);
updateSliderAndKnobs(states[Slider.value]);
}
document.onkeydown = function (e) {
if (e.which === 37) {
Slider.stepDown();
Slider.oninput();
}
if (e.which === 39) {
Slider.stepUp();
Slider.oninput();
}
};
document.getElementById('SliderUI-Prev').onclick = function (e) {
Slider.stepDown();
Slider.oninput();
}
document.getElementById('SliderUI-Next').onclick = function (e) {
Slider.stepUp();
Slider.oninput();
}
console.log('%c ███ Hi Kyle! 👋🏼', 'color: #06f');
@import url('https://fonts.googleapis.com/css?family=Cabin|Cormorant+Garamond|Karla');
@import url('https://use.fontawesome.com/releases/v5.5.0/css/all.css');
/* * { box-sizing: border-box; } */
body {
background: #f1f3f5;
color: #081624;
font-family: 'Karla', -apple-system, BlinkMacSystemFont, Roboto, sans-serif, 'Apple Color Emoji';
margin: auto;
overflow-x: hidden;
padding: 20px;
text-align: center;
}
h1,
h2 {
color: #02167b;
font-family: 'Cabin', sans-serif;
letter-spacing: .1em;
text-transform: uppercase;
}
#Slider { display: none; }
#SliderUI {
display: flex;
align-items: center;
justify-content: center;
}
#SliderUI-Prev,
#SliderUI-Next {
background: none;
border: 0;
color: #bcd;
cursor: pointer;
font-size: 30px;
padding: 1rem;
}
#SliderUI-Prev:hover,
#SliderUI-Next:hover { color: #02167b; }
#SliderUI-Gauge {
border: 3px solid #02167b;
position: relative;
height: 100px;
width: 300px;
}
#SliderUI-Headline {
color: #02167b;
font: 700 30px 'Cabin', sans-serif;
line-height: 1;
}
#SliderUI-Needle {
background: #ea2700;
border-radius: 4px 4px 0 0;
bottom: 0;
height: 24px;
left: 0;
position: absolute;
transition: .4s cubic-bezier(.9, 0, 0, 1);
width: 8px;
}
#Knobs {
display: flex;
flex-wrap: wrap;
flex: 1 1 0;
justify-content: space-between;
padding: 1rem 0;
}
.Knobs-Knob {
align-items: center;
/* border-right: 1px solid #bcd; */
display: flex;
flex-direction: column;
/* min-width: 260px; */
}
.Knob-Value {
color: #ea2700;
font-size: 18px;
font-weight: 700;
padding-bottom: 1rem;
}
.Knob {
height: 150px;
position: relative;
transform: rotate(-45deg);
width: 150px;
}
.Knob-Circle {
background: #02167b;
border-radius: 50%;
height: 75%;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 75%;
}
.Knob-Dot {
height: 75%;
left: 12.5%;
position: absolute;
top: 12.5%;
width: 75%;
}
.Knob-Dot > div {
background: #02167b;
border-radius: 50%;
height: 10px;
width: 10px;
}
.Knob-Dot-1 { /* transform: rotate(0deg); */ }
.Knob-Dot-2 { transform: rotate(45deg); }
.Knob-Dot-3 { transform: rotate(90deg); }
.Knob-Dot-4 { transform: rotate(135deg); }
.Knob-Dot-5 { transform: rotate(180deg); }
.Knob-Dot-6 { transform: rotate(225deg); }
.Knob-Selection {
height: 40%;
left: 30%;
position: absolute;
transition: .4s cubic-bezier(.9, 0, 0, 1);
top: 30%;
width: 40%;
}
.Knob-Selection > div {
background: #fff;
border-radius: 50%;
height: 10px;
width: 10px;
}
.Knob-Title {
font-size: 18px;
text-transform: uppercase;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment