Targetting the last element that has a tabindex attribute? - javascript

How do I target the last element of a given parent, that has a tabindex attribute?
For instance:
<div id="popup">
<div id="some-element" tabindex="0">
<div id="some-other-element" tabindex="0">
<div id="yet-another-element" tabindex="0">
</div>
In this case it would target #yet-another-element

You can use the attribute selector [...] combined with jQuery .last() :
let target = $('#popup [tabindex]').last();
console.log(target.attr('id'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="popup">
<div id="some-element" tabindex="0">
<div id="some-other-element" tabindex="0">
<div id="yet-another-element" tabindex="0">
</div>
Another way is to use jQuery :last selector :
$('#popup [tabindex]:last');
let target = $('#popup [tabindex]:last');
console.log(target.attr('id'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="popup">
<div id="some-element" tabindex="0">
<div id="some-other-element" tabindex="0">
<div id="yet-another-element" tabindex="0">
</div>
If you need to select a specific tabindex value :
$('#popup [tabindex="0"]:last');

Using JavaScript:
Use Document.querySelectorAll() with Attribute selectors to get all the elements first in the form of an array-like object. Then use Spread syntax (...) and array.length - 1 to take the element from the last index:
var div = document.querySelectorAll('#popup > div[tabindex="0"]');
var lastEl = [...div][div.length - 1];
console.log(lastEl.id)
<div id="popup">
<div id="some-element" tabindex="0"></div>
<div id="some-other-element" tabindex="0"></div>
<div id="yet-another-element" tabindex="0"></div>
</div>
Using jQuery: You can use :last as part of the selector:
var lastEl = $('#popup > div[tabindex="0"]:last');
console.log($(lastEl).prop('id'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="popup">
<div id="some-element" tabindex="0"></div>
<div id="some-other-element" tabindex="0"></div>
<div id="yet-another-element" tabindex="0"></div>
</div>

Related

How to create a Xpath of the clicked element using Javascript or Jquery?

I have a webpage where I bind a click event on the element. When user clicks on the particular element. I want to get generate the XPath of the element starting from html or body tag. i.e "The Absolute Xpath"
Suppose in below html sample I click on span having text as "USA" so the Absolute Xpath would be
/html[1]/body[1]/div[2]/div[1]/div[1]/span[1]
<html>
<body>
<div class="header">Countries</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>India</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>USA</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>UK</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>France</span>
</div>
</div>
</div>
</body>
</html>
Do we have any library where it can help me generate the XPath where I pass the element Dom and it can generate it?
I came across few libraries but that help detect the Content inside the html based on provided Xpath.
You need to loop through clicked element and it parents to do this work. So you can call a function nesting to do this work.
var xpath;
$("*").click(function(e){
xpath = '';
addXpath($(this));
console.log(xpath);
e.stopPropagation();
});
function addXpath($ele){
var tagName = $ele[0].tagName.toLowerCase();
var index = $ele.parent().children(tagName).index($ele)+1;
xpath = '/'+tagName +'['+index+']'+ xpath;
!$ele.parent().is(document) ? addXpath($ele.parent()) : "";
}
body {background: green}
.header {background: orange}
.row_in {background: yellow}
.row_in_in {background: blue}
span {background: red}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header">Countries</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>India</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>USA</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>UK</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>France</span>
</div>
</div>
</div>

Get index of element among siblings ignoring sibling with specific child

I have a specific use case I can't seem to find an answer to. Given the DOM elements below:
<div class="wrapper">
<div class="item"></div>
<div class="item">
<div class="foo"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
<div class="item"></div>
<div class="item selected"></div>
<div class="item"></div>
</div>
I need to find the index of the .selected element in regard to it's siblings. But I need to ignore any siblings that have the .foo child element (it will only ever be the direct child).
So typically to find the index of .item .selected you could use $(".item.selected").index() which gives 4, but since one item before it has a .foo child the correct answer is 3.
I thought, the best way to go about it was to grab all the siblings before the selected element (since siblings after it wouldn't shift it's index) and then count how many have a .foo child, and subtract that number from the selected index, so 4-1=3. I tried to do that like this:
var selectedIndex = $(".item.selected").index();
var fooCount = $(".item.selected").prevAll('.item > .foo').length;
var finalIndex = selectedIndex - fooCount;
The problem is, fooCount is coming up 0 instead of 3.
You can simply use .filter() and remove the preceding elements that have a given child.
const selected = $('.selected');
const foos = selected.prevAll().filter(function() {
return !($(this).find('.foo').length);
});
console.log(selected.index(), foos.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="item"></div>
<div class="item">
<div class="foo"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
<div class="item"></div>
<div class="item selected"></div>
<div class="item"></div>
</div>
Use this selector ".item:not(:has(.foo))" and then loop to find the specific index.
var index = $(".item:not(:has(.foo))")
.toArray()
.findIndex(function(item) {
return $(item).hasClass('selected');
});
console.log(index);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="item"></div>
<div class="item">
<div class="foo"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
<div class="item"></div>
<div class="item selected"></div>
<div class="item"></div>
</div>
You were close.
Change:
var fooCount = $(".item.selected").prevAll('.item > .foo').length;
… to:
var fooCount = $(".item.selected").prevAll('.item:has(.foo)').length;
Otherwise, you're looking for a sibling with class .foo, when you actually want a sibling that has a child with class .foo.
Snippet:
var selectedIndex = $(".item.selected").index();
var fooCount = $(".item.selected").prevAll('.item:has(.foo)').length;
var finalIndex = selectedIndex - fooCount;
console.log(finalIndex);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="item"></div>
<div class="item">
<div class="foo"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
<div class="item"></div>
<div class="item selected"></div>
<div class="item"></div>
</div>
You can combine:
:not(): selects all elements that do not match the given selector.
:has(): reduce the set of matched elements to those that have a descendant that matches the selector or DOM element.
:index(element): where element is the DOM element or first element within the jQuery object to look for.
Hence, you can change your code:
var selectedIndex = $(".item.selected").index();
to:
var selectedIndex = $('.item:not(:has(.foo))').index($('.item.selected'));
var selectedIndex = $('.item:not(:has(.foo))').index($('.item.selected'));
console.log(selectedIndex );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="item"></div>
<div class="item">
<div class="foo"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
<div class="item"></div>
<div class="item selected"></div>
<div class="item"></div>
</div>

To access sibilings div in jquery

I want to alert panel-heading text when I click panel-footer
thanks in advance i tried .val() also but not working
$('.panel .panel-footer').on('click',function (e) {
alert($(this).parent('.panel').closest('.panel-heading .panel-title').text());
});
<div class="panel">
<div class="panel-heading">
<h3 class="panel-title">Super Admin</h3>
<div class="right">
on type="button" class="btn-toggle-collapse"><i class="lnr lnr-question-circle"></i></button>
</div>
</div>
<div class="panel-body">
<div>0 Members</div>
</div>
<div class="panel-footer">
<div>View All<i class="lnr lnr-arrow-right pull-right"></i></div>
</div>
</div>
Update closest to find, closest goes up and not down
$('.panel .panel-footer').on('click',function (e) {
alert( $(this).parent('.panel').find('.panel-title').text() );
});
https://api.jquery.com/closest/ it traverses up the DOM tree
Description: For each element in the set, get the first element that
matches the selector by testing the element itself and traversing up
through its ancestors in the DOM tree.
but you want to traverse down since you are already at the parent level($(this).parent('.panel')).
So we use find() https://api.jquery.com/find/ which traverses down
Description: Get the descendants of each element in the current set of
matched elements, filtered by a selector, jQuery object, or element.
If you prefer the 'siblings' approach, that will work, as you're triggering off the panel-footer el.
$('.panel .panel-footer').on('click',function (e) {
console.log($(this).siblings(".panel-heading").text() );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="panel">
<div class="panel-heading">
<h3 class="panel-title">Super Admin</h3>
<div class="right">
<button type="button" class="btn-toggle-collapse"><i class="lnr lnr-question-circle"></i></button>
</div>
</div>
<div class="panel-body">
<div>0 Members</div>
</div>
<div class="panel-footer">
<div>View All<i class="lnr lnr-arrow-right pull-right"></i></div>
</div>
</div>
Replace closest() by find():
$('.panel .panel-footer').on('click',function (e) {
alert($(this).parent('.panel').find('.panel-heading .panel-title').text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="panel">
<div class="panel-heading">
<h3 class="panel-title">Super Admin</h3>
<div class="right">
<button type="button" class="btn-toggle-collapse"><i class="lnr lnr-question-circle"></i></button>
</div>
</div>
<div class="panel-body">
<div>0 Members</div>
</div>
<div class="panel-footer">
<div>View All<i class="lnr lnr-arrow-right pull-right"></i></div>
</div>
</div>

How to count number of element it cross while using find jquery

Supppose HTML structure is:
<div class="history">
<div id="10"></div>
<div id="20"></div>
<div id="30"></div>
<div id="40"></div>
<div id="50"></div>
</div>
If this is HTML structure then in jquery:
$(".history").find("#40").show();
If I use this then jquery has to loop over child element to find id with #40. It have to cross 3 element that is #10, #20, #30. How to return the number of element is has to loop to find specific id.
You can do it with the help of index(), since index is starting with 0 you will it's index will be the count of previous elements.
alert($('#40').index());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="history">
<div id="10"></div>
<div id="20"></div>
<div id="30"></div>
<div id="40"></div>
<div id="50"></div>
</div>
or
alert($('.history > div').index($('#40')));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="history">
<div id="10"></div>
<div id="20"></div>
<div id="30"></div>
<div id="40"></div>
<div id="50"></div>
</div>
or
alert($('.history').children().index($('#40')));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="history">
<div id="10"></div>
<div id="20"></div>
<div id="30"></div>
<div id="40"></div>
<div id="50"></div>
</div>
That's not quite how selectors work. You can, however, still get the number of preceding elements quite easily. Since the element has an ID and IDs have to be unique, you can address it directly, there's no need to address the parent at all.
alert($('#40').prevAll().length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="history">
<div id="10"></div>
<div id="20"></div>
<div id="30"></div>
<div id="40"></div>
<div id="50"></div>
</div>

Append before last child

I have a div with the ID wrapper, and I am using .append() to insert some content at the end of that div, like this:
$("#wrapper").append('<div class="content"><div class="subcontent">Some stuff</div></div>');
However, I also want the option to insert a new child before the last content div in the wrapper.
So if the HTML output looks like this:
<div id="wrapper">
<div class="content">
<div class="subcontent">
First
</div>
</div>
<div class="content">
<div class="subcontent">
Second
</div>
</div>
</div>
I want to insert an element before the last one, so I get this:
<div id="wrapper">
<div class="content">
<div class="subcontent">
First
</div>
</div>
<div class="content">
<div class="subcontent">
Third
</div>
</div>
<div class="content">
<div class="subcontent">
Second
</div>
</div>
</div>
How would I do this?
You could use .before() to add a sibling before the element:
$("#wrapper .content:last").before('<div class="content"><div class="subcontent">Third</div></div>');
.insertBefore() does the same thing with a different syntax, namely that you select the element to be added, and pass the element you want to add it before.
$("#wrapper .content:last").before('<div class="content"><div class="subcontent">Third</div></div>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="wrapper">
<div class="content">
<div class="subcontent">
First
</div>
</div>
<div class="content">
<div class="subcontent">
Second
</div>
</div>
</div>
You can use insertBefore():
$('<div class="content"><div class="subcontent">Some stuff</div></div>').insertBefore('#wrapper > div:last');
Or before():
$('#wrapper > div:last').before('<div class="content"><div class="subcontent">Some stuff</div></div>');
This is how I got there:
http://jsfiddle.net/lharby/00tk6avg/
var htmlString = '<div class="subcontent">Some stuff</div>';
$(htmlString).insertBefore('.content div:last');
Select the last element with :last-of-type and use before() to append the new element:
$('.content:last-of-type').before('<div class="new">test</div>');
.new { color:red }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="wrapper">
<div class="content">
<div class="subcontent">
First
</div>
</div>
<div class="content">
<div class="subcontent">
Second
</div>
</div>
</div>
Use insertBefore:
$('<div class="content"><div class="subcontent">Third</div></div>').insertBefore('#wrapper .content:last');
Insert every element in the set of matched elements before the target.
Demo: http://api.jquery.com/insertBefore/
$( "<p>Test</p>" ).insertBefore( "#wrapper > div:last-child" );
You can last() for selecting last item, and before() for appending
$("#wrapper .content").last().before('<div class="content"><div class="subcontent">Some stuff</div></div>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="wrapper">
<div class=" content ">
<div class="subcontent ">
First
</div>
</div>
<div class="content ">
<div class="subcontent ">
Second
</div>
</div>
</div>
you can use nth last child to select the second last div.
fiddle:
http://jsfiddle.net/08ta9wnL/
html:
<div id="wrapper">
<div class="content">
<div class="subcontent">
First
</div>
</div>
<div class="content">
<div class="subcontent">
Second
</div>
</div>
</div>
javascript:
$(document).ready(function(){
$("#wrapper div:nth-last-child(2)").append('<div class="content"><div class="subcontent">Some stuff</div></div>');
});
You can do like this
$("#wrapper .content:last").before("<div class="content"><div class="subcontent">Some stuff</div></div>");
Have a look at fiddle https://jsfiddle.net/48ebssso/

Categories

Resources