childNodes is 0 but I have children - javascript

I have the following HTML. Using JS, I have a HTMLcollection of slot. And then I am trying to remove the child <p> for a given slot. But the JS console is throwing an error that there is no child. Is it because I have a HTMLCollection?
const slots = document.getElementsByClassName('slot');
for (let i = 0; i < slots.length; i++) {
slots[i].addEventListener('dragover', () => {
const dragging = document.querySelector('.card-dragging');
slots[i].appendChild(dragging);
slots[i].removeChild(slots[i].lastChild);
})
};
<section class="slots">
<div class="slot">
<img id="rabbit" src="https://gravatar.com/avatar/c331326b84b173e6fb0ddaefd8520044?s=400&d=retro&r=x" alt="rabbit" />
<p class="card-slot card-temp"></p>
</div>
<div class="slot">
<img id="ball" src="https://gravatar.com/avatar/c331326b84b173e6fb0ddaefd8520044?s=400&d=retro&r=x" alt="ball" />
<p class="card-slot card-temp"></p>
</div>
<div class="slot">
<img id="book" src="https://gravatar.com/avatar/c331326b84b173e6fb0ddaefd8520044?s=400&d=retro&r=x" alt="book" />
<p class="card-slot card-temp"></p>
</div>
</section>

Your code can benefit from Delegation
You cannot remove the child in the middle of dragging, I expect you want to hide and move it back outside when you drop?
I could not find the .card-dragging so I guessed
const slots = document.querySelector('.slots');
slots.addEventListener('dragover', (e) => {
const tgt = e.target.closest('div.slot');
if (!tgt) return;
const dragging = document.querySelector('.card-dragging');
tgt.appendChild(dragging);
})
img {
height: 50px;
}
.slot { border: 1px solid black; }
<section class="slots">
<div class="slot">
<img id="rabbit" src="https://gravatar.com/avatar/c331326b84b173e6fb0ddaefd8520044?s=400&d=retro&r=x" alt="rabbit" />
<p class="card-slot card-temp"></p>
</div>
<div class="slot">
<img id="ball" src="https://gravatar.com/avatar/c331326b84b173e6fb0ddaefd8520044?s=400&d=retro&r=x" alt="ball" />
<p class="card-slot card-temp"></p>
</div>
<div class="slot">
<img id="book" src="https://gravatar.com/avatar/c331326b84b173e6fb0ddaefd8520044?s=400&d=retro&r=x" alt="book" />
<p class="card-slot card-temp"></p>
</div>
</section>
<div class="card-dragging">Drop?</div>

Related

the elements are cleared after the code runs instead of staying. Any ideas?

// stores books
let myLibrary = [];
// the constructor...
function Book(title, author, pages, read, imageURL) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
this.imageURL = imageURL;
}
//Function to add new books to the array
function addBookToLibrary(title, author, pages, read, imageURL) {
let book = new Book(title, author, pages, read, imageURL);
myLibrary.push(book);
console.log(myLibrary[0]);
displayBooksOnPage();
}
//function to display cards in the array
function displayBooksOnPage() {
const books = document.querySelector(".cards");
//counter used in the content loop
let counter = 0;
//removes previous card before reiteration
//Create the card for each book in array
myLibrary.forEach((myLibrary) => {
const card = document.createElement("div");
card.classList.add("card");
books.append(card);
//Adds all the content into the card
for (let key in myLibrary) {
console.log("a");
if (counter <= 0) {
const titleHeader = document.createElement("h5");
titleHeader.textContent = `${myLibrary[key]}`;
titleHeader.classList.add("card-title");
card.appendChild(titleHeader);
counter = 1;
} else if (counter < 2) {
const cardAuthor = document.createElement("p");
cardAuthor.textContent = `${myLibrary[key]}`;
cardAuthor.classList.add("card-author");
card.appendChild(cardAuthor);
counter = 2;
} else if (counter < 3) {
const cardPages = document.createElement("p");
cardPages.textContent = `${myLibrary[key]}`;
cardPages.classList.add("card-pages");
card.appendChild(cardPages);
counter = 3;
} else if (counter < 4) {
const readContainer = document.createElement("div");
readContainer.classList.add("read");
card.appendChild(readContainer);
const readElement = document.createElement("p");
readElement.textContent = `${myLibrary[key]}`;
readElement.classList.add("card-read");
readContainer.append(readElement);
counter = 4;
} else if (counter < 5) {
const imageContainer = document.createElement("div");
imageContainer.classList.add("book-image-container");
card.appendChild(imageContainer);
const bookImage = document.createElement("img");
bookImage.src = `${myLibrary[key]}`;
bookImage.classList.add("book-image");
imageContainer.append(bookImage);
const editContainer = document.createElement("div");
editContainer.classList.add("edit-container");
card.appendChild(editContainer);
const editBtn = document.createElement("button");
editBtn.innerText = "Edit";
editBtn.classList.add("edit");
editContainer.append(editBtn);
const deleteContainer = document.createElement("div");
deleteContainer.classList.add("delete-container");
card.appendChild(deleteContainer);
const deleteBtn = document.createElement("button");
deleteBtn.innerText = "Delete";
deleteBtn.classList.add("delete");
deleteContainer.append(deleteBtn);
}
}
function resetCounter() {
counter = 0;
}
resetCounter();
});
}
//New book button
const newBookBtn = document.getElementById("newBookBtn");
newBookBtn.addEventListener("click", displayForm);
//Displays the new book form
function displayForm() {
document.getElementById("formContainer").style.display = "";
}
//eventlistener on form to submit data
const submitBtn = document.querySelector(".submit-button");
submitBtn.addEventListener("click", intakeFormData);
//transform form data to variables
function intakeFormData() {
let title = document.getElementById("Title").value;
let author = document.getElementById("Author").value;
let pages = document.getElementById("Pages").value;
let read = document.getElementById("Read").value;
let imageURL = document.getElementById("imageURL").value;
addBookToLibrary(title, author, pages, read, imageURL);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="text/javascript" src="script.js" defer></script>
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="resetcss.css" />
<title>Sign-Up Form</title>
</head>
<body id="body">
<div class="sideBar">
<div class="menuItem">
<img class="white dashIcon" src="./images/view-dashboard-variant-outline.png" alt="" />
<h1>Dashboard</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/home.png" alt="" />
<h1>Home</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/account.png" alt="" />
<h1>Profile</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/message.png" alt="" />
<h1>Messages</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/clock.png" alt="" />
<h1>History</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/note-multiple.png" alt="" />
<h1>Tasks</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/account-group.png" alt="" />
<h1>Communities</h1>
</div>
<!--Needs extra spacing-->
<div class="menuItem">
<img class="white" src="./images/cog.png" alt="" />
<h1>Settings</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/help-circle.png" alt="" />
<h1>Support</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/shield-check-outline.png" alt="" />
<h1>Privacy</h1>
</div>
</div>
<div class="header">
<!--Top section-->
<div class="topHeader">
<div class="search">
<div class="menuItem">
<img src="./images/magnify.png" alt="" />
</div>
<input type="text" name="search" />
</div>
<div class="account">
<div class="menuIcon">
<img src="./images/bell.png" alt="" />
</div>
<img class="avatar" src="./images/avatar.jpg" alt="" />
<p class="name">Benjamin Gill</p>
</div>
</div>
<!--Bottom section-->
<div class="bottomHeader">
<div class="profile">
<img class="avatar" src="./images/avatar.jpg" alt="" />
<div class="profile-name">
<p class="greeting">Hi there,</p>
<p class="name">
Benjamin Gill <span class="username">(#Bgill)</span>
</p>
</div>
</div>
<div class="buttons">
<button id="newBookBtn" class="btn">New Book</button>
</div>
</div>
</div>
<div class="content">
<div class="projects">
<h3>Your Books:</h3>
<div class="cards">
<div class="card">
<h5 class="card-title">The Hobbit</h5>
<p class="card-author">by: J.R.R. Tolken</p>
<p class="card-pages">345 pages</p>
<div class="read">
<p class="card-read">Not yet read</p>
</div>
<div class="book-image-container">
<img src="https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/The_Hobbit_trilogy_dvd_cover.jpg/220px-The_Hobbit_trilogy_dvd_cover.jpg" alt="" class="book-image" />
</div>
<div class="edit-container">
<button class="edit">Edit</button>
</div>
<div class="delete-container">
<button class="delete">Delete</button>
</div>
</div>
<div id="formContainer" class="cards" style="display: none">
<form id="newBookForm" class="card">
<input type="text" name="Title" id="Title" class="card-title" placeholder="Book Title..." />
<input type="text" name="Author" id="Author" placeholder="Author Name..." class="card-author" />
<input type="number" name="Pages" id="Pages" placeholder="Amount of Pages..." class="card-pages" />
<input type="text" name="Read" id="Read" placeholder="Have you read this?" class="read" />
<input type="text" name="imageURL" id="imageURL" placeholder="Enter image URL..." class="book-image-container" />
<div class="edit-container">
<button type="reset" class="reset-button edit">
Reset Form
</button>
</div>
<div class="delete-container">
<button type="submit" class="submit-button delete">
Sumbit to Library
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
My main issue is in Javascript. It takes the intakeFormData and then goes through the add newBookToLibrary. Once there it runs the displayBooksOnPage and creates the new card by adding elements to the dom. Once all the elements are added, it finishes at the intakeFormData and then calls the myLibrary. Once it calls the myLibrary it just removes all the newly added elements.
I've looked at chrome dev tools and followed it through. It completed everything correctly. But once it is towards the end it calls the first two variables as when the page loads and it clears everything that was added.
myLibrary is a global variables. Please change it to variabile locale try again.
function addBookToLibrary add a return value. Call it in the function displayBooksOnPage.
I added two things to your intakeFormData() function:
an ev.preventDefault() to suppress the actual submission of the form and the opening of an empty page
and toggleDisplay() to hide the form after pressing the "Sumbit to Library" button.
toggleDisplay() replaces your original displayForm() function.
My changes will prevent the page and its content from disappearing. I haven't fully understood what you are doing in displayBooksOnPage() but I am sure there are ways of doing the same job in a much simpler way.
// stores books
let myLibrary = [];
// the constructor...
function Book(title, author, pages, read, imageURL) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
this.imageURL = imageURL;
}
//Function to add new books to the array
function addBookToLibrary(title, author, pages, read, imageURL) {
let book = new Book(title, author, pages, read, imageURL);
myLibrary.push(book);
console.log(myLibrary[0]);
displayBooksOnPage();
}
//function to display cards in the array
function displayBooksOnPage() {
const books = document.querySelector(".cards");
//counter used in the content loop
let counter = 0;
//removes previous card before reiteration
//Create the card for each book in array
myLibrary.forEach((myLibrary) => {
const card = document.createElement("div");
card.classList.add("card");
books.append(card);
//Adds all the content into the card
for (let key in myLibrary) {
console.log("a");
if (counter <= 0) {
const titleHeader = document.createElement("h5");
titleHeader.textContent = `${myLibrary[key]}`;
titleHeader.classList.add("card-title");
card.appendChild(titleHeader);
counter = 1;
} else if (counter < 2) {
const cardAuthor = document.createElement("p");
cardAuthor.textContent = `${myLibrary[key]}`;
cardAuthor.classList.add("card-author");
card.appendChild(cardAuthor);
counter = 2;
} else if (counter < 3) {
const cardPages = document.createElement("p");
cardPages.textContent = `${myLibrary[key]}`;
cardPages.classList.add("card-pages");
card.appendChild(cardPages);
counter = 3;
} else if (counter < 4) {
const readContainer = document.createElement("div");
readContainer.classList.add("read");
card.appendChild(readContainer);
const readElement = document.createElement("p");
readElement.textContent = `${myLibrary[key]}`;
readElement.classList.add("card-read");
readContainer.append(readElement);
counter = 4;
} else if (counter < 5) {
const imageContainer = document.createElement("div");
imageContainer.classList.add("book-image-container");
card.appendChild(imageContainer);
const bookImage = document.createElement("img");
bookImage.src = `${myLibrary[key]}`;
bookImage.classList.add("book-image");
imageContainer.append(bookImage);
const editContainer = document.createElement("div");
editContainer.classList.add("edit-container");
card.appendChild(editContainer);
const editBtn = document.createElement("button");
editBtn.innerText = "Edit";
editBtn.classList.add("edit");
editContainer.append(editBtn);
const deleteContainer = document.createElement("div");
deleteContainer.classList.add("delete-container");
card.appendChild(deleteContainer);
const deleteBtn = document.createElement("button");
deleteBtn.innerText = "Delete";
deleteBtn.classList.add("delete");
deleteContainer.append(deleteBtn);
}
}
function resetCounter() {
counter = 0;
}
resetCounter();
});
}
//New book button
const newBookBtn = document.getElementById("newBookBtn");
newBookBtn.addEventListener("click", toggleForm);
//Displays the new book form
function toggleForm() {
const fstyle=document.getElementById("formContainer").style;
fstyle.display=fstyle.display==""?"none":"";
}
//eventlistener on form to submit data
const submitBtn = document.querySelector(".submit-button");
submitBtn.addEventListener("click", intakeFormData);
//transform form data to variables
function intakeFormData(ev) {
ev.preventDefault();
toggleForm();
let title = document.getElementById("Title").value;
let author = document.getElementById("Author").value;
let pages = document.getElementById("Pages").value;
let read = document.getElementById("Read").value;
let imageURL = document.getElementById("imageURL").value;
addBookToLibrary(title, author, pages, read, imageURL);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="text/javascript" src="script.js" defer></script>
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="resetcss.css" />
<title>Sign-Up Form</title>
</head>
<body id="body">
<div class="sideBar">
<div class="menuItem">
<img class="white dashIcon" src="./images/view-dashboard-variant-outline.png" alt="" />
<h1>Dashboard</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/home.png" alt="" />
<h1>Home</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/account.png" alt="" />
<h1>Profile</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/message.png" alt="" />
<h1>Messages</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/clock.png" alt="" />
<h1>History</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/note-multiple.png" alt="" />
<h1>Tasks</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/account-group.png" alt="" />
<h1>Communities</h1>
</div>
<!--Needs extra spacing-->
<div class="menuItem">
<img class="white" src="./images/cog.png" alt="" />
<h1>Settings</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/help-circle.png" alt="" />
<h1>Support</h1>
</div>
<div class="menuItem">
<img class="white" src="./images/shield-check-outline.png" alt="" />
<h1>Privacy</h1>
</div>
</div>
<div class="header">
<!--Top section-->
<div class="topHeader">
<div class="search">
<div class="menuItem">
<img src="./images/magnify.png" alt="" />
</div>
<input type="text" name="search" />
</div>
<div class="account">
<div class="menuIcon">
<img src="./images/bell.png" alt="" />
</div>
<img class="avatar" src="./images/avatar.jpg" alt="" />
<p class="name">Benjamin Gill</p>
</div>
</div>
<!--Bottom section-->
<div class="bottomHeader">
<div class="profile">
<img class="avatar" src="./images/avatar.jpg" alt="" />
<div class="profile-name">
<p class="greeting">Hi there,</p>
<p class="name">
Benjamin Gill <span class="username">(#Bgill)</span>
</p>
</div>
</div>
<div class="buttons">
<button id="newBookBtn" class="btn">New Book</button>
</div>
</div>
</div>
<div class="content">
<div class="projects">
<h3>Your Books:</h3>
<div class="cards">
<div class="card">
<h5 class="card-title">The Hobbit</h5>
<p class="card-author">by: J.R.R. Tolken</p>
<p class="card-pages">345 pages</p>
<div class="read">
<p class="card-read">Not yet read</p>
</div>
<div class="book-image-container">
<img src="https://upload.wikimedia.org/wikipedia/en/thumb/a/a9/The_Hobbit_trilogy_dvd_cover.jpg/220px-The_Hobbit_trilogy_dvd_cover.jpg" alt="" class="book-image" />
</div>
<div class="edit-container">
<button class="edit">Edit</button>
</div>
<div class="delete-container">
<button class="delete">Delete</button>
</div>
</div>
<div id="formContainer" class="cards" style="display: none">
<form id="newBookForm" class="card">
<input type="text" name="Title" id="Title" class="card-title" placeholder="Book Title..." />
<input type="text" name="Author" id="Author" placeholder="Author Name..." class="card-author" />
<input type="number" name="Pages" id="Pages" placeholder="Amount of Pages..." class="card-pages" />
<input type="text" name="Read" id="Read" placeholder="Have you read this?" class="read" />
<input type="text" name="imageURL" id="imageURL" placeholder="Enter image URL..." class="book-image-container" />
<div class="edit-container">
<button type="reset" class="reset-button edit">
Reset Form
</button>
</div>
<div class="delete-container">
<button type="submit" class="submit-button delete">
Sumbit to Library
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>

Increment a random number with a button?

I'm new to coding and I have the following problem:
I created a random number and I have it in a p tag which has a class, then I tried to increment this number by clicking on a button. This is my code so far:
$(document).ready(function(){
let films = JSON.parse(movies);
for (let i = 0; i < films.length; i++){
let movie = `
<div class="container">
<div class="poster">
<img class="pic" src="${films[i].image}">
</div>
<div class="text-box">
<div class="details">
<h2>${films[i].title}</h2>
<p>${films[i].releaseDate}</p>
<p>Genre: ${films[i].genre}</p>
<p>Director: ${films[i].director}</p>
</div>
<div class="like-box">
<input type="button" class="btn" value="Like 👍" number="${i}"></input>
<p class="counter"></p>
</div>
</div>
</div>
`;
$("#main2").append(movie);
$(".counter").text(Math.floor((Math.random()*100) + 1));
}
$(".btn").click(function() {
let el = parseInt($(".counter").text());
$(".counter").text(el+1);
})
});
The problem is, that if I click on the button instead of getting for example: 19 then after the click 20, what I get is 191919191920. So basically the button works, but not exactly how I want it to work. Can anybody help me please?
for (let i = 0; i < films.length; i++){
after this for loop is done, there will be films.length elements in dom with class counter.
and what this $(".counter").text() will return is concatenation of all text in elements with classes counter. That's why you got 191919191920.
Changes you would need to do:
Add new class to the container increaseing row count. This is mandatory to identify which movie you're on and increase the like value.
<div class='container row-" +i+ "'">
Then add onClick event to the like button to pass which row you're on. This is to identify which counter to increase the value.
<input type="button" class="btn" value="Like 👍" number="1" onclick="incrementLikes('row-" +i+ "')"></input>
$(document).ready(function() {
$(".counter").text(Math.floor((Math.random() * 100) + 1));
});
function incrementLikes(rowId) {
let mainRow = document.getElementsByClassName(rowId)[0];
let counter = parseInt(mainRow.getElementsByClassName('counter')[0].innerHTML);
mainRow.getElementsByClassName('counter')[0].innerHTML = counter + 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container row-1">
<div class="poster">
<img class="pic" src="">
</div>
<div class="text-box">
<div class="details">
<h2>Film Title 1</h2>
<p>13/06/2020</p>
<p>Genre: Action</p>
<p>Director: John Doe</p>
</div>
<div class="like-box">
<input type="button" class="btn" value="Like 👍" number="1" onclick="incrementLikes('row-1')"></input>
<p class="counter"></p>
</div>
</div>
</div>
<div class="container row-2">
<div class="poster">
<img class="pic" src="">
</div>
<div class="text-box">
<div class="details">
<h2>Film Title 2</h2>
<p>13/06/2020</p>
<p>Genre: Action</p>
<p>Director: John Doe</p>
</div>
<div class="like-box">
<input type="button" class="btn" value="Like 👍" number="1" onclick="incrementLikes('row-2')"></input>
<p class="counter"></p>
</div>
</div>
</div>
<div class="container row-3">
<div class="poster">
<img class="pic" src="">
</div>
<div class="text-box">
<div class="details">
<h2>Film Title 3</h2>
<p>13/06/2020</p>
<p>Genre: Action</p>
<p>Director: John Doe</p>
</div>
<div class="like-box">
<input type="button" class="btn" value="Like 👍" number="1" onclick="incrementLikes('row-3')"></input>
<p class="counter"></p>
</div>
</div>
</div>
The problem is your selector ".counter"
$(".counter").text returns the combined string value of all elements that have the class ".counter"
I have modified your code using selectors specific to the clicked button
let films = JSON.parse(movies);
for (let i = 0; i < films.length; i++){
let buttonId = "button" + i;
let movie = `
<div class="container">
<div class="poster">
<img class="pic" src="${films[i].image}">
</div>
<div class="text-box">
<div class="details">
<h2>${films[i].title}</h2>
<p>${films[i].releaseDate}</p>
<p>Genre: ${films[i].genre}</p>
<p>Director: ${films[i].director}</p>
</div>
<div class="like-box">
<input id="${buttonId}" type="button" class="btn" value="Like 👍" number="${i}"></input>
<p class="counter"></p>
</div>
</div>
</div>
`;
$("#main2").append(movie);
$("#${buttonId}.btn").next().text(Math.floor((Math.random()*100) + 1));
}
$("#${buttonId}.btn").click(function() {
let el = parseInt($("#${buttonId}.btn").next().text());
$("#${buttonId}.btn").next().text(el+1);
})

How to make a search and filter using javascript

So I am trying to make a Photo filter search. I am able to get to the keyup function but then get stuck on how to search and select the paragraph text. I can not alter the HTML and can only add Javascript.
And what I have so far in my Javascript
window.addEventListener('load', function(e) {
const query = document.querySelector('#filter');
let images = document.querySelector('.thumb-display');
query.addEventListener('keyup', function(e) {
let search = query.value;
for (var i = 0; i < images.length; i++) {
let searchVal = images[i].getElementByTagName('p')[0].innerHTML;
if (searchVal.indexOf(search) > -1) {
images[i].display = "";
} else {
images[i].display = "none";
};
};
});
})// NO CODE OUTSIDE OF HERE
I want to be able to search the (for example) #oceanbeach #mountainroad text and have the images that don't go with the search to be hidden but I can't get it to work.
You can use the input event for the textbox and loop through the p tags to show/hide the .thumb-display.
const txtFilter = document.getElementById('filter');
const lnkReset = document.querySelector('.reset');
const thumbnails = document.querySelectorAll('.thumb-display');
const tagContainers = document.querySelectorAll('.tags');
txtFilter.addEventListener('input', e => {
const filter = e.target.value;
if (filter === '') {
resetFilter();
} else {
// Show the reset link/button.
lnkReset.classList.remove('hidden');
tagContainers.forEach(tagContainer => {
const thumbnail = tagContainer.closest('.thumb-display');
const tags = tagContainer.innerText;
if (tags.indexOf(filter) >= 0) {
thumbnail.classList.remove('hidden');
} else {
thumbnail.classList.add('hidden');
}
});
}
});
lnkReset.addEventListener('click', e => {
e.preventDefault();
resetFilter();
});
function resetFilter() {
thumbnails.forEach(thumbnail => thumbnail.classList.remove('hidden'));
lnkReset.classList.add('hidden');
txtFilter.value = '';
}
body {
font: normal 14px/1.4 sans-serif;
}
img {
background: #eee;
display: inline-block;
height: 100px;
width: 100px;
}
.hidden {
display: none;
}
<nav>
<ul>
<li>
Home
</li>
</ul>
<form class="frm-filter">
<div class="frm-group">
<a class="reset hidden" href="#">Reset</a>
<input class="frm-control" type="text" id="filter" name="filter" placeholder="tag filter" />
</div>
</form>
</nav>
<section class="gallery">
<div class="row">
<h1>Gallery</h1>
</div>
<div class="row">
<div class="thumb-display">
<img />
<p class="tags">#africa #mountain #road</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#palmbeach #distantpeaks</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#oceanbeach #mountainroad</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#lake #clearskies #onthewater</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#fallcolors #bridgecrossing #river</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#fallcolors #slowdown</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#falltrees</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#ontheroad #falldriving</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#mountainflowers #clouds #river</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#mountainlake #retreat</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#stormcoming #thepeak</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#perfectbeach #whitesand</p>
</div>
</div>
</section>
Note that this just checks for the value of the innerText of the p tag.
let images = document.querySelector('.thumb-display');
I think you're looking for .querySelectorAll().
This would be a good place to start:
let images = [ ...document.querySelectorAll('.thumb-display') ];
To select all elements .thumb-display you have to use Document.querySelectorAll()
document.querySelectorAll('.thumb-display')
And then you can do:
const query = document.querySelector('#filter')
const reset = document.querySelector('.reset')
const thumbs = document.querySelectorAll('.thumb-display')
query.addEventListener('keyup', () => thumbs.forEach(t => {
const p = t.querySelector('p')
t.style.display = p.innerText.includes(query.value) ? '' : 'none'
}))
reset.addEventListener('click', (e) => {
e.preventDefault()
query.value = ''
thumbs.forEach(t => t.style.display = '')
})
img {
background: grey;
height: 20px;
width: 60px;
}
<div class="wrapper">
<nav>
<form class="frm-filter">
<div class="frm-group">
<a class="reset hidden" href="#">Reset</a>
<input class="form-control" type="text" id="filter" name="filter" placeholder="tag filter" />
</div>
</form>
</nav>
<section class="gallery">
<div class="row">
<h1>Gallery</h1>
</div>
<div class="row">
<div class="thumb-display">
<img />
<p class="tags">#africa #mountain #road</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#palmbeach #distantpeaks</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#oceanbeach #mountainroad</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#lake #clearskies #onthewater</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#fallcolors #bridgecrossing #river</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#fallcolors #slowdown</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#falltrees</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#ontheroad #falldriving</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#mountainflowers #clouds #river</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#mountainlake #retreat</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#stormcoming #thepeak</p>
</div>
<div class="thumb-display">
<img />
<p class="tags">#perfectbeach #whitesand</p>
</div>
</div>
</section>
</div>

Hide parent div class if child div class does not have content when there are multiple parent divs with the same class name

I have a slider where some of the images in the slider can have an optional photo- credit containing text or link in a popper. I would like to iterate over all of the popper instances and if all of the p tags in the .photo-credit p class are empty, then hide only that instance of the parent popper. I've tried to piece together a solution from some other posts, but have not been able to get it to work. The code I have does not hide a popper if all p tags are empty for that popper. I'm a JavaScript newbie and would appreciate any help.
HTML
<div class="slider-wrapper">
<!--Required Root Element-->
<div class="slider">
<!--Required List Element-->
<div class="slider-list">
<div class="slider-item">
<div class="slider-image-container"><img class="slider-image" src="http://www.someurl.com/Images/Homepage Images/Slider/image1.jpg" /></div>
<div class="slider-content-container">
<h1>B LIne: The Place to Be</h1>
<div class="learn-more">Learn More</div>
</div>
<div class="popper">
<img data-toggle="popover" class="photo-credit-icon" src="http://www.someurl.com/icon-photography.svg" alt="photo credit" />
</div>
<div class="photo-credit hide">
<p><p>A photo credit.</p></p>
<p></p>
</div>
</div><div class="slider-item">
<div class="slider-image-container"><img class="slider-image" src="http://www.someurl.com/Images/Homepage Images/Slider/anotherimage.jpg" /></div>
<div class="slider-content-container">
<h1>July 4th: You missed it!</h1>
<div class="learn-more">Learn More</div>
</div>
<div class="popper">
<img data-toggle="popover" class="photo-credit-icon" src="http://www.someurl.com/icon-photography.svg" alt="photo credit" />
</div>
<div class="photo-credit hide">
<p></p>
<p></p>
</div>
</div><div class="slider-item">
<div class="slider-image-container"><img class="slider-image" src="http://www.someurl.com/Images/Homepage Images/Slider/anotherimage.jpg" /></div>
<div class="slider-content-container">
<h1>Festival coming Aug. 31st!</h1>
<div class="learn-more">Learn More</div>
</div>
<div class="popper">
<img data-toggle="popover" class="photo-credit-icon" src="http://www.someurl.com/icon-photography.svg" alt="photo credit" />
</div>
<div class="photo-credit hide">
<p></p>
<p></p>
</div>
</div>
</div>
</div>
<img src="http://www.someurl.com/images/icons/icon-chevron-left-slider.svg">
<img src="http://www.someurl.com/images/icons/icon-chevron-right-slider.svg">
<p class="slider-pagination"></p>
</div>
JavaScript
$('.popper').each(function () {
//var $thisPopper = $(this);
var hasContent = 0;
$('.photo-credit p').each(function () {
if($(this).html().length > 0) {
hasContent++;
}
});
if(hasContent > 0){
//$thisPopper.hide();
$(this).hide();
}
});
You were on the right direction. However a couple mistakes in your javascript.
You tried to target all the div with "popper" class. However, the div with "popper" and "photo-credit" are on the same level. Why not targeting their parent div instead?
Try this code. It's been tested (Link to jsfiddle)
$('.slider-item').each(function () {
var thisSilerItem = $(this);
var hasContent = 0;
thisSilerItem.find('.photo-credit p').each(function () {
if($(this).html().length > 0) {
hasContent++;
}
});
if(hasContent <= 0){
thisSilerItem.find('.popper').hide();
}
});
Edit:
Bonus:
If your page has a large amount of sliders, this jquery solution will cause some UX issues ("jumpy" div on/after page load)
Try a CSS only solution.
When you render your DOM elements. Add a class to "popper" div if the content of "photo-credit" is empty.
<div class="popper hide">
// img
</div>
Then in your CSS, add
.popper.hide { display: none; }
It's hard to fully gather what you want to do, but if I understand correctly...
$('.popper').each(function () {
var photoCredit = $(this).find(".photo-credit p")
if ( $(photoCredit).is(':empty') ){
$(this).hide();
}
});
It's worth pointing out that CSS4 developers are working on a 'has' selector but as of July 2017 there is no support for any browser just yet.
It is expected to work in the following manner:
.popper:has(> p:empty) { display: none }
I hope this helps... :)
You can check this code.
$.each($('.popper'), function (index, popper) {
var isEmptry = true;
$.each($(popper).next('.photo-credit').children(), function (index, ptag) {
if ($.trim($(ptag).html()) != '')
isEmptry = false;
});
if (isEmptry)
$(popper).hide();
});
Working code
$.each($('.popper'), function (index, popper) {
var isEmptry = true;
$.each($(popper).next('.photo-credit').children(), function (index, ptag) {
if ($.trim($(ptag).html()) != '')
isEmptry = false;
});
if (isEmptry)
$(popper).hide();
});
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<div class="slider-wrapper">
<!--Required Root Element-->
<div class="slider">
<!--Required List Element-->
<div class="slider-list">
<div class="slider-item">
<div class="slider-image-container">
<img class="slider-image" src="http://www.someurl.com/Images/Homepage Images/Slider/image1.jpg" />
</div>
<div class="slider-content-container">
<h1>B LIne: The Place to Be</h1>
<div class="learn-more">Learn More</div>
</div>
<div class="popper">
<img data-toggle="popover" class="photo-credit-icon" src="http://www.someurl.com/icon-photography.svg" alt="photo credit" />
</div>
<div class="photo-credit hide">
<p>
<p>A photo credit.</p>
</p>
<p></p>
</div>
</div>
<div class="slider-item">
<div class="slider-image-container">
<img class="slider-image" src="http://www.someurl.com/Images/Homepage Images/Slider/anotherimage.jpg" />
</div>
<div class="slider-content-container">
<h1>July 4th: You missed it!</h1>
<div class="learn-more">Learn More</div>
</div>
<div class="popper">
<img data-toggle="popover" class="photo-credit-icon" src="http://www.someurl.com/icon-photography.svg" alt="photo credit" />
</div>
<div class="photo-credit hide">
<p></p>
<p></p>
</div>
</div>
<div class="slider-item">
<div class="slider-image-container">
<img class="slider-image" src="http://www.someurl.com/Images/Homepage Images/Slider/anotherimage.jpg" />
</div>
<div class="slider-content-container">
<h1>Festival coming Aug. 31st!</h1>
<div class="learn-more">Learn More</div>
</div>
<div class="popper">
<img data-toggle="popover" class="photo-credit-icon" src="http://www.someurl.com/icon-photography.svg" alt="photo credit" />
</div>
<div class="photo-credit hide">
<p></p>
<p></p>
</div>
</div>
</div>
</div>
<a href="#" class="slider-control-prev">
<img src="http://www.someurl.com/images/icons/icon-chevron-left-slider.svg"></a>
<a href="#" class="slider-control-next">
<img src="http://www.someurl.com/images/icons/icon-chevron-right-slider.svg"></a>
<p class="slider-pagination"></p>
</div>

how to get a grid of different sizes using css and javascript

I have a dynamically created grid with images of different sizes how do i get a tiled gallary
<div class="container">
<div class="block1">
<img src="img1" />
</div>
<div class="block2">
<img src="img1" />
</div>
<div class="block3">
<img src="img1" />
</div>
<div class="block4">
<img src="img1" />
</div>
</div>
I do not want to use third party libraries any help would be appreciated..
You can resize your images by JavaScript. For example, this code will resize each img at the maximumHeight value.
JSFiddle: http://jsfiddle.net/FU76g/
HTML:
<div class="container" id="container">
<div class="block1">
<img src="http://placehold.it/350x150" />
</div>
<div class="block2">
<img src="http://placehold.it/100x100" />
</div>
<div class="block3">
<img src="http://placehold.it/250x200" />
</div>
<div class="block4">
<img src="http://placehold.it/350x150" />
</div>
</div>
JavaScript:
var container_div = document.getElementById("container");
var array_img=container_div.getElementsByTagName("img");
var maxHeight=0;
for(var index = 0; index < array_img.length; index++){
if (array_img[index].clientHeight > maxHeight){
maxHeight = array_img[index].clientHeight;
}
}
alert("will do");
for(index = 0; index < array_img.length; index++){
array_img[index].height = maxHeight;
}
alert("done");

Categories