How to get offset of <li> in nested <ul> - javascript

I am having the following HTML
<ul>
<li>List item one</li>
<li>List item two with subitems:
<ul>
<li>Subitem 1</li>
<li>Subitem 2</li>
</ul>
</li>
<li>Final list item</li>
I am trying to find offset() of all 'li' including sub list 'li'. But it always returns same value for all 'li'
script
$('li').offset().left;
Is this correct? How to get the offset for all 'li' ?

You need to loop with each like
$('li').each(function(){
alert($(this).offset().left);
});

use each() to loop through all the li and get the corresponding offset()
$('li').each(function(){
console.log($(this).offset().left);
});
fiddle

Related

Universal method of dealing with mobile multi-level navigation menus using HTML, CSS and JavaScript

I have my html as follows:
<button id="hamburger-nav"></button>
<nav>
<ul>
<li>
<button>Sub Nav Item 1</button>
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
</ul>
</li>
<li>
<button>Sub Nav Item 2</button>
<ul>
<li>Link 6</li>
<li>Link 7</li>
<li>Link 8</li>
<li>Link 9</li>
<li>Link 10</li>
</ul>
</li>
<ul>
</nav>
This is a mobile menu that has a hamburger button that activates the "nav" on click. How do I get the index of the sub nav buttons so I can active their sibling "ul" sub sub menu? Granted all of this has to be done on the onclick method since it is a mobile menu.
I was hoping to have a universal method that could find the index of (this), i.e., the item that is clicked, and then get the corresponding "ul", instead of individually naming these and creating a massive, duplication of code for each menu section.
I would like to use plain old JavaScript as I am trying to cut down on the dependencies of jQuery, etc. Something along the lines of:
var menuButtons = document.querySelectorAll("nav > ul > li > button");
var submenu = document.querySelectorAll("nav > ul > li > ul");
menuButtons.onclick = myFunction(this);
function myFunction(v) {
submenu[v].classList.add("open");
}
While I know this JavaScript doesn't work, accessing the index of the clicked button and opening its accompanying nav was my thought process. But perhaps I'm way of going about this.
Thank you in advance!

Using isotope.js , deeper levels are getting affected

I'm using isotope.js to make a megamenu, and have the UL's within the megamenu stack in an orderly fashion. So essentially I have the following HTML:
<ul>
<li>ABOUT
<ul>
<li>We're Great</li>
<li>We're Really Great</li>
</ul>
</li>
<li>DIVISIONS
<ul class="level-2">
<li>Category One
<ul class="level-3">
<li>Item One</li>
<li>Item Two</li>
</ul>
</li>
</ul>
<ul class="level-2">
<li>Category Two
<ul class="level-3">
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
</ul>
</li>
</ul>
<ul >
<li>Category Three
<ul class="level-3">
<li>Item One</li>
<li>Item Two</li>
</ul>
</li>
</ul>
</li>
<li>Products
<ul>
<li>Product One</li>
<li>Product Two</li>
</ul>
</li>
</ul>
What I need, is for the LI's within the UL with the class "level-2", to stack together nicely in the megamenu, and have isotope.js applied to them.
Simple enough, except what isotope seems to do for me, is when I use the following JS:
var $container = $('ul.level-2');
$container.isotope({
itemSelector: 'li'
});
It applies isotoping to the li's even within the level-3 class of UL... which I only want it to be applied to that ONE layer of UL, so they stack friendly, but I don't want the deeper LI's to have anything happen, they should just be normal within their respective UL's.
I have position:relative on the containing UL's, and the LI's are floated left with display: block on them as well. Not sure what I might be missing!!
Hopefully this actually makes sense. Anyone able to point me in the right direction?

Counting Sub-Menu Items jQuery without CSS Classes

The great Google and SO didn't render search results regarding this. Some were similar but didn't quite get me there.
I am in need of making a classless submenu that will attach a style attribute to each individual <li> in the sub <ul> in order to set a min-width property based on the number of sub list items.
The HTML
<nav>
<ul>
<li>HOME</li>
<li>ABOUT COMPANY</li>
<li>
ABOUT PRODUCT
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</li>
<li>GETTING STARTED</li>
<li>
PATIENT SUPPORT
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</li>
<li>CONTACT</li>
<li>eUPDATES</li>
</ul>
</nav>
The JavaScript
$('.sub').text(function() {
var count = $(this).next().find('li').length;
var totalwidth = count * 115;
$(this).next().find('li').parent('ul').attr('style','min-width:'+totalwidth+'px');
});
I need to be able to do this without searching based off the class "sub". I've tried a few times, but none of it seems as powerful as the code I'm currently using. The backend developer I'm working with is requiring it to all be simple <ul><li></li></ul> structure with no classes.
If anyone can help point me in the right direction on this, I'd greatly appreciate your time and help!
Target all LI items that contain UL's, find the number of LI's in those UL's, and multiply for width :
$('ul', 'li').css('min-width', function() {
return ( $(this).find('li').length * 115 ) + 'px';
});

How to group and apply class for specific <li> within <ul> based on li:child?

Please find my ul li here, This li is working for horizontal tab using a bootstrap tab. I'm trying to apply a class; when the 2nd and 3rd li have the class active, I want to apply a style class on the 1st li. simlarly for next 3 li and rest also. I've tried with jquery but didn't succeed.
<ul id="myTab" class="nav-tabs">
<li class="side-menu-grp">Group One</li>
<li>List One</li>
<li>List Two</li>
<li class="side-menu-grp">Group Two</li>
<li>List One</li>
<li>List Two</li>
<li class="side-menu-grp">Group Three</li>
<li>List One</li>
<li>List Two</li>
</ul>
I think that this is what you want:
$('.active').prev('.side-menu-grp').addClass('class');
It selects the elements with class active (the lis if you don't reuse the class) and locates the first previous sibling element with class side-menu-grp and add the class what you want to it.

Hide a set number of list objects

I have multiple list objects with the same structure on a page:
Example:
<div class="mainWrapper">
<div class="listWrapper">
<ul>
<li>Object One</li>
<li>Object Two</li>
<li>Object Three</li>
<li>Object four</li>
<li>Object five</li>
</ul>
</div>
<div class="listWrapper">
<ul>
<li>Object One</li>
<li>Object Two</li>
<li>Object Three</li>
<li>Object four</li>
<li>Object five</li>
</ul>
</div>
</div>
Using jQuery, how can I set it so that for each list, only the first 3 objects are showing in each list and the rest are hidden?
You can use :gt() pseudo selector which select all elements at an index greater than index within the matched set.
$('.listWrapper').find('li:gt(2)').hide();
Demo
Try the :gt() (greater than) selector:
$('.listWrapper ul').find('li:gt(2)').hide();
jsFiddle
It's necessary to query the targeted lis in two passes using an additional find(). Otherwise if there are multiple uls, all lis will be treated as a single collection, and only 3 total list items will be shown. This way we hide() selected items as many times as there are lists.
NOTE: You want your initial query to get down to the list itself.
See :gt() selector documentation.
http://jsfiddle.net/GEbxG/
$('div.listWrapper li').each(function(i, elem) {
if($(elem).index() < 3) return;
$(elem).hide();
});
$('.listWrapper li').show().slice(3).hide();
http://api.jquery.com/slice/
You can remove the .show() if all elements are visible initially.
If you don't already have the jQuery object containing all the li elements and/or don't need access to the full element list, you can avoid selecting them at the first place:
$('.listWrapper ul li:gt(2)').hide();

Categories

Resources