I have the following HTML
<ul>
<li><a ...>item 1</a></li>
<li>item 2
<ul>
<li><a ...>item 2-a</a></li>
<li><a ...>item 2-b</a></li>
</ul>
</li>
<li><a ...>item 3</a></li>
<li>item 4
<ul>
<li><a ...>item 4-a</a></li>
<li><a ...>item 4-b</a></li>
</ul>
</li>
<li><a ...>item 5</a></li>
<li><a ...>item 6</a></li>
</ul>
I want to add a class to 'item 2' and 'item 4' with jquery using .has but can't find a way.
I want to clarify my question:
I have a nested list with an unknown amount of items where some items are not linked. I want to add a class to all unliked items.
If you want to add the class depending to the content of the li you could use :contains selector :
$( "li:contains('item 2')" ).addClass('X');
Or filter and check text() content :
$( "li" ).filter(function(){
return $(this).text()==='item 4';
}).addClass('X');
If you want to add class using the index's use .eq() like Robiseb's answer show.
EDIT :
I don't know how many <li> without a link will be in the list. And I don't know what the text inside the <li> will be.
You could use :
$("li:not(:has(>a))").addClass('X');
Hope this helps.
$("li:not(:has(>a))").addClass('X');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a ...>item 1</a></li>
<li>item 2
<ul>
<li><a ...>item 2-a</a></li>
<li><a ...>item 2-b</a></li>
</ul>
</li>
<li><a ...>item 3</a></li>
<li>item 4
<ul>
<li><a ...>item 4-a</a></li>
<li><a ...>item 4-b</a></li>
</ul>
</li>
<li><a ...>item 5</a></li>
<li><a ...>item 6</a></li>
</ul>
Only selecting for list items without anchors, as clarified in the questions comments.
var parentList = $('ul'); // something more specific is assumed.
parentList.children('li').children().not('a').parent().addClass('some-class');
Using "contains" makes the solution dependent on content, not structure. Using "eq" or similar "nth"-like functionality is assuming that the given example is the only structure, whereas I think it is planned as generated code that may extend to a much longer length, but will always keep the structure defined in the snippet.
Try using .eq() documentation
$('li').eq(1).addClass('yourClass');
Be careful, eq starts to 0
Based on comments you want to check if it has a sub <ul>
$('li').has('ul').addClass('has-children');
// OR
$('li:has(ul)').addClass('has-children');
You can select item by your content, using :contains() selector
For more details: https://api.jquery.com/contains-selector/
Example: http://jsbin.com/nutekaxora/edit?html,css,js,output
$("li:contains('Item 1')").addClass('myClass');
Probably not the best way to do this, but use the "eq" method for this.
var first = $("ul").first();
$(first).find("li").eq(1).addClass("newClass"); /// This selects the second list item
$(first).find("li").eq(5).addClass("newClass"); // This selects the sixth list item
Here's a pen for this to show it in action.
http://codepen.io/raghavkanwal/pen/XjLjJM
Do you mean to detect all 'li' with 'ul' as a children?
https://jsfiddle.net/Ln3kt6ya/
May this example help you?
$('li').has('ul').addClass('error');
<style>
ul {color: #777777;}
ul.items-list {color: #880000;}
.your-class-name {color: #008800;}
</style>
<body>
<ul class="items-list">
<li><a>item 1</a></li>
<li>item 2
<ul>
<li><a>item 2-a</a></li>
<li><a>item 2-b</a></li>
</ul>
</li>
<li><a>item 3</a></li>
<li>item 4
<ul>
<li><a>item 4-a</a></li>
<li><a>item 4-b</a></li>
</ul>
</li>
<li><a>item 5</a></li>
<li><a>item 6</a></li>
</ul>
</body>
<script>
var $list = $('ul.items-list');
$list.children('li:nth-child(2), li:nth-child(4)').addClass('your-class-name');
</script>
Related
I have a menu like this on my WordPress site:
<ul id="menu-main-menu" class="clearfix"><li id="menu-item-397" class="menu-item-397">About us</li>
<li id="menu-item-1001" class="menu-item-object-custom menu-item-has-children has-dropdown menu-item-1001">OFFER
<ul class="nav-dropdown">
<li id="menu-item-454" class="not_on_mobile menu-item-has-children has-dropdown menu-item-454">PROBLEM
<ul class="nav-dropdown">
<li id="menu-item-1569" class="menu-item-1569">Test</li>
<li id="menu-item-1572" class="menu-item-1572">Test</li>
</ul>
</li>
<li id="menu-item-1063" class="not_on_mobile menu-item-has-children has-dropdown menu-item-1063">PROBLEM
<ul class="nav-dropdown">
<li id="menu-item-1242" class="menu-item-1242">Test</li>
<li id="menu-item-1243" class="menu-item-1243">Test</li>
</ul>
</li>
<li id="menu-item-508" class="not_on_mobile menu-item-has-children has-dropdown menu-item-508">PROBLEM
<ul class="nav-dropdown">
<li id="menu-item-670" class="menu-item-670">Test</li>
<li id="menu-item-1133" class="menu-item-1133">Test</li>
<li id="menu-item-1427" class="menu-item-1427">Test</li>
</ul>
</li>
<li id="menu-item-673" class="menu-item-673">Ortodoncja</li>
<li id="menu-item-443" class="not_on_mobile menu-item-object-custom menu-item-has-children has-dropdown menu-item-443">PROBLEM
<ul class="nav-dropdown">
<li id="menu-item-1820" class="menu-item-1820">Test</li>
</ul>
</li>
<li id="menu-item-1160" class="menu-item-object-custom menu-item-1160">Test</li>
<li id="menu-item-741" class="menu-item-741">Test</li>
</ul>
</li>
<li id="menu-item-523" class="menu-item-523">Test</li>
</ul>
The problem is that on mobile, when I click on elements that I called PROBLEM, the URL is triggered and it expands another level of menu but in the same time enters an url I just clicked.
I thought that the fix for this could be to replace this PROBLEM URL's by a link like #menu_on_mobile
All of those PROBLEM url's are the first 'a' items in li which has a 'not_on_mobile' class.
I tried to do it like this:
document.querySelectorAll(".not_on_mobile a:first-child").forEach(a => a.setAttribute('href', '#menu_on_mobile'));
But the problem is that it replaces URL in all 'a' element in not_on_mobile class.
How to edit it to replace only the first element in 'li' and work only on mobile?
Try to select the items this way .not_on_mobile>a. In this way, only the first elements will be selected without taking all the children's elements inside.
I hope I understood the task correctly
document.querySelectorAll(".not_on_mobile>a").forEach(a => a.setAttribute('href', '#menu_on_mobile'));
Say I have an unordered list, like so:
Demo
HTML Code:
<ul class="nav_accordian">
<li>One
<ul>
<li>on 1.1</li>
<li>on 1.2</li>
<li>on 1.3</li>
</ul>
</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
<li>One 1</li>
<li>Two 2</li>
<li>Three 3</li>
<li>Four 4</li>
<li>Five 5</li>
<li>One 11</li>
<li>Two 22</li>
<li>Three 33</li>
<li>Four 44</li>
<li>Five 55</li>
</ul>
Script File :
$('.nav_accordian').each(function(){
var max = 4
if ($(this).find('li').length > max) {
$(this).find('li:gt('+max+')').hide().end().append('<li class="sub_accordian"><span class="showMore">show More</span></li>');
$('.sub_accordian').click( function(){
$(this).siblings(':gt('+max+')').toggle();
if ( $('.show_more').length ) {
$(this).html('<span class="showMore">show More</span>');
}
else {
$(this).html('<span class="showMore">less More</span>');
};
});
};
});
i did for when i click on 'show more' it should be visible all the results of list items . Once every results loaded 'show more' text would be changed on 'less more'.
and when i clicked upon the 'less more' button first five results result items should be visible other items would be hide.
The issue is the script is consider only direct child list of i did for when i click on 'show more' it should be visible next five results of list items . Once every results loaded 'show more' text would be changed on 'less more'.
and when i clicked upon the 'less more' button first results result items should be visible other items would be hide.
but my script is consider li child ul also but i dont want
i am expected output as:
one
two
three
four
five
Show more
Try to use the > child selector whenever you want to target the first level children.
if ($(this).find('> li').length > max) {
//----------------^
$(this).find('> li:gt('+max+')').hide().end().append('<li ....
//--------------------^
DEMO
From your explanation I get confused... but as a contribution, this is the code I did...
HTML:
<ul class="nav_accordian">
<li>One
<ul>
<li>on 1.1</li>
<li>on 1.2</li>
<li>on 1.3</li>
</ul>
</li>
<li>Two
<ul>
<li>on 2.1</li>
<li>on 2.2</li>
<li>on 2.3</li>
</ul>
</li>
<li>Three
<ul>
<li>on 3.1</li>
<li>on 3.2</li>
<li>on 3.3</li>
</ul>
</li>
</ul>
*Sorry about the indentation.
jQuery:
$('.nav_accordian > li').each(function(){
$(this).children('ul').hide();
$(this).append('<li class="sub_accordian"><span class="showMore">show More</span></li>');//.children().hide();
});
$(document).on('click','.sub_accordian', function(){
$(this).siblings().toggle();
if ( $('.show_more').length ) {
$(this).html('<span class="showMore">show More</span>');
}
else {
$(this).html('<span class="showMore">less More</span>');
}
});
Trying to make javascript horizontal menu, but can't get second button to open its own items, (when i click the second button it opens the items that are for the first button) here is current code:
JavaScript:
$(document).ready(function() {
$(".menu-button,.menu-button1").click(function() {
$(".menu-bar").toggleClass("open");
});
})
HTML:
<ul class="menu">
<li title="home">menu</li>
<li title="pencil">pencil</li>
<li title="about">about</li>
</ul>
<ul class="menu-bar">
<li>Menu0</li>
<li>Home2000</li>
<li>About</li>
<li>Parent</li>
<li>About</li>
</ul>
<ul class="menu-bar">
<li>Menu1</li>
<li>About</li>
</ul>
Before I start my answer, let me explain jQuery a bit.
$(".menu-button,.menu-button1").click(function() {
$(".menu-bar").toggleClass("open");
});
This broken down:
$(".menu-button,.menu-button1").click(function() { -> When any item with class menu-button OR class menu-button1 is clicked
$(".menu-bar").toggleClass("open"); ->Toggle the "open" class for all elements in your page with class menu-bar.
Since you call all the menus instead of the specific one you want, it opens both of them.
So, be more specific by - for starters - using IDs, or unique/identifying classes:
JS:
$(document).ready(function() {
$(".menu-button.home").click(function() {
$(".menu-bar.home").toggleClass("open");
});
$(".menu-button.pencil").click(function() {
$(".menu-bar.pencil").toggleClass("open");
});
})
HTML:
<ul class="menu">
<li title="home">menu</li>
<li title="pencil">pencil</li>
<li title="about">about</li>
</ul>
<ul class="menu-bar home">
<li>Menu0</li>
<li>Home2000</li>
<li>About</li>
<li>Parent</li>
<li>About</li>
</ul>
<ul class="menu-bar pencil">
<li>Menu1</li>
<li>About</li>
</ul>
I agree with M.Doye's comment about using .each (but sorry, I can't answer directly).
I want to add that, it will be much easier with that kind of HTML structure I think:
<ul class="menu">
<li title="home">
Show Menu 1
<ul class="menu-bar">
<li>Menu1
</li>
</ul>
</li>
<li title="pencil">
Show Menu 2
<ul class="menu-bar">
<li>Menu2
</li>
</ul>
</li>
</ul>
The, click on the link and use .next() or .siblings or closest... to show the right ul.
But of course you'll have to rewrite you CSS :)
Here is updated code
$(document).ready(function () {
$(".menu-button,.menu-button1").click(function () {
$(this).siblings(".menu-bar").toggleClass("open");
})
})
<ul class="menu">
<li title="home">menu
<ul class="menu-bar">
<li>Menu1</li>
<li>About</li>
</ul>
</li>
<li title="pencil">pencil
<ul class="menu-bar">
<li>Menu0</li>
<li>Home2000</li>
<li>About</li>
<li>Parent</li>
<li>About</li>
</ul>
</li>
</ul>
here is a jsfiddle
I'm using the fabulous UI Bootstrap for Angular but am having difficulty getting an onclick event raised.
Here is the code:
<ul class="dropdown-menu" role="menu">
<li><a><img src='/Content/Images/dept_cargo.png'/> CARGO</a></li>
<li><a><img src='/Content/Images/dept_commercial.png'/> COMMJ</a></li>
<li><a><img src='/Content/Images/dept_executive.png'/> EXECJ</a></li>
<li><a><img src='/Content/Images/dept_travel.png'/> TVL</a></li>
</ul>
{{ currentDepartment }}
I've tried every combination: putting the ng-click="behaviour()" variously inside the li, the a and the img, but nothing seems to work.
What am I doing wrong?
(ideally I'd just like to change the value of a scope variable but I'm thinking calling a behaviour to do the work is better practice)
This question is not the same as suggested above. The other question is to do with scope, whereas I would be happy just to be able to execute an alert(); from one of my li's.
You must have an issue in the js code where you set up the controller but if you set it up right, your html should look like this:
<ul class="dropdown-menu" role="menu">
<li ng-click="behaviour()"><a><img src='/Content/Images/dept_cargo.png'/> CARGO</a>
</li>
<li ng-click="behaviour()"><a><img src='/Content/Images/dept_commercial.png'/> COMMJ</a>
</li>
<li ng-click="behaviour()"><a><img src='/Content/Images/dept_executive.png'/> EXECJ</a>
</li>
<li ng-click="behaviour()"><a><img src='/Content/Images/dept_travel.png'/> TVL</a>
</li>
</ul>
and in your js:
function myCtrl($scope) {
$scope.behaviour = function () {
alert('asd');
};
}
and here is a working sample: http://jsfiddle.net/97u2jp6d/1/
<ul class="dropdown-menu" role="menu">
<li><a ng-click="behaviour()"><img src='/Content/Images/dept_cargo.png'/> CARGO</a></li>
Make sure you have $scope.behaviour = function() {} defined inside of the controller for that code snippet.
You don't need more than this:
HTML
<ul>
<li ng-click="doSomething()">item 1</li>
<li ng-click="doSomething()">item 2</li>
<li ng-click="doSomething()">item 3</li>
<li ng-click="doSomething()">item 4</li>
<li ng-click="doSomething()">item 5</li>
</ul>
Controller
$scope.doSomething = function () {
console.log('doing something');
}
http://plnkr.co/edit/52C2daC9jugCOOaNBDvP
I have two navigations and i want the browser to load #informals-1 by default on page load. How can I do that using javascript? I have a code to navigate between the -nav and -subnav, but the #informals-1 section is not activated by default. I have to click on the informals-1 anchor to get the subnav under it.
Before activation - this
After activation - this
<nav id="documentation-nav">
<ul>
<li><span>1</span>Informals
</li>
<li><span>2</span>Tech Events</li>
</ul>
</nav>
<nav id="documentation-subnav">
<ul id="informals">
<li><a href="#informals-1" >Tic Toc</a></li>
<li><a href="#informals-2" >Jack of all Trades</a></li>
<li><a href="#informals-3" >Tattoo making</a></li>
<li><a href="#informals-4" >Face painting</a></li>
<li><a href="#informals-5" >Foosball</a></li>
<li><a href="#informals-6" >Solo Impromptu</a></li>
<li><a href="#informals-7" >Challenge accepted</a></li>
<li><a href="#informals-8" >Sack Race</a></li>
<li><a href="#informals-9" >Connected</a></li>
<li><a href="#informals-10" >Mystery date</a></li>
<li><a href="#informals-11" >The 90's Game</a></li>
</ul>
<ul id="techevents">
<li>name1</li>
<li>name1</li>
<li>name1</li>
<li>name1</li>
<li>name1</li>
</ul>
You can do something like the following.
Give the li an id
<li id="yourId"><a href="#informals-1" >Tic Toc</a></li>
then have the window scroll to 500 pixels from top. Change 500 to whatever amount is correct for you.
document.getElementById('yourId').style.display = 'block';
window.scrollTo(0, 500);