Close accordion alike div using jQuery? - javascript

I have this simple code which shows 3 items
When I press the header ($(".fileHeader")) , it should open then next element which is the next element (hidden div) ($(".LST_Documents"))
sketch :
JSBIN : it does work.
Most important :
When I press on a $(".fileHeader")- i need to close all other $(".LST_Documents") and then ( that why i used promise) open the relevant $(".LST_Documents").
The problem is (look at the pic) if i press again on the first $(".fileHeader").
what is happening is that it closing and then re opening. and I want it to stay CLOSED.
P.S.
I could solve it with class ( .rowOpen or something like that) but I want to do it via JS/JQ only.
How can I enhance my code to work as expected ?

Just hold the header's content visibility state before sliding it up. And slide down the content only when it was not visible.
Here is the fiddle.
$(".fileHeader").on('click', function () {
var content$ = $(this).next(),
isContentVisible = content$.is(':visible');
$(".LST_Documents:visible").slideUp().promise().done(function () {
if ( ! isContentVisible ) {
content$.slideDown();
}
});
});

How 'bout a simple condition:
$(".fileheader").on('click', function() {
var next = $(this).next();
if(next.is(':visible'))
{
next.slideUp();
}
else
{
$(".LST_Documents:visible").slideUp().promise().done(function() {
next.slideDown();
});
}
});

Related

Hide mobile menu on click anywhere on a website [duplicate]

This question already has answers here:
Mobile Menu - Click outside menu to close menu
(2 answers)
Closed 6 months ago.
I have one problem, I want to hide the menu on click anywhere on the website, but nothing works for me :(
Here is my code for closing button:
$('.menu-toggle').on('click',function(e){
e.preventDefault();
if ( $('.lang-mobile').hasClass('is-open') ){
$('.lang-mobile a').trigger('click')
}
if ( !$('header').hasClass('is-open')){
$('header').addClass('is-open');
$('#navbar-main').fadeIn();
}
else {
$('header').removeClass('is-open');
$('#navbar-main').fadeOut();
}
Here is some of my HTML structure
<header class="header clear is-open" role="banner">
<div class="navbar" id="navbar-main" style="display: block;">
<div class="navbar-container" style="height: 797px;">
<div class="navbar-item">
I've tried something like this
$(document).click(function() {
var container = $("#navbar-main");
if (!container.is(event.target) && !container.has(event.target).length) {
container.hide();
}
});
and it's not working, could you please help me? What is incorrect here?
This snippet handles two cases.
Every time there's a click on the page it'll check if the header is open and close it
Every time there's a click on the .menu-toggle item it'll open or close the header
<script>
$(document).on('click', function() {
var header = $(".header");
if ( header.hasClass('is-open') ) {
header.fadeOut();
header.removeClass('is-open');
}
});
$('.menu-toggle').on('click', function() {
var header = $(".header");
if ( !header.hasClass('is-open') ) {
header.fadeIn();
header.addClass('is-open');
} else if ( header.hasClass('is-open') ) {
header.fadeOut();
header.removeClass('is-open');
}
});
</script>
Thank you yousoumar
for sharing this link as an answer - Mobile Menu - Click outside menu to close menu this the only thing that worked for me! I only added some needed parts to this code, so here you go if anyone noob like me and needs more details :D
$(document).mouseup(function(e){
var header = $ (".header, .lang-mobile"); //I have two toggle menus with class that collapse navbars, I also have animation on toggle button that's why I need them also to work
var menu = $(".navbar, .dropdown");//this is to hide menus
if (!menu.is(e.target) // The target of the click isn't the container.
&& menu.has(e.target).length === 0) // Nor a child element of the container
{
header.removeClass('is-open');
menu.hide();
}
});

jQuery Accordion | Open first element on pageload & active state confusion

I am using the Javascript below to animate an accordion (it's a slightly modified variant of the one explained here: http://tympanus.net/codrops/2010/04/26/elegant-accordion-with-jquery-and-css3/.
Now I wanted to have the first element to be open on pageload, so I figured I just give it some sort of extra-class via Javascript (and define that .active state via CSS) to have it open up.
This worked, however if I hover over any but the first-element with said .active class, the first element keeps its state, and stays open until I hover over it at least once.
So, what I want is: the first element of my accordion is open and collapses if the user hovers over any of the elements that are not the first. I think I need to add a line in the hover function to either take the class away of the first element or to give the new element the active state, but I don't know how to do it and keep breaking the thing.
<script type="text/javascript">
jQuery(function() {
activeItem = jQuery("#accordion li:first");
jQuery(activeItem).addClass('active');
jQuery('#accordion > li, #accordion > li.heading').hover(
function () {
var jQuerythis = jQuery(this);
jQuerythis.stop().animate({'height':'280px'},500);
jQuery('.heading',jQuerythis).stop(true,true).fadeOut();
jQuery('.bgDescription',jQuerythis).stop(true,true).slideDown(500);
jQuery('.description',jQuerythis).stop(true,true).fadeIn();
},
function () {
var jQuerythis = jQuery(this);
jQuerythis.stop().animate({'height':'40px'},1000);
jQuery('.heading',jQuerythis).stop(true,true).fadeIn();
jQuery('.description',jQuerythis).stop(true,true).fadeOut(500);
jQuery('.bgDescription',jQuerythis).stop(true,true).slideUp(700);
}
);
});
</script>
Looks like this is happening because each accordion item has its own hover event that takes care of its own animation. You can refactor the code slightly to make this easier to understand and reuse:
var activeItem = jQuery("#accordion li:first");
jQuery('#accordion > li, #accordion > li.heading').hover(
function () { hoverMe(jQuery(this)); },
function () { unhoverMe(jQuery(this)); }
);
//This gets called when cursor hovers over any accordion item
var hoverMe = function(jQuerythis) {
//If the first item is still active
if (activeItem) {
contract(activeItem); //...Shrink it!
activeItem = false;
}
//Expand the accordion item
expand(jQuerythis);
};
//This gets called when cursor moves out of accordion item
var unhoverMe = function(jQuerythis) {
contract(jQuerythis);
};
//I have moved the hover animation out into a separate function, so we can call it on page load
var expand = function(jQuerythis) {
jQuerythis.stop().animate({'height':'280px'},500);
jQuery('.heading',jQuerythis).stop(true,true).fadeOut();
jQuery('.bgDescription',jQuerythis).stop(true,true).slideDown(500);
jQuery('.description',jQuerythis).stop(true,true).fadeIn();
};
//I have moved the unhover animation out into a separate function, so we can contract the first active item from hoverMe()
var contract = function() {
jQuerythis.stop().animate({'height':'40px'},1000);
jQuery('.heading',jQuerythis).stop(true,true).fadeIn();
jQuery('.description',jQuerythis).stop(true,true).fadeOut(500);
jQuery('.bgDescription',jQuerythis).stop(true,true).slideUp(700);
};
//Now expand the first item
expand(activeItem);
I have put together a simplified version demonstrating the logic. Please let me know how you get on.

JScrollPane Plugin - Reinitialize on Collapse

I'm trying to get JScrollPane to reinitialize on expand/collapse of my accordion found here. You can demo the accordion by clicking on one of the parents (Stone Tiles, Stone Sinks, Stone Wall Clading, etc).
Right now I set it as a click event using the following JQuery...
var pane = $('.menuwrap')
pane.jScrollPane();
var api = pane.data('jsp');
var i = 1;
$("ul#widget-collapscat-5-top > li.collapsing").click(function() {
$(this).delay(3000);
api.reinitialise();
});
It seems to work when you click the parent the second time, but not the first. I have no idea why but I went into trying to edit the JS for the accordion so that I can add this function when the collapse is complete (as opposed to trying to do this click workaround). The collapse JS can be viewed here.
I tried to add the JS for the reinitialize function here, but I think I'm not doing something properly.
May you point me in the right direction?
Thanks!
The api.reinitialise() is working properly. What is happening is that it updates the size when you click, and at this moment the element is not expanded yet. You may notice that if you expand, colapse and expand again the same section, nothing happens. But if you expand one and then click another one, the ScrollPane will adjust to the size of the first expanded element.
You can solve this with events: place $(this).trigger('colapseComplete') when the colapse ends. Then you can use:
//Listening to the colapseComplete event we triggered above
$("#widget-collapscat-5-top > li.collapsing").on('colapseComplete', function() {
api.reinitialise();
});
Maybe you can alter the addExpandCollapse function to call the reinitialise function at the end of each of its click actions this way :
function addExpandCollapse(id, expandSym, collapseSym, accordion) {
jQuery('#' + id + ' .expand').live('click', function() {
if (accordion==1) {
var theDiv = jQuery(this).parent().parent().find('span.collapse').parent().find('div');
jQuery(theDiv).hide('normal');
jQuery(this).parent().parent().find('span.collapse').removeClass('collapse').addClass('expand');
createCookie(theDiv.attr('id'), 0, 7);
}
jQuery('#' + id + ' .expand .sym').html(expandSym);
expandCat(this, expandSym, collapseSym);
api.reinitialise(); // HERE
return false;
});
jQuery('#' + id + ' .collapse').live('click', function() {
collapseCat(this, expandSym, collapseSym);
api.reinitialise(); // and HERE
return false;
});
}
and to be on a safer side, make sure you have the var api = pane.data('jsp'); line before the above piece of code anywhere in the file.

jQuery conditionally change events depending on .html( 'string' ) values

http://jsfiddle.net/motocomdigital/Qh8fL/4/
Please feel free to change the heading if you think I've worded it wrong.
General
I'm running a wordpress site with multilingual control. And my menu/navigation is dynamic, controlled via the wordpress admin. The multilingual language plugin also changes the dynamic menu/navigation content, as well as page content.
My Contact button, which is in the dynamic navigation, opens a sliding menu using jQuery. Very simple animation using top css. The contact button is on the page twice, hence why I'm not using the .toggle for iterations. See jsFiddle.
Script
var $button = $(".contact-button"),
// var for button which controls sliding div
$slide = $("#content-slide");
// var for the div which slides up and down
$button.on('click', function () {
// function for when button is clicked
if ($button.html() == 'Close') {
// run this if button says 'Close'
$slide.stop().animate({ top: "-269px" }, 300);
// close slide animation
$button.html('Contact');
// change text back to 'Contact'
} else {
// else if button says Contact or anything else
$slide.stop().animate({ top: "0" }, 300);
// open slide animation
$button.html('Close');
// change text to 'Close'
}
});
Problem
Because I'm running multilingual on the site. The navigation spelling changes. See jsFiddle flag buttons for example. This is fine, the animation still runs OK, because it's using the button class 'contact-button'.
But because I'm using the .html to replace the text of the button to "Close" and then on the second iteration, back to "Contact" - obviously this is a problem for other languages, as it always changes to English 'close' and back to English 'Contact'
But my three languages and words that I need the iterations to run through are...
Contact - Close
Contatto - Cerca
Contacto - Chiudere
Can anyone help me expand my script to accommodate three languages, all my attempts have failed. The jsFiddle has the script.
The language functionality in the fiddle is only for demo purposes, so the iteration sequence can be tested from the beginning. I understand if you change the language whilst the menu is open (in the fiddle), it will confused it. But when the language is changed on my site, the whole page refreshes, which closes the slide and resets the sequence. So it does not matter.
Any pro help would be awesome thanks!!!
MY POOR ATTEMPT, BUT YOU CAN SEE WHAT I'M TRYING TO ACHIEVE
var $button = $(".contact-button"),
// Var for button which controls sliding div
$slide = $("#content-slide");
// Var for the div which slides up and down
$button.on('click', function () {
// function for when button is clicked
if ($button.html() == 'Close' || 'Cerca'|| 'Chiudere' ) {
// run this if button says Close or Cerca or Chiudere
$slide.stop().animate({ top: "-269px" }, 300);
// Close slide animation
$(function () {
if ($button.html(== 'Close') {
$button.html('Contact'); }
else if ($button.html(== 'Cerca') {
$button.html('Contatto'); }
else ($button.html(== 'Chiudere') {
$button.html('Contacto'); }
});
// Change text back to Contact in correct language
} else {
// else if button says Contact or anything else
$slide.stop().animate({ top: "0" }, 300);
// Open slide animation
$(function () {
if ($button.html(== 'Contact') {
$button.html('Close'); }
else if ($button.html(== 'Contatto') {
$button.html('Cerca'); }
else ($button.html(== 'Contacto') {
$button.html('Chiudere'); }
});
// Change text back to Close in the correct language
}
});
See my attempt script above which is not working on this jsFiddle.
Here's a working example: http://jsfiddle.net/Qh8fL/2/
When one of the language buttons gets clicked, it stores the strings for Contact and Close using jQuery's .data() method. Then, when the contact/close button gets clicked, it refers to those strings rather than having it hard-coded.
Here are the relevant lines of code:
$("#english").click(function() {
$(".contact-button").html('Contact').data('langTxt',{contact:'Contact',close:'Close'});
});
$("#spanish").click(function() {
$(".contact-button").html('Contatto').data('langTxt',{contact:'Contatto',close:'Close'});
});
$("#italian").click(function() {
$(".contact-button").html('Contacto').data('langTxt',{contact:'Contacto',close:'Close'});
});
if ($button.html() == 'Close') {
//...
$button.html($button.data('langTxt').contact);
} else {
//...
$button.html($button.data('langTxt').close);
}
All you need to do to modify the "close" text appropriately is by editing the close property inside the calls to data() that occur in each of the click events.
You should never depend on label strings ... especially in a multilingual environment. Instead you should use placeholders that you store in an attribute (maybe using .data()). Then you write your own setters for the labels depending on the value of the attribute.
var myLabels = {'close': ['Close', 'Cerca', 'Chiudere'], 'contact' : ['Contact', 'Contatto', 'Contacto']};
var currLang = 2; // to select italian
....
// to set the label
$button.data('mylabel', 'close');
$button.html(myLabels['close'][currLang]);
....
if($button.data('mylabel') == 'close') {
$button.data('mylabel', 'contact');
$button.html(myLabels['contact'][currLang]);
} else {
$button.data('mylabel', 'close');
$button.html(myLabels['close'][currLang]);
}

Simplify my menu animation code

I've got a bunch of 'project' divs that I want to expand when they're clicked on. If there's already a project open, I want to hide it before I slide out the new one. I also want to stop clicks on an already open project from closing and then opening it again.
Here's an example of what I mean (warning - wrote the code in the browser):
$('.projects').click(function() {
var clicked_project = $(this);
if (clicked_project.is(':visible')) {
clicked_project.height(10).slideUp();
return;
}
var visible_projects = $('.projects:visible');
if (visible_projects.size() > 0) {
visible_projects.height(10).slideUp(function() {
clicked_project.slideDown();
});
} else {
clicked_project.slideDown();
}
});
Really, my big issue is with the second part - it sucks that I have to use that if/else - I should just be able to make the callback run instantly if there aren't any visible_projects.
I would think this would be a pretty common task, and I'm sure there's a simplification I'm missing. Any suggestions appreciated!
slideToggle?
$('.projects').click(function() {
var siblings = $(this).siblings('.projects:visible');
siblings.slideUp(400);
$(this).delay(siblings.length ? 400 : 0).slideToggle();
});
Used a delay rather than a callback because the callback is called once per matched item. This would lead to multiple toggles if multiple items were visible.
Like this?
$(".projects")
.click(function () {
var a = $(this);
if (a.is(":visible")) return a.height(10)
.slideUp(), void 0;
var b = $(".projects:visible");
b.size() > 0 ? b.height(10)
.slideUp(function () {
a.slideDown()
}) : a.slideDown()
})

Categories

Resources