Bootstrap Carousel with Responsive Thumbnail Strip

Bootstrap Carousel with fully responsive thumbnail strip.

HTML

<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="//code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css">
<div id="carousel" class="carousel slide" data-ride="carousel">
  <!-- Wrapper for slides -->
  <div class="carousel-inner" role="listbox">
    <div class="item active">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">1</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">2</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">3</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">4</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">5</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">6</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">7</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">8</div>
    </div>
    <div class="item">
      <img src="http://placehold.it/800x600" class="img-responsive">
      <div class="carousel-caption">9</div>
    </div>
  </div>

  <!-- Controls -->
  <a class="left carousel-control hiden-xs" href="#carousel" role="button" data-slide="prev">
    <span class="glyphicon glyphicon-chevron-left"...

CSS

#carousel,
#carousel-thumbs {
  max-width: 800px;
  margin: 15px auto;
}
#carousel-thumbs .item img {
  opacity: 0.5;
}
#carousel-thumbs .item.active div.active img {
  opacity: 1;
  border: 2px solid #000;
}
#carousel-thumbs .item.active div:not(.active) img {
  cursor:pointer;
}
#carousel-thumbs .carousel-control {
  background-image: none;
}

JavaScript

$(document).ready(function() {
  var totalItems = $('#carousel .item').length;
  var thumbs = 3;
  var currentThumbs = 0;
  var to = 0;
  var thumbActive = 1;
  
  
  function toggleThumbActive (i) {
    $('#carousel-thumbs .item>div').removeClass('active');
		$('#carousel-thumbs .item.active>div:nth-child(' + i +')').addClass('active');
  }
  
  $('#carousel').on('slide.bs.carousel', function(e) {
    //var active = $(e.target).find('.carousel-inner > .item.active');
    //var from = active.index();
    
    var from = $('#carousel .item.active').index()+1;
    var next = $(e.relatedTarget);
    to = next.index()+1;
    var nextThumbs = Math.ceil(to/thumbs) - 1;
    if (nextThumbs != currentThumbs) {
    	$('#carousel-thumbs').carousel(nextThumbs);
    	currentThumbs = nextThumbs;
    }
    thumbActive = +to-(currentThumbs*thumbs);
    //console.log(from + ' => ' + to + ' / ' + currentThumbs);
  });
  $('#carousel').on('slid.bs.carousel', function(e) {
    toggleThumbActive(thumbActive);
  });
  $('#carousel-thumbs').on('slid.bs.carousel', function(e) {
    toggleThumbActive(thumbActive);
  });
    $("#carousel").on("swiperight",function(){
  	$('#carousel').carousel('prev');
	});
  $("#carousel").on("swipeleft",function(){
		$('#carousel').carousel('next');
	});
  $("#carousel-thumbs").on("swiperight",function(){
  	$('#carousel-thumbs').carousel('prev');
	});
  $("#carousel-thumbs").on("swipeleft",function(){
		$('#carousel-thumbs').carousel('next');
	});
});

$('.carousel').carousel({
    interval: false
});