I have the following code, which is written in DOM API instead of jquery. I'm not sure why. It's inside the submit function for jquery form validation. I need to change the "parentNode" part so that instead of "parent" it is "closest." I'm no good with javascript. I tried my hand at converting this to jquery, but wasn't able to get that to work. Basically, if this were jquery, I'd need to change .parent() to .closest().
var summary = "";
$.each(element, function() {
summary += "<li>" + this.element.parentNode.getElementsByTagName('label')[0].innerHTML.replace("\<span\>*\<\/span\>","") + "</li>";
});
summary = summary.replace(/\<li\>.+\<\/li\>\1/, "$1");
alert(summary);
Is this possible to do with javascript? Or, is there an easy way to convert this to jquery?
UPDATE: Here is a fiddle to help explain what I'm trying to accomplish. Basically, because I added a 'span' tag around one of the inputs, the 'p' tag is no longer the parent. As such, the parentNode is not finding the 'p' tag anymore.
/
UPDATE 2 -- THE previous fiddle link was incorrect. The link above is the right one.
How can I modify to find the <p>
tag regardless of whether it is the direct parent, or a grandparent?
I have the following code, which is written in DOM API instead of jquery. I'm not sure why. It's inside the submit function for jquery form validation. I need to change the "parentNode" part so that instead of "parent" it is "closest." I'm no good with javascript. I tried my hand at converting this to jquery, but wasn't able to get that to work. Basically, if this were jquery, I'd need to change .parent() to .closest().
var summary = "";
$.each(element, function() {
summary += "<li>" + this.element.parentNode.getElementsByTagName('label')[0].innerHTML.replace("\<span\>*\<\/span\>","") + "</li>";
});
summary = summary.replace(/\<li\>.+\<\/li\>\1/, "$1");
alert(summary);
Is this possible to do with javascript? Or, is there an easy way to convert this to jquery?
UPDATE: Here is a fiddle to help explain what I'm trying to accomplish. Basically, because I added a 'span' tag around one of the inputs, the 'p' tag is no longer the parent. As such, the parentNode is not finding the 'p' tag anymore.
http://jsfiddle.net/9um8xt79/1/
UPDATE 2 -- THE previous fiddle link was incorrect. The link above is the right one.
How can I modify to find the <p>
tag regardless of whether it is the direct parent, or a grandparent?
- 6 "which is written in javascript instead of jquery" - this overdrove my oxymoron/contradiction detector. – The Paramagnetic Croissant Commented Aug 31, 2014 at 23:52
- 1 Sorry, I'm using the wrong terminology. I realize jquery IS javascript. I'm not sure what you call the parentNode and getElementsByTagName parts.... XML? – Lindsay Commented Aug 31, 2014 at 23:54
- 1 @Lindsay the term you're looking for is native DOM API. – Fabrício Matté Commented Aug 31, 2014 at 23:56
- Thank you Fabricio. Is there any reason something like this would need to be written this way? – Lindsay Commented Aug 31, 2014 at 23:57
- 1 @Lindsay well, I assume you know API is the term to reference a software component's public operations, methods, types, input and output. And you're talking about DOM methods. So yep, DOM API. – Fabrício Matté Commented Sep 1, 2014 at 0:11
4 Answers
Reset to default 19Hello from the future (2019)! This is now directly possible with native DOM API in modern browsers (that is, not Internet Explorer):
Element.closest
So you can replace jQuery(selector).closest
with document.querySelector(selector).closest
.
Similarly, you should be able to eliminate other jQuery
functions in your code such as .children()
by using native .children
and .addClass()
by using .classList.add()
.
See also
- YouMightNotNeedJquery.com
- "Native Equivalents of JQuery Methods - Part 1: Selecting DOM Elements" (links for other parts are at the bottom of this codepen)
- "Native JavaScript Equivalents of jQuery Methods: the DOM and Forms"
Here's the javascript for the .closest property:
closest: function( selectors, context ) {
var cur,
i = 0,
l = this.length,
matched = [],
pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
jQuery( selectors, context || this.context ) :
0;
for ( ; i < l; i++ ) {
for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
// Always skip document fragments
if ( cur.nodeType < 11 && (pos ?
pos.index(cur) > -1 :
// Don't pass non-elements to Sizzle
cur.nodeType === 1 &&
jQuery.find.matchesSelector(cur, selectors)) ) {
matched.push( cur );
break;
}
}
}
Whenever you're trying to figure out something is done in jQuery, you can always just take a look at the jQuery source and reverse engineer it to your scenario. Although there will be times when this won't work, the way your question is phrased, this is where I'd start.
Source: http://code.jquery.com/jquery-2.1.1.js
Reading your question carefully, I think you want something like
var summary = "";
$(element).each(function (id, ele) {
summary += "<li>" + $(ele).closest("label").html().replace("\<span\>*\<\/span\>","") + "</li>";
});
summary = summary.replace(/\<li\>.+\<\/li\>\1/, "$1");
But I'm not sure what you're doing with this last line. First you add all the label-Elements as li-Elements and then you remove all those li-s? But I'm not really a RegExp profi so I might miss something here.
Maybe I'm a bit late ;-) but here is a simple recursive function (calls it self with the parentNode
to be analised) in plain old JS:
function closest( e, classname ) {
if( hasClass( e, classname ) ) {
//We found it!
return e;
}
//console.error(e.parentNode.nodeName);
if(e.parentNode.nodeName != 'BODY') //Last possibility! There's no parent behind!
return e.parentNode && closest( e.parentNode, classname );
//Didn't found it?
return null;
}
hasClass() function (the equivalente to JQuery hasClass()
) depends on the browser knowing classList
- as in nowadays is almost the case.
But, anyway, here it goes for both older and (the so called) newer browsers:
var
hasClass
;
if ( 'classList' in document.documentElement ) {
hasClass = function( elem, c ) {
return elem.classList.contains( c );
};
}
else {
hasClass = function( elem, c ) {
return classReg( c ).test( elem.className );
};
}
As notice, for older browsers, we use a RegExp
to string comparision.
Here it is (and, promisse, final stuff :-) ):
function classReg( className ) {
return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
}
And that's it.
Now it's explained, if anyone uses the complete set of "tools", off course you have to code it down the inverse way (1st classReg()
, then hasClass
stuff and final our closest()
queen).
Also, if you noticed, you gain here 2 equivalente JQuery tools (closest()
and hasClass()
) that you can use in multiple situations - as I use them for several years, now:
hasClass( elem, 'my-class-to-check' ) //<= returns true || false
closest( elem, 'my-class-to-look-up' ) //<= returns the look-up obj || null