Reputation: 21
i am trying to understand how to make this code into a loop so I wouldn't have to copy the part where $('.popup-[insert nr]').click
every time in the future a new menu link is made for navigation.
This code is in the purpose of: Click a link, toggle or add a class of show to a hidden div
and if any other link is clicked after that every shown div will be hidden.
var popContent = $('.popup-1-content');
var popContent2 = $('.popup-2-content');
var popContent3 = $('.popup-3-content');
var popContent4 = $('.popup-4-content');
var popupArray = [popContent, popContent2, popContent3, popContent4];
$('.popup-1').click(function () {
if ( popContent.hasClass("show") ) {
popContent.removeClass("show");
} else {
for (var i = 0; i < popupArray.length; i++) {
popupArray[i].removeClass("show");
}
popContent.addClass("show");
}
return false;
});
$('.popup-2').click(function () {
if (popContent2.hasClass("show") ) {
popContent2.removeClass("show");
} else {
for (var i = 0; i < popupArray.length; i++) {
popupArray[i].removeClass("show");
}
popContent2.addClass("show");
}
return false;
});
$('.close-popup a').click(function(){
$('.popup-content').toggleClass('hide').removeClass('show');
return false;
});
Upvotes: 2
Views: 658
Reputation: 44078
"...i tried your code but it needs to be edited so it wouldn't target divs below the link as the divs are located in random parts of the page. "
The updated demo addresses previously mentioned issue by adding a data-*
attribute to each link. Once a link is clicked, it locates the nth div.pop
by matching its data-idx
with a .pop
's indexed position by using .eq()
method. The following example does not function as is, it is merely the relevant parts with emphasis on the index number to show the correlation between the 2 values.
<a href='#/' class='lnk' data-idx=
'3'>POP3</a>
$('.pop').eq(
3).addClass('show')
The following is the core code without the extra utilities or comments, condensed and chained.
$('.lnk').on('click', function() {
var idx = $(this).data('idx');
$('.pop').removeClass('show').eq(idx).addClass('show');
});
<a href='#/' class='.lnk' data-idx='0'>POP0</a>
For the complete updated code, refer to the Demo below.
On any automated or manually controlled groups of elements (ex. slider) that alternate in states (ex. hide and show), the easiest way to control the flow is to hide all elements and then show the currently active element.
Details commented in Demo
/* This is just to space the links apart. Upadted to provide
|| random location for .lnk's
*/
$('a.lnk').each(function(idx, a) {
var ran = getRandom(1, 60);
a.style.top = (idx * ran) + 'px';
a.style.left = (idx * ran) + 'px';
});
// Click any a.lnk...
$('a.lnk').on('click', function() {
// Reference the div.pop the clicked link belongs to
/* The next statement works if each popup was positioned after
|| a corresponding link. It is commented out in leiu of the
|| uncommented statement that follows this statement.
*/ // var pop = $(this).next('div.pop');
// Get the clicked link's data-idx number
var idx = $(this).data('idx');
// Gather all .pop
var pop = $('.pop');
// ALL .pop remove class .slow
pop.removeClass('show');
/* .pop will open. The specific .pop that corresponds with the
|| clicked link is determined by matching the .pop's current
|| indexed position with that of the indexed position of in
|| $('.pop') by using the eq() method and passing data-idx
*/
pop.eq(idx).addClass('show');
});
/* This function is not neccessary. Its purpose is to generate a
|| random number between min and max parameters (inclusive)
*/
function getRandom(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
a.lnk {
display: inline-block;
position: relative;
z-index: 1;
background:#000;
color:gold;
}
.pop {
display: none;
}
.pop.show {
display: block;
margin-top: 30px
}
<a href='#/' class='lnk' data-idx='0'>POP0</a>
<a href='#/' class='lnk' data-idx='1'>POP1</a>
<a href='#/' class='lnk' data-idx='2'>POP2</a>
<a href='#/' class='lnk' data-idx='3'>POP3</a>
<a href='#/' class='lnk' data-idx='4'>POP4</a>
<div class='pop'>
<img src='https://i.imgur.com/ydfYXqh.jpg'>
<header>POP0</header>
</div>
<div class='pop'>
<img src='https://i.imgur.com/DrEwPH0.jpg'>
<header>POP1</header>
</div>
<div class='pop'>
<img src="https://i.imgur.com/AXUJEUS.jpg">
<header>POP2</header>
</div>
<div class='pop'>
<img src='https://i.imgur.com/MEPxbq4.jpg'>
<header>POP3</header>
</div>
<div class='pop'>
<img src='https://i.imgur.com/dp8G9Fr.jpg'>
<header>POP4</header>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 1
Reputation: 8670
Grab all the popups using a better CSS selector. Then iterate over the list using jquery's each
attaching a click handler to each one.
You're toggling a class manually but JQuery has toggleClass
built in. Use that instead. In your case you stated that you wanted to remove the class from all other elements once one popup had its class changed, to do that we can use jquery's .not
method which specifies to get all items except the item specified, then we just use removeClass
to remove the class from those elements.
var popups = $('[class$="-content"]').filter('[class^="popup-"]');
popups.each(function(index, popup) {
$(".popup-" + (index + 1)).click(function(e) {
$(popup).toggleClass("show");
popups.not(popup).removeClass("show");
});
});
var popups = $('[class$="-content"]').filter('[class^="popup-"]');
popups.each(function(index, popup) {
$(".popup-" + (index + 1)).click(function(e) {
$(popup).toggleClass("show");
popups.not(popup).removeClass("show");
});
});
.show {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="popup-1">toggle 1</button>
<button class="popup-2">toggle 2</button>
<button class="popup-3">toggle 3</button>
<button class="popup-4">toggle 4</button>
<div class="popup-1-content">1</div>
<div class="popup-2-content">2</div>
<div class="popup-3-content">3</div>
<div class="popup-4-content">4</div>
Upvotes: 0
Reputation: 78
Without looking at your HTML structure is hard, but the idea is to create a loop for each link and replace the numbers with an index variable like this:
$.each('a', function(i, link) {
$('.popup-' + i).click(function () {
$('div').removeClass("show");
$(this).parent.addClass("show");
return false;
});
});
Upvotes: 1
Reputation: 31
Add a common class.
<!-- Added a common class popup-content -->
<div class=".popup-1-content popup-content">...<div>
select the common class when adding the event handlers, refer to $(this)
, assuming you are using jQuery, to get the instance where the event occurs (specific element clicked) this can also be captured with event.target in vanilla js when passing it into your callback function handling the event.
ex jQuery:
$('.popup-content').on('click', function(){
// Check if already open, early exit
if ($(this).hasClass('show')) return;
// Close them all
$('.popup-content').removeClass('show')
// Open the one being clicked
$(this).addClass('show');
})
Another option is to use a wildcard selector
$('[class^="popup"]').on('click', function(){
// Check if already open, early exit
if ($(this).hasClass('show')) return;
// Close them all
$('[class^="popup"]').removeClass('show');
// Open the one being clicked
$(this).addClass('show');
})
p {
display: none;
border: solid 1px black;
}
.show p {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="popup-content-1">
1
<p>hidden content 1</p>
</div>
<div class="popup-content">
2
<p>hidden content 2</p>
</div>
Upvotes: 0
Reputation: 871
Using selector attribute (starts with) you can select all popups, and based on popup class name, hide or show its content. This way you can add as many popups as you wish.
<button class="popup-1">1</button>
<span class="content-popup-1">First</span>
$("[class^=popup]").click(function() {
$(".content-" + this.className).toggleClass('hide');
});
Working example here: https://jsfiddle.net/e9qep53w/
More about query selectors here https://api.jquery.com/category/selectors/
Upvotes: 0