How can I iterate through a function with for loop? - javascript

I want to pass the 'y' variable to okayid but there seems to be a problem with the looping. The loop works fine with the first call of 'y' on okay.item(y) but it is not looping through okayid.item(y). It seemed to me like it was a scope problem but I am not sure.
var okay = document.getElementsByClassName("Okay");
var okayid = document.getElementsByClassName("OkayID");
var numberOkays = okay.length;
for(y = 0; y <= numberOkays; y++){
okay.item(y).onclick = function(){
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
alert('vote Sent to picture with id = ' + okayid.item(y).innerHTML);
}
};
xmlhttp.open("GET", "ajax/vote.php", true);
xmlhttp.send();
};
}
Here is the html ...
<a class="Link1A Okay" href="#"><span class="OkayID">[id]</span><div class="Vote1A">Okay</div></a>

You've got lots if issues.
in the for loop, you don't init y with var which could cause problems, as now y is part of the global scope.
in the for loop, you have y <= numberOkays which will cause an empty element to be retrieved at the end since numberOkays is the result of the array's length. So you'd get okay[y] is undefined at the end.
You don't need to retrieve the okays at the onset, you can just get the appropriate element in the onclick event.
After the loops are done y will be at the last index, so when the click event is fired you'd always get the last element when you refer to the Okay[y] (or in your case you'll just get undefined because of problem 2). Using this will refer to the element clicked which effectively what you intended with Okay[y].
Here's an updated version of your code, with a link to a working jsFiddle below:
var okay = document.getElementsByClassName("Okay");
for(var y = 0; y < okay.length; y++){
okay[y].onclick = function(){
idElem = this.getElementsByClassName("OkayID")[0];
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
alert('vote Sent to picture with id = ' + idElem.innerHTML);
}
};
xmlhttp.open("GET", "ajax/vote.php", true);
xmlhttp.send();
};
}
jsFiddle

Related

Save the current value and compare it with the new value of a variable in JavaScript

I came through an api that gives me information in json format, received the price of a currency and displayed it on a screen using JavaScript. And of course I put these in a function that ajax updates the information every x seconds.
I need a code that takes the current value of the price, the next value of the price received compares these two, and if the new price is higher than the previous one, for example, the background turns green or gives an alert. And if it was less than the previous one, the background would turn red.
my code:
var auto_refresh = setInterval(
function() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
document.getElementById("bids1").innerHTML = myObj.BTCUSDT['bids']['0']['0'];
}
};
xmlhttp.open("GET", "all.json", true);
xmlhttp.send();
}, 1000);
Don't use interval on Ajax
let val = 0;
const bids = document.getElementById("bids1");
function getData() {
fetch('all.json')
.then(response => response.json())
.then(data => {
const newVal = myObj.BTCUSDT['bids']['0']['0'];
bids.innerHTML = newVal
bids.classList.toggle("green",val > newVal)
bids.classList.toggle("red",val < newVal)
val = newVal;
setTimeout(getData,1000)
})
}
getData()
Correction
Please refer to mplungjan's answer above for a more correct way to do this. While adding the variable as I specified is a good way to handle this, your existing way to periodically retrieve the data is not the correct way to do it, and you should consider changing it as specified by mplungjan!
Original answer
I would normally recommend using a global variable (or at least outside your function) to keep the current price, and compare the retrieved value to this.
// initialize the current price
let currentPrice = 0;
var auto_refresh = setInterval(function () {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
let newPrice = myObj.BTCUSDT['bids']['0']['0'];
if (newPrice > currentPrice) {
// alert, set some other attribute, etc.
}
// update the global variable and the HTML
currentPrice = newPrice;
document.getElementById("bids1").innerHTML = currentPrice;
}
};
xmlhttp.open("GET", "all.json", true);
xmlhttp.send();
}, 1000);
Depending on your requirements, you can of course also do different checks and comparisons inside your http request handler.

JS: problem with for loop (only one image is shown)

I am completely new to javascript and web development.
I'm having a problem with the for loop; what happens to me is that the ids come back to me all together and not individually in order to retrieve the relative image and title through the id, so I can't recover images and title from the json array.
Specifically I get the error:
Uncaught TypeError: Cannot read properties of undefined (reading 'immagine') at XMLHttpRequest.xmlhttp.onreadystatechange
Warning: I have no problems in how to retrieve items in a json array because I know how to do it very well
This is my code:
//here I get all the articles, so my json array
var xmlhttp = new XMLHttpRequest();
var url = "https://wjko5u1234.execute-api.us-east-2.amazonaws.com/articles";
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var allart = JSON.parse(this.responseText);
var container=document.getElementById("slideshow")
for(var i = 0; i < allart.Items.length; i++)
{
container.innerHTML += '<div class="slideshow-container"></div>';
document.getElementById("id").innerHTML += "<br/>" + allart.Items[i].id;
myFunction1(allart.Items[i].id);
}
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
//here I pass the id via function call, and for each id I want to retrieve image and title which has that specific id only i get the set of ids without having one at a time to retrieve what i need
function myFunction1(id) {
var xmlhttp = new XMLHttpRequest();
var url = "https://wjko5u1234.execute-api.us-east-2.amazonaws.com/articles/"+id;
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myArr = JSON.parse(this.responseText);
console.log(myArr);
document.getElementById("img1").src="articoli_img/"+myArr.Item.immagine;
document.getElementById("title1").innerHTML = myArr.Item.titolo;
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
I would be very thankful for any help.
It seems that "Item" prop doesn't exist in returned object (located in myFunction1()) (did you mean to write myArr.immagine?)
Since you are new: I recommend to use for-each loops in collections, by using:
for(let item of allart.Items) {
.....
}

How to subset specific object properly in JS

I'm currently doing some practice and i want to print the titles of each movie on this api:
https://jsonmock.hackerrank.com/api/movies?Year=1998
Basically, I want each title to be printed for the first page (or preferably a specific page).
This is the code I have:
<script>
function printTItles(year) {
var res;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.responseText);
for(var i=0;i<res.per_page;i++){
document.getElementById("demo").innerHTML = res.data.i.Title;
}
};
}
xmlhttp.open("GET", "https://jsonmock.hackerrank.com/api/movies?Year=<year>", true);
xmlhttp.send();
}
</script>
I know the problem is in res.data.i.title but I'm not sure how to fix it.
You are trying to access the element at the index i in your loop, like you would access a property of an object. To get the element at position i in your res.data array, you need the square bracket access [ ]
Also, you are not replacing the year parameters in your request for the year parameters passed to your function. You might want to check that out.
Here I have use the year 2018 as an example.
function printTItles(year) {
var res;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.responseText);
for(var i=0;i<res.per_page;i++){
document.getElementById("demo").innerHTML = res.data[i].Title;
}
};
}
xmlhttp.open("GET", "https://jsonmock.hackerrank.com/api/movies?Year=2018", true);
xmlhttp.send();
}
printTItles();
<div id="demo"></div>
You could add some more improvement. For example, at each iteration, you are replacing the content of your #demo element. This cause only the last title to be shown. You could, instead, append the data to the already existing html of the div. Or, like I did in this case, build your string before setting it as the new innerHTML value.
function printTItles(year) {
var res;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.responseText);
var output = "";
for(var i=0;i<res.per_page;i++){
if(res.data[i]) {
output += res.data[i].Title + '<br />';
}
}
document.getElementById("demo").innerHTML = output;
};
}
xmlhttp.open("GET", "https://jsonmock.hackerrank.com/api/movies?Year=2018", true);
xmlhttp.send();
}
printTItles();
<div id="demo"></div>
I've also added a condition to check if there is an element at res.data[i].

Why closures are needed here for calling a XMLHttpRequest function in loops?

I am pretty new to this site. I have a question when working on a XMLHttpRequest which is replicated in a for loop as following:
I don't understand the difference between the following two blocks of code:
function changeForm(i) {
if (selection[i-1] != 0) {
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("box"+i).innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("POST", "fetchLineChoice_addData.php", true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("index="+i+"&lc="+selection[i-1]);
} else {
document.getElementById("box"+i).innerHTML = "";
}
}
for (var i = 1 ; i < 4 ; i++) {
changeForm(i);
}
AND
for (var i = 1 ; i < 4 ; i++) {
if (selection[i-1] != 0) {
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("box"+i).innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("POST", "fetchLineChoice_addData.php", true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("index="+i+"&lc="+selection[i-1]);
} else {
document.getElementById("box"+i).innerHTML = "";
}
}
I don't really know why the first one works but the second one does not. I have tried to search on the net about closures and came up with these two:
Calling a XMLHttpRequest continuously
JavaScript closure inside loops – simple practical example
From the second question, it was mentioned that the function is bound to a variable i outside the function. I would like to know for the second block of code (that does not work), I would like to know why the content in the for loop is not fully executed before the value of i increases again? What is the flow when the two blocks of code are being executed?
Thank you very much!
The first one works because the value of "i" does not get written over. It is "closed over" and remains the same throughout the execution.
In the second example, the iteration spawns XMLHttpRequest, but the global value of "i" changes. By the time the request is complete, it is no longer pointing to the value of "i" you are expecting.

How to use Get to parse multiple JSON files?

I'm having some trouble parsing more than one JSON file at a time.
Basically, I have a web form with checkboxes that control which polygons to draw on a Google Map.
Depending what the user selects, that determines which JSON files (and geo coordinates) to get and parse. The script below works except for the last step - it always only returns the very last JSON file regardless how many are selected.
This is my first post to Stackoverflow and I'm new to JS, so any suggestions or different ways to approach this problem would be appreciated!
var xmlhttp = new XMLHttpRequest(); //
xmlhttp.onreadystatechange = function() { //parse json file
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
console.log(myArr);
}
}
function goCheck() {
var input = document.getElementsByTagName('input');
var checkboxCount = 0;
var selections = [];
var urlArray = [];
for (var i=0, length = input.length; i<length; i++) {
if (input[i].checked === true) {
j = input[i].value;
selections.push(j); // store values for checkbox selections in array
checkboxCount++; // keep track how many were checked
var url = "https://mywebsite.ca/" + j + ".txt";
urlArray.push(url); // store urls in array
}
}
console.log(checkboxCount); // number of boxes checked
console.log(selections); // array with the selection values
console.log(urlArray); // an array with the json urls
// 2nd Loop - iterate over URL array and call function to get json object
for (var i=0, length = urlArray.length; i<length; i++) {
console.log(urlArray[i]);// check that loop is working
xmlhttp.open("GET", urlArray[i], true);
xmlhttp.send();
}}
You are reassigning what xmlhttp is doing each time. Create a new var each time and assign the state change handler to it and it should work. E.g.
for (var i=0, length = urlArray.length; i<length; i++) {
console.log(urlArray[i]);// check that loop is working
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() { //parse json file
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
console.log(myArr);
}
};
xmlhttp.open("GET", urlArray[i], true);
xmlhttp.send();
}}
When you recall open on the same XMLHttpRequest you are abandoning the last request, but if you create a new one each time, they will each handle their own requests.
Aside, if you have control over the server side, a server method that takes in an array of files to get and returns a json array in a single AJAX call seems like the way to go long term.
You need to have a new XMLHttpRequest for each file. Replace your last loop with:
var xmlhttp;
for (var i=0, length = urlArray.length; i<length; i++) {
xmlhttp = new XMLHttpRequest(); //
xmlhttp.onreadystatechange = function() { //parse json file
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
console.log(myArr);
}
}
console.log(urlArray[i]);// check that loop is working
xmlhttp.open("GET", urlArray[i], true);
xmlhttp.send();
}}

Categories

Resources