Last active
February 5, 2019 23:37
-
-
Save mattborn/48a4320b4c32ee1142120cf3a5f6332f to your computer and use it in GitHub Desktop.
Keen Pricing Tuner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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