Skip to content

Instantly share code, notes, and snippets.

@p-a-t-a-r
Last active April 26, 2019 11:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save p-a-t-a-r/9ab8ee5c515574c58b68 to your computer and use it in GitHub Desktop.
Save p-a-t-a-r/9ab8ee5c515574c58b68 to your computer and use it in GitHub Desktop.
Derpibooru Image Slideshow (Greasemonkey Userscript for derpibooru.org)
Version 1.0.0 (05/02/2015) - Initial release
Version 1.0.1 (05/02/2015) - Added trixiebooru.org to the include list
Version 1.0.2 (05/26/2015) - Added icon to gallery slideshow button to match the May 2015 UI update
Version 1.0.3 (05/31/2015) - Changes to gallery slideshow button for May 2015 UI update (fixed positioning and made text hide on mobile)
Version 1.0.4 (06/06/2015) - Major refactoring, fixed some occurrences of duplicate history states and changed the behavior of the slideshow button on gallery pages
Version 1.1.0 (06/07/2015) - Added fave/upvote/downvote/comment buttons and scores
Version 1.1.1 (07/05/2015) - Fixed a bug that prevented the slideshow button from working on tag pages
Version 1.1.2 (07/19/2015) - Fixed a bug that prevented the slideshow button from working on search pages
Version 1.2.0 (07/20/2015) - Added HTML5 fullscreen capability
Version 1.2.1 (08/04/2015) - Bugfixes
Version 1.2.2 (10/03/2015) - More bugfixes
Version 1.2.3 (10/04/2015) - ALL the bugfixes!
Version 1.2.4 (10/31/2015) - Maybe someday there will be features... BUGFIX!
Version 1.3.0 (10/31/2015) - Added a button to stretch small images
Version 1.4.0 (11/01/2015) - Added auto-advance system
Version 1.4.1 (12/23/2015) - Added upvote, fave, and find keyboard shortcuts
Version 2.0.0 (03/26/2016) - Complete internal overhaul for improved reliability. Browser forward and back buttons work properly, and there is now a simple indicator for when images are loading and when they have failed to load. The stretch button has been removed, images are now stretched by default. Also gone is the keyboard shortcut for find.
Version 2.0.1 (03/26/2016) - Fixed interactions bug
Version 2.1.0 (03/26/2016) - Added button to hide toolbar
Version 2.2.0 (06/29/2016) - Fixed bugs and breakages caused by derpibooru updates
Version 2.3.0 (09/10/2016) - Updated the script for the September 2016 Derpibooru UI rewrite
Version 2.4.0 (09/29/2016) - Removed the now-deprecated derpiboo.ru domain
Version 2.5.0 (10/11/2016) - Removed all traces of jQuery after it stopped working
Version 2.6.0 (01/31/2017) - Replaced scopes with the new search system
Version 2.6.1 (02/24/2017) - Fixed a bug with keyboard shortcuts caused by Derpibooru's odd way of handling their own shortcuts
// ==UserScript==
// @name Derpibooru Gallery Slideshow
// @namespace dbslideshow
// @description Adds a slideshow feature to all Derpibooru gallery and image pages
// @include https://derpibooru.org/*
// @include https://www.derpibooru.org/*
// @include https://trixiebooru.org/*
// @include https://www.trixiebooru.org/*
// @version 2.6.1
// @grant none
// ==/UserScript==
// ==HTML==
// HTML to load into the body for the slideshow
var slideshowHTML = '\
<div id="slideshow">\
<div class="navcontainer">\
<div class="block__header flex">\
<a href="/" title="Homepage"><i class="fa fa-home"></i></a>\
<span id="nav-links">\
<span class="prev"><a href="" title="Previous Image (j)" id="btnprev"><i class="fa fa-chevron-left"></i></a></span>\
<span class="up"><a href="" title="Find this image in the global image list" id="btnfind"><i class="fa fa-chevron-up"></i></a></span>\
<span class="next"><a href="" title="Next Image (k)" id="btnnext"><i class="fa fa-chevron-right"></i></a></span>\
<span class="rand"><a href="" title="Random (r)" id="btnrand"><i class="fa fa-random"></i></a></span>\
<span><a href="" title="Close Slideshow" id="btnclose"><i class="fa fa-close"></i></a></span>\
</span>\
<a class="interaction--fave" href="#slideshow" id="btnfave">\
<span class="favourites" title="Favourites" id="numfave">0</span>\
<span class="fave-span" title="Fave!"><i class="fa fa-star"></i></span>\
</a>\
<a class="interaction--upvote" href="#slideshow" id="btnupvote">\
<span class="up_vote_count" title="Upvotes" id="numupvote">0</span>\
<span class="upvote-span" title="Yay!"><i class="fa fa-arrow-up"></i></span>\
</a>\
<span class="score block__header__title" id="numscore">0</span>\
<a class="interaction--downvote" href="#slideshow" id="btndownvote">\
<span class="downvote-span" title="Neigh!"><i class="fa fa-arrow-down"></i></span>\
<span class="down_vote_count" data-image-id="1245704" title="Downvotes" id="numdownvote">0</span>\
</a>\
<a class="interaction--comments" href="#comments" title="Comments">\
<i class="fa fa-comments"></i>\
<span class="comments_count" id="numcomment">0</span>\
</a>\
<div>\
<a role="button" tabindex=0 style="cursor:default" id="btnaastart" title="Start auto-advance"><i class="fa fa-play"></i></a>\
<a role="button" tabindex=0 style="cursor:default" class="hidden" id="btnaastop" title="Stop auto-advance"><i class="fa fa-pause"></i></a>\
<a role="button" tabindex=0 style="cursor:default" id="btnshowaasettings" title="Show auto-advance settings"><i class="fa fa-cog"></i></a>\
<a role="button" tabindex=0 style="cursor:default" class="hidden" id="btnhideaasettings" title="Hide auto-advance settings"><i class="fa fa-cog"></i></a>\
</div>\
<div class="hidden" id="aacontrols">\
<a role="button" tabindex=0 style="cursor:default" id="btnaadown10" title="Decrease auto-advance delay by 10"><i class="fa fa-minus"></i></a>\
<a role="button" tabindex=0 style="cursor:default" id="btnaadown1" title="Decrease auto-advance delay by 1">&#8211;</a>\
<strong class="score" id="numaadelay">10</strong>\
<a role="button" tabindex=0 style="cursor:default" id="btnaaup1" title="Decrease auto-advance delay by 1">+</a>\
<a role="button" tabindex=0 style="cursor:default" id="btnaaup10" title="Decrease auto-advance delay by 10"><i class="fa fa-plus"></i></a>\
<a role="button" tabindex=0 style="cursor:default" class="" id="btnaaprev" title="Auto-advance backwards"><i class="fa fa-chevron-left"></i></a>\
<a role="button" tabindex=0 style="cursor:default" class="" id="btnaarand" title="Auto-advance random"><i class="fa fa-random"></i></a>\
<a role="button" tabindex=0 style="cursor:default" class="interaction--upvote active" id="btnaanext" title="Auto-advance forwards"><i class="fa fa-chevron-right"></i></a>\
</div>\
<span id="txtloading">Loading...</span>\
<span id="txterror" class="hidden">ERROR</span>\
<div class="flex__right" id="controls">\
<a role="button" tabindex=0 style="cursor:default" class="hidden" id="btnfullscreen" title="Fullscreen"><i class="fa fa-expand"></i></a>\
<a role="button" tabindex=0 style="cursor:default" class="hidden" id="btnrestorescreen" title="Exit Fullscreen"><i class="fa fa-compress"></i></a>\
<a role="button" tabindex=0 style="cursor:default" id="btnhidetoolbar" title="Hide toolbar"><i class="fa fa-caret-up"></i></a>\
</div>\
</div>\
</div>\
<a role="button" tabindex=0 style="cursor:default" class="hidden" id="btnshowtoolbar" title="Show toolbar"><i class="fa fa-caret-down"></i></a>\
<div id="imgcontainer">\
<img src="" alt="" id="mainimage"></img>\
</div>\
</div>\
';
// HTML for the large slideshow button, used on gallery pages
var bigButtonHTML = '<a href="#slideshow" id="btnslideshow"><i class="fa fa-arrows-alt"></i></i><span class="hide-mobile hide-limited-desktop"> Slideshow</span></a>';
// HTML for the small slideshow button, used on image pages
// Note: the preceding space is necessary for proper spacing
var smallButtonHTML = ' <span><a title="Slideshow" id="btnslideshow" href="#slideshow"><i class="fa fa-arrows-alt"></i></a></span>';
// ==CSS==
// CSS to load for the slideshow
var slideshowCSS = '\
div#slideshow {\
position: fixed;\
display: table;\
width: 100%;\
height: 100%;\
left: 0;\
top: 0;\
}\
div#navcontainer {\
display: table-row;\
width: 100%;\
}\
div#imgcontainer {\
display: table-row;\
position: relative;\
width: 100%;\
height: 100%;\
}\
div#controls {\
float:right;\
}\
#imgcontainer img {\
position: absolute;\
top: 0;\
right: 0;\
bottom: 0;\
left: 0;\
margin: auto;\
max-width: 10%;\
max-height: 10%;\
-webkit-transform: scale(10);\
transform: scale(10);\
}\
a#btnshowtoolbar {\
color: #FFF;\
background-color: rgba(0, 0, 0, .25);\
position: absolute;\
top: 5px;\
right: 5px;\
padding: 5px;\
z-index: 10;\
}\
.hidden {\
display: none !important;\
}\
';
// ==JavaScript==
// -Functions-
// Simple XMLHttpRequest Promise wrapper
function PromiseXHR(url, callback)
{
return new Promise(function(resolve, reject) {
var XHR = new XMLHttpRequest();
XHR.open("get", url, true);
XHR.onload = function() {
if (XHR.status = "200")
{
callback(this.responseText);
resolve(XHR.statusText);
}
else
{
reject(XHR.statusText);
}
};
XHR.onabort = function() {
reject("Operation aborted");
};
XHR.onerror = function() {
reject(XHR.statusText);
};
XHR.send();
})
}
// Sets up the slideshow
function startSlideshow() {
// Nuke derpibooru's JavaScript from orbit to prevent conflicts
window.booru = null;
// Set the loading flag
window.dbslideshow.loading = true;
// Load the slideshow HTML and CSS into the DOM
document.getElementsByTagName("body")[0].innerHTML = slideshowHTML;
document.getElementsByTagName("head")[0].innerHTML += '<style type="text/css">' + slideshowCSS + '</style>';
// Set a couple of variables for auto-advance
window.dbslideshow.aacontrols = false;
window.dbslideshow.aadelay = 10;
window.dbslideshow.aamode = "next";
window.dbslideshow.toolbar = true;
// Register our various event handlers
document.addEventListener("keydown", evtKeypress);
window.onpopstate = evtPopstate;
document.getElementById("btnprev").addEventListener("click", function(event) {
event.preventDefault();
evtPrev();
}, false);
document.getElementById("btnnext").addEventListener("click", function(event) {
event.preventDefault();
evtNext();
}, false);
document.getElementById("btnrand").addEventListener("click", function(event) {
event.preventDefault();
evtRandom();
}, false);
document.getElementById("btnfave").addEventListener("click", evtFave, false);
document.getElementById("btnupvote").addEventListener("click", evtUpvote, false);
document.getElementById("btndownvote").addEventListener("click", evtDownvote, false);
document.getElementById("btnaastart").addEventListener("click", evtAAStart, false);
document.getElementById("btnaastop").addEventListener("click", evtAAStop, false);
document.getElementById("btnshowaasettings").addEventListener("click", evtShowAASettings, false);
document.getElementById("btnhideaasettings").addEventListener("click", evtHideAASettings, false);
document.getElementById("btnaadown10").addEventListener("click", evtAADown10, false);
document.getElementById("btnaadown1").addEventListener("click", evtAADown1, false);
document.getElementById("btnaaup1").addEventListener("click", evtAAUp1, false);
document.getElementById("btnaaup10").addEventListener("click", evtAAUp10, false);
document.getElementById("btnaaprev").addEventListener("click", evtAAPrev, false);
document.getElementById("btnaarand").addEventListener("click", evtAARand, false);
document.getElementById("btnaanext").addEventListener("click", evtAANext, false);
document.getElementById("btnshowtoolbar").addEventListener("click", evtShowToolbar, false);
document.getElementById("btnhidetoolbar").addEventListener("click", evtHideToolbar, false);
// Check if we have fullscreen capability
if (
document.fullscreenEnabled
|| document.mozFullScreenEnabled
|| document.webkitFullccreenEnabled
|| document.msFullscreenEnabled
) {
// Show the fullscreen button by removing the hidden class
document.getElementById("btnfullscreen").className = "";
// Add event handlers to the fullscreen buttons
document.getElementById("btnfullscreen").addEventListener("click", evtFullscreen, false);
document.getElementById("btnrestorescreen").addEventListener("click", evtRestoreScreen, false);
// Add an event listener to update the metabar when our fullscreen state changes
document.addEventListener("fullscreenchange", evtFSChange);
document.addEventListener("mozfullscreenchange", evtFSChange);
document.addEventListener("webkitfullscreenchange", evtFSChange);
document.addEventListener("msfullscreenchange", evtFSChange);
}
// Download the json for the current page
PromiseXHR(location.origin + location.pathname + ".json", function(data) {
// Parse the JSON
var json = JSON.parse(data);
// Load the image
loadImage(json, true)
});
}
// Reads the parsed JSON object from derpibooru to display the image
function loadImage(image, pushstate) {
// Put up the loading indicator
status("loading");
// Prepare a search string for getting the random image
var qd = {};
location.search.substr(1).split("&").forEach((item) => {var [k,v] = item.split("="); v = v && decodeURIComponent(v); (qd[k] = qd[k] || []).push(v)});
if (typeof qd["q"] !== 'undefined') {
var search = location.search + "&random_image=y";
} else {
var search = "?q=*&random_image=y";
}
// Load all the things!
Promise.all([
new Promise(function(resolve, reject) {
var img = new Image()
img.src = image.image;
img.onload = function() { resolve("Image loaded") };
img.onabort = function() { reject("Image load aborted") }
img.onerror = function() { reject("Image not loaded") };
}),
PromiseXHR(location.origin + "/" + image.id + ".json", function(data) {
// Save the JSON
image.json = JSON.parse(data);
}),
PromiseXHR(location.origin + "/prev/" + image.id + ".json" + location.search, function(data) {
// Save the JSON
image.previmage = JSON.parse(data);
}),
PromiseXHR(location.origin + "/next/" + image.id + ".json" + location.search, function(data) {
// Save the JSON
image.nextimage = JSON.parse(data);
}),
PromiseXHR(location.origin + "/search.json" + search, function(data) {
// Parse the JSON
var json = JSON.parse(data);
// Save the random id
image.randomid = json.id;
}),
PromiseXHR(location.origin + "/" + image.id, function(data) {
// Extract the CSRF token from the HTML response
var pos = data.search('<meta name="csrf-token" content="') + 33;
var substr = data.substring(pos);
var end = substr.search('\\"');
image.CSRFToken = substr.substring(0, end);
})]
).then(function(results) {
// Put the image on the page
document.getElementById("mainimage").src = image.image;
// Set the page title
document.title = image.id + " - Slideshow - Derpibooru - My Little Pony: Friendship is Magic Imageboard"
// Push a history state for this image
if (pushstate) {
history.pushState(null, image.id, location.origin + "/" + image.id + location.search + "#slideshow")
}
// Reset our interactions
image.voted = false;
image.faved = false;
// If there are any interactions...
if (typeof image.json.interactions !== 'undefined') {
// Foreach the interactions table and apply the interactions
image.json.interactions.forEach(function(interaction, index, array){
if (interaction.interaction_type == "voted") {
image.voted = interaction.value;
} else if (interaction.interaction_type == "faved") {
image.faved = true;
}
});
}
// Set the URLs of the metabar buttons
document.getElementById("btnprev").href = location.origin + "/" + image.previmage.id + location.search + "#slideshow";
document.getElementById("btnnext").href = location.origin + "/" + image.nextimage.id + location.search + "#slideshow";
document.getElementById("btnrand").href = location.origin + "/" + image.randomid + location.search + "#slideshow";
document.getElementById("btnfind").href = location.origin + "/find/" + image.id;
document.getElementById("btnclose").href = location.origin + "/" + image.id + location.search;
// Update the metabar
updateMetabar(image);
// Save the image object
window.dbslideshow.image = image;
// Hide the loading indicator
status("done");
}, function(result) {
// Something went wrong, set our indicators and abandon ship!
status("error");
})
}
// Processes the json response from an API interaction request
function processInteraction() {
// Parse the JSON
var json = JSON.parse(this.responseText);
// Update the image with the new values
window.dbslideshow.image.faves = json.favourites;
window.dbslideshow.image.upvotes = json.up_vote_count;
window.dbslideshow.image.downvotes = json.down_vote_count;
window.dbslideshow.image.score = json.score;
updateMetabar(window.dbslideshow.image);
}
// Updates the metabar using the given image object
function updateMetabar(image) {
document.getElementById("numfave").innerHTML = image.faves;
document.getElementById("numupvote").innerHTML = image.upvotes;
document.getElementById("numscore").innerHTML = image.score;
document.getElementById("numdownvote").innerHTML = image.downvotes;
document.getElementById("numcomment").innerHTML = image.comment_count;
document.getElementById("btnfave").className = (image.faved ? "interaction--fave active" : "interaction--fave");
document.getElementById("btnupvote").className = (image.voted == "up" ? "interaction--upvote active" : "interaction--upvote")
document.getElementById("btndownvote").className = (image.voted == "down" ? "interaction--downvote active" : "interaction--downvote")
}
// Sets our current page status
function status(status) {
switch(status) {
case "loading":
window.dbslideshow.loading = true;
document.getElementById("txtloading").className = "";
document.getElementById("txterror").className = "hidden";
window.clearTimeout(window.dbslideshow.errortimer);
break;
case "error":
window.dbslideshow.loading = false;
document.getElementById("txtloading").className = "hidden";
document.getElementById("txterror").className = "";
window.dbslideshow.errortimer = window.setTimeout(function() {
document.getElementById("txterror").className = "hidden";
}, 1000);
break;
case "done":
window.dbslideshow.loading = false;
document.getElementById("txtloading").className = "hidden";
document.getElementById("txterror").className = "hidden";
window.clearTimeout(window.dbslideshow.errortimer);
break;
}
}
// -Event Handlers-
// Event handler for keypresses
function evtKeypress(event) {
// Run the function that goes with the keycode
switch(event.which) {
case 74:
evtPrev();
break;
case 75:
evtNext();
break;
case 82:
evtRandom();
break;
case 73:
evtFind();
break;
case 85:
evtUpvote();
break;
case 70:
evtFave();
break;
}
}
// Event handler for popstates
function evtPopstate(event) {
// Put up the loading indicator
status("loading");
// Check if we changed to a slideshow page, if so load the image
if (location.hash == "#slideshow") {
// Download the json for the new page
PromiseXHR(location.origin + location.pathname + ".json", function(data) {
// Load the image
loadImage(JSON.parse(data), false);
}).then(function(results){}, function(result) {
// Something fucked up, set our indicators
status("error");
// Push a history state so we stay in sync with the image that's on screen
history.pushState(null, window.dbslideshow.image.id, location.origin + "/" + window.dbslideshow.image.id + location.search + "#slideshow")
});
} else {
// If we're no longer in the slideshow, just refresh the page
location.reload();
}
}
// Event handler for the previous image button/key
function evtPrev() {
// Load the previous image we aren't already loading something
if (!window.dbslideshow.loading)
{
loadImage(window.dbslideshow.image.previmage, true);
}
}
// Event handler for the next image button/key
function evtNext() {
// Load the next image if we aren't already loading something
if (!window.dbslideshow.loading)
{
loadImage(window.dbslideshow.image.nextimage, true);
}
}
// Event handler for the random image button/key
function evtRandom() {
// Are we loading something?
if (!window.dbslideshow.loading) {
status("loading");
PromiseXHR(location.origin + "/" + window.dbslideshow.image.randomid + ".json", function(data) {
// Load the image
loadImage(JSON.parse(data), true);
}).then(function(results){}, function(result) {
status("error");
});
}
}
// Event handler for the fave button/key
function evtFave() {
// Filter out derpibooru's weird click() hack
if (evtFave.caller === null || evtFave.caller.name === "evtKeypress") {
// Invert our faved variable
window.dbslideshow.image.faved = !window.dbslideshow.image.faved;
// Set our voted variable if neccesary
if (window.dbslideshow.image.faved)
window.dbslideshow.image.voted = "up";
// Send the interaction to the API with a URL encoded data payload
var interactionRequest = new XMLHttpRequest();
interactionRequest.open("put", location.origin + "/api/v2/interactions/fave", true);
interactionRequest.setRequestHeader("X-CSRF-Token", window.dbslideshow.image.CSRFToken);
interactionRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
interactionRequest.onload = processInteraction;
interactionRequest.send("_method=PUT&id=" + window.dbslideshow.image.id + "&value=" + window.dbslideshow.image.faved + "&class=Image");
}
}
// Event handler for the upvote button/key
function evtUpvote() {
// Filter out derpibooru's weird click() hack
if (evtUpvote.caller === null || evtUpvote.caller.name === "evtKeypress") {
// Set the voted variable
window.dbslideshow.image.voted = (window.dbslideshow.image.voted == "up" ? false : "up");
// Send the interaction to the API with a URL encoded data payload
var interactionRequest = new XMLHttpRequest();
interactionRequest.open("put", location.origin + "/api/v2/interactions/vote", true);
interactionRequest.setRequestHeader("X-CSRF-Token", window.dbslideshow.image.CSRFToken);
interactionRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
interactionRequest.onload = processInteraction;
interactionRequest.send("_method=PUT&id=" + window.dbslideshow.image.id + "&value=" + window.dbslideshow.image.voted + "&class=Image");
}
}
// Event handler for the downvote button
function evtDownvote() {
// Set the voted variable
window.dbslideshow.image.voted = (window.dbslideshow.image.voted == "down" ? false : "down");
// Send the interaction to the API with a URL encoded data payload
var interactionRequest = new XMLHttpRequest();
interactionRequest.open("put", location.origin + "/api/v2/interactions/vote", true);
interactionRequest.setRequestHeader("X-CSRF-Token", window.dbslideshow.image.CSRFToken);
interactionRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
interactionRequest.onload = processInteraction;
interactionRequest.send("_method=PUT&id=" + window.dbslideshow.image.id + "&value=" + window.dbslideshow.image.voted + "&class=Image");
}
// Event handler for the start auto-advance button
function evtAAStart() {
// Set the our elapsedtime to 0ms, used to adjust the timer
window.dbslideshow.aaelapsedtime = 0;
// Save the current time, also for timer adjustment
window.dbslideshow.aastarttime = new Date().getTime();
// Swap the start and stop buttons
document.getElementById("btnaastart").className = "hidden";
document.getElementById("btnaastop").className = "";
// Start the self-adjusting timer
window.dbslideshow.aainterval = window.setTimeout(evtAAInterval, 250);
}
// Event handler for the stop auto-advance button
function evtAAStop() {
// Clear our interval function
window.clearTimeout(window.dbslideshow.aainterval);
// Swap the start and stop buttons
document.getElementById("btnaastop").className = "hidden";
document.getElementById("btnaastart").className = "";
}
function evtShowAASettings() {
// Set the aacontrols variable
window.dbslideshow.aacontrols = true;
// Set the visibility of the auto-advance controls accordingly
document.getElementById("btnshowaasettings").className = "hidden";
document.getElementById("btnhideaasettings").className = "";
document.getElementById("aacontrols").className = "metasection";
}
function evtHideAASettings() {
// Set the aacontrols variable
window.dbslideshow.aacontrols = false;
// Set the visibility of the auto-advance controls accordingly
document.getElementById("btnshowaasettings").className = "";
document.getElementById("btnhideaasettings").className = "hidden";
document.getElementById("aacontrols").className = "hidden metasection";
}
// Event handlers for the delay adjustment buttons
// Minimum delay is 1 second, max is one hour (3600 seconds)
function evtAADown10() {
if (window.dbslideshow.aadelay > 10) {
window.dbslideshow.aadelay -= 10;
} else {
window.dbslideshow.aadelay = 1;
}
document.getElementById("numaadelay").innerHTML = window.dbslideshow.aadelay;
window.dbslideshow.aaelapsedtime = 0;
}
function evtAADown1() {
if (window.dbslideshow.aadelay > 1) {
window.dbslideshow.aadelay -= 1;
document.getElementById("numaadelay").innerHTML = window.dbslideshow.aadelay;
window.dbslideshow.aaelapsedtime = 0;
}
}
function evtAAUp1() {
if (window.dbslideshow.aadelay < 3600) {
window.dbslideshow.aadelay += 1;
document.getElementById("numaadelay").innerHTML = window.dbslideshow.aadelay;
window.dbslideshow.aaelapsedtime = 0;
}
}
function evtAAUp10() {
if (window.dbslideshow.aadelay < 3591) {
window.dbslideshow.aadelay += 10;
} else {
window.dbslideshow.aadelay = 3600;
}
document.getElementById("numaadelay").innerHTML = window.dbslideshow.aadelay;
window.dbslideshow.aaelapsedtime = 0;
}
// Event handlers for the auto-advance mode buttons
function evtAAPrev() {
// Set the auto-advance mode
window.dbslideshow.aamode = "prev";
// Set the color of the mode buttons
document.getElementById("btnaaprev").className = "interaction--upvote active";
document.getElementById("btnaarand").className = "";
document.getElementById("btnaanext").className = "";
}
function evtAARand() {
// Set the auto-advance mode
window.dbslideshow.aamode = "rand";
// Set the color of the mode buttons
document.getElementById("btnaaprev").className = "";
document.getElementById("btnaarand").className = "interaction--upvote active";
document.getElementById("btnaanext").className = "";
}
function evtAANext() {
// Set the auto-advance mode
window.dbslideshow.aamode = "next";
// Set the color of the mode buttons
document.getElementById("btnaaprev").className = "";
document.getElementById("btnaarand").className = "";
document.getElementById("btnaanext").className = "interaction--upvote active";
}
function evtAAInterval() {
// Increment the elapsed time by 250ms
window.dbslideshow.aaelapsedtime += 250;
// Calculate our actual elapsed time, so we can adjust the next interval accordingly
var diff = (new Date().getTime() - window.dbslideshow.aastarttime) - window.dbslideshow.aaelapsedtime;
// If it's time to advance, do so
if (window.dbslideshow.aaelapsedtime === (window.dbslideshow.aadelay * 1000)) {
// Reset the elapsed time
window.dbslideshow.aaelapsedtime = 0;
// Perform the necessary action
if (window.dbslideshow.aamode === "prev") {
evtPrev();
} else if (window.dbslideshow.aamode === "rand") {
evtRandom();
} else if (window.dbslideshow.aamode === "next") {
evtNext();
}
// Set our new start time
window.dbslideshow.aastarttime = new Date().getTime();
}
// Set the next interval, adjusted
window.dbslideshow.aainterval = window.setTimeout(evtAAInterval, (250 - diff));
}
function evtShowToolbar() {
// Set the toolbar variable
window.dbslideshow.toolbar = true;
// Set the visibility of the auto-advance controls accordingly
document.getElementById("btnshowtoolbar").className = "hidden";
document.getElementById("btnhidetoolbar").className = "";
document.getElementsByClassName("navcontainer")[0].className = "navcontainer";
}
function evtHideToolbar() {
// Set the toolbar variable
window.dbslideshow.toolbar = false;
// Set the visibility of the auto-advance controls accordingly
document.getElementById("btnshowtoolbar").className = "";
document.getElementById("btnhidetoolbar").className = "hidden";
document.getElementsByClassName("navcontainer")[0].className = "hidden navcontainer";
}
// Event handler for the fullscreen button
function evtFullscreen() {
// Get a reference to the slideshow container
var container = document.getElementById("slideshow");
// Make the container fullscreen using one of the various browser implementations
if (container.requestFullscreen) {
container.requestFullscreen();
} else if (container.mozRequestFullScreen) {
container.mozRequestFullScreen();
} else if (container.webkitRequestFullscreen) {
container.webkitRequestFullscreen();
} else if (container.msRequestFullscreen) {
container.msRequestFullscreen();
}
}
// Event handler for the restore screen (exit fullscreen) button
function evtRestoreScreen() {
// Exit fullscreen using one of the various browser implementations
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
// Event handler to update the metabar when our fullscreen state changes
function evtFSChange() {
// Check if we are fullscreen using one of the various browser implementations
if (
document.fullscreenElement
|| document.mozFullScreenElement
|| document.webkitFullscreenElement
|| document.msFullscreenElement
) {
var fullscreen = true;
} else {
var fullscreen = false;
}
// Display the appropriate fullscreen button
document.getElementById("btnfullscreen").className = (fullscreen ? "hidden" : "");
document.getElementById("btnrestorescreen").className = (fullscreen ? "" : "hidden");
}
// -Code-
// Global container (ew, globals) for storing persistent data about the page
window.dbslideshow = new Object();
// Make sure we're on an image or gallery page
if (document.getElementsByClassName("layout--wide")[0] != null) {
// Check for the #imagelist-container element found on gallery pages
if (document.getElementById("imagelist_container") != null) {
window.dbslideshow.pagetype = "gallery"
} else {
window.dbslideshow.pagetype = "image";
}
} else {
// Set the pagetype to other, we're done here
window.dbslideshow.pagetype = "other";
}
// If we're on an image or gallery page, find our scope and insert the slideshow button
if (window.dbslideshow.pagetype != "other") {
if (window.dbslideshow.pagetype == "image") {
// If we're on a slideshow page, start the slideshow
if (location.hash == "#slideshow") {
startSlideshow();
} else {
// Insert the small slideshow button
document.getElementsByClassName("stretched-mobile-links")[0].innerHTML += smallButtonHTML;
// Add an event listener to the slideshow button so we know when it gets clicked
document.getElementById("btnslideshow").addEventListener("click", startSlideshow, false);
}
} else if (window.dbslideshow.pagetype == "gallery") {
// Download the json for the current page and get our starting ID
var jsonrequest = new XMLHttpRequest();
// If we're on the homepage, use /images instead of the actual pathname
if (location.pathname == "/") {
jsonrequest.open("get", location.origin + "/images" + ".json" + location.search, true);
} else {
jsonrequest.open("get", location.origin + location.pathname + ".json" + location.search, true);
}
jsonrequest.onload = function() {
// Parse the JSON
var json = JSON.parse(this.responseText);
// Extract the starting ID from the json
if (typeof(json.images) !== 'undefined') {
ID = json.images[0].id;
} else {
ID = json.search[0].id;
}
// Insert the big 'Slideshow' button
document.getElementsByClassName("flex__right")[0].innerHTML += bigButtonHTML;
// Set the href of the slideshow button
document.getElementById ("btnslideshow").href = location.origin + "/" + ID + location.search + "#slideshow";
};
jsonrequest.send();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment