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

Найти ближайший предыдущий элемент jQuery

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

Если бы у меня был этот HTML, например,

<h3>
    <span>
        <b>Whaddup?</b>
    </span>
</h3>
<h3>
    <span>
        <b>Hello</b>
    </span>
</h3>
<div>
    <div>
        <img />
    </div>
     <span id="me"></span>
</div>
<h3>
    <span>
        <b>Goodbye</b>
    </span>
</h3>

Я хотел бы иметь возможность сделать что-то вроде этого:

var link = $("#me").closestPreviousElement("h3 span b");
console.log(link.text()); //"Hello"

Есть ли простой способ сделать это в jQuery?

РЕДАКТИРОВАТЬ. Я должен был уточнить свою спецификацию. $("#me") может иметь или не иметь родительский div. Код не должен предполагать, что он это делает. Я не знаю ничего об окружающих элементах.

4b9b3361

Ответ 1

var link = $("#me").closest(":has(h3 span b)").find('h3 span b');

Пример: http://jsfiddle.net/e27r8/

Это использует метод closest() [docs], чтобы получить первый предка, который имеет вложенный h3 span b, а затем .find().

Конечно, у вас может быть несколько совпадений.


В противном случае вы смотрите на более прямой обход.

var link = $("#me").closest("h3 + div").prev().find('span b');

edit: Этот файл работает с вашим обновленным HTML.

Пример: http://jsfiddle.net/e27r8/2/


EDIT: Обновлено для решения обновленного вопроса.

var link = $("#me").closest("h3 + *").prev().find('span b');

Это делает целевой элемент .closest() общим, поэтому даже если родителя нет, он все равно будет работать.

Пример: http://jsfiddle.net/e27r8/4/

Ответ 2

Нет, нет "простого" способа. Лучше всего сделать цикл, в котором вы сначала проверяете каждого предыдущего брата, затем переходите к родительскому node и всем своим предыдущим братьям и сестрам.

Вам нужно разбить селектор на два, 1, чтобы проверить, может ли текущий node быть верхний уровень node в вашем селекторе, и 1, чтобы проверить, совпадают ли его потомки.

Изменить: Это может быть плагин. Вы можете использовать это с любым селектором в любом HTML:

(function($) {
    $.fn.closestPrior = function(selector) {
        selector = selector.replace(/^\s+|\s+$/g, "");
        var combinator = selector.search(/[ +~>]|$/);
        var parent = selector.substr(0, combinator);
        var children = selector.substr(combinator);
        var el = this;
        var match = $();
        while (el.length && !match.length) {
            el = el.prev();
            if (!el.length) {
                var par = el.parent();
                // Don't use the parent - you've already checked all of the previous 
                // elements in this parent, move to its previous sibling, if any.
                while (par.length && !par.prev().length) {
                    par = par.parent();
                }
                el = par.prev();
                if (!el.length) {
                    break;
                }
            }
            if (el.is(parent) && el.find(children).length) {
                match = el.find(children).last();
            }
            else if (el.find(selector).length) {
                match = el.find(selector).last();
            }
        }
        return match;
    }
})(jQuery);

Ответ 4

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

var ClosestPrev = $( StartObject ).prevAll( '.selectorClass' ).first();
var ClosestNext = $( StartObject ).nextAll( '.selectorClass' ).first();

Я не уверен на 100% от порядка возврата коллекции из функций nextAll/prevAll, но в моем тестовом случае кажется, что массив находится в ожидаемом направлении. Может быть полезно, если кто-то может прояснить внутренности jquery для обеспечения надежной гарантии надежности.

Ответ 5

var link = $("#me").closest(":has(h3 span b)").find('span b').text();