Reputation: 32758
I have the following menu which can have anything up to about 50 items and two links that a user can use to navigate to the previous or next city. Here for this example I am just showing four address links.
<ul id="menu">
<li><a href="/City/0101004H">1</a></li>
<li><a href="/City/0101004I">2</a></li>
<li><a href="/City/0101004J">3</a></li>
<li><a href="/City/0101004K">4</a></li>
</ul>
<a id="prev" href="#"><img width="16" height="16" src="/images/prev.png">Prev</a>
<a id="next" href="#"><img width="16" height="16" src="/images/next.png">Next</a>
I had some help on stack overflow and came up with the following code:
$("#menu").on('click', 'a[href^="/City"]', function(event) {
event.preventDefault();
var prev = $(this).parent().prev().find('a');
var next = $(this).parent().next().find('a');
$('#prev').prop('href', jQuery(prev).prop('href')).prop('title', 'City ' + jQuery(prev).text());
$('#next').prop('href', jQuery(next).prop('href')).prop('title', 'City ' + jQuery(next).text())
});
This sets the href of the previous and next to the appropriate value when I click on on one of the menu items. It works but not for the first and last items in the list. What I need is this:
a) When the first item is clicked on I would like the #prev to change to:
<a id="prev" href="#"><img src="/images/noentry.png"></a>
b) When the last item is clicked on I would like the #next to change to:
<a id="next" href="#"><img src="/images/noentry.png"></a>
Is there an easy way I could do this without adding too much additional code?
Upvotes: 7
Views: 215
Reputation: 268344
You can test if the element is the first child, or the last child using the following:
$(this).parent().is(":first-child");
$(this).parent().is(":last-child");
If this
referenced the a
being clicked, we would test whether it was the first link, or the last link in the list by testing whether or not its parent was a first child, or a last child, or neither.
Additionally, you could base attribute-object-construction off of these values:
$("#menu").on('click', 'a', function(event) {
// Prevent link from taking us anywhere
event.preventDefault();
// We'll be referencing the parent numerous times
var parent = $(this).parent();
// Determine the new properties of the PREV link
var prev = parent.is(":first-child")
? { html: '<img src="/images/noentry.png" />',
title: null }
: { html: '<img src="/images/prev.png" /> Prev',
title: 'City ' + parent.prev().text() } ;
// Determine the new properties of the NEXT link
var next = parent.is(":last-child")
? { html: '<img src="/images/noentry.png" />',
title: null }
: { html: '<img src="/images/next.png" /> Next',
title: 'City ' + parent.next().text() } ;
// Set new attribtes of both PREV and NEXT
$("#prev").attr( prev );
$("#next").attr( next );
});
You could further construct the attributes for the #prev
and #next
elements to your needs.
Demo: http://jsfiddle.net/MX94J/1/
Upvotes: 10
Reputation: 707218
You can check the jQuery object length for zero and act accordingly:
$("#menu").on('click', 'a[href^="/City"]', function(event) {
event.preventDefault();
var pHref, nHref, pTitle, nTitle;
var prev = $(this).parent().prev().find('a');
var next = $(this).parent().next().find('a');
if (prev.length == 0) {
pHref = "#";
pTitle = "";
} else {
pHref = prev.prop('href');
pTitle = prev.prop('City' prev.text());
}
if (next.length == 0) {
nHref = "#";
nTitle = "";
} else {
nHref = next.prop('href');
nTitle = next.prop('City' prev.text());
}
$('#prev').prop('href', pHref).prop('title', pTitle);
$('#next').prop('href', nHref).prop('title', nTitle)
});
or a little cleaner with a local function to do the work:
("#menu").on('click', 'a[href^="/City"]', function(event) {
function setProps(targetSelector, srcObject) {
var href, title;
if (srcObject.length) {
href = srcObject.prop('href');
title = srcObject.prop('title');
} else {
href = "#";
title = "";
}
$(targetSelector).prop('href', href).prop('title', title);
}
event.preventDefault();
var p = $(this).parent();
setProps('#prev', p.prev().find('a'));
setProps('#next', p.next().find('a'));
});
Upvotes: 1
Reputation: 18339
An alternate way to do this is the following using an index instead or properties:
var index = 0;
var nElements = $('#menu a').length;
$('#menu a').click(function(e) {
e.preventDefault();
index = $(this).parents('ul').find('a').index(this);
if (index==0) {
$('#prev img').attr('src', '/images/noentry.png');
}
if (index==nElements-1) {
$('#next img').attr('src', '/images/noentry.png');
}
alert(index);
});
$('#prev').click(function() {
index = (index - 1) % nElements;
$('#menu a').eq(index).click();
});
$('#next').click(function() {
index = (index + 1)% nElements;
$('#menu a').eq(index).click();
});
Upvotes: 1
Reputation: 359776
If an element elt
is the first of its siblings, $(elt).prev().length
will be 0
.
If an element elt
is the last of its siblings, $(elt).next().length
will be 0
.
Upvotes: 1