How to toggle using JQuery - javascript

I have an accordion, and I'm able able to open on each click, but how can I close it back again?
HTML:
<ul class="accordion">
<li id="one" class="files">
Calendar 1<span>10</span>
<ul class="sub-menu">
<li><em>01</em>Sub Menu<span>1</span></li>
</ul>
</li>
<li id="two" class="mail">
Calendar 2<span>20</span>
<ul class="sub-menu">
<li><em>01</em>Sub Menu<span>2</span></li>
</ul>
</li>
<li id="three" class="cloud">
Calendar 3<span>30</span>
<ul class="sub-menu">
<li><em>01</em>Sub Menu<span>3</span></li>
</ul>
</li>
<li id="four" class="sign">
Calendar 4
<ul class="sub-menu">
<li><em>01</em>Sub Menu</li>
</ul>
</li>
</ul>
Javascript:
$(document).ready(function() {
// Store variables
var accordion_head = $('.accordion > li > a'),
accordion_body = $('.accordion li > .sub-menu');
// Open the first tab on load
accordion_head.first().addClass('active').next().slideDown('normal');
// Click function
accordion_head.on('click', function(event) {
// Disable header links
event.preventDefault();
// Show and hide the tabs on click
if ($(this).attr('class') != 'active') {
$(this).next().stop(true,true).slideToggle('normal');
$(this).addClass('active');
}
});
});
Fiddle: http://jsfiddle.net/fuuLh494/

You dont need to explicitly check for active class occurence and then do add/remove decision of class. You can achieve this with toggleClass:
accordion_head.on('click', function(event) {
event.preventDefault();
$('.sub-menu').not($(this).next()).slideUp('normal').prev().removeClass('active');
$(this).next().stop(true,true).slideToggle('normal');
$(this).toggleClass('active');
});
Working Demo

You can remove the if completely, and use both slideToggle and toggleClass:
$(this).next().stop(true,true).slideToggle('normal');
$(this).toggleClass('active');
Updated Fiddle

if ($(this).attr('class') != 'active'){
//accordion_body.slideUp('normal');
$(this).next().stop(true,true).slideToggle('normal');
//accordion_head.removeClass('active');
$(this).addClass('active');
} else {
$(this).next().stop(true,true).slideToggle('normal');
$(this).removeClass('active');
}
See the updated fiddle here: http://jsfiddle.net/9ev31v6w/

The best you can do with a tutorial is learn, and not copy&paste without read the code. It's as simple as this:
http://jsfiddle.net/fuuLh494/1/
I add else statement at the end of the script:
else {
$(this).next().stop(true,true).slideToggle('normal');
$(this).removeClass('active');
}

Replace all instances of addClass with toggleClass and remove the condition of if class is active.
We are trying to remove the class when the class is already added using toggleClass() and don't need any if condition block.
accordion_head.first().toggleClass('active').next().slideDown('normal'); // Changed
if ($(this).attr('class') != 'active') { } // Removed
$(this).toggleClass('active'); // Changed
Working JSfiddle

Related

display block with event target id

I'm try to display an item inside a list that has a class which is exactly the same ID on the other list. This would be activated when I click on the other list then it will find a match class on the other list then display it.
Here is the code I'm using basically the first list is in display:none;
List 2 is my menu on which in the list 1 would you like to display.
The first list should only have one visible item at a time.
Fiddle is here
HTML
<div id="gallery-container">
<li class="1723"><p>
123
</p></li>
<li class="1725"><p>
456
</p></li>
</div>
<ul id="gallery-list">
<li id="1723">
<strong>qwertyuiop</strong>
</li>
<li id="1725">
<strong>asdfghjkl</strong>
</li>
</ul>
SCRIPT:
$("#gallery-list li").click(function() {
alert(event.target.id);
$("#gallery-container li .wc-gallery").css("display", "none");
});
window.onload = function () {
$("#gallery-container li p").css("display", "none");
}
CSS:
#gallery-container li p {display:none;}
It's bad bad to use the same id in one HTML document. Never do this. Nobody likes that, jQuery doesn't like that. I don't like it. Try using a class or a data property.
But.. scratch that.. you are not really trying to do that. But still.. it's better to use a data property :)
Anyways, to accomplish this with a data property, you can do something like this:
html
<div id="gallery-container">
<li data-id="1723">
<p>
123
</p>
</li>
<li data-id="1725">
<p>
456
</p>
</li>
</div>
<ul id="gallery-list">
<li data-id="1723">
<strong>qwertyuiop</strong>
</li>
<li data-id="1725">
<strong>asdfghjkl</strong>
</li>
</ul>
js
$("#gallery-list li").click(function() {
var id = $(this).data('id');
$("#gallery-container").find('li').each(function() {
$(this).find('p').toggle($(this).data('id') === id);
});
});
jsfiddle
If you want to fetch the id of the list you clicked:
$("#gallery-list li").on("click", function() {
alert($(this).attr("id"))
$("#gallery-container li .wc-gallery").css("display", "none");
});
$('#gallery-list li').click(function() {
var targeeet = $(this).attr('id');
$('.' + targeeet).children().css('display', 'block');
});
Try this.
All you need is :
$('#gallery-list li').click(function() {
var target = $(this).attr('id');
$("#gallery-container li").hide();
$("#gallery-container li."+target).css('display', 'block');
});
Check the example below :
$('#gallery-list li').click(function() {
var target = $(this).attr('id');
$("#gallery-container li").hide();
$("#gallery-container li."+target).css('display', 'block');
});
#gallery-container li{
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="gallery-container">
<li class="1723">
<p>
123
</p>
</li>
<li class="1725">
<p>
456
</p>
</li>
</div>
<ul id="gallery-list">
<li id="1723">
<strong>qwertyuiop</strong>
</li>
<li id="1725">
<strong>asdfghjkl</strong>
</li>
</ul>
Are you trying to do an accordion?
$("#gallery-container li").hide();
$("#gallery-list li").click(function() {
$("#gallery-container li").hide();
$("#gallery-container li."+this.id).show();
});
jsFiddle

Prevent default only on some levels

I am making a menu that has submenu. When I click on a menu item I am using prevent default because it is a tags, but on the submenu level I don't want to prevent default. I haven't been able to figure out how to make it work so it doesn't affect the top level.
<div id="block-menu-block-2">
<ul class="menu">
<li>
1
</li>
<li>
2
<ul class="menu">
<li>2.1</li>
<li>2.2</li>
<li>2.3</li>
<li>2.4</li>
</ul>
</li>
<li>
3
<ul class="menu">
<li>3.1</li>
<li>3.2</li>
<li>3.3</li>
<li>3.4</li>
</ul>
</li>
<li>
4
</li>
<li>
5
</li>
<li>
6
<ul class="menu">
<li>6.1</li>
</ul>
</li>
</ul>
</div>
Here is the jQuery
$('#block-menu-block-2 ul li').on("click", function() {
if ($(this).children().is('ul')) {
if ($(this).find('ul').is(':visible')) {
$(this).find('ul').hide("blind");
$(this).removeClass('menuItemSelected');
$(this).find('ul').removeClass('menuItemSelected');
} else {
$(this).parent().find('li ul').hide("blind");
$(this).parent().find('.menuItemSelected').removeClass('menuItemSelected');
$(this).find('ul').show("blind");
$(this).addClass('menuItemSelected');
$(this).find('ul').addClass('menuItemSelected');
};
event.preventDefault()
}
});
Here is a codepen for reference: http://codepen.io/mathiasha/pen/bVpMyo
Added some stuff. Changed some stuff. Couldn't paste into codepen from my phone so this might not work. Code first, then word wall.
$('#block-menu-block-2 ul li').each (function () {
var $this = $(this);
if ($this.find ('ul:first').length > 0) {
$this.click (function () {
if ($this.find ('ul:visible').length > 0) {
$this.removeClass ('menuItemSelected').find ('ul').removeClass('menuItemSelected').hide ('blind');
} else {
$this.parent ().find ('ul li').hide ('blind');
$this.parent ().find('.menuItemSelected').removeClass ('menuItemSelected');
$this.addClass ('menuItemSelected').find ('ul').show ('blind').addClass ('menuItemSelected');
}
});
}
});
$('#block-menu-block-2 > ul > li > a').click (function (e) {
if ($(this).find ('ul:first').length > 0)
e.preventDefault ();
});
The real answer lies in only putting the preventDefault only on the a tag and only when it is the immediate child of a li tag tjat is the immediate child of a ul tag that is the immediate child of the block-menu. See the last 3 lines.
The rest of the code below should only add the click listener to li tags with ul tags inside. Tried to use chaining to limit the number of jQuery objects created. Might have messed up what it was doing. You only really need to remove preventDefault from where it is and than use the last 3 lines.
Can you not add a class to your submenu triggers, e.g. .submenu-trigger, and then use the following jQuery:
$(document).on('click', function(e) {
if ($(e.target).hasClass('submenu-trigger')) e.preventDefault();
});
Ignoring all the other menu manipulation and putting the event on <a> tags you can simply check if the <a> has a sibling <ul> and if it does prevent default
$('#block-menu-block-2 a').click(function(e){
if( $(this).siblings('ul').length ){
e.preventDefault();
}
// menu manipulation code
});

Issue targeting specific selector jquery in dropdwon menu

I have a drop down menu with jquery and I want to modify some text in different way depending on what is selected in the drop down menu.
The drop down menu works.
Html code:
<div>
<ul class="myMenu">
<li>Choose your location
<ul>
<li id="op1">option1</li>
<li id="op2">option2</li>
<li id="op2">option3</li>
</ul>
</li>
</ul>
</div>
<div>
<h1 id="text_to_change">Welcome to blabla</h1>
</div>
Javascript code:
$(document).ready(function() {
$('.myMenu li ul li').click( function(event){
$(document).find('#text_to_change').css('visibility', 'visible');
$('.myMenu').hide();
if ($(this) == '#op1'){
$('#text_to_change').text("text changed");
}
if ($(this) == '#op2'){
$('#text_to_change').text("text changed differently");
}
else{
$('#text_to_change').text("text changed differently again");
}
});
});
Why does ($(this) == '#op1') not work?
You are trying to compare a jquery object $(this) with a string #op1
To get the id of the element use:
$(this).attr('id');
It will give you the id of the element without the #
Also i think your second if needs to be an else if { ...
$(document).ready(function() {
$('.myMenu li ul li').click( function(event){
console.log($(this).attr('id'), $(this).prop('id'));
$(document).find('#text_to_change').css('visibility', 'visible');
$('.myMenu').hide();
if ($(this).attr('id') == 'op1'){
$('#text_to_change').text("text changed");
}
else if ($(this).attr('id') == 'op2'){
$('#text_to_change').text("text changed differently");
}
else{
$('#text_to_change').text("text changed differently again");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div>
<ul class="myMenu">
<li>Choose your location
<ul>
<li id="op1">option1</li>
<li id="op2">option2</li>
<li id="op2">option3</li>
</ul>
</li>
</ul>
</div>
<div>
<h1 id="text_to_change">Welcome to blabla</h1>
</div>
This two item must not share the same id 'op2'
<li id="op2">option2</li>
<li id="op2">option3</li>

prev or siblings select jQuery

<li class="page_item ">A
<ul class="children">
<li class="page_item">1</li>
<li class="page_item">2</li>
</ul>
</li>
<li class="page_item ">B
<ul class="children">
<li class="page_item">1</li>
<li class="page_item">2</li>
<li class="page_item">3</li>
<li class="page_item">4</li>
</ul>
</li>
$('.children a').click(function(event){
event.stopPropagation();
$('ul.children').prev().css('background','red');
});
ONLINE SAMPLE: http://jsfiddle.net/uybPf/
I'd like to achieve when I click A or B's submenu, and then A or B will be highlighted. but my code highlighted all of them. I don't want to use toggleClass() could someone please help to fix my code. Thanks
That's because you're using ul.children which will perform the code for every element in that set. Try this instead:
$('.children a').click(function(event){
event.stopPropagation();
$("ul.children").prev().css('background','none');
$(this).closest("ul.children").prev().css('background','red');
});
DEMO: http://jsfiddle.net/uybPf/6/
$('.children a').click(function(event) {
event.stopPropagation();
$(this).closest('ul.children').prev().css('background', 'red');
});
http://jsfiddle.net/uybPf/2/
You should use closest or parent methods:
$('.children a').click(function (event) {
event.stopPropagation();
$('.page_item a').removeClass('highlight'); // remove previously active class
$(this).closest('.children').prev().addClass('highlight');
});
http://jsfiddle.net/uybPf/3/
You should better use addClass and removeClass methods instead of css since you already defined .highlight class in CSS.
Try this
$('.children a').click(function(event){
event.stopPropagation();
$('>a:first', $(this).closest('.children').closest('.page_item')).css('background', '#f00')
});
This however doesn't unhighlight the previously highlighted parent
After reading your question's comments, edit:
add
$('.page_item > a').css('background','transparent');
after
event.stopPropagation();
Try this
$('.children a').click(function (event) {
event.stopPropagation();
$(this).closest('ul.children').parent().children('a').css('background', 'red');
});
http://jsfiddle.net/uybPf/2/

Slide Toggle automatically open the first item?

I have aJQuery accordian using the following JS.
function initMenu() {
$('#accordion ul').hide();
$('#accordion li a').click(
function() {
$(this).next().slideToggle('normal');
}
);
}
$(document).ready(function() {initMenu();});
And the following HTML
<ul id="accordion">
<li><a class="firstheading" href="#">Making words work</a>
<ul class="panelContent">
<li>
<p>IPSUM</p>
</li>
</ul>
</li>
<li><a class="heading" href="#">Full business-writing services</a>
<ul class="panelContent">
<li>
<p>IPSUM<p>
</li>
</ul>
</li>
</ul>
Can anyone tell me how to ensure the first item is opened when the page loads?
You can use the gt selector to specify the ul's with an index greater than zero, so every ul except the first.
Demo here
function initMenu() {
$('#accordion ul:gt(0)').hide();
$('#accordion li a').click(
function() {
$(this).next().slideToggle('normal');
}
);
}
$(document).ready(function() {initMenu();});
It should be opening automatically, but you can open up accordion pieces programmatically like so:
.accordion( 'activate' , index )
so to open up the first section, you would do
$('#accordion').accordion('activate',0);
You could put that in your document ready function. Note that a selector can also be used in place of the number, which represents each section from 0 onwards.
Source

Categories

Resources