I want to loop multiple DIV elements.
There are 5 books. I want to loop 5 books in ID: BootLoop.
What I tried?
my_orders.append(data[i].order.bname).appendTo("#bookLoop > div > div > div > h3");
my_orders.append(data[i].order.blink).appendTo("#bookLoop > div > div > div > a");
It didn't work. Where am I making a mistake?
JS:
var my_orders = $("#bookLoop");
$.each(data, function(i, order) {
$("#bookName").append(data[i].order.bname);,
$("#bookURL").append(data[i].order.blink);
});
HTML (Code structure that should be loop):
<div id="bookLoop">
<div class="col-3">
<div class="block-content">
<div class="d-md-flex">
<h3 id="bookName" class="h4 font-w700"></h3>
<div>
<div class="d-md-flex link">
Details
<div>
<div>
<div>
<div>
JSON:
[
{"order":{"id":"61","bname":"Book 1","blink":984}},
{"order":{"id":"42","bname":"Book 2","blink":5414}},
{"order":{"id":"185","bname":"Book 3","blink":4521}},
{"order":{"id":"62","bname":"Book 4","blink":41254}},
{"order":{"id":"15","bname":"Book 5","blink":7464}}
]
I think that what you want is to append each book and link inside #bookLoop, beign each book and link with it's own content.
Below I'm creating elements (nodes) to each book you have then appending it to my_orders.
Take a look if it is what you want, if not, please edit your question showing an example of the desired rendered HTML
var my_orders = $("#bookLoop");
var books = ''
var links = ''
let data = [
{"order":{"id":"61","bname":"Book 1","blink":984}},
{"order":{"id":"42","bname":"Book 2","blink":5414}},
{"order":{"id":"185","bname":"Book 3","blink":4521}},
{"order":{"id":"62","bname":"Book 4","blink":41254}},
{"order":{"id":"15","bname":"Book 5","blink":7464}}
]
$.each(data, function(i, order) {
let col = document.createElement('div')
col.className = 'col-3'
let content = document.createElement('div')
content.className = 'block-content'
let flexC = document.createElement('div')
flexC.className = 'd-md-flex'
let title = document.createElement('h3')
title.className = 'h4 font-w700'
title.textContent = data[i].order.bname;
flexC.append(title)
let flexL = document.createElement('div')
flexL.className = 'd-md-flex link'
let details = document.createElement('a')
details.className = 'bookURL'
details.href = "#"
details.textContent = "Details: " + data[i].order.blink
flexL.append(details)
my_orders.append(col)
col.append(content)
content.append(flexC)
content.append(flexL)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="bookLoop">
<div>
Related
I am completely lost on a task where I have to add a date to the items when they are created, store them in a list and then present on my webpage.
my javascript code
var counter=4;
var completelist = document.getElementById("thelist");
var currentTime = new Date();
todo=[todo1,todo2,todo3];
todoButton.onclick=function addelement() {
var userTodoInput = document.getElementById("todoInput");
if(userTodoInput.value!=="" ){
let node = document.createElement("LI");
node.innerHTML = userTodoInput.value;
completelist.appendChild(node);
todo.push(userTodoInput);
document.getElementById("mydiv").innerHTML += "<div class='todo' ><p id='t-list'> You have added this to the list of actions: " + userTodoInput.value + "</p></br></div>";
} else {
alert("Enter something in textarea")
}
counter++;
}
My dom
<div class="todo-container" >
<h1 class="about-heading">The todo list </h1>
<p id="todo-paragraph">On this page you are able to add new items to your to-do list </p>
<div class="todo-items">
<ul id="thelist">
<li class="todo"id="todo1">Item 1</li>
<li class="todo" id="todo2">Item 2</li>
<li class="todo" id="todo3"> Item 3</li>
</ul>
<input id="todoInput" type="text" name="todoInput" placehoder="Type your to-do here">
<button id="todo-button" >Add Item </button>
<div id="mydiv">
</div>
</div>
what would you suggest on this?
The problem is, your todoButton is not defined anywhere in your code.
If you add var todoButton = document.getElementById("todo-button");, your script should be working.
EDIT:
If you want to append date to user input, check edited code below. I stored userTodoInput and currentTime to single variable, named newItem and then place the variable on places you need it. I hope this help.
var counter = 4;
var completelist = document.getElementById("thelist");
var currentTime = new Date();
todo = [todo1, todo2, todo3];
todoButton.onclick = function addelement() {
var userTodoInput = document.getElementById("todoInput");
if (userTodoInput.value !== "") {
let node = document.createElement("LI");
let newItem = `${userTodoInput.value} ${currentTime}`;
node.innerHTML = newItem;
completelist.appendChild(node);
todo.push(newItem);
document.getElementById("mydiv").innerHTML += "<div class='todo' ><p id='t-list'> You have added this to the list of actions: " + newItem + "</p></br></div>";
} else {
alert("Enter something in textarea")
}
counter++;
Take a look to the following commented code. Obviously it is a basic implementation, but I think that main concepts are clear:
// GET ELEMENTS.
const list = document.getElementById('list');
const input = document.getElementById('input');
const button = document.getElementById('button');
const onClickHandler = () => {
// CHECK FOR TO-DO NAME.
if (input.value) {
// USE ELEMENT CHILDREN COUNT AS INDEX.
const index = list.children.length;
// CREATE li ELEMENT PROGRAMMATICALLY.
const li = document.createElement('LI');
// INSTANTIATE A NEW DATE OBJECT.
const date = new Date();
// ADD ATTRIBUTES.
li.id = `todo${index}`;
li.class = 'todo';
li.innerText = `${input.value} - ${date.toString()}`;
// ADD ELEMENT TO DOM.
list.appendChild(li);
} else {
alert('Please type your to-do.')
}
};
// ADD EVENT LISTENER.
button.addEventListener('click', onClickHandler);
<div>
<h1>The todo list</h1>
<p>On this page you are able to add new items to your to-do list</p>
<div>
<ul id="list"></ul>
</div>
<input id="input" type="text" name="todo" placeholder="Type your to-do here">
<button id="button" type="button">Add Item</button>
</div>
I'm attempting to make an automatic ToC that can be dropped on a page. All of the pages have h3 tags with id set already. All of the code I'm finding wants to create the id for the tags first, but the pages I'm working on already have tags.
Basically I just need the code to
Step through all h3s on the page and get the ID and the text.
Create links to each of the h3s using the ID and text Text
Here's the code I've tried:
$(document).ready(function() {
setTimeout(() => {
// Get ToC div
toc = document.getElementById("ToC"); //Add a header
tocHeader = document.createElement("h2");
tocHeader.innerText = "Table of contents";
toc.appendChild(tocHeader); // Get the h3 tags — ToC entries
$('h3').each(function() {
var headers = $(this).attr('id');
var name = $(this).text();
});
// For each h3
for (i = 0; i < headers.length; i++) {
tocListItem = document.createElement("li");
// a link for the h3
tocEntry = document.createElement("a");
tocEntry.setAttribute("href", "#" + name);
tocEntry.innerText = name[i];
tocListItem.appendChild(tocEntry);
tocList.appendChild(tocListItem);
}
toc.appendChild(tocList);
// Create a list for the ToC entries
tocList = document.createElement("ul");
}, 1000);
});
<body>
<div id="ToC"></div>
<div>
<h3 id="this-is-heading-1">First Heading</h1>
<p>
This is paragrah 1
</p>
<h3 id="another-heading">Second Section</h1>
<p>
This is some words
</p>
<h3 id="last-heading">And Finally</h1>
<p>
Some more verbiage
</p>
</div>
</body>
Simply you can go through of each h3 and get id attribute and then create link to corresponding element.
Try this one:
$(document).ready(function () {
setTimeout(() => {
// Get ToC div
toc = document.getElementById("ToC"); //Add a header
tocHeader = document.createElement("h2");
tocHeader.innerText = "Table of contents";
toc.appendChild(tocHeader); // Get the h3 tags — ToC entries
// Create a list for the ToC entries
tocList = document.createElement("ul");
$('h3').each(function () {
tocListItem = document.createElement("li");
// a link for the h3
tocEntry = document.createElement("a");
tocEntry.setAttribute("href", "#" + $(this).attr('id'));
tocEntry.innerText = $(this).text();
tocListItem.appendChild(tocEntry);
tocList.appendChild(tocListItem);
});
toc.appendChild(tocList);
});
});
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div id="ToC"></div>
<div>
<h3 id="this-is-heading-1">
First Heading
</h3>
<p>
This is paragrah 1
</p>
<h3 id="another-heading">
Second Section
</h3>
<p>
This is some words
</p>
<h3 id="last-heading">
And Finally
</h3>
<p>
Some more verbiage
</p>
</div>
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 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);
});
}