I'm a newbie and I'm looking to get my basic HTML calculator working.
I have the JavaScript working to the point it's logging the button presses from my HTML buttons in a string variable. So for example if I click 9 * 9 on the calculator I can see I have a string "9*9" in the console which is what I was after.
I have been trying to get JavaScript to treat the string as a mathematical statement and I understand I need an anonymous function to get JS to calculate the string so "10*10" becomes 100 for example.
However, when my function is called from the event listener on my equals button, I am not getting a result in the console. I added a console log to at least let me know the equals button press was registered and it is. I only get a numerical result if I call the function in the code with a console log separately, or I set the userInput variable at the point of declaration to a string suitable for calculating e.e. "10*10". So It's kind of working but I can't get it to calculate userInput in normal use, only when it's been hard coded. I have double checked userInput is a string user typeof and it is.
// My event listener statement is here:
eqs.addEventListener("click", calcs);
When I click = I hoped calcs is called and the return statement is returned with whatever the value of userInput is, and it gets calculated.
// The function:
function calcs() {
return new Function("return " userInput)();
}
First ever post so this is likely missing key bits of info but any help gratefully received.
CodePudding user response:
Not sure why you think you need to return back the result of the function being executed. That is just returning the result back to the click event to determine if it should process it or stop.
userInput = "9*10";
const eqs = document.querySelector("button");
eqs.addEventListener("click", calcs);
function calcs() {
const result = new Function("return " userInput)();
console.log(result);
}
<button type="button">=</button>
CodePudding user response:
Why not something like this:
https://jsfiddle.net/9svfy0gc/2/
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>7</button>
<button>8</button>
<button>9</button>
<br/>
<button> </button>
<button>-</button>
<button>/</button>
<button>*</button>
<br/>
<button>=</button>
<div >
</div>
let actions = []
const log = (data) => {
document.querySelector('.log').textContent = data
}
const calc = () => {
log(`Do something with [${actions.join(',')}]`)
actions = []
}
document.querySelectorAll('button').forEach(div => {
div.addEventListener('click', () => {
actions.push(div.textContent)
log(`Queue action: ${div.textContent} - Actions: ${actions.join(',')}`)
if (actions[actions.length-1] === '=') {
calc()
}
})
})
CodePudding user response:
Rick, I do not know the all the implementation details but I do want to help.
Warnings
- Using Function constructor or eval is a security risk. Never do this in a production code
- You can not create a usable calculator without a parser. You will only end up with spaghetti code if you try without
- An anonymous function is just a function without a name.
- Your best bet is to use the eval function because the function constructor will not compile the operator
Spaghetti Answer
const calc = () => {
const leftOperand = document.querySelector('#leftOperand').value;
const operator = document.querySelector('#operator').value;
const rightOperand = document.querySelector('#rightOperand').value;
var actual = eval(`${leftOperand}${operator}${rightOperand}`);
console.log(actual);
return actual;
}
document.querySelector('#evaluator').addEventListener('click', calc);
<input id="leftOperand" type="text" placeholder="Left Operand" />
<input id="operator" type="text" placeholder="Operator" />
<input id="rightOperand" type="text" placeholder="Right Operand" />
<button id="evaluator">=</button>