Photo Slideshow Codebase
Markup
<html>
<head>
<link rel="stylesheet" type="text/css" href="/content/styles/slideshow.css" />
</head>
<body class="body-example">
<h3 class="center-aligned-block">Photo Slideshow: 2009 Tolt River Flood</h3>
<div class="ss-wrapper">
<div class="ss-toolbar">
<span class="ss-button" id="ss-prev" title="previous image">
<a href="#" onclick="return false">
<span>prev</span>
</a>
</span>
<span class="ss-button" id="ss-pause" title="pause slidshow">
<a href="#" onclick="return false">
<span>pause</span>
</a>
</span>
<span class="ss-button hidden" id="ss-play" title="play slideshow">
<a href="#" onclick="return false">
<span>play</span>
</a>
</span>
<span class="ss-button" id="ss-next" title="next image">
<a href="#" onclick="return false">
<span>next</span>
</a>
</span>
</div>
<div id="ss-img-title"></div>
<div id="ss-img-wrapper"></div>
</div>
<script type="text/javascript" src="/content/scripts/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="/content/scripts/slideshow.js"></script>
</body>
</html>
Javascript, JQuery
/* -----------------------------
/content/scripts/slideshow.js
----------------------------- */
$(function () {
var images = [],
$wrapper = $("#ss-img-wrapper"),
$title = $("#ss-img-title"),
$img = $("#ss-img"),
$prev = $("#ss-prev"),
$pause = $("#ss-pause"),
$play = $("#ss-play"),
$next = $("#ss-next");
images.timer = null;
images.preloader = null;
images.currentIndex = 0;
images.loadDelay = 2000;
images.transitionRate = 4000;
images.errorMessage = "unable to load slideshow";
images.waitMessage = "loading images. please wait...";
function imageItem(src, title) {
this.src = src;
this.title = title;
}
function preloadImage(i, ms) {
if (i < images.length) {
(new Image()).src = images[i].src;
images.preloader = setTimeout(function () {
i++;
preloadImage(images, i, ms);
}, ms);
} else {
images.preloader = clearTimeout(images.preloader);
}
}
function renderImage(fadeType) {
$wrapper.empty();
$img = $('<img id="ss-img" />');
$img.addClass("ss-fade-in" + (fadeType === 1 ? "-out" : ""));
$img.css('animation-duration', (images.transitionRate + 'ms'));
$img.attr("src", images[images.currentIndex].src);
$wrapper.append($img);
$title.text(images[images.currentIndex].title);
}
function pauseSlideshow() {
images.timer = clearTimeout(images.timer);
$img.removeClass("ss-fade-in-out");
}
function moveAdjacent(dir) {
var i = images.currentIndex + (dir === 1 ? 1 : -1);
images.currentIndex = i > images.length - 1 ? 0 : (i < 0 ? images.length - 1 : i);
renderImage();
}
function playSlideshow() {
// adjust index if playing after pausing
if ($img.hasClass("ss-fade-in")) {
images.currentIndex++;
}
if (images.currentIndex < images.length) {
renderImage(1);
images.timer = setTimeout(function () {
images.currentIndex++;
playSlideshow();
}, images.transitionRate);
} else {
images.timer = clearTimeout(images.timer);
images.currentIndex = 0;
playSlideshow();
}
}
function playOnClick(e) {
$(this).addClass("hidden");
$pause.removeClass("hidden");
playSlideshow();
e.stopPropagation();
}
function pauseOnClick(e) {
$(this).addClass("hidden");
$play.removeClass("hidden");
pauseSlideshow();
e.stopPropagation();
}
function prevOnClick(e) {
$pause.trigger("click");
moveAdjacent(-1);
e.stopPropagation();
}
function nextOnClick(e) {
$pause.trigger("click");
moveAdjacent(1);
e.stopPropagation();
}
// set button event handlers
function setButtonEvents() {
$play.on("click", playOnClick);
$pause.on("click", pauseOnClick);
$prev.on("click", prevOnClick);
$next.on("click", nextOnClick);
}
function ajaxDone(xml) {
var src, title,
// xmlString = (new XMLSerializer()).serializeToString(xml),
$xml = $(xml),
$entry = $xml.find("entry");
$entry.each(function (i) {
title = $(this).find("title").text();
if (title.length) src = $(this).find("link[rel=enclosure]").attr("href");
if (src.length) images[i] = new imageItem(src, title);
});
if (images.length) {
$title.text(images.waitMessage);
preloadImage(0, images.transitionRate / images.length);
setButtonEvents();
setTimeout(function () {
playSlideshow()
}, images.loadDelay);
}
}
function ajaxFail() {
$title.text(images.errorMessage);
}
$.ajax({
type: "GET",
url: "/content/resources/flickrfeed.xml",
dataType: "xml"
})
.done(ajaxDone)
.fail(ajaxFail);
});
CSS
/* -----------------------------
/content/styles/slideshow.css
----------------------------- */
.body-example {
font: bold .76em verdana !important;
}
.body-example .center-aligned-block {
width: 100%;
text-align: center;
}
.ss-wrapper {
width: 100%;
text-align: center;
margin: 0 auto;
}
.ss-toolbar {
padding: 1em 0;
}
#ss-img-title {
font-weight: bold;
padding-bottom: 1em;
}
.ss-toolbar .ss-button {
display: inline-block;
width: 60px;
height: 26px;
text-align: center;
background: #e0e0e0;
line-height: 1em;
cursor: pointer;
border: 1px solid #bbb;
white-space: nowrap;
}
.ss-toolbar .ss-button:hover {
background: #f0f0f0;
}
.ss-button a {
width: 18px;
height: 18px;
margin-top: 3px;
display: inline-block;
color: #000;
background: url('data:image/gif;base64,R0lGODlhSAASAKIBAAkJCf39/a+vr5OTk/Pz81xcXNXV1R4eHiH5BAEAAAEALAAAAABIABIAAAPVGLrc/jDKSau9OFchrADgsHyh5gyH+Bhd8xUGRQJqMNcLCwmpSz8onILUk9xGoF8j+PgInY5CyZeERY7DpNAGsjJ4z+LwACBvZyAxVcmdfsvlVvapNAzSbiS8GlvXsG9JAAVIdCIGZIJseop5bWyAI4lwBzFgPoeTWg5oSWZ+jGeNBx1QbzVSnqKjfYGQm2tdhZhfZJ+xZVtZuZKONomktYYNBqmrXa2csG1qu16zp0DNzHI7yzy+l8phugE6PoQy18s51dEmDN8yiX+J5ujw8fLz9PQJADs=') 0 0 no-repeat;
}
#ss-play a {
background-position: -18px 0;
}
#ss-pause a {
background-position: -36px 0;
}
#ss-next a {
background-position: -54px 0;
}
.ss-button a span {
position: absolute;
width: 54px;
opacity: 0.3;
margin-top: -20px;
margin-left: -28px;
visibility: hidden;
}
.ss-button:hover a span {
visibility: visible;
}
#ss-img {
max-width: 70%;
height: auto;
border: 1px solid #111;
}
#ss-pause.hidden,
#ss-play.hidden {
display: none;
}
.ss-fade-in {
animation: ssFadeIn ease 1s;
}
.ss-fade-in-out {
animation: ssFadeInOut ease 1s;
}
@keyframes ssFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes ssFadeInOut {
0% {
opacity: 0;
}
70% {
opacity: 1;
}
100% {
opacity: 0;
}
}