Skip to content

Instantly share code, notes, and snippets.

@Jubin369
Created April 1, 2018 07:51
Show Gist options
  • Save Jubin369/36bfaea7ef9e450a7c21f135f1db77ca to your computer and use it in GitHub Desktop.
Save Jubin369/36bfaea7ef9e450a7c21f135f1db77ca to your computer and use it in GitHub Desktop.
FCC: calculator
// PROJECTOR SELECTOR FOR EXTERNAL TEST SCRIPT:
const project_name = '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>
)
}
};
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'));
<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://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js"></script>
$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