I have this structure of html. To present the list of two different sets. and i must handle the click event differently.
<div id='nodelist1'>
<ul>
<li class='nodeelem'>first node
<ul>
<li class='nodeelem'>second node
<ul>
<li class='nodeelem'>third node</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div id='nodelist2'>
<ul>
<li class='nodeelem'>first node
<ul>
<li class='nodeelem'>second node
<ul>
<li class='nodeelem'>third node</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
I have to access the nodes using div id
$('#nodelist1 li.nodeelem').click(handler);
$('#nodelist2 li.nodeelem').click(handler2);
Is this rightway to access children clicks???
You forgot the hash # for ID selectors (although you corrected this in your edit):
$('#nodelist1 li.nodeelem').click(handler);
$('#nodelist2 li.nodeelem').click(handler2);
Tip: you can make the event more effective by using on() instead for event delegation:
$('#nodelist1').on('click', '.nodeelem', handler);
$('#nodelist2').on('click', '.nodeelem', handler2);
Related
I have an unordered nested list
I want to count these nested lists in such a way that inside <li>Animals</li> there are 19 animals inside this li. I wanted to count all li having the name of animals using Javascript. How should I proceed?
<ul>
<li>
Animals
<ul>
<li>
Mammals
<ul>
<li>Apes
<ul>
<li>Chimpanzee</li>
<li>Gorilla</li>
<li>Orangutan</li>
</ul>
</li>
<li>Coyotes</li>
<li>Dogs</li>
<li>Elephants</li>
<li>Horses</li>
<li>Whales</li>
</ul>
</li>
<li>
Other
<ul>
<li>
Birds
<ul>
<li>Albatross</li>
<li>Emu</li>
<li>Ostrich</li>
</ul>
</li>
<li>Lizards</li>
<li>Snakes</li>
</ul>
</li>
</ul>
</li>
<li>Fish
<ul>
<li>Goldfish</li>
<li>Salmon</li>
<li>Trout</li>
</ul>
</li>
</ul>
#mplungjan put forward this solution in the comments and it works. document.querySelectorAll("ul")[1].querySelectorAll("li").length
this gives 17 which is the correct count (after clarification in comments which overrode the first count given which was 19).
The question asks about traversing and we show that step by step here so as to help with more general solutions.
We first have to find the element which is holding all the other lists. I have assumed that that ul element is the first in the document. In the general case we'd probably find such an element by knowing it's id or its class.
We then find the li element which is associated with Animals and again we assume it's the first one, as it is in the HTML given. However, if it was to be more sophisticated you'd want to look for the li element that has Animals as its innerHTML.
We then find the associated lis and count them.
Here is the code and you can run the snippet to see it gets to 17 (which was clarified in comments, the original count in the question was given as 19, also clarified was that this has nothing to do with counting actual animal names, only to do with counting li elements).
<!DOCTYPE html>
<html>
<body>
<ul>
<li>
Animals
<ul>
<li>
Mammals
<ul>
<li>Apes
<ul>
<li>Chimpanzee</li>
<li>Gorilla</li>
<li>Orangutan</li>
</ul>
</li>
<li>Coyotes</li>
<li>Dogs</li>
<li>Elephants</li>
<li>Horses</li>
<li>Whales</li>
</ul>
</li>
<li>
Other
<ul>
<li>
Birds
<ul>
<li>Albatross</li>
<li>Emu</li>
<li>Ostrich</li>
</ul>
</li>
<li>Lizards</li>
<li>Snakes</li>
</ul>
</li>
</ul>
</li>
<li>Fish
<ul>
<li>Goldfish</li>
<li>Salmon</li>
<li>Trout</li>
</ul>
</li>
</ul>
<script>
var firstUL = document.getElementsByTagName('UL')[0]; //assuming the whole list is the first UL in the document
var animalsLI = firstUL.getElementsByTagName('LI')[0];
var animalsLIUL = animalsLI.getElementsByTagName('UL')[0];
var animalsLIs = animalsLI.getElementsByTagName('LI');
alert('The count of LIs is ' + animalsLIs.length);
</script>
</body>
</html>
I need to loop through the DOM with JQuery, and add a click handler to multiple parent elements that contain a child that will also be given a slideToggle(). I have the logic working fine when I add the click handlers manually, but now I need to be able to dynamically do this to multiple parent elements.
Here is my HTML:
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
Basically, you click on .sub-menu-link to slideToggle() .sub-menu-list.
Here is the JS that I have working so far. It targets the id's manually currently, which feels gross:
$('#sub-menu-link-1').click(function() {
$('#sub-menu-list-1').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
$('#sub-menu-link-2').click(function() {
$('#sub-menu-list-2').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
My apologies if this is something very apparent to do in JQuery. I am not at all familiar with it, and it just so happens to be a requirement of this project.
you could simply use below code.
select all list items with class name and add listener. click will be attached to all elements
$('.sub-menu-link').click(function() {
$(this).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
You already have classes, so just use them instead of the ids: use this to refer to the clicked element, .next() to get the next sibling (the li.sub-menu), and .find('.sub-menu-list') to get to the ul you want to toggle:
$('.sub-menu-link').click(function() {
const $subMenuList = $(this).next().find('.sub-menu-list');
console.log($subMenuList.text().trim());
$subMenuList.slideToggle(100);
$(this).toggleClass('active-menu-link');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
You can use jQuery's .next() like so:
$(".sub-menu-link").click(function() {
$(this).next(".sub-menu-link").slideToggle(100);
$(this).toggleClass("active-menu-link");
})
Or you can chain them and use ES6 arrow syntax to make it more concise:
$(".sub-menu-link").click(() => $(this).toggleClass("active-menu-link").next(".sub-menu-link").slideToggle(100));
You should try this if your list and link ids have similiar pattern as in the code you have shown
$('#sub-menu-link').click(function() {
var id = $(this).attr("id").replace("sub-menu-link", "")
$('#sub-menu-list-'+ id).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
I have html code like this:
<ul class="dropdown-menu mega-dropdown-menu">
<li class="should be = col-sm-4">
<ul>
<li class="should be = dropdown-header">Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
<li class="should be = col-sm-4">
<ul>
<li class="should be = dropdown-header">Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
<li class="should be = col-sm-4">
<ul>
<li class="should be = dropdown-header">Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
</ul>
this code is generated from server side, now my question is, how can I append col-sm-4 css class to all li parents and add css class dropdown-header to first li child elements with javascript?
Vanilla Javascript Solution:
By storing all applicable list items in a variable, that can be later ustilised in a for loop, we can iterate through each instance and add the required class.
This solution is preferable if an entire javascript library or framework (like jQuery) is not required for trivial change that only needs to occur once.
Code Snippet Demonstration:
// Get direct descendant list-item children using querySelectorAll and CSS child combinator selector
var listItems = document.querySelectorAll('.dropdown-menu > li');
// Add class to each instance in for loop
for(var i = 0; i < listItems.length; i++) {
listItems[i].className = 'col-sm-4';
}
// Get first list-item child of nested ul element with class name "col-sm-4" using querySelectorAll and CSS :first-child pseudo-selector
var headerListItems = document.querySelectorAll('.dropdown-menu .col-sm-4 li:first-child');
// Add class to each instance in for loop
for(var i = 0; i < listItems.length; i++) {
headerListItems[i].className = 'dropdown-header';
}
// Note: "querySelectorAll" allows for the ability to specify selectors using CSS Selector Syntax
<ul class="dropdown-menu mega-dropdown-menu">
<li >
<ul>
<li>Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
<li >
<ul>
<li >Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
<li >
<ul>
<li >Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
</ul>
jQuery Solution:
Consider using the .addClass() method to add the required classes by specifying the intended selectors as demonstrated in the embedded code snippet below.
This solution is preferable if this change needs to occur more than once or elsewhere in a similar scope.
Code Snippet Demonstration:
jQuery('.dropdown-menu > li').addClass('col-sm-4');
jQuery('.dropdown-menu .col-sm-4 li:first-child').addClass('dropdown-header');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="dropdown-menu mega-dropdown-menu">
<li >
<ul>
<li>Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
<li >
<ul>
<li >Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
<li >
<ul>
<li >Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
</li>
</ul>
Alternative: Standard CSS Selector Syntax
The elements in question can still be targeted using CSS Selector Syntax with the following methods:
For what would be "col-sm-4": .dropdown-menu > li
Selecting the first direct descendant list-item element using the child combinator (>)
For what would be "dropdown-header": .dropdown-menu ul li:first-child
Selecting the first child list-item element using :first-child pseudo-selector
I want jquery to include <li> and all other tags inside <ul class="visib-1"></ul> to <ul class="visib-2"></ul> without writing li,a href="" tags again. Is there have any solution?Is it possible to capture all elements from one UL and transfer to other UL?
From:
<ul class="visib-1">
<li>Home</li>
<li>Properties</li>
<li>Blog</li>
<li>Start Now</li>
</ul>
To:
<ul visib-1>
?
</ul>
If all you want is to move from one <ul> to another:
$('#first-ul-id li').appendTo('#second-ul-id');
If you want to copy use clone()
$('#first-ul-id li').clone().appendTo('#second-ul-id');
Here is the solution. Check the code below:
This code will also copy the event handlers attached.
var cloneOfOld = $('[data-status="old"]').clone(true);
cloneOfOld.attr('data-status','new');
var newUl = $('[data-status="new"]');
newUl.replaceWith(cloneOfOld);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul data-status="old"><li>Home</li>
<li>Properties</li>
<li>Blog</li>
<li>Start Now</li>
</ul>
<ul data-status="new">
</ul>
Basically i want to click on a tab and a drop down menu appears then when you re-click the same tab or any of the others I want it to hide that tab/show the other tab if clicked on the same/other tab.
I tried
$('.click').click(function() {
$(this).find('.sub-nav-list').toggleClass('active');
});
and tried
$('.click').click(function() {
$('.sub-nav-list').removeClass('active');
$(this).find('.sub-nav-list').toggleClass('active');
});
but cant work it out! any insight? Thanks
html:
<nav class="secondary-nav">
<ul class="list clearfix">
<li class="leaders click">Leadership <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Management</li>
<li>Board of Directors</li>
</ul>
</li>
<li class="contact click">Contact Info <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Email Notification</li>
<li>Information Request</li>
</ul>
</li>
<li class="docs click">Documents <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Governance Documents</li>
<li>Press Release</li>
<li>Reports & Presentations</li>
<li>Sec Filings</li>
<li>Frenquently Asked Questions</li>
<li>Tax Information</li>
</ul>
</li>
<li class="research click">Research <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Dividends and Distributions</li>
<li>Stock Information</li>
<li>Analyst Coverage</li>
<li>Market Makers</li>
</ul>
</li>
</ul>
</nav>
I can see at least two possible issues there.
1) sub-nav-list is not a children of click element. If they are on the same level something like that might work:
$('.click').click(function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});
2) You have these elements generated dynamically - so you need use on with selector of any parent element that exists before you dynamically generate your sub-menus (let say nav-list):
$(".click").on("click", ".nav-list", function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});