Last active
April 26, 2019 11:32
-
-
Save p-a-t-a-r/9ab8ee5c515574c58b68 to your computer and use it in GitHub Desktop.
Derpibooru Image Slideshow (Greasemonkey Userscript for derpibooru.org)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==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">–</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