I'm trying to make one element disapear and another be created on another part of my document. When the item that I want to disapear is clicked it disapears, however the element I want to create isn't created. I have definitly appended it to the correct element so I'm very confused as to why it doesnt appear in chrome dev tools or on the page. Here's the code and thanks for any help.
let hideGridItem = document.addEventListener('click', function(e) {
let hideItem = (e.target.parentElement.parentElement.id)
let hideItemTwo = (e.target.parentElement.id)
let hideItemThree = (e.target.id)
const displayedItemWrapper = document.getElementById('selected-item-container')
let hiddenItem = document.getElementById(hideItem)
if(hideItem.includes('grid-item')){
hiddenItem.style.display = 'none';
let hiddednItemWeapon = (hiddenItem.childNodes[2].childNodes[0].innerHTML);
let hiddednItemCondition = (hiddenItem.childNodes[0].childNodes[0].innerHTML);
let hiddenItemImg = (hiddenItem.childNodes[1].childNodes[0].src);
let hiddednItemWeaponName = (hiddenItem.childNodes[2].childNodes[1].innerHTML);
let hiddednItemWeaponPrice = (hiddenItem.childNodes[2].childNodes[2].innerHTML);
let displayedItemContainer = document.createElement('div');
displayedItemContainer.className = 'selected-item-container';
let displayedItemImgContainer = document.createElement('div');
displayedItemImgContainer.className = 'selected-item-img-container';
let displayedItemImg = document.createElement('img');
displayedItemImg.src = hiddenItemImg;
displayedItemWrapper.appendChild.displayedItemContainer;
displayedItemContainer.appendChild.displayedItemImgContainer;
displayedItemImgContainer.appendChild.displayedItemImgContainer;
}
let hiddenItemTwo = document.getElementById(hideItemTwo)
if(hideItemTwo.includes('grid-item') ){
hiddenItemTwo.style.display = 'none'
}
let hiddenItemThree = document.getElementById(hideItemThree)
if(hideItemThree.includes('grid-item') ){
hiddenItemThree.style.display = 'none'
}
}, false);
Related
If you go through the process of creating html elements in JavaScript, you can see that this process is repeated a lot. For example I made a function to create, edit and delete comments in real time, please see the following code.
function addComment(comment, score) {
// Create a list for comments
const newComment = document.createElement('li');
newComment.setAttribute('data-commentid', comment._id);
newComment.classList.add('detail__comment');
// Creating a Comments Information
const commentInfo = document.createElement('div');
commentInfo.classList.add('detail__comment__info');
const scoreConfigWrap = document.createElement('div');
scoreConfigWrap.classList.add('detail__comment__score');
for (let i = 0; i < score; i++) {
const filledScore = document.createElement('i');
const filledScoreClass = ['fa-solid', 'fa-star', 'filled'];
filledScore.classList.add(...filledScoreClass);
scoreConfigWrap.appendChild(filledScore);
}
for (let j = score; j < 5; j++) {
const score = document.createElement('i');
const scoreClass = ['fa-solid', 'fa-star'];
score.classList.add(...scoreClass);
scoreConfigWrap.appendChild(score);
}
// Create a comment edit button and include it in its parent
const commentBtns = document.createElement('div');
commentBtns.classList.add('detail__comment__btns');
const modifyBtn = document.createElement('button');
modifyBtn.innerText = 'Update';
modifyBtn.classList.add('detail__comment__modify-btn');
const cancelModifyBtn = document.createElement('button');
cancelModifyBtn.innerText = 'Cancel';
cancelModifyBtn.classList.add('detail__comment__modify-cancel');
cancelModifyBtn.classList.add('hidden');
commentBtns.appendChild(modifyBtn);
commentBtns.appendChild(cancelModifyBtn);
commentInfo.appendChild(scoreConfigWrap);
commentInfo.appendChild(commentBtns);
// Create space for comment text, author
const commentText = document.createElement('div');
commentText.classList.add('detail__comment__text');
const span = document.createElement('span');
span.innerText = comment.text;
const commentOwner = document.createElement('a');
commentOwner.setAttribute('href', `users/${comment.owner._id}`);
commentOwner.innerText = comment.owner.uid;
commentText.appendChild(span);
commentText.appendChild(commentOwner);
// Create a delete comment button
const deleteBtn = document.createElement('button');
deleteBtn.innerText = 'X';
deleteBtn.classList.add('detail__comment__delete');
// Saving information to be used for comment editing and deletion functions
comment = {
text: comment.text,
_id: comment._id,
};
commentObj = {
comment,
commentBtns,
commentElement: commentText,
};
// Link all elements related to comments with their parent
newComment.appendChild(commentInfo);
newComment.appendChild(commentText);
newComment.appendChild(modifyForm);
newComment.appendChild(deleteBtn);
detailComments.prepend(newComment);
}
Doesn't it make you annoyed just by looking at it? The problem is I don't know how to refactor this iteration. I thought about making the process of creating html elements into a separate function.
export default function createHtmlTag(
element,
text,
attrObj,
className,
parentNode
) {
const newElement = document.createElement(element);
if (attrObj) {
newElement.setAttribute(attrObj.key, attrObj.value);
}
if (text) {
newElement.innerText = text;
}
if (className) {
newElement.classList.add(className);
}
parentNode.appendChild(newElement);
}
But even then, the code looked like it was less readable. So I'd like to get a little hint about the refactoring process.
firstly, when I search for any city it shows the weather correctly, but when I try to search for another city/country It shows the details of the same city that I have searched for before. I think there is something wrong with my JavaScript code. I think the new values that I'm fetching from the API are not getting replaced by the old values.
let enterCity = document.querySelector("#enterCity");
let city = document.querySelector(".city");
let country = document.querySelector(".country");
let temp = document.querySelector(".temp");
let text = document.querySelector(".text");
let inputVal = enterCity.value;
// the base url
let url = `http://api.weatherapi.com/v1/current.json?q=${inputVal}&key=cb58be19d0d2****************`;
fetch(url).then((response) => {
return response.json();
}).then((data) => {
let search = document.querySelector(".search");
search.addEventListener("click", () => {
let container = document.querySelector(".container");
card = document.createElement("div");
card.className = "card";
city = document.createElement("h2");
city.className = "city";
***The problems are with the innerText down below ***
city.innerText = data.location.name;
country = document.createElement("h5");
country.className = "country";
country.innerText = data.location.country;
temp = document.createElement("h4");
temp.className = "temp";
temp.innerText = data.current.temp_c;
span1 = document.createElement("span");
span1.id = "deg";
span1.innerText = "°C"
temp.appendChild(span1);
icon = document.createElement("img");
icon.className = "icon";
icon.src = data.current.condition.icon;
text = document.createElement("h3");
text.className = "text";
text.innerText = data.current.condition.text;
card.appendChild(city);
card.appendChild(country);
card.appendChild(temp);
card.appendChild(icon);
card.appendChild(text);
container.appendChild(card);
Here, I have also cleared the input value
that I'm taking from the user
enterCity.value = "";
});
});
let search = document.querySelector(".search");
search.addEventListener("click", () => {
let enterCity = document.querySelector("#enterCity");
let city = document.querySelector(".city");
let country = document.querySelector(".country");
let temp = document.querySelector(".temp");
let text = document.querySelector(".text");
var inputVal = enterCity.value;
// the base url
let url = `http://api.weatherapi.com/v1/current.json?q=${inputVal}&key=cb58be19d0d2********************`;
fetch(url).then((response) => {
return response.json();
}).then((data) => {
//Do the remaining works here
})
});
The actual problem was already assigned the value of document.querySelector("#enterCity"); when the page loads instead of on click. So value of enterCity was not changing when you click the search button.
Note : If the key you given in the question is your personal API key,
then please try to change it in the console, because it is not good
idea to publish it in the outside.
This is happening beacause you haven't added onchange event listener on your input(enter city).if you don't add onchange event this will take only your inital value.
So add a onchange listener then call fetch api inside of it.
Dummy example -
let entercity=document.querySelector("#entercity");
entercity.addEventListener('change',()=>{
let inputVal=entercity.value;
let url = `http://api.weatherapi.com/v1/current.json?q=${inputVal}&key=cb58be19d0d2476da35134140211107`;
fetch(url).then((res)=>console.log(res))
.catch((err)=>console.log(err));
})
I'm very new to javascript/dev so I hope there is a an obvious solution that I've not thought of. My code returns search items from TVMaze.com API. The feature giving me trouble is the incremental search (as a user types in input box, the code returns and displays images by creating a new div and appending images, removing and replacing the an div).
My problem is that on deleting all characters from input box, I receive the error: "Uncaught (in promise) TypeError: shows is not iterable" which I suppose means that there is no object to iterate over? Thanks in advance for any help.
const input = document.querySelector("#query");
input.addEventListener("input", async function (e) {
e.preventDefault();
const searchTerm = e.target.value;
const config = { params: { q: searchTerm } };
const res = await axios.get(`http://api.tvmaze.com/search/shows?`, config);
makeImages(res.data);
clearList();
});
const makeImages = (shows) => {
const div = document.createElement("div");
for (let result of shows) {
if (result.show.image) {
const img = document.createElement("IMG");
img.className += "resultImage";
img.src = result.show.image.medium;
const title = document.createElement("h3");
title.className += "resultTitle";
title.innerText = result.show.name;
const year = document.createElement("h4");
year.className += "score";
year.innerText = result.show.premiered;
var sub = year.innerText.substring(0, 4);
var yearNum = parseInt(sub);
div.append(year);
div.append(img);
div.append(title);
document.body.appendChild(div);
}
if (yearNum <= 2000) {
var retro = document.createElement("h5");
retro.className = "retro";
retro.innerText = "retro";
div.append(retro);
}
}
};
let clearList = () => {
var allImg = document.querySelectorAll("IMG");
if (allImg.length === 0) {
document.createElement("div");
return makeImages();
}
var oldDiv = document.querySelector("div");
oldDiv.remove();
console.log(oldDiv);
};
I'm making a browser game but I've run into a issue I cant fix no matter how hard I try.
Click the green square increases the counter
and console shows variable being saved to localStorage
but upon returning on the website it returns to 0
Below is my entire JS file. Only part that matters is at the bottom and you can go see for yourself at https://sleepyshepherd.com
//Saved Variables
let ashCount = 0;
let firetruck = 0;
//Initialize Game
window.onload = function() {
const realmTab = document.createElement("div");
const settingsTab = document.createElement("div");
const shopTab = document.createElement("div");
const statsTab = document.createElement("div");
const upgradesTab = document.createElement("div");
const burningBtn = document.createElement("div");
const enslavedTab = document.createElement("div");
const e1 = document.createElement("div");
realmTab.id = "realm";
upgradesTab.id = "upgrades";
settingsTab.id = "settings";
shopTab.id = "shop";
statsTab.id = "stats";
enslavedTab.id = "enslaved";
burningBtn.id = "burning";
e1.id = "e1";
const t1 = document.createTextNode("Realm");
realmTab.appendChild(t1);
const t2 = document.createTextNode("Upgrades");
upgradesTab.appendChild(t2);
const t3 = document.createTextNode("Shop");
shopTab.appendChild(t3);
const t4 = document.createTextNode("Stats");
statsTab.appendChild(t4);
const t5 = document.createTextNode("Settings");
settingsTab.appendChild(t5);
document.getElementById("menu").appendChild(realmTab);
document.getElementById("menu").appendChild(upgradesTab);
document.getElementById("menu").appendChild(shopTab);
document.getElementById("menu").appendChild(statsTab);
document.getElementById("menu").appendChild(settingsTab);
document.getElementById("destroy").appendChild(burningBtn);
document.getElementById("destroy").appendChild(enslavedTab);
document.getElementById("enslaved").appendChild(e1);
//Menu Buttons
const viewport1 = document.querySelector(".viewport");
//Realm View Select
document.querySelector("#realm").addEventListener("click", function() {
viewport1.id = "realmView";
});
//Upgrades View Select
document.querySelector("#upgrades").addEventListener("click", function() {
viewport1.id = "upgradeView";
});
//shop View Select
document.querySelector("#shop").addEventListener("click", function() {
viewport1.id = "shopView";
});
//stats View Select
document.querySelector("#stats").addEventListener("click", function() {
viewport1.id = "statsView";
});
//settings View Select
document.querySelector("#settings").addEventListener("click", function() {
viewport1.id = "settingsView";
});
// Destroy
function increaseAsh() {
ashCount += 1;
}
document.querySelector("#destroy").addEventListener("click", increaseAsh);
//Resources
const r1 = document.createElement("div");
r1.id = "r1";
document.querySelector("#resources").appendChild(r1);
const t6 = document.createElement("p");
r1.appendChild(t6);
window.setInterval(function() {
t6.textContent = ashCount;
}, 16);
//load game
let sg = JSON.parse(localStorage.getItem("save"));
sg.ashCount = ashCount;
}
// Save Game Interval
window.setInterval(function() {
let save = {
ashCount: ashCount,
firetruck: firetruck
}
localStorage.setItem("save", JSON.stringify(save));
}, 10000);
you wrote sg.ashCount = ashCount; when you want ashCount = sg.ashCount;
add a console.log(sg);
Currently I have a delete function already which is shown by a cross
So how I am doing this is by using a function that renders in the information from another database, into this list.
function renderCafe(doc){
let li = document.createElement('li');
let name = document.createElement('span');
let city = document.createElement('span');
let cross = document.createElement('div');
li.setAttribute('data-id', doc.id);
name.textContent = doc.data().name;
city.textContent = doc.data().city;
cross.textContent = 'x';
li.appendChild(name);
li.appendChild(city);
li.appendChild(cross);
cafeList.appendChild(li);
// deleting data
cross.addEventListener('click', (e) => {
e.stopPropagation();
let id = e.target.parentElement.getAttribute('data-id');
db.collection('cafes').doc(id).delete();
});}
So how do I create the edit button function like this delete one? Should it also be an EventListener that occurs when clicked?
I was thinking to have an edit button, when clicked, changes into "Update", while the static information turns into a text box with the current values.
Then when the "Update" is being clicked, it then saves the information.
I am a student, and have no prior knowledge in javascript, i took these codes from tutorials that I can find online.
Here's a possible solution, similar to your style.
Replace the alert with a database update.
Make sure you're listening for document changes, and updating your UI accordingly, so that the new name and city will replace your old ones.
const cafeList = document.getElementById('cafe-list');
const sampleCafes = [
{ data: () => ({ name: 'new cafe', city: 'new city'}), id: 'sample-cafe' },
];
sampleCafes.forEach(cafe => renderCafe(cafe));
function renderCafe(doc){
let li = document.createElement('li');
let name = document.createElement('p');
let city = document.createElement('p');
let nameInput = document.createElement('input');
let cityInput = document.createElement('input');
let edit = document.createElement('div');
let submit = document.createElement('div');
let cross = document.createElement('div');
li.setAttribute('data-id', doc.id);
name.textContent = doc.data().name;
city.textContent = doc.data().city;
nameInput.value = name.textContent;
cityInput.value = city.textContent;
nameInput.hidden = true;
cityInput.hidden = true;
edit.textContent = 'edit';
submit.textContent = 'submit';
submit.hidden = true;
cross.textContent = 'x';
li.appendChild(name);
li.appendChild(city);
li.appendChild(nameInput);
li.appendChild(cityInput);
li.appendChild(edit);
li.appendChild(submit);
li.appendChild(cross);
cafeList.appendChild(li);
// deleting data
cross.addEventListener('click', (e) => {
e.stopPropagation();
let id = e.target.parentElement.getAttribute('data-id');
alert(`db.collection('cafes').doc(id).delete();`);
});
// editing data
edit.addEventListener('click', (e) => {
e.stopPropagation();
nameInput.hidden = false;
cityInput.hidden = false;
submit.hidden = false;
name.hidden = true;
city.hidden = true;
edit.hidden = true;
});
// submitting new data
submit.addEventListener('click', (e) => {
e.stopPropagation();
const id = e.target.parentElement.getAttribute('data-id');
nameInput.hidden = true;
cityInput.hidden = true;
submit.hidden = true;
name.hidden = false;
city.hidden = false;
edit.hidden = false;
const newName = nameInput.value;
const newCity = cityInput.value;
alert(`TODO: update doc '${id}' to\n{name: '${newName}', city: '${newCity}'}.`);
});
}
<ul id="cafe-list"></ul>