How do I apply the same logic to multiple repeated elements? - javascript

I am trying to add the same drop down functionality to an amount n of "cards". How could I do this in javascript without having to create new code for each card?
This is my current code that I have tried, but even if I got this working it would only work for the first card: (working example below)
my html:
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow"></i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow"></i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
js:
var maintxt = document.querySelector(".maintext");
var title = document.querySelector(".title");
var titleArrow = document.querySelector(".title-arrow");
var mainArrow = document.querySelector(".maintxt-arrow");
var comments = document.querySelector(".comments");
var mainArrows = document.querySelectorAll(".maintxt-arrow")
titleArrow.addEventListener('click', function() {
maintxt.classList.toggle("hidden");
mainArrow.classList.toggle("hidden");
if (comments.classList.contains("hidden")){
;
} else {
comments.classList.toggle("hidden");
};
});
mainArrow.addEventListener("click", function() {
comments.classList.toggle("hidden");
});
Example: https://codepen.io/ricodon1000/pen/Baoxwed
I would like for the dropdown arrows to trigger the boxes below them, the upper arrow should trigger only the box below it on, but if both boxes are open both should be closed. The arrow that is below should only trigger the box directly below it on and off (display: none on and off).

Do the same for each node, and limit your querySelector to the group
const ideanodes = [...document.querySelectorAll('.ideanode')];
ideanodes.forEach(ideanode => {
const maintxt = ideanode.querySelector(".maintext");
const title = ideanode.querySelector(".title");
const titleArrow = ideanode.querySelector(".title-arrow");
const mainArrow = ideanode.querySelector(".maintxt-arrow");
const comments = ideanode.querySelector(".comments");
titleArrow.addEventListener('click', function() {
maintxt.classList.toggle("hidden");
mainArrow.classList.toggle("hidden");
if (comments.classList.contains("hidden")) {;
} else {
comments.classList.toggle("hidden");
};
});
mainArrow.addEventListener("click", function() {
comments.classList.toggle("hidden");
});
});

You have a couple of options here, but the thing they have in common is that when you get a click on a .title-arrow element, you know which .title-arrow was clicked because it's the value of this (and event.currentTarget) in the event callback. From there, you can find the other elements it relates to using various DOM properties and methods, such as closest or the element version of querySelector.
So you could loop through all the .title-arrow elements and hook click on them, and then work it out from there. But I think you probably want to use event delegation instead: Hook click once, on the container for the various .ideanode elements, and then use event.target to figure out what to do.
I assume all those .ideanode elements are in a container, e.g. something like:
<div class="container">
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<!-- ...and so on... -->
</div>
So you can do this (see comments):
// A single handler on the container
document.querySelector(".container").addEventListener("click", function(event) {
// Find the arrow that was clicked and the .ideanode it's in, if any
const arrow = event.target.closest(".title-arrow, .maintxt-arrow");
const ideanode = arrow && arrow.closest(".ideanode");
if (!ideanode || !this.contains(ideanode)) {
// Click wasn't on a `.title-arrow` or a `.maintxt-arrow` within an `.ideanode`
return;
}
if (arrow.matches(".title-arrow")) {
// It was a .title-arrow
titleArrowClick.call(arrow, ideanode, event);
} else {
// It was a .maintxt-arrow
mainArrowClick.call(arrow, ideanode, event);
}
});
function titleArrowClick(ideanode, event) {
// Use `querySelector` to look for elements within `.ideanode`
ideanode.querySelector(".maintext").classList.toggle("hidden");
ideanode.querySelector(".maintxt-arrow").classList.toggle("hidden");
const comments = ideanode.querySelector(".comments");
// (Couldn't the following be replaced with `comments.classList.add("hidden");` ?)
if (comments.classList.contains("hidden")){
;
} else {
comments.classList.toggle("hidden");
};
}
function mainArrowClick(ideanode, event) {
ideanode.querySelector(".comments").classList.toggle("hidden");
}
Live Example:
// A single handler on the container
document.querySelector(".container").addEventListener("click", function(event) {
// Find the arrow that was clicked and the .ideanode it's in, if any
const arrow = event.target.closest(".title-arrow, .maintxt-arrow");
const ideanode = arrow && arrow.closest(".ideanode");
if (!ideanode || !this.contains(ideanode)) {
// Click wasn't on a `.title-arrow` or a `.maintxt-arrow` within an `.ideanode`
return;
}
if (arrow.matches(".title-arrow")) {
// It was a .title-arrow
titleArrowClick.call(arrow, ideanode, event);
} else {
// It was a .maintxt-arrow
mainArrowClick.call(arrow, ideanode, event);
}
});
function titleArrowClick(ideanode, event) {
// Use `querySelector` to look for elements within `.ideanode`
ideanode.querySelector(".maintext").classList.toggle("hidden");
ideanode.querySelector(".maintxt-arrow").classList.toggle("hidden");
const comments = ideanode.querySelector(".comments");
// (Couldn't the following be replaced with `comments.classList.add("hidden");` ?)
if (comments.classList.contains("hidden")){
;
} else {
comments.classList.toggle("hidden");
};
}
function mainArrowClick(ideanode, event) {
ideanode.querySelector(".comments").classList.toggle("hidden");
}
.hidden {
display: none;
}
<div class="container">
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<!-- ...and so on... -->
</div>

Here's a suggestion, out of the many possibilities to tackle such a thing:
You start with the most basic array of classnames references and build you way into an Object with keys & values which values represent DOM nodes.
For the events part, you should very much use event-delegation so you won't need to bind an event for each and every card. Just make sure they have the same parent node, and bind your events there.
// preparation
var elms = ['maintext', 'title-arrow', 'maintxt-arrow'].reduce((acc, name) => {
acc[name] = document.querySelector(`.${name}`)
return acc
}, {}
)
// iterating each "variable"
for( let elm in elms )
console.log(elm)
<div class='maintext'></div>
<div class='title-arrow'></div>
<div class='maintxt-arrow'></div>

Related

How to look for child elements in a collection

im very new to javascript and probably thats a silly question. What I am trying to achieve is to loop through rows of a "table", get the innerHTML of specific child nodes and multiply them together.
The html looks like this:
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">5</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">2</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
To be specific: I want to get both the values inside the'countChild' and the 'valueChild'. In this example those are 5 and 30 for the first row and for the second row its 2 and 30. Then perform a muiltiplication.
What I tried to do is to get all the parent nodes and then iterating through them to get the child nodes.
const parents = document.getElementsByClassName('parent');
for(var row in parents) {
var count = row.getElementsByClassName('countChild').lastChild.innerHTML;
var value = row.getElementsByClassName('valueChild').lastChild.innerHTML;
....
}
However the debugger already throws an error when im trying to get the childs. The error message is row.getElemenstByClassName is not a function. I guess the collection cannot be used like this and my understanding of how to use js to get information from the document is wrong.
Edit: This is what the tree looks like
<div class="listing-entry">
<div class="value-container d-none d-md-flex justify-content-end">
<div class="d-flex flex-column">
<div class="d-flex align-items-center justify-content-end">
<span class="font-weight-bold color-primary small text-right text-nowrap">30</span>
</div>
</div>
</div>
<div class="count-container d-none d-md-flex justify-content-end mr-3">
<span class="item-count small text-right">5</span>
</div>
</div>
You should access parents like an array (not really array but you can cast it to one). Btw, I encourage you to use querySelectorAll and querySelector instead of getElementsByClassName
const parents = document.querySelectorAll(".parent")
parents.forEach(function(row) {
var countChild = row.querySelector(".countChild")
var valueChild = row.querySelector(".valueChild")
var count = countChild ? countChild.innerText : 0
var value = valueChild ? valueChild.innerText : 0
console.log(count, value, count * value)
})
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">5</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">2</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
Edit: I'm using querySelector instead of getElementsByClassName, and checking if child exists before accessing its innerText property.
Edit: here's a function to get all text nodes under a specific node. Then you can combine them and trim the result to get the value you want.
function textNodesUnder(node) {
var all = [];
for (node = node.firstChild; node; node = node.nextSibling) {
if (node.nodeType == 3) {
all.push(node);
} else {
all = all.concat(this.textNodesUnder(node));
}
}
return all;
}
var nodes = textNodesUnder(document.querySelector(".listing-entry"))
var texts = nodes.map(item => item.nodeValue.trim())
console.log(texts)
<div class="listing-entry">
<div class="value-container d-none d-md-flex justify-content-end">
<div class="d-flex flex-column">
<div class="d-flex align-items-center justify-content-end">
<span class="font-weight-bold color-primary small text-right text-nowrap">30</span>
</div>
</div>
</div>
<div class="count-container d-none d-md-flex justify-content-end mr-3">
<span class="item-count small text-right">5</span>
</div>
</div>

Why when I create several html tags with javascript then I can not delete it with the same javascript?

When I create a form with the write () command, then I want to delete it, but I can't. What is the cause of this problem?
In order to do this correctly, what command should I use or what should I change in my code?
var btn = document.querySelector('#btn');
var btn_alert = document.querySelector('#btn-alert');
var content = document.querySelector('.popup-container');
var div1 = document.getElementById('div1');
function message(message, btn) {
document.write('<div id="div1"><div id="content" class="popup-container"><div class="box-item"><div class="icon-success"><span class="span1"></span> <span class="span2"></span><div class="ring"></div></div><h2 class="alert-title">Good job!</h2><div class="alert-content">' + message + '</div><div class="actions-btn"><button onclick="ok()" class="btn-alert" id="btn-alert">' + btn + '</button></div></div></div></div>')
}
function ok() {
div1.removeChild(content);
}
<button class="btn-alert" id="btn">OK</button>
<!-- <div id="content" class="popup-container dis-active">
<div class="box-item">
<div class="icon-success">
<span class="span1"></span>
<span class="span2"></span>
<div class="ring"></div>
</div>
<h2 class="alert-title">Good job!</h2>
<div class="alert-content">is ok.</div>
<div class="actions-btn">
<button class="btn-alert" id="btn-alert">OK</button>
</div>
</div>
</div> -->
<script src="script.js"></script>
<script>
message("خوش اومدی!", "کلیک کن");
</script>
document.write is really outdated. In your script you write the elements to the document after you're trying to retrieve them. That won't work.
Here is an example snippet using insertAdjacentHTML to create a message element with a button to remove it.
It is generally not a good idea to use inline event handlers. The snippet uses event delegation to handle button clicks.
It may be wise to first learn more about html document manipulation or javascript.
document.addEventListener(`click`, handle);
const create = () => message(`خوش اومدی!`,`کلیک کن`);
create();
function handle(evt) {
if (evt.target.id === `btn-alert`) {
document.getElementById('div1').remove();
}
if (evt.target.id === `recreate`) {
create();
}
}
function message(message, btnTxt) {
document.body.insertAdjacentHTML(`beforeEnd`, `
<div id="div1">
<div id="content" class="popup-container">
<div class="box-item">
<div class="icon-success">
<span class="span1"></span>
<span class="span2"></span>
<div class="ring"></div>
</div>
<h2 class="alert-title">Good job!</h2>
<div class="alert-content">${message}</div>
<div class="actions-btn">
<button class="btn-alert" id="btn-alert">${btnTxt}</button>
</div>
</div>
</div>
</div>`);
}
<button id="recreate">(re)create message</button>

How can I add elements in JS to certain divs

How do I put the created input into the other div in situation I presented below? If I introduce divs in js like this - '<div class="monday_input"><input type="button" class="remove_button" value="-" onclick="removeMon(this)" /></div>' removing the whole element is not working for some reason in this specific case. Answering the question. No I cannot create div in parent in html because input won't magically suit to created div . Please help me somehow, thank you!
HTML:
<div class="day">
<div class="day_info">
<p>Monday</p>
</div>
<div class="add">
<div class="button" onclick="add_monday()">
<i class="fas fa-plus" id="plus"></i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="mon">
<div style="clear:both"></div>
</div>
JavaScript:
Function to adding:
function add_monday() {
if (monday_sub_count < 5) {
monday_sub_count++;
{
const mon = document.createElement('div');
mon.className = 'subcategory';
mon.innerHTML = '<textarea name="monday'+monday_id_count+'" placeholder="Type anything you want here" class="subcategory_text"></textarea><input type="button" class="remove_button" value="-" onclick="removeMon(this)" />';
monday_id_count++;
document.getElementById('mon').appendChild(mon);
}
}
}
Function to removing:
function removeMon(mon) {
document.getElementById('mon').removeChild(mon.parentNode);
monday_sub_count--;
monday_id_count--;
};
with your own HTML
function add_monday() {
var monday_sub_count = 0;
var a;
while (monday_sub_count < 5) {
a = '<div><textarea name="monday'+monday_id_count+'" placeholder="Type anything you want here" class="subcategory_text"></textarea><input type="button" class="remove_button" value="-" onclick="removeMon(this)" /></div>';
monday_sub_count++;
$('#mon').append(a);
}
}
Here is working, "proper" version of your code. I think your problem may come from over-complicating the removal process.
function add_monday()
{
let monday_count = 0;
// Use DocumentFragment for marginal optimizations
let fragment = new DocumentFragment();
while(monday_count < 5)
{
let monday = document.createElement('div');
monday.classList.add('subcategory');
let textarea = document.createElement('textarea');
textarea.classList.add('subcategory_text');
textarea.name = "monday_"+monday_count;
textarea.placeholder = "Type anything you want here";
let removeBtn = document.createElement('input');
removeBtn.type = "button";
removeBtn.classList.add('remove_button');
removeBtn.value = "-";
removeBtn.addEventListener('click', removeMon.bind(null, removeBtn));
monday.append(textarea, removeBtn);
fragment.appendChild(monday);
monday_count++;
}
document.getElementById('mon').appendChild(fragment);
}
function removeMon(button)
{
button.parentElement.remove();
}
I simplified your script a little and changed your name attributes: Instead of assigning individual names I simply gave all textareas the name monday[]. When posting this to a PHP page the values will be pushed into an array with the same name and in case you want to harvest the values with JavaScript, then this can be done easily too.
function add_monday(){
$("#mon").append('<div><textarea name="monday[]" placeholder="Type anything you want here"></textarea><input type="button" value="-"/></div>'.repeat(5))
}
$("#mon").on("click","input[type=button]",function(){$(this).parent(). remove()})
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div class="day">
<div class="day_info">
<p>Monday</p>
</div>
<div class="add">
<div class="button" onclick="add_monday()">
<i class="fas fa-plus" id="plus">click here to add fields</i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="mon">
<div style="clear:both"></div>
</div>
And here a non-jQuery version:
const ad=document.querySelector(".alldays");
ad.innerHTML=
"Mon,Tues,Wednes,Thurs,Fri,Satur,Sun".split(",").map(d=>`
<div class="day">
<div class="day_info"><p>${d}day</p></div>
<div class="add">
<div class="button">
<i class="fas fa-plus" id="plus">click here to add fields</i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="${d.toLowerCase().substr(0,3)}">
<div style="clear:both"></div>
</div>`).join("");
function add2day(el,n){
const wd=el.closest(".day"),
d=wd.querySelector("p").textContent.toLowerCase(),
html=`<textarea name="${d.toLowerCase()}[]" placeholder="Type anything you want here"></textarea><input type="button" value="-"/>`;
while (n--) {
let div= document.createElement("div");
div.innerHTML=html;
wd.nextElementSibling.appendChild(div);
}
}
ad.addEventListener("click",function(ev){
const el=ev.target;
switch(el.tagName){
case "INPUT": // remove field
el.parentNode.remove(); break;
case "I": // add new fields
add2day(el,3); break;
}
})
<div class="alldays"></div>
I extended the second script to make it work for any day of the week.

How to bind this within js nested object iteration within a function. Jquery

again, probably a terrible title - but what I'm trying to do is to make a simple search feature on my website. You click a nav button, which updates the search bar, whi in turn triggers an onchange event to update the current appended list.
function update() {
var list = $("#comic__modern-list");
list.empty();
$.each(Object.keys(comics), function() {
var currentObject = comics[this];
var filter = comics[this].type;
var publisher = comics[this].publisher;
if (search == "") {
if(filter == "modern") {
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
} else if (search == publisher) {
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
});
}
The current list is generated by this, which works fine:
$.each(Object.keys(comics), function() {
var currentObject = comics[this];
var currentObject2 = comics[this].type;
console.log(currentObject2);
if (search == "") {
if(currentObject2 == "modern") {
var list = $("#comic__modern-list");
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
}
});
From what I can gather, this has to do with the keyword "this" no longer meaning what it did when it was outside of the function, so I'm assuming the fix will be to do with bind(), but I can't make heads nor tails of it.
p.s, if there's an easier/simpler way to set up a search system, please enlighten me!

JavaScript, HTML search engine - how to get parent of an element?

My problem is:
Search script is working, but it only hides h3 elements from the code.
<h3 class="post-subtitle" style="display: flex;">Protokoły tunelowania VPN</h3>
<h3 class="post-subtitle" style="display: flex;">Certyfikat cyfrowy</h3>
I need the code to hide the whole div with "post" ID instead of just h3 element.
How do i do that?
HTML Code for Search Bar:
<div id="kontener" class="container">
<div style="text-align:center" id="search-bar">
<input type="text" id="searchbar" onkeyup="searchBar()" class="shadow-lg">
</div>
</div>
HTML Code on Website
<!-- First element -->
<div id="post">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<div class="post-preview">
<a href="URL">
<h2 class="post-title"><i class="far fa-sticky-note fa-xs" aria-hidden="true"></i> ASO</h2>
<h3 class="post-subtitle" style="display: flex;">Protokoły tunelowania VPN</h3>
</a>
<p class="post-meta">11 Maj, 2021</p>
</div>
</div>
</div>
<hr>
</div>
<!-- End of First element -->
<!-- Second element -->
<div id="post">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<div class="post-preview">
<a href="URL">
<h2 class="post-title"><i class="far fa-sticky-note fa-xs" aria-hidden="true"></i> ELSK</h2>
<h3 class="post-subtitle" style="display: flex;">Certyfikat cyfrowy</h3>
</a>
<p class="post-meta">26 Kwiecień, 2021</p>
</div>
</div>
</div>
<hr>
</div>
<!-- End of Second element -->
JavaScript code:
<script>
function searchBar() {
let input = document.getElementById('searchbar').value
input=input.toLowerCase();
let x = document.getElementsByClassName('post-subtitle');
for (i = 0; i < x.length; i++) {
if (!x[i].innerHTML.toLowerCase().includes(input)) {
x[i].style.display="none";
}
else {
x[i].style.display="flex";
}
}
}
</script>
You just need to target couple of parent nodes, either by .parentElement / .parentNode or use .closest function.
Example:
<script>
function searchBar() {
let input = document.getElementById('searchbar').value
input=input.toLowerCase();
let x = document.getElementsByClassName('post-subtitle');
for (i = 0; i < x.length; i++) {
if (!x[i].innerHTML.toLowerCase().includes(input)) {
x[i].closest('#post').style.display="none";
// Or this below (note each parentElement targets parent tag)
// x[i].parentElement.parentElement.parentElement.parentElement.parentElement.style.display="none";
}
else {
x[i].closest('#post').style.display="flex";
}
}
}
</script>

Categories

Resources