Javascirpt: How to pass JSON response as parameter from onreadystatechange? - javascript

So I'm trying to get a list of JSON objects and then loop through its elements via fori loop, creating <li> and <a> elements.
Everything works smoothly except when I try to add an onclick function to the in each iteration. I'm trying to pass the json object to the onclick function, but all tags have are showing the last json object.
What I need is for every <a> to show its corresponding json object when clicked.
Please see the code:
var url = "https://restcountries.eu/rest/v2/all"
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var countries = JSON.parse(xhttp.responseText)
var ul = document.getElementById('countries')
for (var i = 0; i < countries.length; i++) { //start iteration
var li = document.createElement("LI")
var img = document.createElement("IMG")
var a = document.createElement("A")
var textNode = document.createTextNode(countries[i].name)
img.setAttribute("src", countries[i].flag)
ul.appendChild(li)
li.appendChild(a)
a.appendChild(img)
a.appendChild(textNode);
a.setAttribute("title", countries[i].name)
var country = countries[i]
a.onclick = function(){ CountryClicked(country)} //pass the current JSON to the onclick function of the current <a> Node, this isn't working correctly.
}
}
}
xhttp.open('GET', url, true);
xhttp.send();
function CountryClicked(country){
var div = document.getElementById("parent-country-container")
var h1 = document.createElement("h1")
// div.appendChild(h1)
h1.appendChild(document.createTextNode(country.name + " Clicked"))
div.innerHTML = ""
div.appendChild(h1)
}
Thank you for your time.

It is neccesary to use a closures function to be able to send the right country.
function CountryClicked(el) {
alert(el.name);
}
var countries = [{'flag':'xx',name:'name'}, {'flag':'xx',name:'text 2'}];
var ul = document.getElementById('countries')
for (var i = 0; i < countries.length; i++) { //start iteration
var li = document.createElement("LI")
var img = document.createElement("IMG")
var a = document.createElement("A")
var textNode = document.createTextNode(countries[i].name)
img.setAttribute("src", countries[i].flag)
ul.appendChild(li)
li.appendChild(a)
a.appendChild(img)
a.appendChild(textNode);
a.setAttribute("title", countries[i].name)
var country = countries[i];
a.onclick = (function(country){
return function(){ CountryClicked(country); }
})(country);
}
<ul id="countries"></ul>

Related

$ dot each not working for recursion (JS)

I have a loop in which I am calling rec_append() recursively, apparently the first pass alone works, then the loop stops.
I have an array of 4 elements going into that $.each loop but I see only the first element going into the function recursively. Help!
I switched it for a element.forEach but that gives me only the second element and I am stuck, is there a better solution to process a tree of elements? My array is a part of a tree.
var data = JSON.parse(JSON.stringify(result))
var graph = $(".entry-point");
function rec_append(requestData, parentDiv) {
var temp_parent_details;
$.each(requestData, function (index, jsonElement) {
if (typeof jsonElement === 'string') {
//Element construction
//Name and other details in the form of a : delimited string
var splitString = jsonElement.split(':');
var details = document.createElement("details");
var summary = document.createElement("summary");
summary.innerText = splitString[0];
details.append(summary);
temp_parent_details = details;
parentDiv.append(details);
var kbd = document.createElement("kbd");
kbd.innerText = splitString[1];
summary.append(' ');
summary.append(kbd);
var div = document.createElement("div");
div.className = "col";
details.append(div);
var dl = document.createElement("dl");
div.append(dl);
var dt = document.createElement("dt");
dt.className = "col-sm-1";
dt.innerText = "Path";
div.append(dt);
var dd = document.createElement("dd");
dd.className = "col-sm-11";
dd.innerText = splitString[2];
div.append(dd);
var dt2 = document.createElement("dt");
dt2.className = "col-sm-1";
dt2.innerText = "Type";
div.append(dt2);
var dd2 = document.createElement("dd");
dd2.className = "col-sm-11";
dd2.innerText = splitString[1];
div.append(dd2);
} else {
$.each(jsonElement, function (jsonElementArrIndx, jsonChildElement) {
rec_append(jsonChildElement, temp_parent_details); //Only 1 pass works, rest skip
});
}
});
}
rec_append(data, graph);
Sample data:enter image description here

global string array in javascript

As you can see, I have defined a global variable called filas, which in the function get_filas (full_text), I assign it the value full_text.split (": & ^").Then I must use that assigned value in the following function () but I get the following console output: Unncaught TypeError: Cannot read property 'split' of undefined.
How then is it possible to define the rows variable and assign it a data to then use them in another function?
var filas;
var cantidad_de_eventos_vistos;
window.onload = function(){
get_data();
var ul = document.getElementById("dynamic-list");
ul.onclick = function(event) {
var target = getEventTarget(event);
alert(target.innerHTML);
};
cantidad_de_eventos_vistos=2;
}
function get_data(){
console.log("algo");
var request = new XMLHttpRequest();
var url = 'http://192.168.0.248:10000'
request.open("POST", url, true);
var header="#:::|$&!";
var mensaje = "get_data"
request.send(header+mensaje);
request.onreadystatechange = function() { // Call a function when the state changes.
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
console.log(request.responseText);
get_filas(request.responseText);
}
}
}
function get_filas(texto_completo){
filas=texto_completo.split(":&^");
if (2 < filas.length){
for (var i = 1; i < 2+1; i++) {
var ul = document.getElementById("dynamic-list");
var candidate = document.getElementById("candidate");
var li = document.createElement("li");
li.setAttribute('id',filas[i].split(";¬")[0]);
li.appendChild(document.createTextNode(filas[i].split(";¬")[0]));
ul.appendChild(li);
cantidad_de_eventos_vistos=cantidad_de_eventos_vistos+2;
}
btn_siguiente.style.visibility="visible"
}
else{
for (var i = 1; i < filas.length; i++) {
var ul = document.getElementById("dynamic-list");
var candidate = document.getElementById("candidate");
var li = document.createElement("li");
li.setAttribute('id',filas[i].split(";¬")[0]);
li.appendChild(document.createTextNode(filas[i].split(";¬")[0]));
ul.appendChild(li);
}
}
}
function siguiente(){
var ul = document.getElementById("dynamic-list");
ul.parentNode.removeChild(ul);
for (var i = 1+cantidad_de_eventos_vistos; i < cantidad_de_eventos_vistos+2+1; i++) {
var candidate = document.getElementById("candidate");
var li = document.createElement("li");
li.setAttribute('id',filas[i].split(";¬")[0]);
li.appendChild(document.createTextNode(filas[i].split(";¬")[0]));
ul.appendChild(li);
if(cantidad_de_eventos_vistos!=filas.length){
cantidad_de_eventos_vistos=cantidad_de_eventos_vistos+2;
btn_siguiente.style.visibility="hide";
}
}
}

append onclick event to anchor element that returns id

below I'm trying to add new anchor elements to the DOM.
I also like to add an onclick event to each new created element that returns its id, but can't get it done.
All help is welcome!
var text = document.getElementById("output");
for (var i = 0; i < uld.length; i++){
var x = document.createElement("A");
var t = document.createTextNode(uld[i][1]);
x.setAttribute('id', i);
x.onclick = function getId() {alert("kikker");};
x.appendChild(t);
text.appendChild(x);
}
The 'this' pointer in a onclick is refering to the element.
So you could use the 'id' like this:
var text = document.getElementById("output");
var i;
for (i = 0; i < uld.length; i++) {
var x = document.createElement("A");
var t = document.createTextNode(uld[i][1]);
x.setAttribute("id", i);
x.onclick = function() {
var id = this.id;
alert(id);
};
x.appendChild(t);
text.appendChild(x);
}

Write arrays content in my page using javascript

I'm studying javascript for the first time and I've some doubt: I have two arrays; the first one contain the image of a person, the second one his personal informations (the arrays' length is the same because they contain the same number of people). I'd like to write the content in my page so print the image and the infos of the first user, then the image and the infos of the second and so on...
How can I do it?
this is the code:
function jsonCard()
{
var richiestaCard = new XMLHttpRequest();
richiestaCard.onreadystatechange = function()
{
if(richiestaCard.readyState == 4)
{
var objectcardjson = {};
window.arrayCard= []; //creazione dell'array che conterrà le cards
objectcardjson = JSON.parse(richiestaCard.responseText);
arrayCard = objectcardjson.cards; //the first array
}
}
richiestaCard.open("GET", "longanocard.json", true);
richiestaCard.send(null);
}
function jsonEntity()
{
var richiestaEntity = new XMLHttpRequest();
richiestaEntity.onreadystatechange = function()
{
if(richiestaEntity.readyState == 4)
{
var objectentityjson = {};
window.arrayEntity= []; //creazione dell'array che conterrà le entity
objectentityjson = JSON.parse(richiestaEntity.responseText);
arrayEntity = objectentityjson.cards; //the second array
}
}
richiestaEntity.open("GET", "longano.json", true);
richiestaEntity.send(null);
}
function displayArrayCards()
{
jsonCard();
jsonEntity();
var inizioTag = "<img src=";
var fineTag = "\>";
for(i = 0; i < arrayCard.length; i++)
{
...
}
}
I'd like to have the image and then the infos (for the first user), the image and the infos for the second and so on all included in a div.
Try something along the lines of
function displayArrayCards()
{
jsonCard();
jsonEntity();
var wrapper = document.getElementById('div you want to put all of these users into');
for(i = 0; i < arrayCard.length; i++)
{
var userDiv = document.createElement('div');
var cardImg = document.createElement('img');
img.src = arrayCard[i];
/** Set other attributes for img **/
var entityDiv = document.createElement('div');
entityImg.innerHTML = arrayEntity[i];
/** Set other attributes for div **/
userDiv.appendChild(cardImg);
userDiv.appendChild(entityDiv);
wrapper.appendChild(userDiv);
}
}
Honestly there are a lot of ways to do this. Above is simply what I would do.

JQuery with several Elements issue

i got an anchor in the DOM and the following code replaces it with a fancy button. This works well but if i want more buttons it crashes. Can I do it without a for-loop?
$(document).ready(buttonize);
function buttonize(){
//alert(buttonAmount);
//Lookup for the classes
var button = $('a.makeabutton');
var buttonContent = button.text();
var buttonStyle = button.attr('class');
var link = button.attr('href');
var linkTarget = button.attr('target');
var toSearchFor = 'makeabutton';
var toReplaceWith = 'buttonize';
var searchButtonStyle = buttonStyle.search(toSearchFor);
if (searchButtonStyle != -1) {
//When class 'makeabutton' is found in string, build the new classname
newButtonStyle = buttonStyle.replace(toSearchFor, toReplaceWith);
button.replaceWith('<span class="'+newButtonStyle
+'"><span class="left"></span><span class="body">'
+buttonContent+'</span><span class="right"></span></span>');
$('.buttonize').click(function(e){
if (linkTarget == '_blank') {
window.open(link);
}
else window.location = link;
});
}
}
Use the each method because you are fetching a collection of elements (even if its just one)
var button = $('a.makeabutton');
button.each(function () {
var btn = $(this);
var buttonContent = btn.text();
var buttonStyle = btn.attr('class');
var link = btn.attr('href');
var linkTarget = btn.attr('target');
var toSearchFor = 'makeabutton';
var toReplaceWith = 'buttonize';
var searchButtonStyle = buttonStyle.search(toSearchFor);
...
};
the each method loops through all the elements that were retrieved, and you can use the this keyword to refer to the current element in the loop
var button = $('a.makeabutton');
This code returns a jQuery object which contains all the matching anchors. You need to loop through them using .each:
$(document).ready(buttonize);
function buttonize() {
//alert(buttonAmount);
//Lookup for the classes
var $buttons = $('a.makeabutton');
$buttons.each(function() {
var button = $(this);
var buttonContent = button.text();
var buttonStyle = button.attr('class');
var link = button.attr('href');
var linkTarget = button.attr('target');
var toSearchFor = 'makeabutton';
var toReplaceWith = 'buttonize';
var searchButtonStyle = buttonStyle.search(toSearchFor);
if (searchButtonStyle != -1) {
newButtonStyle = buttonStyle.replace(toSearchFor, toReplaceWith);
button.replaceWith('<span class="'
+ newButtonStyle
+ '"><span class="left"></span><span class="body">'
+ buttonContent
+ '</span><span class="right"></span></span>');
$('.buttonize').click(function(e) {
if (linkTarget == '_blank') {
window.open(link);
} else window.location = link;
}); // end click
} // end if
}); // end each
}

Categories