Event handler for loop with dynamic jQuery selectors - javascript

What I want is to click on #bt-1 and change the color of #target-1, click on #bt-2 and change the color of #target-2...
I started writing a particular click event handler for each #bt-n / #target-n but as the site got bigger I thought about using a loop. My approach was using a for loop with variables in jQuery selectors. Here is my code:
$(document).ready(function() {
var total = $('.target').length;
for(n=1; n<=total; n++) {
var num = String(n);
$('#bt-'+num).on('click', function() {
$('#target-'+num).toggleClass('yellow');
});
}
});
.wrapper {
display: flex;
text-align: center;
}
.button, .target {
padding: 20px;
margin: 10px;
}
.button {
background: gray;
}
#target-1 {
background: red;
}
#target-2 {
background: green;
}
#target-3 {
background: blue;
}
.yellow {
background: yellow !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div id="bt-1" class="button">
<h1>Button 1</h1>
</div>
<div id="target-1" class="target">
<h1>Target 1</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-2" class="button">
<h1>Button 2</h1>
</div>
<div id="target-2" class="target">
<h1>Target 2</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-3" class="button">
<h1>Button 3</h1>
</div>
<div id="target-3" class="target">
<h1>Target 3</h1>
</div>
</div>
I don't understand why it only targets the last #target-n as the loop seems to be working on #bt-n. I also thought about using an array but can't figure out how to implement it.
I managed to make it work using $(this).siblings('.target')... which do not require the for loop and ids but a parent element for each .button / .target, in this case .wrapper Code Here. Although this was a good solution, I would like to understand what I did wrong and how to properly implement a loop to achieve this without using the parent .wrapper. Thank you.

The reason that only the last item gets affected is because the loop has completed before any event fires. Therefore n holds the last value in the loop. To fix this you need to use a closure:
for (n = 1; n <= total; n++) {
(function(n) {
$('#bt-' + n).on('click', function() {
$('#target-' + n).toggleClass('yellow');
});
})(n);
}
That said, a much better approach would be avoid the loop and to use DOM traversal to find the .target related to the clicked .button, like this:
$('.button').click(function() {
$(this).next('.target').toggleClass('yellow');
});
.wrapper {
display: flex;
text-align: center;
}
.button,
.target {
padding: 20px;
margin: 10px;
}
.button {
background: gray;
}
#target-1 {
background: red;
}
#target-2 {
background: green;
}
#target-3 {
background: blue;
}
.yellow {
background: yellow !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div id="bt-1" class="button">
<h1>Button 1</h1>
</div>
<div id="target-1" class="target">
<h1>Target 1</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-2" class="button">
<h1>Button 2</h1>
</div>
<div id="target-2" class="target">
<h1>Target 2</h1>
</div>
</div>
<div class="wrapper">
<div id="bt-3" class="button">
<h1>Button 3</h1>
</div>
<div id="target-3" class="target">
<h1>Target 3</h1>
</div>
</div>

It is unwise to register a lot of event handlers. You can bind one event handler and perform action for given specific idx read from element id, eg:
$('body').on('click', function (event) {
if (!event.target.id.match(/^bt-\d+/)) {
return; //id of clicked element does not match bt-{number}
}
var idx = event.target.id.replace('bt-', ''); //remove prefix "bt-" and leave only numeric postfix
$('#target-' + idx).toggleClass('yellow');
});
Explanation:
When you bind click on body element You are getting access to all click events from child elements that not cancelled passing that event up. Element that has been clicked in saved inside event.target and it has property id in event.target.id.
On this id property I call match function with regular expression - it will match string which starts ^ from bt- and have any number \d at least one one + .
if (!event.target.id.match(/^bt-\d+/)) {
return; //id of clicked element does not match bt-{number}
}
There is negation of this statement, so If this id is not in format bt-someNumber it will not go further.
var idx = event.target.id.replace('bt-', '');
Than takes id and replaces bt- part in it with empty string ''
$('#target-' + idx).toggleClass('yellow');
Finally You are toggling class on element with same number as button but with different prefix target- instead of bt-.
Happy hacking!

Related

Select the third div from bottom

How can i select the third div from bottom (i.e in this case, the div with "4")
<div class='elem'>1</div>
<div class='elem'>2</div>
<div class='elem'>3</div>
<div class='elem'>4</div>
<div class='elem'>5</div>
<div class='elem'>6</div>
I tried this but it selected last three divs.
$('div:gt(-3)').css('background':'red');
Kindly know that, i may not know the total divs(it's dynamic), but i only need to select the third div from bottom.
You can use the eq() method by specifying a value of -3, which will hover over the third element from the bottom.
$('div:eq(-3)').css('background', 'red');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='elem'>1</div>
<div class='elem'>2</div>
<div class='elem'>3</div>
<div class='elem'>4</div>
<div class='elem'>5</div>
<div class='elem'>6</div>
If all you're trying to do is apply styling to that element:
/* a simple reset so all elements have similar
and consistent defaults: */
*,
::before,
::after {
box-sizing: border-box;
font-size: 1rem;
line-height: 1.5;
margin: 0;
padding: 0;
}
/* purely for aesthetics in order to visually
separate each of the 'demo' blocks; using
CSS logical properties to define margins: */
.demo {
border: 1px solid #000;
margin-block: 1em;
margin-inline: 0.5em;
}
/* to visually distinguish the selected elements: */
.elem:nth-last-child(3) {
background-color: #f00;
color: #fff;
}
<div class="demo">
<div class="elem">1</div>
<div class="elem">2</div>
<div class="elem">3</div>
<div class="elem">4</div>
<div class="elem">5</div>
<div class="elem">6</div>
<div class="elem">7</div>
<div class="elem">8</div>
<div class="elem">9</div>
<div class="elem">10</div>
</div>
<div class="demo">
<div class="elem">1</div>
<div class="elem">2</div>
<div class="elem">3</div>
</div>
<div class="demo">
<div class="elem">1</div>
</div>
If you instead need to use JavaScript, then I'd suggest the following:
// defining an Arrow function, passing two arguments:
// selector: a String, CSS selector with which to select the elements,
// index: a Number, the 1-based index of the element starting from
// the end. The last element would be index 1, the
// penultimate element index 2:
const nthLastChild = (selector, index) => {
// here we return an Array literal, which takes the spread operator and
// converts the iterable NodeList returned from document.querySelectorAll()
// and converts it into an Array:
return [...document.querySelectorAll(
// the template-literal we use to construct the CSS selector, we use a
// template-literal in order to interpolate the JavaScript variables
// into the String:
`${selector}:nth-last-child( ${Math.abs(index)} )`
)];
}
// because we return an Array, we can here use Array.prototype.forEach()
// - along with other Array methods - to perform operations on the returned
// elements:
nthLastChild('.elem', '-3').forEach(
(el) => {
el.style.color = '#fff';
el.style.fontWeight = 'bold';
el.style.background = 'linear-gradient(90deg, #f90, #fff)';
});
*,
::before,
::after {
box-sizing: border-box;
font-size: 1rem;
line-height: 1.5;
margin: 0;
padding: 0;
}
.demo {
border: 1px solid #000;
margin-block: 1em;
margin-inline: 0.5em;
}
<div class="demo">
<div class="elem">1</div>
<div class="elem">2</div>
<div class="elem">3</div>
<div class="elem">4</div>
<div class="elem">5</div>
<div class="elem">6</div>
<div class="elem">7</div>
<div class="elem">8</div>
<div class="elem">9</div>
<div class="elem">10</div>
</div>
<div class="demo">
<div class="elem">1</div>
<div class="elem">2</div>
<div class="elem">3</div>
<div class="elem">4</div>
</div>
<div class="demo">
<div class="elem">1</div>
<div class="elem">2</div>
<div class="elem">3</div>
</div>
<div class="demo">
<div class="elem">1</div>
</div>
References:
CSS:
:nth-last-child().
JavaScript:
Arrow functions.
Array.prototype.forEach().
document.querySelectorAll().
Spread (...) syntax.
Template literals.
const elements = document.querySelectorAll(".elem");
const lastThird = elements[elements.length - 3];
You can simply use $('body div')[$('body div').length-3]; as a selector. This selects all the <div>s and then selects the third from the bottom.
const allElem = [...document.querySelectorAll(".elem")];
allElem[allElem.length - 3].style.background = "red";
<div class="elem">1</div>
<div class="elem">2</div>
<div class="elem">3</div>
<div class="elem">4</div>
<div class="elem">5</div>
<div class="elem">6</div>
<div class="elem">7</div>
<div class="elem">8</div>
<div class="elem">9</div>
<div class="elem">10</div>
The best way to your problem will be to use nth-last-child() CSS property. add the following code in your CSS file.
.elem:nth-last-child(3){
background: red;
}

how can i have one function be used on multiple items without creating seperate ids?

I have a game where there are balloons and each balloon has an onclick attribute which passes the id into a JS function to change the css.
Example:
<div id="balloon" class="container" onclick="popBalloon(this.id);"></div>
clicking this item will call the function below
function popBalloon(id){
document.getElementById(id).setAttribute("class","pop");
}
Problem is that I have multiples balloons of the same type, and instead of using a unique id for each one, I would like a way to determine the specific balloon being clicked using the same attribute names.
Is this possible?
If you pass event as the function parameter, you can use event.target to get the clicked Element
function popBalloon (event) {
event.target.setAttribute("class", "pop");
}
div {
margin-top: 10px;
height: 30px;
width: 30px;
border: 1px solid;
border-radius: 50%;
}
.container {
background-color: red;
}
.pop {
background-color: blue;
}
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
Most of current answers suggest a function that defines click listener to a group of elements however you asked how to omit unique IDs where there are too many elements in a game. The simple answer is to pass OBJECT instead of ID to the function:
<div class="container" onclick="popBalloon(this);"></div>
and in the function:
function popBalloon(myobj){
myobj.setAttribute("class","pop");
}
Thats all.
Instead of manually entering the function signature in each balloon entry, handle it all in the javascript below. Throw all those balloons into a list. As Scott Hunter suggested, place each balloon in a class. Let's call it "balloon". Then add an event listener to each of those balloons. Here's a quick demo.
var balloonArray = document.querySelectorAll(".balloon");
balloonArray.forEach(function(item) {
item.addEventListener('click', function() {
item.innerText = "Clicked";
});
});
.container {
color: white;
height: 80px;
margin: 10px;
text-align: center;
}
<div class="container balloon" style="background-color: blue">Click me</div>
<div class="container balloon" style="background-color: red">Click me</div>
<div class="container balloon" style="background-color: green">Click me</div>
A good way to do it is add some class to all the balloons. Let's modify your code a bit
<div class="balloon"></div>
<div class="balloon"></div>
<div class="balloon"></div>
I have 3 of those divs with a class of balloon here. For the js we can do
Array.from(document.querySelectorAll(".balloon")).forEach(balloon=>{
balloon.addEventListener('click',()=>{
//On click event here
});
});
Here's how you add a click event to each of the balloon.

Insert HTML or append Child onClick, and remove from previous clicked element

I have a set of div elements inside a container, .div-to-hide is displayed by default whilst .div-to-show is hidden.
When I click in .set, .div-to-hide should hide and .div-to-show should be visible. Next click should return the previous clicked element to its default state.
I need to display to buttons on click inside on .div-to-show.
<div class="container">
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
</div>
So far I have this:
let lastClicked;
$('.container').on('click', function(e) {
if (this == lastClicked) {
lastClicked = '';
$('.div-to-hide').show();
$(this).children('.div-to-hide').hide();
} else {
lastClicked = this;
$('.div-to-hide').hide();
$(this).children('.div-to-hide').show();
$(this).children('.div-to-show').hide();
}
});
Can't get it to work properly tho.. I don't know what I am missing...
Any help is deeply appreciated!
UPDATE: got it working! Thanks everyone!
First, you are not using delegation (second parameter on the $.on() function) to define the .set element as your this inside the function.
If I understood correctly, you want to show the elements on the last one clicked and hide the rest. You don't really need to know which one you last clicked to do that
$('.container').on('click', '.set', function (e) {
// Now "this" is the clicked .set element
var $this = $(this);
// We'll get the children of .set we want to manipulate
var $div_to_hide = $this.find(".div-to-hide");
var $div_to_show = $this.find(".div-to-show");
// If it's already visible, there's no need to do anything
if ($div_to_show.is(":visible")) {
$div_to_hide.show();
$div_to_show.hide();
}
// Now we get the other .sets
var $other_sets = $this.siblings(".set");
// This second way works for more complex hierarchies. Uncomment if you need it
// var $other_sets = $this.closest(".container").find(".set").not(this);
// We reset ALL af them
$other_sets.find(".div-to-show").hide();
$other_sets.find(".div-to-hide").show();
});
Consider using class toggling instead.
$('.set').on('click', function(e) {
$('.set').removeClass('hidden-child');
$(this).addClass('hidden-child');
});
css:
.hidden-child .div-to-hide, .div-to-show {
display: none;
}
.hidden-child .div-to-show, .div-to-hide {
display: block;
}
This will make your code easier to reason about, and lets css control the display (style) rules.
Edit: changed class name for clarity; expanded explanation; corrected answer to conform to question
Try to make use of siblings() jQuery to hide and show other divs and toggle() jQuery to show and hide itself and also you will need to set click() event on .set, not in .container
$(document).on('click', '.set', function(e) {
$(this).find('.hide').toggle();
$(this).find('.show').toggle();
$(this).siblings('.set').find('.hide').show();
$(this).siblings('.set').find('.show').hide();
});
.show {
display: none;
}
.set div {
padding: 10px;
font: 13px Verdana;
font-weight: bold;
background: red;
color: #ffffff;
margin-bottom: 10px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="set">
<div class="hide">1 Hide</div>
<div class="show">1 Show</div>
</div>
<div class="set">
<div class="hide">2 Hide</div>
<div class="show">2 Show</div>
</div>
<div class="set">
<div class="hide">3 Hide</div>
<div class="show">3 Show</div>
</div>
</div>

hover over one div to show the nearest div of a certain class

i want to hover over one div and use jquery to find the nearest div by the name and to show that div.
<div class="entry">
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
</div>
all the .footer classes will be hidden but i want to make it so that when i over over the .body class, only the nearest .footer class shows. [ meaning : if i hover over the first .body class, only the first .footer will be shown. ]
my current code isn't working and i'm starting to wonder if it's something wrong with it.
current jquery code :
$('.footer').hide();
$('.body').hover(function(){
$(this).closest('.footer').find('.footer').show();
});
While the problem is the same as this question, the reason is slightly different.
When you use .closest(".class") it's the equivalent of .parents().filter(".class").first() (or .last(), I don't recall exactly which way parents() works as that's what closest is for).
ie it goes up the tree
So $(".body").closest(".entry") would give you an element for your HTML.
In this case, you want siblings, but more specifically the next one. There's a jquery method .next() which looks like it's correct, but as detailed in the link above, this only gives the very next one (in your HTML this would be the date div) even if a filter is applied - so $(this).next(".footer") would give an empty set (as it's not .date).
The work around is:
$(this).nextAll(".footer").first()
Once you get this working, your will find that your hover does not work as expected as the footers are not hiding again - as you're using .hover rather than mouseenter mouseout, you just need to move the .hide() call inside the second event handler, giving:
// startup
$(".footer").hide();
// event
$(".body").hover(function() {
$(this).nextAll(".footer").first().show();
}, function() {
$(".footer").hide();
});
div > div { width: 100px; height: 10px }
.body { border: 1px solid red; }
.date { border: 1px solid blue; }
.footer { border: 1px solid green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
</div>
$(this).closest('.footer')
You should start to use console.log() sometimes to check elements you would like to get. This does not find anything so nothing further to search and to show.
If you possibly can separate bodies and footers into containers you can do smth like
this.
Try to make use of nextUntil(".footer").next(); as below
$('.body').hover(function() {
$(this).nextUntil(".footer").next().show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
IF your html is gonna keep those triads layout, you don't need jQuery for it.
Just use CSS to select the second div after the .body on hover
div{width:100px; height:100px; background-color:lime; margin:10px; float:left}
.body{background:yellow; clear:left;}
.footer{display:none;}
.body:hover + div + div{
display:block;
background:red;
}
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
The answer by freedomn-m offered a good explanation and good solution in case you want the nearest NEXT .footer, which seems to be the case from your example HTML.
However, if you want your request strictly, so you want exact NEAREST .footer, then his solution will not work for you. And I don't think there is a jQuery built-in functionality that can give you that, so you'll have to do it manually. Get the list of the children of the parent (don't use the siblings as they don't include the current element) and go through the list to calculate the distance from your current element using the indexes and then select the .footer that is really the nearest.
$('.body').hover(function() {
var children = $(this).parent().children();
var index = children.index(this);
var closest = children.length;
var footer = -1;
children.each(function(i, child) {
if (i !== index && $(child).hasClass("footer")) {
var distance = Math.abs(index - i);
if (distance < closest) {
closest = distance;
footer = i;
}
}
});
if (footer > -1)
children.eq(footer).show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
If you don't care much about the performance, you can shorten the code a bit by selecting the list of .footer instead of the children of the parent, and then let jQuery give you the index of each of them. Not very efficient, but shorter code:
$('.body').hover(function() {
var index = $(this).index();
var closest = 9999;
var footer;
$(this).siblings(".footer").each(function(i, sibling) {
var distance = Math.abs(index - $(sibling).index());
if (distance < closest) {
closest = distance;
footer = sibling;
}
});
if (footer !== undefined)
$(footer).show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
Inspired by freedomn-m's comment, we can also use the .prevAll() and .nextAll() methods to get the previous and next .footer siblings. These two methords return the siblings ordered by the closest, so we simply pick the first one of each list, subtract their indexes from our element's index (to find the distance), compare them together, and return the closest. This solution is also less efficient than the first one, but you may find the code easier to read:
$('.body').hover(function() {
var me = $(this);
var prev = me.prevAll(".footer").first();
var next = me.nextAll(".footer").first();
if (prev.length == 0)
next.show();
else if (next.length == 0)
prev.show();
else {
index = me.index();
if (Math.abs(prev.index() - index) < Math.abs(next.index() - index))
prev.show();
else
next.show();
}
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>

Changing Parent Class With Child's Button Using Javascript

What i'm basically asking is if i could do this?
function Close(){
// what the furry mermaids should i put in here!?
}
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1{
background-color: red;
}
#parentDiv2{
background-color:blue;
}
<div id="parentDiv1" class="visible">
<button id="closebtn" onclick="Close()">close</button>
<p> This is div 1 </p>
</div>
<div id="parentDiv2" class="visible">
<button id="closebtn" onclick="Close()">close</button>
<p> This is div 2 </p>
</div>
There are two divs that contain the same button but each button changes their parent div's class to hidden. Their parent's div only.
This is because i want to make a lot of pages but they close one by one with the same code and the same button. I'm wanting a minimalist solution here.
Oh and please don't be vague with your answers. If you are going to present it please explain how it works and how to apply it. A working code example is desired.
Note: Only one function may be used and is used by two identical buttons that are separated by two Divs.
Please and Thank You! :D
You can pass the current element context this to method. Then parent div can be accessed using parentNode property. To manipulate element's class use Element.classList property.
function Close(elem) {
elem.parentNode.classList.add('hidden')
elem.parentNode.classList.remove('visible')
}
function Close(elem) {
elem.parentNode.classList.add('hidden')
elem.parentNode.classList.remove('visible')
}
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1 {
background-color: red;
}
#parentDiv2 {
background-color: blue;
}
<div id="parentDiv1" class="visible">
<button id="closebtn" onclick="Close(this)">close</button>
<p>This is div 1</p>
</div>
<div id="parentDiv2" class="visible">
<button id="closebtn" onclick="Close(this)">close</button>
<p>This is div 2</p>
</div>
I would recommend you to use unobtrusive event handler. Instead of using ugly inline click handler.
document.addEventListener("DOMContentLoaded", function(event) {
var elements = document.querySelectorAll('.closebtn');
elements.forEach(function(element) {
element.addEventListener('click', function() {
this.parentNode.classList.add('hidden');
this.parentNode.classList.remove('visible');
})
});
});
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1 {
background-color: red;
}
#parentDiv2 {
background-color: blue;
}
<div id="parentDiv1" class="visible">
<button type="button" class="closebtn">close</button>
<p>This is div 1</p>
</div>
<div id="parentDiv2" class="visible">
<button type="button" class="closebtn">close</button>
<p>This is div 2</p>
</div>
Pass event in close function and access to parent with event.target.parentNode;
function Close(event){
const parent= event.target.parentNode
parent.classList.remove('vissible');
parent.classList.add('hidden');
// what the furry mermaids should i put in here!?
}
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1{
background-color: red;
}
#parentDiv2{
background-color:blue;
}
<div id="parentDiv1" class="visible">
<button id="closebtn" onclick="Close(event)">close</button>
<p> This is div 1 </p>
</div>
<div id="parentDiv2" class="visible">
<button id="closebtn" onclick="Close(event)">close</button>
<p> This is div 2 </p>
</div>
Here you go :)
https://jsfiddle.net/
$('#parentDiv1 #closebtn').on('click', function(){
$(this).parent().addClass('hidden')
})
$('#parentDiv2 #closebtn').on('click', function(){
$(this).parent().addClass('hidden')
})
This is how i would do it. Use something like this.
$(".closebtn").click(function(){
$(this).parent().removeClass("visible");
$(this).parent().addClass("hidden");
});
Also in your css your class is spelled vissible and in your html the class it spelled visible

Categories

Resources