Skip to content

Instantly share code, notes, and snippets.

@Jesse-Bett
Last active October 10, 2019 09:18
Show Gist options
  • Save Jesse-Bett/dbf08423ad08dba0ad6d3b69b4f40358 to your computer and use it in GitHub Desktop.
Save Jesse-Bett/dbf08423ad08dba0ad6d3b69b4f40358 to your computer and use it in GitHub Desktop.
Demo Calc
<div id="challenge"></div>
const isOperator = /[x/+‑]/,
endsWithOperator = /[-x+/]$/,
endsWithNegativeSign = /[x/+][-]$/;
class Keypad extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="keypad">
<div className="top">
<button
id="clear"
value="AC"
onClick={this.props.clickedClear}
class="AC-0 pad"
>
AC
</button>
<button
id="divide"
value="/"
onClick={this.props.clickedOperator}
class="number-operator pad op"
>
/
</button>
<button
id="multiply"
value="x"
onClick={this.props.clickedOperator}
class="number-operator pad op"
>
x
</button>
</div>
<div className="middle">
<div>
<button
id="seven"
value={7}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
7
</button>
<button
id="eight"
value={8}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
8
</button>
<button
id="nine"
value={9}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
9
</button>
<button
id="subtract"
value="-"
onClick={this.props.clickedOperator}
class="number-operator pad op"
>
-
</button>
</div>
<div>
<button
id="four"
value={4}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
4
</button>
<button
id="five"
value={5}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
5
</button>
<button
id="six"
value={6}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
6
</button>
<button
id="add"
value="+"
onClick={this.props.clickedOperator}
class="number-operator pad op"
>
+
</button>
</div>
</div>
<div className="bottom">
<div className="bottom-left">
<div className="one-two-three">
<button
id="one"
value={1}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
1
</button>
<button
id="two"
value={2}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
2
</button>
<button
id="three"
value={3}
onClick={this.props.clickedNumber}
class="number-operator pad"
>
3
</button>
</div>
<div className="zero-decimal">
<button
id="zero"
value={0}
onClick={this.props.clickedNumber}
class="AC-0 pad"
>
0
</button>
<button
id="decimal"
value="."
onClick={this.props.clickedDecimal}
class="number-operator pad"
>
.
</button>
</div>
</div>
<div className="bottom-right">
<button
id="equals"
value="="
onClick={this.props.clickedEquals}
class="equals pad"
>
=
</button>
</div>
</div>
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentValue: "0", // 0 or an operator or a value
prevValue: "",
formula: "", // a string of the expression
currentSign: "pos"
};
// bindings
this.limitWarning = this.limitWarning.bind(this);
this.clickedNumber = this.clickedNumber.bind(this);
this.clickedOperator = this.clickedOperator.bind(this);
this.clickedDecimal = this.clickedDecimal.bind(this);
this.clickedEquals = this.clickedEquals.bind(this);
this.clickedClear = this.clickedClear.bind(this);
}
// methods
limitWarning() {
this.setState({
currentValue: "Digit Limit Reached",
prevValue: "Digit Limit Reached"
});
}
clickedClear(e) {
this.setState({
currentValue: "0",
prevValue: "",
formula: ""
});
}
clickedNumber(e) {
if (!this.state.currentValue.includes("Limit")) {
const { currentValue, formula, evaluated } = this.state;
const val = e.target.value;
this.setState({ evaluated: false });
if (currentValue.length > 21) {
this.limitWarning();
} else if (evaluated) {
this.setState({
currentValue: val,
formula: val !== "0" ? val : ""
});
} else {
this.setState({
currentValue:
currentValue === "0" || isOperator.test(currentValue)
? val
: currentValue + val,
formula:
currentValue === "0" && val === "0"
? formula
: /([^.0-9]0)$/.test(formula)
? formula.slice(0, -1) + val
: formula + val
});
}
}
}
clickedOperator(e) {
if (!this.state.currentValue.includes('Limit')) {
const val = e.target.value;
const { formula, prevValue, evaluated } = this.state;
this.setState({ currentValue: val, evaluated: false });
if (evaluated) {
this.setState({ formula: prevValue + val });
} else if (!endsWithOperator.test(formula)) {
this.setState({
prevValue: formula,
formula: formula + val
});
} else if (!endsWithNegativeSign.test(formula)) {
this.setState({
formula: (endsWithNegativeSign.test(formula + val)) ? (formula + val) : (prevValue + val)
});
} else if (val !== "-") {
this.setState({
formula: prevValue + val
});
}
}
}
clickedDecimal() {
if (this.state.evaluated === true) {
this.setState({
currentValue: "0.",
formula: "0."
});
} else if (
!this.state.currentValue.includes(".") &&
!this.state.currentValue.includes("Limit")
) {
this.setState({ evaluated: false });
if(this.state.currentValue.length > 21) {
this.limitWarning;
} else if (
endsWithOperator.test(this.state.formula) ||
(this.state.currentValue === '0' && this.state.formula === '')
) {
this.setState({
currentValue: '0.',
formula: this.state.formula + '0.'
});
} else {
this.setState({
currentValue: this.state.formula.match(/(-?\d+\.?\d*)$/)[0] + '.',
formula: this.state.formula + '.'
});
}
}
}
clickedEquals(e) {
if (!this.state.currentValue.includes("Limit")) {
if(this.state.formula !== "") {
let expression = this.state.formula;
while (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({
currentValue: answer.toString(),
formula:
expression.replace(/\*/g, "⋅").replace(/-/g, "‑") + "=" + answer,
prevValue: answer,
evaluated: true
});
}
}
}
render() {
return (
<div>
<div id="calculator">
<div className="display">
<div id="formula">{this.state.formula.replace(/x/g, "⋅")}</div>
<div id="display">{this.state.currentValue}</div>
</div>
<Keypad
clickedNumber={this.clickedNumber}
clickedOperator={this.clickedOperator}
clickedClear={this.clickedClear}
clickedDecimal={this.clickedDecimal}
clickedEquals={this.clickedEquals}
/>
</div>
<div id="zeek">
<a href="https://codepen.io/odkpatrick" target="_blank">zeek</a>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("challenge"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.1/umd/react-dom.production.min.js"></script>
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
@import 'https://fonts.googleapis.com/css?family=Share+Tech+Mono';
* {
border-box: content-box;
margin: 0;
padding: 0;
font-family: 'Share Tech Mono', monospace;;
}
#challenge {
height: 100vh;
display: flex;
justify-content: top;
align-items: center;
}
#calculator {
width: 400px;
background-color: #000;
padding: 2px;
font-size: 32px;
}
.display {
text-align: right;
margin-bottom: 15px;
padding: 10px 15px;
color: #dedede;
}
#formula,
#display {
height: 20px;
color: #fff;
padding: 1px solid #000;
}
.keypad {
display: flex;
flex-direction: column;
border: 1px solid #000;
border-width: 1px;
}
.top,
.middle,
.bottom,
.bottom-left {
width: 100%;
display: grid;
}
.top {
grid-template-columns: 2fr 1fr 1fr;
}
.middle {
grid-template-rows: 1fr 1fr;
}
.middle div {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
}
.bottom {
grid-template-columns: 3fr 1fr;
}
.bottom-left {
grid-template-rows: 1fr 1fr;
}
.one-two-three {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.zero-decimal {
display: grid;
grid-template-columns: 2fr 1fr;
}
.AC-0,
.number-operator,
.equals {
text-align: center;
border: 1px solid #000;
}
.pad {
height: 65px;
font-size: 20px;
}
.equals {
width: 100%;
height: 100%;
}
.pad:hover {
border: 1px solid #FFF;
}
.number-operator, #zero {
background-color: #ffff;
}
.op {
background-color: #F9E79F;
}
#equals {
background-color: #F9E79F;
}
#clear {
background-color: #F9E79F;
}
a {
display: block;
text-align: right;
padding: 5px;
color: green;
text-decoration: none;
}
a:hover {
text-decoration: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment