2008-09-17 3 views
7

Данный пример:Как выбрать последовательные элементы, которые соответствуют фильтр

<img class="a" /> 
<img /> 
<img class="a" /> 
<img class="a" id="active" /> 
<img class="a" /> 
<img class="a" /> 
<img /> 
<img class="a" /> 

(я просто использовал IMG теги в качестве примера, что это не то, что это в моем коде)

Используя jQuery, как бы вы выбрали теги img с классом «a», которые находятся рядом с # активным (средний четвертый, в этом примере)?

Вы можете сделать это довольно легко, перейдя по всем последующим и предшествующим элементам, остановившись, когда условие фильтра не удастся, но мне было интересно, может ли jQuery быть изначально?

ответ

4

Вот что я придумал в конце.

// here's our active element. 
var $active = $('#active'); 

// here is the filter we'll be testing against. 
var filter = "img.a"; 

// $all will be the final jQuery object with all the consecutively matched elements. 
// start it out by populating it with the current object. 
var $all = $active; 

for ($curr = $active.prev(filter); $curr.length > 0; $curr = $curr.prev(filter)) { 
    $all = $all.add($curr); 
} 
for ($curr = $td.next(filter); $curr.length > 0; $curr = $curr.next(filter)) { 
    $all = $all.add($curr); 
} 

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


Edit: Я с тех пор нашел, что функция каждого() будет делать это достаточно хорошо для некоторых целей. В моем случае это работает не так, как будто я хочу, чтобы для всех этих элементов был один объект jQuery, но вот как вы могли бы использовать каждый для другой цели (скрывая последовательные «.a» элементы в этом примере :)

$('#active') 
    .nextAll() 
    .each(hideConsecutive) 
    .end() 
    .prevAll() 
    .each(hideConsecutive) 
; 
function hideConsecutive(index, element) { 
    var $e = $(element); 
    if (!$e.is(".a")) { 
     return false; // this stops the each function. 
    } else { 
     $e.hide('slow'); 
    } 
} 

-

Edit: Я поместил это вместе в плагин в настоящее время. Посмотрите на http://plugins.jquery.com/project/Adjacent, если вам интересно.

2

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

+0

Не могли бы вы предоставить фрагмент кода, пожалуйста. Было бы полезно, поскольку я не совсем понял, что вы имеете в виду. – 2013-07-03 06:12:19

0

Это еще один способ сделать это, хотя ответ селектора родственного довольно прохладно:

var next = $('#active').next('.a'); 
var prev = $('#active').prev('.a'); 

Edit: Я перечитываю ваши требования, и это не совсем то, что вы хотите , Вы можете использовать nextAll и prevAll, но те тоже не останавливались на IMG без имени класса.

1

В приведенном ниже коде будут добавлены две новые функции nextConsecutive() и prevConsecutive(). Они должны делать то, что вы хотите.

$ .each (['prev', 'next'], function (unusedIndex, name) { $.fn [имя + «последовательный»] = функция (matchExpr) {

var $all = 
     (name == 'prev') 
      ? $(this).prevAll() 
      : $(this).nextAll(); 
    if (!matchExpr) 
     return $all; 

    var $notMatch = $($all).not(matchExpr).filter(':first'); 
    if ($all.index($notMatch) != -1) 
     return $allConsecutive = $all.slice(0, $all.index($notMatch)); 

    return $all; 
}; 

});

Смежные вопросы