This is my code:
let info = document.getElementById('info');
let week = document.getElementById('week');
/*Initializer Function*/
window.addEventListener('load', () => {
let long;
let lat;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
long = position.coords.longitude;
lat = position.coords.latitude;
const proxy = 'https://cors-anywhere.herokuapp.com/';
const api = `${proxy}https://api.darksky.net/forecast/d571a1e2483b31605b94edaae84c647e/${lat},${long}`;
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
let obj = JSON.parse(this.responseText);
console.log(obj);
document.getElementById('temperature-degree').innerHTML = obj.currently.apparentTemperature;
document.getElementById('location').innerHTML = obj.timezone;
document.getElementById('temperature-description').innerHTML = obj.currently.summary;
setIcons(obj.currently.icon, document.getElementById('currentDayIcon'));
for (let i = 0; i < obj.hourly.data.length; i++) {
info.innerHTML += `<div id='hour${i + 1}' class='hourly'>` + `<canvas id='hourIcon${i + 1}'></canvas>` + `<h3 id='hourTemp${i + 1}'></h3>` + `<p id='hourSummary${i + 1}'></p>` + '</div>';
setIcons(obj.hourly.data[i].icon, document.getElementById(`hourIcon${i + 1}`));
document.getElementById(`hourTemp${i + 1}`).innerHTML = obj.hourly.data[i].temperature;
document.getElementById(`hourSummary${i + 1}`).innerHTML = obj.hourly.data[i].summary;
}
for (let i = 0; i < 5; i++) {
week.innerHTML += `<div id='day${i + 1}' class='daily'>` + `<canvas id='dayIcon${i + 1}'></canvas>` + `<h2 id='dayTemp${i + 1}'></h2>` + `<p id='daySummary${i + 1}'></p>` + '</div>';
setIcons(obj.daily.data[i].icon, document.getElementById(`dayIcon${i + 1}`));
document.getElementById(`dayTemp${i + 1}`).innerHTML = obj.daily.data[i].temperatureMax;
document.getElementById(`daySummary${i + 1}`).innerHTML = obj.daily.data[i].summary;
}
}
};
xhr.open("GET", api, true);
xhr.send();
});
}
function setIcons(icon, iconId) {
const skycons = new Skycons({color: 'white'});
const currentIcon = icon.replace(/-/g, '_').toUpperCase();
skycons.play();
return skycons.set(iconId, Skycons[currentIcon]);
}
;
});
...and the problem is that when it comes to the icons being loaded and displayed it's only the last one that actually displays. I don't know what the problem is because if it's successful for the last one, then it should be successful for the previous 47 since the last is the same iteration done for the 48th time. Any ideas?
Related
So I have some Javascript that does an XMLHttpRequest (xhr), on receival of response it does a second response (xhr2) to get remaining data.
But I have now split this second call into batches so that it has to call multiple times depending on how much data there. After the first request I know how many calls I haven to make
var batches = Math.ceil((counter.innerText.substring(0,counter.innerText.indexOf(" ")) - 100) / 1000);
But then I am just making multiple calls to xdr2, but this doesn't work because it closes after first call. So I realize I probably need to initialize multiple XMLHttpRequest based on the value of batches, but how do I define the onreadystatechange function succinctly.
function get_tracklist_data(path, cid, title)
{
var xhr = new XMLHttpRequest();
var xhr2 = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
{
var counter = document.getElementById("counter");
counter.innerHTML = xhr.responseText.substring(0, xhr.responseText.indexOf(":"));
var data = document.getElementById("data");
data.innerHTML = xhr.responseText.substring(xhr.responseText.indexOf(":") + 1);
//Work out how many calls we need to make
var batches = Math.ceil((counter.innerText.substring(0,counter.innerText.indexOf(" ")) - 100) / 1000);
for(i=1; i<batches;i++)
{
xhr2.open('GET',path + '?cid=' + cid + "&title=" + title+"&batch=" + i, true);
xhr2.send();
}
}
};
xhr2.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
{
var data = document.getElementById("tbody");
data.innerHTML+=xhr2.responseText;
}
};
xhr.open('GET',path + '?cid=' + cid + "&title=" + title +"&batch=0", true);
xhr.send();
};
Update to make xhr2 local variable in loop, but doesnt seem to work properly Im getting the same data back multiple times.
function get_tracklist_data(path, cid, title)
{
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
{
var counter = document.getElementById("counter");
counter.innerHTML = xhr.responseText.substring(0, xhr.responseText.indexOf(":"));
var data = document.getElementById("data");
data.innerHTML = xhr.responseText.substring(xhr.responseText.indexOf(":") + 1);
//Work out how many calls we need to make
var batches = Math.ceil((counter.innerText.substring(0,counter.innerText.indexOf(" ")) - 100) / 1000);
for(i=1; i<batches;i++)
{
var xhr2 = new XMLHttpRequest();
xhr2.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
{
var data = document.getElementById("tbody");
data.innerHTML+=xhr2.responseText;
}
};
xhr2.open('GET',path + '?cid=' + cid + "&title=" + title+"&batch=" + i, true);
xhr2.send();
}
}
};
xhr.open('GET',path + '?cid=' + cid + "&title=" + title +"&batch=0", true);
xhr.send();
};
here example using await fetch() and fetch().then()
function listenForButtonCollapse(buttonId, collapseId, buttonText) {
let button = document.getElementById(buttonId);
let section = document.getElementById(collapseId);
if (section != null) {
section.addEventListener('show.bs.collapse', function() {
button.innerText = 'Hide ' + buttonText;
});
section.addEventListener('hide.bs.collapse', function() {
button.innerText = 'Show ' + buttonText;
});
}
}
async function get_tracklist_data(path, cid, title) {
let xhr = await fetch(path + '?cid=' + cid + "&title=" + title + "&batch=0");
let responseText = await xhr.text()
let counter = document.getElementById("counter");
counter.innerHTML = responseText.substring(0, responseText.indexOf(":"));
let data = document.getElementById("data");
data.innerHTML = responseText.substring(responseText.indexOf(":") + 1);
listenForButtonCollapse('show_focus_button', 'focus_id', 'Spotlight');
listenForButtonCollapse('show_albums_button', 'albums_id', 'Albums');
listenForButtonCollapse('show_tracks_button', 'tracks_id', 'Tracks');
listenForButtonCollapse('show_works_button', 'works_id', 'Works');
//Work out how many calls we need to make
let batches = Math.ceil((counter.innerText.substring(0, counter.innerText.indexOf(" ")) - 100) / 1000);
data = document.getElementById("tbody");
for (i = 1; i < batches; i++) {
fetch(path + '?cid=' + cid + "&title=" + title + "&batch=" + i)
.then(resp => resp.text())
.then(responseText => {
data.innerHTML += responseText;
})
}
}
Using XMLHttpRequest: save xhr object into array then add parameter to the callback listXHR[i].onreadystatechange = function(x) then call x.target for current xhr object
function get_tracklist_data(path, cid, title) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var counter = document.getElementById("counter");
counter.innerHTML = xhr.responseText.substring(0, xhr.responseText.indexOf(":"));
var data = document.getElementById("data");
data.innerHTML = xhr.responseText.substring(xhr.responseText.indexOf(":") + 1);
//Work out how many calls we need to make
var batches = Math.ceil((counter.innerText.substring(0, counter.innerText.indexOf(" ")) - 100) / 1000);
var listXHR = []
for (i = 1; i < batches; i++) {
listXHR[i] = new XMLHttpRequest();
listXHR[i].onreadystatechange = function(x) {
if (x.target.readyState == 4 && x.target.status == 200) {
var data = document.getElementById("tbody");
data.innerHTML += x.target.responseText;
}
};
listXHR[i].open('GET', path + '?cid=' + cid + "&title=" + title + "&batch=" + i, true);
listXHR[i].send();
}
}
};
xhr.open('GET', path + '?cid=' + cid + "&title=" + title + "&batch=0", true);
xhr.send();
};
I am writing a REST client to remote api. And I am using xmlHTTPRequest to get information about images.I need to refresh my images in every 30 seconds. My implementation of setTimeout function doesn't work. Anyone can help me? Thank you in advance.
Here is my code: Image.js
function Camera(id, name, ip, port) {
var button = document.createElement("button");
button.classList.add("camera");
button.innerHTML += "<h3>" + name + "</h3><br>";
var ismin = true;
this.id = id;
this.name = name;
this.ip = ip;
this.port = port;
this.getURL = function getURL(min) {
var url = 'http://' + ip + ":8080/api";
return min ? url + '/miniature/' + id + '?t=' + new Date().getTime() : url + '/image/' + id + '?t=' + new Date().getTime();
};
this.appendImg = function appendImg(url) {
button.innerHTML = "<h3>" + name + '</h3><br><img src="' + url + '"/>';
setTimeout(appendImg(url),30000);
};
this.showElement = function showElement(url) {
this.appendImg(url);
var that = this;
document.querySelector('#camera-section').appendChild(button);
button.addEventListener('click', function () {
ismin = !ismin;
that.appendImg(that.getURL(ismin), false);
});
};}
And a part of main.js:
function showImage(response) {
response = JSON.parse(sessionStorage.getItem('camera'));
console.log(response);
for (var i = 0; i < response.length; i++) {
var a = response[i];
var camera = new Camera(a.cameraId, a.name, ip, port, true);
var curl = camera.getURL(true);
camera.showElement(curl);
}
}
xml.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
sessionStorage.setItem('camera',JSON.stringify(response));
//console.log(sessionStorage.getItem('camera'));
showImage(sessionStorage.getItem('camera'));
}
};
xml.open('GET', mainUrl);
xml.send(null);
Regarding the comment of Pranay Kumar, first part of your code could be like this::
function Camera(id, name, ip, port) {
var button = document.createElement("button");
button.classList.add("camera");
button.innerHTML += "<h3>" + name + "</h3><br>";
var ismin = true;
this.id = id;
this.name = name;
this.ip = ip;
this.port = port;
this.getURL = function getURL(min) {
var url = 'http://' + ip + ":8080/api";
return min ? url + '/miniature/' + id + '?t=' + new Date().getTime() : url + '/image/' + id + '?t=' + new Date().getTime();
};
this._appendImg = function(url) {
return function() {
button.innerHTML = "<h3>" + name + '</h3><br><img src="' + url + '"/>';
}
};
this._timerHandle = 0;
this.appendImg = function(url) {
if (this._timerHandle) {
clearInterval(this._timerHandle);
}
this._timerHandle = setInterval(this._appendImg(url),30000);
}
this.showElement = function showElement(url) {
this.appendImg(url);
var that = this;
document.querySelector('#camera-section').appendChild(button);
button.addEventListener('click', function () {
ismin = !ismin;
that.appendImg(that.getURL(ismin), false);
});
}
}
You want refresh image every 30 seconds.
So use setInterval instead of setTimeout
I'm trying to create a weather app, sending Ajax requests to OpenWeatherMap. I've got an error in w.getWeatherFunc, when I'm giving the function sendRequest the parameter of w.weather and then giving the same parameter to the function displayFunc, which I'm calling next.
Here is what I've got in the console:
Uncaught TypeError: Cannot read property 'weather' of undefined
at displayFunc (weather.js:46)
at weather.js:78
How can I fix this and make it work?
function Weather () {
var w = this;
var weatherUrl = 'http://api.openweathermap.org/data/2.5/weather?';
var appid = '&appid=c0a7816b2acba9dbfb70977a1e537369';
var googleUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address=';
var googleKey = '&key=AIzaSyBHBjF5lDpw2tSXVJ6A1ra-RKT90ek5bvQ';
w.demo = document.getElementById('demo');
w.place = document.getElementById('place');
w.description = document.getElementById('description');
w.temp = document.getElementById('temp');
w.humidity = document.getElementById('humidity');
w.getWeather = document.getElementById('getWeather');
w.addCityBtn = document.getElementById('addCity');
w.rmCityBtn = document.getElementById('rmCity');
w.icon = document.getElementById('icon');
w.wind = document.getElementById('wind');
w.time = document.getElementById('time');
w.lat = null;
w.lon = null;
w.cityArray = [];
w.weather = null;
function sendRequest (url, data) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.send();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
data = JSON.parse(request.responseText);
console.log(data);
return data;
} else {
console.log(request.status + ': ' + request.statusText);
}
}
}
function displayFunc (obj) {
console.log('obj ' + obj);
w.icon.src = 'http://openweathermap.org/img/w/' + obj.weather[0].icon + '.png';
var timeNow = new Date();
var hours = timeNow.getHours();
var minutes = timeNow.getMinutes() < 10 ? '0' + timeNow.getMinutes() : timeNow.getMinutes();
w.time.innerHTML = hours + ':' + minutes;
w.place.innerHTML = 'Place: ' + obj.name;
w.description.innerHTML = "Weather: " + obj.weather[0].description;
w.temp.innerHTML = "Temperature: " + w.convertToCels(obj.main.temp) + "°C";
w.humidity.innerHTML = "Humidity: " + obj.main.humidity + '%';
w.wind.innerHTML = 'Wind: ' + obj.wind.speed + ' meter/sec';
}
w.convertToCels = function(temp) {
var tempC = Math.round(temp - 273.15);
return tempC;
}
w.getWeatherFunc = function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(location){
w.lat = location.coords.latitude;
w.lon = location.coords.longitude;
var url = weatherUrl + 'lat=' + w.lat + '&lon=' + w.lon + appid;
var result = sendRequest(url, w.weather);
console.log(result);
displayFunc(result);
});
} else {
alert('Browser could not find your current location');
}
}
w.addCityBtn.onclick = function() {
var newCity = prompt('Please insert city', 'Kiev');
var gUrl = googleUrl + newCity + googleKey;
var newCityWeather = null;
sendRequest(url, newCityWeather);
var location = newCityWeather.results[0].geometry.location;
var newUrl = weatherUrl + 'lat=' + location.lat + '&lon=' + location.lng + appid;
sendRequest(newUrl, w.weather);
displayFunc(newCity);
w.cityArray.push(newCity);
}
window.onload = w.getWeatherFunc;
setInterval(function() {
w.getWeatherFunc();
}, 900000);
}
Your ajax return returns into the browsers engine. As its async you need to create a callback:
function sendRequest(url,data,callback){
//if the data was received
callback(data);
}
Use like this
sendRequest("yoururl",data,function(data){
displayFunc(data);
});
The first time you pass the obj to the function it will save it one scope higher. after that, if you don;t pass the object the one you saved earlier will be used.
var objBkp;
function displayFunc (obj) {
if(undefined === obj) obj = objBkp;
else objBkp = obj;
// rest of code here
}
In your sendRequest you are passing only the value of w.weather, not its reference. JavaScript doesn't pass variables by value or by reference, but by sharing. So if you want to give the value to your variable you should do this inside your function sendRequest:
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
w.weather = JSON.parse(request.responseText);
console.log(data);
return data;
} else {
console.log(request.status + ': ' + request.statusText);
}
}
Also, if you are using the attributes, you don't have to pass them in the function as arguments. Besides that fact, it would be good if you also create get() and set()
What does the console.log(result); in getWeatherFunc gives you?
The problem as I see it is that in the displayFunc the parameter passed is undefined.
I'm having a bit of trouble when preloading images in an array to later be drawn on a canvas (like a 2D top-down game board). However, it seems like one of these images (Greyscale GIFs, btw) refuses to load. I know it is one because when using an example from somewhere to count down the remaining images, it stops if set to 256, but will continue if set to 255.
var xhttp = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP");
var xmlDoc;
var canvas = document.getElementById("leveldraw");
var displayLevel = document.getElementById("leveldisp");
var levelList = document.getElementById("level");
var setlayer1 = document.getElementById("layer1");
var setlayer2 = document.getElementById("layer2");
var setlayer3 = document.getElementById("layer3");
var setlayer4 = document.getElementById("layer4");
var setmarkings = document.getElementById("marks");
var objects = [];
xhttp.onreadystatechange = function()
{
if (xhttp.readyState == 4 && xhttp.status == 200)
{
xmlDoc = xhttp.responseXML;
preloadImages()
}
};
xhttp.open("GET", "levels.xml", true);
xhttp.send();
if(canvas.getContext)
{
var ctx = canvas.getContext("2d");
}
function preloadImages()
{
var img;
var remaining = 256;
for(var i=0; i<256; i=i+1)
{
img = new Image();
img.onload = function()
{
--remaining;
document.getElementById("loader").innerHTML = "<b>Loading: " + parseInt((1-(remaining/256))*100) + "%</b>";
if(remaining<=0)
{
ChangeLevel();
}
};
img.src = "objects/img" + ("00" + i.toString(16)).slice(-2) + ".gif";
objects.push(img);
}
}
function ChangeLevel()
{
document.getElementById("loader").innerHTML = "<b>Loading...</b>";
var levelnumber = levelList.selectedIndex;
var width=xmlDoc.getElementsByTagName("width")[levelnumber].childNodes[0].nodeValue;
var height=xmlDoc.getElementsByTagName("height")[levelnumber].childNodes[0].nodeValue;
var layout=xmlDoc.getElementsByTagName("layout")[levelnumber].childNodes[0].nodeValue;
var type=xmlDoc.getElementsByTagName("type")[levelnumber].childNodes[0].nodeValue;
var layer0data=xmlDoc.getElementsByTagName("layer0")[levelnumber].childNodes[0].nodeValue;
var layer1data=xmlDoc.getElementsByTagName("layer1")[levelnumber].childNodes[0].nodeValue;
var layer2data=xmlDoc.getElementsByTagName("layer2")[levelnumber].childNodes[0].nodeValue;
var layer3data=xmlDoc.getElementsByTagName("layer3")[levelnumber].childNodes[0].nodeValue;
canvas.width=width*16;
canvas.height=height*16;
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0,0,canvas.width,canvas.height);
if(layer1.checked==true)
{
console.log("layer1");
var i=1;
for(var y=0; y<height; y=y+1)
{
for(var x=0; x<width; x=x+1)
{
try {
ctx.drawImage(objects[parseInt(layer0data.substring(i,i+2),16)],x*16,y*16);
} catch(err) {
console.log(err.message + " at " + ("00" + x).slice(-2) + "x" + ("00" + y).slice(-2) + " obj:" + layer0data.substring(i,i+2));
}
i=i+2;
}
}
}
if(layer2.checked==true)
{
console.log("layer2");
var i=1;
for(var y=0; y<height; y=y+1)
{
for(var x=0; x<width; x=x+1)
{
try {
ctx.drawImage(objects[parseInt(layer1data.substring(i,i+2),16)],x*16,y*16);
} catch(err) {
console.log(err.message + " at " + ("00" + x).slice(-2) + "x" + ("00" + y).slice(-2) + " obj:" + layer1data.substring(i,i+2));
}
i=i+2;
}
}
}
if(layer3.checked==true)
{
console.log("layer3");
var i=1;
for(var y=0; y<height; y=y+1)
{
for(var x=0; x<width; x=x+1)
{
try {
ctx.drawImage(objects[parseInt(layer2data.substring(i,i+2),16)],x*16,y*16);
} catch(err) {
console.log(err.message + " at " + ("00" + x).slice(-2) + "x" + ("00" + y).slice(-2) + " obj:" + layer2data.substring(i,i+2));
}
i=i+2;
}
}
}
if(layer4.checked==true)
{
console.log("layer4");
var i=1;
for(var y=0; y<height; y=y+1)
{
for(var x=0; x<width; x=x+1)
{
try {
ctx.drawImage(objects[parseInt(layer3data.substring(i,i+2),16)],x*16,y*16);
} catch(err) {
console.log(err.message + " at " + ("00" + x).slice(-2) + "x" + ("00" + y).slice(-2) + " obj:" + layer3data.substring(i,i+2));
}
i=i+2;
}
}
}
document.getElementById("loader").innerHTML = "";
}
Any ideas why this is happening? Been reuploading the same GIF over and over (imgad.gif).
Because the image file name is imgad.gif, most AdBlockers block it, because of the ad part.... Renaming the image should solve it.
SOLUTION: Never use hexadecimals because the number AD can be blocked by Adblockers.
Thanks to Philip for discovering that.
I want to loop an httprequest every 5 seconds.
Here is my code :
var xmlhttp2 = new XMLHttpRequest();
var url2 = "http:...";
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
var response2 = xmlhttp2.responseText;
var response2 = xmlhttp2.responseText;
var json2 = JSON.parse(response2);
for (var i = 2; i < json2.length; i++){
document.getElementById('table2').innerHTML += '<tr><td>' + json2[i].nm + '</td><td>' + json2[i].id + '</td><td id="uid_'+i+'">' + json2[i].stn + '</td></tr>';
}
}
xmlhttp2.open("GET", url2, true);
xmlhttp2.send();
I tried to put this whole code in a function and called
setInterval(myFunction,5000);
This works. However the table is displaying several times.
I tried
setInterval("xmlhttp2.send();",5000);
and this doesn't work. The request is made only once.
Any advice ?
Thank you
You can clear the table before populating it with the server response
Answer
var xmlhttp2 = new XMLHttpRequest();
var url2 = "http:...";
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
var response2 = xmlhttp2.responseText;
var response2 = xmlhttp2.responseText;
var json2 = JSON.parse(response2);
var table = document.getElementById('table2');
table.innerHTML = '';
for (var i = 2; i < json2.length; i++){
table.innerHTML += '<tr><td>' + json2[i].nm + '</td><td>' + json2[i].id + '</td><td id="uid_'+i+'">' + json2[i].stn + '</td></tr>';
}
}
xmlhttp2.open("GET", url2, true);
xmlhttp2.send();
Use setInterval(myFunction,5000); to make periodic request.
Edited
var xmlhttp2 = new XMLHttpRequest();
var url2 = "http:...";
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
var response2 = xmlhttp2.responseText;
var response2 = xmlhttp2.responseText;
var json2 = JSON.parse(response2);
var tableBody = document.getElementById('table2Body');
tableBody.innerHTML = '';
for (var i = 2; i < json2.length; i++){
tableBody.innerHTML += '<tr><td>' + json2[i].nm + '</td><td>' + json2[i].id + '</td><td id="uid_'+i+'">' + json2[i].stn + '</td></tr>';
}
}
xmlhttp2.open("GET", url2, true);
xmlhttp2.send();