I want to concatinate class name with variable count which keep getting updated after each button click, for which I am getting error as "citysName is null". can anyone suggest
button.addEventListener('click', resp => {
count = count +1;
var card = document.createElement('card');
card.innerHTML = `
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
**<h5 class="card_title" + count></h5>
<h6 class="temp" + count></h6>
<p class="card-text" + count></p>**
</div>
`;
card.className = 'card';
var content = document.getElementById('id1');
content.appendChild(card);
**var citysName = document.querySelector('.card_title'+count);
var description = document.querySelector('.card-text'+count);
var temp = document.querySelector('.temp'+count);**
fetch('https://api.openweathermap.org/data/2.5/weather?q='+inputVal.value+'&appid=a5599c020b0d897cbc8b52d547289acc')
.then(post => post.json())
.then(data => {
var cityName = data['name'];
var temper = data['main']['temp'];
var descrip = data['weather'][0]['description'];
let ctemp = Math.round(temper-273);
citysName.innerHTML = cityName;
temp.innerHTML = ctemp + "°C";
description.innerHTML = descrip;
})
})
First of all thats not how you add variables using template literals you can read more about it here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Second why do you query it again when you've just made the element you can use card as reference and if you need something within it, its much easier to access it using the variable you already have other than looking for it in your document
Maybe something like this but its hard to tell withouth more code etc
button.addEventListener('click', resp => {
count = count +1;
var card = document.createElement('card');
card.innerHTML = `
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
**<h5 class="card_title${count}"></h5>
<h6 class="temp${count}"></h6>
<p class="card-text${count}"></p>**
</div>
`;
card.className = 'card';
var content = document.getElementById('id1');
content.appendChild(card);
var citysName = card.querySelector('.card_title'+count);
var description = card.querySelector('.card-text'+count);
var temp = card.querySelector('.temp'+count);
fetch('https://api.openweathermap.org/data/2.5/weather?q='+inputVal.value+'&appid=a5599c020b0d897cbc8b52d547289acc')
.then(post => post.json())
.then(data => {
var cityName = data['name'];
var temper = data['main']['temp'];
var descrip = data['weather'][0]['description'];
let ctemp = Math.round(temper-273);
citysName.innerHTML = cityName;
temp.innerHTML = ctemp + "°C";
description.innerHTML = descrip;
})
})
Related
I'm having trouble implementing the logic that will limit me from adding the same items to my shopping list. When the item is the same, I just want to display the quantity with the existing item.
<div class="pizzas">
</div>
<div class="shoppingCart">
<p class="totalPrice">Hungry? order our pizzas</p>
</div>
// js
fetch("https://raw.githubusercontent.com/alexsimkovich/patronage/main/api/data.json")
.then(data => data.json())
.then(data => {
let valueCurrency = 0;
data.forEach(element => {
const shoppingCart = document.querySelector(".shoppingCart");
const pizzas = document.querySelector(".pizzas");
const box = document.createElement("div");
const img = document.createElement("img");
const title = document.createElement("h3");
const ingredients = document.createElement("p");
const price = document.createElement("h4");
const btn = document.createElement("button");
const totalPrice = document.querySelector(".totalPrice");
box.className = "box";
ingredients.className = "ingredients"
btn.className = "btn";
img.src = element.image;
img.className = "img";
title.innerHTML = element.title;
ingredients.innerHTML = element.ingredients;
price.innerHTML = element.price.toFixed(2) + " zł";
btn.innerHTML = "Dodaj do koszyka";
box.appendChild(img);
box.appendChild(title);
box.appendChild(ingredients);
box.appendChild(price);
box.appendChild(btn);
pizzas.appendChild(box);
btn.addEventListener("click", (e) => {
valueCurrency = valueCurrency + element.price;
const pizza = document.createElement("div");
pizza.className = "pizzaList";
const pizzasList = document.createElement("li");
const pizzaPrice = document.createElement("p");
const btnRemove = document.createElement("button");
btnRemove.innerText = "X";
pizzasList.innerText = title.textContent;
pizzaPrice.innerText = price.textContent;
pizza.appendChild(pizzasList);
pizza.appendChild(pizzaPrice);
pizza.appendChild(btnRemove);
totalPrice.innerText = "Całkowita cena: " + valueCurrency.toFixed(2);
if(pizzasList.innerText === pizzasList.innerText)
{
// don't add another item to the list
// just add +1 to existing element
}
else
{
// add an item to the list
shoppingCart.prepend(pizza);
}
btnRemove.addEventListener("click", (e) => {
pizza.remove();
valueCurrency = valueCurrency - element.price;
totalPrice.innerText = "Całkowita cena: " + valueCurrency.toFixed(2);
})
})
});
})
.catch(err => console.log(err));
My problem is exactly in the conditional statement, I don't know exactly how to implement the counting of the same pizzas option.
Thank you in advance for your help.
Since you are using html elements for this, what you can do is to use a data-attribute in your pizza element and increment it each time you need.
Something like:
if(pizzasList === pizzasList)
{
pizza.dataset.total = Number(pizza.dataset.total) + 1;
}
else
{
pizza.dataset.total = 1;
shoppingCart.prepend(pizza);
}
Then just use pizza.dataset.total to retieve the total number of repetitions.
Usually my page looks like this:
Take note of the scroll bar on right most part of the image.
PROBLEM: sometimes the school logo card would appear at the bottom of the page whenever I go back and forth with Home tab and About tab buttons on the left.
There is no consistent count every time I switch between Home and About on whenever the school logo card would appear at the bottom.
it looks like this:
The school logo card would be rendered after the home carousel card
My js code:
const pageContent = document.getElementById('page-content')
handleLogoForm()
//handles form submission for school logo card
function handleLogoForm(){
var logoform = document.getElementById('logo-form')
logoform.addEventListener('submit', function(e){
e.preventDefault()
let input = document.getElementById('inputGroupFile02');
let data = new FormData();
data.append('image',input.files[0]);
var url = "/web-content/api/changelogo/"
fetch(url,{
method: "POST",
headers: {
"X-CSRFToken": csrftoken,
},
body:data
})
.then((response) => response.json())
.then(function(data){
updateLogo()
e.target.reset()
handleLogoForm.call(this);
logo = document.getElementById('logo-div')
logo.innerHTML = ""
logo.innerHTML = `<img src="${data.image}" alt="no image provided" style="max-width: 7rem; max-height: 7rem;">`
})
})
}
// Getting Home Page Contents
function getLogoCard(){
var url = "http://localhost:8000/web-content/api/changelogo/"
fetch(url)
.then((response) => response.json())
.then(function(data){
// constructing nodes
// create div card parent node
var card = document.createElement('div')
card.classList.add('card')
// cardBody child
var cardBody = document.createElement('div')
cardBody.classList.add('card-body')
var header = document.createElement('h5')
header.innerText = 'School Logo'
var label1 = document.createElement('small')
label1.innerText = 'On display: '
var image = document.createElement('img')
image.src = data[0].image
image.id = 'img'
image.classList.add('card-img-top')
image.style.maxWidth = '10rem'
image.style.maxHeight = '10rem'
var form = document.createElement('form')
form.action = '/web-content/api/changelogo/'
form.method = 'POST'
form.enctype ='multipart/form-data'
form.id ='logo-form'
form.style.display = 'inline'
var csrftokennode = document.createElement('input')
csrftokennode.type = 'hidden'
csrftokennode.value = csrftoken
var inputGroup = document.createElement('div')
inputGroup.classList.add('input-group', 'mb-3')
var imageField = document.createElement('input')
imageField.type = 'file'
imageField.name = 'image'
imageField.classList.add('form-control')
imageField.required = true
imageField.id = 'inputGroupFile02'
var uploadButton = document.createElement('button')
uploadButton.type = 'submit'
uploadButton.classList.add('input-group-text')
uploadButton.for = 'inputGroupFile02'
uploadButton.innerText = 'Upload'
var label = document.createElement('label')
label.for = 'inputGroupFile02'
label.innerText = 'Change:'
// combine elemnts together
card.append(cardBody)
cardBody.append(header)
cardBody.append(label1)
cardBody.append(image)
cardBody.append(document.createElement('br'))
cardBody.append(label)
cardBody.append(form)
form.append(csrftokennode)
form.append(imageField)
form.append(uploadButton)
pageContent.append(card)
handleLogoForm()
})
}
function getCarouselCard(){
var url = "/web-content/api/home-carousel/"
fetch(url)
.then((response) => response.json())
.then(function(data){
var carouselItems = data
// // constructing nodes
var card = document.createElement('div')
card.id = 'carousel'
card.classList.add('card')
var cardBody = document.createElement('div')
cardBody.id = 'card-body'
cardBody.classList.add('card-body')
var header = document.createElement('h5')
header.innerText = 'Home Carousel'
var onDisplay = document.createElement('small')
onDisplay.innerText = 'On display: '
var cardImage = document.createElement('img')
cardImage.classList.add('card-img-top')
cardImage.alt = '...'
cardImage.style.maxWidth = '15rem'
cardImage.style.maxHeight = '15rem'
var cardLabel = document.createElement('small')
cardLabel.innerText = ""
var cardContent = document.createElement('small')
cardContent.innerText = ""
var iconGroup = document.createElement('span')
iconGroup.style.fontSize = '20px'
var trashIconSpan = document.createElement('span')
trashIconSpan.style.color = 'red'
var trashIcon = document.createElement('i')
trashIcon.classList.add('fas', 'fa-trash-alt')
var editIconSpan = document.createElement('span')
editIconSpan.style.color = 'brown'
var editIcon = document.createElement('i')
editIcon.classList.add('far', 'fa-edit')
// construct nodes
card.append(cardBody)
cardBody.append(header)
for (var i = 0; i < data.length; i++) {
cardBody.append(onDisplay)
cardImage.src = data[i].image
cardBody.append(cardImage)
cardBody.innerHTML += '<br>'
cardBody.append(cardLabel)
cardLabel.innerText = data[i].label
cardBody.innerHTML += '<br>'
cardBody.append(cardContent)
cardContent.innerText = data[i].content
cardBody.innerHTML += '<br>'
cardBody.append(iconGroup)
iconGroup.append(trashIconSpan)
trashIconSpan.append(trashIcon)
iconGroup.append(editIconSpan)
editIconSpan.append(editIcon)
cardBody.innerHTML += `<br><hr>`
}
pageContent.append(card)
})
}
// formsssssss
// change logo
function showHomeContent(){
if ( document.getElementById("homeButton").className.match(/(?:^|\s)active(?!\S)/) ){
}else{
document.getElementById('homeButton').classList.add('active')
pageContent.innerHTML = ""
getLogoCard()
getCarouselCard()
}
if ( document.getElementById("aboutButton").className.match(/(?:^|\s)active(?!\S)/) ){
document.getElementById("aboutButton").classList.remove('active')
}
}
function showAboutContent(){
if ( document.getElementById("aboutButton").className.match(/(?:^|\s)active(?!\S)/) ){
return;
}else{
document.getElementById('aboutButton').classList.add('active')
pageContent.innerHTML = ""
pageContent.innerHTML += `
this is about content
`
}
if ( document.getElementById("homeButton").className.match(/(?:^|\s)active(?!\S)/) ){
document.getElementById("homeButton").classList.remove('active')
}
}
the functions that are hooked with Home and About button on the left are showHomeContent() and showAboutContent()
As I mentioned in the comments, you are making two fetch requests that are asynchronous and they are racing to be done first. Whoever wins the race is rendered on top.
So when you fetch the contents, use Promise All
Promise.all([getLogoCard(), getCarouselCard()]).then((values) => {
values.forEach(card => pageContent.append(card));
});
In your functions, return the fetch call, have the fetch return the element you want to append to the document
function getLogoCard() {
...
return fetch(url)
.then((response) => response.json())
.then(function(data){
...
return card;
});
}
I'm trying to make a script that creates an object on submit from form values but on each submit it returns values as undefined .
This is HTML:
<header>
<input type="text" class="title">
<input type="text" class="image">
<textarea class="text"></textarea>
<button id="submit">+</button>
</header>
<main>
<div class="dashboard"></div>
</main>
This is my script:
(function(){
function Post(title, image, text) {
this.title = title;
this.image = image;
this.text = text;
this.date = new Date();
}
var post = new Post();
function Dashboard() {
var main = document.querySelector("main");
var article = document.createElement("div");
article.classList.add("post");
var title = document.createElement("h1");
var image = document.createElement("div");
image.classList.add("img");
var text = document.createElement("p");
var date = document.createElement("p");
var postTitle = post.title;
var postImage = post.image;
var postText = post.text;
var postDate = post.date;
title.innerText=postTitle;
image.style.backgroundImage="url("+postImage+")";
text.innerText=postText;
date.innerText=postDate;
article.appendChild(title);
article.appendChild(image);
article.appendChild(text);
article.appendChild(date);
main.appendChild(article);
}
var submit = document.getElementById("submit");
submit.addEventListener("click", function(){
var inputTitle = document.querySelector(".title").value;
var inputImage = document.querySelector(".image").value;
var inputText = document.querySelector(".text").value;
var post = new Post(inputTitle, inputImage, inputText);
Dashboard();
});
})();
You are creating a new variable post within the click handler but your Dashboard is using one it captures in closure. You could make your Dashboard function to accept post as an argument.
function Post(title, image, text) {
this.title = title;
this.image = image;
this.text = text;
this.date = new Date();
}
function Dashboard(post) {
var main = document.querySelector("main");
var article = document.createElement("div");
article.classList.add("post");
var title = document.createElement("h1");
var image = document.createElement("div");
image.classList.add("img");
var text = document.createElement("p");
var date = document.createElement("p");
var postTitle = post.title;
var postImage = post.image;
var postText = post.text;
var postDate = post.date;
title.innerText = postTitle;
image.style.backgroundImage = "url(" + postImage + ")";
text.innerText = postText;
date.innerText = postDate;
article.appendChild(title);
article.appendChild(image);
article.appendChild(text);
article.appendChild(date);
main.appendChild(article);
}
var submit = document.getElementById("submit");
submit.addEventListener("click", function() {
var inputTitle = document.querySelector(".title").value;
var inputImage = document.querySelector(".image").value;
var inputText = document.querySelector(".text").value;
var post = new Post(inputTitle, inputImage, inputText);
Dashboard(post);
});
<header>
<input type="text" class="title">
<input type="text" class="image">
<textarea class="text"></textarea>
<button id="submit">+</button>
</header>
<main>
<div class="dashboard"></div>
</main>
I am trying to convert an HTML Collection of "li"s into an array, but the result in the array being emptied.
I read this question and applied that, but it doesn't work.How do I convert a HTMLCollection into an array, without emptying it?
<body>
<ul id="base"></ul>
<script>
const json = [{
"id" : "1",
"date" : "2013/05/05",
},{
"id" : "2",
"date" : "2019/05/05",
}];
for (item of json) {
const list = document.createElement('li');
list.textContent = `${item.date}`;
base.appendChild(list)
}
///the code above works fine.
const base = document.getElementById("base");
const myNodeList = base.getElementsByTagName("li");
console.log(myNodeList);
// gives HTMLCollection
const myArray = Array.from(myNodeList)
// returns empty array
</script>
</body>
the result
I tested the same code on console and it worked fine as below.
The code cannot work before you are using base before initializing it. Placing the initialization before using it makes it work.
Here I modified it: https://jsfiddle.net/tk78z5gq/
Thank you so much guys!
The problem was async.
I should have said that earlier, I fetch the data from NeDB with async function.
The array was empty because DOM was executed before async function fetching data was executed.
The full code below was fixed one. I'm not sure this is best way, but at least it worked.
let dataM = null;
async function getHTMLData() {
const response = await fetch('/api');
const data = await response.json();
dataM = data;
const base = document.getElementById("base");
for (item of data) {
const root = document.createElement('li');
root.className = "col-md-auto";
root.title = `${item.date}`;
const border = document.createElement('div');
border.className = "row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative";
root.appendChild(border);
const flex = document.createElement('div');
flex.className = "col p-4 d-flex flex-column position-static";
border.appendChild(flex);
const country = document.createElement('strong');
country.className = "d-inline-block mb-2 text-primary";
const title = document.createElement('h3');
title.className = "mb-0";
const date = document.createElement('div');
date.className = "mb-1 text-muted";
date.id = "date";
const fieldItem = document.createElement('p');
fieldItem.className = "mb-auto";
const imageRoot = document.createElement('figure');
imageRoot.className = "image mb-2";
const link = document.createElement('a');
link.className = "p-4";
const linkText = document.createTextNode("Source");
country.textContent = `${item.country}`;
title.textContent = `${item.title}`;
date.textContent = `${item.date}`;
fieldItem.textContent = `${(item.fieldItem)}`;
for (var i = 0; i < item.imageSrc.length; i++) {
const image = document.createElement('img');
image.src = item.imageSrc[i];
image.alt = 'seized items'
image.className = "w-5 h-5";
// image.crossOrigin ="use-credentials";
imageRoot.appendChild(image);
}
const imageText = document.createElement('text');
imageText.innerHTML = `<br>${item.imageText}`;
imageRoot.appendChild(imageText);
link.appendChild(linkText);
link.title = "Source";
link.href = item.URL;
link.className = "";
flex.append(country, title, date, fieldItem, imageRoot, link);
base.appendChild(root);
}
}
sortDate();
async function sortDate() {
const gethtml = await getHTMLData();
const base = await document.getElementById("base");
const myNodeList = await base.getElementsByTagName("li");
const myArray = Array.from(myNodeList);
myArray.sort(function (a, b) {
return new Date(a.title) > new Date(b.title)? -1
: new Date(a.title) < new Date(b.title)? 1
: 0;
})
for (i = 0; i < myArray.length; i++) {
base.appendChild(base.removeChild(myArray[i]))}
}
index.js
app.get('/api', (request, response) => {
database.find({}).exec(function(err, data){
if (err) {
response.end();
return;
}
response.json(data);
})
});
I am trying to create a number of DOM item's using data from my firebase Firestore, however upon running, I have an error in line 34. I am just not quite sure what I should append resultGrid to, to achieve what I am looking for.
<div class="w-layout-grid grid">
<div class="result div-block">
<div class="data-image"></div>
<div class="result-footer">
<div class="results-text">
<h5 class="data-text">Taffy, 8 | Arabian</h5>
<h5 class="data-text">$12,000</h5>
This is my current javascript.
const resultList = document.querySelector('#horseList')
function renderResult(doc){
var resultGrid = document.createElement('div');
resultGrid.className = ('w-layout-grid grid');
var resultDiv = document.createElement('div');
resultDiv.className = ('result');
var resultImage = document.createElement('div');
resultImage.className = ('data-image');
var resultFooter = document.createElement('div');
resultFooter.className = ('result-footer');
var resultText = document.createElement('div');
resultText.className = ('results-text');
var resultButton = document.createElement('button');
resultButton.className = ('button tiny w-button');
resultButton.innerHTML = "View";
//Render text from database inside H5
const string = (`${doc.data().name}, ${doc.data().age} | ${doc.data().type}`);
let resultOne = document.createElement('h5');
let price = document.createElement('h5');
resultOne.className = ('data-text');
price.className = ('data-text');
price.textContent = (`$${doc.data().price}`);
resultOne.textContent = string;
resultList.appendChild(resultGrid);
resultGrid.appendChild(resultDiv);
resultDiv.appendChild(resultImage);
resultDiv.appendChild(resultFooter);
resultFooter.appendChild(resultText);
resultFooter.appendChild(resultButton);
resultText.appendChild(resultOne);
resultText.appendChild(price);
}
//connect to database & get data
const db = firebase.firestore();
db.collection("Horses").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
// doc.data() is never undefined for query doc snapshots
renderResult(doc);
});
})
.catch(function(error) {
console.log("Error getting documents: ", error);
});
Thanks in advance!
I figured it out! I ended up making the div GRID statically in HTML then I just set javascript to create the dynamic div's within that grid!
HTML
<div id="horseList" class="w-layout-grid grid"></div>
Javascript
const resultList = document.querySelector('#horseList')
function renderResult(doc){
var resultDiv = document.createElement('div');
resultDiv.className = ('result');
resultDiv.setAttribute('data-id', doc.id);
var resultImage = document.createElement('div');
resultImage.className = ('data-image');
var resultFooter = document.createElement('div');
resultFooter.className = ('result-footer');
var resultText = document.createElement('div');
resultText.className = ('results-text');
var resultButton = document.createElement('button');
resultButton.className = ('button tiny w-button');
resultButton.innerHTML = "View";
//Render text from database inside H5
const string = (`${doc.data().name}, ${doc.data().age} | ${doc.data().type}`);
let resultOne = document.createElement('h5');
let price = document.createElement('h5');
resultOne.className = ('data-text');
price.className = ('data-text');
price.textContent = (`$${doc.data().price}`);
resultOne.textContent = string;
resultList.appendChild(resultDiv);
resultDiv.appendChild(resultImage);
resultDiv.appendChild(resultFooter);
resultFooter.appendChild(resultText);
resultFooter.appendChild(resultButton);
resultText.appendChild(resultOne);
resultText.appendChild(price);
}