A Pen by freeCodeCamp on CodePen.
Created
February 4, 2019 03:27
-
-
Save iam-pankaj/05a61788f15170b05052e78eba335bdc to your computer and use it in GitHub Desktop.
FCC: Javascript Calculator
This file contains 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
#app | |
This file contains 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
// To see a more advanced version of this app with features such as toggle sign and Clear Entry buttons, see this pen https://codepen.io/no_stack_dub_sack/full/jrxpKP/ | |
// coded by @no-stack-dub-sack (github) / @no_stack_sub_sack (codepen) | |
// PROJECTOR SELECTOR FOR EXTERNAL TEST SCRIPT: | |
const projectName = 'javascript-calculator'; | |
localStorage.setItem('example_project', 'Javascript Calculator'); | |
// VARS: | |
const isOperator = /[x/+‑]/, | |
endsWithOperator = /[x+‑/]$/, | |
clearStyle = {background: '#ac3939'}, | |
operatorStyle = {background: '#666666'}, | |
equalsStyle = { | |
background: '#004466', | |
position: 'absolute', | |
height: 130, | |
bottom: 5 | |
}; | |
// COMPONENTS: | |
class Calculator extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
currentVal: '0', | |
prevVal: '0', | |
formula: '', | |
currentSign: 'pos', | |
lastClicked: '' | |
} | |
this.maxDigitWarning = this.maxDigitWarning.bind(this); | |
this.handleOperators = this.handleOperators.bind(this); | |
this.handleEvaluate = this.handleEvaluate.bind(this); | |
this.initialize = this.initialize.bind(this); | |
this.handleDecimal = this.handleDecimal.bind(this); | |
this.handleNumbers = this.handleNumbers.bind(this); | |
} | |
maxDigitWarning() { | |
this.setState({ | |
currentVal: 'Digit Limit Met', | |
prevVal: this.state.currentVal | |
}); | |
setTimeout(() => this.setState({currentVal: this.state.prevVal}), 1000); | |
} | |
handleEvaluate() { | |
if (!this.state.currentVal.includes('Limit')) { | |
let expression = this.state.formula; | |
if (endsWithOperator.test(expression)) expression = expression.slice(0, -1); | |
expression = expression.replace(/x/g, "*").replace(/‑/g, "-"); | |
let answer = Math.round(1000000000000 * eval(expression)) / 1000000000000; | |
this.setState({ | |
currentVal: answer.toString(), | |
formula: expression.replace(/\*/g, '⋅').replace(/-/g, '‑') + '=' + answer, | |
prevVal: answer, | |
evaluated: true | |
}); | |
} | |
} | |
handleOperators(e) { | |
if (!this.state.currentVal.includes('Limit')) { | |
this.setState({currentVal: e.target.value,evaluated: false}); | |
if (this.state.formula.includes('=')) { | |
this.setState({formula: this.state.prevVal + e.target.value}); // comment 1 | |
} else { | |
this.setState({ // comment 2 | |
prevVal: !isOperator.test(this.state.currentVal) ? | |
this.state.formula : | |
this.state.prevVal, | |
formula: !isOperator.test(this.state.currentVal) ? | |
this.state.formula += e.target.value : | |
this.state.prevVal += e.target.value | |
}); | |
} | |
} | |
} | |
handleNumbers(e) { | |
if (!this.state.currentVal.includes('Limit')) { | |
this.setState({evaluated: false}) | |
if (this.state.currentVal.length > 21) { | |
this.maxDigitWarning(); | |
} else if (this.state.evaluated === true) { | |
this.setState({ | |
currentVal: e.target.value, | |
formula: e.target.value != '0' ? e.target.value : '', | |
}); | |
} else { | |
this.setState({ | |
currentVal: | |
this.state.currentVal == '0' || | |
isOperator.test(this.state.currentVal) ? | |
e.target.value : this.state.currentVal + e.target.value, | |
formula: | |
this.state.currentVal == '0' && e.target.value == '0' ? | |
this.state.formula : | |
/([^.0-9]0)$/.test(this.state.formula) ? | |
this.state.formula.slice(0, -1) + e.target.value : | |
this.state.formula + e.target.value, | |
}); | |
} | |
} | |
} | |
handleDecimal() { | |
if (this.state.evaluated === true) { | |
this.setState({ | |
currentVal: '0.', | |
formula: '0.', | |
evaluated: false}); | |
} else if (!this.state.currentVal.includes('.') && | |
!this.state.currentVal.includes('Limit')) { | |
this.setState({evaluated: false}) | |
if (this.state.currentVal.length > 21) { | |
this.maxDigitWarning(); | |
} else if (endsWithOperator.test(this.state.formula) || | |
this.state.currentVal == '0' && this.state.formula === '') { | |
this.setState({ | |
currentVal: '0.', | |
formula: this.state.formula + '0.' | |
}); | |
} else { | |
this.setState({ | |
currentVal: this.state.formula.match(/(-?\d+\.?\d*)$/)[0] + '.', | |
formula: this.state.formula + '.', | |
}); | |
} | |
} | |
} | |
initialize() { | |
this.setState({ | |
currentVal: '0', | |
prevVal: '0', | |
formula: '', | |
currentSign: 'pos', | |
lastClicked: '' | |
}); | |
} | |
render() { | |
return ( | |
<div> | |
<div className='calculator'> | |
<Formula formula={this.state.formula.replace(/x/g, '⋅')} /> | |
<Output currentValue={this.state.currentVal} /> | |
<Buttons evaluate={this.handleEvaluate} | |
operators={this.handleOperators} | |
initialize={this.initialize} | |
decimal={this.handleDecimal} | |
numbers={this.handleNumbers} /> | |
</div> | |
<div className="author"> Designed and Coded By <br /> | |
<a target="_blank" href="https://goo.gl/6NNLMG"> | |
Peter Weinberg | |
</a> | |
</div> | |
</div> | |
) | |
} | |
}; | |
class Buttons extends React.Component { | |
render() { | |
return ( | |
<div> | |
<button id="clear" value='AC' onClick={this.props.initialize} className='jumbo' style={clearStyle}>AC</button> | |
<button id="divide" value='/' onClick={this.props.operators} style={operatorStyle}>/</button> | |
<button id="multiply" value='x' onClick={this.props.operators} style={operatorStyle}>x</button> | |
<button id="seven" value='7' onClick={this.props.numbers} >7</button> | |
<button id="eight" value='8' onClick={this.props.numbers} >8</button> | |
<button id="nine" value='9' onClick={this.props.numbers} >9</button> | |
<button id="subtract" value='‑' onClick={this.props.operators} style={operatorStyle}>-</button> | |
<button id="four" value='4' onClick={this.props.numbers} >4</button> | |
<button id="five" value='5' onClick={this.props.numbers} >5</button> | |
<button id="six" value='6' onClick={this.props.numbers} >6</button> | |
<button id="add" value='+' onClick={this.props.operators} style={operatorStyle}>+</button> | |
<button id="one" value='1' onClick={this.props.numbers} >1</button> | |
<button id="two" value='2' onClick={this.props.numbers} >2</button> | |
<button id="three" value='3' onClick={this.props.numbers} >3</button> | |
<button id="zero" value='0' onClick={this.props.numbers} className='jumbo'>0</button> | |
<button id="decimal" value='.' onClick={this.props.decimal} >.</button> | |
<button id="equals" value='=' onClick={this.props.evaluate} style={equalsStyle}>=</button> | |
</div> | |
); | |
} | |
} | |
class Output extends React.Component { | |
render () { | |
return <div id="display" className="outputScreen">{this.props.currentValue}</div> | |
} | |
}; | |
class Formula extends React.Component { | |
render() { | |
return <div className="formulaScreen">{this.props.formula}</div> | |
} | |
}; | |
ReactDOM.render(<Calculator />, document.getElementById('app')); | |
This file contains 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
<script src="https://codepen.io/no_stack_dub_sack/pen/bwJxAw"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script> | |
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script> |
This file contains 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
$button: #4d4d4d; | |
@import 'https://fonts.googleapis.com/css?family=Share+Tech+Mono'; | |
@font-face { | |
font-family: "Digital"; | |
src: url("//db.onlinewebfonts.com/t/8e22783d707ad140bffe18b2a3812529.eot"); | |
src: url("//db.onlinewebfonts.com/t/8e22783d707ad140bffe18b2a3812529.eot?#iefix") format("embedded-opentype"), url("//db.onlinewebfonts.com/t/8e22783d707ad140bffe18b2a3812529.woff2") format("woff2"), url("//db.onlinewebfonts.com/t/8e22783d707ad140bffe18b2a3812529.woff") format("woff"), url("//db.onlinewebfonts.com/t/8e22783d707ad140bffe18b2a3812529.ttf") format("truetype"), url("//db.onlinewebfonts.com/t/8e22783d707ad140bffe18b2a3812529.svg#Digital-7") format("svg"); | |
} | |
#app { | |
height: 100vh; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
body { | |
background: #c2c2d6; | |
-webkit-touch-callout: none; | |
-moz-user-select: none; | |
-ms-user-select: none; | |
-webkit-user-select: none; | |
user-select: none; | |
cursor: default; | |
} | |
.calculator { | |
border: 2px solid #47476b; | |
padding: 5px; | |
background: black; | |
width: 320px; | |
position: relative; | |
} | |
.formulaScreen { | |
min-height: 20px; | |
font-family: digital; | |
font-size: 20px; | |
color: orange; | |
text-align: right; | |
vertical-align: text-top; | |
line-height: 20px; | |
overflow-wrap: break-word; | |
word-wrap: break-word; | |
} | |
.outputScreen { | |
font-size: 29px; | |
font-family: digital; | |
color: white; | |
text-align: right; | |
line-height: 35px; | |
} | |
button { | |
position: relative; | |
height: 65px; | |
width: 80px; | |
color: white; | |
outline: 1px solid black; | |
border: none; | |
background: $button; | |
font-family: Share Tech Mono, monospace; | |
font-size: 20px; | |
cursor: default; | |
&:hover { | |
color: black; | |
outline: .05em solid grey; | |
z-index: 3; | |
} | |
} | |
.jumbo { | |
width: 160px; | |
} | |
.author { | |
text-align: center; | |
font-family: Share Tech Mono, sans; | |
margin-top: 15px; | |
a { | |
text-decoration: none; | |
color: #00264d; | |
line-height: 26px; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment