Issue with local/global scope and NAN - javascript

Ok so I have the following code in order to create a calculator:
const numbers = document.querySelector('.numbers')
const display = document.querySelector('.display')
const functions = document.querySelector('.functions')
const equalClear = document.querySelector('.equalClear')
numbers.addEventListener('click', e => {
// selecting and adding nr to display
if(e.target.innerHTML == '1'){
display.innerHTML += '1';
}else if (e.target.innerHTML == '2'){
display.innerHTML += '2';
}else if (e.target.innerHTML == '3'){
display.innerHTML += '3';
}else if (e.target.innerHTML == '4'){
display.innerHTML += '4';
}else if (e.target.innerHTML == '5'){
display.innerHTML += '5';
}else if (e.target.innerHTML == '6'){
display.innerHTML += '6';
}else if (e.target.innerHTML == '7'){
display.innerHTML += '7';
}else if (e.target.innerHTML == '8'){
display.innerHTML += '8';
}else if (e.target.innerHTML == '9'){
display.innerHTML += '9';
}else if (e.target.innerHTML == '0'){
display.innerHTML += '0';
}
});
functions.addEventListener('click', e => {
// selecting a function and adding it to the display
if(e.target.innerHTML == 'Add'){
display.innerHTML += '+';
functionVal = add();
} else if(e.target.innerHTML == 'Subtract'){
display.innerHTML += '-';
functionVal = subtract();
} else if(e.target.innerHTML == 'Multiply'){
display.innerHTML += '*';
functionVal = multiply()
} else if(e.target.innerHTML == 'Divide'){
display.innerHTML += '/';
functionVal = divide();
}else{
display.innerHTML + 'Error'
}
numberVal = display.innerText; //creating variable with value of nr in display
console.log(numberVal, "numberVal");
console.log(functionVal, "functionVal");
});
equalClear.addEventListener('click', e => {
if(e.target.innerHTML === 'Clear'){
display.innerHTML = "";
}
else if(e.target.innerHTML = '='){
}
})
//functions for calculator
function add(variable1, variable2) {
return variable1 + variable2;
};
function subtract(variable1, variable2) {
return variable1 - variable2;
}
function multiply(variable1, variable2) {
return variable1 * variable2;
};
function divide(variable1, variable2) {
return variable1 / variable2;
}
// operation in calculator
function operate(operator, num1, num2){
operate = operator, num1, num2;
}
operate(functionVal(numberVal,5))
console.log(operate, "this is an operation");
I define "functionVal" and "numberVal" within "functions.addEventListener". But when I try calling them within the "operate" function at the bottom of my code, I get that "functionVal" and "numberVal" is undefined. I know that this is due to it being in a local scope within the "functions.addEventListener" function, and I have tried adding a "var" for each of them before the code block in order to give them global scope. But it just won't work and I'm going a bit crazy trying to find out how to be able to call them within my "operate" function.
Also, when I call "functionVal" within "console.log" in the "functions.AddEventListener" I get that "functionVal" is NAN which I know is "not a number", but shouldn't it display the actual function that I gave it the value to have? I have set that if you press "add" in the HTML, the value of "functionVal" becomes the "add" function I have defined in the bottom of the code. I'm not sure what is going wrong here so any help would be very appreciated.
In the "operate" function, I have given the second parameter the value 5 just for testing, but will add the actual "second number" in the display once I have been able to sort out the issues.
Grateful for any assistance!
Kind regards,
A JS noob

Okay, at first, this is really not good, why you sould ever check equality (and use === operator for the same types):
numbers.addEventListener('click', e => {
// selecting and adding nr to display
if(e.target.innerHTML == '1'){
display.innerHTML += '1';
}else if (e.target.innerHTML == '2'){
display.innerHTML += '2';
}else if (e.target.innerHTML == '3'){
display.innerHTML += '3';
}else if (e.target.innerHTML == '4'){
display.innerHTML += '4';
}else if (e.target.innerHTML == '5'){
display.innerHTML += '5';
}else if (e.target.innerHTML == '6'){
display.innerHTML += '6';
}else if (e.target.innerHTML == '7'){
display.innerHTML += '7';
}else if (e.target.innerHTML == '8'){
display.innerHTML += '8';
}else if (e.target.innerHTML == '9'){
display.innerHTML += '9';
}else if (e.target.innerHTML == '0'){
display.innerHTML += '0';
}
});
You can rewrite it like this:
numbers.addEventListener('click', e => {
display.innerHTML += e.target.innerHTML;
}
And if I understand correct, numbers must be array of buttons with numbers, but querySelector return only first occurrence, so it will return only first button.
You should use querySelectorAll and rewrite it like this:
const numbersButtons = document.querySelectorAll('.numbers');
// convert to array, because we can't iterate over querySelectorAll result
Array.from(numbersButtons).forEach((button,index) => {
button.addEventListener('click', e => {
display.innerHTML += e.target.innerHTML;
}
});
Functions, probability, must be an array too, and you can make code clearer, using, for example map of functions:
const functionsMap = {
'+': add,
'-': subtract
// and other functions..
}
And call them like this:
// will return add function
const targetFunc = functionsMap['+'];
// call with parameters
targetFunc(1,2);
And yes, when you make this:
functionVal = divide();
You don't pass reference to function, you execute it, so functionVal will store result of function execute, and yes, it will return NaN, because you execute it with no params, try this in console:
function add (a,b){return a + b}
console.log(add());
There are still a lot of mistakes, which I will not analyze, so I advise you to go back to the very beginning and take good care of what you are doing.

Related

Input Validation in JS

why my last if condition is not working to show validity error, if user input no value. Actually i am beginner in js making calculator as practice. I shall be very thankful if anyone could resolve it.
function calc()
{
let n1 = parseFloat(document.getElementById('n1').value);
let n2 = parseFloat(document.getElementById('n2').value);
let oper = document.getElementById('operators').value;
if(oper === '+')
{
document.getElementById('result').value = n1+n2;
}
if(oper === '-')
{
document.getElementById('result').value = n1-n2;
}
if(oper === '/')
{
document.getElementById('result').value = n1/n2;
}
if(oper === 'X')
{
document.getElementById('result').value = n1*n2;
}
if(n1=="" || n2==""){
document.getElementById("error").innerHTML="invalid input";
return true;
}
else{
return false;
}
Probably it happens because it reacts to the condition next to the last one where you have n1=="" || n2==""

Getting the error "Uncaught SyntaxError: continue must be inside loop" in the following code

document.querySelector('button[type="submit"]').addEventListener('click', () => {
const inputTags = Array.from(document.querySelectorAll('input'));
const textArea = document.querySelector('textarea');
inputTags.splice(inputTags.length, 0, textArea);
let output = "";
inputTags.forEach((input) => {
if(input.type == "checkbox" && input.checked == true ) {
output += input.nextElementSibling.textContent;
output += input.checked;
output += "\n";
continue;
} else if(input.type == "radio" && input.checked == true) {
if(input.nextElementSibling.textContent == "I have money and can pay for this") {
output += input.nextElementSibling.textContent.toLowerCase();
output += "\n";
}
} else {
output += input.nextElementSibling.textContent;
output += input.value;
}
})
alert(output);
})
You are trying to use continue outside a loop. A forEach call does not count as being inside a loop. Instead just return or make sure that nothing else happens before the function completes.
Seems like you could just remove that continue and everything would be fine.
you are not in a loop, you are in a function (forEach), so use return instead of continue

Javascript multiconverter

I have this 3 functions (multiconverter) in javascript, but i can´t figure it out why i can´t make the program to display the result.
function WhichConversion () {
var answer = window.prompt( " Welcome to the Mutliconverter! What do you want to convert? ( Dollars, Francs, Knots");
if (answer == "Dollars", "Knots", "Francs"){
return true;
} else {
return false;
}
}
function AskForValue () {
var answer = window.prompt( " Enter a Value to Convert")
return answer;
}
while (WhichConversion()) {
var ConversionType = WhichConversion();
var ConversionValue = AskForValue();
var resultMessage = " The result is ";
var result = 0;
if (ConversionType == "Dollars"){
resultMessage += DollarstoEuros(Number(ConversionValue))
.toString();
}else if (ConversionType == "Francs"){
resultMessage += SwissFrancsToEuros(Number(ConversionValue))
.toString();
}else if (ConversionType == "Knots"){
resultMessage += KnotstoKph(Number(ConversionValue))
.toString();
}else{
resultMessage = " Pay attention! That conversion is not supported.";
}
}
console.log(resultMessage);
The if statement to check for which conversion to use only has one check answer == "Dollars". To make the script work for other values you will need to create multiple checks:
if (answer == "Dollars" || answer == "Knots" || answer == "Francs"){
For an working example check the code below:
var currentCurrency = '';
function WhichConversion () {
var answer = window.prompt( " Welcome to the Mutliconverter! What do you want to convert? ( Dollars, Francs, Knots");
currentCurrency = answer;
return answer !== null
}
function DollarstoEuros(value){
return value * 12;
}
function AskForValue () {
var answer = window.prompt( " Enter a Value to Convert")
return answer;
}
while (WhichConversion()) {
var ConversionValue = AskForValue();
var result = 0;
var resultMessage = " The result is ";
if (currentCurrency == "Dollars"){
resultMessage += DollarstoEuros(Number(ConversionValue))
.toString();
}else if (currentCurrency == "Francs"){
resultMessage += SwissFrancsToEuros(Number(ConversionValue))
.toString();
}else if (currentCurrency == "Knots"){
resultMessage += KnotstoKph(Number(ConversionValue))
.toString();
}else{
resultMessage = " Pay attention! That conversion is not supported.";
}
console.log(resultMessage);
}

Changing property of an object in Javascript

Hi i am trying to refresh the value of a property inside an object after delay of one second i am using setInterval function for that purpose but value of the property i get is not right
var nextlvl = '';
function showPlaybackData() {
if(j.nextLevel == -1){
nextlvl = '';
}else if(j.nextLevel == 0){
nextlvl = '240p';
}else if(j.nextLevel == 1){
nextlvl = '360p';
}else if(j.nextLevel == 2){
nextlvl = '480p';
}else if(j.nextLevel == 3){
nextlvl = '720p';
}else if(j.nextLevel == 4){
nextlvl = '1080p';
}
console.log(nextlvl);
return nextlvl;
}
var g = {
id: -1,
label: 'auto(' + setInterval( showPlaybackData , 1000) +')',
selected: -1 === j.manualLevel
};
e.push(g)
the property label's value should be one of these resolutions i am setting according to condition but it shows 14 or 18 or 15. any solution to that?
when i use console.log i get accurate value within the function but when i call the function in setInterval the value is not right.
You need to refactor the code so that you use nextlvl within the function, instead of returning it. It's difficult to answer without seeing your full code, but something like this :
var j = ....
var e = [];
var g = {
id: -1,
selected: -1 === j.manualLevel
};
function showPlaybackData() {
var nextlvl = '';
if(j.nextLevel == 8){
nextlvl = '';
}else if(j.nextLevel == 0){
nextlvl = '240p';
}else if(j.nextLevel == 1){
nextlvl = '360p';
}else if(j.nextLevel == 2){
nextlvl = '480p';
}else if(j.nextLevel == 3){
nextlvl = '720p';
}else if(j.nextLevel == 4){
nextlvl = '1080p';
}
console.log(nextlvl);
g.label = 'auto(' + nextlvl +')';
e.push(g);
};
setInterval(showPlaybackData, 1000);
As a note, you should consider looking at switch statements, if you're not aware of them, as an alternative to the if/elses.
setInterval returns an identifier that allows you to retrieve (and, for example, clear) the timer, rather than the result of the function. Rather than returning the value you want in the function that's looped, you'll need to set a value in an object whose scope you have access to from within that loop.
May be this works for you :
function showPlaybackData(jpassed) {
var nextlvl = '';
switch(jpassed.nextLevel) {
case '':
nextlvl = '';
break;
case '240p':
nextlvl = '240p';
break;
case '360p':
nextlvl = '360p';
break;
case '480p':
nextlvl = '480p';
break;
case '720p':
nextlvl = '720p';
break;
case '1080p':
nextlvl = '1080p';
break;
default:
// any default logic
}
console.log(nextlvl);
return nextlvl;
}
And then update your object inside setinterval :
var j = ...
var g = {
id: -1,
label:'',
selected: -1 === j.manualLevel
};
setInterval(function(){
g.label = 'auto(' +showPlaybackData(j)+')' ;
e.push(g)
},2000,j,showPlaybackData,g);
#Karl Reid : Thanx Karl, I've updated the answer.

four repeating letters check javascript, spam detection

Is there a a "smarter" way to do this? This works but I imagine has something to do with for loops, what if I was checking for 20 repeating characters?
What happens if javascript is disabled?
Is there an easier way to check for "sensical" posts instead of say aldjfalkfja;lfjaklfjlkfj how would I filter that out without storing a library of words and comparing the string to those?
function counter(){
this.value = 0;
}
var count = new counter();
function updatecount(fnc){
fnc.value = count.value + 1;
}
function charbank1(){
this.value = "";
}
var cb1 = new charbank1();
function insertchar1(fnc){
fnc.value = cb1.value + String.fromCharCode(keynum);
}
function charbank2(){
this.value = "";
}
var cb2 = new charbank2();
function insertchar2(fnc){
fnc.value = cb2.value + String.fromCharCode(keynum);
}
function charbank3(){
this.value = "";
}
var cb3 = new charbank3();
function insertchar3(fnc){
fnc.value = cb3.value + String.fromCharCode(keynum);
}
function charbank4(){
this.value = "";
}
var cb4 = new charbank4();
function insertchar1(fnc){
fnc.value = cb4.value + String.fromCharCode(keynum);
}
function repeatingcharcheck(){
if(count.value < 4){
if(count.value == 1){
insertchar1(cb1);
}
if(count.value == 2){
insertchar2(cb2);
}
if(count.value == 3){
insertchar3(cb3);
}
if(count.value == 4){
insertchar4(cb4);
}
}else{
if(cb1.value == cb2.value == cb3.value == cb4.value){
alert('four letters in a row is not allowed');
window.location.replace('somewhere.com');
}
}
}

Categories

Resources