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

JavaScript: как получить родительский элемент по селектору?

Пример:

<div someAttr="parentDiv. We need to get it from child.">
    <table> ....
        <td> <div id="myDiv"></div> </td>
    ... </table>
</div>

Я хочу получить родительский селектор из внутреннего элемента div (в примере с классом myDiv). Как его получить БЕЗ jQuery, только JS?

Что-то вроде:

var div = document.getElementById('myDiv');
div.someParentFindMethod('some selector');
4b9b3361

Ответ 1

Здесь самая базовая версия:

function collectionHas(a, b) { //helper function (see below)
    for(var i = 0, len = a.length; i < len; i ++) {
        if(a[i] == b) return true;
    }
    return false;
}
function findParentBySelector(elm, selector) {
    var all = document.querySelectorAll(selector);
    var cur = elm.parentNode;
    while(cur && !collectionHas(all, cur)) { //keep going up until you find a match
        cur = cur.parentNode; //go up
    }
    return cur; //will return null if not found
}

var yourElm = document.getElementById("yourElm"); //div in your original code
var selector = ".yes";
var parent = findParentBySelector(yourElm, selector);

Ответ 2

Вы можете использовать closest() в современных браузерах:

var div = document.querySelector('div#myDiv');
div.closest('div[someAtrr]');

Используйте обнаружение объектов для предоставления полифилла или альтернативного метода обратной совместимости с IE.

Ответ 3

Находит ближайший родитель (или сам элемент), который соответствует данному селектору. Также включен селектор, чтобы остановить поиск, если вы знаете общего предка, на который вы должны прекратить поиск.

function closest(el, selector, stopSelector) {
  var retval = null;
  while (el) {
    if (el.matches(selector)) {
      retval = el;
      break
    } else if (stopSelector && el.matches(stopSelector)) {
      break
    }
    el = el.parentElement;
  }
  return retval;
}

Ответ 4

Использование ответа на leech с помощью indexOf (для поддержки IE)

Это то, о чем говорила пиявка, но заставляя ее работать в IE (IE не поддерживает совпадения):

function closest(el, selector, stopSelector) {
  var retval = null;
  while (el) {
    if (el.className.indexOf(selector) > -1) {
      retval = el;
      break
    } else if (stopSelector && el.className.indexOf(stopSelector) > -1) {
      break
    }
    el = el.parentElement;
  }
  return retval;
}

Это не идеально, но работает, если селектор достаточно уникален, поэтому он не будет случайно соответствовать неправильному элементу.

Ответ 5

Вот рекурсивное решение:

function closest(el, selector, stopSelector) {
  if(!el || !el.parentElement) return null
  else if(stopSelector && el.parentElement.matches(stopSelector)) return null
  else if(el.parentElement.matches(selector)) return el.parentElement
  else return closest(el.parentElement, selector, stopSelector)
}

Ответ 6

простой пример функции parent_by_selector, возвращающей родительский или нулевой (без селектора):

function parent_by_selector(node, selector, stop_selector = 'body') {
  var parent = node.parentNode;
  while (true) {
    if (parent.matches(stop_selector)) break;
    if (parent.matches(selector)) break;
    parent = parent.parentNode; // get upper parent and check again
  }
  if (parent.matches(stop_selector)) parent = null; // when parent is a tag 'body' -> parent not found
  return parent;
};

Ответ 7

Я подумал, что приведу гораздо более надежный пример, в том числе в машинописном тексте, но его будет легко конвертировать в чистый javascript. Эта функция будет запрашивать родителей, используя идентификатор, например "# my-element", или класс ".my-class" и, в отличие от некоторых из этих ответов, будет обрабатывать несколько классов. Я обнаружил, что назвал некоторые аналогично, и поэтому в приведенных выше примерах были найдены неправильные вещи.

function queryParentElement(el:HTMLElement | null, selector:string) {
    let isIDSelector = selector.indexOf("#") === 0
    if (selector.indexOf('.') === 0 || selector.indexOf('#') === 0) {
        selector = selector.slice(1)
    }
    while (el) {
        if (isIDSelector) {
            if (el.id === selector) {
                return el
            }
        }
        else if (el.classList.contains(selector)) {
            return el;
        }
        el = el.parentElement;
    }
    return null;
}

Для выбора по имени класса:

let elementByClassName = queryParentElement(someElement,".my-class")

Для выбора по идентификатору:

let elementByID = queryParentElement(someElement,"#my-element")

Ответ 8

Вот простой способ доступа к родительскому id

document.getElementById("child1").parentNode;

сделает магию для доступа к родительскому div.

<html>
<head>
</head>
<body id="body">
<script>
function alertAncestorsUntilID() {
var a = document.getElementById("child").parentNode;
alert(a.id);
}
</script>
<div id="master">
Master
<div id="child">Child</div>
</div>
<script>
alertAncestorsUntilID();
</script>
</body>
</html>