SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    SitePoint Addict
    Join Date
    Jan 2009
    Posts
    369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Responsive thumbnail carousel

    I have a jsfiddle here - http://jsfiddle.net/ZrHfu/1/

    Demo here - http://www.ttmt.org.uk/forum/thumb_test/

    I'm trying to create a responsive thumbnail carousel - I've seen plugins to do this but they all need images the same size, I need something with images in different sizes.

    It's very basic - list of images floated left, overflow: hidden on container.

    I have left/right buttons, when the button is clicked I'm trying to move the ul with the images left/right.

    Only the right button is connected.

    My problem is it only works once.

    If you click the right button, the images move left, click it a second time and nothing happens.

    Why does it work only once.


    Code:
    <!DOCTYPE html>
        <html>
          <meta charset="UTF-8">
          <title>Title of the document</title>
          <meta name="description" content="">
          <meta name="keywords" content="">
          <meta name="robots" content="">
    
          <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    
          <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    
          <link rel="stylesheet" href="css/master.css" />
    
          </head>
    
        <body>
    
    
            <a class="arrow left">&larr;</a>
    
            <div class="thumbs">
    
              <ul>
    
                <li><a href="#"><img alt="" src="images/01.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/02.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/03.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/04.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/05.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/06.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/07.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/08.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/09.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/10.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/11.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/12.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/13.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/14.jpg" /></a></li>
                <li><a href="#"><img alt="" src="images/15.jpg" /></a></li>
    
              </ul>
            </div>
    
            <a class="arrow right">&rarr;</a>
    
    
            <script src="js/hel.js"></script>
    
        </body>
    
        </html>

  2. #2
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,938
    Mentioned
    214 Post(s)
    Tagged
    12 Thread(s)
    Hi,

    First off, thank you for asking your question in such a clear and concise way. I wish more people would do this.

    Quote Originally Posted by ttmt View Post
    Why does it work only once.
    The problem is this line:

    Code JavaScript:
    $('.thumbs ul').animate({'left': -width } , 1000);

    If width is 400px, you are animating the <ul> tag inside the "thumbs" <div> to a position of left: -400px.
    Once it has reached this position, there is nowhere else for it to go.

    What you want to do instead is this:

    Code JavaScript:
    $('.thumbs ul').animate({'left': '-=' + width } , 1000);

    Whereby every time you click the arrow, you are subtracting width from the <ul> element's current left position and animating to that value.

    For example, if you start off at left: 0px and width is 400px:

    Click 1: 0 - 400 = -400, animate <ul> from left: 0px to left: -400px
    Click 2: -400 - 400 = -800, animate <ul> from left: -400px to left: -800px
    Click 3: -800 - 400 = -1200, animate <ul> from left: -800px to left: -1200px

    and so on ...

  3. #3
    SitePoint Addict
    Join Date
    Jan 2009
    Posts
    369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Pullo, I understand now.

    My question was clear because I have to asked a lot of questions, and here's another.

    How do I stop the ul moving when the last image is in view.

    I knew i would have to address this but I thought I might be able to use the
    overall width of the ul with the width of the containing div.

    The ul's width is set very wide to accommodate the floated img's so I don't think this would work.

    Could I use a conditional statement that ran the animate function if the last image had NOT past the right button?

  4. #4
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,938
    Mentioned
    214 Post(s)
    Tagged
    12 Thread(s)
    It's not so hard, what you need to do is this:
    • Get references to the width of the thumbs container and to the width of the <ul> element containing the thumbs.
    • Get a reference to the left offset of the <ul> containing the thumbs.
    • When the user presses scroll left, check that the left offset of the <ul> + the width of the thumbs container are less than, or equal to the total width of the <ul>. If so, then you have enough space for another scroll, if not, then just scroll by the remaining space.
    • When scrolling right, just don't go beyond offset left of zero

    Does that make sense?

  5. #5
    SitePoint Addict
    Join Date
    Jan 2009
    Posts
    369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That is how I thought I would do it but the width of the <ul> containing the thumbs is wider than the actual width of the of all the thumbs together.

    I have set the width of the <ul> to 4000px to accommodate the thumbs.

    I thought I could do something like:

    Code:
    .thumbs ul{
        	width:auto;
        	position:relative;
    }
    so the <ul> would be as wide as it's contents but that doesn't seem to work.

    I've had to make the <ul> wider than it's contents.

    Here is the code with the CSS

    Code:
    <!DOCTYPE html>
    <html>
      <meta charset="UTF-8">
      <title>Title of the document</title>
      <meta name="description" content="">
      <meta name="keywords" content="">
      <meta name="robots" content="">
      
      <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
      
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
      
      <style type="text/css" >
        *{
          margin:0;
          padding:0;
        }
        body{
        	background:#eee;
        }
        .thumbs{
        	width:80%;
        	overflow:hidden;
        	margin:100px;
        }
        .thumbs ul{
        	width:4000px;
        	position:relative;
        }
        .thumbs ul li{
        	display:inline;
        }
        .thumbs ul li a{
        	display:inline-block;
        	float:left;
        }
        .arrow{
        	font-size:2em;
        	display:inline-block;
        	padding:5px;
        	background:red;
        	position:absolute;
        }
        .left{
        	top:100px;
        	left:10px;
        }
        .right{
        	right:5%;
        	top:100px;
        }
      </style>
        
      </head>
      
    <body>
      
        
        <a class="arrow left">&larr;</a>
        
        <div class="thumbs">
    
          <ul>
    
            <li><a href="#"><img alt="" src="images/01.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/02.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/03.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/04.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/05.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/06.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/07.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/08.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/09.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/10.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/11.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/12.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/13.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/14.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/15.jpg" /></a></li>
            
          </ul>
        </div>
      
        <a class="arrow right">&rarr;</a>
        
        
        <script src="js/hel.js"></script>
        
    </body>
    
    </html>

  6. #6
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,938
    Mentioned
    214 Post(s)
    Tagged
    12 Thread(s)
    Hi there,

    So I changed the CSS so that your <ul> doesn't need an explicit length declaration, then implemented the rest for you.
    I've also added scrolling to the ".left" button, so that the whole thing scrolls both ways.
    If there's anything you don't understand, just let me know.

    Demo

    Code:

    Code:
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8">
        <title>Responsive slider demo</title>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
        <link rel="stylesheet" href="css/reset.css" />
        <style>
          body{ background:#eee; }
          .thumbs{
            width:80%;
            overflow:hidden;
            margin:100px;
            white-space: nowrap;
          }
          .thumbs ul{
            position:relative;
            float:left;
          }
          .thumbs ul li{
            display: inline-block;
          }
          .arrow{
            font-size:2em;
            display:inline-block;
            padding:5px;
            background:red;
            position:absolute;
          }
          .left{
            top:100px;
            left:10px;
          }
          .right{
            right:5%;
            top:100px;
          }
        </style>
      </head>
      
      <body>
        <a class="arrow left">&larr;</a>
        <div class="thumbs">
          <ul>
            <li><a href="#"><img alt="" src="images/01.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/02.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/03.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/04.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/05.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/06.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/07.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/08.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/09.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/10.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/11.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/12.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/13.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/14.jpg" /></a></li>
            <li><a href="#"><img alt="" src="images/15.jpg" /></a></li>
          </ul>
        </div>
        <a class="arrow right">&rarr;</a>
        
        <script>
          $(window).load(function(){
            var $thumbsContainer = $(".thumbs ul"),
                thumbsDisplayWidth = $(".thumbs").width(),
                totalThumbsWidth = $thumbsContainer.width(),
                currentPosition = 0,
                scrollAmount;
            
            $('.right').click(function(){
              if(currentPosition < totalThumbsWidth - (2 * thumbsDisplayWidth)){
                scrollAmount = thumbsDisplayWidth;
              } else {
                scrollAmount = totalThumbsWidth - (thumbsDisplayWidth + currentPosition)
              }
              $thumbsContainer.filter(':not(:animated)').animate({'left': '-=' + scrollAmount }, 1000, function(){
                currentPosition = Math.abs(parseInt($thumbsContainer.css('left')));
              });
            })
            
            $('.left').click(function(){
              if(currentPosition > 0 && currentPosition > thumbsDisplayWidth){
    	    scrollAmount = thumbsDisplayWidth;
    	  } else {
    	    scrollAmount = totalThumbsWidth - (totalThumbsWidth - currentPosition);
    	  }
              $thumbsContainer.filter(':not(:animated)').animate({'left': '+=' + scrollAmount }, 1000, function(){
                currentPosition = Math.abs(parseInt($thumbsContainer.css('left')));
              });
            });
          })
        </script>
      </body>
    </html>

  7. #7
    SitePoint Addict
    Join Date
    Jan 2009
    Posts
    369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    wow thats brilliant thanks.

    Only bit I'm not to sure about is

    Code:
    $thumbsContainer.filter(':not(:animated)').animate({'left': '-=' + scrollAmount }, 1000, function(){
                currentPosition = Math.abs(parseInt($thumbsContainer.css('left')));
              });

  8. #8
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,938
    Mentioned
    214 Post(s)
    Tagged
    12 Thread(s)
    Ok, let's break it down:

    You probably know about the problem with animations stacking up and that if someone kept hammering on the right or left buttons of your scroller, then it would scroll way past the position it was meant to.
    Well, this bit here, says to filter the selection, only to include elements that are not being animated. That way we avoid the problem altogether:

    Code JavaScript:
    .filter(':not(:animated)')

    Then we pass an anonymous callback to animate(), so that we can update the scroller's current position, once the animation has completed.

    The current position is obtained, thus:

    Code JavaScript:
    currentPosition = Math.abs(parseInt($thumbsContainer.css('left')));

    Working from the inside out:

    Code JavaScript:
    $thumbsContainer.css('left')

    will give us a pixel value between 0 and minus the width of the thumbs container. This will be a string.

    Code JavaScript:
    parseInt($thumbsContainer.css('left'))

    We apply parseint() to this value, as it will parse a string (ignoring the 'px') and returns an integer value.

    Code JavaScript:
    Math.abs(parseInt($thumbsContainer.css('left')));

    We then use Math.abs() to turn a potential negative number into a positive one.

    And that's it!

    Does that all make sense?

    You might also want to read: http://css-tricks.com/full-jquery-animations/

  9. #9
    SitePoint Addict
    Join Date
    Jan 2009
    Posts
    369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Perfect, thanks for all your help


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •