gFused
gFused

Reputation: 73

Traversing a list with jQuery

I have a list of items that I want to traverse through from any point in any direction. I also want to loop around the list, meaning if I end up on the last list item and click on next, I want the next item to be the first item on the list. My page is simple, just an unordered list of 5 items, 2 buttons (one for previous and one for next) and a textarea that displays the results. Here is my code:

$(function() {
  var prev = $("#prev"); // grabbing the prev button
  var next = $("#next"); // grabbing the next button
  var listItems = $("#listItems p"); // grabbing the p elements of the list items
  var results = $("#results"); // grabbing the textarea
  var itemText; // variable for holding the text node
  var selectedItem; // variable for the current selected item

  listItems.click(function() { // click event for any item
    itemText = $(this).text(); // selects the text of the clicked list item
    results.text(itemText); // adds text to textarea
    selectedItem = $(this).parent(); // sets selected item as the li element of the selected p element
  });

  next.click(function() { // click event for next button
    var nextItem = selectedItem.next(); // setting the next item
    itemText = nextItem.children("p").text(); // grabbing the text of the next item
    results.text(itemText); // adds text to textarea
    selectedItem = nextItem; // sets next item
  });

  prev.click(function() { // click event for the prev button
    var prevItem = selectedItem.prev(); // setting the prev item
    itemText = prevItem.children("p").text(); // grabbing the text of the prev item
    results.text(itemText); // adds text to textarea
    selectedItem = prevItem; // sets prev item
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul id="listItems">
        <li><p>First item</p></li>
        <li><p>Item 2</p></li>
        <li><p>Item 3</p></li>
        <li><p>Item 4</p></li>
        <li><p>Last item</p></li>
</ul>
<button id="prev">Prev</button>
<textarea name="results" id="results" cols="30" rows="1"></textarea>
<button id="next">Next</button>

As it sits, when I click on or approach the last item, pressing the next button clears the textarea and renders both buttons unresponsive. Logically, I know that there needs to be an if statement stating if the current item is the last item, then the next item has to be the first item. I just couldn't figure out how to code it. Here is the jsfiddle:

jsfiddle

Upvotes: 7

Views: 80

Answers (5)

guest271314
guest271314

Reputation: 1

Try utilizing id of button to cycle text next , prev

var results = $("#results");
var items = $("#listItems li")
// show first `li p` text
results.text(items.eq(0).addClass("active").find("p").text());

function cycle(idx) {
  var active = $(".active")
  // cycle through `next` , `prev` `li` elements
  , next = active[idx]().is("*") 
           ? active[idx]() 
           : idx === "prev" 
             ? active.siblings().eq(active.index("li") - 1) 
             : active.siblings().addBack().eq(0);

  active.removeClass("active");
  // set text of `results` with `next` , `prev` `li p` text
  results.text(next.addClass("active").find("p").text());
};

$("button").on("click", function(e) {
  cycle(this.id)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="listItems">
  <li>
    <p>First item</p>
  </li>
  <li>
    <p>Item 2</p>
  </li>
  <li>
    <p>Item 3</p>
  </li>
  <li>
    <p>Item 4</p>
  </li>
  <li>
    <p>Last item</p>
  </li>
</ul>
<button id="prev">Prev</button>
<textarea name="results" id="results" cols="30" rows="1"></textarea>
<button id="next">Next</button>

Upvotes: 0

anthonybell
anthonybell

Reputation: 5998

You can use selectedItem.is(':first-child') and selectedItem.is(':last-child') selectors to find if you've reached the beginning or end of the list. Then you can select the first or last element of the list by going to the parent and finding the first/last child with selectedItem.parent().find('li:first') or selectedItem.parent().find('li:last')

$(function () {
    var prev = $("#prev");
    var next = $("#next");
    var listItems = $("#listItems p");
    var results = $("#results");
    var itemText;
    var selectedItem;

    listItems.on('click', function () {
        itemText = $(this).text();
        results.text(itemText);
        selectedItem = $(this).parent();
    });

    next.on('click', function () {
        var nextItem;
        //if i'm the last child, go to the parent and find the first child
        if (selectedItem.is(':last-child'))
            nextItem = selectedItem.parent().find('li:first');
        else
            nextItem = selectedItem.next();
        itemText = nextItem.children("p").text();
        results.text(itemText);
        selectedItem = nextItem;
    });

    prev.on('click', function () {
    var prevItem;
    //if im the first child, go to the parent to find the last
    if (selectedItem.is(':first-child'))
        prevItem = selectedItem.parent().find('li:last');
    else
        prevItem = selectedItem.prev();
    itemText = prevItem.children("p").text();
    results.text(itemText);
    selectedItem = prevItem;
  });
});

Upvotes: 0

Vishwajeet Bose
Vishwajeet Bose

Reputation: 430

$(function () {
    var prev = $("#prev");
    var next = $("#next");
    var listItems = $("#listItems p");
    var results = $("#results");
    var itemText;
    var selectedItem;

    listItems.click (function () {
        itemText = $(this).text();
        results.text(itemText);
        selectedItem = $(this).parent();
    });

    next.click (function () {
        var nextItem = selectedItem.next();
        if(nextItem.length==0){
            nextItem = $("#listItems li").first();
        }            
        itemText = nextItem.children("p").text();
        results.text(itemText);
        selectedItem = nextItem;
    });

    prev.click (function () {
        var prevItem = selectedItem.prev();
        if(prevItem.length==0){
            prevItem = $("#listItems li").last();
        }
        itemText = prevItem.children("p").text();
        results.text(itemText);
        selectedItem = prevItem;
    });
});

When it reach to last or first make next element setting as last and first this will resolve the issue.

For next:

    if(nextItem.length==0){
        nextItem = $("#listItems li").first();
    }

For previous:

    if(prevItem.length==0){
        prevItem = $("#listItems li").last();
    }

Demo: https://jsfiddle.net/763x97qb/1/

Upvotes: 0

renakre
renakre

Reputation: 8291

Building on top of your code, you can check if the current element is the last or the first element, and put some conditions like this:

next.click (function () { // click event for next button
  var nextItem = '';
  if(selectedItem.index() == listItems.length -1 ){//if the last element
      nextItem == listItems[0];
  }else{
    nextItem = selectedItem.next(); // setting the next item
    itemText = nextItem.children("p").text(); // grabbing the text of the next item
    results.text(itemText); // adds text to textarea
    selectedItem = nextItem; // sets next item
  }
});

prev.click (function () { // click event for the prev button
  var prevItem = '';
  if(selectedItem.index() == 0 ){//if the first element
      prevItem == listItems[listItems.length-1]
  }else{
    prevItem = selectedItem.prev(); // setting the prev item
    itemText = prevItem.children("p").text(); // grabbing the text of the prev item
    results.text(itemText); // adds text to textarea
    selectedItem = prevItem; // sets prev item
  }
});

Upvotes: 2

Rob M.
Rob M.

Reputation: 36511

Not sure if this helps, but here is a jQuery plugin I came up with to reorder an element list starting from a supplied index:

$.fn.reorder = function(head) {
   var arr  = this;
   var rest = arr.splice(head, arr.length - head);
   return rest.concat(Array.prototype.slice.call(arr, 0));
};

// make the array start from the 3rd element
$.each(listItems.reorder(3), function() { ...

In the example, calling .reorder(3) will move all elements beyond the 3rd index to the front of the array allowing you to then iterate over your collection with $.each in the expected order.

Upvotes: 0

Related Questions