Very grateful if someone can help me out with the syntax here- I am hoping to make several XML requests, each time getting a different text file. Here is the general structure of my code. How can I get each file in turn (f0, f1 and f2)?
window.onload = function(){
var f = (function(){
var xhr = [];
for (i = 0; i < 3; i++){
(function (i){
xhr[i] = new XMLHttpRequest();
f0 = "0.txt"
f1 = "1.txt"
f2 = "2.txt"
//??? xhr[i].open("GET", file i, true);
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
//do stuff
}
};
xhr[i].send();
})(i);
}
})();
};
Simply put your filenames in an array.
window.onload = function(){
var f = (function(){
var xhr = [];
var files = ["f0.txt", "f1.txt", "f2.txt"];
for (i = 0; i < 3; i++){
(function (i){
xhr[i] = new XMLHttpRequest();
xhr[i].open("GET", files[i], true);
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
//do stuff
}
};
xhr[i].send();
})(i);
}
})();
};
Something like this should work
// ...
for (i = 0; i < 3; i++){
(function (i){
xhr[i] = new XMLHttpRequest();
xhr[i].open('GET', i.toString() + '.txt'); // <-- this line
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
// ....
Related
This function operates perfectly, onclick it subtracts a price amount from 7 ‘cosT’ divs and 1 ‘cosT1’ div, as if removing an item from a shopping cart.
function changePrice0000() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = document.querySelectorAll(".cosT, .cosT1");
x[0].innerHTML = parseFloat(Number(x[0].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[1].innerHTML = parseFloat(Number(x[1].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[2].innerHTML = parseFloat(Number(x[2].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[3].innerHTML = parseFloat(Number(x[3].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[4].innerHTML = parseFloat(Number(x[4].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[5].innerHTML = parseFloat(Number(x[5].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[6].innerHTML = parseFloat(Number(x[6].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[7].innerHTML = parseFloat(Number(x[7].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
}
};
xhttp.open("GET", "text/p0000.txt", true);
xhttp.send();
}
I’ve tried a few variations of the following, nooby attempts at looping and getting it to work but without even remote success…
function changePrice0000() {
for(i=0; i<7; i++) {
var xhttp = new XMLHttpRequest();xhttp.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {
var x = document.querySelectorAll(".cosT, .cosT1");
x[n].innerHTML = parseFloat(Number(x[n].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
x[0].innerHTML = parseFloat(Number(x[0].innerHTML) - Number(x[7].innerHTML)).toFixed(2);}};
xhttp.open("GET", "text/p0000.txt", true);
xhttp.send();
}
}
…way beyond my capabilities , one for the experts I think, explicit assistance or just a point in the right direction would be most gratefully appreciated.
You were close, you only need the for loop around the part of the code you want to repeat. You also used an undefined variable n instead of the i in the loop, as #Rup mentioned in the comments:
function changePrice0000() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = document.querySelectorAll(".cosT, .cosT1");
for(i = 0; i<7; i++) {
x[i].innerHTML = parseFloat(Number(x[i].innerHTML) - Number(x[7].innerHTML)).toFixed(2);
}
xhttp.open("GET", "text/p0000.txt", true);
xhttp.send();
}
}
}
Here a small snippet with a simple loop solution:
var x = document.querySelectorAll(".cost");
x.forEach(function(el) {
el.innerHTML = parseFloat(Number(el.innerHTML) - Number(x[7].innerHTML)).toFixed(2);
});
<div class="cost">1</div>
<div class="cost">2</div>
<div class="cost">3</div>
<div class="cost">4</div>
<div class="cost">5</div>
<div class="cost">6</div>
<div class="cost">7</div>
<div class="cost">8</div>
function changePrice0000() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = document.querySelectorAll(".cosT, .cosT1");
// loop over n starts here
for (n = 0; n < 7; n++) {
x[n].innerHTML = parseFloat(
Number(x[n].innerHTML) - Number(x[7].innerHTML)
).toFixed(2);
}
// loop ends here
}
xhttp.open("GET", "text/p0000.txt", true);
xhttp.send();
};
}
maybe this is what you mean? N is the var, so I from your example will not work, and you gotta makes sure your loop is inside of where you want to handle it...
Ok so huge thank you to the blisteringly fast expert responses, bit of jigging about–here is what is working perfectly (don’t ask me how :), endeavoured to indent a bit:
function changePrice0000() {var xhttp = new XMLHttpRequest();xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = document.querySelectorAll(".cosT, .cosT1");
// loop begins
for(n=0; n<7; n++) {
x[n].innerHTML = parseFloat(Number(x[n].innerHTML) - Number(x[7].innerHTML)).toFixed(2)};
// loop ends
x[n].innerHTML = parseFloat(Number(x[n].innerHTML) - Number(x[7].innerHTML)).toFixed(2);}};
xhttp.open("GET", "text/p0000.txt", true);
xhttp.send();}
Thanks again guys !!!
You just have to put for loop to the code which you want to repeat.
var n=7
for(i = 0; i <= n; i++) {
x[i].innerHTML = parseFloat(Number(x[i].innerHTML)-(Number(x[n].innerHTML)).toFixed(2);
}
I wrote this code, which creates divs depending on the amount of text files in local directory.
Then I tried to write additional code, which appends photos to each of these divs. Unfortunately, this code doesn't append any photos...
function liGenerator() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
var n = (xmlhttp.responseText.match(/txt/g) || []).length;
for (var i = 1; i < n; i++) {
$.get("projects/txt/"+i+".txt", function(data) {
var line = data.split('\n');
var num = line[0]-"\n";
var clss = line[1];
var title = line[2];
var price = line[3];
var content = line[4];
$("#list-portfolio").append("<li class='item "+clss+" show' onclick='productSelection('"+num+"')'><img src='projects/src/"+num+"/title.jpg'/><div class='title'><h1>"+title+"</h1><h2>"+price+"</h2></div><article>"+content+"</article></li>");
$("#full-size-articles").append("<li class='product "+num+"'><div><div class='photo_gallery'><div id='fsa_img "+num+"'><div width='100%' class='firstgalleryitem'></div></div></div><article class='content'><h1 class='header_article'>"+title+"</h1><h2 class='price_article'>"+price+"</h2><section class='section_article'>"+content+"</section></article></div></li>");
});
}
}
}
};
xmlhttp.open("GET", "projects/txt/", true);
xmlhttp.send();
}
function pushPhotos() {
var list = document.getElementById("full-size-articles").getElementsByTagName("li");
var amount = list.length;
for(var i=1;i<=amount;i++) {
var divID = "#fsa_img "+i;
var where = "projects/src/"+i+"/";
var fx = ".jpg";
loadPhotos(where, fx, divID);
}
}
function loadPhotos(dir, fileextension, div) {
$.ajax({
url: dir,
success: function (data) {
$(data).find("a:contains(" + fileextension + ")").each(function () {
var filename = this.href.replace(window.location, "").replace("http://", "");
$(div).append("<img src='"+dir+filename+"' class='mini_photo'/>");
});
}
});
}
Any ideas on why this code is not working as intended?
The main issue is the space between "#fsa_img" and "i". When I changed it to '"#fsa_img_"+i', the code started work as intended.
I have some divs that I replace with new html. So far so good.
(function() {
var obj = function(div) {
var obj = {};
obj.divToReplace = div;
obj.objId = obj.divToReplace.dataset.id;
obj.template = "<div class="newDivs"><p>#Name</p><img src='#ImageUrl'/></div>";
obj.replaceDiv = function() {
var xhr = new XMLHttpRequest();
xhr.open( 'GET', encodeURI('http://.../' + obj.objId) );
xhr.onload = function(e) {
if (xhr.status === 200) {
var x = JSON.parse(xhr.responseText).data.attributes;
var newHtml = obj.template
.replaceAll("#Name", x.name)
.replaceAll("#ImageUrl", x.imageUrl);
obj.divToReplace.outerHTML = newHtml;
}
else {
console.log(xhr.status);
}
};
xhr.send();
};
return {
replaceDiv: obj.replaceDiv
}
};
String.prototype.replaceAll = function(search, replace)
{
return this.replace(new RegExp(search, 'g'), replace);
};
//get the elements I want to replace
var elems = document.getElementsByClassName('divToReplace');
//replace them
for (i = 0; i < elems.length; i++) {
obj(elems[i]).replaceDiv();
}
//call handleStuff ?
})();
Then I want to add addEventListener to the divs, and it's here I get stuck. I want to call handleStuff() after all the divs are replaced. (Because of course, before I replace them the new divs don't exists.) And I can't use jQuery.
var handleStuff = function(){
var classname = document.getElementsByClassName("newDivs");
var myFunction = function() {
};
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', myFunction, false);
}
...............
How can I add a callback that tells me when all the divs are replaced? Or is it overall not a good solution for what I'm trying to do?
Sorry for using jQuery previously, here is solution with native Promise(tested)
(function() {
var f = {
send : function(){
var promise = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.open( 'GET', encodeURI('http://www.google.com/') );
xhr.onload = function(e) {
if (xhr.status === 200) {
//your code
resolve();
console.log('resolve');
} else {
console.log(xhr.status);
}
};
xhr.send();
});
return promise;
}
}
var promises = [];
for (i = 0; i < 100; i++) {
promises.push(f.send());
}
Promise.all(promises).then(function(){
console.log('success');
});
})();
I am trying to write a OBJMesh model reader and I've got the OBJMesh class setted up, but when I try to retrieve the stored data in the array by creating the OBJMesh object and call the get function, it doesn't do it.
Here's the code
OBJMesh.js
function OBJMesh(file)
{
this.modelVertex = [];
this.modelColor = [];
this.init = false;
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, true);
var objmesh = this;
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState == 4)
{
if(rawFile.status === 200 || rawFile.status === 0)
{
var allText = rawFile.responseText;
var lines = allText.split("\n");
for(var i = 0; i < lines.length; i ++)
{
var lineData = lines[i];
var lineString = lineData.split(" ");
if(lineString[0] === "v")
{
var x = parseFloat(lineString[1]);
var y = parseFloat(lineString[2]);
var z = parseFloat(lineString[3]);
objmesh.modelVertex.push(x);
objmesh.modelVertex.push(y);
objmesh.modelVertex.push(z);
objmesh.modelColor.push(0.0);
objmesh.modelColor.push(0.0);
objmesh.modelColor.push(0.0);
objmesh.modelColor.push(1.0);
//document.getElementById("textSection").innerHTML = objmesh.modelVertex[0];
}
}
}
}
objmesh.init = true;
}
rawFile.send();
}
OBJMesh.prototype.getModelVertex = function ()
{
return this.modelVertex;
};
OBJMesh.prototype.getModelColor = function ()
{
return this.modelColor;
};
OBJMesh.prototype.getInit = function ()
{
return this.init;
};
main.js
var cubeModel;
function main()
{
cubeModel = new OBJMesh("file:///Users/DannyChen/Desktop/3DHTMLGame/cube.obj");
while(cubeModel.getInit() === false)
{
//wait for it
}
var cubeVertex = cubeModel.getModelVertex();
document.getElementById("textSection").innerHTML = cubeVertex[0];
}
it just keeps printing out "undefined". Why's that? and how can I fix it??
but it seems that onreadystatechange is an async-Call so,
this.init = true;
will be set before the function onreadystatechange is called.
May be you could set at the end of the onreadystatechange function
objmesh.init = true;
i hope this helps
I've been trying to add data into my array for sometime now and it doesn't work. I have the following code:
function OBJMesh(file)
{
this.modelVertex = [];
this.modelColor = [];
var that = this;
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, true);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState == 4)
{
if(rawFile.status === 200 || rawFile.status === 0)
{
var allText = rawFile.responseText;
var lines = allText.split("\n");
for(var i = 0; i < lines.length; i ++)
{
var lineData = lines[i];
var lineString = lineData.split(" ");
if(lineString[0] === "v")
{
var x = parseFloat(lineString[1]);
var y = parseFloat(lineString[2]);
var z = parseFloat(lineString[3]);
/*
this.modelVertex.push(x);
this.modelVertex.push(y);
this.modelVertex.push(z);
this.modelColor.push(0.0);
this.modelColor.push(0.0);
this.modelColor.push(0.0);
this.modelColor.push(1.0);
*/
that.modelVertex.push(10.0);
//document.getElementById("textSection").innerHTML = "testing";
}
}
}
}
}
rawFile.send();
}
OBJMesh.prototype.getModelVertex = function ()
{
return this.modelVertex;
};
OBJMesh.prototype.getModelColor = function ()
{
return this.modelColor;
};
If I comment out the this.modelVertex.push(10.0); it gets pass the error and prints out "testing". But if I uncomment it, it gets stuck there and won't print anything out. Why is it doing this? how can I solve it so it actually pushes the given data to the this.modelVertex array?
Many Thanks
Edit: I have edited my code after dystroy told me what to do and it do work when I try to print the values in the OBJMesh constructor (shown above), but when I try to do this by creating the object in my main function (shown below) it doesn't print anything.
var cubeModel;
function main()
{
cubeModel = new OBJMesh("file:///Users/Danny/Desktop/3DHTMLGame%202/cube.obj");
document.getElementById("textSection").innerHTML = cubeModel.getModelVertex();
}
this isn't your new instance of OBJMesh in the callback but the XMLHttpRequest.
Start by referencing the desired object just before defining the callback :
var that = this;
rawFile.onreadystatechange = function ()
then use it :
that.modelVertex.push(10.0);
Answer to the question in your edit :
Your constructor contains an asynchronous request. Which means your array isn't available immediately but later.
A solution would be to pass a callback to the constructor :
function OBJMesh(file, doAfterInit) {
this.modelVertex = [];
this.modelColor = [];
var that = this;
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, true);
rawFile.onreadystatechange = function () {
if(rawFile.readyState == 4)
{
if(rawFile.status === 200 || rawFile.status === 0)
{
var allText = rawFile.responseText;
var lines = allText.split("\n");
for(var i = 0; i < lines.length; i ++)
{
var lineData = lines[i];
var lineString = lineData.split(" ");
if(lineString[0] === "v"){
that.modelVertex.push(10.0);
if (doAfterInit) doAfterInit();
}
}
}
}
}
rawFile.send();
}
...
cubeModel = new OBJMesh("file:///Users/Danny/Desktop/3DHTMLGame%202/cube.obj", function() {
document.getElementById("textSection").innerHTML = cubeModel.getModelVertex();
});
But having a class here doesn't look like a smart idea.