Toggle/Show one defined DIV with JS - javascript

I have a fiddle for you: http://jsfiddle.net/vSs4f/
I want to show the div.sub-menu with a simple click on a.haschildren. If the body loads the div.sub-menu should be closed. If I click a second time on a.haschildren the div.sub-menu should be close.
I have sampled so many things but I think the problems are the lot of DIV's. One idea is in the fiddle.
$(function() {
$("a.haschildren").click(function(e) {
e.preventDefault();
$('div.sub-menu:visible').hide();
$(this).next('div.sub-menu').show();
});
});
I really hope you can help me, thanks!

Try this:-
Fiddle
$(function () {
$("a.haschildren").click(function (e) {
e.preventDefault();
var subMenu = $(this).closest('div.haschildren').nextUntil('.sub-menu').next().toggle();
$('div.sub-menu:visible').not(subMenu).hide();
});
});
Using .nextUntil to reach a point till the .sub-menu, incase any other siblings come in between this will still work.

Personally there are MANY things I would have changed about the structure of your DOM. I am a strong believer that you should base your javascript structure around a well structured DOM, so the traversal is very easy and intuitive. That being said, I'm going to be slightly daring by submitting my fiddle, in the hope that if nothing else, you can look at it and gain a little insight on how to take advantage of a few DOM quirks to make your javascript a bit more intuitive and elegant.
http://jsfiddle.net/vSs4f/6/
$(function() {
$('#menu > div.item')
.find('a').click(function() {
var submenu_index = $(this).parents('.item:first').find('.sub-menu').toggle().index('.sub-menu');
// This chunk can disappear if you're not interested in hiding all of the other sub-menus
$('.sub-menu').filter(function(index) {
if(index != submenu_index)
return true;
}).hide();
}).end()
.find('div:first').after('<div class="trenner"></div>');
});

Try
$(function() {
$("a.haschildren").click(function(e) {
e.preventDefault();
var item = $(this).closest('div.haschildren').next().next('div.sub-menu').toggle();
$('div.sub-menu:visible').not(item).hide();
});
});
Demo: Fiddle

just use toggle()
$('div.sub-menu').toggle();

Ironically enough, the method you're looking for is .toggle();
http://api.jquery.com/toggle/

try it:
$(function() {
$("div.haschildren").click(function() {
if($(this).next().next('div.sub-menu').is(":hidden")){
$('div.sub-menu:visible').hide();
$(this).next().next('div.sub-menu').show();
}else{
$(this).next().next('div.sub-menu').hide();
}
return false;
});
});

Related

Struggling to add active class/state to faq accordion

I'm quite the amateur when it comes to Javascript, hence why I'm posting this on here. I've spent quite a lot of time searching for the answer but can't seem to find it.
I've created a FAQ Accordion on jsfiddle and can't for the life on me get it to add an active class/state when the tabs are extended so I can apply styling appropriately.
If anyone can be of any assistance it would be greatly appreciated :)
$(function () {
$('.acc_trigger a').click(function () {
$('.acc_trigger').next('.acc_container').slideUp();
$(this).closest('.acc_trigger').next('.acc_container').stop().slideDown();
return false;
})
$('.expand').click(function () {
$('.acc_trigger').closest('.acc_trigger').next('.acc_container').slideDown('slow');
return false;
})
$('.collapse').click(function () {
$('.acc_trigger').next('.acc_container').slideUp('slow');
return false;
})
});
jsfiddle
What yakutsa said, but to answer your question you can continue to use Jquery and use the .addClass('addedClass') to the end of whichever you wish to change.
For example if you want the opened container to have a red background
$('.acc_trigger').next('.acc_container').slideUp().addClass('addedClass');
width css
.addedClass {
background: red;
}
when you close it, use .removeClass('addedClass');
here's a fiddle

Avoid giant cascading in jQuery?

I feel like this is something that is solved by "deferreds" or "promises" that I've heard about in jQuery, but looking searching for related articles on that doesn't exactly show me what I'm looking for.
I want to be able to do a simple jquery function call (like animate() or slideUp()) then call another simple function when it is completed. Of course I know about slideUp(400, function(){ //onComplete... }); but if you have a large cascade of animations, that can get pretty hairy pretty quickly.
Check out the following jsfiddle:
http://jsfiddle.net/ue3daeab/
When you click the first button, you see the visual effect I want to acheive. However, I'm accomplishing it with "cascade hell," and the relevant code being:
$("#clickme").click(function(){
//Cascade hell
$("#my1").slideUp(400, function(){
$("#my2").slideUp(400, function(){
$("#my3").slideUp(400, function(){
$("#my4").slideUp(400, function(){
$("#my5").slideUp(400, function(){
$("#my6").slideUp(400, function(){
$("#my7").slideUp(400, function(){
$("#my8").slideUp(400, function(){
$("#my9").slideUp(400, function(){
$("#my10").slideUp(400);
});
});
});
});
});
});
});
});
});
});
When you click button 2, all the divs collapse at once, which isn't the effect I want. I feel like I should be able to do something like this, but obviously it doesn't work. The relevant code for the 2nd button is:
$.when($("#my1").slideUp())
.done($("#my2").slideUp())
.done($("#my3").slideUp())
.done($("#my4").slideUp())
.done($("#my5").slideUp())
.done($("#my6").slideUp())
.done($("#my7").slideUp())
.done($("#my8").slideUp())
.done($("#my9").slideUp())
.done($("#my10").slideUp());
Any advice? Thanks.
Why not use a simple array of ids to collapse, and then collapse them one item at a time?
$("#clickme").click(function(){
var toCollapse = ["#my1", "#my2", ...];
(function collapse(){
var id = toCollapse.shift();
if (!id) return;
$(id).slideUp(400, collapse);
})();
});
I edited your jsfiddle with this example too: http://jsfiddle.net/ue3daeab/2/
I would do something like this:
UNTESTED
$.each($('.item', '#container'), function(index, value) {
$(this).delay(50*index).slideUp(400);
});
This way everything doesn't try to happen all at once.

toggling booleans in javascript

I am pretty new in javascript and there seems to be something I just don't get about booleans. I am trying to toggle a boolean whenever someone clicks on an element on my webpage. The code looks like this:
$(document).ready(function() {
var toggled;
$("#button").click(function(){
toggled=!toggled;
});
if(toggled){
$(".offcanvas").css("margin-left","0%");
}
else{
$(".offcanvas").css("margin-left","-40%");
}
});
If someone could explain me what I'm doing wrong I would greatly appreciate your help.
Thank you in advance
Try this ...
$(document).ready(function() {
var toggled = false;
$("#button").click(function(){
toggled=!toggled;
if(toggled){
$(".offcanvas").css("margin-left","0%");
}
else{
$(".offcanvas").css("margin-left","-40%");
}
});
});
Moving the if structure inside the click event will ensure it is checked after the toggle is changed. Setting a default value just feels right to me, although with truthy/falsy you might be good there.

Filtering Content using jQuery

I'm attempting to create a filterable photo gallery using jQuery and multiple classes. I have some code set up, but it doesn't seem to work. Can anybody give me any insight on how to fix this function?
$(document).ready(function(){
$('#sorter a').click(function(e){
var sortName = $(this).text().toLowerCase().replace(' ','-');
if(sortName === 'all-images'){
$('#photorow1 li').show().removeClass('hidden');
}
else {
$('#photorow1 li').filter(sortName).show().removeClass('hidden')
.end().not(sortName).hide().addClass('hidden');
}
e.preventDefault();
});
});
Any help would be greatly appreciated!!
*updated code
The problem is you're doing a return false before any work is being done, move that to the end of your click handler :)
Overall you can clean it up a bit, something like this should do:
$(function(){
$('#sorter a').click(function(e){
var sortName = $(this).text().toLowerCase().replace(' ','-');
if(sortName === 'all-images') {
$('#photorow1 li').show();
} else {
$('#photorow1 li').filter(filterVal).show().removeClass('hidden')
.end().not(filterVal).hide().addClass('hidden');
}
e.preventDefault();
});
});
I recommend that you just add display: none; to the .hidden CSS rules (if you need that class for something else), otherwise just .hide()/.show() works.
For starters, return false; should be at the end of the function, because any code that comes after it in that function will be ignored.
Plus, you don't need that and e.preventDefault(); in the same function, they overlap a bit. You can read more about their similarities here. Pick one.

Jquery mouse-over fade-in/out (best practices)

I've got working Jquery code to fade in/out descriptive text in a div below the question. The problem? The solution is not very elegant. Here's what I've got:
$("#home").mouseover(function() {
$("#homeText").fadeIn("slow");
});
$("#homeText").mouseout(function() {
$("#homeText").fadeOut();
});
I know there is better way to do this, I'm just not sure what it is.
you could use hover, the first function will act on a "hover over" and the second will act on a "hover out"
The documentation is located here: http://docs.jquery.com/Events/hover
$("#home").hover(function(){
$("#homeText").fadeIn("slow");
},
function(){
$("#homeText").fadeOut();
});
How about 3 lines?
<script>
$(function () {
$('#home').hover(function() {
$('#homeText').fadeToggle("slow");
});
});
</script>
Elegant enough?
Jon, Great advice! I used as a staring point though for a more complete solution. Doing this with just the basic hover would still leave me with a hover call for single menu item..A lot of redundant code. So using what you suggested, I came up with this:
$('.topMenu').hover(function()
{
$('#_'+this.id).fadeIn("slow");
},
function ()
{
$('#_'+this.id).fadeOut();
});
});
All menu items are given the topMenu class and ID. The corresponding div to display is the same id as the menu item, just prefixed with _
Example:
....
Stuff about us!
...
Thanks!
$(function () {
$('#home').hover(function() {
$('#homeText').fadeIn("slow");
});
$('#home').mouseout(function() {
$('#homeText').fadeOut("slow");
});
});

Categories