State dependent class names on accordion - javascript

So I have this problem that I guess is a walk in the park to fix.
I'm using the JS snippet below on a website I'm building and what the snippet does is it creates accordions for some HTML elements where the class .bapf_head is the header (control) of the accordion and the .bapf_body is the expand/collapse.
I wrote the if logic where the function checks if the .bapf_body is opened or not and will then add or remove a class to the .bapf_head depending on the state. This then results in a +/- symbol that indicates open/close depending on the state.
So the problem is that I have multiple Div's that uses the same class names and all of them gets updated with the .open class name when one of the accordions are opened or closed. So let's say I have three accordions and I open one of them, then all three gets the class .open added and hence all gets the '-' symbol even though only one accordion is open.
Anyone knows how to make sure only the clicked accordion gets the updated class-name rather then all of the accordions at the same time?
Code below;
jQuery(document).ready(function($) {
$(".bapf_head").click(function () {
$header = $(this);
$content = $header.next();
$content.slideToggle(300, function () {
$header.text(function () {
if ($content.is(":visible")) {
$(".bapf_head").addClass("open");
} else {
$(".bapf_head").removeClass("open");
};
});
});
});
});

if ($content.is(":visible")) {
$(this).addClass("open");
} else {
$(this).removeClass("open");
};
you need to reference the event-related DOM element, not select all the ones with that class
also, .click() is long deprecated afaik, you should use .on('click', ...

Related

Toggle class doesn't work with push menu

Can you help me and tell me why this code doesn't work? On click '.push-button' it should open the '#push-menu' and that works but the other part of the doesn't work instead of showing the elements on the first click and then hiding the elements on the second click, it doesn't even show them when I open the menu it is empty, just white!
$(document).ready(function () {
$(".push-button").click(function () {
$("#push-menu").toggle(
function (){
$('.link-item-1').addClass('active-1');
$('.link-item-2').addClass('active-2');
$('.link-item-3').addClass('active-3');
$('.link-item-4').addClass('active-4');
$('.link-item-5').addClass('active-5');
}, function (){
$('.link-item-1').removeClass('active-1');
$('.link-item-2').removeClass('active-2');
$('.link-item-3').removeClass('active-3');
$('.link-item-4').removeClass('active-4');
$('.link-item-5').removeClass('active-5');
}
);
});
});
The problem is because the toggle() method no longer works in the manner you expect. It was changed several versions ago.
However, you can fix both the issue and massively simplify your code by using toggleClass() instead:
$(".push-button").click(function () {
$('.link-item-1').toggleClass('active-1');
$('.link-item-2').toggleClass('active-2');
$('.link-item-3').toggleClass('active-3');
$('.link-item-4').toggleClass('active-4');
$('.link-item-5').toggleClass('active-5');
});
I would also suggest you revisit the logic you're using with regard to the classes. They are supposed to group common elements, yet you have given each element its own unique class which is the complete opposite pattern.
To make that work you could then use the same class on all elements, eg. link-item, then identify them by index in either JS or CSS, whenever required.
$(".push-button").click(function () {
$('.link-item').toggleClass('active');
});

onclick function requires double click because of class assignment delay

The title says it all. I got a list of LI elements. When clicked on navigation the active li gets a class 'current' but this takes a second.
But when I use my code I need to click on the nav then the li opens and I need to click again to make the code register.
The place of the videos cannot be hardcoded! It needs to be dynamic.
(function($) {
$(document).ready(function(){
$('video').each(function() {
$(this).get(0).pause();
});
$('.slides').children('li').addClass('test');
});
$(document).on('click','span',function(){
if ( $('li').hasClass('current') ) {
$('li.test').find('video').each(function() {
$(this).get(0).pause();
});
$('li.current.test').find('video').each(function() {
$(this).get(0).play();
});
}
});
})(jQuery);
http://codepen.io/hennysmafter/pen/aNrVKG?editors=1010
Unfortunately I won't be available for the next hour or so but will be back after that! Everyone thank you for helping.
I found what is causing the issue :
You are playing the elements whose parent has ".current" class when a span is clicked.
But when you click an element, it et the ".show" class, and the previously selected span get the ".hide" class AND keeps the ".current" class, until the animation is finished (then the ".show" & ".hide" class are removed and the ".current" class switch elements).
One solution is changing the selectors like this :
$(document).on('click','span',function(){
console.log('the if is running');
$('.current, .hide').find('video').each(function() {
$(this).get(0).pause();
});
$('.show').find('video').each(function() {
$(this).get(0).play();
});
});
By doing this, whenever a span is clicked, you pause the element whose parents have the ".hide" class, and play the ones whose parents have the ".show" class.
Another solution should be creating an event when a class is applied (See jQuery - Fire event if CSS class changed).

Animate icon don't take his original position on toggle click

I have a accordion menu which have for each parent menu a icon, and this icon is animated with css transition and transform. I added a class with a if condition to the click event. The problem is that when I click for example on Menu1, the icon animation does very well, but if I click directly on Menu2, the menu2 dropdown appear but icon from the menu1 don't take his original position.
This problem applies to each icon in each menu/submenu, I thinks that I have a mistake in my code.
$(document).ready(function() {
// Icons effect
$('#mw_nav .toggle').click(function() {
if($(this).hasClass('rotate_close'))
{
$(this).addClass('rotate_open').removeClass('rotate_close');
}
else {
$(this).addClass('rotate_close').removeClass('rotate_open');
}
});
// Toggle Menu Items
$(function () {
$("#m_nav > ul ul").hide();
$('#m_nav .toggle').click(function (e) {
e.preventDefault();
e.stopPropagation();
var $parentli = $(this).closest('li');
$parentli.siblings('li').find('ul:visible').slideToggle(400);
$parentli.find('> ul').stop().slideToggle(400);
$(this).remove;
});
});
});
FIDDLE
Any help would be appreciated
There are 2 issues I see with your code. The first is a recommendation to NOT have $(function() { // your code }) inside of $(document).ready(). $(function() {}) is actually just shorthand for $(document).ready() so you are adding code you do not need.
The second is an issue with your logic.
$('#mw_nav .toggle') and $('#m_nav .toggle') click listeners are essentially adding a click listener on the same exact element, but both run different logic. When the $('#mw_nav .toggle') click listener is getting called it checks for a class to exist to decide what class it needs to remove and add. When $('#m_nav .toggle') click listener is getting called it calls a slideToggle function on the current nested <ul> regardless if another menu is opened or closed and there is no check in place of whether or not the rotate_open/rotate_close classes exist allowing for the classes to get swapped. There is no relation between the swapping of rotate_open/rotate_close classes and the logic that slideToggles <ul> up/down.
UPDATE
I have edited your code and made updates that will now work seen here: https://jsfiddle.net/vhfn0q5a/9/
I have added a class of .top_level to the top level items in your HTML. I use this as a way of differentiating the top level <li> from the sub menus. Next, at the end of the click event listener I check to see if the .toggle element clicked is a top level element, if so I target all top level elements that are not the current selected and make sure they have the .rotate_close class.
$(function() {}) shorthand reference
Use this code in your first click handler:
$('#mw_nav .toggle').click(function() {
$(this).toggleClass('rotate_close rotate_open');
if ($('#mw_nav .toggle').not(this).hasClass('rotate_open')) {
$('#mw_nav .toggle').not(this).removeClass('rotate_open').addClass('rotate_close');
}
});
I've updated your FIDDLE with an working example.
Cheers!

Understanding JQuery. Collapsible menu

I have created a collapsible menu in JQuery with the help of some coding I've found around this site.
And everything work. But now it's time for me to understand how and why it works.
The JQuery:
jQuery(document).ready(function($) {
var submenu = $('.submenu').hide();
$('.open').click(function() {
$this = $(this);
$target = $this.parent().next();
if(!$this.hasClass('close')){
$('.open').removeClass('close');
submenu.slideUp();
$this.addClass('close');
$target.slideDown();
}else{
$target.slideUp();
$this.removeClass('close');
}
});
});
The HTML and CSS are in here: JSFIDDLE!
Can someone break the code down for me, and explain what it does.
I know that it hides my .submenu class when the page loads.
And when I click the class .open the .submenu. slides down
But then I am a bit lost to what it does with my .close class.
Thanks in advance!
No problems :)
Let's start with this:
jQuery(document).ready(function($){});
this wraps around all jQuery code. it defines an anonymous function and attaches it to the event $(document).ready meaning - this code runs only after the entire DOM is loaded. This is needed because if the following code will run before the elements were loaded it will have no effect on them,
var submenu = $('.submenu').hide();
This line picks all elements with class="submenu", hides them - and returns an array of all submenus to the submenu variable. The rest of the explanation will be commented on each line:
$('.open').click(function() { // the following code will run if you click an element with class="open"
$this = $(this); // $this will hold the element you clicked
$target = $this.parent().next(); // $target will hold the next element (relevant single submenu)
if(!$this.hasClass('close')){ // if the current element is open (marked by class="closed")
$('.open').removeClass('close'); // remove the "close" class from all main menu items
submenu.slideUp(); // close all submenus
$this.addClass('close'); // add "close" class only to the clicked main menu item
$target.slideDown(); // open the correct submenu (the element after the clicked main menu item)
}else{ // if current submenu is already open
$target.slideUp(); // close it
$this.removeClass('close'); // remove class "close" from the main menu item.
}
});
When user clicks on a menu group, you need to consider two cases:
The clicked menu group is closed (i.e. it doesn't have the close class)
!$this.hasClass('close')
If so, you first have to close all open menus, and set their class accordingly:
$('.open').removeClass('close');
submenu.slideUp();
Then you can expand the clicked menu group, and mark it as currently open:
$this.addClass('close');
$target.slideDown();
The clicked menu group is already open. The only thing that needs to be done in that case is closing the menu:
$target.slideUp();
$this.removeClass('close');

Toggle class on div = Untoggle class on another div

I have some divs (#div1, #div2, #div3) that change appearence on click, they toggle a class using this script:
$(document).ready(function() {
$("#parent_div").on('click', '.current_class', function () {
$(this).toggleClass("new_class");
});
});
Now I want the the divs to be unable to toggle at the same time, so they work kinda like a radio-button with same "name".
Example: Imagine three divs that looks the same (default class), then you click on one of the divs (example #div1) and that one toggles a new class and change appearence. Now you click on one of the other two and this one also change appearence (toggle class), at the same time when this one change appearence #div1 changes back to the default class.
So there can only be one div of those three that toggles the new class at once.
Is this possible?
You first need to remove the class from all the divs, and then add it to the current one. Try this:
$("#parent_div").on('click', '.current_class', function () {
$('#parent_div .new_class').removeClass('new_class'); // remove exisiting
$(this).addClass("new_class"); // add to current
});
Update
Added functionality to remove class from current:
$("#parent_div").on('click', '.current_class', function () {
var $this = $(this);
if (!$this.hasClass('new_class')) {
$('#parent_div .new_class').removeClass('new_class');
$this.addClass("new_class");
}
else {
$this.removeClass("new_class");
}
});
Use:
$(document).ready(function() {
$("#parent_div").on('click', '.current_class', function (){
if($(this).hasClass('.new_class')){
$(this).removeClass('.new_class');
}else {
$('.new_class').removeClass('.new_class');
$(this).addClass('.new_class');
}
});
});
Updated: Code now allows for toggling of current element with class .new_class.
This would be possible, but you'll need to reset all the other divs manually.
An example would be :
I have 3 divs available with id's div-1, div-2 and div-3.
I'm using a default class 'default' and a definition class so i can click them 'clickable', and my other class would be 'selected'.
To implement this you would need to do the following:
$(document).ready(function() {
$('#parent-div').on('click, 'clickable', function() {
$('.selected').removeClass("selected").addClass("default");
$(this).addClass("selected");
})
});
I hope this helps.
I didn't have the possibility to check if the syntax is exactly correct, but I believe this does the job as required.
Kind regards,
NDakotaBE

Categories