Neo
Neo

Reputation: 407

How to get middle item in carousel to increase in width and display more info?

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:

http://jsfiddle.net/uL04mvwe/

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

Answers (2)

unconditional
unconditional

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

mxlse
mxlse

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

Related Questions