jQuery Slideshow

by Amy Kirst

HTML

<div class="slideshow">
                <figure class="image">
                    <img src="https://c1.staticflickr.com/9/8584/16136057529_e7b64928d0_z.jpg"  />
                    <figcaption>This is an example of a really long caption. Here I go. Do I wrap to a second line? Wrap wrap wrap wrap. Wrap Wrap Wrap Wrap Wrap Wrap Wrap Wrap Wrap Wrap Wrap</figcaption>
                </figure>
                <figure class="image">
                    <img src="https://c4.staticflickr.com/8/7495/16322256485_08ee0ee36f_z.jpg" />
                    <figcaption>Insert caption</figcaption>
                </figure>
                <figure class="image">
                    <img src="https://c2.staticflickr.com/8/7474/16120961661_8dc12962dd_z.jpg" />
                    <figcaption>Insert caption</figcaption>
                </figure>

CSS

/* INSTRUCTIONS
 
All photos should be wrapped in figure elements and should be the same size
Compress photos before uploading (save originals)

*/

body {
  box-sizing:border-box
}

figure {
  margin:0
}

.slideshow {
  display:inline-block;
  padding:0;
  position:relative;
/* To position slideshow buttons */
  max-width:920px
}


.hide {
  display: none;
}

.slideshow img {
  width:100%;
  border-top-left-radius:10px;
  border-top-right-radius:10px;
  margin-top: 1em;
}

.slideshow figcaption {
  background-color:#000;
  color:#fff;
  padding:1em;
  border-bottom-right-radius:10px;
  border-bottom-left-radius:10px;
  font-family:Helvetica,Arial,Tahoma,sans-serif;
  font-size:15px;
  line-height:150%;
  margin-top:-5px
}

.previous, .next {
  height:0;
/* Padding-bottom is added via JS; calculates based on height of image */
  position:absolute;
  top:0
}

.previous p, .next p {
  margin:0;
  display:table;
  padding:1em 10px;
  color:#fff;
  font-family:Arial;
  font-size:24px;
  background-color:#000;
  text-align:center;
  font-weight:700;
  opacity:.8;
  position:absolute;
/* positioned in relation to the #previous and #next spans */
  top:50%;
  margin-top:-1.6em
/* previously used transformY(-50%) to bring arrow up half the width of itself; not supported in IE 8 */
}

.previous p {
  left:0;
  border-radius:0 5px 5px 0
}

.next p {
  right:0;
/*moves button to right corner of span instead of left */
  border-radius:5px 0 0 5px
}

.previous {
  left:0
}

.next {
  right:0
}

.previous:hover, .next:hover {
  opacity:.5;
  cursor:pointer;
  cursor:hand
}

JavaScript

/* LIMITATIONS
  - Need script in document head that hides slideshow while the page loads, then reveals it when images are loaded (avoids flash of images before images are hidden with JS)
*/

// Get array with photos
var photos = ($(".image")); 
var numPhotos = photos.length;
var shownPhotoIndex;

// Hide all photos except first 
function hidePhotos() {
  $(photos).not(":first").addClass("hide");
} // end hidePhotos

// Calculate position of buttons
function positionButtons() {
  // get the height and width of the shown image
  var imageHeight = $(".slideshow img").first().height();
  var imageWidth = $(".slideshow img").first().width();
  var paddingTop = (imageHeight / imageWidth) * 100;
  paddingTop = +paddingTop.toFixed(2);
  var percent = paddingTop + "%";
  $(".previous").css("paddingBottom", percent);
  $(".next").css("paddingBottom", percent);
}
  
// Add controls (if JS is not enabled; controls will not be present)
function addControls() {
  // Create buttons
  $(".slideshow").append('<span class="next"><p>>></p></span>');
  $(".slideshow").append('<span class="previous"><p><<</p></span>');
  // Calculate position of buttons
  positionButtons();
} // end addControls
  
// Find curently shown photo
function findShownPhoto() {
  for (var i = 0; i < numPhotos; i++) {
    // if the image does not contain a class of "hide"
    if (!$(photos[i]).hasClass("hide")) {
      shownPhotoIndex = i;
    } // end if statement  
  } // end for statement
} // end findShownPhoto

function progressSlides() {
  var next = $(".next");
  // When the next button is clicked, show next photo
  next.click(function() {
    var nextPhoto;
    findShownPhoto();
    // If current photo is last photo, go to first photo
    if (shownPhotoIndex === (numPhotos - 1)) {
      nextPhoto = photos[0];
    } else {
      nextPhoto = photos[shownPhotoIndex + 1];
    }
    // Hide current photo
    $(photos[shownPhotoIndex]).addClass("hide");
    // Show next photo by removing "hide" class
   ...