Changing property of an object in Javascript - 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.

Related

Issue with local/global scope and NAN

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.

Get random 8 images from directory for my game using JQuery

I have developed a memory game from a set of images using JS and PHP and everything works fine. Now I'd like to expand this work and get images from the directory for the game.
JS code :
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function (e) {
var turnable = e.target.dataset.turnable;
//first click
if (!wait && lastKnownButtonId == undefined && lastKnownButtonNumber == undefined && turnable == 'true') {
e.target.dataset.turnable = 'false';
e.target.innerHTML = getgImage(event.target.dataset.number);
e.target.style.backgroundColor = 'yellow';
lastKnownButtonId = e.target.id;
lastKnownButtonNumber = e.target.dataset.number;
}
//second click
else if (!wait && lastKnownButtonId != undefined && lastKnownButtonNumber != undefined && turnable == 'true' && e.target.id != lastKnownButtonId) {
e.target.dataset.turnable = 'false';
e.target.innerHTML = getgImage(event.target.dataset.number);
//match
if (e.target.dataset.number == lastKnownButtonNumber) {
e.target.style.backgroundColor = '#00FF7F';
document.getElementById(lastKnownButtonId).style.backgroundColor = '#00FF7F';
lastKnownButtonId = undefined;
lastKnownButtonNumber = undefined;
matches++;
if (matches == 8) {
showWinScreen();
//clearTimeout(timeoutHandle);
document.getElementById("finalMove").innerHTML = moves;
}
}
//no match
else {
document.getElementById(lastKnownButtonId).style.backgroundColor = 'red';
e.target.style.backgroundColor = 'red';
wait = true;
setTimeout(() => {
e.target.dataset.turnable = 'true';
e.target.style.backgroundColor = 'white'
e.target.innerHTML = getgImage(0);
var tempLastClickedButton = document.getElementById(lastKnownButtonId);
tempLastClickedButton.dataset.turnable = 'true';
tempLastClickedButton.style.backgroundColor = 'white';
tempLastClickedButton.innerHTML = getgImage(0);
lastKnownButtonId = undefined;
lastKnownButtonNumber = undefined;
wait = false;
}, 1000);
}
moveCounter();
}
});
}
function getgImage(number) {
switch (number) {
case '1':
return '<img src="resources/fashion1.jpg">';
case '2':
return '<img src="resources/fashion2.jpg">';
case '3':
return '<img src="resources/fashion3.jpg">';
case '4':
return '<img src="resources/fashion4.jpg">';
case '5':
return '<img src="resources/fashion5.jpg">';
case '6':
return '<img src="resources/fashion6.jpg">';
case '7':
return '<img src="resources/fashion7.jpg">';
case '8':
return '<img src="resources/fashion8.jpg">';
default:
return '<img src="resources/logo.png">';
}
}
So in the above code, I use a set of images in the switch case. Now I'd like to use random 8 images from the directory called "resources". Is it possible to use Jquery to get random 8 images from the directory? I don't know how to proceed
This should help you:
arrayOfImages[Math.floor(Math.random()*arrayOfImages.length)];
So, are they named like fashion1, fashion2, ..... fashion8 if so you could just do this:
'<img src="resources/fashion' + (Math.floor(Math.random() * 8) + 1) + '.jpg">'
This would get you a random image. But if not, it's not possible until your client side code knows all the names upfront like in the comments

Create a MR and MC in a javascript calculator

Idealy, I would like my little project to have the memory functions M-, M+, MR and MC.
I was thinking of separate functions and variables to hold the M- and M+.
Is this a normal approach or there is a better one ?
Any idea what might be wrong with my script ? if there is something wrong ?
the number-display ID is the actual calculator screen
the code is :
$(document).ready(function(){
var display = "";
var operators = ["/", "*", "-", "+"];
var decimalAdded = false;
$("button").click(function() {
var key = $(this).text();
//update screen by adding display string to screen with maximum 19 numbers viewable
function updateDisplay() {
if (display.length > 19) {
$("#number-display").html(display.substr(display.length - 19, display.length));
} else {
$("#number-display").html(display.substr(0, 19));
}
}
//clear all entries by resetting display and variables
if (key === "AC" || key === "ON" || key === "MC") {
decimalAdded = false;
display = "";
$("#number-display").html("0");
}
else if (key === "OFF") {
decimalAdded = false;
display = "";
$("#number-display").html("");
}
//clear previous character and reset decimal bool if last character is decimal
else if (key === "CE") {
if (display.substr(display.length - 1, display.length) === ".") {
decimalAdded = false;
}
display = display.substr(0, display.length - 1);
updateDisplay();
}
//add key to display if key is a number
else if (!isNaN(key)) {
display += key;
updateDisplay();
}
//check that . is the first in the number before adding and add 0. or just .
else if (key === ".") {
if (!decimalAdded) {
if(display > 0){
display += key;
}
else {
display += "0" + key;
}
decimalAdded = true;
updateDisplay();
}
}
//if key is basic operator, check that the last input was a number before inputting
else if (operators.indexOf(key) > -1) {
decimalAdded = false;
//first input is a number
if (display.length > 0 && !isNaN(display.substr(display.length - 1, display.length))) {
display += key;
updateDisplay();
}
// allow minus sign as first input
else if (display.length === 0 && key === "-") {
display += key;
updateDisplay();
}
}
// calculate square root of number
else if ( $(this).id === "sqrt") {
var tempStore = display.html();
$("#number-display").html(eval(Math.sqrt(tempStore)));
decimalAdded = false;
}
// change sign of number
else if ($(this).id === "plusmn") {
var newNum = display * -1;
$("#number-display").html(newNum);
}
// create memory plus and minus and calculate MR
else if (key === "M-") {
}
else if (key === "M+") {
}
// percentage function
else if (key === "%"){
}
else if (key == "=") {
//if last input is a decimal or operator, remove from display
if (isNaN(display.substr(display.length - 1, display.length))) {
display = display.substr(0, display.length - 1);
}
var calc = display;
calc = eval(calc);
display = String(calc);
if (display.indexOf('.')) {
decimalAdded = true;
} else {
decimalAdded = false;
}
$("#number-display").html(display);
}
});});
One alternative is a switch statement, which would look something like:
switch (key) {
case "M-":
// do stuff
break;
case "M+":
// do stuff
break;
case "%":
// do stuff
break;
case "=":
// do stuff
break;
}
More documentation on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch

JS Basics: How to use if/else inside a function and set to variable

I'm a JavaScript total beginner and I've gotten stuck on something that seems like it should work while trying to set a variable with a an if/else condition inside and anonymous function. Here is my code:
function changeValue(){
var newValue = (function(){
var getRadioValue = $( "input:radio[name=Radio1]:checked" ).val();
if (getRadioValue === 5){
var final = 8;
}
else if (getRadioValue === 4){
var final = 5;
}
else if (getRadioValue === 3){
var final = 3;
}
else if (getRadioValue === 2){
var final = 1;
}
else if (getRadioValue === 1){
var final = -1;
}
else
{
var final = 0;
}
return final;
})();
alert(newValue);
}
Right now, the alert is showing 0 because none of the "ifs" are returning true, but if I set the getRadioValue variable hard coded like:
var getRadioValue = 5;
then the if/else conditional works and the alert message shows 8. That makes it seem like the .val() method isn't working. However, if I simply set the alert to:
alert(getRadioValue);
The alert message does in fact display the correctly selected radio value from the radio button set on my page. So I know that is working... Now I can't figure out where I'm going wrong. It seems like since the radio value is getting assigned to getRadioValue correctly, and the conditional is working, the whole thing should work. I'm sure it's such a basic problem, but after much research I still can't seem to get it. Any help is greatly appreciated!
.val() is returning a string but you are testing for number if (getRadioValue === 5){.
You might want to do getRadioValue = parseInt(getRadioValue) first.
Demo:
getRadioValue = parseInt("5")
var final = 0; // use var once, its cleaner ;)
if (getRadioValue === 5) {
final = 8;
} else if (getRadioValue === 4) {
final = 5;
} else if (getRadioValue === 3) {
final = 3;
} else if (getRadioValue === 2) {
final = 1;
} else if (getRadioValue === 1) {
final = -1;
}
alert(final);
Thanks to CodeiSir! That was the issue. Here is my final working code for others who might run into a similar problem:
function changeValue(){
var newValue = (function(){
var getRadioValue = $( "input:radio[name=CalcItem1]:checked" ).val();
var RadioValue = parseInt(getRadioValue);
if (RadioValue === 5){
var final = 8;
}
else if (RadioValue === 4){
var final = 5;
}
else if (RadioValue === 3){
var final = 3;
}
else if (RadioValue === 2){
var final = 1;
}
else if (RadioValue === 1){
var final = -1;
}
else
{
var final = 0;
}
return final;
})();
alert(newValue);
}

How to write if ,else block for multiple conditions?

I am new to javascript what is right way to write if and else block with below code i am getting an error on else condition that syntax is not correct. Please let me know what i have implemented wrong.
main.js
if (dataRow.opriskYesNo === 'Yes') {
$scope.opRiskCompleted = 'Y';
} else if (dataRow.opriskYesNo === 'No') {
$scope.opRiskCompleted = 'N';
} else(dataRow.opriskYesNo === '') {
$scope.opRiskCompleted = '';
$scope.opRiskCompleted = '';
}
You should have else without any condition in your last conditional code block.
Though the improved version would look like below, I'd say maintain one object with key value and use it.
var mappedModel = {'Yes': 'Y', 'No': 'N'};
$scope.opRiskCompleted = mappedModel[dataRow.opriskYesNo] || '';
Why don't you use a Switch?
switch(dataRow.opriskYesNo){
case "Yes":
$scope.opRiskCompleted = 'Y';
break;
case "No":
$scope.opRiskCompleted = 'N';
break;
default:
$scope.opRiskCompleted = '';
break; }
Try this:
if(dataRow.opriskYesNo==='Yes'){
$scope.opRiskCompleted = 'Y';
} else if (dataRow.opriskYesNo==='No') {
$scope.opRiskCompleted = 'N';
} else {
$scope.opRiskCompleted = '';
$scope.opRiskCompleted = '';
}

Categories

Resources