Найти ближайший предыдущий элемент 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. Код не должен предполагать, что он это делает. Я не знаю ничего об окружающих элементах.
Ответы
Ответ 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);
Ответ 3
см. http://api.jquery.com/prev/
var link = $("#me").parent("div").prev("h3").find("b");
alert(link.text());
см. http://jsfiddle.net/gBwLq/
Ответ 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();