Jquery CSS- nested <li> 4 levels deep call the parent - javascript

Okay so I am stylizing a dynamic menu so I can't just assign class names or even just html code this.
Here is what I am dealing with:
I need to stylize each parent in something like this:
<div class="menu">
<ul>
<li>
Level 1
<ul>
<li>Level 2</li>
<li>Level 2
<ul>
<li>Level 3</li>
<li>Level 3</li>
<li>Level 3
<ul>
<li>Level 4</li>
<li>Level 4</li>
<li>Level 4</li>
<li>Level 4</li>
</ul>
</li>
</ul>
</li>
<li>Level 2</li>
<li>Level 2</li>
</ul>
</li>
</ul>
</div>
And I need to change all the parents with a jquery afterwards with something like:
jQuery('.menu').find('li.parent').prepend('<i class="icon-plus"></i>');
I need to change all parents with a child menu. How do I do that?
Thanks in advance

This should do the job, if I understand your question correctly:
jQuery('.menu li > ul').parent().prepend('<i class="icon-plus"></i>');
http://jsfiddle.net/Zgaj3/

I think this can work in you situation (li:parent).
jQuery('.menu').find('li:parent').prepend('<i style="" class="icon-plus"></i>');

I am not sure, if I understood your question correctly.
Anyway, the simplest solution to what I think your problem is, would be to iterate through each ul-element following a .menu and check whether the parent is a li-element and apply your styling:
jQuery('.menu').find('ul').each(function(){
if (jQuery(this).parent().is('li'))
jQuery(this).parent().prepend('<i class="icon-plus"></i>');
});

I think you'll need an if statement, something like:
if ($('.menu>ul>li>ul')){
$('.menu>ul').prepend('<i class="icon-plus"></i>');
}
Might have to do one for each level, so:
if ($('.menu>ul>li>ul>li>ul')){
$('.menu>ul>li>ul').prepend('<i class="icon-plus"></i>');
}

// return all li elements inside of the menu class
$('.menu').find('li');
this will find the 4th level and each level after that.
$('.menu').find('ul li ul li ul li ul li').each(function(index, element){
// validate that this is indeed correct
// 4th level elements and deeper
console.log(element);
// do stuff
});
Honestly its better to just use a class when constructing these html elements. Its faster and help other people read the code.

I'm not sure about your requirements, but I think you are feeling difficulty in finding LI elements which contain a UL. The following code will help you find such elements.
$('.menu li>ul').parent().addClass('node')
Now you can do the required operation on this. Please come back if further help required.
Please mark as answer if it helped you.

Related

find next elements but not in order having same class

I want to find elements which have .item class but they are not in order. Below is sample code.
<ul>
<li class="item">list item 1</li>
<li>list item 2</li>
<li>list item 3</li>
<li class="item">list item 4</li>
<li>list item 5</li>
<li class="item">list item 6</li>
</ul>
I want to traverse each li element having only .item class on key-press event. I have tried .nextAll() getting all elements but it takes much time to produce resultsets as I have huge li elements.
var siblingsElements = $('.item').nextAll(); // Takes much time
How can i achieve the result ? Thanks in advance.
Try to rewrite code with Native JS, it works much faster
var items = $('ul')[0].getElementsByClassName('item');
items = $(items);
You can try
$('li.item').each(function(){
--your code here--
})
Because this will find only li having class "item" instead of all dom elements having class "item" which may speed up your process.

How to use jquery to get to previous li

I have the following html:
<li>
Presentation Name
</li>
<li>
Survey Length
</li>
and here is the jquery:
var yolo = $('.not-allowed').first();
yolo.removeClass("not-allowed");
yolo.prev("li").addClass("active");
The first two lines of javascript are working. For some reason, i can't get the last line to work. I'm trying to have the second li tag have the class active, but the class is just not being added anywhere.
There is no previous element for that link. You want to get the parent of the link:
yolo.parent().addClass("active");
Ref: .parent()
jsFiddle example
Note that you could also use .closest('li') instead of .parent().
You want parent() not prev().
.prev() queries only the siblings of the element, and .not-allowed has none. In order to use .prev() you'd need to call .parent() to get the list item element the anchor is within:
yolo.parent().prev("li").addClass("active");
Edit: I'm an idiot
Have a look at this with the example. I think this answers your question: https://api.jquery.com/prev/
Markup
<ul>
<li>list item 1</li>
<li>list item 2</li>
<li class="third-item">list item 3</li>
<li>list item 4</li>
<li>list item 5</li>
</ul>
JQuery
$( "li.third-item" ).prev().css( "background-color", "red" );
I made a JSFiddle here: https://jsfiddle.net/ToreanJoel/nq6efza9/

Parallel element selector

We have the following situation:
<ul>
<li>Button 1</li>
<li class="active">Button 2</li>
<li>Button 3</li>
<li>Button 4</li>
</ul>
now the following code that handles it:
$('.tab-menu li').on('click', function() {
$($($(this).closest('.tab-menu')).find('li')).removeClass('active');
$(this).addClass('active');
});
it works, but is there a jQuery function that selects all 'parallel' elements ? I want this
part
$($($(this).closest('.tab-menu')).find('li')).removeClass('active');
make shorter. I know 'toggleClass', but this works only on the clicked element. Is there any shorter method to select all parallel elements? (In this siutation all 'li' that belongs to the specific 'ul');
Try this, using .siblings()
$(this).addClass('active').siblings().removeClass('active');
DEMO with onclick

Toggling list, clicking on item shows all subitems instead of only subitems from item

Sorry for the vague title, but I couldn't find an appropriate title, explaining the problem well.
The problem: I wrote a code that toggles lists. It works the way I want it. When I click on the the 'headcategory' it opens the subcategories, etc. The problem occurs when I click on the headcategory for the first time, it opens every list, which is not what I want. When I close and open it again, it works the way it should be. I'm trying to figure out why it does that, but I've no clue. So if someone could help me, he/she would be greatly appreciated.
JQuery code.
$(document).ready(function()
{
$('ul.subcat').hide();
$('li').click(function(event)
{
event.stopPropagation();
$('ul', this).toggle();
});
});
HTML code
<ul class="headcat">
<li>item 1
<ul class="subcat">
<li>subitem 1
<ul class="subcat">
<li>subsubitem 1
<ul class="subcat">
<li><p>text</p></li>
</ul>
</li>
<li>subsubitem 2
<ul class="subcat">
<li><p>text</p></li>
<li>subsubsubitem 1
<ul class="subcat">
<li><p>text</p></li>
</ul>
</li>
<li>subsubsubitem 2</li>
</ul>
</li>
</ul>
</li>
<li>item 2</li>
</ul>
</li>
</ul>
You need to only select direct descendants of the currently clicked li, try this:
$(this).children("ul").toggle();
The following will also work, however it's not considered best practice to use the > descendant selector without a primary element before it.
$('> ul', this).toggle();
Example fiddle
Or try to hide the first subcat only on init:
$('ul.subcat:first').hide();
DEMO here: http://jsfiddle.net/kv4dT/

Find the last child or grandchild in a UL

I have a CMS generating a basic navigation using a UL. Each first-level LI is styled to be a group. I need to apply a style to the last element within each of the first level LI "groups". Meaning; if a first-level LI has no children, I want to apply a style to it (as the "bottom" of the group); if it does have children, I want to find the last child OR grandchild element that appears (again, the "bottom" of the group). I have used both CSS and Javascript "last" classes, and have successfully applied styles to the last child of a certain depth within the first-level LI, but that isn't helpful since the bottom button of the list is of an unknown depth.
My line of thinking involves a IF statement that finds the last child of the first level, checks if it has children, and if it does, go another level deep and find that last child and checks for children, repeating this process until it finds the last LI that does not have children within the first-level LI groups. However, I am a JS noob and am not sure how to go about that.
I am open to CSS or JavaScript/jQuery solutions. I have been banging my head on this one for a while and appreciate any input or better ideas. Thanks for your help!!
--
Update: here's a code sample of what I am hoping for:
<ul id="navigation>
<li>Item one</li> <!--Style this one-->
<li>Item Two
<ul>
<li>Item Two-One</li>
<li>Item Two-Two</li> <!--Style this one-->
</ul>
<li>
<li>Item Three
<ul>
<li>Item Three-One</li>
<li>Item Three-Two
<ul>
<li>Item Three-Two-One</li>
<li>Item Three-Two-One</li> <!--Style this one-->
</ul>
</li>
</ul>
<li>
<li>Item Four
<ul>
<li>Item Four-One</li>
<li>Item Four-Two
<ul>
<li>Item Four-Two-One</li>
<li>Item Four-Two-One</li>
</ul>
</li>
<li>Item Four-Three</li> <!--Style this one-->
</ul>
<li>
</ul>
The reason the .last selector doesn't work is because, in the above example, it would style item Four-Two-One since it is the last element of its UL.
To clean up my answer, incase this is read at a later date.
here is my solution to your problem:
var checkChildren = function($this) {
if (!$this.children().length) {
$this.css({
color: '#f00',
fontWeight: '700',
textDecoration: 'underline'
});
return false;
}
return true;
};
$("#navigation").children("li").each(function() {
$these = $(this);
while (checkChildren($these)) {
$these = $these.children().last() || $these.next();
}
});
I think this is what you want. It's part of the jQuery API.
http://api.jquery.com/last/
HTML
<ul>
<li>list item 1</li>
<li>list item 2</li>
<li>list item 3</li>
<li>list item 4</li>
<li>list item 5</li>
</ul>
jQuery
$('li').last().css('background-color', 'red');
EDIT:
Okay I figured out a way for you to do it.. the only caveat is that you need to be able to set a class for the first level of <li>'s. I've posted my findings here:
http://jsfiddle.net/TTXch/54/
It selects the last of the <li>'s for each main navigation element. Your posted structure was a little off... the end tags didn't all match up. Anyway, check out the jQuery in the javascript window in the jsFiddle.
You should be able to use the jQuery last selector for this (http://api.jquery.com/last-selector/).

Categories