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

JQuery найти следующий и предыдущий элемент

Я пытаюсь найти элемент next или prev текущего элемента. Но функция next() и prev() может работать только в области видимости, она не может выйти наружу. Например, это то, чего я хочу достичь:

<ul id="ul1">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>
    <ul id="ul2">
      <li>4</li>
      <li>
        <ul id="ul3">
          <li>5</li>
          <li>6</li>
        </ul>
      </li>
      <li>7</li>
      <li>8</li>
    </ul>
  </li>
  <li>9</li>
</ul>

Если текущий элемент ul1, следующий элемент <li>1</li>, элемент prev - null.

Если текущий элемент <li>1</li>, следующий элемент <li>2</li>, предыдущий элемент ul1

Если текущий элемент <li>8</li>, следующий элемент <li>9</li>, предшествующий элемент <li>7</li>

4b9b3361

Ответ 1

Прежде всего, это была действительно опрятная проблема. Спасибо за публикацию!

Я выполнил это с помощью закодированного оператора jQuery. Единственное, если вы запустите previous() в верхней части ul, вы получите body. Я думаю, что технически это имеет смысл. Однако, если это не является желаемым поведением, см. Мое обновление ниже.

Использование: next("#ul3") возвращает <li>5</li>

Далее:

function next(selector) {
    var $element = $(selector);

    return $element
        .children(":eq(0)")
        .add($element.next())
        .add($element.parents().filter(function() {
            return $(this).next().length > 0;
        }).next()).first();
}

Предыдущая:

function previous(selector) {
    var $element = $(selector);

    return $element
        .prev().find("*:last")   
        .add($element.parent())    
        .add($element.prev())
        .last();     
}

Обновить Если вы хотите ограничить верхнюю часть самой node предыдущей, вы можете сделать:

function previous(selector, root) {
    var $element = $(selector);

    return $element
        .prev().find("*:last")   
        .add($element.parent())     
        .add($element.prev())
        .last().not($(root).parent());      
}

http://jsfiddle.net/andrewwhitaker/n89dz/

Другое обновление. Здесь для удобства используется плагин jQuery:

(function($) {
    $.fn.domNext = function() {
        return this
            .children(":eq(0)")
            .add(this.next())
            .add(this.parents().filter(function() {
                return $(this).next().length > 0;
            }).next()).first();        
    };

    $.fn.domPrevious = function() {
        return this
            .prev().find("*:last")   
            .add(this.parent())     
            .add(this.prev())
            .last();         
    };
})(jQuery);

Расширенный пример здесь: http://jsfiddle.net/andrewwhitaker/KzyAY/

Ответ 2

Какая интересная проблема! Похоже, что вы сглаживаете рекурсивную структуру HTML, чтобы она не зависела от цикла - я вижу, что это пригодится.

Вы можете решить проблему, разбив .next() на следующие случаи:

  • Элемент имеет дочерние элементы → next() - это первый ребенок.
  • Элемент не имеет дочерних элементов и не является последним дочерним элементом → next() таким же, как jQuery .next()
  • Элемент не имеет детей, последний ребенок:
    • Найти ближайшего родителя, который не является последним потомком → next(), - это следующий родительский родной
    • Если такого родителя нет → next() есть null

Код будет (называть его flatNext для сохранения исходного поведения jQuery .next):

$.fn.flatNext = function () {
   if (this.children().length) return this.children().eq(0);
   if (!this.is(":last-child")) return this.next();
   if (this.closest(":not(:last-child)").length)
       return this.closest(":not(:last-child)").next();
   return $([]); // Return empty jQuery object rather than null
};

И $.fn.flatPrev должен следовать.

Ответ 3

В зависимости от вашего набора данных вы можете просто сгладить все (предполагая, что $.find является стабильным, и я считаю, что это так):

var eles = [];
$("#ul1").find("li").each(function (e) {
    eles.push(e);
});

Следующий элемент после ele[3] равен ele[4] независимо от уровня отступа.

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