Javascript: " != " Operator doesn't work properly - javascript

Good evening !
I am facing a strange behavior with my js/jquery, for a simple function where I am retrieving the last ID of a row, in order to check wether or not it's different from the previous one:
oldMsgId = 0;
// Ajax...
currentId = $( ".message_container tr:last" ).attr('id');
checkNewMsg(currentId);
// ... End Ajax.
function checkNewMsg(MsgId) {
if (MsgId != oldMsgId) {
var snd_msg = new Audio('sound/msg.wav');
snd_msg.volume = 0.3;
snd_msg.play();
}
oldMsgId = MsgId ;
}
The system works, however, when no new messages are retrieved, which means the latest ID is EQUAL to the old ID, it still execute the condition !
Of course, it will execute once the page is loaded because the oldMsgId is set to 0, but after that by testing with alerts, it has shown that the condition is running as it should not !
It drives me crazy, if someone has a solution I would be glad to hear it :)
EDIT : RESOLVED
Well, while using alerts inside the function this time, it appears I have made a huge mistake placing my oldMsgId var inside a loop function (which calls to ajax), so, the variable was reset to 0 everytime and thus made the difference, I'm very sorry xD!
Problem resolved, thanks everyone !

Well, while viewing with alerts inside the function this time, it appears I have made a huge mistake placing my oldMsgId var inside a loop function (which calls to ajax), I'm sorry xD!
Problem resolved, thanks everyone !

Related

Why will my button not advance to the next question?

I am a new developer and this is my first question. I am trying to make a multiple choice quiz for an assignment. I am stuck on making the NEXT button move to the next question. I think the rest of the JS file is correct...
Right now the clickNext doesn't do anything, so I need to do the following
check if the time expired (line 39)
did the user answer the question in the allotted time (line 40)
if no, try again and the clock will start over (line 60-70)
if yes, then store the answer selected - I think this part is tripping me up and I am not sure what to use here
check if the selected answer is correct (line 50-57)
if the answer is correct, move to the next question (line 52-53)
if the answer is wrong, alert "Please try again" (line 55-56)
I have tried to return the answer, the addEventListener, putting the checkAnswer function in the clickNext function
var indexQuestion = 0; // Current index of question we are on
var timer = 0; // A clock that goes up by 1 every second
var timeLastSubmit = 0; // the time we last submitted an answer
var timeExpired = false; // Did time expire for current question?
// number of seconds to wait for each question
var WAIT_TIME = 30;
// all questions to be used on the website
var QUESTIONS = [
{
"question":"Which city is the capital of Ontario?",
"choices":["New York","Toronto","Berlin","Kuala Lumpur"],
"answer":1
},
{
"question":"Which city is the capital of Canada?",
"choices":["New York","Toronto","Ottawa","Vancouver"],
"answer":2
},
{
"question":"Which continent does the south pole reside?",
"choices":["Africa","Antarctica","Asia","Australia","Europe","North America","South America"],
"answer":1
},
];
function loadApplication() {
loadQuestion(indexQuestion); // load the first question into the web page
// update the timer every second and check if question has been answered yet
setInterval(function(){
timer++;
checkExpirationTime();
},1000);
}
function clickNext() {
// make sure that the user has answered the question before the time has expired
timeLastSubmit = timer;
checkExpirationTime();
// Get the answer from drop down
var selectedIndexAnswer = getElementById('choices');
return selectedIndexAnswer;
// Get the anwer from the array
var answer = QUESTIONS[indexQuestion].choices[i];
checkAnswer();
};
function checkAnswer(){
// Compare answer. Only if correct, do you move onto next question - if(answer == QUESTIONS[indexQuestion].answer)
if(selectedIndexAnswer == answer) {
nextQuestion();
}
else {
alert('Please try again.');
}
}
function checkExpirationTime() {
// check the time, once the clock has reached 30 seconds do not move to the next quesiton
if(timer - timeLastSubmit < WAIT_TIME && !timeExpired){
document.getElementById("seconds").innerHTML = WAIT_TIME;
}
else{
timeExpired = true;
alert('Please try again.');
clearInterval(timeExpired);
}
}
function nextQuestion() {
// advance to the next question, until the there are no more questions
if(indexQuestion<QUESTIONS.length-1)
{
indexQuestion++;
loadQuestion(indexQuestion);
}
}
function loadQuestion(indexQuestion){
// grab the question
document.getElementById("question").textContent = QUESTIONS[indexQuestion].question;
// build the html string for select menu
var choices = "";
var i=0;
//loop through the choices
while(i<QUESTIONS[indexQuestion].choices.length){
// create a string of <option>answer</option><option>answer</option><option>answer</option>... and load it into the choices variable
choices += "<option>" + QUESTIONS[indexQuestion].choices[i] +"</option>";
i++;
}
document.getElementById("choices").innerHTML = choices;
}
// When the DOM is ready, run the function loadApplication();
document.addEventListener("DOMContentLoaded",loadApplication);
Right now the program does not advance to the next question, but it just stays on the first question.
To answer your first question
I am stuck on making the NEXT button move to the next question
For this you need to add click event listener to next button.
document.getElementById("btnNext").addEventListener("click",clickNext)
And the next part
I think the rest of the JS file is correct.
Almost.. You need to make a few corrections here and there.
I made some edits to the pen and is available here.
https://codepen.io/nithinthampi/pen/Yzzqqae
As, you are a learner, I would suggest not to copy it. Even the codepen I shared is not complete, but should help you to move on.
Going through your pens, here are the following issues I found with your code:
Misuse of return statements. You added a return statement in the second line of your function causing the rest of it to be completely ignored.
function clickNext() {
// make sure that the user has answered the question before the time has expired
timeLastSubmit = timer;
checkExpirationTime();
// Get the answer from drop down
var selectedIndexAnswer = getElementById('choices');
Here --> return selectedIndexAnswer;
// Get the anwer from the array
var answer = QUESTIONS[indexQuestion].choices[i];
checkAnswer();
}
onclick not added to your "Next" button, neither a addEventListener in your script was. As a result, clicking the "Next" button had no effect on your app, at all.
<button id="btnNext">Next</button>
Scoping problems. In JavaScript, when you define a variable within a scope, that variable can never be accessed from outside that very scope. Meaning defining a variable inside a function (like in your case) will not make it available in another completely separate function (unless you pass it as a parameter in some way). I'd recommend researching a bit more about JavaScript scopes to get a better of idea of how it works.
All 3 issues have been fixed in a new pen I've created for you to take a look at: https://codepen.io/MMortaga/pen/PooNNYE?editors=1010
However you might need to play a bit more with your timer, so see if you can fix it :P
Take the time to review all the changes I've mentioned and if you still face any issues just comment below, I'd be glad to help.

Game loop appears to be breaking at the end of iterating through array. Uncaught TypeError

Morning all,
Definitely a novice question here, this is my first real JS project - so apologies in advance for the clunky code.
The following functions are being used to show the light sequence for a "simon" game. The code seems to work fine initially, as I've tested multiple lengths of array, however on exiting the loop I get the following error:
Uncaught TypeError: Cannot read property 'setAttribute' of null
at show (script.js:95)
at showLights (script.js:83)
at script.js:88
I've looked around a lot for fixes to this error, and the majority of feedback is that it's related to the DOM and a wrapper will fix. I've found that a wrapper doesn't resolve. Similarly, I can't see that it's an issue with the CSS or HTML as the functions work ok until exit.
The looping functions are copied below:
// iterates through simon.array then allows button press
function showLights(x) {
if (x >= simon.array.length) {
clearTimeout(timer);
show(x);
allowPress();
} else {
show(x);
var timer = setTimeout(function(){
showLights(x+1);
},500);
}
}
// adds then removes flash class to light pads.
function show(x){
var display = document.getElementById("light" + simon.array[x]);
display.setAttribute("class", "flasher");
setTimeout(function(){
display.setAttribute("class", "game-box");
},500);
}
Apologies in advance for any errors or faux pas in posting this. I strongly suspect that I'll be kicking myself when this is fixed.
Kind Regards
Andy
The issue is related to you checking the length of an array, then trying to use an element of that array that does not exist. You are possibly also trying to set an attribute to an element that does not exist.
At a guess, this is the real cause of the issue:
if (x >= simon.array.length) {
clearTimeout(timer);
show(x);
allowPress();
Simply removing show(x) should help. The reason is you are checking for the length of simon.array, then later in function show(x) you make a request for simon.array[x], but that is not going to find anything, as x is greater than the length of that array.
The other possible issue is in the following chunk, but could be solved a number of ways. One way is to check x before passing. Another is making sure the element (display) is not null before setting the attribute.
// adds then removes flash class to light pads.
function show(x){
var display = document.getElementById("light" + simon.array[x]);
display.setAttribute("class", "flasher");
setTimeout(function(){
display.setAttribute("class", "game-box");
},500);
}
My suggestion would be as follows:
// adds then removes flash class to light pads.
function show(x){
var display = document.getElementById("light" + simon.array[x]);
if (display) {
display.setAttribute("class", "flasher");
setTimeout(function(){
display.setAttribute("class", "game-box");
},500);
}
}
You may want to check out classList as well as an alternative to setAttribute.
Something else to consider instead of using setTimeout would be to use a CSS animation.

Javascript code causing IE freeze

I have the below code causing Internet Explorer to freeze. It's a project that involves processing student grades as an assignment:
var array1 = StudentGradeAreadHugeList();
var nextArrayItem = function() {
var grade = array1.pop();
if (grade) {
nextArrayItem();
}
};
i hope you can help me with this.
You could show more info about the application you're trying to do. But I believe it's a matter of stack overflow (maybe you're using a big list). So, to overcome that you should modify the "nextArrayItem":
window.setTimeout (nextArrayItem, 0)
The freeze incurring mainly from the big data, but now the Event Loop will handle the Recursion process and not your Call Stack.
This is likely caused by an endless recursion. Be aware of proper handling of return values in IE:
var array1 = StudentGradeAreadHugeList();
var nextArrayItem = function() {
var grade = array1.pop();
if ( grade !== null && typeof(grade) !== "undefined" ) {
nextArrayItem();
}
};
pop() on an empty array will not return boolean false but a typeless "undefined".
There's two problems here:
You might be exceeding the call stack limit
Your if-conditional is set-up incorrectly
For the first issue:
As one of the previous responders mentioned, if you have a very large list you can exceed the limit of the call stack since you need to do a recursive call for each element. While doing setTimeout might work, it feels like a hack-y solution. I think the real issue is that your function is handling the array recursively rather than iteratively. I would recommend re-writing your function using a for-loop.
For the second issue:
Let's say in this case your array was set to [100, 90, 80]. When you invoke nextArrayItem() it will work properly the first two time, but the third time you call nextArrayItem() you are popping off the last remaining item (in this case 100) and your grade will be set to 100 which is a truthy value. Therefore, your if-conditional will pass and your function erroneously try to invoke itself again despite the fact that your array is now empty and the program should now exit the call stack.
I tried testing your code using my example in Chrome and what happens is that it will recurse one too many times and invoke pop on an empty array, which will return undefined.
You can fix this issue by changing the if conditional to check for the last element in the array after you have popped the array.
See revised code:
var nextArrayItem = function() {
var grade = array1.pop();
if (array1[array1.length-1]) {
nextArrayItem();
}
};

What is the initial value of an initialized Array in Javascript on different systems?

I've been struggling for months with a JavaScript problem where I have an array with a few properties, and later some of these properties are checked to decide whether or not to show a message to the user.
Now this all goes well on most systems (especially more recent browsers) but not so much on some of my client's IE7 computers.
Now I just found out that somewhere in my code I initialize a new Array like below, but never actually set the value for 'done'
var qar=new Array('question_no','pos','done');
qar['question_no'] = 1234;
qar['pos'] = 1234; //dont mind these numbers
Later in some for loop I check:
//check if this question was already shown
if(qar['done'])
continue; //stop here, don't show message
//set done to true, so that this question will not be shown again
qar['done'] = true;
window.alert('messaged!');
Again, what goes wrong is that sometimes (actually pretty often, but not always) the message is not shown at all in IE7.
Now for my question to you: I know that qar['done'] should be undefined right after initialization, which makes my code work fine (in Chrome etc), but could it be that somehow in IE7 this situation is handled differently? For example that qar['done'] is not undefined, but some random value and therefore is sometimes considered true accidentally? Or is that a stupid thing to think?
If this is not the problem, then I don't know what is..
Thanks in advance!
By doing this:
var qar=new Array('question_no','pos','done');
You are just creating array with indexes.
qar[0] will be 'question_no'
qar[1] will be 'pos'
qar[2] will be 'done'
in this case, qas['done'] will always be undefined.
Thats why its causing problems. You should either use javascript object instead of using an array.
But you can do something like this:
if(typeof qar['done'] === 'undefined'){
qar['done'] = true;
alert('messaged!');
}
Your code should be like this:
var qar={};
qar['question_no'] = 1234;
qar['pos'] = 1234; //dont mind these numbers
//check if this question was already shown
if(!qar['done']) {
//set done to true, so that this question will not be shown again
qar['done'] = true;
window.alert('messaged!');
}

Trying to number objects in jQuery

I'm trying to number objects, which can be added to a cart with drag'n'drop. So, this snippet should check the current number written in span.amountVal, and easily add ´+1´ to this number, but the result is always ´1´. When I uncomment the ´alert(i++);´, the snippet work like I want to. I'm confused, what is this about?
$.favList.find("div[data-asset-id="+ _itemID +"]").each(function() {
var i = $(this).find("span.amountVal").text();
// alert(i++);
$(this).find("span.amountVal").text(i++);
});
Thank you.
i++ first returns the value of i, then increments it. When you have the alert( i++ ) in place, the variable is already once incremented.
Put the ++ in front of the variable:
$(this).find("span.amountVal").text( ++i );
Or simply add one to it since you're discarding the variable right after:
$(this).find("span.amountVal").text( i + 1 );
you have a pre-increment/post-increment issue, the following change should solve it:
$.favList.find("div[data-asset-id="+ _itemID +"]").each(function() {
var i = $(this).find("span.amountVal").text();
$(this).find("span.amountVal").text(++i);
});
Pre-Increment adds one to i and then returns i while Post-Increment adds 1 to i after it has been returned.
Below is a similar post on StackOverflow touching on the topic:
post increment vs pre increment - Javascript Optimization
What are you guys doing? It SHOULDN'T read a SPAN's value, it's bad practice. Instead, it should read the items length (inside an object, for example) and then display it.

Categories

Resources