Automate Parent hierarchy - javascript

var classFind= $('.frame').parent().parent().parent().parent().parent();
if (classfind.hasClass(".class")) {
return true;
}
I have a class that is located according to this path^... How could I loop through the dom to automate this process with better code readability? If it does not find the .hasclass before it hits a null then simply return false.

Can't you just replace this with...
return !!$('.frame').closest('.class').length;
The closest methods travels up the DOM tree until it finds the element that matches the selector given as its param - and then stops immediately; it will return empty collection of elements (which is still an object, hence its length should be checked) if no such element is found. And !! is the same as Boolean() call - it's not required, but will make your function return boolean values (true/false) instead of 0/1.

You can try someting like this:
var classFind= $('.frame').closest(".class");

With the closest function, you will not get exact 5 parents, if it is what you want...
This selector will do this.
function findEl() {
if($('.class > * > * > * > * > .frame').length > 0) {
return true;
}
return false;
}
Test it on:
http://jsfiddle.net/S5juG/1/
Take a look at the child selector:
http://api.jquery.com/child-selector/

Related

Check if elements are part of wrapper [duplicate]

How can I check if one DOM element is a child of another DOM element? Are there any built in methods for this? For example, something like:
if (element1.hasDescendant(element2))
or
if (element2.hasParent(element1))
If not then any ideas how to do this? It also needs to be cross browser. I should also mention that the child could be nested many levels below the parent.
You should use Node.contains, since it's now standard and available in all browsers.
https://developer.mozilla.org/en-US/docs/Web/API/Node.contains
Update: There's now a native way to achieve this. Node.contains(). Mentioned in comment and below answers as well.
Old answer:
Using the parentNode property should work. It's also pretty safe from a cross-browser standpoint. If the relationship is known to be one level deep, you could check it simply:
if (element2.parentNode == element1) { ... }
If the the child can be nested arbitrarily deep inside the parent, you could use a function similar to the following to test for the relationship:
function isDescendant(parent, child) {
var node = child.parentNode;
while (node != null) {
if (node == parent) {
return true;
}
node = node.parentNode;
}
return false;
}
I just had to share 'mine'.
Although conceptually the same as Asaph's answer (benefiting from the same cross-browser compatibility, even IE6), it is a lot smaller and comes in handy when size is at a premium and/or when it is not needed so often.
function childOf(/*child node*/c, /*parent node*/p){ //returns boolean
while((c=c.parentNode)&&c!==p);
return !!c;
}
..or as one-liner (just 64 chars!):
function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c}
and jsfiddle here.
Usage:
childOf(child, parent) returns boolean true|false.
Explanation:
while evaluates as long as the while-condition evaluates to true.
The && (AND) operator returns this boolean true/false after evaluating the left-hand side and the right-hand side, but only if the left-hand side was true (left-hand && right-hand).
The left-hand side (of &&) is: (c=c.parentNode).
This will first assign the parentNode of c to c and then the AND operator will evaluate the resulting c as a boolean.
Since parentNode returns null if there is no parent left and null is converted to false, the while-loop will correctly stop when there are no more parents.
The right-hand side (of &&) is: c!==p.
The !== comparison operator is 'not exactly equal to'. So if the child's parent isn't the parent (you specified) it evaluates to true, but if the child's parent is the parent then it evaluates to false.
So if c!==p evaluates to false, then the && operator returns false as the while-condition and the while-loop stops. (Note there is no need for a while-body and the closing ; semicolon is required.)
So when the while-loop ends, c is either a node (not null) when it found a parent OR it is null (when the loop ran through to the end without finding a match).
Thus we simply return that fact (converted as boolean value, instead of the node) with: return !!c;: the ! (NOT operator) inverts a boolean value (true becomes false and vice-versa).
!c converts c (node or null) to a boolean before it can invert that value. So adding a second ! (!!c) converts this false back to true (which is why a double !! is often used to 'convert anything to boolean').
Extra:
The function's body/payload is so small that, depending on case (like when it is not used often and appears just once in the code), one could even omit the function (wrapping) and just use the while-loop:
var a=document.getElementById('child'),
b=document.getElementById('parent'),
c;
c=a; while((c=c.parentNode)&&c!==b); //c=!!c;
if(!!c){ //`if(c)` if `c=!!c;` was used after while-loop above
//do stuff
}
instead of:
var a=document.getElementById('child'),
b=document.getElementById('parent'),
c;
function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c}
c=childOf(a, b);
if(c){
//do stuff
}
Another solution that wasn't mentioned:
Example Here
var parent = document.querySelector('.parent');
if (parent.querySelector('.child') !== null) {
// .. it's a child
}
It doesn't matter whether the element is a direct child, it will work at any depth.
Alternatively, using the .contains() method:
Example Here
var parent = document.querySelector('.parent'),
child = document.querySelector('.child');
if (parent.contains(child)) {
// .. it's a child
}
You can use the contains method
var result = parent.contains(child);
or you can try to use compareDocumentPosition()
var result = nodeA.compareDocumentPosition(nodeB);
The last one is more powerful: it return a bitmask as result.
Take a look at Node#compareDocumentPosition.
function isDescendant(ancestor,descendant){
return ancestor.compareDocumentPosition(descendant) &
Node.DOCUMENT_POSITION_CONTAINS;
}
function isAncestor(descendant,ancestor){
return descendant.compareDocumentPosition(ancestor) &
Node.DOCUMENT_POSITION_CONTAINED_BY;
}
Other relationships include DOCUMENT_POSITION_DISCONNECTED, DOCUMENT_POSITION_PRECEDING, and DOCUMENT_POSITION_FOLLOWING.
Not supported in IE<=8.
I came across a wonderful piece of code to check whether or not an element is a child of another element. I have to use this because IE doesn't support the .contains element method. Hope this will help others as well.
Below is the function:
function isChildOf(childObject, containerObject) {
var returnValue = false;
var currentObject;
if (typeof containerObject === 'string') {
containerObject = document.getElementById(containerObject);
}
if (typeof childObject === 'string') {
childObject = document.getElementById(childObject);
}
currentObject = childObject.parentNode;
while (currentObject !== undefined) {
if (currentObject === document.body) {
break;
}
if (currentObject.id == containerObject.id) {
returnValue = true;
break;
}
// Move up the hierarchy
currentObject = currentObject.parentNode;
}
return returnValue;
}
Consider using closest('.selector')
It returns null if neither element nor any of its ancestors matches the selector. Alternatively returns the element which was found
try this one:
x = document.getElementById("td35");
if (x.childElementCount > 0) {
x = document.getElementById("LastRow");
x.style.display = "block";
}
else {
x = document.getElementById("LastRow");
x.style.display = "none";
}
TL;DR: a library
I advise using something like dom-helpers, written by the react team as a regular JS lib.
In their contains implementation you will see a Node#contains based implementation with a Node#compareDocumentPosition fallback.
Support for very old browsers e.g. IE <9 would not be given, which I find acceptable.
This answer incorporates the above ones, however I would advise against looping yourself.

how can I know what index is an html element in its parent children [duplicate]

Normally I'm doing it this way:
for(i=0;i<elem.parentNode.length;i++) {
if (elem.parentNode[i] == elem) //.... etc.. etc...
}
function getChildIndex(node) {
return Array.prototype.indexOf.call(node.parentNode.childNodes, node);
}
This seems to work in Opera 11, Firefox 4, Chromium 10. Other browsers untested. It will throw TypeError if node has no parent (add a check for node.parentNode !== undefined if you care about that case).
Of course, Array.prototype.indexOf does still loop, just within the function call. It's impossible to do this without looping.
Note: If you want to obtain the index of a child Element, you can modify the function above by changing childNodes to children.
function getChildElementIndex(node) {
return Array.prototype.indexOf.call(node.parentNode.children, node);
}
Option #1
You can use the Array.from() method to convert an HTMLCollection of elements to an array. From there, you can use the native .indexOf() method in order to get the index:
function getElementIndex (element) {
return Array.from(element.parentNode.children).indexOf(element);
}
If you want the node index (as oppose to the element's index), then replace the children property with the childNodes property:
function getNodeIndex (element) {
return Array.from(element.parentNode.childNodes).indexOf(element);
}
Option #2
You can use the .call() method to invoke the array type's native .indexOf() method. This is how the .index() method is implemented in jQuery if you look at the source code.
function getElementIndex(element) {
return [].indexOf.call(element.parentNode.children, element);
}
Likewise, using the childNodes property in place of the children property:
function getNodeIndex (element) {
return [].indexOf.call(element.parentNode.childNodes, element);
}
Option #3
You can also use the spread operator:
function getElementIndex (element) {
return [...element.parentNode.children].indexOf(element);
}
function getNodeIndex (element) {
return [...element.parentNode.childNodes].indexOf(element);
}
You could count siblings...
The childNodes list includes text and element nodes-
function whichChild(elem){
var i= 0;
while((elem=elem.previousSibling)!=null) ++i;
return i;
}
There is no way to get the index of a node within its parent without looping in some manner, be that a for-loop, an Array method like indexOf or forEach, or something else. An index-of operation in the DOM is linear-time, not constant-time.
More generally, if list mutations are possible (and the DOM certainly supports mutation), it's generally impossible to provide an index-of operation that runs in constant time. There are two common implementation tactics: linked lists (usually doubly) and arrays. Finding an index using a linked list requires a walk. Finding an index using an array requires a scan. Some engines will cache indexes to reduce time needed to compute node.childNodes[i], but this won't help you if you're searching for a node. Not asking the question is the best policy.
I think you've got it, but:
make sure that variable "i" is declared with var
use === instead of == in the comparison
If you have a collection input elements with the same name (like <textarea name="text_field[]"…) in your form and you want to get the exact numeric index of the field that triggered an event:
function getElementIdxFromName(elem, parent) {
var elms = parent[elem.name];
var i = 0;
if (elms.length === undefined) // there is only one element with this name in the document
return 0;
while((elem!=elms[i])) i++;
return i;
}
Getting numeric id of an element from a collection of elements with the same class name:
function getElementIdxFromClass(elem, cl) {
var elems = document.getElementsByClassName(cl);
var i = 0;
if (elems.length > 0) {
while((elem!=elems[i])) i++;
return i;
}
return 0;
}
Try this:
let element = document.getElementById("your-element-id");
let indexInParent = Array.prototype.slice.call(element.parentNode.parentNode.children).indexOf(element.parentNode));

Return "True" on Empty jQuery Selector Array?

I'm working on creating a more semantic way of checking for elements with jQuery. Using $("#element").length > 0 just doesn't really feel very well worded to me, so I'm making my own selector addition for use in .is:
if($("#element").is(":present")) {
console.log("It's aliiiveeee!!");
}
That part was easy, like this:
$.extend($.expr[':'],{
present: function(a) {
return $(a).length > 0;
}
});
I want to go a step further, and make it easy to see if an element doesn't exist, using similar syntax:
$.extend($.expr[':'],{
present: function(a) {
return $(a).length > 0;
},
absent: function(a) {
return $(a).length === 0;
}
});
$(function() {
if($("#element").is(":absent")) {
console.log("He's dead, Jim.");
}
});
But this part is surprisingly hard to do. I think it's because I'm paring down the returned elements to get a result, and paring the selector to .length === 0 is the same as asking for no elelements: it returns false no matter what.
I've tried a lot of different ways to reverse things and get this to return true when the element doesn't exist, and false if it does:
return $(a).length === 0;
return !($(a).length > 0);
if(!($(a).length > 0)) {
return true;
}
if($(a).length > 0) {
return false;
} else {
return true;
}
return !!($(a).length === 0);
// etc...
Is there an easy way to get this to just return true if the element doesn't exist, and false if it does?
The definition of is:
Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
The problem is that since you have no elements, it's not possible that one of your elements matches some condition. jQuery is not even calling your code because there are no elements.
EDIT: To clarify slightly, your code is being called once for every element in your object (at least until one returns true). No elements means the code is never called. a in your code is always a single element.
EDIT2: With that in mind, this would be a more efficient implementation of present:
$.extend($.expr[':'],{
present: function(a) {
return true;
}
});
You can simply use
if(​$('element').length) // 1 or 0 will be returned
or
$.extend($.expr[':'],{
present: function(a) {
return $(a).length;
}
});
if($('#element').is(':present'))
{
// code for existence
}
else
{
// code for non-existence
}
Example.
Given that $().is() won't even run when the collection is empty, the :present selector is rather superfluous. So rather than playing with $.expr[':'], I'd go with extending $.fn to contain appropriate function, e.g.:
$.fn.extend({
hasAny: function() {
return this.length > 0;
},
});
or
$.fn.extend({
isEmpty: function() {
return this.length == 0;
},
});
The reason I would personally go with this approach is that selectors are typically used to check particular properties of elements (compare :checked, :enabled, :selected, :hover, etc.), not the properties of jQuery element set as a whole (e.g. .size(), .index()).
Usage would of course be similar to the following:
if ($('#element').isEmpty())
console.log("He's dead, Jim.");
0 is "falsy" in JavaScript.
You can just return !$(a).length.
How about:
if ( !$(a)[0] ) {
// $(a) is empty
}
So, $(a)[0] retrieves the first element in the jQuery object. If that element is null/undefined, that means that the jQuery object is empty.

jQuery: Check if div with certain class name exists

Using jQuery I'm programmatically generating a bunch of div's like this:
<div class="mydivclass" id="myid1">Some Text1</div>
<div class="mydivclass" id="myid2">Some Text2</div>
Somewhere else in my code I need to detect if these DIVs exist. The class name for the divs is the same but the ID changes for each div. Any idea how to detect them using jQuery?
You can simplify this by checking the first object that is returned from JQuery like so:
if ($(".mydivclass")[0]){
// Do something if class exists
} else {
// Do something if class does not exist
}
In this case if there is a truthy value at the first ([0]) index, then assume class exists.
Edit 04/10/2013: I've created a jsperf test case here.
You can use size(), but jQuery recommends you use length to avoid the overhead of another function call:
$('div.mydivclass').length
So:
// since length is zero, it evaluates to false
if ($('div.mydivclass').length) {
http://api.jquery.com/size/
http://api.jquery.com/length/
UPDATE
The selected answer uses a perf test, but it's slightly flawed since it is also including element selection as part of the perf, which is not what's being tested here. Here is an updated perf test:
http://jsperf.com/check-if-div-exists/3
My first run of the test shows that property retrieval is faster than index retrieval, although IMO it's pretty negligible. I still prefer using length as to me it makes more sense as to the intent of the code instead of a more terse condition.
Without jQuery:
Native JavaScript is always going to be faster. In this case: (example)
if (document.querySelector('.mydivclass') !== null) {
// .. it exists
}
If you want to check to see if a parent element contains another element with a specific class, you could use either of the following. (example)
var parent = document.querySelector('.parent');
if (parent.querySelector('.child') !== null) {
// .. it exists as a child
}
Alternatively, you can use the .contains() method on the parent element. (example)
var parent = document.querySelector('.parent'),
child = document.querySelector('.child');
if (parent.contains(child)) {
// .. it exists as a child
}
..and finally, if you want to check to see if a given element merely contains a certain class, use:
if (el.classList.contains(className)) {
// .. el contains the class
}
$('div').hasClass('mydivclass')// Returns true if the class exist.
Here is a solution without using Jquery
var hasClass = element.classList.contains('class name to search');
// hasClass is boolean
if(hasClass === true)
{
// Class exists
}
reference link
It's quite simple...
if ($('.mydivclass').length > 0) {
//do something
}
To test for div elements explicitly:
if( $('div.mydivclass').length ){...}
Here are some ways:
1. if($("div").hasClass("mydivclass")){
//Your code
//It returns true if any div has 'mydivclass' name. It is a based on the class name
}
2. if($("#myid1").hasClass("mydivclass")){
//Your code
// It returns true if specific div(myid1) has this class "mydivclass" name.
// It is a based on the specific div id's.
}
3. if($("div[class='mydivclass']").length > 0){
//Your code
// It returns all the divs whose class name is "mydivclass"
// and it's length would be greater than one.
}
We can use any one of the abobe defined ways based on the requirement.
The simple code is given below :
if ($('.mydivclass').length > 0) {
//Things to do if class exist
}
To hide the div with particuler id :
if ($('#'+given_id+'.mydivclass').length > 0) {
//Things to do if class exist
}
Best way is to check the length of the class as shown below:
if ($('.myDivClass').length) {
if ($("#myid1").hasClass("mydivclass")){// Do any thing}
Use this to search whole page
if($('*').hasClass('mydivclass')){
// Do Stuff
}
Here is very sample solution for check class (hasClass) in Javascript:
const mydivclass = document.querySelector('.mydivclass');
// if 'hasClass' is exist on 'mydivclass'
if(mydivclass.classList.contains('hasClass')) {
// do something if 'hasClass' is exist.
}
In Jquery you can use like this.
if ($(".className")[0]){
// Do something if class exists
} else {
// Do something if class does not exist
}
With JavaScript
if (document.getElementsByClassName("className").length > 0) {
// Do something if class exists
}else{
// Do something if class does not exist......
}
check if the div exists with a certain class
if ($(".mydivclass").length > 0) //it exists
{
}
if($(".myClass")[0] != undefined){
// it exists
}else{
// does not exist
}
The best way in Javascript:
if (document.getElementsByClassName("search-box").length > 0) {
// do something
}
if ($(".mydivclass").size()){
// code here
}
The size() method just returns the number of elements that the jQuery selector selects - in this case the number of elements with the class mydivclass. If it returns 0, the expression is false, and therefore there are none, and if it returns any other number, the divs must exist.
var x = document.getElementsByClassName("class name");
if (x[0]) {
alert('has');
} else {
alert('no has');
}

jquery, how to check if a specific ID is a child of an other id?

I have a specific id ("mysubid"), now I want to check if this element (this id) is in a child path of an other id ("mymainid").
Is there an easy way to do this or will I go upwards, element by element, to see if the element is in a child path.
By child path I am talking about something like this:
A > B > C > D
So D is in the Child Path of A,B and C
You all are making this very complicated. Use the descendant selector:
if ($('#mymainid #mysubid').length) {
// #mysubid is inside #mymainid
}
var isInPath = $("#mysubid").closest("#mymainid").length > 0;
if( $("#mymainid").find("#mysubid").length > 0 )
if($('#mysubid','#mymainid').length)
{
}
This will check to see if #mysubid is within #mymainid
jQuery( selector, [ context ] )
selector: A string containing a selector expression
context: A DOM Element, Document, or jQuery to use as context
This is a just an overlaod for $('#mymainid').find('#mysubid').lentgh btw, verified from: http://github.com/jquery/jquery/blob/master/src/core.js#L162
On another note, using a method such as $('#a #b') resorts to using the Sizzle Selector witch is slower than doing $('#a',$('#b')), witch uses purely javascript's getElementById
Note: as jQuery returns an empty object by default if the selection is not found you should always use length.
If you want to see the entire chain as an array use elm.parentNode and work backwards. So, to answer your question (and the depth or distance between the elements) in POJ, you can use:
var doc = document,
child = doc.getElementById("mysubid"),
parent = doc.getElementById("mymainid"),
getParents = function (elm) {
var a = [], p = elm.parentNode;
while (p) {
a.push(p);
p = p.parentNode;
}
return a;
};
getParents(child).indexOf(parent);
I tried on various browsers and the DOM function below is between 3 to 10 times faster than the selector methods(jQuery or document.querySelectorAll)
function is(parent){
return {
aParentOf:function(child){
var cp = child.parentNode;
if(cp){
return cp.id === parent.id ?
true : is(parent).aParentOf(cp);
}
}
}
}
The call below will return true if A is a parent of D
is(document.getElementById('A')).aParentOf(document.getElementById('D'))
For just few calls I would use the $('#A #D').length
For very frequent calls I would use the DOM one.
Using the 'is' method actually returns a boolean.
if($('#mymainid').is(':has(#mysubid)')) // true
Going the other direction...
if($('#mysubid').parents('#mymainid').length) // 1

Categories

Resources