Estoy tratando de encontrar el elemento más cercano con un nombre de etiqueta específico sin jquery. Cuando hago clic en un <th>
, quiero tener acceso al <tbody>
para esa tabla. Sugerencias Leí sobre la compensación, pero realmente no lo entendí demasiado. Debería usar:
Suponga que th ya está configurado para hacer clic en el elemento
th.offsetParent.getElementsByTagName('tbody')[0]
javascript
hunterc
fuente
fuente
parentNode
: developer.mozilla.org/en-US/docs/Web/API/Node.parentNodeel.closest('tbody')
para navegadores que no son ie. Vea una respuesta más elaborada + polyfill a continuación.Respuestas:
Poco (muy) tarde para la fiesta, pero no obstante. Esto debería hacer el truco :
function closest(el, selector) { var matchesFn; // find vendor prefix ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) { if (typeof document.body[fn] == 'function') { matchesFn = fn; return true; } return false; }) var parent; // traverse parents while (el) { parent = el.parentElement; if (parent && parent[matchesFn](selector)) { return parent; } el = parent; } return null; }
fuente
el
Cambié el código para que también pruebe el elemento que jQuery.closest () y también Element.closest ().for( var parent = el ; parent !== null && !parent[matchesFn](selector) ; parent = el.parentElement ){ el = parent; } return parent;
parent
en el alcance global (!)el.parentNode
o esto se romperá al atravesar un SVG en IE.Muy simple:
el.closest('tbody')
Compatible con todos los navegadores excepto IE.
ACTUALIZACIÓN : Edge ahora también lo admite.
No es necesario jQuery. Además, reemplazar jQuery
$(this).closest('tbody')
con$(this.closest('tbody'))
aumentará el rendimiento, significativamente cuando no se encuentre el elemento.Polyfill para IE:
if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector; if (!Element.prototype.closest) Element.prototype.closest = function (selector) { var el = this; while (el) { if (el.matches(selector)) { return el; } el = el.parentElement; } };
Tenga en cuenta que no hay
return
cuando no se encontró el elemento, regresando efectivamenteundefined
cuando no se encontró el elemento más cercano.Para obtener más detalles, consulte: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
fuente
Así es como se obtiene el elemento más cercano por nombre de etiqueta sin jQuery:
function getClosest(el, tag) { // this is necessary since nodeName is always in upper case tag = tag.toUpperCase(); do { if (el.nodeName === tag) { // tag name is found! let's return it. :) return el; } } while (el = el.parentNode); // not found :( return null; } getClosest(th, 'tbody');
fuente
Existe una función estandarizada para hacer esto: Element.closest . La mayoría de los navegadores, excepto IE11, lo admiten ( detalles por caniuse.com ). Los documentos de MDN también incluyen un polyfill en caso de que tenga que apuntar a navegadores más antiguos.
Para encontrar el
tbody
padre más cercano dadoth
que podría hacer:th.closest('tbody');
En caso de que desee escribir la función usted mismo, esto es lo que se me ocurrió:
function findClosestParent (startElement, fn) { var parent = startElement.parentElement; if (!parent) return undefined; return fn(parent) ? parent : findClosestParent(parent, fn); }
Para encontrar el padre más cercano por nombre de etiqueta, puede usarlo así:
findClosestParent(x, element => return element.tagName === "SECTION");
fuente
function closest(el, sel) { if (el != null) return el.matches(sel) ? el : (el.querySelector(sel) || closest(el.parentNode, sel)); }
Esta solución utiliza algunas de las características más recientes de la especificación HTML 5, y su uso en navegadores más antiguos / incompatibles (lea: Internet Explorer) requerirá un polyfill.
fuente
Para extender la respuesta de @SalmanPK
permitirá usar el nodo como selector, útil cuando se trabaja con eventos como el mouseover.
function closest(el, selector) { if (typeof selector === 'string') { matches = el.webkitMatchesSelector ? 'webkitMatchesSelector' : (el.msMatchesSelector ? 'msMatchesSelector' : 'matches'); while (el.parentElement) { if (el[matches](selector)) { return el }; el = el.parentElement; } } else { while (el.parentElement) { if (el === selector) { return el }; el = el.parentElement; } } return null; }
fuente
Aquí está la función simple que estoy usando: -
function closest(el, selector) { var matches = el.webkitMatchesSelector ? 'webkitMatchesSelector' : (el.msMatchesSelector ? 'msMatchesSelector' : 'matches'); while (el.parentElement) { if (el[matches](selector)) return el; el = el.parentElement; } return null; }
fuente
Resumen:
Para encontrar un antepasado en particular, podemos usar:
Element.closest();
Esta función toma una cadena de selección de CSS como argumento. luego devuelve el ancestro más cercano del elemento actual (o el elemento en sí) que coincide con el selector de CSS que se pasó en los argumentos. Si no hay antepasado, regresará
null
.Ejemplo:
const child = document.querySelector('.child'); // select the child console.dir(child.closest('.parent').className); // check if there is any ancestor called parent
<div class="parent"> <div></div> <div> <div></div> <div class="child"></div> </div> </div>
fuente
Obtenga el elemento DOM más cercano en el árbol que contiene una clase, ID, atributo de datos o etiqueta. Incluye el propio elemento. Compatible con IE6.
var getClosest = function (elem, selector) { var firstChar = selector.charAt(0); // Get closest match for ( ; elem && elem !== document; elem = elem.parentNode ) { // If selector is a class if ( firstChar === '.' ) { if ( elem.classList.contains( selector.substr(1) ) ) { return elem; } } // If selector is an ID if ( firstChar === '#' ) { if ( elem.id === selector.substr(1) ) { return elem; } } // If selector is a data attribute if ( firstChar === '[' ) { if ( elem.hasAttribute( selector.substr(1, selector.length - 2) ) ) { return elem; } } // If selector is a tag if ( elem.tagName.toLowerCase() === selector ) { return elem; } } return false; }; var elem = document.querySelector('#some-element'); var closest = getClosest(elem, '.some-class'); var closestLink = getClosest(elem, 'a'); var closestExcludingElement = getClosest(elem.parentNode, '.some-class');
fuente
firstChar
lugar de para todasIF
?for
bucle oculto ?Encuentre los childNodes de Elements más cercanos.
closest:function(el, selector,userMatchFn) { var matchesFn; // find vendor prefix ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) { if (typeof document.body[fn] == 'function') { matchesFn = fn; return true; } return false; }); function findInChilds(el){ if(!el) return false; if(el && el[matchesFn] && el[matchesFn](selector) && userMatchFn(el) ) return [el]; var resultAsArr=[]; if(el.childNodes && el.childNodes.length){ for(var i=0;i< el.childNodes.length;i++) { var child=el.childNodes[i]; var resultForChild=findInChilds(child); if(resultForChild instanceof Array){ for(var j=0;j<resultForChild.length;j++) { resultAsArr.push(resultForChild[j]); } } } } return resultAsArr.length?resultAsArr: false; } var parent; if(!userMatchFn || arguments.length==2) userMatchFn=function(){return true;} while (el) { parent = el.parentElement; result=findInChilds(parent); if (result) return result; el = parent; } return null;
}
fuente
Aquí.
function findNearest(el, tag) { while( el && el.tagName && el.tagName !== tag.toUpperCase()) { el = el.nextSibling; } return el; }
Solo encuentra hermanos más abajo en el árbol. Use previousSibling para ir al revés O use variables para recorrer ambos caminos y regresar lo que se encuentre primero. Obtiene la idea general, pero si desea atravesar parentNodes o hijos si un hermano no coincide, también puede usar jQuery. En ese punto, fácilmente vale la pena.
fuente
Un poco tarde para la fiesta, pero mientras pasaba y respondía una pregunta muy similar, dejo aquí mi solución: podemos decir que es el
closest()
enfoque de JQuery , pero en JavaScript.No necesita pollyfills y son navegadores más antiguos y compatible con IE (:-)): https://stackoverflow.com/a/48726873/2816279
fuente
Creo que el código más fácil de atrapar con jquery más cercano:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script> $(document).ready(function () { $(".add").on("click", function () { var v = $(this).closest(".division").find("input[name='roll']").val(); alert(v); }); }); </script> <?php for ($i = 1; $i <= 5; $i++) { echo'<div class = "division">' . '<form method="POST" action="">' . '<p><input type="number" name="roll" placeholder="Enter Roll"></p>' . '<p><input type="button" class="add" name = "submit" value = "Click"></p>' . '</form></div>'; } ?>
Muchas gracias.
fuente