Struggling to understand AJAX w/ Javascript - javascript

I am very new to programming.
I am trying to output a list of (my two empty) GitHub repositories into a <p> with id="repos". When I run the code, I receive the error message:
Uncaught ReferenceError: id is not defined at XMLHttpRequest.gitHubRequest.onreadystatechange
And I'll receive this error for every the other two keys I want to pull the value from (full_name & html_url).
Can someone give me some insight as to how I can make this code work? it needs to be Javascript- its for a class. Thanks you!
let gitHubRequest = new XMLHttpRequest();
gitHubRequest.open('GET', 'https://api.github.com/users/billythesailor/repos', true);
gitHubRequest.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
var repos = JSON.parse(this.responseText);
var output = '';
for(var i in repos){
output +=
'<ul>' +
'<li>ID: ' +id[i]+'</li>' +
'<li>Full Name: ' +full_name[i]+'</li>' +
'<li>URL: ' +html_url[i]+'</li>'+
'</ul>'
}
document.getElementById('repos').innerHTML = output;
}
}
gitHubRequest.send();

The issue is that the id, full_name, and html_url are fields on the repo objects, but you're accessing them as defined arrays. So id[i] needs to change to repos[i].id and so on. I've updated your example below!
let gitHubRequest = new XMLHttpRequest();
gitHubRequest.open('GET', 'https://api.github.com/users/billythesailor/repos', true);
gitHubRequest.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
var repos = JSON.parse(this.responseText);
var output = '';
for(var i in repos){
output +=
'<ul>' +
'<li>ID: ' + repos[i].id +'</li>' +
'<li>Full Name: ' + repos[i].full_name +'</li>' +
'<li>URL: ' + repos[i].html_url +'</li>'+
'</ul>'
}
document.getElementById('repos').innerHTML = output;
}
}
gitHubRequest.send();
<div id="repos"></div>
Also, if you're new to Javascript and interested in making ajax requests, I'd look into the Fetch API, which is bit cleaner to use.
fetch('https://api.github.com/users/billythesailor/repos')
.then(res => res.json())
.then(repos => {
// do stuff with the repo data!
});

Related

How do I get scripts to work after a xhttps request

So I have a search page that I'm working on that has a given JSON object as a return. When I click the search button, it's supposed to load up the results page (without a refresh), with the JSON parsed and placed neatly in div's using JS (I can't use jQuery) (this code is in ajax_info.html). Everything independently works. However, when I try to use AJAX with JavaScript, it doesn't load. Again, everything works when loaded independently. But right now, no scripts are working inside the script tag of ajax_info.html. Is there a better method that I could use to update the page with the results page without reloading? This is my code:
function loadDoc() {
var setInnerHTML = function(elm, html) {
elm.innerHTML = html;
Array.from(elm.querySelectorAll("script")).forEach( oldScript => {
const newScript = document.createElement("script");
Array.from(oldScript.attributes)
.forEach( attr => newScript.setAttributes(attr.name, attr.value) );
newScript.appendChild(document.createTextNode(oldScript.innerHTML));
oldScript.parentNode.replaceChild(newScript, oldScript);
});
}
console.log('hello');
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200 && xhttp.readyState == XMLHttpRequest.DONE) {
setInnerHTML(document.getElementById("demo"),this.responseText);
console.log(this.responseText);
}
};
xhttp.open("POST", "ajax_info.html", true);
xhttp.send();
}
and this is the relevant code for ajax_info.html:
<script>
alert("hello");
console.log('adfasdf');
const searchResults = {
//Json stuff
}
// console.log(searchResults);
//const obj = JSON.parse(searchResults);
//document.getElementById("demo2").innerHTML = searchResults.response.docs[0].es_description;
let text="";
for(let i=0; i<searchResults.response.docs.length; i++) {
text+="<div class='p-3 border rounded-3'>";
text+="<a href=''>"+ "<strong class='text-primary largeText'>" + searchResults.response.docs[i].es_title + "</strong></a>";
text+="<div class='largeText'>" + searchResults.response.docs[i].es_description + "</div>";
text+="<div>" + searchResults.response.docs[i].author + "</div>";
text+="<div>" + searchResults.response.docs[i].site + "</div>";
text+="<div>" + searchResults.response.docs[i].es_date + "<a class='text-success'> " + searchResults.response.docs[i].site + "</a></div>";
//text+="<a href='url'>"+ searchResults.response.docs[i].es_title + "</a>";
text+="</div>";
//text+=searchResults.response.docs[i].author + "<br>";
//text+=searchResults.response.docs[i].site + "<br>";
//text+=searchResults.response.docs[i].es_date + "<br>";
//text+="<p></p>";
document.getElementById("demo2").innerHTML = text;
console.log(i);
}
//alert(searchResults.response.docs.length);
</script>
demo2 is the id of the div inside of ajax_info and demo is the id of the body of index.html

How do i print from a json string array using javascript within html code

Example output image
I have a JSON file which I populate from excel via a bit of vba code. It comes out in the format of:
[{"Name":"testing1","Data":"15"},{"Name":"testing2","Data":"1"},{"Name":"testing3","Data":"3"}]
I wish to take this data to an HTML webpage. I want to print it as a simple list.
I've printed from a json object using something like:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(xhttp.responseText);
var people = response.people;
var output = '';
for (var i = 0; i < people.length; i++) {
//console.log(people[i].name);
output += '<li>' + "Name: " + people[i].name + " Age:" + people[i].age + '</li>';
}
document.getElementById('people').innerHTML = output;
}
};
xhttp.open("GET", "people.json", true);
xhttp.send();
I want to know how to change it to print from the string array without the object.

Request Data from one API according to the data recolted on another API

I'm using two functions to get some data from an API :
The first one request the data for each cycle, the second check if the payment has been done for each cycle.
All the data are placed in a common table. It seems that my issue come from the fact that I use a function in another function. It the that the second function executes itself only after the first one is complete.
https://codepen.io/anon/pen/XQOVVB?editors=1001
var obj, obj2, dbParam,dbParam2, xmlhttp, xmlhttp2, myObj, myObj2, x, y, txt, txt2 = "";
obj = { table: "cycle", limit: 10 };
dbParam = JSON.stringify(obj);
xmlhttp = new XMLHttpRequest();
// Get the value of the inputbox
// KT1 adress for trial KT19www5fiQNAiqTWrugTVLm9FB3th5DzH54
var KT1 = $('#KT1').val();
xmlhttp.onreadystatechange = function() {
obj2 = { table: "cycle2", limit: 100 };
if (this.readyState == 4 && this.status == 200) {
myObj = JSON.parse(this.responseText);
txt += "<table><tr bgcolor=#000000 color=White>"
txt += "<th>Cycle</th>"
//txt += "<th>Reward</th>"
txt += "<th>Paid</th>"
txt += "</tr>"
// Get the data of every cycle using API 1
for (x in myObj) {
// force x to 11 to get the condition PaymentCycle = cycle
x = 11;
cycle = myObj[x].cycle;
//balance = myObj[x].balance/1000000;
//TotalReward = myObj[x].rewards/1000000;
//stakingBalance = myObj[x].staking_balance/1000000;
//Share = balance/stakingBalance*100;
//DelegatorReward = Share*TotalReward/100;
// create line of the table
txt += "<tr>";
txt += "<td width=10% align=center>" + cycle + "</td>";
//txt += "<td width=10% align=center>" + Math.round(DelegatorReward*100)/100 + "</td>";
// here the CYCLE CHANGE CORRECTLY from 106 to 87
console.log("Cycle before function: " + cycle);
//API2 request
dbParam2 = JSON.stringify(obj2);
xmlhttp2 = new XMLHttpRequest();
xmlhttp2.onreadystatechange = function() {
if (this.readyState == 4 && (this.status == 200 || this.status == 0)) {
myObj2 = JSON.parse(this.responseText);
// ERROR HERE - ALWAYS GET THE DATA OF THE LAST CYCLE (87) instead of every cycle check with API1
// It seems that this fonction xmlhttp2 is executed only after xmlhttp is complete giving to cycle the last value of saved for cycle (87)
console.log("Cycle after function: " + cycle);
for (var y = 0; y < 30; y++) {
// Get the Paiement cycle which varies from 106 to 90
Block = myObj2[y].type.operations[0].op_level;
PaiementCycle = Math.round(Block/4096);
PaiementCycle = PaiementCycle - 6;
// If the Data entered in the input box = of the destination adress of API 2 and the cycle of API1 and API2 is the same then
// Here cycle is always = 87 (Last value of the API1 reading (before the function the cycle change from 106 to 87).
// I really don't understand why
if (KT1 == myObj2[y].type.operations[0].destination.tz && PaiementCycle == cycle) {
console.log("Get one");
console.log("Paiement Cycle : " + PaiementCycle);
Paid = "/////////////////" + myObj2[y].type.operations[0].amount/1000000;
console.log("Paid : " + Paid);
txt += "<td width=10% align=center>Paiement :" + Paid + "</td>";
txt += "</tr>";
// All the data saved during this function is saved after the execution or the boucle for(x)
console.log("Txt /////: " + txt);
// document.getElementById("demo2").innerHTML = txt2;
} else {
}//
}
//return txt;
} else {
//console.log("Not Ok");
}
};
xmlhttp2.open("POST", "https://api6.tzscan.io/v3/operations/tz1XynULiFpVVguYbYeopHTkLZFzapvhZQxs?type=Transaction&number=100", true);
xmlhttp2.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp2.send("x=" + dbParam2);
}
txt += "</table>";
console.log("Txt 2 : " + txt);
document.getElementById("demo").innerHTML = txt;
}
};
xmlhttp.open("POST", "https://api6.tzscan.io/v3/delegator_rewards_with_details/" + KT1, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("x=" + dbParam);
You can see here my codepen, you can easily see that my function xmlhttp2.onreadystatechange = function() { only executes itself after xmlhttp.onreadystatechange = function() { instead of after getting each data from the JSON file
try to use JavaScript Promises.
A simple Promise is here

Ajax request: undefined

Hello there i wanted to request an api with ajax.
The api has plain json (what i thought)
now i set up an ajax request in javascript but i get an undefined error for the variables.I think i know the problem but I dont know an answer yet.
<script type="text/javascript">
document.getElementById("button").addEventListener('click', loadUsers);
// Load Github USers
function loadUsers(){
var xhr = new XMLHttpRequest();
xhr.open("GET", "dontKnowtheUrl", true);
xhr.onload = function()
{
if(this.status == 200){
var stats = JSON.parse(this.responseText)
var output = "";
for(var i in stats){
output +=
'<div class="user">' +
'<ul>' +
'<li>p_level: '+stats[i].p_level+'</li>'+
'<li>p_currentmmr: '+stats[i].p_currentmmr+'</li>' +
'</ul>' +
'</div>';
}
document.getElementById("users").innerHTML = output;
}
}
xhr.send();
}
This was the javascript part
the json file from the api looks like this
{"results":
[{"p_id":"test",
"p_name":"test",
"p_level":"test",
"p_platform":"test",
"p_user":"test",
"p_currentmmr":"test",
"p_currentrank":"test",
"kd":"test"},
{"p_id":"test",
"p_name":"test",
"p_level":"test",
"p_platform":"test",
"p_user":"test",
"p_currentmmr":"test",
"p_currentrank":"test",
"kd":"test"}],
"totalresults":2}
My Guess is that the json file isnt a normal array because it contains the "results": and "totalresults" property.
Does Anyone know how to fix it without getting into the json file?
You're going to want to loop through stats.results instead of just stats, see the following example:
function loadUsers(){
var xhr = new XMLHttpRequest();
xhr.open("GET", "dontKnowtheUrl", true);
xhr.onload = function()
{
if(this.status == 200){
var stats = JSON.parse(this.responseText)
var output = "";
for(var i in stats.results){
var row = stats.results[i];
output +=
'<div class="user">' +
'<ul>' +
'<li>p_level: '+row.p_level+'</li>'+
'<li>p_currentmmr: '+row.p_currentmmr+'</li>' +
'</ul>' +
'</div>';
}
document.getElementById("users").innerHTML = output;
}
}
xhr.send();
}

How to set my HTML Table progressively with Javascript/AJAX and Java Servlet?

Hy everyone! I've got a problem developping a little webapp.
The goal is to search for a specific word in files from a stating folder on the server.
To do that, I've implemented a recursive algorithm using java.io.File and a BufferReader.
When I get the results, I had them in a table using a script in my jsp file :
// Posting founded files in a table.
var files = response.getElementsByTagName("file");
// -> Creating the results table.
var table = "<table width=\"100%\">\n";
for (var i = 0, c = files.length; i < c; i++) {
// -> Building the number of apparence in each file.
var nb = files[i].getAttribute("nb");
var nbSentence = "";
if (nb == 1) { nbSentence = nb + " time in this file."; }
else { nbSentence = nb + " times in this file."; }
// Building and filling the table.
if (i % 2 == 0) { table += "<tr class=\"pair\"><td><a href=" + files[i].firstChild.nodeValue + " target=\"_blank\" >"
+ files[i].getAttribute("name") + "</a></td><td>" + nbSentence + "</td></tr>\n"; }
else { table += "<tr class=\"impair\"><td><a href=" + files[i].firstChild.nodeValue + " target=\"_blank\" >"
+ files[i].getAttribute("name") + "</a></td><td>" + nbSentence + "</td></tr>\n"; }
}
table += "</table>\n";
// -> To end the procedure, we had the table to the right div.
document.getElementById("files").innerHTML = table;
My problem is that with this code, all of the results are printed in one tim in the target table. I would like to see the results comming one by one, everytime a file is found in the algorithm.
I've tried to change the readystate to "3" in the onreadystatestage function :
xhr.onreadystatechange = function() {
if (xhr.readyState >= 3 && (xhr.status == 200 || xhr.status == 0)) {
callback(xhr.responseXML);
document.getElementById("loader").style.display = "none";
document.getElementById("btn").value = "Search";
} else if (xhr.readyState < 3) {
document.getElementById("loader").style.display = "inline";
document.getElementById("btn").value = "Cancel";
}
};
But it doesn't change anything.
Does somebody have an idea? How can I send every founded file one by one ? Do I have t do it in the servlet class ?
The for instruction in the servlet class :
// If the input word name isn't empty, the algorithm is launched.
if (null != wordToSearch && !"".equals(wordToSearch))
{
lstFiles.clear();
searching(new File(contextPath), wordToSearch);
int n = lstFiles.size();
// Priting a message that indicate how many files have been found with the word to search.
emptyFieldMessage = n + " files has been found containing the word '" + wordToSearch + "'!";
output.append("<message>").append(emptyFieldMessage).append("</message>\n");
output.append("<lstFiles>\n");
// Then, files list with :
// - File path in "name" parameter,
// - Number of apparence of the word in "nb" parameter,
// - Formatted path as the value.
for(int i = 0; i < n; i++)
{
output.append("<file name=\"" + lstFiles.get(i) + "\" nb=\"" + lstNbApparence.get(i) + "\" >").append(lstFilesPath.get(i)).append("</file>\n");
}
output.append("</lstFiles>\n");
}
To be more complet, the whole script code :
<script>
// Creating xhr variable.
var xhr = null;
// Creating the "Search" button function.
function request(callback) {
// "Cancel" button case.
if (xhr && xhr.readyState != 0)
{
xhr.abort();
}
// "Search" button case.
else
{
// Calling the good function from external file.
xhr = getXMLHttpRequest();
// Callback and loading icon management.
xhr.onreadystatechange = function() {
if (xhr.readyState >= 3 && (xhr.status == 200 || xhr.status == 0)) {
callback(xhr.responseXML);
document.getElementById("loader").style.display = "none";
document.getElementById("btn").value = "Search";
} else if (xhr.readyState < 3) {
document.getElementById("loader").style.display = "inline";
document.getElementById("btn").value = "Cancel";
}
};
// Calling the Servlet in charge of the recursion algorithm.
var input = encodeURIComponent(document.getElementById("wordName").value);
xhr.open("GET", "/webApp_Search_Merge/ActionServlet?wordName=" + input, true);
xhr.send(null);
}
}
// Creating the reponse function.
function readData(response) {
if (null != response)
{
// Posting the message include in the XML file sending back by the Servlet.
var message = response.getElementsByTagName("message");
document.getElementById("message").innerHTML = message[0].firstChild.nodeValue;
// Posting founded files in a table.
var files = response.getElementsByTagName("file");
// -> Creating the results table.
var table = "<table width=\"100%\">\n";
for (var i = 0, c = files.length; i < c; i++) {
// -> Building the number of apparence in each file.
var nb = files[i].getAttribute("nb");
var nbSentence = "";
if (nb == 1) { nbSentence = nb + " time in this file."; }
else { nbSentence = nb + " times in this file."; }
// Building and filling the table.
if (i % 2 == 0) { table += "<tr class=\"pair\"><td><a href=" + files[i].firstChild.nodeValue + " target=\"_blank\" >"
+ files[i].getAttribute("name") + "</a></td><td>" + nbSentence + "</td></tr>\n"; }
else { table += "<tr class=\"impair\"><td><a href=" + files[i].firstChild.nodeValue + " target=\"_blank\" >"
+ files[i].getAttribute("name") + "</a></td><td>" + nbSentence + "</td></tr>\n"; }
}
table += "</table>\n";
// -> To end the procedure, we had the table to the right div.
document.getElementById("files").innerHTML = table;
}
}
Thanks by advance for your help, Thomas.
I tried to set up a working demo, but with no results. I was also searching why I can't find the way to "sleep" a function and re-execute after 1000 milliseconds or whatever you want. Already found an answer to that, but I think it's not really what did you expected:
A sleep function will kill the browser and possibly the machine.
Javascript is single threaded, so the browser will block while this
executes, and the loop itself will just take up a lot of CPU. I’ve
heard of some libraries that actually do sleep correctly in an
asynchronous manner, but I can’t remember the name right now.
This is a very bad idea. JavaScript is single threaded so while that
for loop is running nothing else can execute (js timers, browser
events, even the UI in most browsers). Try to sleep for 5 or more
seconds and the browser will even warn the user that a script is
running slowly.
Just use setTimeout.
Also speaks about a sleep function into Native Javascript. It seems that it's like a framework or something like that. You can download it and try it at your own. I can't say anything about this because I've never tested, it's just what I found on internet.
I'm sorry to give you bad news.

Categories