Подтвердить что ты не робот

Поиск ближайшего элемента без jQuery

Я пытаюсь найти ближайший элемент с определенным именем тега без jquery. Когда я нажимаю <th> я хочу получить доступ к <tbody> для этой таблицы. Предложения? Я читал о смещении, но не слишком понимал это. Должен ли я просто использовать:

Предположим, что th уже настроен на нажатый элемент th

th.offsetParent.getElementsByTagName('tbody')[0]
4b9b3361

Ответ 1

Немного (очень) поздно на вечеринку, но тем не менее. Это должно сделать трюк :

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;
}

Ответ 2

Очень просто:

el.closest('tbody')

Поддерживается во всех браузерах, кроме IE.
UPDATE: Edge также поддерживает его.

Нет необходимости в jQuery. Более того, замена jQuery $(this).closest('tbody') на $(this.closest('tbody')) повысит производительность, значительно, когда элемент не будет найден.

Polyfill для 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;
    }
};

Обратите внимание, что там нет return, когда элемент не был найден, эффективно возвращая undefined, когда ближайший элемент не был найден.

Подробнее см.: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest

Ответ 3

Вот как вы получите ближайший элемент по имени тега без 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 return it. :)
      return el;
    }
  } while (el = el.parentNode);

  // not found :(
  return null;
}

getClosest(th, 'tbody');

Ответ 4

function closest(el, sel) {
    if (el != null)
        return el.matches(sel) ? el 
            : (el.querySelector(sel) 
                || closest(el.parentNode, sel));
}

В этом решении используются некоторые из последних возможностей спецификации HTML 5, и использование этого в старых/несовместимых браузерах (далее: Internet Explorer) потребует polyfill.

Element.prototype.matches = (Element.prototype.matches || Element.prototype.mozMatchesSelector 
    || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector 
    || Element.prototype.webkitMatchesSelector || Element.prototype.webkitMatchesSelector);

Ответ 5

Для этого существует стандартизированная функция: Element.closest. Большинство браузеров, кроме IE11, поддерживают его (подробности от caniuse.com). Документы MDN также включают в себя полизаполнение на случай, если вам нужно настроить таргетинг на старые браузеры.

Для того, чтобы найти ближайший tbody родителя по заданному th вы могли бы сделать:

th.closest('tbody');

Если вы хотите написать функцию самостоятельно - вот что я придумал:

function findClosestParent (startElement, fn) {
  var parent = startElement.parentElement;
  if (!parent) return undefined;
  return fn(parent) ? parent : findClosestParent(parent, fn);
}

Чтобы найти ближайшего родителя по имени тега, вы можете использовать его следующим образом:

findClosestParent(x, element => return element.tagName === "SECTION");

Ответ 6

Здесь простая функция, которую я использую: -

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;
}

Ответ 7

Чтобы расширить ответ @SalmanPK

это позволит использовать узел в качестве селектора, что полезно при работе с такими событиями, как наведение мыши.

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;
}

Ответ 8

Резюме:

Для нахождения конкретного предка мы можем использовать:

Element.closest();

Эта функция принимает строку селектора CSS в качестве аргумента. затем он возвращает ближайшего предка текущего элемента (или самого элемента), который соответствует селектору CSS, который был передан в аргументах. Если предка нет, он вернет null.

Пример:

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>

Ответ 9

Получить самый близкий элемент DOM до дерева, содержащего класс, идентификатор, атрибут данных или тег. Включает сам элемент. Поддерживается обратно в 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');

Ответ 10

Здесь.

function findNearest(el, tag) {
    while( el && el.tagName && el.tagName !== tag.toUpperCase()) {
        el = el.nextSibling;     
    } return el;
} 

Только находит братьев и сестер дальше по дереву. Используйте previousSibling, чтобы пойти другим путем Или используйте переменные для прохождения в обоих направлениях и возврата в зависимости от того, что было найдено первым. Вы получаете общую идею, но если вы хотите пройти через parentNodes или дети, если родной брат не подходит, вы можете использовать jQuery. В этот момент это легко стоит.

Ответ 11

Найти ближайшие дочерние элементы Elements.

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;

}

Ответ 12

Немного опоздал на вечеринку, но когда я проходил мимо и просто отвечал на очень похожий вопрос, я оставляю здесь свое решение - мы можем сказать, что это подход JQuery closest(), но в довольно хорошем старом JavaScript.

Он не нуждается в поллифлеях и более старых браузерах, а также для IE (:-)): fooobar.com/questions/8970322/...

Ответ 13

я написал маленький отрывок, чтобы пройти через DOM, чтобы найти первый соответствующий parentNode.

Надеюсь, это когда-нибудь кому-нибудь поможет.

(/¯◡ ‿ ◡) ⊃━ ☆ ゚. * ・。 ゚,

function getFirstParentMatch(element, selector) {
  if (!element) {return element};
  element.matches(selector) || (element = (element.nodeName.toLowerCase() === 'html' ? false : getFirstParent(element.parentNode, selector)));
  return element;    
}

Ответ 14

Я думаю, что самый простой код, чтобы поймать с помощью jquery ближайший:

<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>';
}
?>

Большое спасибо.