Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery find next and prev element

Tags:

jquery

I try to find a next or prev element of current element. But next() and prev() function can only work in a scope, it can not reach outside. For an example this is what I want to achieve:

<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>

If current element is ul1, next element is <li>1</li>, prev element is null.

If current element is <li>1</li>, next element is <li>2</li>, prev element is ul1

If current element is <li>8</li>, next element is <li>9</li>, prev element is <li>7</li>

like image 252
StoneHeart Avatar asked Dec 23 '10 23:12

StoneHeart


People also ask

How to get next and previous element in jQuery?

prev('a'); var next = curr. next('a'); To make this cross row you need to check if you have current element first or last of row. If current element is first then last would be last element for previous row and similarly if current element is last of row then next will be first of next row.

How to get prev element in jQuery?

jQuery prev() Method The prev() method returns the previous sibling element of the selected element. Sibling elements are elements that share the same parent. The DOM tree: This method traverse backwards along the previous sibling of DOM elements.

How to get element before element in jQuery?

prev( [selector ] )Returns: jQuery. Description: Get the immediately preceding sibling of each element in the set of matched elements. If a selector is provided, it retrieves the previous sibling only if it matches that selector.


1 Answers

First of all, this was a really neat problem. Thanks for posting!

I accomplished this with a chained jQuery statement. Only thing is, if you run previous() on the top ul you'll get body. Which I think technically makes sense. However, if this isn't the desired behavior, see my update below.

Usage: next("#ul3") returns <li>5</li>

Next:

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();
}

Previous:

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

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

Update If you want to limit the upper most node previous can be, you could do:

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/

Another Update: Here's a jQuery plugin for convenience:

(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);

Expanded example here: http://jsfiddle.net/andrewwhitaker/KzyAY/

like image 150
Andrew Whitaker Avatar answered Sep 23 '22 13:09

Andrew Whitaker