jQuery - предложения для обхода "nextWhile"? - PullRequest
4 голосов
/ 12 февраля 2009

jQuery в настоящее время имеет .next(filter) и .nextAll(filter), но мне нужно что-то, что подходит посередине из них - по сути, .nextWhile(filter), который многократно делает следующее, пока фильтр больше не будет истинным, затем останавливается (вместо того, чтобы продолжать конец).

Чтобы продемонстрировать это, ниже приведен некоторый упрощенный HTML - (на самом деле он генерируется динамически, случайный порядок / данные, больше столбцов, собственные имена классов и т. Д.).

<table>
    <thead>
        <tr>
            <th>...</th>
        </tr>
    </thead>
    <tbody>

        <tr class="x"><td>a <button>Show/Hide</button></td></tr>
            <tr class="x y"><td>a1</td></tr>
            <tr class="x y"><td>a2</td></tr>

        <tr class="z"><td>b</td></tr>

        <tr class="z"><td>c</td></tr>

        <tr class="x"><td>d <button>Show/Hide</button></td></tr>
            <tr class="x y"><td>d1</td></tr>
            <tr class="x y"><td>d2</td></tr>
            <tr class="x y"><td>d3</td></tr>

        <tr class="z"><td>e</td></tr>

        <tr class="x"><td>f</td></tr>

        <tr class="x"><td>g <button>Show/Hide</button></td></tr>
            <tr class="x y"><td>g1</td></tr>
            <tr class="x y"><td>g2</td></tr>

    </tbody>
</table>

И против этого запускается некоторый JavaScript:

<script type="text/javascript">
    var $j = jQuery.noConflict();

    $j().ready(init);

    function init()
    {
        $j('tr.y').hide();
        $j('tr.x button').click( toggleRelated );
    }

    function toggleRelated()
    {
        // Only toggles one row
        // $j(this).parents('tr').next('.y').toggle();

        // Toggles unrelated ones also
        $j(this).parents('tr').nextAll('.y').toggle();

        // Not currently a jQuery construct
        // $j(this).parents('tr').nextWhile('.y').toggle();
    }

</script>

Есть ли простой способ реализовать эту nextWhile конструкцию?

В идеале это должно быть достигнуто без изменения текущего HTML.

Ответы [ 3 ]

6 голосов
/ 19 марта 2013

В jQuery вы можете создать nextWhile() эквивалент, используя nextUntil() метод и :not селектор. Проще говоря, while (condition is true) { do something } - это то же самое, что сказать until (condition is false) { do something }.

Рассмотрим этот уловочный пример, в котором вам необходимо выбрать все элементы .child, следующие за первым .parent:

<ul id="test">
  <li class="parent"></li>
  <li class="child"></li>
  <li class="child"></li>
  <li class="child"></li>
  <li class="divider"></li>
  <li class="parent"></li>
  <li class="child"></li>
  <li class="child"></li>
  <li class="child"></li>
</ul>

Следующий код приблизительно эквивалентен .nextWhile(".child") и выбирает три элемента .child:

$("#test .parent:first").nextUntil(":not(.child)");
1 голос
/ 12 февраля 2009

ОБНОВЛЕНИЕ: Отказались от идеи рекурсии и решили подсчитать и нарезать (см. Последний пример).

Начальная попытка:
Этот код содержит ошибки - он возвращает только последние два элемента, поэтому не работает для 3+ элементов.

jQuery.fn.nextWhile = function(f)
{
    if( this.next(f).html() )
    {
        return this.next(f).nextWhile(f).andSelf();
    }
    else
    {
        return this;
    }
};


Текущая версия:

jQuery.fn.nextWhile = function(f)
{
    var Next = this.next(f);
    var Pos = 0;

    while( Next.length > 0 )
    {
        Pos++;
        Next = Next.next(f);
    }

    return this.nextAll(f).slice(0,Pos);
}

Кажется, это работает нормально, но я не уверен, есть ли какие-либо потери производительности для выбора всего, а затем вырезания из него только нескольких?

0 голосов
/ 07 июля 2015

Моя версия:

$.fn.extend({
  nextWhile: function(selector) {
    var $result = $([]);
    this.each(function() {
      var $next = $(this).next();
      while ($next.is(selector)) {
        $result = $result.add($next);
        $next = $next.next();
      }
    });
    return $result;
  }
});
...