I am trying to loop through some sibling elements one at a time, and I am having trouble separating the process from just running through all matching elements at once. This has to be dynamic, as the list of items will vary and will not always be the same size. Examples below:
<div class="class">
<ul>
<li class="active"></li>
<li></li>
<li></li>
</ul>
</div>
<div class="class">
<ul>
<li class="active"></li>
<li></li>
<li></li>
</ul>
</div>
<div class="class">
<ul>
<li class="active"></li>
<li></li>
<li></li>
</ul>
</div>
The goal is to limit the number of active elements in each list to 1. However, when I loop through the elements using a normal .each() loop, it runs through all of the lists at the same time and limits the total amount to 1 rather then 1 per list. The code is rather simple so far, as I don't have a solution to this problem.
$('.class').find('li').each(function() {
// do something
});
I am curious of the basic task of looping through each of these lists individually and completing the tasks rather then looping through all lists at once. I would rather not create a separate jQuery call for each possible list, and would prefer a single call to handle the task. Any help or ideas would be appreciated, I might be looking past a simple solution.
Use nested loops, one for each list, then loop through the items in that list.
$(".class ul").each(function() {
var active_count = 0;
$(this).find("li").each(function() {
// do something
});
});
Loop your .class than:
$('.class').each(function() {
var $li = $(this).find('li');
// $li is now a collection of n LI elements inside the current .class
$li.each(function () {
// you can use $(this) at this point
});
});
That's how jQuery's .find works, first you searched for elements matching .class, then in all of these you searched for li. You'd have to do something like this:
$('.class').each(function () {
$(this).find('li')...
});
Your code is saying "find all the elements named class. Then loop through the <li>s present".
Try something like:
$('.class').each(function(){
$(this).find(li).each ...
}
Since each div with class ".class" contains a ul with li elements in which you want to have only one set as active, you would need to .each() on your divs and have an inner .each() on your li elements for each div.
$('.class').each(function(i, ele){
$(ele).find('li').each( function(i, ele) {} ); });
This snippet treats each list individually, and stores the first active item. Removes active from every li, then sets the original first active element to active. It also sets the first list item active if no item was active in this list.
$('.class').find('ul').each(function() {
let firstActiveLink = $(this).children('li.active:first');
$(this).children('li').removeClass('active');
if (firstActiveLink.length) {
firstActiveLink.addClass('active');
} else {
$(this).children('li:first-child()').addClass('active');
}
});
.active {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="class">
<ul>
<li class="active"></li>
<li class="active"></li>
<li class="active"></li>
</ul>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<ul>
<li></li>
<li class="active"></li>
<li class="active"></li>
<li></li>
</ul>
<ul>
<li class="active"></li>
<li></li>
<li class="active"></li>
<li></li>
</ul>
</div>
Thank you for all the help! I ended up solving my problem by adding in a data- field and incrementing that field. Using a simple less than if statement to see if the element had more then the correct amount of li's associated with it. If anyone is having a similar situation, let me know if you want to see the code.
Related
I have a menu system that indicated the active item with a class of "selected". Menu items are categorized into groups contained in a div. I'm trying to determine which group number the selected item is in. for example, in the code below it's in the second div group, so I'm trying to return a value of "2". Is this possible?
<div class="nav_group">
<ul>
<li></li>
<li></li>
</ul>
</div>
<div class="nav_group">
<ul>
<li></li>
<li></li>
<li class="selected"></li>
</ul>
</div>
Retrieve the .index() of the .closest() div.nav_group containing the li.selected:
jQuery(function($) {
var index = $('li.selected').closest('.nav_group').index();
console.log(index); // outputs 1 (as 0 is the first)
});
Working JSFiddle
I need some help with getting some items to stay in place in a jquery UI sortable.
I know about JQuery sortable lists and fixed/locked items and it does work quite nicely, the problem is that this works fine if you're not adding items. If you add more items to the sortable you have to call .fixedsortable again and I'd like to avoid that.
Here's an example of my setup:
<ul>
<li></li>
<li class="fixed"></li>
<li></li>
<li class="fixed"></li>
<li></li>
</ul>
I need the "fixed" class to remain in place when sorting.
You can make container element sortable so that you will not have to worry about new elements:
Demo
HTML:
<ul id="container">
<li>1</li>
<li class="fixed">2</li>
<li>3</li>
<li class="fixed">4</li>
<li>5</li>
</ul>
JS:
$("#container").sortable();
I have a List and I want to add a list item before the last one with JQuery:
<ul id="myList">
<li></li>
<li></li>
<li></li>
<-- here i want to add the new one
<li id="myLastLi"></li>
</ul>
How can I achieve that?
As you're using jQuery, you may simply do
$('<li/>', {text:'something'}).insertBefore('#myLastLi');
Demonstration
Note that you don't have to give an ID to the last LI, you could do this without the id :
$('<li/>', {text:'something new'}).insertBefore('#myList li:last-child');
I'm just wondering how to improve this code :
pagination.children('li.active').prev().prev().prev().prev().prevAll('li.pgn').css("display","none");
I just don't like the .prev() chain and I didn't find a way to improve it but I'm sure you know how ;-)
Edit:
pagination is my ul which contains a lot of li with one who has the active class.
I want to select all the li before the li.active but not the first 5 previous one.
Exemple (forget the pgn class):
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li class="active"></li>
That will give this :
<li style="displat: none;"></li>
<li style="display: none;"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li class="active"></li>
You can use :gt() selector.
pagination.children('li.active').prevAll('li:gt(4)').hide();
http://jsfiddle.net/MrvDX/
I think the fact you are doing this this way is indicative of the fact that the design of your page/app can be improved.
Why are you having to find the LI with the active class? Why don't you already know this? Surely it was your app that generated the markup in the first place.
It seems as though you are trying to determine state from markup, which I like to steer away from. You should have an object which tells you which index of LI is selected. Then you can use a much simpler jQ selector to select the indexes you are interested in.
Try this
EDIT
var pagination = $('ul');
var len = pagination.find('li.active').prevAll('li').length;
pagination.find('li.png').slice(0 , len-5).css('display','none');
WORKING FIDDLE
You could try something like this...
var $prevAll = pagination.children('li.active').prevAll('li.pgn');
var prevCount = $prevAll.length;
$prevAll.filter(function(index){
return (prevCount - index < 5)
}).hide() //instead of - .css("display", "none");
using the filter method and passing a function to it.
http://api.jquery.com/filter/
Here's a working example.
http://jsfiddle.net/aTzzK/2/
The following lines of code do two things. The first two lines add classes to the siblings immediately before and after an element with a given id (in this case a UL with id "nav")
The last two lines add the classes first and last to the first and last sibling elements whose parent has the id "nav".
This is jquery. How would I achieve the same with Mootools 1.11. Any help appreciated.
$('#nav .active').prev().addClass('prevtab');
$('#nav .active').next().addClass('nexttab');
$('#nav').children(":first").addClass('first');
$('#nav').children(":last").addClass('last');
formatting doesn't work in comments so repeating for zombat:
Using mootools 1.1
There is no edit button available to me, and I can't comment as I don't have enough rep.
Your solution is doing something, but not targeting the correct element.
This is the result I want and am getting with jquery:
<ul id="nav">
<li class="first"></li>
<li></li>
<li class="prevtab"></li>
<li class="active"></li>
<li class="nexttab"></li>
<li class="last"></li>
</ul>
This is the result of your js:
<div class="prevtab"></div>
<ul id="nav">
<li></li>
<li></li>
<li></li>
<li class="active"></li>
<li></li>
<li></li>
</ul>
<div class="nexttab"><div>
Give this a shot.
$('nav').getNext().addClass('nexttab');
$('nav').getPrevious().addClass('prevtab');
var c = $('nav').getChildren();
c[0].addClass('first');
c[c.length-1].addClass('last');
Edit: Working now.
Second/Third edits:
Ok, I misunderstood the way you're using the .active class. Try this:
var n = $('nav').getElement('.active').getNext();
if (n) n.addClass('nexttab');
var p = $('nav').getElement('.active').getPrevious();
if (p) p.addClass('prevtab');
var c = $('nav').getChildren();
c[0].addClass('first');
c[c.length-1].addClass('last');
$each($$('#nav .active'),function(item){
item.getPrevious().classname='prevtab';
}
);
This is the first line.
Second you can use getNext
Third you can use $('#nav').getFirst //make sure it has children....
Fourth you can use getLast