How can we increment variables declared in scriptlet inside javascript - javascript

I want to display an element of the list, but I have a problem with the incrementation of list counter. it inrements only one time.
here is my function code in javascript
var element= document.getElementById("question");
timeTotal =timeTotal -1;
var nextQuestNumber = <%=k%>;
var nbQuestion = <%=iter%>;
if (timeTotal <= 0 && nextQuestNumber>0 && nextQuestNumber<nbQuestion)
{
timeTotal=<%=a%>;
element.innerHTML = '<c:out value="<%=listQuestions.get(k).getQuestion()%>"/>';
<%=k++%>;
}
setTimeout("listIter()", 1000);
k is the counter initialized to zero, iter is the list size, and timeTotal is the variable decrimenting the total time (one minute).
So each minute i want to get the next element of list and display it.
So to load this function I did this:
<body onload="listIter()">
And to repeate this function each second i did this inside the function:
setTimeout("listIter()", 1000);
But unfortunately, this not work for me.
Could you help me on that please and tell m

You can't do this directly.
Either pass the whole list to the client side code first then have k client side and read the proper item from the client side array, or use AJAX to read the proper item from the server.
In addition, you don't have any stop condition so your function will keep running endlessly which isn't a good practice. When you are finished, don't call the function again.

The jsp expressions like <% .. %> or <c:out .. /> are evaluated on server side while your javascript code runs on client side. You should check the javascript code in your browser to see what is rendered server side.

Following issues in the program:
setTimeout("listIter()", 1000);
to
setTimeout(listIter, 1000);
and
<%=k++%>;
to
nextQuestNumber++;
and
timeTotal=<%=a%>;
receive it in some other varible in the program as it is getting reset in every run.

Related

How does this interesting piece of JavaScript code work?

A friend of mine brought to my attention a piece of JavaScript code that gives you unrealistic time scores on the flashcard website Quizlet's match game. It somehow stops the game's timer at the user specified time.
document.getElementsByClassName("UIButton UIButton--hero")[0].click();
setTimeout(function(){for(var F = setTimeout(";"), i = 0; i < F; i++) clearTimeout(i)}, 5100); //Change 5100
Using it is simple, you get on the match game (for example https://quizlet.com/187478162/match) and you simply enter this code in the console in the inspect menu. You then need to complete the game but it doesn't matter how long you take.
I don't know JavaScript (I am very knowledgeable with Python) but I have figured out so far that the first line clicks the start button and the first setTimeout function waits until the specified time to execute the function inside of it. It is the function inside that confuses me. It seems to just create and clear a bunch of Timeouts. I have no Idea how this stops the game timer though.
If someone could explain how it works that would be very much appreciated
Ah, that's a very interesting piece of code, very clever. Here's what's happening.
The inner function basically has the following (expanded for readability):
var F = setTimeout(";")
for(i = 0; i < F; i++) clearTimeout(i)
setTimeout can accept functions or strings that get evaluated after a timeout. They're just passing in the no-op ';', and they're not even passing in a delay. What they care about is the timer-id "F". If you go to the dev-tools (on a non-busy page), and put setTimeout(';') in the console, you'll see that it'll first return the id 0, then 1, then 2, and so on. The ids counts up.
So, you can imagine this timeline:
Random background stuff happens
The webpage starts a timeout with setTimeout, that has, lets say, id 7.
More background stuff
This script executes. It creates a timeout, and gets back an id that's going to be bigger than any timeouts made in the past. Lets say that id is 9.
Now the script goes through all ids from 0 to 9, stopping any active timeouts by passing in the id to clearTimeout. This includes clearing the timeout for id 7.
Before I get to the answer part, you should know a couple of things about setTimeout( ):
The setTimeout( ) function, can accept a callback function as it's first parameter, or, it can also accept code in a 'string'.
Whenever the setTimeout( ) function is called, it returns a timeout id which can be used in order to pass into the clearTimeout( ) function when you want to clear a particular timeout.
Now, please run the below code snippet and see what happens:
a) In the very first setTimeout call, I'm passing a callback function, storing the returned id in the const variable 'id1'.
b) In the second setTimeout call, I'm passing a code string, storing the returned id in a const variable 'id2'.
const id1 = setTimeout(() => console.log('setTimeout with callback fn'), 1000, '_');
const id2 = setTimeout('console.log("setTimeout with code string")', 2000);
console.log('id from 1st setTimeout( ) is :', id1);
console.log('id from 2nd setTimeout( ) is :', id2);
Both the setTimeout calls work without an issue, but the more interesting thing is when you look at the 'id' values for both function, for the first call the id is '1', for the second call the id is '2'.
This means two things: One these IDs are unique and secondly, these IDs are in the same ID pool, think of it like an ID list or an array where for each setTimeout call, a new ID is created by incrementing over the last existing setTimeout ID from the ID Pool.
Now, let's look at the code in question:
In the first line of code, the getElementsByClassName returns a nodelist of all the elements with the class passed in, and with the click( ), you are just simulating a buttonclick for the 0th element from the nodelist that is returned. You can use other functions like querySelector('UIButton UIButton--hero') or querySelecorAll('UIButton UIButton--hero') in this case and it will not make a difference in the way this works.
document.getElementsByClassName("UIButton UIButton--hero")[0].click();
Now, when we look at the below setTimeout( ) function calls with the knowledge we have about how the setTimeout function and setTimeout IDs work, it will be way easier to understand how it stops the actual timer:
setTimeout(function () {
for (var F = setTimeout("console.log(';')"), i = 0; i < F; i++)
clearTimeout(i);
}, 5100); //Change 5100
We are making an outer setTimeout call which takes in a callback function, and the timer for this setTimeout is set to '5100' milliseconds, which is basically a 5 second timer.
Looking at the callback function itself:
function () {
for (var F = setTimeout("console.log(';')"), i = 0; i < F; i++)
clearTimeout(i);
}
This callback function, runs a for loop, in the initialization block of this for loop, two variables are initialized, 'F' and 'i', value of 'F' is the ID returned by the current setTimeout( ) function, 'i' is set to 0.
Now from what we know from the code snippet I posted above is that the ID pool for all the IDs is the same, which means the ID 'F' is definitely going to be greater the setTimeout ID of the original timer that is present on the webpage.
Answer & Conclusion:
Now the loop itself iterates basing on the value of 'i', as long as it is less than 'F', and it clears the interval using clearInterval(i) for each value of i from 0 to F, which means it stops all timers on the page from ID = 0 to ID = 'F'.
And that is the reason this code can be used in order to exploit the website and stop it's timer so users can cheat and complete the quiz. Please let me know if you have any further queries.

saving current value of a variable on page reload in JAVASCRIPT

Is there a way to keep a variable value on page refresh, if I have
var x=0;
but then a users does something that makes that value become
x=4;
and then the page is refreshed, is there a way to keep that value of 4 for the x variable or it will always reset to the original value?
I have written 2 functions to set and get the value like this:
function SetlifeCounter()
{
life = 3;
localStorage.setItem("life", life);
}
function GetlifeCounter()
{
life1 = localStorage.getItem("life");
life1=life1-1;
return life1;
}
And then calling them this way:
var mainLife;
SetlifeCounter();
mainLife=GetlifeCounter();
while(mainLife!=0)
{
window.location.reload();
}
But when I run this the page freezes...
What m I doing wrong??
P.S this is to keep track of the no. of lives in a game every time you die(page reloads) in the game life gets deducted.
Yes, use localStorage.
When using persisted values, you'll need to check to see if a value was already saved (from the user's previous visit) and, if so, use that. If not, you'll need to create a value and set it into storage so that it can be used on a subsequent visit.
This is generally done like this:
var x = null;
// Check to see if there is already a value in localStorage
if(localStorage.getItem("x")){
// Value exists. Get it assign it:
x = localStorage.getItem("x");
} else {
// Value doesn't exist. Set it locally and store it for future visits
x = 3.14;
x = Math.floor(x);
localStorage.setItem("x", x);
}
In your example, you have a variety of issues, but the browser locking up was due to the while loop, which was creating an infinite loop whenever the life count was not zero. You must be VERY careful with while loops and ensure that they will always have a termination condition that will be hit. But, for your purposes, this was unnecessary anyway.
See comments inline below for details on the correct usage of localStorage.
NOTE: This code won't work here in the Stack Overflow code snippet editor due to sandboxing, but you can see this working example here.
// This is where you will store the lives remaining
// You don't need several variables to keep track of this
// (mainLife, life, life1). Just modify this one variable as needed.
var lifeCount = null;
// As soon as the user arrives at the page, get or set the life count
window.addEventListener("DOMContentLoaded", initLifeCount);
// By convention use camelCase for identifier names that aren't constructors
// and put opening curly brace on same line as declaration
function initLifeCount() {
// You need to test to see if an item exists in localStorage before getting it
if(localStorage.getItem("life")){
// And, remember that localStorage values are stored as strings, so you must
// convert them to numbers before doing math with them.
lifeCount = parseInt(localStorage.getItem("life"), 10) - 1;
// Test to see if there are any lives left
if(lifeCount === 0){
// Invoke "Game Over" code
alert("Game Over!");
}
} else {
// User hasn't previously stored a count, so they must be starting a new game
lifeCount = 3;
}
// Any time the count changes, remember to update it in localStorage
updateLifeCount();
// Temporary code for debugging:
console.log("Life count is: " + lifeCount);
}
// Call this function after the life count changes during game play
function updateLifeCount(){
localStorage.setItem("life", lifeCount)
}
If you open your developer tools (F12) and navigate to view the localStorage, you will be able to see the value decrease every time you re-run the Fiddle. You can also see the value in the console.
Many. You can choose between cookies, local storage, web sql, remote backend...
See this question about setting the value inside a cookie:
Set cookie and get cookie with JavaScript
For local storage, use:
localStorage.setItem("x", x);

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

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 !

JavaScript: Set Variable

I'm using http://fakeapp.com to run some browser automation tasks and am running into a bit of a roadblock with parsing in a variable to the URL string. This question is more about JavaScript loops than FakeApp (but just so question has some context). Here's what I have so far:
var idx = fake.loop.index;
fake.set('idx', idx);
console.log('idx: ' + idx)
What I need to do is just set the starting variable at let's say 500. Right now the repeatable action (this part is done in FakeApp) starts at 0 -- I need to start the index at a specific number and increment by one. Thanks!

slide a div using javascript

I wanted to write a javascript code that will slide a div in specific direction, distance and in some given time. I wrote this small script. but doesn't work at all. Instead browser gets slow. No change in position is visible.
Can someone tell me how to achieve the result ? I know there are many ready made libraries that can do this easily. But I just wanted to give it a try.
<script type="text/javascript" language="javascript">
var element = '';
var slidePerMS = '';
function slideIt(ele, direction, distance, slideDuration){
element = ele;
var i=0;
slidePerMS = distance / (slideDuration*1000);
for(i=0; i<3000; i++){
setTimeout("changePosition()",1);
}
}
function changePosition(){
var currElement = document.getElementById(element);
currElement.style.left = "'"+slidePerMS+"px'";
}
</script>
SOO many things wrong with that code it's not even funny... Let's see...
You are trying to render a 1,000 FPS animation. This is simply impossible for a browser.
You are passing a string as parameter to setTimeout, which is as evil as eval.
You set slidePerMS once but never change it after, resulting in the div being moved to the exact same spot over and over.
You are setting the style with extra quotes inside - do you put quotes in a CSS file?
That's to name but a few. Try this instead:
<script type="text/javascript" language="javascript">
function slideIt(elem, direction, distance, slideDuration){
var elmt = document.getElementById(elem),
i=0, step = distance / (slideDuration*20),
stepper = setInterval(function() {
i = Math.min(distance,i+step);
elmt.style.left = i+'px';
if( i == distance) clearInterval(stepper);
},50);
}
</script>
You have many problems.
You are treating setTimeout as if it was sleep. Don't do that. It isn't like sleep at all, it runs a function after a given period of time, but doesn't pause the execution of anything else.
This means you just hammer the function repeatedly 3000 times, which is what is locking up the browser.
Instead of using a for loop, you should be using setInterval.
Don't pass a string to setInterval (or setTimeout), it gets evaled, which is slow and hard to debug, and it breaks scope. Pass a function instead.
Inside changePosition you are trying to use a variable called slidePerMS, which is undefined because it is defined in the scope of slideIt.
You are also trying to set left to "'123px'". You can't quote your values in CSS.
Get rid of both the 's.
This is why you can't see any change. Invalid values are ignored in CSS.

Categories

Resources