jQuery if any of an element's parents' href begins with - javascript

So what I'm trying to achieve is a way to check if any of an element's parents' href begin with something. Here's how far I've come:
$('.element').click(function(e){
if($(this).is('[href^="X"')){
// How to check if the clicked element's href begins with X
}
});
But this is not what I want. I wanna check if any of the element's parents have a href beginning with something.
Any ideas?
Gustaf

I'd suggest, given that nesting an <a> element is invalid so that there can be only one ancestor <a> element (or no ancestor <a> elements, obviously):
$('.element').click(function(e){
// here we use a terribly-, but meaningfully-, named variable
// to hold the Boolean result of the assessment;
// the assessment looks from the clicked element up through
// the ancestors for the first <a> element matching the
// attribute-starts-with selector ([href^=x])
// this will return either 1 or 0 elements.
// we check the length; if it's equal to 1 then the ancestor
// has an href starting with x, if it's 0 then there is either
// no ancestor <a> element or no ancestor <a> element with a
// href matching the attribute-starts-with selector:
var ancestorAnchorStartsWithX = $(this).closest('a[href^=x]').length === 1;
});
It's worth noting, as #A. Wolff did, in the comments below, that:
…closest() [checks the] element itself too.
Which means that if the clicked element itself matches the selector supplied to closest (and is therefore an <a> element with an href beginning with x) then the assessment will return true, even though it's not an ancestor element. I considered this a feature – while writing out the selector – but I forgot to detail that in the answer itself.
If this is considered a bug, then an option using parents('a[href^=x]') in place of closest('a[href^=x]') will be more appropriate to your use-case.
References:
CSS:
Attribute-selectors.
jQuery:
click().
closest().

$(".element").click(function(e) {
var res = $(this).parents("[href^=X]").is("*");
console.log(res);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<a href="Xabc123">
<div class="element">click</div>
</a>

This is what you want:
$('.element').click(function(e){
var $parents=$(this).parents();
var matches=$parents.filter('[href^="x"]');
if(matches.length){
}
}
});

Related

How to put into querySelector some IDs?

querySelector("#ID1, #ID2, ID#3")
Is there a possibility to put into one querySelector some IDs?
querySelectorAll can be used to target multiple selectors.
document.querySelectorAll("#div1, .div2, h3");
Simple ! Use following code.
document.querySelectorAll('#id1, #id2 , #id3');
This will return nodelist which you can iterate and can perform actions that you want.
The querySelector() method returns the first element that matches a specified CSS selector(s) in the document.
Keep in mind that to return all the matches, use the querySelectorAll() method instead.
example
<div class="bar">.first </div>
<div class="bar">.second</div>
//get the first element with class bar
let firstElement = document.querySelector('.bar');
//log the first match
console.log(firstElement)
//get all elements with class bar
let allElements = document.querySelectorAll('.bar')
//You can use any common looping statement to access the matches
allElements.forEach(function(elements){
console.log(elements);
});
/*
querySelector("#ID1, #ID2, ID#3")
*select element matches #ID1
*select element matches #ID2
*select element matches #ID3
**/
//select elements matches specified selectors #id1 , #id2 , #id3 and use any common looping statement to access them
let allMatchesId = document.querySelectorAll('#id1 , #id2 , #id3');
allMatchesId .forEach(function(elements){
console.log(elements);
});
read the docs here at MDN https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
const divs = document.querySelectorAll('#id1, #id2');
console.log(divs[0], divs[1]);
<div id="id1"><div id="id2"></div></div>
Source
Just some more explanation:
This will work (if you correct the error ID#3 instead of #ID3), however querySelector only returns the first element in the document that it matches (NOT the first ID in the list).
If you want all of the elements, then use querySelectorAll, but again the order of the elements will NOT be the order of the IDs, but the order of elements in the document. For example, given the following HTML:
<div id="id2"></div>
<div id="id1"></div>
then following JS:
const divs = document.querySelectorAll("#id1, #id2");
alert(divs[0].id); // This will show "id2"!

How do you grab an element relative to an Element instance with a selector?

I am writing a small library where I am in need of selecting a relative element to the targeted element through querySelector method.
For example:
HTML
<div class="target"></div>
<div class="relative"></div>
<!-- querySelector will select only this .target element -->
<div class="target"></div>
<div class="relative"></div>
<div class="target"></div>
<div class="relative"></div>
JavaScript
var target = document.querySelectorAll('.target')[1];
// Something like this which doesn't work actually
var relativeElement = target.querySelector('this + .relative');
In the above example, I am trying to select the .relative class element relative only to the .target element whose value is stored in target variable. No styles should apply to the other .relative class elements.
PS: the selectors can vary. So, I can't use JavaScript's predefined methods like previousElementSibling or nextElementSibling.
I don't need solution in jQuery or other JavaScript libraries.
Well it should be ideally:
var relativeElement = target.querySelector('.relative');
But this will actually try to select something inside the target element.
therefore this would only work if your html structure is something like:
<div class="target">
<div class="relative"></div>
</div>
Your best bet would probably in this case be to use nextElementSibling which I understand is difficult for you to use.
You cannot.
If you insist on using the querySelector of the subject element, the answers is there is no way.
The spec and MDN both says clearly that Element.querySelector must return "a descendant of the element on which it is invoked", and the object element you want does not meet this limitation.
You must go up and use other elements, e.g. document.querySelector, if you want to break out.
You can always override Element.prototype.querySelector to do your biddings, including implementing your own CSS engine that select whatever element you want in whatever syntax you want.
I didn't mention this because you will be breaking the assumption of a very important function, easily breaking other libraries and even normal code, or at best slowing them down.
target.querySelector('.relative');
By using querySelector on the target instead of document, you scope the DOM traversal to the target element.
It is not entirely clear from your explanation, but by related i assume you mean descendant?
To get all target elements you can use
document.querySelectorAll('.target')
And then iterate the result
I found a way which will work for my library.
I will replace "this " in the querySelector with a unique custom attribute value. Something like this:
Element.prototype.customQuerySelector = function(selector){
// Adding a custom attribute to refer for selector
this.setAttribute('data-unique-id', '1');
// Replace "this " string with custom attribute's value
// You can also add a unique class name instead of adding custom attribute
selector = selector.replace("this ", '[data-unique-id="1"] ');
// Get the relative element
var relativeElement = document.querySelector(selector);
// After getting the relative element, the added custom attribute is useless
// So, remove it
this.removeAttribute('data-unique-id');
// return the fetched element
return relativeElement;
}
var element = document.querySelectorAll('.target')[1];
var targetElement = element.customQuerySelector('this + .relative');
// Now, do anything with the fetched relative element
targetElement.style.color = "red";
Working Fiddle

how to use the closest function using specific div

I need jquery to get the closest id,once the the image is visible.
this is my query so far
(...)
if(isonscreen)
{
//this works, but I need it to find only images inside the content-bubble div tag
// and of course this grabs any image no matter what div the image is inside of
console.log($(this).closest('img').attr('id'));
}
(...)
<div class="content-bubble">
<h2>{{imageTitle}}</h2>
<img src="loading.gif" id="lazyload{{imgId}}" class="content-bubble-img"">
</div>
I've tried this but its not working and returns undefined
console.log($(this).closest('.content-bubble-img').find('img').attr('id'));
console.log($('.content-bubble-img').closest('img').attr('id'));
I thing you want the function find(), not closest().
closest finds the nearest parent of an element, while find().filter(':first') finds the first children inside an element. Or to say it with the doc's words:
closest:
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.
find:
Get the descendants of each element in the current set of matched
elements, filtered by a selector, jQuery object, or element.
http://api.jquery.com/closest/
http://api.jquery.com/find/
To comment your code:
console.log($(this).closest('img').attr('id'));
This is actually pretty bad since images cant have children, this does only work since closest() returns the selected element itself which is the image when you use $(image).closest(). Replace closest with find and you're good to go.
If u have to find all images inside "content-bubble div" no matter what div the image is inside of then use this :
$('.content-bubble img');
First of all it would be much easier to fully understand what you're trying to achieve if you have added a fiddle of it.
Nevertheless I'm guessing that you're checking whether an image is currently visible - which means that in this piece of code
(...)
if(isonscreen)
{
console.log($(this).closest('img').attr('id'));
}
(...)
$(this) actually refers to the image you're interested in - thus you might want to simply retrieve its id attribute with $(this).attr('id')
Since you want to limit it to images which are placed in divs with a specific class, you might just want to check if one of its parents has class '.content-bubble', by
$(this).parents('.content-bubble').length
You may also use closest, since it actually traverses up the DOM tree from the element you specified, and:
if($(this).closest('.content-bubble').length)
which in this case would return true when $(this) or any of its parent has class .content-bubble
I'm using the espy plugin for jquery
This is how you find the id of the nearest image inside a div tag
once the image is visible
$('.content-bubble-img').espy(function (entered, state) {
if (entered)
{
// element entered the viewport
// state === 'inside'
console.log('element entered viewport');
console.log($(this).closest('img').attr('id'));
}
else
{
// element left the viewport
if (state === 'up')
{
// element is now above the trigger area
console.log('element left the viewport');
}
else if (state === 'down')
{
// element is now below the trigger area
console.log('element below the trigger area');
}
}
});

What is this xPath trying to capture?

I have come across this bit of jQuery and I am failing to understand what the xPath (?) means in this context:
var all_line_height = $(this).find("*[style*='line-height']");
I haven't seen this before, is it looking for an element that contains line-height in its style attribute?
I did a small test and it doesn't pick up on it.
That's not XPath. It's a selector, which selects any element whose style attribute contains line-height from the currently selected element (this).
$(this) // selects the current element
.find(...) // Select all elements which match the selector:
*[style*='line-height'] // Any element (*),
// whose style attribute ([style])
// contains "line-height" (*='line-height')
It could be implemented as follows:
// HTML:
// <div id="test">
// <a style="line-height:10px;color:red;">...
$("#test").click(function(){
// this points to <div id="test">
var all_line_height = $(this).find("*[style*='line-height']");
alert(all_line_height.length); //Alerts 1
})

How do I get the n-th level parent of an element in jQuery?

When I want to get, for example, the 3rd level parent of the element I must write $('#element').parent().parent().parent() Is there a more optimal method for this?
Since parents() returns the ancestor elements ordered from the closest to the outer ones, you can chain it into eq():
$('#element').parents().eq(0); // "Father".
$('#element').parents().eq(2); // "Great-grandfather".
Depends on your needs, if you know what parent your looking for you can use the .parents() selector.
E.G:
http://jsfiddle.net/HenryGarle/Kyp5g/2/
<div id="One">
<div id="Two">
<div id="Three">
<div id="Four">
</div>
</div>
</div>
</div>
var top = $("#Four").parents("#One");
alert($(top).html());
Example using index:
//First parent - 2 levels up from #Four
// I.e Selects div#One
var topTwo = $("#Four").parents().eq(2);
alert($(topTwo ).html());
You could give the target parent an id or class (e.g. myParent) and reference is with $('#element').parents(".myParent")
Didn't find any answer using closest()
and I think it's the most simple answer when you don't know how many levels up the required element is, so posting an answer:
You can use the closest() function combined with selectors to get the first element that matches when traversing upwards from the element:
('#element').closest('div') // returns the innermost 'div' in its parents
('#element').closest('.container') // returns innermost element with 'container' class among parents
('#element').closest('#foo') // returns the closest parent with id 'foo'
A faster way is to use javascript directly, eg.
var parent = $(innerdiv.get(0).parentNode.parentNode.parentNode);
This runs significantly faster on my browser than chaining jQuery .parent() calls.
See: http://jsperf.com/jquery-get-3rd-level-parent
It's simple. Just use
$(selector).parents().eq(0);
where 0 is the parent level (0 is parent, 1 is parent's parent etc)
Just add :eq() selector like this:
$("#element").parents(":eq(2)")
You just specify index which parent: 0 for immediate parent, 1 for grand-parent, ...
If you plan on reusing this functionality, the optimal solution is to make a jQuery plugin:
(function($){
$.fn.nthParent = function(n){
var $p = $(this);
while ( n-- >= 0 )
{
$p = $p.parent();
}
return $p;
};
}(jQuery));
Of course, you may want to extend it to allow for an optional selector and other such things.
One note: this uses a 0 based index for parents, so nthParent(0) is the same as calling parent(). If you'd rather have 1 based indexing, use n-- > 0
If you have a common parent div you can use parentsUntil() link
eg: $('#element').parentsUntil('.commonClass')
Advantage is that you need not to remember how many generation are there between this element and the common parent(defined by commonclass).
you can also use :
$(this).ancestors().eq(n)
ex: $(this).ancestors().eq(2) -> the parent of the parent of this.
using eq appears to grab the dynamic DOM whereas using .parent().parent() appears to grab the DOM that was initially loaded (if that is even possible).
I use them both on an element that has classes applied it to on onmouseover. eq shows the classes while .parent().parent() doesnt.
As parents() returns a list, this also works
$('#element').parents()[3];
You could use something like this:
(function($) {
$.fn.parentNth = function(n) {
var el = $(this);
for(var i = 0; i < n; i++)
el = el.parent();
return el;
};
})(jQuery);
alert($("#foo").parentNth(2).attr("id"));
http://jsfiddle.net/Xeon06/AsNUu/

Categories

Resources