0

jQuery: Как реализовать "hasParent"?

20

Описание проблемы:

Я использую jQuery и столкнулся с проблемой, связанной с выбором элементов на основе их предков. Методы parent([selector]) и parents([selector]) выбирают только родителей, но мне нужно отобрать элементы, у которых есть определённые предки.

Я знаю, что метод "has" позволяет выбрать элементы с определёнными потомками, но мне нужен эквивалент для предков.

У меня уже есть jQuery объект, состоящий из элементов 2, 3, 4 и 5. Я хочу выбрать именно те элементы, которые имеют родителя с классом "x".

Пример кода:

<ul class="x">
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>
<ul class="y">
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

В этом примере я хочу, чтобы результатом были элементы 2 и 3, так как они имеют родителя с классом "x".

Я уже имею контекст элемента дальше по иерархии, так что провести запрос сверху вниз не получится. Есть ли метод или способ в jQuery, который позволит сделать то, что мне нужно?

Надеюсь, теперь это яснее.

5 ответ(ов)

0

Для чистого и переиспользуемого решения рассмотрите возможность расширения объекта jQuery.fn с помощью собственного метода, который будет использоваться для определения наличия конкретного предка для любого заданного элемента:

// Расширяем jQuery.fn новым методом
jQuery.extend( jQuery.fn, {
    // Имя нашего метода и один параметр (селектора родителя)
    within: function( pSelector ) {
        // Возвращаем подмножество элементов, используя jQuery.filter
        return this.filter(function(){
            // Возвращаем true/false в зависимости от наличия в родителе
            return $(this).closest( pSelector ).length;
        });
    }
});

Это создает новый метод $.fn.within, который мы можем использовать для фильтрации результатов:

$("li").within(".x").css("background", "red");

Этот код выбирает все элементы списка в документе, а затем фильтрует только те, которые имеют .x в качестве предка. Поскольку используется jQuery, вы можете передать более сложный селектор:

$("li").within(".x, .y").css("background", "red");

Этот код отфильтрует коллекцию до элементов, которые являются потомками либо .x, либо .y, или обоих.

Пробный пример: http://jsfiddle.net/jonathansampson/6GMN5/

0

Вы можете использовать следующий код для проверки, если элемент с классом .foo имеет родителя, соответствующего селектору .parentSelector:

if ( $('.foo').parents('.parentSelector').length ) {
    // У элемента есть родитель, соответствующий селектору
}

В этом фрагменте кода метод parents() ищет всех предков элемента с классом .foo, которые соответствуют селектору .parentSelector. Если длина результата (т.е. количество найденных предков) больше нуля, это означает, что такой родитель существует.

0

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

$.fn.hasAncestor = function(a) {
    return this.filter(function() {
        return !!$(this).closest(a).length;
    });
};

$('.element').hasAncestor('.container').myAction();

В данном примере метод hasAncestor добавляется к jQuery, позволяя вам проверять, есть ли у элемента указанный родитель. Вызов $('.element').hasAncestor('.container') вернет все элементы с классом element, которые имеют родителя с классом container. После этого вы можете вызвать ваш метод myAction() на отфильтрованных элементах.

Вот HTML-код для дополнительного контекста:

<div class="container">
  <span>
    <strong class="element">strong</strong>
  </span>
</div>

Таким образом, если вы хотите узнать, является ли элемент strong потомком div с классом container, этот код будет работать корректно.

0

В вашем коде используется метод hasParent, который проверяет, есть ли у текущего элемента родительский элемент, соответствующий селектору e. Давайте подробнее рассмотрим ваши примеры.

  1. В первом примере:

    $('body').hasParent('html') // true
    

    Здесь вы проверяете, имеет ли элемент body родителя, который является элементом html. Так как body действительно является дочерним элементом html, метод возвращает true.

  2. Во втором примере:

    $('div#myDiv').hasParent($('body')) // true
    

    В этом коде вы проверяете, есть ли у элемента div с id="myDiv" родитель, который равен элементу body. Если myDiv находится внутри body, то вызов также вернет true.

Описание метода hasParent:

Ваш метод hasParent реализован с использованием jQuery и выглядит следующим образом:

// проверяет, есть ли у текущего элемента родительский элемент 'e' 
$.fn.hasParent = function (e) {
    return !!$(this).parents(e).length
}
  • $(this) ссылается на текущий jQuery объект.
  • this.parents(e) находит всех родительских элементов, соответствующих селектору e.
  • length вернет количество найденных элементов: если оно больше нуля, то это значит, что родитель существует, и метод вернет true.

Таким образом, ваш код работает корректно и удобен для использования при проверке иерархии DOM-элементов. Если у вас возникли дополнительные вопросы, не стесняйтесь их задавать!

0

Вы можете использовать filter напрямую (без функции, вызывающей closest), и это даст вам более высокую производительность. Просто используйте селектор, который соответствует элементам, содержащимся внутри .x:

$("li").filter(".x *")

Это также немного отличается от решений с closest, предложенных другими, так как не будет соответствовать элементу, если он сам имеет данный класс, а только если он находится внутри элемента с этим классом.

Если вы хотите, чтобы соответствовал и сам элемент с классом, то это можно немного изменить:

$("li").filter(".x, .x *")

Пример с применением стиля:

$("li").filter(".x *").css("background", "red");

Вот пример кода:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="x"><li>1</li><li>2</li><li>3</li></ul>
<ul class="y"><li>4</li><li>5</li><li>6</li></ul>

С помощью этого подхода вы сможете эффективно отфильтровать элементы и применить к ним стили.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь