I have this simple code with 5 paramaters taken from an API that logs data:
for (i = 0; i < arr.length-1; i++) {
console.log('For Calls')
console.log(arr[i].league.name)
console.log(arr[i].teams.home.name, arr[i].goals.home)
console.log(arr[i].teams.away.name, arr[i].goals.away)
}
it logs this data to the console (2 sets of data shown):
Logged Data
The issue I am having is trying to display this looped content to the website, I haven't even been able to get it on the screen so far using the .append methods.
Here is the format I am trying to create:
<div class="parentDiv">
<div class="league">Data goes here</div>
<div class="team1">Data goes here</div>
<div class="score1">Data goes here</div>
<div class="team2">Data goes here</div>
<div class="score2">Data goes here</div>
</div>
I am aware I can give each div a class and append that way but I need this in a loop so those methods do not work for me in this circumstance.
Any Tips are Appreciated.
My current attempt:
for (i = 0; i < filtered.length-1; i++) {
let parent = document.createElement("div")
parent.className = 'parentDiv'
let homeTeamName = document.createElement("div")
homeTeamName.className = 'league'
homeTeamName.innerHTML = filtered[i].league.name
parent.appendChild(homeTeamName)
let homeTeamScore = document.createElement("div")
homeTeamScore.className = 'team1'
homeTeamScore.innerHTML = filtered[i].teams.home.name
parent.appendChild(homeTeamScore)
let awayTeamName = document.createElement("div")
awayTeamName.className = 'score1'
awayTeamName.innerHTML = filtered[i].teams.home.name
parent.appendChild(awayTeamName)
let awayTeamScore = document.createElement("div")
awayTeamScore.className = 'team2'
awayTeamScore.innerHTML = filtered[i].teams.home.name
parent.appendChild(awayTeamScore)
}
It prints nothing to the dom, blank page. You can use the web console at footballify.net/test
You never Attach the "parent" variable to your body
Try:
document.body.append(parent) at the end
Related
I'm a beginner in JavaScript. I've got a problem.
I need to create some elements and I need to put my API's data is these elements. But I want to create 3 cards (bootstraps) in my first row and 2 in my second row.
But I think my loop isn't ok. Because all my data are on my fifth card.
That's my code HTML and JavaScript:
HTML :
</section>
<section class="container">
<div class="row">
<div id="colCam1" class="col-12 col-lg-4"></div>
<div id="colCam2" class="col-12 col-lg-4"></div>
<div id="colCam3" class="col-12 col-lg-4"></div>
</div>
<div class="row">
<div id="colCam4" class="col-12 col-lg-4"></div>
<div id="colCam5" class="col-12 col-lg-4"></div>
</div>
</section>
JS :
fetch("http://localhost:3000/api/cameras")
.then((response) =>
response.json().then ((data) => {
console.log(data);
for(i=0; i < data.length; i++) {
let indexCard = document.createElement("div");
let indexImg = document.createElement("img");
let indexBodyCard = document.createElement("div");
let indexProductTitle = document.createElement("h5");
let indexProductPrice = document.createElement("p");
colCam1.appendChild(indexCard);
colCam2.appendChild(indexCard);
colCam3.appendChild(indexCard);
colCam4.appendChild(indexCard);
colCam5.appendChild(indexCard);
indexCard.classList.add("card");
indexCard.appendChild(indexImg);
indexImg.classList.add("card-img-top");
indexCard.appendChild(indexBodyCard);
indexBodyCard.classList.add("card-body");
indexBodyCard.appendChild(indexProductTitle)
indexProductTitle.classList.add("card-title");
indexBodyCard.appendChild(indexProductPrice);
indexProductPrice.classList.add("card-text");
indexProductTitle.innerHTML = data[i].name;
indexProductPrice.innerHTML = parseInt(data[i].price) + " €";
indexImg.setAttribute("src", data[i].imageUrl);
}
})
);
That's the result on my inspector :
Result of my code
Thx for your help
If I understood correctly, you are only expecting to get 5 elements from your API and you want to put each of them in one column. If that's the case, you can put your column elements in an array and index them accordingly in your loop like so:
const cols = [colCam1, colCam2, colCam3, colCam4, colCam5]
for(i=0; i < data.length; i++) {
let indexCard = document.createElement("div");
let indexImg = document.createElement("img");
let indexBodyCard = document.createElement("div");
let indexProductTitle = document.createElement("h5");
let indexProductPrice = document.createElement("p");
cols[i].appendChild(indexCard);
indexCard.classList.add("card");
indexCard.appendChild(indexImg);
indexImg.classList.add("card-img-top");
indexCard.appendChild(indexBodyCard);
indexBodyCard.classList.add("card-body");
indexBodyCard.appendChild(indexProductTitle)
indexProductTitle.classList.add("card-title");
indexBodyCard.appendChild(indexProductPrice);
indexProductPrice.classList.add("card-text");
indexProductTitle.innerHTML = data[i].name;
indexProductPrice.innerHTML = parseInt(data[i].price) + " €";
indexImg.setAttribute("src", data[i].imageUrl);
}
This code is going to break if your API returns more than 5 elements. You could try something like cols[i % 5].appendChild(indexCard); or consider other layout strategies.
I'm using newsapi to request JSON data, and am then dynamically loading it onto the page without reloading the page/going onto another page.
When the user initially goes onto the site, a request made on the backend will automatically be made and load the results onto the site via an EJS template. There will also be a button at the bottom of the page, so when a user clicks on it, new articles will be loaded.
The issue is that when the user clicks on the button, the new articles aren't appended after the last instance of a card-container. For example, say I have articles 1 2 3 4 5 already on the page and want to load articles 6 7 8 9, after clicking the button the articles are now in the order of 1 6 2 7 3 8 4 9 5. Where I want it to be in the order 1 2 3 4 5 6 7 8 9.
I've thought by using Jquerys insertAfter() function to insert each new element after the last would work, but it clearly doesn't.
Whilst the code I have below may be messy, I want to fix the logic before tidying it up.
JS
let more = document.getElementById("test");
more.addEventListener("click", function () {
(async () => {
const data = await fetch('http://localhost:3000/articles/');
const articles = await data.json()
for (let i = 0; i < articles.articles.length; i++) {
let newDate = articles.articles[i].date;
newDate = newDate.substring(0, newDate.indexOf('T')).split("-");
var articleList = document.getElementsByClassName("card-container");
var lastArticle = articleList[articleList.length - 1];
let cardContainer = document.createElement('div');
cardContainer.className += "card-container";
let card = document.createElement('div');
card.className += "card";
let content = document.createElement('div');
content.className += "content";
let thumbnail = document.createElement('div');
thumbnail.className += "thumbnail";
let image = document.createElement('img');
image.className += "image";
let text = document.createElement('div');
text.className += "text";
let title = document.createElement('div');
title.className += "title";
let a = document.createElement('a');
let meta = document.createElement('div');
meta.className += "meta";
let source = document.createElement('div');
source.className += "source";
let date = document.createElement('div');
date.className += "date";
document.getElementsByClassName('card-container')[i]
.appendChild(card).appendChild(content).appendChild(thumbnail)
.appendChild(image)
document.getElementsByClassName("content")[i]
.appendChild(text).appendChild(title).appendChild(a)
document.getElementsByClassName("text")[i]
.appendChild(meta).appendChild(source)
document.getElementsByClassName("meta")[i]
.appendChild(date)
let container = document.getElementById('article-container')
container.innerHTML = container.innerHTML + cardContainer;
image.setAttribute("src", articles.articles[i].image)
a.setAttribute('href', articles.articles[i].link);
a.innerHTML = articles.articles[i].title;
source.innerHTML = articles.articles[i].source.name;
date.innerHTML = newDate[1] + " " + newDate[2] + " " + newDate[0];
}
})();
})
Desired markup
<div class="card-container">
<div class="card">
<!-- Post-->
<div class="content">
<!-- Thumbnail-->
<div class="thumbnail">
<img
src="https://ssio.azurewebsites.net/x500,q75,jpeg/http://supersport-img.azureedge.net/2019/8/Man-City-190804-Celebrating-G-1050.jpg" />
</div>
<!-- Post Content-->
<div class="text">
<div class="title"><a
href="https://www.goal.com/en-gb/lists/deadline-day-dybala-coutinho-premier-league-transfers-happen/68rpu0erk0e81pm2anfv2ku16">Coutinho
llega a un acuerdo con el Arsenal para marcharse del Barcelona - PASIÓN
FUTBOL</a>
</div>
<div class="meta">
<div>Source</div>
<div class="date-text">07 07 2019</div>
</div>
</div>
</div>
</div>
</div>
JS Fiddle
I seem to have got it working - but not all of the JSON (other than the image) are being mapped to their divs inner HTML :/
https://jsfiddle.net/georgegilliland/ofxtsz2a/5/
In order to append in pure JS you have to take the last content of the container, append new data to it, then replace the container content with the new data.
I wrote a jsfiddle based on the stack overflow question I posted in the comment : https://jsfiddle.net/HolyNoodle/bnqs83hr/1/
var container = document.getElementById('container')
for(var i = 0; i < 3; i++) {
container.innerHTML = container.innerHTML + "<p>" + i + "</p>"
}
Here you can see I am getting the container inner html, appending new value to it, then replacing the container inner html by the new html
Fixed the issue... The problem was that I was getting elements by class name at whatever index the for loop was on. So if the for loop was on it's 5th iteration, it was appending content to the 5th instance of content, rather than appending it to the end of the container.
document.getElementById('article-container')
.appendChild(cardContainer)
.appendChild(card).appendChild(content).appendChild(thumbnail)
.appendChild(image)
document.getElementsByClassName("content")[i]
.appendChild(text).appendChild(title).appendChild(a)
document.getElementsByClassName("text")[i]
.appendChild(meta).appendChild(source)
document.getElementsByClassName("meta")[i]
.appendChild(date)
What I did to fix this was get the number of elements with the classname card-container before the for loop:
let nodelist = document.getElementsByClassName("card-container").length;
And then get elements at the index of the for loop summed with the amount nodelist.
document.getElementById('article-container')
.appendChild(cardContainer)
.appendChild(card).appendChild(content).appendChild(thumbnail)
.appendChild(image)
document.getElementsByClassName("content")[i + nodelist]
.appendChild(text).appendChild(title).appendChild(a)
document.getElementsByClassName("text")[i + nodelist]
.appendChild(meta).appendChild(source)
document.getElementsByClassName("meta")[i + nodelist]
.appendChild(date)
I want to assign array elements to multiple divs which also have image tag in them using for loop.
Array consists of image paths.
var img_list = ["one.png", "two.png", "three.png", "four.png"];
By using above array I have to create below HTML Structure. All divs should be inside "outer" div with a data-slide attribute which is without ".png".
<div id="outer">
<div class="slide" data-slide="one"><img src="Images/one.png" /></div>
<div class="slide" data-slide="two"><img src="Images/two.png" /></div>
<div class="slide" data-slide="three"><img src="Images/three.png" /></div>
<div class="slide" data-slide="four"><img src="Images/four.png" /></div>
</div>
This is what I wrote:
for (var i=0; i < img_list.length; i++){
var container = document.getElementById("outer").innerHTML;
var new_card = "<div class=\"slide\" data-slide=\'" + img_list[i] + "\'><img src=\'Images/" + img_list[i] + "\' /></div>";
document.getElementById("outer").innerHTML = new_card;
}
But it is only showing the last image.
Please help.
Each time your for loop runs, it is replacing the html element within the "outer" div with the current img html.
In order to have it append you can simply change
document.getElementById("outer").innerHTML = new_card;
to
document.getElementById("outer").innerHTML += new_card; so that the element is appended rather than overwritten.
The code at the question overwrites the .innerHTML within the for loop by setting .innerHTML to new_card at every iteration of the array. You can substitute .insertAdjacentHTML() for setting .innerHTML. Also, substitute const for var to prevent new_card from being defined globally. Include alt attribute at <img> element. You can .split() img_list[0] at dot character ., .shift() the resulting array to get word before . in the string img_list[i] to set data-* attribute value.
const img_list = ["one.png", "two.png", "three.png", "four.png"];
for (let i = 0, container = document.getElementById("outer"); i < img_list.length; i++) {
const src = img_list[i];
const data = src.split(".").shift();
const new_card = `<div class="slide" data-slide="${data}"><img src="Images/${src}" alt="${data}"/></div>`;
container.insertAdjacentHTML("beforeend", new_card);
}
<div id="outer"></div>
You are changing the innerHTML you need to add to it. And use Template literals for creating html strings
var img_list = ["one.png", "two.png", "three.png", "four.png"];
const outer = document.getElementById('outer')
img_list.forEach(img => {
outer.innerHTML += `<div class="slider" data-slide="${img.split('.')[0]}"><img src="Images/${img}" /></div>`
})
console.log(outer.innerHTML)
<div id="outer">
</div>
#Tony7931, please replace the last line of for loop with below code:
document.getElementById("outer").innerHTML += new_card;
You are almost there but, every time you are overriding the slider div.
You just have to add + at assignments section. like below.
document.getElementById("outer").innerHTML += new_card;
Here is the full example:
var img_list = ["one.png", "two.png", "three.png", "four.png"];
for (var i=0; i < img_list.length; i++){
var container = document.getElementById("outer").innerHTML;
var new_card = "<div class=\"slide\" data-slide=\'" + img_list[i].split('.')[0] + "\'><img src=\'Images/" + img_list[i] + "\' /></div>";
document.getElementById("outer").innerHTML += new_card;
}
<div id="outer"></div>
You could also use map method of array and Element.innerHTML to get the required result.
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
Demo
const img_list = ["one.png", "two.png", "three.png", "four.png"];
let result = img_list.map((v, i) => `<div class="slide" data-slide="${v.split(".")[0]}"><img src="Images/${v}"/>${i+1}</div>`).join('');
document.getElementById('outer').innerHTML = result;
<div id="outer"></div>
You can declare your variables outside of the loop and reuse them. This is more efficient.
const and let are preferable to var. You only need to set container once so it can be const. new_card should be let since you need to assign it more than once.
You can also use template string so you don't need all the back slashes.
using forEach will make the code cleaner:
const img_list = ["one.png", "two.png", "three.png", "four.png"];
const container = document.getElementById("outer")
let new_card;
img_list.forEach(i => {
new_card = `<div class=slide data-slide='${i.split(".")[0]}'><img src='Images/${i}'></div>`
container.innerHTML += new_card;
})
<div id="outer">
</div>
Alternately, using reduce:
const img_list = ["one.png", "two.png", "three.png", "four.png"];
const container = document.getElementById("outer")
const reducer = (a, i) => a + `<div class=slide data-slide='${i.split(".")[0]}'><img src='Images/${i}'></div>`
container.innerHTML = img_list.reduce(reducer, '')
<div id="outer">
</div>
Every time a selection is made from a dropdown menu, specific data is pulled from facebook and added to different divs. I am trying to update the contents of the div every time a different selection is made, however at the minute, the contents are just appended on after the initial contents.
This is the code that gets data based on a selection and creates the list from the returned data
<script>
city = document.getElementById("citySelection")
city.addEventListener("change", function() {
var selected = this.value;
var eventsList = document.getElementById("events");
if (selected == "None") {
eventsList.style.display = "none";
} else {
eventsList.style.display = "block";
};
if (selected == 'Bristol') {
getBristolEvents();
};
if (selected == 'Leeds') {
getLeedsEvents();
};
if (selected == 'Manchester') {
getManchesterEvents();
};
if (selected == 'Newcastle') {
getNewcastleEvents();
};
});
function createList(response, listId) {
var list = document.createElement('UL')
for (var i = 0; i < 10; i++) {
var events = response.data[i].name
var node = document.createElement('LI');
var textNode = document.createTextNode(events);
node.appendChild(textNode);
list.appendChild(node)
listId.appendChild(list);
}};
</script
This is the div being targeted:
<html>
<div id="events" style="display: none">
<div id="eventsDiv" style="display: block">
<div id="eventsListOne">
<h3 id='headerOne'></h3>
</div>
<div id="eventsListTwo">
<h3 id='headerTwo'></h3>
</div>
<div id="eventsListThree">
<h3 id='headerThree'></h3>
</div>
</div>
</div>
</div>
</html>
I have tried resetting the innerHtml of the div every time the function to get the data from facebook is called:
<script>
function getEventsThree(fbUrl, title) {
var listId = document.getElementById('eventsListThree');
var headerThree = document.getElementById('headerThree');
listId.innerHtml = "";
headerThree.append(title)
FB.api(
fbUrl,
'GET', {
access_token
},
function(response) {
listId.innerHtml = createList(response, listId)
}
)};
</script>
However, that still doesn't reset the contents of the div.
I've looked at other response but they all use jquery which I am not using.
Can anyone advise on the best way to fix this? Thanks.
I think your Hennessy approach is fine. Generate the inner content, then set .innerHTML.
At least one of your problems, maybe the only one, appears to be that you set .innerHTML to the return value of createList, but that function does not return anything.
I want to create a list of clickable divs from arrays using Javascript, where the list structure has to be something like this:-
<div id="outerContainer">
<div id="listContainer">
<div id="listElement">
<div id="itemId"> </div>
<div id="itemTitle"> </div>
<div id="itemStatus"> </div>
</div>
<div id="listElement">
<div id="itemId"> </div>
<div id="itemTitle"> </div>
<div id="itemStatus"> </div>
</div>
</div>
</div>
I want to extract the values of itemId, itemTitle and itemStatus from three arrays itemIdData[ ], itemTitleData[ ] and itemStatusData[ ] respectively, to create the whole list.
Also, when I click on any of the listElements, I want an alert showing the itemId. Can anyone help me with this problem.
If you're using jQuery, then try something like this:
$("#listContainer").on("click", "div", function () {
console.log("jQuery Event Delegation");
alert($(this).find(">:first-child").attr("id"));
});
It's possible to write the same thing without jQuery, but will take further lines of code - I'm conveying the idea of delegation here (there are extensive existing docs and examples on the JQuery site, and here on this site).
NB: the code you're submitted in the question can't(shouldn't) have multiple DOM elements with same IDs (that's what classes are for - for semantically similar elements). Also, trying to emulate a list using divs instead of li elements is perhaps not best practice.
After a bit of experimentation, understood what I was doing wrong and how to get it done.
Here's the code:-
var listContainer = document.createElement("div");
document.getElementById("outerContainer").appendChild(listContainer);
for (var i = 0; i < json.length; i++) {
//create the element container and attach it to listContainer.
var listElement = document.createElement("div");
listElement.id = i;
listElement.className = "listItemContainer";
listElement.addEventListener("click", function(e){
var itemId = e.target.children[1].innerHTML;
alert(itemId);
});
listContainer.appendChild(listElement);
//create and attach the subchilds for listElement.
var itemTitle = document.createElement("span");
itemTitle.innerHTML = postTitleData[i];
itemTitle.id = 'title'+i;
itemTitle.className = "itemTitle";
listElement.appendChild(itemTitle);
var itemId = document.createElement("div");
itemId.innerHTML = postIdData[i];
itemId.id = 'id'+i;
itemId.className = "itemId";
listElement.appendChild(itemId);
var itemStatus = document.createElement("span");
itemStatus.innerHTML = postStatusData[i];
itemStatus.id = 'status'+i;
itemStatus.className = "itemStatus";
listElement.appendChild(itemStatus);
}
Tried something like this which isn't quite working!
var listContainer = document.createElement("div");
document.getElementById("outerContainer").appendChild(listContainer);
var listElement = document.createElement("div");
listContainer.appendChild(listElement);
listElement.className = "listItemContainer";
for (var i = 0; i < json.length; i++) {
var itemId = document.createElement("div");
itemId.innerHTML = idData[i];
listElement.appendChild(itemId);
itemId.className = "itemId";
var itemTitle = document.createElement("div");
itemTitle.innerHTML = titleData[i];
listElement.appendChild(itemTitle);
itemTitle.className = "itemTitle";
var itemStatus = document.createElement("div");
itemStatus.innerHTML = statusData[i];
listElement.appendChild(itemStatus);
itemStatus.className = "itemStatus";
listElement.appendChild(document.createElement("hr"));
var elementId = 'ListElement'+i;
listElement.id = elementId;
listElement.addEventListener("click", function(){
alert(document.getElementById(elementId).innerHTML);
});
}