I just started working with jQuery and I'm running into a bit of a snag with iterating through each parent UL's list items.
I have a simple accordion menu where I'm adding transition-delay inline style to each individual list item. The issue I have is that I'm not sure how to iterate through each set of parent's list items.
Below is an example of what is occurring on every list item.
<ul class="sub-menu">
<li style="transition-delay: 0ms;></li>
<li style="transition-delay: 25ms;>
<ul class="sub-menu">
<li style="transition-delay: 50ms;>
<li style="transition-delay: 75ms;>
<li style="transition-delay: 100ms;>
</ul>
</li>
<li style="transition-delay: 125ms;></li>
<li style="transition-delay: 150ms;></li>
<li style="transition-delay: 175ms;></li>
</ul>
This is what I'm looking to achieve:
<ul class="sub-menu">
<li style="transition-delay: 0ms;></li>
<li style="transition-delay: 25ms;>
<ul class="sub-menu">
<li style="transition-delay: 0ms;>
<li style="transition-delay: 25ms;>
<li style="transition-delay: 50ms;>
</ul>
</li>
<li style="transition-delay: 50ms;></li>
<li style="transition-delay: 75ms;></li>
<li style="transition-delay: 100ms;></li>
</ul>
This is what my jQuery looks like:
$('ul.mobile-menu li.menu-item-has-children ul.sub-menu li').each(function(i){
$(this).css({ 'transition-delay': (i*25)+"ms" });
});
Any help would greatly be appreciated as I am just getting started with jQuery. I created a codepen so you can see the menu in action and visually see the issue.
http://codepen.io/creativenauts/pen/wGLqPg
Here is my approach:
$('.sub-menu').each(function() {
// $(this) = single ul element
$(this).children('li').each(function(idx, el){
// idx = index of current list [0 ... number]
// $(el) = single li element
$(el).css('transition-delay', (idx * 25) + 'ms');
});
});
But in this use case (w.r.t. the size of the list) you can and should use CSS, something like this.
You could use .index(), which gives an element's position among its siblings:
$('ul.mobile-menu li.menu-item-has-children ul.sub-menu li').each(function(){
$(this).css({ 'transition-delay': ($(this).index()*25)+"ms" });
});
Like this:
$('ul.mobile-menu li.menu-item-has-children ul.sub-menu').each(function(j, subMenu){
$(subMenu).children('li').each(function(i, li){
$(li).css('transition-delay', (i*25)+'ms')
})
});
Related
Hello so I have this problem, I use magento and my I can't find a place how to switch my tabs in position so I thought JQuery could come in hand. So this is what i have as an example
<li id="tab-4">
<li id="tab-3">
<li id="tab-2">
<li id="tab-1">
And i need to make it
<li id="tab-1">
<li id="tab-2">
<li id="tab-3">
<li id="tab-4">
Is there a fast way to do it? Or I have to do it one by one?
I guess you have an <ul> around you <li>
ul = $('ul'); // your parent ul element
ul.children().each(function(_,li){ul.prepend(li)})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="tab-4">4</li>
<li id="tab-3">3</li>
<li id="tab-2">2</li>
<li id="tab-1">1</li>
</ul>
Pure JS solution.
var a = document.getElementsByTagName('li');
var b = document.getElementById('list');
var arr = [];
Array.from(a).forEach(v => arr.push(v));
arr.reverse().forEach(v => b.append(v));
<ul id='list'>
<li id="tab-4">4</li>
<li id="tab-3">3</li>
<li id="tab-2">2</li>
<li id="tab-1">1</li>
</ul>
Also, for a sollution working (actually sorting) regardless of the initial order you can use sort() and append like this:
$("ul li").sort(function(a,b){
if(a.id.substring(4, 5) < b.id.substring(4, 5)) {
return -1;
} else {
return 1;
}
}).each(function() { $('ul').append(this);});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="tab-4">4</li>
<li id="tab-1">1</li>
<li id="tab-3">3</li>
<li id="tab-2">2</li>
</ul>
$(".list > li").detach().sort(function(a, b) {
return +a.id.replace("tab-","") - b.id.replace("tab-","") ;
}).appendTo("ul.list");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li id="tab-3">3
<li id="tab-4">4
<li id="tab-2">2
<li id="tab-1">1
</ul>
If your HTML code like this you can write your code using detach and a single appendTo like this.
More about detach(): https://www.w3schools.com/jquery/html_detach.asp
I'm trying to replace two divs that has separate ul elements into a single one, so I can create a single ul with the li of both, but my current code creates separate ul, and that is not my intended purpose, could anyone enlighten me on how to make the proper selection for these:
my jQuery
$('nav div.moduletable_gfbb_navigationbar, nav div.moduletable_menu_navigationbar').replaceWith(function(){
var html = '<ul class="nav navbar-nav navbar-right">';
$(' ul',this).each(function(){
html += $(this).html();
});
html+='</ul>';
return html;
});
my HTML
<div class="moduletable_menu_navigationbar">
<ul class="menu">
<li id="current" class="active item8"><span>Banca Personas</span></li>
<li class="item9"><span>Banca Pyme</span></li>
<li class="item10"><span>Banca Empresas</span></li>
<li class="item602"><span>Bankard</span></li>
</ul>
</div>
<div class="moduletable_gfbb_navigationbar">
<ul class="menu">
<li class="item12"><span>Informacion Institucional</span></li>
</ul>
</div>
And the output I get (not what I want)
<ul class="nav navbar-nav navbar-right">
<li class="item12"><span>Informacion Institucional</span></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li id="current" class="active item8"><span>Banca Personas</span></li>
<li class="item9"><span>Banca Pyme</span></li>
<li class="item10"><span>Banca Empresas</span></li>
<li class="item602"><span>Bankard</span></li>
</ul>
What I want is a single 'ul', I know I can recode it, but I'm trying to use the less code posible.
Your example does not include a <nav> tag which may be the primary cause of your problem, but to produce more readable code I would do it like this.
I used an array for the selectors, because it aids in readability and maintainability. It also allows you to easily insert the new list before the first menu by using only the first selector, whatever that may be.
Basically I select all of the <li> elements descending from the selectors and move those to the newlist. Then insert the new list before the first list div. Then remove the old lists.
var selectors = [
'nav div.moduletable_gfbb_navigationbar',
'nav div.moduletable_menu_navigationbar'
], selectorText = selectors.join(', ');
var newList = $('<ul class="nav navbar-nav navbar-right">');
$('li', selectorText).each(function(){ newList.append(this); });
$(selectors[0]).before(newList);
$(selectorText).remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div class="moduletable_menu_navigationbar">
<ul class="menu">
<li id="current" class="active item8"><span>Banca Personas</span></li>
<li class="item9"><span>Banca Pyme</span></li>
<li class="item10"><span>Banca Empresas</span></li>
<li class="item602"><span>Bankard</span></li>
</ul>
</div>
<div class="moduletable_gfbb_navigationbar">
<ul class="menu">
<li class="item12"><span>Informacion Institucional</span></li>
</ul>
</div>
</nav>
$('.moduletable_menu_navigationbar .menu').append($('.moduletable_gfbb_navigationbar .menu').html());
$('.moduletable_gfbb_navigationbar').remove();
Is this what you are looking for!!
I'm currently searching for a solution for sorting a nested list with Tinysort.js
My HTML
<ul class="speechlev1">
<li data-title="indo-european" data-ratio="48">Indo-European
<ul class="speechlev2">
<li data-title="albanian" data-ratio="100">Albanian</li>
<li data-title="armenian" data-ratio="75">Armenian</li>
<li data-title="balto-slavic" data-ratio="75">Balto-Slavic</li>
<li data-title="celtic" data-ratio="34">Celtic</li>
<li data-title="germanic" data-ratio="78">Germanic</li>
<li data-title="greek-phrygian" data-ratio="23">Greek-Phrygian</li>
<li data-title="tokharian" data-ratio="0">Tokharian</li>
</ul>
</li>
<li data-title="nilo-saharan" data-ratio="43">Nilo-Saharan</li>
<li ata-title="sepik" data-ratio="42">Sepik</li>
<li data-title="sino-tibetan" data-ratio="28">Sino-Tibetan
<ul class="speechlev2">
<li data-title="chinese" data-ratio="13">Chinese</li>
<li data-title="tibeto-burman" data-ratio="34">Tibeto-Burman</li>
</ul>
</li>
<li data-title="uto-aztecan" data-ratio="60">Uto-Aztecan</li>
</ul>
Javascript
$(document).ready(function() {
tinysort('.speechlev2>li',{attr:'data-ratio'});
});
Result:
Indo-European
Tokharian
Chinese
Greek-Phrygian
Celtic
Tibeto-Burman
Armenian
Balto-Slavic
Nilo-Saharan
Sepik
Sino-Tibetan
Germanic
Albanian
Uto-Aztecan
Should be:
Indo-European
Tokharian
Greek-Phrygian
Celtic
Armenian
Balto-Slavic
Germanic
Albanian
Nilo-Saharan
Sepik
Sino-Tibetan
Chinese
Tibeto-Burman
Uto-Aztecan
I have set up a CodePen to show my problem:
http://codepen.io/anon/pen/QbPVox
My problem is that tinysort sorts the li also between different parents. How can I fix that
Can somebody help me with that?
Just sort each of your lists separately:
$(document).ready(function() {
$('.speechlev2').each(function() {
tinysort($('li', this), {attr:'data-ratio'});
});
});
Let's say I have a list of items under a div or UL. I want to take all the list items with the same title attribute and wrap a UL around it. The next part though is that I want that UL to be under the LI with the same attribute. So, I'm trying to group basically.
So.... I start with.....
<li>Insurance</li>
<li>Education</li>
<li>Sports</li>
<li>Construction</li>
<li title ="Insurance">Malpractice</li>
<li title ="Construction">Carpentry</li>
<li title ="Education">College</li>
<li title ="Insurance">Automobile</li>
<li title ="Education">High School</li>
<li title ="Construction">Iron Worker</li>
and I want to get to......
<li>Insurance
<ul>
<li title ="Insurance">Malpractice</li>
<li title ="Insurance">Automobile</li>
</ul>
</li>
<li>Education
<ul>
<li title ="Education">College</li>
<li title ="Education">High School</li>
</ul>
</li>
<li>Sports</li>
<li>Construction
<ul>
<li title ="Construction">Carpentry</li>
<li title ="Construction">Iron Worker</li>
</ul>
</li>
Any help would be appreciated. Obviously new to the jquery and javascript world so I'm trying to wrap my brain around this.
Input:
<div id="stuffs">
<li>Insurance</li>
<li>Education</li>
<li>Sports</li>
<li>Construction</li>
<li title ="Insurance">Malpractice</li>
<li title ="Construction">Carpentry</li>
<li title ="Education">College</li>
<li title ="Insurance">Automobile</li>
<li title ="Education">High School</li>
<li title ="Construction">Iron Worker</li>
</div>
jQuery:
$("#stuffs li").each(function(){
$("#stuffs li[title='"+$(this).text()+"']").appendTo($(this)).wrapAll("<ul />");
});
Output:
<div id="stuffs">
<ul>
<li>Insurance
<ul>
<li title="Insurance">Malpractice</li>
<li title="Insurance">Automobile</li>
</ul>
</li>
<li>Education
<ul>
<li title="Education">College</li>
<li title="Education">High School</li>
</ul>
</li>
<li>Sports</li>
<li>Construction
<ul>
<li title="Construction">Carpentry</li>
<li title="Construction">Iron Worker</li>
</ul>
</li>
</ul>
</div>
Smile :-)
Demo here
// first we fetch all items without title attribute
var topLevel = $('li:not([title])');
// for each of those...
topLevel.each(function() {
var li = $(this),
// ... we get its text ...
title = li.text(),
// ... and other li elements with the corresponding title
children = $('li[title="' + title + '"]');
// if there are any...
if (children.length > 0) {
// ... create an empty list ...
var ul = $('<ul></ul>');
// ... fill it and ...
children.appendTo(ul);
// ... append it to the original li element
ul.appendTo(li);
}
});
jQuery documentation: :not(), [title], each(), appendTo()
This should work
$('#id li:not([title])').append('<ul />');
$('#id li[title]').each(function() {
$(this).appendTo('#id li:contains(' + $(this).attr('title') + ') ul');
})
A demo
I have a drop-down menu that are dynamically added through WordPress. It looks like this:
Pictures
Sea
Forest
City
"Sea", "Forest" and "City" is categories with "Pictures" as parent category.
My question is:
How do I make the "Pictures" category unclickable?
I did this with jQuery:
$(document).ready(function(){
//Make parent links unclickable
$(".page-item-3").click(function(){
return false;
});
});
...and this with CSS:
li.page-item-3 a {
cursor:default;
}
.page-item-3 ul li a {
cursor: pointer;
}
Markup looks like this:
<div id="menu" class="jqueryslidemenu">
<ul>
<li class="cat-item cat-item-1 current_page_item">Blabla</li>
<li class="page_item page-item-2">Blabla
<ul>
<li class="page_item page-item-28">Blabla</li>
<li class="page_item page-item-30">Blabla</li>
<li class="page_item page-item-39">Blabla</li>
</ul>
</li>
<li class="page_item page-item-3">Blabla
<ul>
<li class="page_item page-item-5">Blabla 1</li>
<li class="page_item page-item-7">Blabla 2</li>
<li class="page_item page-item-9">Blabla 3</li>
<li class="page_item page-item-11">Blabla 4</li>
<li class="page_item page-item-13">Blabla 5</li>
</ul>
</li>
<li class="page_item page-item-15">Blabla
<ul>
<li class="page_item page-item-222">Blabla</li>
<li class="page_item page-item-224">Blabla</li>
<li class="page_item page-item-226">Blabla</li>
</ul>
</li>
<li class="page_item page-item-17">Blabla</li>
<li class="page_item page-item-36">Blabla</li>
</ul>
</div>
This almost works But the jQuery code makes all the drop-down links unclickable too.
It would be great if anyone knows how to remove the status bar url while hover the "Pictures" link. But I don't think that is possible to make in moderns browsers such as Safari och Firefox?
Thanks!
I don't know what control you have because of Wordpress but you're having this problem because everything is contained in the title list item (page-item-3) and you're cancelling the click on this item. If you can apply a class to the title link itself, you can apply the jQuery to that directly.
Unfortunately you can't say ".page-item-3 a" because this apply to all links in the list.
Re-Edit - This should select the first link in the list and cancel the click value of that. You may need to apply this for each 'title' link you have.
$(".page-item-3 a:first").click(function() {
return false;
}
$(".page-item-3").children("a").click(function(e) {
e.preventDefault();
});
*****or with CSS*****
.unclickable {
z-index:-1;
}
$(".page-item-3").children("a").addClass("unclickable");
just replace the href attribute value with #. That way when the user clicks on it, the page goes to #, which is the same page they are on, and nothing happens. Keep the CSS you wrote so the hand pointer does not appear when they hover it, but remove the jQuery code.
Using jQuery:
$(".page-item-3>a").attr("href", "#")
Try this:
$(document).ready(function(){
//Make parent links unclickable
$("div > ul > li > a").click(function(){
return false;
});
});
This will disable all the first links in your list without needing the class name.
I use this :
$j = jQuery.noConflict();
$j(document).ready(function(){
//Make parent links unclickable
$j("div[id='nav'] > ul > li > a ").removeAttr("href");
});