How to find the 2nd closest ancestor in jQuery? - javascript

My DOM looks something like this:
<li>
<li><a class="editEntity>Edit</a></li>
<li><a class="deleteEntity>Delete</a></li>
</li>
When the used clicks on 'Edit', I want to change the outer <li> to <li class="selected>.
I tried something like this, but this is not working:
$('li a.editEntity').live('click', function() {
$(this).closest('li').closest('li').addClass('selected');
});
Any help is appreciated.

Go up a parent:
$(this).closest('li').parent().closest('li').addClass('selected');
It wasn't working because closest starts with the current element, and so if you call it on something that matches the selector, you get back the same thing you started with.
Live example
Or you can use parents with the :eq selector:
$(this).parents("li:eq(1)").toggleClass("selected");
Note that :eq uses 0-based indexes, so :eq(1) is the second parent li.
Live example
Your quoted HTML is invalid, though (an li can't directly contain an li); I assume you meant:
<li>
<ul>
<li><a class="editEntity>Edit</a></li>
<li><a class="deleteEntity>Delete</a></li>
</ul>
</li>
...or similar.

you can use
$('li a.editEntity').live('click', function() {
$(this).parents('li').addClass('selected');
});

following my previous comment.. here's the example promised... :)
$('li').each(function(index) {
alert(index + ': ' + $(this).text());
});
Stop at the second index
Further info can be found here
http://api.jquery.com/each/

I'm using this code to add active class depending on the page. This is working 100% for multi level sub-menus of AdminLTE 3, just put this code in the footer section of your page.
var url = window.location;
const allLinks = document.querySelectorAll('.nav-item a');
const currentLink = [...allLinks].filter(e => {
return e.href == url;
});
currentLink[0].classList.add("active");
currentLink[0].closest(".nav-treeview").style.display = "block ";
currentLink[0].closest("ul.nav-treeview").closest('li').classList.add('menu-open');
$('.menu-open').find('a').each(function() {
if (!$(this).parents().hasClass('active')) {
$(this).parents().addClass("active");
$(this).addClass("active");
}
});

Related

active class on menu and parent item

i have this HTML code for my menu:
<nav id="main-navigation" class="navigation-simple">
<ul>
<li>Home</li>
<li><a class="active-nav" href="">About Us</a>
<ul>
<li><a class="active-nav" href="about">About</a></li>
<li>Testimonials</li>
<li>Meet The Team</li>
</ul>
</li>
</nav>
i have added in the active-nav class but how can i automatically set the active class on parent and child items when the current URL is the href value of the link?
you need java script for this, jQuery is great for beginners!
It could be done like this:
var url = window.location.href;
$( "nav li a" ).each(function(index) {
if (url.indexOf($(this).attr('href')) >= 0){
$(this).addClass('active-nav');
}
});
line by line -
get the current page url
for each link in the navigation...
check if its href is in the current url
if it is, add the class 'active-nav'
close if statement
close for loop
You can use the .filter() method to find the appropriate link and add the required class:
$('#main-navigation li > a').removeClass('active-nav')
.filter(function() {
return location.href.indexOf(this.href) > -1;
})
.addClass('active-nav') //add class to matched element(s)
//add class to parent(s) of matched, if any
.each(function() {
$($(this).parents('a'), '#main-navigation').addClass('active-nav');
});
Also remember to close your first ul.
Something like:
$(function() {
$('#main-navigation a').each(function() {
if(this.href.indexOf(window.location.pathname) === 0) {
$(this).addClass('active-nav');
} else {
// case when something was set to active by the server
$(this).removeClass('active-nav');
}
});
});
will do the job.
Make sure you make the if condition safe to your sites deeplinking implementation (e.g. GET params, anchors or multiple domains with same pathname are possible within your navigation).

Better way to Find which element has a specific class from an array of elements

Suppose I have a List like the following
<ul>
<li id="slide-a" class="slide-li active-slide"><a href="#" >A</a></li>
<li id="slide-b" class="slide-li"><a href="#" >B</a></li>
<li id="slide-c" class="slide-li"><a href="#" >C</a></li
</ul>
Now , using Jquery I wanna Find out which Element has the class 'active-class'. One way would to have a nested if statement something like this:
if($("#slide-a").hasClass('active-slide'))
{
active = 'slide-a';
}
else
{
if($("#slide-b").hasClass('active-slide'))
{
active = 'slide-b';
}
else
{
if($("#slide-c").hasClass('active-slide'))
{
active = 'slide-c';
}
}
}
My question is if there exists any way to optimize the code above. Is there a generic way to achieve this such that even if I add 10 more li's in the ul the code just works fine without any modification.
Maybe just
var active = $(".active-slide").attr("id");
Demo
Use Attribute starts with selector and .each(). Try this:
$(document).ready(function(){
$('li[id^=slide]').each(function(){
if($(this).hasClass('active-slide'))
alert($(this).attr('id'));
});
});
DEMO
If you have more than one li with classactive-slide use this:
$(document).ready(function(){
var idVal = [];
$('li[id^=slide]').each(function(){
if($(this).hasClass('active-slide'))
idVal.push($(this).attr('id'));
});
console.log(idVal);
});
DEMO
You could a use jQuery $.each() on the ul to iterate through.
fiddle coming in a second.

jQuery, get each value from a list and wrap it with <a href="same value">

I have four lists
<li class='lists'>http://google.com</li>
<li class='lists'>http://facebook.com</li>
<li class='lists'>http://twitter.com</li>
<li class='lists'>http://youtube.com</li>
I want to wrap an a tag around the values of this lists with href= value from the values in the list.
The end result I am trying to achieve is:
<li class='lists'>http://google.com</li>
<li class='lists'>http://facebook.com</li>
<li class='lists'>http://twitter.com</li>
<li class='lists'>http://youtube.com</li>
So far I did with jQuery
$('li.lists').wrapInner('<a class="links"> </a>');
which wraps contents inside li with a tags, but I am little short on logic how to put the links into the a field.
I tried with
$.each($('.links'), function() {
$('.links').attr({'href':$(this).text()});
})
But this changes all the links to the http://youtube.com which is the last link, as you can see in the JSFiddle here
You can continue to use wrapInner. Just use this syntax:
$('li.lists').wrapInner(function () {
return "<a href='" + $(this).text() + "'></a>";
});
jsFiddle example
You're close with your last example. Try this:
$('.lists').each(function() {
var href = $(this).text();
$(this).html($('<a>').attr('href', href).text(href));
});
jsFiddle
Try
$('li.lists').html(function (_, old_html) {
return '' + old_html + '';
});
fiddle Demo
.html()
As this jQuery article mentions, $.each is used for non-JQuery objects while .each() is used for jQuery objects. Since you're setting the href attribute of each tag using the jQuery selector, you'll want to use .each() in such a way to set both the tag with wrapInner and its href:
$('.lists').each(function() {
$(this).wrapInner('<a class="links"> </a>');
$(this).children('a').attr({'href':$(this).text()});
})
jsfiddle example
You should try something like this:
$('.lists').each(function() {
$(this).wrapInner('<a class="links" href="'+$(this).text()+'"> </a>');
});
You could also use the $.each for all li.list and $.append() to append the child element(<a> tag).
Demo
$('li.lists').each((i,el) => {
let text =$(el).text();
$(el).text('');
$(el).append($('<a>').attr('href', text).text(text));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li class='lists'>http://google.com</li>
<li class='lists'>http://facebook.com</li>
<li class='lists'>http://twitter.com</li>
<li class='lists'>http://youtube.com</li>

How can i change the css class based on keywords in url with jquery

I have the navigation bar as below
<ul>
<li class="selected"><a href=">My Profile</a></li>
<li>xxxx</li>
<li>mybook</li>
<li>Photos <span>4</span></li>
<li>Profile List</li>
</ul>
I want that if the url is www.abc.com/user/profile then profile tab class should have class selected attached
If photos then photo tab.
If we can have partial match that will be good but i am not sure if thats possible
like in url i have /user/book and myBook gets selected
Some elegant variant:
<ul class="menu">
<li><a class="profile" href="/user/profile">My Profile</a></li>
<li><a class="book" href="/user/book">My Book</a></li>
</ul>
$(document).ready(function () {
var page = document.location.href.split('/').slice(-1)[0];
$('.menu .' + page).addClass('selected');
});
You can grab the part you want with regex:
var userPage = /user\/(.+)/.exec(location.href)[1];
That will give you the part after user/. Then you could use a switch statement:
switch (userPage) {
case 'profile':
...
break;
case 'book':
...
break;
}
You would want to switch off of location.pathname. Granted that you give that <ul> a class of nav:
$(function () {
if (location.pathname.search("/user/profile") != -1) {
// page is /user/profile
$("#nav li").eq(0).addClass("selected");
} else if (location.pathname.search("/user/photos") != -1) {
// page is some/thing
$("#nav li").eq(3).addClass("selected");
}
... etc
});
Things to notice
We use $(function () {...}); as opposed to $(document).ready(function() {...});. It is less typing and more efficient
We use String.search(), which returns the index at which the string "/user/profile" appears. If the string is not found, String.search() will return -1, so if it != -1, it exists.
We also use jQuery.eq( index ) this treats elements selected by a jQuery selector as an array and returns the element of the specified index.
References
Check out jQuery's .eq here, and JavaScript's String.search here

which <li> element was clicked?

I have 5 (maybe more) li elements.
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
</ul>
I want to get which elements was clicked(which row??). If random user clicks Two I want to get $("li:eq(1)")(as typed).
How can I get this result?
You can use jQuery.index. Something like this:
$('ul > li').click(function() {
alert($(this).index($(this).parent('li'));
});
You can get the text node value of the clicked item with:
$('li').click(function(){
var clicked = $(this).text();
alert(clicked+" was clicked");
});
$("#ulId li").click(function() {
$(this).something(); //the clicked li is $(this), and you can invoke functions on it.
})
If you give your elements an id such as
<ul id="mylist">
<li id="el_1">One</li>
<li id="el_2">Two</li>
<li id="el_3">Three</li>
<li id="el_4">Four</li>
<li id="el_5">Five</li>
</ul>
Then you can use $(this).attr(id) in the click handler to determine the id of the clicked element. This will also allow to give non sequential ids to your elements, and will detach what's written in the <li> from the actual value you get.
Also, you can encode multiple value in the id (for instance el_5_3) which can be useful sometimes.
$("#mylist li").click(function()
{
var id = $(this).attr("id").split("_");
alert("You clicked the element with id="+id[1]);
});
Working example:
http://jsfiddle.net/jFrdp/
Working example: http://jsfiddle.net/tbugV/1/
$("#mylist li").each(function(index)
{
$(this).data("row", index);
}).
click(function()
{
alert($(this).data("row"));
});
$('html').click(function() {
var el = e.target;
alert(el);
});
As people just keep posting code, and no explanations, I will try the other way around...
The click event handler is called in the scope of the clicked element, so you can use the this keyword to access the element. You can use $(this) to get a jQuery object that contains the clicked element, so that you can use jQuery methods on it.
Example:
$(document).ready(function(){
$('ul li').click(function({
var text = $(this).text();
alert('You clicked on the item with the text "' + text + '"');
}));
});
$('li').click(function(){
alert($(this).html());
});
This code will alert one when user will click the one button.

Categories