markdown FCC 48G计算器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown FCC 48G计算器相关的知识,希望对你有一定的参考价值。
html {
height: 100%;
}
body {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAEUlEQVQImWNgYGD4z4AGMAUANfEC/vDaGN0AAAAASUVORK5CYII=) repeat fixed,
url(https://c2.staticflickr.com/6/5077/5864814103_710f2f5b70_b.jpg)
center center no-repeat fixed;
background-size: auto, cover;
}
.container {
-webkit-perspective: 1000px;
perspective: 1000px;
}
.right {
float: right;
}
.left {
float: left;
}
.hide {
display: none;
}
#overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: hsla(0, 0%, 0%, 0.7);
z-index: 9;
visibility: hidden;
opacity: 0;
-webkit-transition: all 0.75s ease;
transition: all 0.75s ease;
}
#overlay.overlay-show {
visibility: visible;
opacity: 1;
}
#modal {
position: absolute;
top: 40px;
width: 275px;
margin-left: -140px;
left: 50%;
z-index: 10;
opacity: 0;
-webkit-transform: translateY(-30px);
transform: translateY(-30px);
-webkit-transition: all 0.5s ease;
transition: all 0.5s ease;
}
#modal.modal-show {
opacity: 1;
-webkit-transform: translateY(0px);
transform: translateY(0px);
}
.modal-tab {
background-color: hsl(360, 50%, 50%);
border-top-right-radius: 10px;
border-top-left-radius: 10px;
width: 50px;
padding: 5px 5px 0px 5px;
}
.modal-content {
background-color: white;
padding: 5px;
border-width: 5px 2px 2px 2px;
border-style: solid;
border-color: hsl(360, 50%, 50%);
}
.image {
padding: 5px;
width: 95%;
border: 1px solid black;
}
.caption {
font-size: 0.58em;
margin-top: 0;
}
#calculator {
width: 300px;
border: 3px solid black;
outline: 1px solid transparent;
border-radius: 10px;
margin: auto;
overflow: hidden;
-webkit-transform: rotateX(4deg);
transform: rotateX(4deg);
box-shadow: 1px 5px 3px 0px hsla(0, 0%, 0%, 1),
0 0px 2px 2px hsla(0, 0%, 60%, 0.9) inset,
0 0px 0px 8px hsla(0, 0%, 0%, 1) inset;
padding: 8px;
}
#logo {
cursor: pointer;
}
.flash {
-webkit-animation: flash 2s;
animation: flash 2s;
}
@-webkit-keyframes flash {
0% { }
30% {
background-color: hsla(60, 100%, 75%, 0.5);
box-shadow: 0px 0px 20px 5px hsl(60, 100%, 75%);
}
70% {
background-color: hsl(60, 100%, 75%);
box-shadow: 0px 0px 20px 5px hsl(60, 100%, 75%);
}
100% { background-color: none;}
}
@keyframes flash {
0% { }
30% {
background-color: hsla(60, 100%, 75%, 0.5);
box-shadow: 0px 0px 20px 5px hsl(60, 100%, 75%);
}
70% {
background-color: hsl(60, 100%, 75%);
box-shadow: 0px 0px 20px 5px hsl(60, 100%, 75%);
}
100% { background-color: none;}
}
/* */
/* Screen Area */
/* */
#screen-container {
background-color: hsl(200, 5%, 40%);
position:relative;
z-index: 1;
height: 200px;
padding: 40px 20px 20px;
box-shadow: 0 2px 2px 2px hsla(0, 0%, 0%, 0.7),
0 0px 2px 2px hsla(0, 0%, 0%, 0.7) inset;
}
#top-header {
position: absolute;
top: 5px;
left: 20px;
height: 25px;
width: 260px;
vertical-align: middle;
background-color: hsl(200, 5%, 40%);
color: hsl(140, 0%, 90%);
z-index: 2;
}
.large {
font-size: 1.5em;
}
.small-fa {
font-size: 0.8em;
}
.middle {
vertical-align: middle;
}
.blue {
color: hsl(180, 100%, 40%);
}
.nudge-fa {
top: 3px !important;
left: -4px !important;
}
#screen {
position: relative;
font-family: 'Play', sans-serif;
font-size: 14px;
background-color: hsla(40, 25%, 50%, 1);
height: 100%;
width: 100%;
}
#screen::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAGElEQVQImWNggIIFXfFpDCicBV3xaTAMAH0OCaz5r9XrAAAAAElFTkSuQmCC) repeat;
box-shadow: 0 -1px 3px 2px hsla(0, 50%, 0%, 0.8),
0 -1px 3px 2px black inset;
pointer-events: none;
}
.screen-header-container {
padding: 5px 3px 3px 3px;
}
.screen-header {
padding: 0 5px;
}
.screen-header-row div {
display: inline-block;
}
.screen-header-container hr {
border-color: hsl(130, 15%, 10%);
margin: 0;
}
.screen-main-display-container {
position: absolute;
bottom: 30px;
}
.screen-main-display {
height: 145px;
width: 600px;
display: table-cell;
vertical-align: bottom;
padding: 0 10px;
font-size: 22px;
}
.line {
text-align: right;
clear: both;
}
.line-content {
width: 100%;
}
.input-line {
text-align: left;
}
.cursor {
//font-size: 0.8em;
-webkit-animation: blinker 1000ms linear infinite;
animation: blinker 1000ms linear infinite;
}
@-webkit-keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}
@keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}
.screen-menus {
position: absolute;
bottom: 3px;
left: 5px;
}
.menu {
display: inline-block;
vertical-align: top;
position: relative;
width: 35px;
height: 15px;
margin-bottom: 2px;
text-align: center;
padding: 2px 2px;
color: hsla(40, 25%, 50%, 1);
background-color: hsl(130, 15%, 10%);
}
.menu-folder::before {
content: '';
position: absolute;
top: -3px;
left: 1px;
height: 3px;
width: 10px;
background-color: hsl(130, 35%, 10%);
}
/* */
/* Keypad Area */
/* */
#keys {
background-color: hsl(200, 5%, 30%);
text-align: center;
position: relative;
padding-bottom: 15px;
}
#keys:after {
content:'';
position: absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:1;
box-shadow: 1px 1px 2px 4px hsla(0, 0%, 0%, 0.8) inset;
pointer-events: none;
}
.key-button {
display: table;
background-color: hsl(200, 5%, 20%);
color: #fff;
border: 1px solid hsl(200, 5%, 5%);
border-radius: 5px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
box-shadow: 0px 2px black,
2px 2px 2px 1px hsla(0, 50%, 0%, 0.8),
-1px -1px 1px 0px hsla(0, 50%, 0%, 0.4) inset,
0px 0px 4px 1px hsla(200, 5%, 10%, 0.8) inset,
0px 0px 0px 3px hsl(200, 5%, 20%) inset;
-webkit-transition: hover 100ms ease-out;
transition: hover 100ms ease-out;
cursor: pointer;
}
.key-button:active {
-webkit-transform: translateX(2px);
transform: translateX(2px);
box-shadow: 0px 2px black,
-1px -1px 1px 0px hsla(0, 50%, 0%, 0.4) inset,
0px 0px 4px 1px hsla(200, 5%, 10%, 0.8) inset,
0px 0px 0px 3px hsl(200, 5%, 20%) inset;
}
.key-text {
width: 100%;
height: 100%;
display: table-cell;
vertical-align: middle;
pointer-events: none;
}
/* */
/* Small Keys */
/* */
.key-small-container {
position: relative;
display: inline-block;
margin: -2px;
width: 49px;
height: 45px;
vertical-align: bottom;
}
.key-small-button {
position: absolute;
bottom: 5px;
left: 50%;
width: 36px;
height: 20px;
margin-left: -19px;
font-size: 0.8em;
}
.key-enter-container {
width: 98px;
}
.key-enter-button {
width: 87px;
left: 25%;
}
/* */
/* Large Keys */
/* */
.key-large-container {
position: relative;
display: inline-block;
margin: 4px -1px -1px -1px;
width: 55px;
height: 51px;
vertical-align: bottom;
}
.key-large-button {
position: absolute;
bottom: 5px;
left: 50%;
width: 44px;
height: 28px;
margin-left: -24px;
//border: 1px solid black;
}
.key-bg-light {
background-color: hsl(200, 5%, 40%);
}
/* */
/* Alt Keys */
/* */
.key-alt {
font-size: 0.7em;
margin-top: 4px;
text-transform: uppercase;
font-weight: bold;
white-space: nowrap;
}
.key-alt-1 {
background-color: hsl(300, 40%, 50%);
color: hsl(200, 5%, 20%);
}
.key-alt-2 {
background-color: hsl(125, 40%, 50%);
color: hsl(200, 5%, 20%);
}
.key-alt-text-1 {
color: hsl(300, 40%, 50%);
}
.key-alt-text-2 {
color: hsl(125, 40%, 50%);
padding-left: 2px;
}
.math {
text-transform: none;
}
sup {
vertical-align: top;
position: relative;
top: -0.3em;
}
/* */
/* Option Keys */
/* */
#key-option-row {
position: relative;
padding-top: 15px;
padding-bottom: 10px;
background-color: hsl(200, 5%, 40%);
box-shadow: 0 -1px 3px 0px hsla(0, 50%, 0%, 0.8),
0 -1px 3px 0px black inset;
}
.key-option-container {
position: relative;
display: inline-block;
margin: -2px;
width: 49px;
height: 15px;
}
.key-option-button {
position: absolute;
bottom: 0px;
left: 50%;
width: 32px;
height: 15px;
margin-left: -19px;
background-color: white;
}
/* Cancel Key */
#cancel {
position: absolute;
bottom: -14px;
width: 100%;
color: white;
font-size: 12px;
}
#attribution-container {
position: absolute;
top: 700px;
bottom: 0px;
right: 0px;
min-height: 100px;
width: 300px;
}
.attribution {
position: absolute;
right: 10px;
bottom: 10px;
margin-top: 20px;
padding: 5px;
background-color: hsla(360, 0%, 0%, 0.4);
color: #fff;
font-size: 0.8em;
}
.attribution a {
color: #fff;
text-decoration: none;
}
(function(document, window) {
var $display = document.querySelector('.screen-main-display-container'),
$headerRow1 = document.querySelector('#header-row1 .screen-header-content'),
$headerRow1Right = document.querySelector('#header-row1 .screen-header-right'),
$headerRow2 = document.querySelector('#header-row2 .screen-header-content'),
$headerRow2Right = document.querySelector('#header-row2 .screen-header-right'),
$keyAlt1Text = document.querySelectorAll('.key-alt-text-1'),
$keyAlt2Text = document.querySelectorAll('.key-alt-text-2'),
$keyButtons = document.querySelectorAll('.key-button'),
$keyText = document.querySelectorAll('.key-text'),
$logo = document.querySelector('#logo'),
$modal = document.querySelector('#modal'),
$modalClose = document.querySelector('#modal-close'),
$overlay = document.querySelector('#overlay'),
altBtnState = '',
cancelKey = 'k38',
cursorPosition = 0,
defaultLineNums = ["1:", "2:", "3:", "4:", "5:"],
inputLine = false,
inputMode = 'dec',
keyboardKeyMap,
keyMap,
maxDispDigits = 9,
maxLineChars = 18,
menu,
menuSlots = 6, // number of menu spaces on screen
mode = 'deg',
reDec = new RegExp(/^([\-\+]?)([\d]*)(\.?)([\d]*)([Ee][\-\+]?[\d]+)?$/),
screenStack = {
lineNumbers: defaultLineNums.slice(),
lineContents: []
};
keyboardKeyMap = {
// number pad 0-9 and '.'
'96': 'k39',
'97': 'k34',
'98': 'k35',
'99': 'k36',
'100': 'k29',
'101': 'k30',
'102': 'k31',
'103': 'k24',
'104': 'k25',
'105': 'k26',
'110': 'k40',
// number keys 0-9 and '.'
'48': 'k39',
'49': 'k34',
'50': 'k35',
'51': 'k36',
'52': 'k29',
'53': 'k30',
'54': 'k31',
'55': 'k24',
'56': 'k25',
'57': 'k26',
'190': 'k40',
'13': 'k18', // etner key
'107': 'k42', // '+' key
'109': 'k37', // '-' key
'106': 'k32', // '*' key
'111': 'k27', // '/' key
'69': 'k41', // 'e' key
'8': 'k22', // backspace key
'46': 'k21', // delete key
'37': 'k15', // ArrowLeft key
'39': 'k17', // ArrowRight key
'38': 'k10', // ArrowUp key
'40': 'k16', // ArrowDown key
'27': 'k38'// Escape key
};
function forEachNode(NodeList, callback, scope) {
for(var i = 0; i < NodeList.length; i++) {
callback.call(scope, NodeList[i], i);
}
}
/**
*
*Initialization and Setup Functions
*
*/
//setKeys function maps text onto appropriate key.
function setKeys() {
//set text for each key
forEachNode($keyText, function(node, ind) {
node.innerHTML = keyMap["k" + ind].main.text || "~k" + ind + "~";
});
//set alt1 text for each key
forEachNode($keyAlt1Text, function(node, ind) {
var offset = ind + 6; //compensate for 6 top keys w/o alt text
node.innerHTML = keyMap["k" + offset].alt1.text;
});
//set alt2 text for each key
forEachNode($keyAlt2Text, function(node, ind) {
var offset = ind + 6; //compensate for 6 top keys w/o alt text
node.innerHTML = keyMap["k" + offset].alt2.text;
});
//set Cancel key (overrides key's native main func)
//should be bottom row key or text will interfere
var CancelKeyNode = document.createElement("div");
CancelKeyNode.id = "cancel"
CancelKeyNode.innerHTML = "Cancel"
document.getElementById(cancelKey).parentElement.appendChild(CancelKeyNode);
keyMap[cancelKey].main.func = clearInputLine;
}
// set the keyMap object. This is in a function so that other objects
// which may be needed can be instantiated first.
function setKeyMap() {
keyMap = {
"k0": {
"main": {
"text": " ",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k1": {
"main": {
"text": " ",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k2": {
"main": {
"text": " ",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k3": {
"main": {
"text": " ",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k4": {
"main": {
"text": " ",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k5": {
"main": {
"text": " ",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k6": {
"main": {
"text": "Main",
"arg": "main",
"func": menu.goToMenu
},
"alt1": {
"text": "A",
"arg": "A",
"func": numClick
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k7": {
"main": {
"text": "sin",
"arg": [1, sin],
"func": stackOperation
},
"alt1": {
"text": "B",
"arg": "B",
"func": numClick
},
"alt2": {
"text": "asin",
"arg": [1, asin],
"func": stackOperation
}
},
"k8": {
"main": {
"text": "cos",
"arg": [1, cos],
"func": stackOperation
},
"alt1": {
"text": "C",
"arg": "C",
"func": numClick
},
"alt2": {
"text": "acos",
"arg": [1, acos],
"func": stackOperation
}
},
"k9": {
"main": {
"text": "tan",
"arg": [1, tan],
"func": stackOperation
},
"alt1": {
"text": "D",
"arg": "D",
"func": numClick
},
"alt2": {
"text": "atan",
"arg": [1, atan],
"func": stackOperation
}
},
"k10": {
"main": {
"text": "<i class='fa fa-chevron-up'></i>",
"arg": "",
"func": ""
},
"alt1": {
"text": "E",
"arg": "E",
"func": numClick
},
"alt2": {
"text": "Up",
"arg": "",
"func": menu.goToPrevMenu
}
},
"k11": {
"main": {
"text": "Next",
"arg": "",
"func": nextMenu
},
"alt1": {
"text": "F",
"arg": "F",
"func": numClick
},
"alt2": {
"text": "Prev",
"arg": "",
"func": ""
}
},
"k12": {
"main": {
"text": "√x",
"arg": [1, squareRoot],
"func": stackOperation
},
"alt1": {
"text": "<span class='math'>x<sup>2</sup></span>",
"arg": [1, squared],
"func": stackOperation
},
"alt2": {
"text": "<span class='math'><sup>x</sup>√y</span>",
"arg": [2, xthRoot],
"func": stackOperation
}
},
"k13": {
"main": {
"text": "y<sup>x</sup>",
"arg": [2, xthPower],
"func": stackOperation
},
"alt1": {
"text": "<span class='math'>10<sup>x</sup></span>",
"arg": [1, tenPow],
"func": stackOperation
},
"alt2": {
"text": "log",
"arg": [1, log10],
"func": stackOperation
}
},
"k14": {
"main": {
"text": "1/x",
"arg": [1, inverse],
"func": stackOperation
},
"alt1": {
"text": "<span class='math'>e<sup>x</sup></span>",
"arg": [1, exp],
"func": stackOperation
},
"alt2": {
"text": "ln",
"arg": [1, ln10],
"func": stackOperation
}
},
"k15": {
"main": {
"text": "<i class='fa fa-chevron-left'></i>",
"arg": "",
"func": cursorLeft
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k16": {
"main": {
"text": "<i class='fa fa-chevron-down'></i>",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k17": {
"main": {
"text": "<i class='fa fa-chevron-right'></i>",
"arg": "",
"func": cursorRight
},
"alt1": {
"text": "Swap",
"arg": "",
"func": swapLines
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k18": {
"main": {
"text": "ENTER",
"arg": "",
"func": enterKey
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k19": {
"main": {
"text": "π",
"arg": "",
"func": piKey
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k20": {
"main": {
"text": "mod",
"arg": [2, modulo],
"func": stackOperation
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k21": {
"main": {
"text": "DEL",
"arg": "",
"func": clearStack
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k22": {
"main": {
"text": "<i class='fa fa-arrow-left'></i>",
"arg": "",
"func": delKey
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k23": {
"main": {
"text": "+/-",
"arg": "",
"func": toggleSign
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k24": {
"main": {
"text": "7",
"arg": 7,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k25": {
"main": {
"text": "8",
"arg": 8,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k26": {
"main": {
"text": "9",
"arg": 9,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k27": {
"main": {
"text": "/",
"arg": [2, divide],
"func": stackOperation
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k28": {
"main": {
"text": "<i class='fa fa-reply'></i>",
"arg": "alt1",
"func": altBtn
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k29": {
"main": {
"text": "4",
"arg": 4,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k30": {
"main": {
"text": "5",
"arg": 5,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k31": {
"main": {
"text": "6",
"arg": 6,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k32": {
"main": {
"text": "*",
"arg": [2, multiply],
"func": stackOperation
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k33": {
"main": {
"text": "<i class='fa fa-share'></i>",
"arg": "alt2",
"func": altBtn
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k34": {
"main": {
"text": "1",
"arg": 1,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k35": {
"main": {
"text": "2",
"arg": 2,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k36": {
"main": {
"text": "3",
"arg": 3,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k37": {
"main": {
"text": "-",
"arg": [2, subtract],
"func": stackOperation
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k38": {
"main": {
"text": "ON",
"arg": "",
"func": ""
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k39": {
"main": {
"text": "0",
"arg": 0,
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k40": {
"main": {
"text": ".",
"arg": ".",
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k41": {
"main": {
"text": "EE",
"arg": "E",
"func": numClick
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
},
"k42": {
"main": {
"text": "+",
"arg": [2,add],
"func": stackOperation
},
"alt1": {
"text": "",
"arg": "",
"func": ""
},
"alt2": {
"text": "",
"arg": "",
"func": ""
}
}
};
}
/**
*
*Screen Functions
*
*/
// function returns a copy of the input line with cursor at given position
function insertCurosr(position) {
var newLine;
//verify we're on input line
if(inputLine === true) {
//check if input line is array of characters
if(Array.isArray(screenStack.lineContents[0])) {
//grab a copy of the input array
newLine = screenStack.lineContents[0].slice();
} else { //a string is displayed there, so make it an array.
newLine = screenStack.lineContents[0].split("");
}
//splice in the cursor at the given position
newLine.splice(position, 0, '<span class="cursor">|</span>');
}
return newLine;
}
// function to handle excessive characters on a line.
function formatLine(contents) {
var formattedLine,
numExcessChars = contents.length - maxLineChars,
type = typeof contents,
startIndex = numExcessChars < 0 ? 0 : numExcessChars;
if(numExcessChars > 0) {
if(Array.isArray(contents)) {
formattedLine = contents.slice();
} else if(type === 'string') {
formattedLine = contents.split("");
}
if(cursorPosition > startIndex){
formattedLine.splice(0, contents.length - maxLineChars, "...");
} else if(cursorPosition <= startIndex && cursorPosition > 1) {
formattedLine = formattedLine.splice(cursorPosition, maxLineChars - 2);
formattedLine.unshift("...");
formattedLine.push("...");
} else {
formattedLine = formattedLine.splice(0, maxLineChars - 2);
formattedLine.push("...");
}
if(type === 'string') {
formattedLine.join("");
}
}
return formattedLine || contents;
}
// Format numbers to fit maxDispDigits
function screenNumberFormat(num) {
var numLen,
whole,
wholeLen;
// validate input is number, if not attempt conversion.
if(num === undefined || isNaN(num)) { // if num is undefined should dispaly empty string
return "";
} else if(typeof num === 'string') {
num = parseFloat(num);
} else if(Array.isArray(num)) {
num = parseFloat(num.join(""));
}
// number of chracters in num
numLen = num.toString().length;
whole = Math.floor(num);
wholeLen = whole.toString().length;
if(numLen > maxDispDigits) { //num is too large
// whole number protion is too long then put in exponential form
if(wholeLen > maxDispDigits ) {
return num.toExponential(maxDispDigits);
} else { // decimals take up too much room so display in fixed form
return num.toFixed(maxDispDigits - wholeLen);
}
}
return num;
}
// draw the screen
function refreshScreen() {
var nodeText = ['<div class="screen-main-display">'],
j = 1,
lineNum,
content;
// create html for each line
for (var i = 4; i >= 0; i--) {
lineNum = screenStack.lineNumbers[i];
// check for input line and also verify that this is index 0
// any other index would be anomalous
if(inputLine === true && i === 0) {
// insert the cursor and join the input array to be dispalyed as string
content = formatLine(insertCurosr(cursorPosition)).join("");
// opening line div tag needs 'input-line' class
nodeText[j++] = '<div id="line' + i + '" class="line input-line">';
} else {
//grabe content from the screenStack object.
content = screenNumberFormat(screenStack.lineContents[i]);
// generic opeing line div tag.
nodeText[j++] = '<div id="line' + i + '" class="line">';
}
nodeText[j++] = '<div class="line-number left">';
nodeText[j++] = lineNum;
nodeText[j++] = '</div>';
nodeText[j++] = '<div class="line-content">';
nodeText[j++] = content;
nodeText[j++] = '</div>';
nodeText[j++] = '</div>';
}
//close screen-main-dispaly div
nodeText[j++] = '</div>';
//replace display with newly created html
$display.innerHTML = nodeText.join("");
}
//Create a new input line
function openInputLine(char) {
inputLine = true;
cursorPosition++;
//new line is added to front of screenStack
screenStack.lineNumbers.unshift(""); //has no line number
screenStack.lineContents.unshift([char.toString()]);
refreshScreen();
}
//Add characters to the input line text
function concatInputChar(char) {
screenStack.lineContents[0].splice(cursorPosition, 0, char.toString());
cursorPosition++;
refreshScreen();
}
//Remove characters from the input line
function delInputChar() {
if(cursorPosition > 0) {
cursorPosition--;
screenStack.lineContents[0].splice(cursorPosition, 1);
}
}
//Remove the inputLine and return what was there as a float
function clearInputLine() {
var input = [];
//only clear first screenStack entries if current line is
//an input line.
if(screenStack.lineNumbers[0] === "") {
input = screenStack.lineContents[0];
screenStack.lineNumbers.shift();
screenStack.lineContents.shift();
inputLine = false;
cursorPosition = 0; // reset cursor position
refreshScreen();
}
return parseFloat(input.join(""));
}
// function returns the content of a given line number.
// line number corresponds to line number on screen.
// If present, 0 represents input line
function getLineContents(lineNum) {
var contents;
//if input line is present, screenStack.lineContents is indexed correctly
if(inputLine === true) {
contents = screenStack.lineContents[lineNum];
} else { //if no inptul line, screen line 1 lies at index 0;
contents = screenStack.lineContents[lineNum - 1] || "";
}
return contents;
}
function getLineString(lineNum) {
var str = getLineContents(lineNum);
return Array.isArray(str) ? str.join("") : str;
}
// function clears number of lines specified starting from the bottom of
// the stack. This occurs irrespective of input line
function clearLines(num) {
// defalut to 1 if none specified.
num = num || 1;
// delete line conents and numbers for number of lines specified.
for(var i = 0; i < num; i++) {
screenStack.lineNumbers.shift();
screenStack.lineContents.shift();
}
//maintain minimum of default line numbers
if(screenStack.lineNumbers.length < defaultLineNums.length) {
screenStack.lineNumbers = defaultLineNums.slice();
}
// in case was input line, set inputLine to false and reset cursor position
inputLine = false;
cursorPosition = 0;
}
function addLineToStack(val) {
var lineNum;
if(!isNaN(val)) {
//the next line number value
lineNum = screenStack.lineNumbers.length + 1;
//prepend val to the screenStack.lineContents array
screenStack.lineContents.unshift(val);
//if another line number is needed, add it to the line numbers.
if(screenStack.lineContents.length > screenStack.lineNumbers.length) {
screenStack.lineNumbers.push(lineNum.toString(10) + ":");
}
}
}
//Place content at a specific line.
//0 is input line (which may not be visible)
//If no input line is present, one will be created
function placeAtLine(lineNum, val) {
if(lineNum > 0) {
screenStack.lineContents.splice(lineNum - 1 , 0, val);
} else {
}
}
/**
*
* Menu Functionality
*
*/
menu = (function() {
var $keyOptionButtons = document.querySelectorAll('.key-option-button'),
$menus = document.querySelectorAll('.menu'),
slots = menuSlots,
menuLength,
mainMenu = 'main',
menuState = [],
page = 0,
screenMenus = {
main: {
mode: {
deg: degKey,
rad: radKey,
'd->r': degToRad,
'r->d': radToDeg
}
}
};
// Draws appropriate menu text and menu button style
function drawMenu(menuObj) {
// get keys for menuObj. These are the menu block labels
var keys = Object.keys(menuObj);
// iterate through the menu divs
forEachNode($menus, function(node, ind) {
var key = keys[ind + (page * slots)];
// if there's something to add to the menus
if(key) {
// set the menu html to the key text for each menu
node.innerHTML = key;
// check if this key's property is an object. If so, this is a menu
// otherwise it is an action button.
if(typeof menuObj[key] === 'object') {
node.classList.add('menu-folder');
} else {
node.classList.remove('menu-folder');
}
} else { // else ensure the menu space is empty
node.innerHTML = '';
}
});
menuLength = keys.length;
}
function getCurrMenuObj() {
return menuState.reduce(function(prev, curr) {
return prev[curr];
}, screenMenus);
}
function nextMenu() {
if(menuLength > slots) {
page = ++page % ((menuLength % slots) + 1);
drawMenu(getCurrMenuObj());
}
}
// navigate to top level menu
function goToMenu(name) {
menuState = [name];
$headerRow2.innerHTML = menuState.join(' -> ');
drawMenu(getCurrMenuObj());
}
// Draws submenu by name relative to the current menu object
function goToSubMenu(name) {
menuState.push(name);
$headerRow2.innerHTML = menuState.join(' -> ');
drawMenu(getCurrMenuObj());
}
function goToPrevMenu() {
if(menuState.length > 1){
menuState.pop();
$headerRow2.innerHTML = menuState.join(' -> ');
drawMenu(getCurrMenuObj());
}
}
// handle clicks to option buttons
forEachNode($keyOptionButtons, function(node, ind) {
node.addEventListener('click', function() {
var name = $menus[ind].textContent,
currMenu = getCurrMenuObj();
if(typeof currMenu[name] === 'object') { // if button is submenu
goToSubMenu(name); // the go to subment
} else if (typeof currMenu[name] === 'function') {
currMenu[name](); // if button is an action/function, run it.
}
});
})
// initialize the menus
function init() {
goToMenu(mainMenu);
}
// return the menu object for public reference
return {
init: init,
nextMenu: nextMenu,
subMenu: goToSubMenu,
goToMenu: goToMenu,
goToPrevMenu: goToPrevMenu
};
})();
/**
*
* Number Handling
*
*/
// returns the number of digits to the right of the decimal.
function decimalPlaces(num) {
var decDigits,
sciDigits,
match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match) {
return 0;
}
// digits to right of the decimal
decDigits = match[1] ? match[1].length : 0;
// decimal places due to scientific notation
sciDigits = match[2] ? +match[2] : 0;
return Math.max(0, decDigits - sciDigits);
}
// return max decimal places from number arbitrary number of numbers
function maxDecimalPlaces() {
var numArr = Array.prototype.slice.call(arguments);
return numArr.reduce(function(max, curr) {
return decimalPlaces(curr) > max ? decimalPlaces(curr) : max;
}, 0);
}
function scaleVal() {
var args = Array.prototype.slice.call(arguments),
places = maxDecimalPlaces.apply(this, args);
return Math.pow(10, places);
}
/**
*Calculation/Operation functions
*These are assigned to keys in the keyMap object
*
*/
//
//Basic Calculator functionality
//
//handle any character that needs to be added to input line
function numClick(char) {
//check that we have an input line (a line with no line number)
//otherwise assume input and concat to what's there
if (screenStack.lineNumbers[0] !== "") {
openInputLine(char);
} else {
concatInputChar(char);
}
}
// toggles a +/- at the given index of an array.
function toggleSignAt(arr, ind) {
if(arr[ind] === '+') { //if + make it -
arr[ind] = '-';
} else if(arr[ind] === '-') { //if - make it +
arr[ind] = '+';
} else { //else number is implied positive, make it -
arr.splice(ind, 0, '-');
cursorPosition++;
}
}
// Take content and return a string with toggled sign for the number portion
function changeNumberSign(lineContent) {
var isArray = Array.isArray(lineContent);
if(isArray) { // lineContent will be array on input line
toggleSignAt(lineContent, 0);
} else {
// other lines contain number, so invert sign
lineContent *= -1;
}
return lineContent;
}
// return the index of 'E' for a given line number.
function indexOfE(lineNum) {
var num,
type;
if(!inputLine) {
lineNum = lineNum - 1;
}
// get info at lineNum
num = screenStack.lineContents[lineNum];
type = typeof num;
// Find the index of E
if(Array.isArray(num)) { // if it's an array, join it
return num.join('').indexOf('E');
} else if(type === 'Number'){ // if it's a number, toString it.
return screenStack.lineContents[lineNum].toString().indexOf('E');
} else if (type === "String") { // if it's a string, then just find index
return screenStack.lineContents[lineNum].indexOf('E');
}
}
// toggles the sign of the scientific notation exponent.
function changeSciSign(lineContent, idxOfE) {
var isArray = Array.isArray(lineContent);
if(!isArray) { // line content won't be array for non-input lines
lineContent.split("");
}
toggleSignAt(lineContent, idxOfE + 1);
return isArray ? lineContent : lineContent.join("");
}
//toggle sign of active line
function toggleSign() {
var lineNum = inputLine ? 0 : 1,
currLineContents = getLineContents(lineNum),
idxOfE;
// get index of 'E' in case of sci notation.
idxOfE = indexOfE(lineNum);
// if cursor is in exponential portion, toggle sign there.
if(idxOfE > -1 && cursorPosition > idxOfE) {
changeSciSign(currLineContents, idxOfE);
} else { // replace first line of screen with signed version
screenStack.lineContents[0] = changeNumberSign(currLineContents);
}
refreshScreen();
}
//validate the syntax of string number for a give mode.
// mode: 'dec', 'bin', 'hex'
function validateSyntax(str, mode) {
switch(mode) {
case 'dec':
return reDec.test(str);
}
}
function enterKey() {
var val = "";
if(inputLine === true) {
val = getLineString(0);
if(validateSyntax(val, inputMode)) {
addLineToStack(clearInputLine());
} else {
displaySyntaxErr();
}
} else {
val = screenStack.lineContents[0];
placeAtLine(1, val);
}
refreshScreen();
}
//Clear the screen stack and reset the line numbers
function clearStack() {
//enforce clearing of stack only when input line not present.
if(inputLine === false) {
screenStack.lineContents = [];
screenStack.lineNumbers = defaultLineNums.slice();
refreshScreen();
}
}
// display syntax error message in the header.
function displaySyntaxErr() {
$headerRow1Right.innerHTML = "SYNTAX ERROR";
}
function clearSyntaxErr() {
$headerRow1Right.innerHTML = "";
}
// checks the elements of an array and returns false if any are
// the falsy values used.
function checkForArgs(arr) {
return !(arr.some(function(arg) {
if(arg === undefined || arg === '' || isNaN(arg) || arg === null) {
return true;
}
}));
}
// function returs an array of 'num' arguments from the stack in decending
// order, irrespecitve of the precesnce of the input Line.
function getFirstLines(num) {
var arr = [],
firstLine = 1; // starting line
if(inputLine === true) {
firstLine = 0; // if on inputline, start with line 0
num = num - 1; // adjust num to compensate from starting at zero
}
for(var i = firstLine; i <= num; i++ ) {
if(i === 0) {
arr.push(parseFloat(getLineString(0))); // handle input line
} else {
arr.push(getLineContents(i));
}
}
// check for valid arguments.
if(checkForArgs(arr)) {
// return reveresed array so arguemnts are in decending stack order.
return arr.reverse();
} else {
displaySyntaxErr();
return false;
}
}
// clears the number of lines specfied, runs the callback function
// on the arguments from those lines, then places the result on the screen.
function stackOperation(numLinesInOperation, callback) {
var argsArray = getFirstLines(numLinesInOperation);
if(argsArray) {
clearLines(numLinesInOperation);
addLineToStack(callback.apply(this, argsArray));
}
refreshScreen();
}
function add(x, y) {
var scaleFactor = scaleVal(x,y);
return ( x * scaleFactor + y * scaleFactor ) / scaleFactor;
}
function subtract(x, y) {
var scaleFactor = scaleVal(x,y);
return ( x * scaleFactor - y * scaleFactor ) / scaleFactor;
}
function multiply(x, y) {
return x * y;
}
function divide(x, y) {
return x / y;
}
function modulo(x, y) {
return x % y;
}
//
// Power/Exponential functionality
//
function inverse(x) {
return 1/x;
}
function squareRoot(x) {
return Math.sqrt(x);
}
function xthRoot(x, y) {
// handle negative numbers with odd roots
if(x < 0 && y % 2 === 1) {
return -Math.pow(-x, 1/y);
} else {
return Math.pow(x, 1/y);
}
}
function squared(x) {
return x * x;
}
function xthPower(x, y) {
return Math.pow(x,y);
}
function tenPow(x) {
return Math.pow(10, x);
}
function log10(x) {
return Math.log10(x);
}
function ln10(x) {
return Math.log(x);
}
function exp(x) {
return Math.exp(x);
}
//
// Trig functionality
//
function changeMode(angleMode) {
if(mode === angleMode) {
return;
}
mode = angleMode;
if(mode === 'rad') {
$headerRow1.innerHTML = 'rad';
} else {
$headerRow1.innerHTML = '';
}
}
function degKey() {
changeMode('deg');
}
function radKey() {
changeMode('rad');
}
function convertToRad(deg) {
return deg * (Math.PI / 180);
}
function convertToDeg(rad) {
return rad * (180 / Math.PI);
}
function degToRad() {
stackOperation(1, convertToRad);
}
function radToDeg() {
stackOperation(1, convertToDeg);
}
function sin(num) {
if(mode === 'deg') {
return Math.sin(convertToRad(num));
} else if(mode === 'rad') {
return Math.sin(num);
}
}
function cos(num) {
if(mode === 'deg') {
return Math.cos(convertToRad(num));
} else if(mode === 'rad') {
return Math.cos(num);
}
}
function tan(num) {
if(mode === 'deg') {
return Math.tan(convertToRad(num));
} else if(mode === 'rad') {
return Math.tan(num);
}
}
function asin(num) {
if(mode === 'deg') {
return convertToDeg(Math.asin(num));
} else if(mode === 'rad') {
return Math.asin(num);
}
}
function acos(num) {
if(mode === 'deg') {
return convertToDeg(Math.acos(num));
} else if(mode === 'rad') {
return Math.acos(num);
}
}
function atan(num) {
if(mode === 'deg') {
return convertToDeg(Math.atan(num));
} else if(mode === 'rad') {
return Math.atan(num);
}
}
//
// misc math buttons
//
function piKey() {
addLineToStack(Math.PI);
refreshScreen();
}
//
// Non-math related buttons
//
function delKey() {
if(inputLine) {
delInputChar();
} else {
clearLines(1);
}
refreshScreen();
}
function cursorLeft() {
if(cursorPosition > 0 && inputLine === true) {
cursorPosition--;
refreshScreen();
}
}
function cursorRight() {
if(cursorPosition < screenStack.lineContents[0].length &&
inputLine === true) {
cursorPosition++;
refreshScreen();
}
}
function setAltBtnState(type) {
var btnText = {
alt1: "<i class='fa fa-reply'></i>",
alt2: "<i class='fa fa-share'></i>"
};
altBtnState = type;
if(type !== '') {
$headerRow2Right.innerHTML = btnText[type];
} else {
$headerRow2Right.innerHTML ='';
}
}
function altBtn(name) {
if(altBtnState === name) {
setAltBtnState('');
} else {
setAltBtnState(name);
}
}
function nextMenu() {
menu.nextMenu();
}
function swapLines() {
var a, b;
if(inputLine) {
a = getLineContents(1);
b = getLineContents(0);
screenStack.lineContents[1] = b.join("");
screenStack.lineContents[0] = a.toString().split("");
cursorPosition = screenStack.lineContents[0].length;
} else {
a = getLineContents(2);
b = getLineContents(1);
screenStack.lineContents[1] = b;
screenStack.lineContents[0] = a;
}
refreshScreen();
}
/**
*
*Event bindings
*
*/
// calls the callback function with the given arguments which may be
// a single argument or an array of arguments.
function callWithArgs(callback, args) {
if(typeof callback === 'function') {
if(Array.isArray(args)) {
callback.apply(this, args);
} else {
callback(args);
}
}
}
function keyButtonsClick() {
var key = this.id,
func,
arg;
// clear any operation syntax error on screeen.
clearSyntaxErr();
switch(altBtnState) {
case 'alt1':
func = keyMap[key].alt1.func;
arg = keyMap[key].alt1.arg;
setAltBtnState('');
break;
case 'alt2':
func = keyMap[key].alt2.func;
arg = keyMap[key].alt2.arg;
setAltBtnState('');
break;
default:
func = keyMap[key].main.func;
arg = keyMap[key].main.arg;
break;
}
// run calc key function
callWithArgs(func, arg);
}
forEachNode($keyButtons, function(node, ind){
node.addEventListener('click', keyButtonsClick)
})
// physical keyboard button bindings
document.querySelector('body').addEventListener('keydown', function(e){
var keyPressed,
calcKey,
func,
arg;
// get key pressed. Attempt cross browser compatability.
keyPressed = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
// check that key is used
if(keyboardKeyMap[keyPressed]) {
e.preventDefault();
// clear any operation syntax error on screeen.
clearSyntaxErr();
calcKey = keyboardKeyMap[keyPressed]; // get corresponding calc key
func = keyMap[calcKey].main.func; // get calc key function
arg = keyMap[calcKey].main.arg; // get calc key value
// run calc key function
callWithArgs(func, arg);
}
});
// show modal and overaly on logo click
$logo.addEventListener('click', function() {
$overlay.classList.add('overlay-show');
$modal.classList.add('modal-show');
});
// hide modal and overylay on model close x click.
$modalClose.addEventListener('click', function() {
$overlay.classList.remove('overlay-show');
$modal.classList.remove('modal-show');
});
// highlight the logo to call attention to modal.
function logoFlash(delay) {
setTimeout(function() {
$logo.classList.add('flash');
}, delay);
}
/**
*
*Lets' Go!: Initialize the calculator
*
*/
(function initialize() {
menu.init(); // initialize the menu first so that methods are available.
setKeyMap();
setKeys();
refreshScreen();
logoFlash(1000);
})();
})(document, window);
<body>
<div id="overlay">
<div id="modal">
<div class="modal-tab">
Info <i id='modal-close' class="fa fa-close"></i>
</div>
<div class="modal-content">
<p>This calculator was inspired by my handy <a href="https://en.wikipedia.org/wiki/HP_48_series" target="_blank">HP 48G</a> calculator. My high school Calculus teacher required every student to use this calculator (and even sold them to us). I quickly fell in love with it and relished the reverse polish notation (RPN). It took many years to unlearn RPN so that I could use a regular, non RPN, calculator again without operation errors.</p>
<a title="By No machine-readable author provided. Heretiq assumed (based on copyright claims). [CC BY-SA 2.5 (http://creativecommons.org/licenses/by-sa/2.5)], via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File%3AHP48G.jpg" target="_blank">
<img class="image" width="256" alt="HP48G" src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/HP48G.jpg/256px-HP48G.jpg"/>
</a>
</div>
</div>
</div>
<div class="container">
<div id="calculator">
<div id="screen-container">
<div id="top-header">
<span class="left">FCC <span class="large middle">48</span></span>
<span class="right">
<span id="logo" class="fa-stack small-fa">
<i class="fa fa-clone fa-rotate-90 fa-stack-2x"></i>
<i class="fa fa-fire fa-stack-1x blue nudge-fa"></i>
</span>
</span>
</div>
<div id="screen">
<div class="screen-header-container">
<div class="screen-header">
<div id="header-row1" class="screen-header-row">
<div class="screen-header-content"></div>
<div class="screen-header-right right"></div>
</div>
<div id="header-row2" class="screen-header-row">
<div class="screen-header-content">Home</div>
<div class="screen-header-right right"></div>
</div>
</div>
<hr>
</div>
<div class="screen-main-display-container">
<div class="screen-main-display">
<div id="line4" class="line">
<span class="line-number left"></span>
<span class="content"></span>
</div>
<div id="line3" class="line">
<span class="line-number left"></span>
<span class="content"></span>
</div>
<div id="line2" class="line">
<span class="line-number left"></span>
<span class="content"></span>
</div>
<div id="line1" class="line">
<span class="line-number left"></span>
<span class="content"></span>
</div>
<div id="line0" class="line">
<span class="line-number left"></span>
<span class="content"></span>
</div>
</div>
</div>
<div class="screen-menus">
<div id="menu1" class="menu"></div>
<div id="menu2" class="menu"></div>
<div id="menu3" class="menu"></div>
<div id="menu4" class="menu"></div>
<div id="menu5" class="menu"></div>
<div id="menu6" class="menu"></div>
</div>
</div>
</div>
<div id="keys">
<div id="key-option-row" class="key-row group">
<div class="key-option-container">
<div id="k0" class="key-button key-option-button">
<div class="key-text"></div>
</div>
</div>
<div class="key-option-container">
<div id="k1" class="key-button key-option-button">
<div class="key-text"></div>
</div>
</div>
<div class="key-option-container">
<div id="k2" class="key-button key-option-button">
<div class="key-text"></div>
</div>
</div>
<div class="key-option-container">
<div id="k3" class="key-button key-option-button">
<div class="key-text"></div>
</div>
</div>
<div class="key-option-container">
<div id="k4" class="key-button key-option-button">
<div class="key-text"></div>
</div>
</div>
<div class="key-option-container">
<div id="k5" class="key-button key-option-button">
<div class="key-text"></div>
</div>
</div>
</div>
<div class="key-row group">
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k6" class="key-button key-small-button">
<div class="key-text">6</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k7" class="key-button key-small-button">
<div class="key-text">7</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k8" class="key-button key-small-button">
<div class="key-text">8</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k9" class="key-button key-small-button">
<div class="key-text">9</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k10" class="key-button key-small-button">
<div class="key-text">10</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k11" class="key-button key-small-button">
<div class="key-text">11</div>
</div>
</div>
</div>
<div class="key-row group">
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k12" class="key-button key-small-button">
<div class="key-text">12</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k13" class="key-button key-small-button">
<div class="key-text">13</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k14" class="key-button key-small-button">
<div class="key-text">14</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k15" class="key-button key-small-button">
<div class="key-text">15</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k16" class="key-button key-small-button">
<div class="key-text">16</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k17" class="key-button key-small-button">
<div class="key-text">17</div>
</div>
</div>
</div>
<div class="key-row group">
<div class="key-small-container key-enter-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k18" class="key-button key-small-button key-enter-button">
<div class="key-text">18</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k19" class="key-button key-small-button">
<div class="key-text">19</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k20" class="key-button key-small-button">
<div class="key-text">20</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k21" class="key-button key-small-button">
<div class="key-text">21</div>
</div>
</div>
<div class="key-small-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k22" class="key-button key-small-button">
<div class="key-text">22</div>
</div>
</div>
</div>
<div class="key-row group">
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k23" class="key-button key-large-button">
<div class="key-text">23</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k24" class="key-button key-large-button">
<div class="key-text">24</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k25" class="key-button key-large-button">
<div class="key-text">25</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k26" class="key-button key-large-button">
<div class="key-text">26</div>
</div>
</div>
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k27" class="key-button key-large-button">
<div class="key-text">27</div>
</div>
</div>
</div>
<div class="key-row group">
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k28" class="key-button key-large-button key-alt-1">
<div class="key-text">28</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k29" class="key-button key-large-button">
<div class="key-text">29</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k30" class="key-button key-large-button">
<div class="key-text">30</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k31" class="key-button key-large-button">
<div class="key-text">31</div>
</div>
</div>
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k32" class="key-button key-large-button">
<div class="key-text">32</div>
</div>
</div>
</div>
<div class="key-row group">
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k33" class="key-button key-large-button key-alt-2">
<div class="key-text">33</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k34" class="key-button key-large-button">
<div class="key-text">34</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k35" class="key-button key-large-button">
<div class="key-text">35</div>
</div>
</div>
<div class="key-large-container key-bg-light">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k36" class="key-button key-large-button">
<div class="key-text">36</div>
</div>
</div>
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k37" class="key-button key-large-button">
<div class="key-text">37</div>
</div>
</div>
</div>
<div class="key-row group">
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k38" class="key-button key-large-button">
<div class="key-text">38</div>
</div>
</div>
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k39" class="key-button key-large-button">
<div class="key-text">39</div>
</div>
</div>
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k40" class="key-button key-large-button">
<div class="key-text">40</div>
</div>
</div>
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k41" class="key-button key-large-button">
<div class="key-text">41</div>
</div>
</div>
<div class="key-large-container">
<div class="key-alt">
<span class="key-alt-text-1"></span>
<span class="key-alt-text-2"></span>
</div>
<div id="k42" class="key-button key-large-button">
<div class="key-text">42</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="attribution-container">
<div class="attribution">
<a href="https://www.flickr.com/photos/aheram/5864814103/" target="_blank">Math Homework</a> by <a href="https://tr.gravatar.com/tebm" target="_blank">HARUN PEHLİVAN </a><br>
is licensed under <a href="http://harunpehlivan-blog.tumblr.com/" target="_blank">CC BY 2.0</a>
</div>
</div>
</body>
FCC 48G Calculator
------------------
FreeCodeCamp Zipline: Build a JavaScript Calculator
A tribute to my favorite calculator, the HP 48G
A lot of the alt buttons are empty, as well as the on screen menus. Maybe one day I'll return to build the calculator out more.... one day.
A [Pen](https://codepen.io/harunpehlivan/pen/KQOmLa) by [HARUN PEHLİVAN](https://codepen.io/harunpehlivan) on [CodePen](https://codepen.io).
[License](https://codepen.io/harunpehlivan/pen/KQOmLa/license).
以上是关于markdown FCC 48G计算器的主要内容,如果未能解决你的问题,请参考以下文章
markdown [FCC] Tribute Page MJ