Toggle anchor to work only in the first child? - javascript

I have been trying to make -just- the first child of: ".accordion-media-types a" to work.
At the moment, every anchor is toggling and grabbing the style of ".accordion-media-types" while they should be a regular looking link, so I just need the first one to work, is it possible somehow?
http://jsfiddle.net/0mpuh2f2/8/
html:
<ul class="accordion-media-types">
<li>
Info
<div class="hidden-content">
<ul>
<li>
link
</li>
</ul>
</div>
</li>
</ul>
js:
$(document).on('click', '.accordion-media-types a', function (e) {
e.preventDefault();
$(this).closest('.accordion-media-types').toggleClass('active').find('.hidden- content').slideToggle(500);
});
thanks in advance for any help!

You can use direct child selector: .accordion-media-types > li > a:
$(document).on('click', '.accordion-media-types > li > a', function (e) {
e.preventDefault();
$(this).closest('li').toggleClass('active').find('.hidden-content').slideToggle(500);
});
Read about child selectors here.
Also note that you probably want to toggle only closest li hidden content, not all of them at once.
Demo: http://jsfiddle.net/0mpuh2f2/11/

Related

add active class to main menu using javascript

I have searched a lot for adding active class to the parent menu using javascript.
I found many more examples but not a single one is working for me, below is my code
HTML
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
My requirement is when i click on SubItem1 then both Item1 and SubItem1 should be active.
And when i click on SubSubItem1 then SubSubItem1 ,SubItem1 and Item1 should be active.
Means when click on any link then its all parent link and the same link should be active.
I have tried with this javascript code :
$(document).ready(function () {
$('.hmenu ul li ul').find('li').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents('li').addClass('active');
});
});
Actually i don't have any experience with javascript coding and unable to figure out the problem in my code.
Can anyone suggest me for the same.
The issue comes from .find('li').click().
As you use nestsed <li>, this will cause the event to be fired two times when you click on a child <li>. This causes problems. Can not you add the click() to <a> elements?
$(document).ready(function () {
$('.hmenu a').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents("li").addClass('active');
});
});
It works just fine: https://jsfiddle.net/6put8tdx/
Note that your page will be bumped to the top while clicking to a tab because of # anchor. If you want to prevent this, you may pass the event to the function .click(function (event) {...} and add event.preventDefault inside.
If you need the click target to be the LI element (as opposed to Delgan's answer)
you can use .not() over the targeted LI's parents to prevent messing with the bubbling event targets:
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault(); // Prevent page jumps due to anchors
var $par = $(event.target).parents("li"); // get list of parents
$(".hmenu .active").not( $par ).removeClass("active"); // not them
$(this).addClass('active'); // let the event propagation do the work
});
});
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault();
var $par = $(event.target).parents("li");
$(".hmenu .active").not($par).removeClass("active");
$(this).addClass('active');
});
});
.active > a{
background: gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
To better understand the above
The following example works out-of-the-box, and the clicked one and all it's LI parents get the "active" class.
Why? Cause the event target is li, means any li of .hmenu - so that click is attached to any of them, and clicking the subsub LI the event will propagate to the LI parents - triggering the same click behavior (this add class)!
$(".hmenu").on("click", "li", function(){
$(this).addClass("active"); // Wow! Event propagation rulez!!
});
But we need to remove existing .active and here it gets messy...
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active"); // triggered on every event bubble :(
$(this).addClass("active"); // leaving only the main parent with active class
});
That's caused by the concurrency that happens while the event bubbles and triggers the same actions for the parent elements.
One way to prevent that concurrency would be using a setTimeout of 1ms:
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active");
setTimeout(function(){ // Let the previous finish the bubbling mess
$(this).addClass("active"); // Yey! all fine! Every LI has the active class
}, 1);
});
But here the timeout of 1ms can lead to visual "blinking" issues.
Try this:
$(function () {
$("li a")
.on("click", function () {
$(this).toggleClass("active");
$(this).closest("ul").parent().children("li a").toggleClass("active")
.parent().parent().parent().children("li a").toggleClass("active");
});
});
fiddle
Traverse from the clicked element. And use toggleClass() to avoid the mundane checking if hasclass removeClass ...

Find <li> tag by its child tag <a> href value

How to find Li tag which has a child tag by its Href value. By this I need to set class for that li tag.
My HTML
<div id="tabs" class="tab_wrapper">
<ul class="nav nav-tabs">
<li>Subject
</li>
<li>Contract
</li>
<li>Neighborhood
</li>
<li>Site
</li>
<li>Improvements
</li>
<li>Supplemental Data
</li>
</ul>
</div>
Css
.Active
{
color:red;
}
For example I have to set class "Active" for li tag which has href value "#tabNeighbourhood", so that li tag will be like
<li class="active">Neighborhood
</li>
Using :has() selector:
$('li:has(a[href="#tabNeighbourhood"])').addClass('active');
This will add class active to any LI containing anchor with specific href attribute.
Use .parent() :
$("ul.nav > li").removeClass("active"); // Clear all li's class attributes.
$("a[href='#tabNeighborhood']").parent().addClass("active"); // Add active to neighborhood.
$('li', '#tabs')
.filter(function() {
return !! $(this).find('a[href="#tabNeighbourhood"]').length;
})
.addClass('active');
I refer you to the official docs for explanation of the single parts.
Try Below Code
$(document).ready(function(){
$('body').find('a').each(function(){
if($(this).attr('href')=="#tabNeighbourhood"){
$(this).closest('li').addClass("Active");
}
});
});
Using your HTML structure you can use an immediate children selector >, has selector and a selector on href attribute.
Code:
$('#tabs>ul>li:has(a[href="#tabNeighbourhood"])').addClass('active');
Demo: http://jsfiddle.net/swvzot7f/
Try it by yourself. Here is an algorithm if you consider it too complex:
Search for needed <a> by attribute.
Select the parent of <a> that was found.
Add class to that parent.
Answer is pretty simple, so I do think it is much more important to show you the way of thinking instead of feeding with ready made-up solution.
EDIT
Just in case you fail I decided to add a solution too:
$( "a[href='NEEDED HREF TO SEARCH']" ).parent().addClass('active');
Another option, You can achieve by CSS alone:
a[href$='#tabNeighbourhood']
{
color:red;
}
Fiddle
JQuery method (using :has() selector):
$('ul li:has(a[href="#tabNeighbourhood"])').addClass('Active');
Fiddle
The following code (vanilla js :-) shows you how to add a class to an HTML element which ha specific href value. Just enter in the field the href value you want to search, it will add a class active, example try: #tabSubject or #tabImprovements. I hope it is what you need.
function setActive(){
var elm = document.getElementsByName('findElm')[0],
searchElm = elm.value,
targetStr = 'a[href*="' + searchElm + '"]',
target = document.querySelector(targetStr);
target.classList.add('Active');
}
.Active
{
color:red;
}
<div id="tabs" class="tab_wrapper">
<ul class="nav nav-tabs">
<li>Subject
</li>
<li>Contract
</li>
<li>Neighborhood
</li>
<li>Site
</li>
<li>Improvements
</li>
<li>Supplemental Data
</li>
</ul>
</div>
<input type="text" name="findElm" value="#tabImprovements"><br>
<input type="submit" value="Search" name="submit" onclick="setActive();">
css: Use the nth-child concept(Best Practice)
.tab_wrapper ul :nth-child(3) a {
color:red;
}

How to Remove a Class from a Sibling of a Parent

I'm working with the off-canvas script from Foundation and it isn't working out of the box (of course) when I try to use the submenu options. I realized it wasn't adding a class (move-right) to the ul's of the li's in the off-canvas navigation. So I wrote a script to add that class which can be found here:
jQuery(document).ready(function() {
jQuery('ul.off-canvas-list li a').click(function() {
jQuery('ul.off-canvas-list li ul.left-submenu').addClass('move-right');
});
});
And here is how my HTML is structured:
<ul class="off-canvas-list">
<li class="has-submenu">Name 1
<ul class="left-submenu">
<li class="back">Back</li>
<li><a href="#"></li>
<li><a href="#"></li>
</ul>
</li>
<li class="has-submenu">Name 2
<ul class="left-submenu">
<li class="back">Back</li>
<li><a href="#"></li>
<li><a href="#"></li>
</ul>
</li>
<li class="has-submenu">Name 3
<ul class="left-submenu">
<li class="back">Back</li>
<li><a href="#"></li>
<li><a href="#"></li>
</ul>
</li>
...etc
</ul>
My problem is that my script is adding the class to ALL ul.left-submenu's instead of just the one directly under the li that I click on. I can't figure out how to add the class 'move-right' to only the 'ul.left-submenu' child of the parents li that I clicked on and remove the 'move-right' class from the other 'ul.left-submenu'
I thought maybe using the sibling() selector, but I wasn't quite sure how to implement that into my script. Any and all help is greatly appreciated.
Another issue has arose and that is being able to close the opened "ul.left-submenu" by clicking on the "Back" which comes before the other li's in each ul.left-submenu. I updated the HTML above to include the "" and also have provided the script below that I tried using that hasn't worked.
jQuery('li.back').on('click', function() {
console.log('close submenu');
jQuery('ul.left-submenu').removeClass('move-right');
});
The target element is the grandparent of the clicked element so you can use the closest method:
$('ul.off-canvas-list li a').click(function() {
$('.move-right').removeClass('move-right');
$(this).closest('ul.left-submenu').addClass('move-right');
});
you can add it directly to the clicked element by using this
jQuery(document).ready(function() {
jQuery('.left-submenu li a').click(function() {
jQuery('.left-submenu').removeClass('move-right'); // remove class move-right from every elements with class left-submenu
jQuery(this).parents('.left-submenu').addClass('move-right'); // add class move-right to the parent with class left-submenu of current element
});
});
Edit:
if in your updated code, you want to click only by a right after .has-submenu, you need this probably, so it didn't trigger on click for a inside .left-submenu
jQuery(document).ready(function() {
jQuery('.has-submenu > a').click(function() {
jQuery('.left-submenu').removeClass('move-right'); // remove class move-right from every elements with class left-submenu
jQuery(this).children('.left-submenu').addClass('move-right'); // add class move-right to the children with class left-submenu of current element
});
});
sorry for my mistakes not looking again for the code before posting it, because ul.left-submenu is in the same position with a and not it's children, you need to use .siblings to get ul.left-submenu, so change the code to this
jQuery(document).ready(function() {
jQuery('.has-submenu > a').click(function() {
jQuery('.left-submenu').removeClass('move-right');
jQuery(this).siblings('.left-submenu').addClass('move-right');
});
});
here's the working Example in Fiddle
Ok, so you want to add a class move-right to the ul.left-submenu that is directly under the has-submenu li that you clicked, right?
So:
$(document).ready(function() {
//Trigger the click only on the li's has-submenu
$('li.has-submenu').on('click', function() {
//Remove the class from other ul, if there's any
$('ul.left-submenu').removeClass('move-right');
//Finds the direct ul child using the '>' selector, and adds the class.
$(this).find('> ul.left-submenu').addClass('move-right');
});
});
The way you have your selector it targets all the ul.left-submenu elements you have, another way to target just the element clicked would be like this:
$('.off-canvas-list').on('click', 'ul.off-canvas-list li a', function (){
$('.move-right').removeClass('move-right');
$(event.target).closest('ul.left-submenu').addClass('move-right');
});
Your selector is too broad. If what you want to do is to add move-right to left-submenu when you click has-submenu, that's what you need to do:
$('.has-submenu').click(function() {
$(this).find($('.left-submenu')).addClass('move-right');
});
Fiddle: http://jsfiddle.net/x9zcav0p/
If you need to reset move-right, do this:
$('.has-submenu').click(function() {
$('.move-right').removeClass('move-right');
$(this).find($('.left-submenu')).addClass('move-right');
});
Fiddle: http://jsfiddle.net/x9zcav0p/1/
Updated markup:
For your updated markup, you can target the next() element after the anchor tag:
$('.has-submenu > a').on('click', function() {
$('.move-right').removeClass('move-right');
$(this).next().addClass('move-right');
});
Fiddle: http://jsfiddle.net/x9zcav0p/2/

Finding children of element without an id or class

I have the following code structure:
<ul class='menu'>
<li>
Main Menu
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
Main2
<ul class='hide'>
<li>Sub1</li>
</ul>
</li>
</ul>
Is there a way for me to have a jQuery click event on Main Menu and Main2 in a generic way that will remove the class 'hide' of the correct children each time?
Here is another way, which uses event delegation and only runs when the li element and not its children was clicked:
$('ul.menu').on('click', 'ul.menu > li', function(e) {
if(e.target === this) {
$(this).children('ul').toggleClass('hide');
}
});
DEMO
$("ul.menu > li").on("click", function () {
$(this).children("ul").removeClass("hide");
});
Example: http://jsfiddle.net/dpkBL/
Dont always do what the crowd tells you, at least think about it for a while!
I bet people will recommend you to use a selector such as ul.menu > li, but please remember that this will not only trigger a click event when you click on the text "Main Menu", but also when you click on any of the other content inside the matching li.
If you'd like to implement a show/hide toggle you are far better off wrapping the text "Main Menu" inside it's on element, and then use something as the below to alter what you may want to alter.
$(<main menu text selector>).siblings (<siblings selector>);
Still want/have to follow the crowd?
If this is the case I'd recommend you to at least do it with a little twist to prevent what I previously described.
(edit: revised version after reading the jquery documentation for elements)
$('ul.menu > li').click (function(e){
if (e.target === this) {
$(this).children ('.hide').removeClass ('hide');
}
});
$("ul.menu > li").click (function () {
$(this).find ('.hide').removeClass ('hide');
});
$("ul.menu > li > *").click (function () {
return false; // prevent event from bubbling up
});
Sample implementation of recommended version
The below will bind a click-event-listener to .menu-toggle, when the event is fired the siblings (ie. the tags who are in the same scope as the clicked .menu-toggle) matching .hide will have their class="hide" removed.
Javascript
$(".menu-toggle").click (function () {
$(this).siblings ('.hide').removeClass ('hide');
});
HTML
<ul class='menu'>
<li>
<span class="menu-toggle">Main Menu</span>
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
<span class="menu-toggle">Main2</span>
<ul class='hide'>
<li>Sub1</li>
</ul>
</li> </ul>
Take a look at the child selectors. I think that is what you want.
$('.menu > li').click(function () {
$(this).children('ul').removeClass('hidden');
});

how to select a li a based on the text using jQuery

How can I select a given li a element so that it is selected by default?
Please refer to this question to see the example that I'm working with...
How can I navigation up and down a ul using two buttons?
Basically I need to select the Patient Test li a item by default.
Try this:
$(function(){
$("#MainMenu li:contains('PATIENT TEST')").click();
});
You could do something like this
$('li a').each(function(){
if($(this).text() == 'PATIENT TEST'){
//do something here
}
});
Example: http://jsfiddle.net/jasongennaro/uuaKH/
Try:
<script type="text/javascript">
$(function() {
$('#MainMenu li > a').eq(0).focus()
});
</script>
set in the loaded html, since the next click will remove and reset the "status", based on the other post
<div id="MainMenu">
<ul>
<li class="menuActive">PATIENT TEST</li>
<li>QC TEST</li>
<li>REVIEW RESULTS</li>
<li>OTHER</li>
</ul>
</div>
I just had to create an ID for each li and then use jQuery addClass and removeClass to swap the classes.
$("#repeatMenuItem").removeClass("active");
$("#deleteMenuItem").removeClass("active");
$("#okMenuItem").addClass("active");

Categories