I'm making a gallery in a modal window and when I try to set a class to the next element, it gives an error "Cannot read property 'classList' of null". How can I fix this?
HTML
<div class="card-page__imgs">
<img id="1" href="assets/img/card-page-main-img.png" class="card-page__main-img gallery-img"
src="assets/img/card-page-main-img.png" alt="Изображение">
<div class="card-page__img-group">
<img id="2" src="assets/img/card-page-img1.png" class="card-page__second-img gallery-img next-img">
<img id="3" src="assets/img/card-page-img2.png" class="card-page__second-img gallery-img">
<img id="4" src="assets/img/card-page-img3.png" class="card-page__second-img gallery-img">
</div>
</div>
JS
const galleryBtnPrev = document.querySelector('.gallery__btn_prev'),
galleryBtnNext = document.querySelector('.gallery__btn_next'),
galleryMainImg = document.querySelector('.gallery__main-img'),
galleryImages = document.querySelectorAll('.gallery-img');
const showNext = () => {
const galleryImagesArr = Array.from(galleryImages);
galleryImagesArr.forEach((el, i) => {
//if(el.classList.contains('next'))
const nextSrc = el.getAttribute('src');
if(el.classList.contains('next-img')) {
galleryMainImg.setAttribute('src', nextSrc);
el.classList.remove('next-img');
// el.classList.add('next-img');
const nextElem =el.nextElementSibling;
console.log(nextElem);
nextElem.classList.add('next-img');
return false;
}
// console.log(el, i);
});
};
You cant do const nextElem = el.nextElementSibling; because you have converted the nodeList to an array so the nextElementSibiling property doesn't work, however you can iterate through a nodeList using the forEach anyway so if you remove the const galleryImagesArr = Array.from(galleryImages); and just use galleryImages in place of galleryImagesArr It will work
EDIT
The error was from trying to read next sibling at when at the end of the array so it was returning null instead of wrapping over to the start, fixed this with simple IF statement
Like this
const galleryBtnPrev = document.querySelector('.gallery__btn_prev'),
galleryBtnNext = document.querySelector('.gallery__btn_next'),
galleryMainImg = document.querySelector('.gallery__main-img'),
galleryImages = document.querySelectorAll('.gallery-img');
const showNext = () => {
galleryImages.forEach((el, i) => {
//if(el.classList.contains('next'))
const nextSrc = el.getAttribute('src');
if(el.classList.contains('next-img')) {
//galleryMainImg.setAttribute('src', nextSrc);
el.classList.remove('next-img');
// el.classList.add('next-img');
var nextElem = el.nextElementSibling
if (nextElem === null) {
nextElem = galleryImages[0]
}
nextElem.classList.add('next-img');
return false;
}
// console.log(el, i);
});
};
showNext()
Related
i'm having a trouble using the id from a template string item
const elementoParaInserirJogosNaLista = document.getElementById("listaJogos");
function exibirJogosNaTela(listaDeJogos) {
elementoParaInserirJogosNaLista.innerHTML = "";
listaDeJogos.forEach((jogo) => {
elementoParaInserirJogosNaLista.innerHTML += `
<div class="jogo">
<a href="paginajogo.html">
<img class="jogo__imagem" src="${jogo.imagem}" alt="${jogo.titulo}" />
</a>
<h2 class="jogo__titulo">${jogo.titulo}</h2>
<p class="jogo__preco" id="preco">R$${jogo.preco}<a ><img class="jogo__carrinho" id="addCarrinho" src="./images/addcart.png" alt="Adicionar ao carrinho"/></p><a/>
</div>
`;
});
}
i've tried to use the id "addCarrinho" and nothing happens
i'm newb on developing
const botoesAddCarrinho = [];
botoesAddCarrinho = document.querySelectorAll(".jogo__carrinho");
botoesAddCarrinho.forEach((evento) =>
evento.addEventListener("click", addNoCarrinho)
);
function addNoCarrinho () {
console.log('ok')
}
i've changed the selector to by the class, but nothings happens, is like the nothing was selected
i'm using the exibirNaTela on the fetch with the json
let jogos = [];
const endpointDaAPI ="jogos.json"
getBuscarJogosDaAPI();
async function getBuscarJogosDaAPI() {
const respost = await fetch(endpointDaAPI);
jogos = await respost.json();
exibirJogosNaTela(jogos.jogos);
}
** I want when to click on the active button if the checkbox is checked to add filtered class in HTML element but it doesn't work and give me an undefined error in this line check.parentElement.classList.add("filtered"); **
<ul class="ul-list"></ul>
</section>
</main>
<footer class="footer">
<button class="all footer-btn">All</button>
<button class="active footer-btn">Active</button>
<button class="complete footer-btn">Complete</button>
</footer>
let check = document.querySelectorAll(".complete-txt");
let complete_btn = document.querySelector(".complete");
let active_btn = document.querySelector(".active");
let all_btn = document.querySelector(".all");
let edit_list = document.querySelector(".edit-list");
let main_text = document.querySelector(".main-text");
let list_item = document.querySelector(".list-item");
let footer = document.querySelector(".footer");
const generateTemplate = (todo) => {
const html = `
<li class="list-item">
<input type="checkbox" class="complete-txt" name="" id="check"><span class="main-text">${todo}</span><div class="edit-list"></div><div class="delete-list"></div>
</li>
`;
list.innerHTML += html;
};
// add todos event
addForm.addEventListener("submit", (e) => {
e.preventDefault();
const todo = addForm.add.value.trim();
if (todo.length) {
generateTemplate(todo);
addForm.reset();
}
});
active_btn.addEventListener("click", function () {
let check_id = document.querySelector(".complete-txt");
// check.forEach(function () {
debugger;
if (check.checked !== "true") {
check.parentElement.classList.add("filtered");
console.log("hi");
}
// });
// console.log("hi");
console.log("hi");
// console.log(check.checked.value);
});
if the larger document fixes all other inconcistencies you should be able to change the eventlistener to
active_btn.addEventListener("click", function () {
let check_id = document.querySelector(".complete-txt");
if (check_id.checked !== "true") {
check_id.parentElement.classList.add("filtered");
}
});
BUT!!! this will not "fix" all of your errors, like defining let check before the checkbox is created with generateTemplate
Why when you are searching for something else is deleting the previous contents ?For example first you search for egg and show the contents but then when you search for beef the program deletes the egg and shows only beef.Thank you for your time code:
const searchBtn = document.getElementById('search-btn');
const mealList = document.getElementById('meal');
const mealDetailsContent = document.querySelector('.meal-details-content');
const recipeCloseBtn = document.getElementById('recipe-close-btn');
// event listeners
searchBtn.addEventListener('click', getMealList);
mealList.addEventListener('click', getMealRecipe);
recipeCloseBtn.addEventListener('click', () => {
mealDetailsContent.parentElement.classList.remove('showRecipe');
});
// get meal list that matches with the ingredients
function getMealList(){
let searchInputTxt = document.getElementById('search-input').value.trim();
fetch(`https://www.themealdb.com/api/json/v1/1/filter.php?i=${searchInputTxt}`)
.then(response => response.json())
.then(data => {
let html = "";
if(data.meals){
data.meals.forEach(meal => {
html += `
<div class = "meal-item" data-id = "${meal.idMeal}">
<div class = "meal-img">
<img src = "${meal.strMealThumb}" alt = "food">
</div>
<div class = "meal-name">
<h3>${meal.strMeal}</h3>
Get Recipe
</div>
</div>
`;
});
mealList.classList.remove('notFound');
} else{
html = "Sorry, we didn't find any meal!";
mealList.classList.add('notFound');
}
mealList.innerHTML = html;
});
}
Beacuse you are using innerHTML , if you want to save the previous contents you should use append or innerHTML + = .
Because everytime you make a search, the html var is populated with new data.
if you move the 'html' variable to the root scope, this should get you there:
// get meal list that matches with the ingredients
let html = ""; // <-- place it outside the function body
function getMealList(){
let searchInputTxt = document.getElementById('search-input').value.trim();
fetch(`https://www.themealdb.com/api/json/v1/1/filter.php?i=${searchInputTxt}`)
.then(response => response.json())
.then(data => {
// let html = ""; // <-- remove it from here
if(data.meals){
data.meals.forEach(meal => {
I've tried to retrieve a saved picture URL from Firebase Firestore, but I'm keep getting this error:
Uncaught (in promise) TypeError: Cannot read property 'picURL' of undefined.
I've tried a code, which you can see below. It's from "imgRef" and down.
HTML:
<div class="container">
<ul class="posts">
</ul>
</div>
JavaScript:
var postDocRef = db.collection('posts').doc(uid).collection('userPosts')
postDocRef.get().then(snapshot => {
setupPosts(snapshot.docs)
})
const posts = document.querySelector('.posts');
const setupPosts = (data) => {
let html = '';
data.forEach(doc => {
var docRefIDpost = docRef.id
const post = doc.data();
const li = `
<li>
<div class="title">${post.title}</div>
<div class="content">${post.content}</div>
<img class="img">
</li>
`;
var imgRef = db.collection('posts').doc(uid).collection('userPosts').doc(docRefIDpost);
imgRef.get().then(function(snapshot) {
const picURL = snapshot.data().picURL
if (picURL.exists) {
console.log(snapshot.data)
console.log(picURL)
var imgpost = document.querySelector(".img");
imgpost.src = picURL
}
})
html += li
})
posts.innerHTML = html;
}
});
The error is telling you that snapshot.data() returned undefined. As you can see from the API documentation, data() will return undefined when the requested document was not found. It's not clear here why, but your code should check for that first before accessing properties.
imgRef.get().then(function(snapshot) {
const data = snapshot.data()
if (data) {
const picURL = data.picURL
}
else {
// decide what you want to do if the document doesn't exist
}
})
This is my HTML snippet
<div class="well">
<h5>Test Subject ID No.:</h5>
<select id="selDataset" onchange="optionChanged(this.value)"></select>
</div>
This is how I appended options
const url = "./samples.json";
var selectDropdown = d3.select("#selDataset")
function addOptions() {
d3.json(url).then(function(data) {
data.names.forEach(name => {
var appendOption = selectDropdown.append("option").text(name)
})
})
}
addOptions()
I am now trying to add an index to each option as a value, any idea how I can do this?
D3 has an .attr method which does what you want.
var selectDropdown = d3.select("#selDataset");
function addOptions() {
d3.json(url).then(function(data) {
data.names.forEach((name, i) => {
var appendOption = selectDropdown.append("option").text(name).attr('value', i);
});
});
}
addOptions();