XHR Response with For-Loop not working - javascript

I have this issue with my XMLHttpRequest that I'm making. The idea is that the loop is mean to loop through a JSON array of users and also load their profile image. Loading the users works absolutely fine but when I loop to get the profile image, it shows it with the last user.
I can see where the issue lies but I don't know how to solve it. When I debug this, it does not run the xhr[i].onload part, which is important because I'm trying to append the image found to the id of the user as the loop runs. The first part of the loop will create the 'img id ="username"' for the username and then i want the XHR request to run and get the image and then append it to the 'img id' tag.
function parseJSON() {
console.log(jsonArrayOfUsers);
var htmlStart = '<ul class ="softwares">';
var htmlEnd = '</ul>'
var html = ''
var len = jsonArrayOfUsers.length;
for (var i = 0; i < len; i++) {
var xhr = [];
currentuser = jsonArrayOfUsers[i].username;
currentavatar = jsonArrayOfUsers[i].avatar
console.log(currentuser);
html += '<li class ="softwares">'
+ '<p><img id ="' + jsonArrayOfUsers[i].username + '" width="auto" height="100px"/></p>'
+ '<p>' + jsonArrayOfUsers[i].fullName + '</p>'
+ '<p>' + jsonArrayOfUsers[i].username + '</p>'
+ '<p>' + jsonArrayOfUsers[i].university + '</p>'
+ '<p>' + jsonArrayOfUsers[i].userType + '</p></li>';
(function (i){
if (jsonArrayOfUsers[i].avatar == null){}
else{
xhr[i] = new XMLHttpRequest();
xhr[i].open("GET", "URL TO API" + jsonArrayOfUsers[i].avatar, true);
xhr[i].setRequestHeader("Authorization", localStorage.token);
xhr[i].responseType = 'blob';
xhr[i].onload = function response(e) {
var urlCreator = window.URL || window.webkitURL;
imageUrl = urlCreator.createObjectURL(this.response);
document.querySelector("#" + currentuser).src = imageUrl;
};
xhr[i].send();
}})(i);
}
var htmlFull = htmlStart + html + htmlEnd
$('.people').append(htmlFull);

The way you are appending insecure text into html is bad...
I would have solved it this way using a simple forEach loop instead of a for loop
function parseJSON() {
var list = $('<ul class="softwares">');
var url = window.URL || window.webkitURL;
jsonArrayOfUsers.forEach(function(user) {
var currentuser = user.username;
var currentavatar = user.avatar;
console.log(currentuser);
var img = $('<img>', {
id: user.username,
width: 'auto',
height: '100px'
})[0];
$('<li class ="softwares">').append(
$('<p>').append(img),
$('<p>', {text: user.fullName}),
$('<p>', {text: user.username}),
$('<p>', {text: user.university}),
$('<p>', {text: user.userType})
).appendTo(list)
if (jsonArrayOfUsers[i].avatar == null) {
} else {
var xhr = new XMLHttpRequest();
xhr.open("GET", "URL TO API" + user.avatar);
xhr.setRequestHeader("Authorization", localStorage.token);
xhr.responseType = 'blob';
xhr.onload = function response(e) {
img.onload = function() {
url.revokeObjectURL(this.src);
}
img.src = url.createObjectURL(xhr.response);
};
xhr.send();
}
})
$('.people').append(list);
}

Related

'object HTMLCollection' instead of Image URL from RSS

I'm trying to pull thumbnail URLs from a wordpress feed and keep getting [object HTMLCollection] instead of an image URL string for the thumbnail. The feed i'm pulling from is: https://harpercollegece.com/feed/. I know that the tag is named media:thumbnail and the value is stored in 'URL'. I can't find the correct way to reference this image inside of the forEach loop when running through each post. I've tried searching other posts as well as on google for several hours.
var proxy = 'https://api.allorigins.win/raw?url=';
var feeds = [
'https://harpercollegece.com/feed/',
];
var limit = 10;
var forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
};
function strip_tags(string) {
if ((string === null) || (string === '')) {
return '';
} else {
string = string.toString();
}
string = string.replace('<![CDATA[', '');
string = string.replace(' […]]]>', '');
string = string.replace(/<[^>]*>/g, '');
string = string.replace(/<[^>]*>/g, '');
string = string.replace(']]>', '');
return string;
}
function get_rss(url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) {
return;
}
if (xhr.status >= 200 && xhr.status < 300) {
var response = xhr.responseText;
var parser = new window.DOMParser();
var data = parser.parseFromString(response, "text/xml");
var items = Array.from(data.querySelectorAll("item"));
var output = '';
forEach(items, function(index, item) {
if (index <= limit) {
var ilink = item.querySelector("link").innerHTML;
var title = item.querySelector("title").innerHTML;
var descr = item.querySelector("description").innerHTML;
var thumb = item.getElementsByTagName("media:thumbnail");
//console.log(item);
output +=
'<div class="ce-blog-slider-well">' +
'<div class = "ce-blog-thumb">' +
'<img class="blog-post-img" src="' + thumb + '" alt="Veterans Center Sign">' +
'</div>' +
'<div class = "ce-blog-header">' +
'' + strip_tags(title) + '' +
'</div>' +
'<div class ="ce-blog-descr">' + strip_tags(descr) + '</div>' +
'</div>';
}
});
var d1 = document.getElementById('wp-blog-posts');
d1.insertAdjacentHTML("beforeend", output);
}
};
xhr.open('GET', url);
xhr.send();
}
forEach(feeds, function(index, feed) {
get_rss(proxy + encodeURIComponent(feed));
});
<div class="ce-blog-slider" id="wp-blog-posts"></div>
getElementsByTagName returns an HTMLCollection. To get the URL, you'll have to grab the first element in that collection with [0]. The URL is stored in an attribute called url, a la
<media:thumbnail url="https://harpercollegece.files.wordpress.com/2021/01/writing-red-typewriter-typing.jpg" />
From your HTMLElement, get the url attribute like so:
var thumb = item.getElementsByTagName("media:thumbnail")[0].getAttribute("url");
var proxy = 'https://api.allorigins.win/raw?url=';
var feeds = [
'https://harpercollegece.com/feed/',
];
var limit = 10;
var forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
};
function strip_tags(string) {
if ((string === null) || (string === '')) {
return '';
} else {
string = string.toString();
}
string = string.replace('<![CDATA[', '');
string = string.replace(' […]]]>', '');
string = string.replace(/<[^>]*>/g, '');
string = string.replace(/<[^>]*>/g, '');
string = string.replace(']]>', '');
return string;
}
function get_rss(url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) {
return;
}
if (xhr.status >= 200 && xhr.status < 300) {
var response = xhr.responseText;
var parser = new window.DOMParser();
var data = parser.parseFromString(response, "text/xml");
var items = Array.from(data.querySelectorAll("item"));
var output = '';
forEach(items, function(index, item) {
if (index <= limit) {
var ilink = item.querySelector("link").innerHTML;
var title = item.querySelector("title").innerHTML;
var descr = item.querySelector("description").innerHTML;
var thumb = item.getElementsByTagName("media:thumbnail")[0].getAttribute("url");
//console.log(item);
output +=
'<div class="ce-blog-slider-well">' +
'<div class = "ce-blog-thumb">' +
'<img class="blog-post-img" src="' + thumb + '" alt="Veterans Center Sign">' +
'</div>' +
'<div class = "ce-blog-header">' +
'' + strip_tags(title) + '' +
'</div>' +
'<div class ="ce-blog-descr">' + strip_tags(descr) + '</div>' +
'</div>';
}
});
var d1 = document.getElementById('wp-blog-posts');
d1.insertAdjacentHTML("beforeend", output);
}
};
xhr.open('GET', url);
xhr.send();
}
forEach(feeds, function(index, feed) {
get_rss(proxy + encodeURIComponent(feed));
});
<div class="ce-blog-slider" id="wp-blog-posts"></div>

Optionlist built in Ajax returns null value

Im new to javascript. Im using Ajax to request endpoint information. Im dynamically building my optionlist based on results form the endpoint but I cannot get the select to work.
I want to get the value from the option list based on the value of the option but I only get ”TypeError: elSelectArtist is null”
var xhr = new XMLHttpRequest();
var eId;
xhr.onload = function() {
responseObject = JSON.parse(xhr.responseText);
// build dropdown
var artistName = '';
artistName += '<form name="jump" id="formArtist" class="center">' +
'<select id="artistList" name="menu">' +
'<option value="#">Choose Artist:</option>';
for (var i = 0; i < responseObject.length; i++) {
artistName += '<option value="'+ responseObject[i].id +'">' + responseObject[i].name + ' ';
artistName += ' ' + responseObject[i].surname + '</option>';
}
artistName += '</select></form></p>';
var elSelectArtist = document.getElementById('artistList');
elSelectArtist.addEventListener('change', function() {
alert(this.value);
eId = this.value;
}, false);
document.getElementById('artists').innerHTML = artistName;
};
xhr.open('GET', 'http://localhost:8080/api/artists', true);
xhr.send(null);
I did expect to get the value from the option list.
html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
Vilken artist:
<script src="js/artists.js"></script>
List of artists:
<div id="artists"></div>
</body>
</html>
var xhr = new XMLHttpRequest();
var eId;
xhr.onload = function() {
responseObject = JSON.parse(xhr.responseText);
// build dropdown
var artistName = '';
artistName += '<form name="jump" id="formArtist" class="center">' +
'<select id="artistList" name="menu">' +
'<option value="#">Choose Artist:</option>';
for (var i = 0; i < responseObject.length; i++) {
artistName += '<option value="'+ responseObject[i].id +'">' + responseObject[i].name + ' ';
artistName += ' ' + responseObject[i].surname + '</option>';
}
artistName += '</select></form></p>';
document.getElementById('artists').innerHTML = artistName; //changed position of this
var elSelectArtist = document.getElementById('artistList'); //and this
elSelectArtist.addEventListener('change', function() {
alert(this.value);
eId = this.value;
}, false);
};
xhr.open('GET', 'http://localhost:8080/api/artists', true);
xhr.send(null);
Your id="artistList" was still just a variable, if you add it to the DOM first, then reference it, then it works.

Previous data is lost because of new data

I am creating some html tag and assigning data as below.
MyCombo = function(args) {
var dataUrl = args.url;
var divID = args.divID;
var div = document.getElementById(divID);
var myTable = '<input type="text" id="myInput" list="myUL" onclick = "MyList()" onkeyup="MyList()" style="width:100% " >' +
'<ul id="myUL" hidden=false>' + '<li>' + '<a href="#" ></a>' + '</li>' + '</ul>';
div.innerHTML = myTable;
function getData(callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', dataUrl, true);
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === XMLHttpRequest.DONE && httpRequest.status === 200) {
callback(httpRequest.responseText);
}
};
httpRequest.send();
}
getData(function(data) {
var jsonc = JSON.parse(data);
var new_opt = "";
for (i = 0; i < jsonc.length; i++) {
new_opt += '<li>' + jsonc[i]['VALUE'] + '</li>';
}
document.getElementById('myUL').innerHTML = new_opt;
});
}
Now when I pass my second div, previous data is getting lost. And for first div I am getting second data.
This how I am calling the class :
For the first instance
var myCombo = new liveSearch({
"url": "data1.json",
"divID": "ID1",
});
For the second instance
var myCombo2 = new liveSearch({
"url": "data2.json",
"divID": "ID2",
});
Any idea how to overcome this?
In getData you call
document.getElementById('myUL').innerHTML = new_opt;
which writes to the element called myUL everytime it is called.
Append instead of replacing
document.getElementById('myUL').appendChild(new_opt);
or you can append to the old
old_html = document.getElementById('myUL').innerHTML;
document.getElementById('myUL').innerHTML = old_html+new_opt;

How to use <img src= > with Ajax call

I am trying to insert pictures to id "pokedex-view" by using Ajax GET. I think "spriteurl" is showing the correct path. But does not work correctly, and it cannot find the pciture for the local folder. Is there something wrong in this code. Thanks.
function populatePokedex() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://webster.cs.washington.edu/pokedex/pokedex.php?pokedex=all");
xhr.onload = function(){
if (this.status == 200) {
var picArr = this.responseText.split("\n");
for(var i=0; i < picArr.length; i++){
var eachName = picArr[i].split(":")
var spriteurl = "/Pokedex/sprites/" + eachName[1];
document.getElementById("pokedex-view").innerHTML += spriteurl
document.getElementById("pokedex-view").innerHTML += "<img src = spriteurl>";
}
} else {
document.getElementById("pokedex-view").innerHTML = "ERROR: Status: " + this.status + ", " + this.statusText;
}
}
xhr.onerror = function(){
document.getElementById("pokedex-view").innerHTML = "ERROR";
}
xhr.send();
}
Try to concatenate or to interpolate the way you assign the spriteurl as the src attribute:
document.getElementById("pokedex-view").innerHTML += '<img src="' + spriteurl + '">'
Or:
document.getElementById("pokedex-view").innerHTML += `<img src="${spriteurl}">`

Twitch TV API JSON Issue

I work with Twitch API. If the streamer streams I work with with property "Stream". But If he's not streaming, then I need refer to another link. Then I again turn to the function of the getJSON and pass there the necessary API link. And I'm working with her. However, the loop does not work as it should. It takes the last streamer out of the "channels" array, but it should all those who do not stream. I can not understand what the problem is. Help...
JSFiddle: https://jsfiddle.net/e7gLL25y/
JS Code:
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onload = function() {
if(xhr.readyState == 4 && xhr.status == "200") {
callback(JSON.parse(xhr.responseText));
}
};
xhr.send();
};
var channels = ["summit1g", "esl_RuHub_CSGO", "Starladder1", "Senpai_Frozen", "tehvivalazz", "ESL_CSGO"];
var client_id = "hx3dea4ifwensxffoe8iwvekwvksnx";
var section = document.getElementById("main-section");
var streamer = [];
for(var i = 0; i < channels.length; i++) {
var url_channels = "https://api.twitch.tv/kraken/channels/" + channels[i] + "?client_id=" + client_id;
var url_streams = "https://api.twitch.tv/kraken/streams/" + channels[i] + "?client_id=" + client_id;
getJSON(url_streams, function(response) {
if( response["stream"] !== null ) {
streamer[i] = document.createElement("div");
streamer[i].className = "streamer";
streamer[i].innerHTML = "<a target='_blank' href='" + response.stream.channel["url"] +
"'><img id='streamer-image' src='" +
response.stream.channel["logo"] +
"' alt='Av' /><h2 id='streamer-name'>" +
response.stream.channel["name"] +
"</h2><p id='stream-status'>" +
response.stream["game"] + "</p></a>";
section.appendChild(streamer[i]);
} else {
getJSON(url_channels, function(r) {
streamer[i] = document.createElement("div");
streamer[i].className = "streamer";
streamer[i].innerHTML = "<a target='_blank' href='" + r["url"] +
"'><img id='streamer-image' src='" +
r["logo"] +
"' alt='Av' /><h2 id='streamer-name'>" +
r["name"] +
"</h2><p id='stream-status'>Offline</p></a>";
section.appendChild(streamer[i]);
});
}
});
}
You are having a common misconception about JavaScript contexts.
Refer to my answer here to see details about this problem: https://stackoverflow.com/a/42283571/1525495
Simply, the getJSON response is called after all the array is looped, so i will be the last index in all the responses. You have to create another context to keep the i number so is not increased.
for(var i = 0; i < channels.length; i++) {
var url_channels = "https://api.twitch.tv/kraken/channels/" + channels[i] + "?client_id=" + client_id;
var url_streams = "https://api.twitch.tv/kraken/streams/" + channels[i] + "?client_id=" + client_id;
(function(i) {
// i will not be changed by the external loop as is in another context
getJSON(url_streams, function(response) {
// Thingy things...
});
})(i);
}

Categories