Skip to content

Instantly share code, notes, and snippets.

@mcpower
Last active January 9, 2017 12:05
Show Gist options
  • Save mcpower/0fc6ef8d61a81bfdd7b50e4478b2d293 to your computer and use it in GitHub Desktop.
Save mcpower/0fc6ef8d61a81bfdd7b50e4478b2d293 to your computer and use it in GitHub Desktop.
Dynasty Preloader
// ==UserScript==
// @name Dynasty Preloader
// @namespace http://tampermonkey.net/
// @version 0.3.5.1
// @description Preloads Dynasty Reader pages.
// @author mcpower
// @match http://dynasty-scans.com/chapters/*
// @grant none
// @license GPLv3
// ==/UserScript==
// Dynasty Preloader - a UserScript to preload pages in Dynasty Reader
// Copyright (C) 2017 mcpower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// This preloads Dynasty Reader pages and indicates it with colours.
// Red means it's in the queue, but it hasn't preloaded it yet.
// Yellow means it's currently preloading.
// Green means it's preloaded.
//
// If you wish, you can also preload all pages by clicking on the "Load All" button
// to the right of the "Fullscreen" button.
// Change these variables if you wish.
// lookahead is the number of pages to load ahead of you.
// lookbehind
// max_concurrent is the maximum number of image requests at any one time.
// Turn this down if you get loading screens, even though the page has been preloaded.
const lookahead = 4;
const lookbehind = 2;
const max_concurrent = 5;
(function () {
"use strict";
let queue = []; // page objects
let images = []; // stack/queue of Image objects to be used after they've been loaded
const states = {
default: -1,
queued: 0,
loading: 1,
loaded: 2
};
const state_classes = {
[states.default]: "",
[states.queued]: "queued",
[states.loading]: "loading",
[states.loaded]: "loaded"
};
const state_list = Object.keys(states);
const css_text = ".queued{background:#ebccd1} .loading{background:#fcf8e3} .loaded{background:#dff0d8}";
// initialise images with the image elements
// define the onload event so we don't have to define it later
// just set any Image.page then Image.src and then it'll be all good
function img_onload(event) {
const img = event.path[0];
const page = img.page;
page.state = states.loaded;
images.push(img);
update_style(page);
check_queue();
}
for (let i = 0; i < max_concurrent; i++) {
const cur_img = new Image();
cur_img.onload = img_onload;
images.push(cur_img);
}
function update_style(page) {
if (page.state === page.styled_state) return;
const cl = page.element.classList;
if (page.styled_state !== states.default) {
cl.remove(state_classes[page.styled_state]);
}
cl.add(state_classes[page.state]);
page.styled_state = page.state;
}
// To load stuff, chuck it onto the queue and call this function
function check_queue() {
while (images.length > 0 && queue.length > 0) {
load(queue.shift());
}
}
// Actually, to check stuff on the queue you should probably use this function
// You still need to call check_queue though.
function chuck_on_queue(page) {
if (page.state === states.loading || page.state === states.loaded) return;
page.state = states.queued;
queue.push(page);
update_style(page);
}
function load(page) {
if (page.state === states.loading || page.state === states.loaded) return;
const img = images.pop();
page.state = states.loading;
update_style(page);
img.page = page;
img.src = page.image;
}
// loads `lookahead` pages after the current page and `lookbehind` before.
function load_lookahead() {
let cur_page;
switch (window.location.hash) {
case "#last":
cur_page = window.pages.length;
break;
case "":
cur_page = 1;
break;
default:
cur_page = parseInt(window.location.hash.substr(1));
}
// clamp juust in case
cur_page = Math.min(window.pages.length, Math.max(1, cur_page));
const cur_index = cur_page - 1;
// Always load lookahead before lookbehind
for (let i = cur_index; i <= cur_index + lookahead && i < window.pages.length; i++) {
chuck_on_queue(window.pages[i]);
}
for (let i = cur_index - 1; i >= cur_index - lookbehind && i >= 0; i--) {
chuck_on_queue(window.pages[i]);
}
check_queue();
}
// loads all pages
function load_all() {
window.pages.forEach(chuck_on_queue);
check_queue();
return false;
}
// inject the CSS we want
const css = document.createElement("style");
css.innerHTML = css_text;
document.body.appendChild(css);
// precalculate all the DOM elements
const pages_list = document.getElementById("prev_link").parentElement;
for (let i = 0; i < window.pages.length; i++) {
window.pages[i].element = pages_list.children[i+1];
window.pages[i].state = states.default;
window.pages[i].styled_state = states.default;
}
// create the "Load All" button
const load_button = document.createElement("a");
load_button.className = "btn btn-mini";
load_button.innerHTML = "Load All";
load_button.href = "#";
load_button.onclick = load_all;
document.getElementById("fullscreen").insertAdjacentElement("afterend", load_button);
// lookahead stuff
window.addEventListener("hashchange", load_lookahead);
load_lookahead();
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment