Reputation: 73
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:
Upvotes: 7
Views: 80
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
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
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
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
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