Reputation: 407
I'm working with an infinite loop carousel for a meetup type website.
This carousel will eventually hold user avatars. I'd like it so that the middle item is increased in width and has displayed text that was previously hidden when the user was scrolling through and it wasn't yet in the middle. This text would display brief information about the middle user, such as their age, hobbies, etc.
In this case, the middle item is #4, but as you scroll through the middle item changes (i.e. if you scroll right one time, the middle item is #5). Just writing this for the sake of clarity.
Hope this makes sense. Here is the code:
HTML
<a href="javascript:void(0);" class="btnPrevious">Previous</a>
<a href="javascript:void(0);" class="btnNext">Next</a>
<div class="carousel">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
</ul>
</div>
CSS
.carousel{
padding-top: 20px;
width: 357px;
overflow: hidden;
height: 50px;
position: relative;
}.carousel ul{
position: relative;
list-style: none;
list-style-type: none;
margin: 0;
height: 50px;
padding: 0;
}.carousel ul li{
position: absolute;
height: 25px;
width: 50px;
float: left;
margin-right: 1px;
background: #f2f2f2;
text-align: center;
padding-top: 25px;
}
JS
$(function(){
var carousel = $('.carousel ul');
var carouselChild = carousel.find('li');
var clickCount = 0;
var canClick = true;
itemWidth = carousel.find('li:first').width()+1; //Including margin
//Set Carousel width so it won't wrap
carousel.width(itemWidth*carouselChild.length);
//Place the child elements to their original locations.
refreshChildPosition();
//Set the event handlers for buttons.
$('.btnNext').click(function(){
if(canClick){
canClick = false;
clickCount++;
//Animate the slider to left as item width
carousel.stop(false, true).animate({
left : '-='+itemWidth
},600, function(){
//Find the first item and append it as the last item.
lastItem = carousel.find('li:first');
lastItem.remove().appendTo(carousel);
lastItem.css('left', ((carouselChild.length-1)*(itemWidth))+(clickCount*itemWidth));
canClick = true;
});
}
});
$('.btnPrevious').click(function(){
if(canClick){
canClick = false;
clickCount--;
//Find the first item and append it as the last item.
lastItem = carousel.find('li:last');
lastItem.remove().prependTo(carousel);
lastItem.css('left', itemWidth*clickCount);
//Animate the slider to right as item width
carousel.finish(true).animate({
left: '+='+itemWidth
},300, function(){
canClick = true;
});
}
});
function refreshChildPosition(){
carouselChild.each(function(){
$(this).css('left', itemWidth*carouselChild.index($(this)));
});
}
});
Upvotes: 1
Views: 1852
Reputation: 7656
I've slightly optimized your code and added the middle element expansion:
$(function(){
var carousel = $('.carousel ul');
var carouselChild = carousel.find('li');
var clickCount = 0;
var canClick = true;
var itemWidth = carouselChild.first().outerWidth(true); //Including margin
var lastItem;
// Get an element in the middle of the visible part of the carousel
var getMiddleElement = function($carousel){
var carouselWidth = $carousel.width();
var $items = $carousel.find('li');
var lastVisibleItem = 0;
$items.each(function(index, el) {
if ( $(this).position().left >= carouselWidth ) {
return false;
}
lastVisibleItem = index;
});
return $items.eq(Math.floor(lastVisibleItem/2));
}; // getMiddleElement
//Set Carousel width so it won't wrap
carousel.width(itemWidth * carouselChild.length);
// Expand the middle element
var $middle = getMiddleElement($('.carousel')).toggleClass('expanded');
//Set the event handlers for buttons.
$('.btnNext').click(function() {
if (canClick) {
canClick = false;
clickCount++;
//Animate the slider to left as item width
carousel.stop(false, true).animate({
left : '-='+itemWidth
},600, function(){
//Find the first item and append it as the last item.
lastItem = carousel.find('li:first');
lastItem.remove().appendTo(carousel);
carousel.css('left', 0);
canClick = true;
// Collapse the previous middle and expand the new one
$middle.toggleClass('expanded');
$middle = getMiddleElement($('.carousel')).toggleClass('expanded');
});
}
}); // btnNext
$('.btnPrevious').click(function() {
if (canClick) {
canClick = false;
clickCount--;
//Find the first item and append it as the last item.
lastItem = carousel.find('li:last');
lastItem.remove().prependTo(carousel);
carousel.css('left', -itemWidth);
//Animate the slider to right as item width
carousel.finish(true).animate({
left: '+='+itemWidth
},300, function(){
canClick = true;
// Collapse the previous middle and expand the new one
$middle.toggleClass('expanded');
$middle = getMiddleElement($('.carousel')).toggleClass('expanded');
});
}
}); // btnPrevious
});
Check the full code here: JSFiddle
Upvotes: 1
Reputation: 2784
You could create a CSS-class with the properties you like (actually the width wouldn't look so good in your fiddle, because you set absolute left values - but this should be an example only):
.focus{
color: red;
}
Then you define your middle child like
var middle = 4;
In your click events you could add the class to the middle element (and of course assign the class to the middle element when loading):
$('.btnNext').click(function(){
if(canClick){
middle+1;
$('ul li').eq(middle-1).removeClass('focus');
$('ul li').eq(middle).addClass('focus');
....
For "back" you just have to do it the other way round.
middle-1;
$('ul li').eq(middle).removeClass('focus');
$('ul li').eq(middle-1).addClass('focus');
Hope this helps.
Additionally you would have to change the positioning with the width-value and of course change the content. This can be achieved with .html(). Example:
btnNext:
$('ul li').eq(middle-1).removeClass('focus').html(middle-1+clickCount);
$('ul li').eq(middle).addClass('focus').html('more');
and
btnPrevious:
$('ul li').eq(middle).removeClass('focus').html(middle+1+clickCount);
$('ul li').eq(middle-1).addClass('focus').html('more');
Upvotes: 1