您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds custom quality of life features to MSPFA.
当前为
- // ==UserScript==
- // @name MSPFA extras
- // @namespace http://tampermonkey.net/
- // @version 1.7.2
- // @description Adds custom quality of life features to MSPFA.
- // @author seymour schlong
- // @icon https://pipe.miroware.io/5b52ba1d94357d5d623f74aa/mspfa/ico.png
- // @icon64 https://pipe.miroware.io/5b52ba1d94357d5d623f74aa/mspfa/ico.png
- // @match https://mspfa.com/
- // @match https://mspfa.com/*/
- // @match https://mspfa.com/*/?*
- // @match https://mspfa.com/?s=*
- // @match https://mspfa.com/my/*
- // @match https://mspfa.com/random/
- // @exclude https://mspfa.com/js/*
- // @exclude https://mspfa.com/css/*
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- const currentVersion = "1.7.2";
- console.log(`MSPFA extras script v${currentVersion} by seymour schlong`);
- const debug = false;
- /**
- * https://github.com/GrantGryczan/MSPFA/projects/1?fullscreen=true
- * Github to-do completion list (and other stuff too)
- *
- * https://github.com/GrantGryczan/MSPFA/issues/26 - Dropdown menu - February 23rd, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/18 - MSPFA themes - February 23rd, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/32 - Adventure creation dates - February 23rd, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/32 - User creation dates - February 23rd, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/40 - Turn certain buttons into links - July 21st, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/41 - Word and character count - July 21st, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/57 - Default spoiler values - August 7th, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/62 - Buttonless spoilers - August 7th, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/52 - Hash URLs - August 8th, 2020
- * - Page drafts - August 8th, 2020
- * - Edit pages button - August 8th, 2020
- * - Image preloading - August 20th, 2020
- * https://github.com/GrantGryczan/MSPFA/issues/19 - Manage game saves - August 22nd, 2020
- *
- * Extension to-do... maybe...
- *
- * If trying to save a page and any other save button is not disabled, ask the user if they would rather Save All instead, or prompt to disable update notifications.
- * When adding a new page, store it in an array and if that array length is > 1 when someone tries to save, prompt them to press Save All?
- */
- // A general function that allows for waiting until a certain element appears on the page.
- const pageLoad = (fn, length) => {
- const interval = setInterval(() => {
- if (fn()) clearInterval(interval);
- }, length ? length*1000 : 500);
- };
- // Saves the options data for the script.
- const saveData = (data) => {
- localStorage.mspfaextra = JSON.stringify(data);
- if (debug) {
- console.log('Settings:');
- console.log(data);
- }
- };
- // Saves the data for drafts
- const saveDrafts = (data) => {
- localStorage.mspfadrafts = JSON.stringify(data);
- if (debug) {
- console.log('Drafts:');
- console.log(data);
- }
- };
- // Encases an element within a link
- const addLink = (elm, url, target) => {
- const link = document.createElement('a');
- link.href = url;
- link.draggable = false;
- if (elm.parentNode) elm.parentNode.insertBefore(link, elm);
- if (target) link.target = target;
- link.appendChild(elm);
- return link;
- };
- // Easy br element
- const newBr = () => {
- return document.createElement('br');
- }
- // Make creating label elements easier
- const createLabel = (text, id) => {
- const newLabel = document.createElement('label');
- newLabel.textContent = text;
- newLabel.setAttribute('for', id);
- return newLabel;
- }
- let settings = {};
- let drafts = {};
- const defaultSettings = {
- autospoiler: false,
- style: 0,
- styleURL: "",
- night: false,
- auto502: true,
- textFix: false,
- pixelFix: false,
- intro: false,
- commandScroll: false,
- preload: true,
- dialogKeys: true,
- dialogFocus: false,
- spoilerValues: {}
- }
- let pageLoaded = false;
- const loadDrafts = () => {
- if (localStorage.mspfadrafts) {
- drafts = JSON.parse(localStorage.mspfadrafts);
- }
- }
- loadDrafts();
- // Load any previous settings from localStorage
- if (localStorage.mspfaextra) {
- Object.assign(settings, JSON.parse(localStorage.mspfaextra));
- // Get draft data from settings
- if (typeof settings.drafts === "object") {
- if (Object.keys(settings.drafts).length > 0 && Object.keys(drafts).length === 0) {
- drafts = settings.drafts;
- }
- }
- saveDrafts(drafts);
- }
- // If any settings are undefined, re-set to their default state. (For older users when new things get stored)
- const checkSettings = () => {
- const defaultSettingsKeys = Object.keys(defaultSettings);
- for (let i = 0; i < defaultSettingsKeys.length; i++) {
- if (typeof settings[defaultSettingsKeys[i]] === "undefined") {
- settings[defaultSettingsKeys[i]] = defaultSettings[defaultSettingsKeys[i]];
- }
- }
- saveData(settings);
- }
- checkSettings();
- if (GM_info && GM_info.scriptHandler !== "Tampermonkey" && !settings.warned) {
- alert(`It appears that you're running the MSPFA extras script with ${GM_info.scriptHandler}.\nUnfortunately, this script cannot run at its full potential because of that.\nTry switching to Tampermonkey if you want to use more of the features!\n(this message will only appear once.)`);
- settings.warned = true;
- saveData(settings);
- }
- // Scrolls you to where you need to be
- const hashSearch = location.href.replace(location.origin + location.pathname, '').replace(location.search, '');
- if (hashSearch !== '') {
- pageLoad(() => {
- const idElement = document.querySelector(hashSearch);
- if (idElement) {
- const selected = document.querySelector(hashSearch);
- selected.scrollIntoView();
- selected.style.outline = '3px solid black';
- selected.style.transition = '0.5s';
- pageLoad(() => {
- if (pageLoaded) {
- selected.style.outline = '0px solid black';
- }
- });
- return true;
- }
- }, 1);
- }
- // Ripped shamelessly right from mspfa lol (URL search parameters -- story ID, page num, etc.)
- let rawParams;
- if (location.href.indexOf("#") != -1) {
- rawParams = location.href.slice(0, location.href.indexOf("#"));
- } else {
- rawParams = location.href;
- }
- if (rawParams.indexOf("?") != -1) {
- rawParams = rawParams.slice(rawParams.indexOf("?") + 1).split("&");
- } else {
- rawParams = [];
- }
- const params = {};
- for (let i = 0; i < rawParams.length; i++) {
- try {
- const p = rawParams[i].split("=");
- params[p[0]] = decodeURIComponent(p[1]);
- } catch (err) {}
- }
- if (debug) {
- console.log('URL parameters:');
- console.log(params);
- }
- // Functions to get/change data from the console
- window.MSPFAe = {
- getSettings: () => {
- return settings;
- },
- getSettingsString: (formatted) => {
- if (formatted) {
- console.log(JSON.stringify(settings, null, 4));
- } else {
- console.log(JSON.stringify(settings));
- }
- },
- getDrafts: () => {
- loadDrafts();
- return drafts;
- },
- getDraftsString: (formatted) => {
- loadDrafts();
- if (formatted) {
- console.log(JSON.stringify(drafts, null, 4));
- } else {
- console.log(JSON.stringify(drafts));
- }
- },
- changeSettings: (newSettings) => {
- console.log('Settings updated');
- console.log(settings);
- Object.assign(settings, newSettings);
- saveData(settings);
- },
- changeSettingsString: (fullString) => {
- try {
- JSON.parse(fullString);
- } catch (err) {
- console.error(err);
- return;
- }
- settings = JSON.parse(fullString);
- checkSettings();
- console.log(settings);
- },
- getParams: params
- }
- // Error reloading
- window.addEventListener("load", () => {
- // Reload the page if 502 CloudFlare error page appears
- if (settings.auto502 && document.querySelector('#cf-wrapper')) {
- window.location.reload();
- }
- // Wait five seconds, then refresh the page
- if (document.body.textContent === "Your client is sending data to MSPFA too quickly. Wait a moment before continuing.") {
- setTimeout(() => {
- window.location.reload();
- }, 5000);
- }
- pageLoaded = true;
- });
- // Delete any unchanged spoiler values
- if (location.pathname !== "/my/stories/pages/") {
- // Go through spoiler values and remove any that aren't unique
- Object.keys(settings.spoilerValues).forEach(adventure => {
- if (settings.spoilerValues[adventure].open === "Show" && settings.spoilerValues[adventure].close === "Hide") {
- delete settings.spoilerValues[adventure];
- } else if (settings.spoilerValues[adventure].open === '' && settings.spoilerValues[adventure].close === '') {
- delete settings.spoilerValues[adventure];
- }
- });
- }
- const styleOptions = ["Standard", "Low Contrast", "Light", "Dark", "Felt", "Trickster", "Custom"];
- const styleUrls = ['', '/css/theme1.css', '/css/theme2.css', 'https://pipe.miroware.io/5b52ba1d94357d5d623f74aa/mspfa/themes/dark.css', '/css/theme4.css', '/css/theme5.css'];
- const createDropdown = (parent, explore) => {
- const dropDiv = document.createElement('div');
- dropDiv.className = 'dropdown';
- dropDiv.style.display = 'inline-block';
- const dropContent = document.createElement('div');
- dropContent.className = 'dropdown-content';
- dropContent.style.display = 'none';
- if (!explore) {
- dropDiv.addEventListener('mouseenter', evt => {
- dropContent.style.display = 'block';
- dropContent.style.color = getComputedStyle(parent).color;
- dropContent.querySelectorAll('a').forEach(link => {
- link.style.color = getComputedStyle(parent).color;
- });
- });
- dropDiv.addEventListener('mouseleave', evt => {
- dropContent.style.display = 'none';
- });
- }
- parent.parentNode.insertBefore(dropDiv, parent);
- dropDiv.appendChild(parent);
- dropDiv.appendChild(dropContent);
- return [dropDiv, dropContent];
- }
- // "MY MSPFA" dropdown
- const myLink = document.querySelector('nav a[href="/my/"]');
- if (myLink) {
- const dropContent = createDropdown(myLink)[1];
- const dLinks = [];
- dLinks[0] = [ 'Messages', 'My Adventures', 'Settings' ];
- dLinks[1] = [ '/my/messages/', '/my/stories/', '/my/settings/' ];
- for (let i = 0; i < dLinks[0].length; i++) {
- const newLink = document.createElement('a');
- newLink.textContent = dLinks[0][i];
- newLink.href = dLinks[1][i];
- dropContent.appendChild(newLink);
- }
- // Append "My Profile" to the dropdown list if you're signed in
- pageLoad(() => {
- if (window.MSPFA) {
- if (window.MSPFA.me.n) {
- if (settings.dropFav) {
- const newFavLink = document.createElement('a');
- newFavLink.textContent = "My Favourites";
- newFavLink.href = `/favs/?u=${window.MSPFA.me.i}`;
- dropContent.appendChild(newFavLink);
- }
- const newMyLink = document.createElement('a');
- newMyLink.textContent = "My Profile";
- newMyLink.href = `/user/?u=${window.MSPFA.me.i}`;
- dropContent.appendChild(newMyLink);
- // Move SETTINGS to the bottom
- dropContent.appendChild(dropContent.querySelectorAll('a')[2]);
- return true;
- }
- }
- });
- }
- // "RANDOM" dropdown
- const randomLink = document.querySelector('nav a[href="/random/"]');
- if (randomLink) {
- // Thank you @MadCreativity 🙏
- const dropContent = createDropdown(randomLink)[1];
- (async () => {
- const dLinks = [];
- dLinks[0] = [ 'Recent ongoing' ];
- dLinks[1] = [ await fetch(`https://mspfa-extras-server.herokuapp.com/api/random`).then(e => e.text()) ];
- for (let i = 0; i < dLinks[0].length; i++) {
- const newLink = document.createElement('a');
- newLink.textContent = dLinks[0][i];
- newLink.href = dLinks[1][i];
- dropContent.appendChild(newLink);
- }
- })()
- }
- // "EXPLORE" dropdown
- const exploreLink = document.querySelector('nav a[href="/stories/"');
- if (exploreLink) {
- const dropdown = createDropdown(exploreLink, true);
- const dropDiv = dropdown[0];
- const dropContent = dropdown[1];
- const exploreInput = document.createElement('input');
- Object.assign(exploreInput, { type: 'text', placeholder: 'Search...', id: 'dropdown-explore' });
- dropContent.appendChild(exploreInput);
- exploreInput.addEventListener('keydown', ke => {
- if (ke.code === 'Enter') {
- const searchLink = `/stories/?go=1&n=${encodeURIComponent(exploreInput.value)}&t=&h=14&o=favs&p=p&m=50&load=true`;
- if (ke.altKey || ke.ctrlKey) {
- window.open(searchLink, '_blank').focus();
- } else {
- location.href = searchLink;
- }
- return;
- }
- });
- dropDiv.addEventListener('mouseenter', evt => {
- dropContent.style.display = 'block';
- });
- dropDiv.addEventListener('mouseleave', evt => {
- // If input is focused
- if (document.activeElement !== exploreInput) {
- dropContent.style.display = 'none';
- }
- });
- document.body.addEventListener('click', evt => {
- if (document.activeElement !== exploreInput) {
- dropContent.style.display = 'none';
- }
- });
- }
- document.querySelector('header .mspfalogo').parentNode.draggable = false;
- addLink(document.querySelector('footer .mspfalogo'), 'javascript:void(0);');
- // Message that shows when you first get the script
- const showIntroDialog = () => {
- const msg = window.MSPFA.parseBBCode('Hi! Thanks for installing this script!\n\nBe sure to check the [url=https://greasyfork.org/en/scripts/396798-mspfa-extras#additional-info]GreasyFork[/url] page to see a full list of features, and don\'t forget to check out your [url=https://mspfa.com/my/settings/#extraSettings]settings[/url] page to tweak things to how you want.\n\nIf you have any suggestions, or you find a bug, please be sure to let me know on Discord at [url=discord://discordapp.com/users/277928549866799125]@seymour schlong#3669[/url].\n\n[size=12]This dialog will only appear once. To view it again, click "View Script Message" at the bottom of the site.[/size]');
- window.MSPFA.dialog("MSPFA extras message", msg, ["Okay"]);
- }
- // Check if show intro dialog has displayed
- if (!settings.intro) {
- pageLoad(() => {
- if (window.MSPFA) {
- showIntroDialog();
- settings.intro = true;
- saveData(settings);
- return true;
- }
- });
- }
- const details = document.querySelector('#details');
- // Add 'link' at the bottom to show the intro dialog again
- const introLink = document.createElement('a');
- introLink.textContent = 'View Script Message';
- introLink.href = 'javascript:void(0);';
- introLink.addEventListener('click', showIntroDialog);
- details.appendChild(introLink);
- // vbar!!!!
- const vbar = document.createElement('span');
- Object.assign(vbar, {className: 'vbar', textContent: '|'});
- details.appendChild(document.createTextNode(' '));
- details.appendChild(vbar);
- details.appendChild(document.createTextNode(' '));
- // if you really enjoy the script and has some extra moneys 🥺
- const donateLink = document.createElement('a');
- donateLink.textContent = 'Donate';
- donateLink.href = 'https://ko-fi.com/ironbean';
- donateLink.target = "blank";
- details.appendChild(donateLink);
- // Theme stuff
- const theme = document.createElement('link');
- Object.assign(theme, { id: 'theme', type: 'text/css', rel: 'stylesheet' });
- const updateTheme = (src) => {
- theme.href = src;
- }
- if (!document.querySelector('#theme')) {
- document.querySelector('head').appendChild(theme);
- if (settings.night) {
- updateTheme(styleUrls[3]);
- } else {
- updateTheme(settings.style == styleOptions.length - 1 ? settings.styleURL : styleUrls[settings.style]);
- }
- }
- const pixelText = () => {
- return settings.pixelFix ? 'body { image-rendering: pixelated; image-rendering: -moz-crisp-edges; }' : '';
- }
- // Dropdown menu and pixelated scaling
- const mspfaeCSS = document.createElement('link');
- Object.assign(mspfaeCSS, { id: 'script-css', type: 'text/css', rel: 'stylesheet', href: 'https://pipe.miroware.io/5b52ba1d94357d5d623f74aa/mspfa/mspfae.css' });
- document.querySelector('head').appendChild(mspfaeCSS);
- const extraStyle = document.createElement('style');
- if (!document.querySelector('#extra-style')) {
- extraStyle.id = 'extra-style';
- extraStyle.textContent = pixelText();
- document.querySelector('head').appendChild(extraStyle);
- }
- let nightSwitch = [];
- // Enabling night mode.
- document.querySelector('footer .mspfalogo').addEventListener('click', evt => {
- settings.night = !settings.night;
- saveData(settings);
- for (let i = 0; i < nightSwitch.length; i++) {
- clearTimeout(nightSwitch[i]);
- }
- nightSwitch = [];
- // Transition to make it feel nicer on the eyes
- extraStyle.textContent = pixelText();
- extraStyle.textContent = pixelText() + ' *{transition:1.5s;}';
- if (settings.night) {
- updateTheme(styleUrls[3]);
- } else {
- updateTheme(settings.style == styleOptions.length - 1 ? settings.styleURL : styleUrls[settings.style]);
- }
- nightSwitch.push(setTimeout(() => {
- extraStyle.textContent = pixelText();
- }, 1500));
- });
- // Enable keyboard controls for some dialog boxes (enter/esc to accept/close)
- const dialog = document.querySelector('#dialog');
- document.addEventListener('keydown', evt => {
- if (settings.dialogKeys && !dialog.textContent.includes('BBCode')) {
- if (dialog.style.display === '' && (evt.code === 'Enter' || evt.code === "Escape") && (document.activeElement === document.body || settings.dialogFocus)) {
- let buttons = dialog.querySelectorAll('button');
- if (buttons.length === 1) {
- buttons[0].click();
- } else if (buttons.length === 2) {
- if (buttons[0].textContent === 'Okay' && evt.code === "Enter") {
- buttons[0].click();
- }
- }
- if (["Cancel", "Close"].indexOf(buttons[buttons.length - 1].textContent) !== -1 && evt.code === "Escape") {
- buttons[buttons.length - 1].click();
- }
- }
- }
- });
- if (location.pathname.includes('//')) {
- location.href = location.pathname.replace(/\/\//g, '/') + location.search;
- }
- if (location.pathname === "/" || location.pathname === "/preview/") {
- if (location.search) {
- // Remove the current theme if the adventure has CSS (to prevent conflicts);
- if (settings.style > 0) {
- pageLoad(() => {
- if (window.MSPFA) {
- if (window.MSPFA.story && window.MSPFA.story.y && (window.MSPFA.story.y.toLowerCase().includes('import') || window.MSPFA.story.y.includes('{'))) {
- if (!settings.night) updateTheme('');
- return true;
- }
- }
- if (pageLoaded) return true;
- });
- }
- // Preload adjacent pages
- if (settings.preload) {
- const preloadImages = document.createElement('div');
- preloadImages.id = 'preload';
- document.querySelector('#container').appendChild(preloadImages);
- window.MSPFA.slide.push(p => {
- preloadImages.innerHTML = '';
- if (window.MSPFA.story.p[p-2]) {
- let page = window.MSPFA.parseBBCode(window.MSPFA.story.p[p-2].b);
- page.querySelectorAll('img').forEach(image => {
- preloadImages.appendChild(image);
- });
- page.innerHTML = '';
- }
- if (window.MSPFA.story.p[p]) {
- let page = window.MSPFA.parseBBCode(window.MSPFA.story.p[p].b);
- page.querySelectorAll('img').forEach(image => {
- preloadImages.appendChild(image);
- });
- page.innerHTML = '';
- }
- });
- }
- // Automatic spoiler opening
- if (settings.autospoiler) {
- window.MSPFA.slide.push((p) => {
- document.querySelectorAll('#slide .spoiler:not(.open) > div:first-child > input').forEach(sb => sb.click());
- });
- }
- // Scroll up to the nav bar when changing page so you don't have to scroll down as much =)
- if (settings.commandScroll) {
- const heightTop = document.querySelector('nav').getBoundingClientRect().top - document.body.getBoundingClientRect().top;
- let temp = -2; // To prevent moving the page down when loading it for the first time
- window.MSPFA.slide.push((p) => {
- if (temp < 0) {
- temp++;
- } else {
- window.scroll(0, heightTop);
- }
- });
- }
- // Show creation date
- pageLoad(() => {
- if (document.querySelector('#infobox tr td:nth-child(2)')) {
- document.querySelector('#infobox tr td:nth-child(2)').appendChild(document.createTextNode('Creation date: ' + new Date(window.MSPFA.story.d).toString().split(' ').splice(1, 3).join(' ')));
- return true;
- }
- });
- // Hash scrolling and opening infobox or commmentbox
- if (['#infobox', '#commentbox', '#newcomment', '#latestpages'].indexOf(hashSearch) !== -1) {
- pageLoad(() => {
- if (document.querySelector(hashSearch)) {
- if (hashSearch === '#infobox') {
- document.querySelector('input[data-open="Show Adventure Info"]').click();
- } else if (hashSearch === '#commentbox' || hashSearch === '#newcomment') {
- document.querySelector('input[data-open="Show Comments"]').click();
- } else if (hashSearch === '#latestpages') {
- document.querySelector('input[data-open="Show Adventure Info"]').click();
- document.querySelector('input[data-open="Show Latest Pages"]').click();
- }
- return true;
- }
- });
- }
- // Attempt to fix text errors
- if (settings.textFix && location.pathname !== "/preview/") {
- pageLoad(() => {
- if (window.MSPFA.story && window.MSPFA.story.p) {
- // russian/bulgarian is not possible =(
- const currentPage = parseInt(/^\?s(?:.*?)&p=([\d]*)$/.exec(location.search)[1]);
- const library = [
- ["�", "'"],
- ["Ã�", "Ñ"],
- ["ñ", "ñ"],
- ["ó", "ó"],
- ["á", "á"],
- ["Ä�", "ą"],
- ["í", "í"],
- ["ú", "ú"],
- ["é", "é"],
- ["Å�", "ł"],
- ["ż", "ż"],
- ["¡", "¡"],
- ["¿", "¿"],
- ["Nº", "#"]
- ];
- // https://mspfa.com/?s=5280&p=51 -- unknown error
- const replaceTerms = (p) => {
- library.forEach(term => {
- if (window.MSPFA.story.p[p]) {
- window.MSPFA.story.p[p].c = window.MSPFA.story.p[p].c.replace(new RegExp(term[0], 'g'), term[1]);
- window.MSPFA.story.p[p].b = window.MSPFA.story.p[p].b.replace(new RegExp(term[0], 'g'), term[1]);
- }
- });
- };
- replaceTerms(currentPage-1);
- window.MSPFA.slide.push(p => {
- replaceTerms(p);
- replaceTerms(p-2);
- });
- return true;
- }
- });
- }
- // Turn buttons into links
- const pageButton = document.createElement('button');
- const pageLink = addLink(pageButton, `/my/stories/pages/?s=${params.s}#p${params.p}`);
- pageButton.className = 'pages edit major';
- pageButton.type = 'button';
- pageButton.title = 'Edit Pages';
- // Edit pages button & button link
- pageLoad(() => {
- const infoButton = document.querySelector('.edit.major');
- if (infoButton) {
- pageLoad(() => {
- if (window.MSPFA.me.i) {
- infoButton.title = "Edit Info";
- infoButton.parentNode.insertBefore(pageLink, infoButton);
- infoButton.parentNode.insertBefore(document.createTextNode(' '), infoButton);
- addLink(infoButton, `/my/stories/info/?s=${params.s}`);
- pageButton.style.display = document.querySelector('.edit.major:not(.pages)').style.display;
- // Change change page link when switching pages
- window.MSPFA.slide.push(p => {
- const newSearch = location.search.split('&p=');
- pageLink.href = `/my/stories/pages/?s=${params.s}#p${newSearch[1].split('#')[0]}`;
- });
- return true;
- }
- });
- addLink(document.querySelector('.rss.major'), `/rss/?s=${params.s}`);
- return true;
- }
- });
- // Add "Reply" button next to comment gear
- setInterval(() => {
- if (document.querySelector('#commentbox > .spoiler.open')) {
- document.querySelectorAll('.gear').forEach(gear => {
- if (!gear.parentNode.querySelector('.reply')) {
- const replyDiv = document.createElement('div');
- replyDiv.className = 'reply';
- gear.insertAdjacentElement('afterEnd', replyDiv);
- gear.insertAdjacentHTML('afterEnd', '<span style="float: right"> </span>');
- const userID = gear.parentNode.parentNode.classList[2].replace('u', '');
- replyDiv.addEventListener('click', () => {
- const commentBox = document.querySelector('#commentbox textarea');
- commentBox.value = `[user]${userID}[/user], ${commentBox.value}`;
- commentBox.focus();
- commentBox.parentNode.scrollIntoView();
- });
- }
- });
- }
- }, 500);
- }
- }
- else if (location.pathname === "/my/") {
- const parent = document.querySelector('#editstories').parentNode;
- const viewSaves = document.createElement('a');
- Object.assign(viewSaves, { id: 'viewsaves', className: 'major', textContent: 'View Adventure Saves' });
- parent.appendChild(viewSaves);
- parent.appendChild(newBr());
- parent.appendChild(newBr());
- pageLoad(() => {
- if (window.MSPFA && window.MSPFA.me && window.MSPFA.me.i) {
- viewSaves.href = `/?s=36596&p=6`;
- return true;
- }
- });
- document.querySelector('#editstories').classList.remove('alt');
- }
- else if (location.pathname === "/my/settings/") { // Custom settings
- const saveBtn = document.querySelector('#savesettings');
- const table = document.querySelector("#editsettings tbody");
- let saveTr = table.querySelectorAll("tr");
- saveTr = saveTr[saveTr.length - 1];
- const headerTr = document.createElement('tr');
- const header = document.createElement('th');
- Object.assign(header, { id: 'extraSettings', textContent: 'Extra Settings' });
- headerTr.appendChild(header);
- const moreTr = document.createElement('tr');
- const more = document.createElement('td');
- more.textContent = "* This only applies to a select few older adventures that have had their text corrupted. Some punctuation is fixed, as well as regular characters with accents. Currently only some spanish/french is fixable. Russian/Bulgarian is not possible.";
- moreTr.appendChild(more);
- const settingsTr = document.createElement('tr');
- const localMsg = document.createElement('span');
- const settingsTd = document.createElement('td');
- localMsg.innerHTML = "Because this is an extension, any data saved is only <b>locally</b> on this device.<br>Don't forget to <b>save</b> when you've finished making changes!";
- const plusTable = document.createElement('table');
- const plusTbody = document.createElement('tbody');
- plusTable.appendChild(plusTbody);
- settingsTd.appendChild(localMsg);
- settingsTd.appendChild(newBr());
- settingsTd.appendChild(newBr());
- settingsTd.appendChild(plusTable);
- settingsTr.appendChild(settingsTd);
- plusTable.style = "text-align: center;";
- // Create checkbox (soooo much better)
- const createCheckbox = (text, checked, id) => {
- const optionTr = plusTbody.insertRow(plusTbody.childNodes.length);
- const optionTextTd = optionTr.insertCell(0);
- const optionLabel = createLabel(text, id);
- const optionInputTd = optionTr.insertCell(1);
- const optionInput = document.createElement('input');
- optionInputTd.appendChild(optionInput);
- optionTextTd.appendChild(optionLabel);
- optionInput.type = "checkbox";
- optionInput.checked = checked;
- optionInput.id = id;
- return optionInput;
- }
- const spoilerInput = createCheckbox("Automatically open spoilers:", settings.autospoiler, 'autospoiler');
- const preloadInput = createCheckbox("Preload images for the pages immediately before and after:", settings.preload, 'preload');
- const dropFavInput = createCheckbox("Adds \"My Favourites\" to the dropdown menu:", settings.dropFav, 'dropFav');
- const errorInput = createCheckbox("Automatically reload Cloudflare 502 error pages:", settings.auto502, 'auto502');
- const commandScrollInput = createCheckbox("Scroll back up to the nav bar when switching page:", settings.commandScroll, 'commandScroll');
- const dialogKeysInput = createCheckbox("Use enter/escape keys to accept/exit control some dialogs:", settings.dialogKeys, 'dialogKeys');
- const dialogFocusInput = createCheckbox("Let keys work while dialog isn't focused (above required):", settings.dialogFocus, 'dialogFocus');
- const pixelFixInput = createCheckbox("Change pixel scaling to nearest neighbour:", settings.pixelFix, 'pixelFix');
- const textFixInput = createCheckbox("Attempt to fix text errors (experimental)*:", settings.textFix, 'textFix');
- const cssTr = plusTbody.insertRow(plusTbody.childNodes.length);
- const cssTextTd = cssTr.insertCell(0);
- const cssSelectTd = cssTr.insertCell(1);
- const cssSelect = document.createElement('select');
- cssSelectTd.appendChild(cssSelect);
- cssTextTd.textContent = "Change style:";
- const customTr = plusTbody.insertRow(plusTbody.childNodes.length);
- const customTextTd = customTr.insertCell(0);
- const customCssTd = customTr.insertCell(1);
- const customCssInput = document.createElement('input');
- customCssTd.appendChild(customCssInput);
- customTextTd.textContent = "Custom CSS URL:";
- customCssInput.style.width = "99px";
- customCssInput.value = settings.styleURL;
- styleOptions.forEach(o => cssSelect.appendChild(new Option(o, o)));
- saveTr.parentNode.insertBefore(headerTr, saveTr);
- saveTr.parentNode.insertBefore(settingsTr, saveTr);
- saveTr.parentNode.insertBefore(moreTr, saveTr);
- cssSelect.selectedIndex = settings.style;
- const buttonSpan = document.createElement('span');
- const draftButton = document.createElement('input');
- const spoilerButton = document.createElement('input');
- draftButton.value = 'Manage Drafts';
- draftButton.className = 'major';
- draftButton.type = 'button';
- spoilerButton.value = 'Manage Spoiler Values';
- spoilerButton.className = 'major';
- spoilerButton.type = 'button';
- buttonSpan.appendChild(draftButton);
- buttonSpan.appendChild(document.createTextNode(' '));
- buttonSpan.appendChild(spoilerButton);
- settingsTd.appendChild(buttonSpan);
- const draftMsg = window.MSPFA.parseBBCode('Here you can manage the drafts that you have saved for your adventure(s).\n');
- const listTable = document.createElement('table');
- listTable.id = 'draft-table';
- const listTbody = document.createElement('tbody');
- listTable.appendChild(listTbody);
- const draftsEmpty = () => {
- loadDrafts();
- let empty = true;
- Object.keys(drafts).forEach(adv => {
- if (empty) {
- const length = typeof drafts[adv].cachedTitle === "undefined" ? 0 : 1;
- if (Object.keys(drafts[adv]).length > length) {
- empty = false;
- }
- }
- });
- return empty;
- }
- setInterval(() => {
- draftButton.disabled = draftsEmpty();
- }, 1000);
- draftButton.addEventListener('click', () => {
- draftMsg.appendChild(listTable);
- listTbody.innerHTML = '';
- loadDrafts();
- const addAdv = (story, name) => {
- const storyTr = listTbody.insertRow(listTable.rows);
- const titleLink = document.createElement('a');
- Object.assign(titleLink, { className: 'major', href: `/my/stories/pages/?s=${story}&click=d`, textContent: name, target: '_blank' });
- storyTr.insertCell(0).appendChild(titleLink);
- const deleteButton = document.createElement('input');
- Object.assign(deleteButton, { className: 'major', type: 'button', value: 'Delete' });
- storyTr.insertCell(1).appendChild(deleteButton);
- deleteButton.addEventListener('click', () => {
- setTimeout(() => {
- window.MSPFA.dialog('Delete adventure draft?', document.createTextNode('Are you really sure?\nThis action cannot be undone!'), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- loadDrafts();
- drafts[story] = {};
- if (settings.drafts && settings.drafts[story]) {
- delete settings.drafts[story];
- saveData(settings);
- }
- saveDrafts(drafts);
- setTimeout(() => {
- draftButton.click();
- }, 1);
- if (draftsEmpty) {
- draftButton.disabled = true;
- }
- }
- });
- }, 1);
- });
- }
- Object.keys(drafts).forEach(adv => {
- const length = typeof drafts[adv].cachedTitle === "undefined" ? 0 : 1;
- if (Object.keys(drafts[adv]).length > length) {
- if (!!length) {
- addAdv(adv, drafts[adv].cachedTitle);
- }
- else {
- window.MSPFA.request(0, {
- do: "story",
- s: adv
- }, story => {
- if (typeof story !== "undefined") {
- console.log(story);
- addAdv(adv, story.n);
- }
- });
- }
- }
- });
- window.MSPFA.dialog('Manage Drafts', draftMsg, ["Delete All", "Close"], (output, form) => {
- if (output === "Delete All") {
- setTimeout(() => {
- window.MSPFA.dialog('Delete all Drafts?', document.createTextNode('Are you really sure?\nThis action cannot be undone!'), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- Object.keys(drafts).forEach(adv => {
- drafts[adv] = {};
- });
- saveDrafts(drafts);
- if (typeof settings.drafts !== "undefined") {
- delete settings.drafts;
- saveData(settings);
- }
- draftButton.disabled = true;
- }
- });
- }, 1);
- }
- });
- });
- if (Object.keys(settings.spoilerValues).length === 0) {
- spoilerButton.disabled = true;
- }
- const spoilerMsg = window.MSPFA.parseBBCode('Here you can manage the spoiler values that you have set for your adventure(s).\nClick on an adventure\'s title to see the values.\n');
- spoilerButton.addEventListener('click', () => {
- spoilerMsg.appendChild(listTable);
- listTbody.innerHTML = '';
- Object.keys(settings.spoilerValues).forEach(adv => {
- window.MSPFA.request(0, {
- do: "story",
- s: adv
- }, story => {
- if (typeof story !== "undefined") {
- const storyTr = listTbody.insertRow(listTable.rows);
- const titleLink = document.createElement('a');
- Object.assign(titleLink, { className: 'major', href: `/my/stories/pages/?s=${adv}&click=s`, textContent: story.n, target: '_blank' });
- storyTr.insertCell(0).appendChild(titleLink);
- const deleteButton = document.createElement('input');
- Object.assign(deleteButton, { className: 'major', type: 'button', value: 'Delete' });
- storyTr.insertCell(1).appendChild(deleteButton);
- deleteButton.addEventListener('click', () => {
- setTimeout(() => {
- window.MSPFA.dialog('Delete adventure spoilers?', document.createTextNode('Are you really sure?\nThis action cannot be undone!'), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- delete settings.spoilerValues[adv];
- saveData(settings);
- setTimeout(() => {
- spoilerButton.click();
- }, 1);
- if (Object.keys(settings.spoilerValues).length === 0) {
- spoilerButton.disabled = true;
- }
- }
- });
- }, 1);
- });
- }
- });
- });
- window.MSPFA.dialog('Manage Spoiler Values', spoilerMsg, ["Delete All", "Close"], (output, form) => {
- if (output === "Delete All") {
- setTimeout(() => {
- window.MSPFA.dialog('Delete all Spoiler Values?', 'Are you sure you want to delete all spoiler values?\nThis action cannot be undone!', ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- settings.spoilerValues = {};
- saveData(settings);
- spoilerButton.disabled = true;
- }
- });
- }, 1);
- }
- });
- });
- // Add event listeners
- plusTbody.querySelectorAll('input, select').forEach(elm => {
- elm.addEventListener("change", () => {
- saveBtn.disabled = false;
- });
- });
- saveBtn.addEventListener('mouseup', () => {
- settings.autospoiler = spoilerInput.checked;
- settings.style = cssSelect.selectedIndex;
- settings.styleURL = customCssInput.value;
- settings.auto502 = errorInput.checked;
- settings.textFix = textFixInput.checked;
- settings.pixelFix = pixelFixInput.checked;
- settings.dialogKeys = dialogKeysInput.checked;
- settings.dialogFocus = dialogFocusInput.checked;
- settings.commandScroll = commandScrollInput.checked;
- settings.preload = preloadInput.checked;
- settings.dropFav = dropFavInput.checked;
- settings.night = false;
- console.log(settings);
- saveData(settings);
- updateTheme(settings.style == styleOptions.length - 1 ? settings.styleURL : styleUrls[settings.style]);
- extraStyle.textContent = pixelText() + ' *{transition:1s}';
- extraStyle.textContent = pixelText();
- setTimeout(() => {
- extraStyle.textContent = pixelText();
- }, 1000);
- });
- }
- else if (location.pathname === "/my/messages/") { // New buttons
- // Select all read messages button.
- const selRead = document.createElement('input');
- Object.assign(selRead, { value: 'Select Read', className: 'major', type: 'button' });
- // On click, select all messages with the style attribute indicating it as read.
- selRead.addEventListener('mouseup', () => {
- document.querySelectorAll('td[style="border-left: 8px solid rgb(221, 221, 221);"] > input').forEach((m) => m.click());
- });
- // Select duplicate message (multiple update notifications).
- const selDupe = document.createElement('input');
- Object.assign(selDupe, { value: 'Select Same', className: 'major', type: 'button', style: 'margin-top: 6px' });
- selDupe.addEventListener('mouseup', evt => {
- const temp = document.querySelectorAll('#messages > tr');
- const msgs = [];
- for (let i = temp.length - 1; i >= 0; i--) {
- msgs.push(temp[i]);
- }
- const titles = [];
- msgs.forEach((msg) => {
- const title = msg.querySelector('a.major').textContent;
- // Select only adventure updates
- if (/^New update: /.test(title)) {
- if (titles.indexOf(title) === -1) {
- if (msg.querySelector('td').style.cssText !== "border-left: 8px solid rgb(221, 221, 221);") {
- titles.push(title);
- }
- } else {
- msg.querySelector('input').click();
- }
- }
- });
- });
- // Prune button
- const pruneButton = document.createElement('input');
- Object.assign(pruneButton, { type: 'button', value: 'Prune', className: 'major' });
- pruneButton.addEventListener('click', () => {
- const ageInput = document.createElement('input');
- Object.assign(ageInput, { type: 'number', min: 1, max: 10, value: 1 });
- const msgState = document.createElement('select');
- ['all', 'all unread', 'all read'].forEach(option => {
- const op = document.createElement('option');
- op.textContent = option;
- msgState.appendChild(op);
- });
- const timeUnit = document.createElement('select');
- ['month(s)', 'week(s)', 'day(s)'].forEach(option => {
- const op = document.createElement('option');
- op.textContent = option;
- timeUnit.appendChild(op);
- });
- timeUnit.childNodes[1].setAttribute('selected', 'selected');
- const msg = document.createElement('span');
- msg.appendChild(document.createTextNode('Prune '));
- msg.appendChild(msgState);
- msg.appendChild(document.createTextNode(' messages older than '));
- msg.appendChild(ageInput);
- msg.appendChild(timeUnit);
- window.MSPFA.dialog('Prune messages', msg, ['Prune', 'Cancel'], (output, form) => {
- if (output === 'Prune') {
- document.querySelector('#messages').childNodes.forEach(node => {
- if (node.firstChild.firstChild.checked) {
- node.firstChild.firstChild.click();
- }
- const selectedState = msgState.selectedOptions[0].textContent;
- const selectedUnit = timeUnit.selectedOptions[0].textContent;
- if (selectedState === 'all unread') {
- if (node.firstChild.style.borderLeftColor === 'rgb(221, 221, 221)') {
- return;
- }
- }
- else if (selectedState === 'all read') {
- if (node.firstChild.style.borderLeftColor === 'rgb(92, 174, 223)') {
- return;
- }
- }
- const dateText = node.childNodes[2].childNodes[2].textContent.split(' - ');
- const messageDate = new Date(dateText[dateText.length-1]);
- const currentDate = Date.now();
- const diff = Math.floor(Math.round((currentDate-messageDate)/(1000*60*60))/24); // Difference in days
- if (selectedUnit === 'month(s)') diff = Math.floor(diff / 30);
- else if (selectedUnit === 'week(s)') diff = Math.floor(diff / 7);
- if (diff >= ageInput.value) {
- node.firstChild.firstChild.click();
- }
- });
- setTimeout(() => {
- document.querySelector('input[value=Delete]').click();
- }, 1);
- }
- });
- });
- // Maybe add a "Merge Updates" button?
- // [Merge Updates] would create a list of updates, similar to [Select Same]
- // Add buttons to the page.
- const del = document.querySelector('#deletemsgs');
- del.parentNode.appendChild(newBr());
- del.parentNode.appendChild(selRead);
- del.parentNode.appendChild(document.createTextNode(' '));
- del.parentNode.appendChild(selDupe);
- del.parentNode.appendChild(document.createTextNode(' '));
- del.parentNode.appendChild(pruneButton);
- // Click the green cube to open the update/comment in a new tab, and mark notification as read.
- pageLoad(() => {
- if (document.querySelector('#messages').childNodes.length > 0) {
- if (document.querySelector('#messages').textContent === 'No new messages were found.') {
- // Disable some buttons if there are no messages.
- pruneButton.disabled = true;
- selDupe.disabled = true;
- return true;
- } else {
- document.querySelector('#messages').childNodes.forEach(node => {
- if (node.textContent.includes('New update:') && node.textContent.includes('MS Paint Fan Adventures')) {
- const link = addLink(node.querySelector('.cellicon'), node.querySelector('.spoiler a').href);
- link.addEventListener('mouseup', () => {
- const spoiler = node.querySelector('.spoiler');
- const button = spoiler.querySelector('input');
- spoiler.className = 'spoiler closed';
- button.click();
- button.click();
- });
- }
- else if (node.textContent.includes('New comment on ') && node.textContent.includes('MS Paint Fan Adventures')) {
- const link = addLink(node.querySelector('.cellicon'), node.querySelectorAll('.spoiler a')[1].href + '#commentbox');
- link.addEventListener('mouseup', () => {
- const spoiler = node.querySelector('.spoiler');
- const button = spoiler.querySelector('input');
- spoiler.className = 'spoiler closed';
- button.click();
- button.click();
- });
- }
- });
- return true;
- }
- }
- });
- }
- else if (location.pathname === "/my/messages/new/" && location.search) { // Auto-fill user when linked from a user page
- const recipientInput = document.querySelector('#addrecipient');
- recipientInput.value = params.u;
- pageLoad(() => {
- const recipientButton = document.querySelector('#addrecipientbtn');
- if (recipientButton) {
- recipientButton.click();
- if (recipientInput.value === "") { // If the button press doesn't work
- return true;
- }
- }
- });
- }
- else if (location.pathname === "/my/stories/") {
- // Add links to buttons
- pageLoad(() => {
- const adventures = document.querySelectorAll('#stories tr');
- if (adventures.length > 0) {
- adventures.forEach(story => {
- const buttons = story.querySelectorAll('input.major');
- const id = story.querySelector('a').href.replace('https://mspfa.com/', '').replace('&p=1', '');
- if (id) {
- addLink(buttons[0], `/my/stories/info/${id}`);
- addLink(buttons[1], `/my/stories/pages/${id}`);
- addLink(story.querySelector('img'), `/${id}&p=1`);
- }
- });
- return true;
- }
- if (pageLoaded) return true;
- });
- // Add user guides
- const guides = ["A Guide To Uploading Your Comic To MSPFA", "MSPFA Etiquette", "Fanventure Guide for Dummies", "CSS Guide", "HTML and CSS Things", ];
- const links = ["https://docs.google.com/document/d/17QI6Cv_BMbr8l06RrRzysoRjASJ-ruWioEtVZfzvBzU/edit?usp=sharing", "/?s=27631", "/?s=29299", "/?s=21099", "/?s=23711"];
- const authors = ["Farfrom Tile", "Radical Dude 42", "nzar", "MadCreativity", "seymour schlong"];
- const parentTd = document.querySelector('.container > tbody > tr:last-child > td');
- const unofficial = parentTd.querySelector('span');
- unofficial.textContent = "Unofficial Guides";
- const guideTable = document.createElement('table');
- const guideTbody = document.createElement('tbody');
- guideTable.style.width = "100%";
- guideTable.style.textAlign = "center";
- guideTable.appendChild(guideTbody);
- parentTd.appendChild(guideTable);
- for (let i = 0; i < guides.length; i++) {
- const guideTr = guideTbody.insertRow(i);
- const guideTd = guideTr.insertCell(0);
- const guideLink = document.createElement('a');
- Object.assign(guideLink, { href: links[i], textContent: guides[i], className: 'major' });
- guideTd.appendChild(guideLink);
- guideTd.appendChild(newBr());
- guideTd.appendChild(document.createTextNode('by '+authors[i]));
- guideTd.appendChild(newBr());
- guideTd.appendChild(newBr());
- }
- }
- else if (location.pathname === "/my/stories/info/" && location.search) {
- // Button links
- addLink(document.querySelector('#userfavs'), `/readers/?s=${params.s}`);
- addLink(document.querySelector('#editpages'), `/my/stories/pages/?s=${params.s}`);
- // Download adventure data
- if (params.s !== 'new') {
- const downloadButton = document.createElement('input');
- Object.assign(downloadButton, { className: 'major', value: 'Export Data', type: 'button', style: 'margin-top: 6px' });
- const downloadLink = document.createElement('a');
- window.MSPFA.request(0, {
- do: "story",
- s: params.s
- }, (s) => {
- if (s) {
- downloadLink.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(s, null, 4)));
- }
- });
- downloadLink.setAttribute('download', `${params.s}.json`);
- downloadLink.appendChild(downloadButton);
- document.querySelector('#savestory').parentNode.appendChild(newBr());
- document.querySelector('#savestory').parentNode.appendChild(downloadLink);
- }
- }
- else if (location.pathname === "/my/stories/pages/" && location.search) {
- const adventureID = params.s;
- const notifyLabel = createLabel('Notify readers of new pages during this editing session: ', 'notifyreaders');
- const notifyButton = document.querySelector('#notifyreaders');
- notifyButton.previousSibling.textContent = '';
- notifyButton.parentNode.insertBefore(notifyLabel, notifyButton);/**/
- if (!drafts[adventureID]) {
- drafts[adventureID] = {};
- saveDrafts(drafts);
- }
- pageLoad(() => {
- if (document.querySelector('#storyname').textContent !== '-') {
- drafts[adventureID].cachedTitle = document.querySelector('#storyname').textContent;
- saveDrafts(drafts);
- return true;
- }
- });
- // Button links
- addLink(document.querySelector('#editinfo'), `/my/stories/info/?s=${adventureID}`);
- // Default spoiler values
- const replaceButton = document.querySelector('#replaceall');
- const spoilerButton = document.createElement('input');
- Object.assign(spoilerButton, { className: 'major', value: 'Default Spoiler Values', type: 'button'});
- replaceButton.parentNode.insertBefore(spoilerButton, replaceButton);
- replaceButton.parentNode.insertBefore(newBr(), replaceButton);
- replaceButton.parentNode.insertBefore(newBr(), replaceButton);
- if (!settings.spoilerValues[adventureID]) {
- settings.spoilerValues[adventureID] = {
- open: 'Show',
- close: 'Hide'
- }
- }
- spoilerButton.addEventListener('click', evt => {
- const spoilerSpan = document.createElement('span');
- const spoilerOpen = document.createElement('input');
- const spoilerClose = document.createElement('input');
- spoilerSpan.appendChild(document.createTextNode('Open button text:'));
- spoilerSpan.appendChild(newBr());
- spoilerSpan.appendChild(spoilerOpen);
- spoilerSpan.appendChild(newBr());
- spoilerSpan.appendChild(newBr());
- spoilerSpan.appendChild(document.createTextNode('Close button text:'));
- spoilerSpan.appendChild(newBr());
- spoilerSpan.appendChild(spoilerClose);
- spoilerOpen.value = settings.spoilerValues[adventureID].open;
- spoilerClose.value = settings.spoilerValues[adventureID].close;
- window.MSPFA.dialog('Default Spoiler Values', spoilerSpan, ['Save', 'Cancel'], (output, form) => {
- if (output === 'Save') {
- settings.spoilerValues[adventureID].open = spoilerOpen.value === '' ? 'Show' : spoilerOpen.value;
- settings.spoilerValues[adventureID].close = spoilerClose.value === '' ? 'Hide' : spoilerClose.value;
- if (settings.spoilerValues[adventureID].open === 'Show' && settings.spoilerValues[adventureID].close === 'Hide') {
- delete settings.spoilerValues[adventureID];
- }
- saveData(settings);
- }
- });
- });
- document.querySelector('input[title="Spoiler"]').addEventListener('click', evt => {
- document.querySelector('#dialog input[name="open"]').value = document.querySelector('#dialog input[name="open"]').placeholder = settings.spoilerValues[adventureID].open;
- document.querySelector('#dialog input[name="close"]').value = document.querySelector('#dialog input[name="close"]').placeholder = settings.spoilerValues[adventureID].close;
- });
- // --- Custom BBToolbar buttons
- // Buttonless spoilers
- const flashButton = document.querySelector('input[title=Flash]');
- const newSpoilerButton = document.createElement('input');
- newSpoilerButton.setAttribute('data-tag', 'Buttonless Spoiler');
- Object.assign(newSpoilerButton, { title: 'Buttonless Spoiler', type: 'button', style: 'background-position: -66px -88px;' });
- newSpoilerButton.addEventListener('click', evt => {
- const bbe = document.querySelector('#bbtoolbar').parentNode.querySelector('textarea');
- if (bbe) {
- bbe.focus();
- const start = bbe.selectionStart;
- const end = bbe.selectionEnd;
- bbe.value = bbe.value.slice(0, start) + '<div class="spoiler"><div>' + bbe.value.slice(start, end) + '</div></div>' + bbe.value.slice(end);
- bbe.selectionStart = start + 26;
- bbe.selectionEnd = end + 26;
- }
- });
- flashButton.parentNode.insertBefore(newSpoilerButton, flashButton);
- // Audio button
- const audioButton = document.createElement('input');
- Object.assign(audioButton, { title: 'Audio Player', type: 'button', style: 'background-position: -22px -110px' });
- audioButton.addEventListener('click', evt => {
- const bbe = document.querySelector('#bbtoolbar').parentNode.querySelector('textarea');
- if (bbe) {
- const msg = window.MSPFA.parseBBCode('Audio URL:<br>');
- const audioInput = document.createElement('input');
- Object.assign(audioInput, { type: 'url', name: 'audio-url', required: true });
- const autoplayButton = document.createElement('input');
- autoplayButton.type = 'checkbox';
- autoplayButton.id = 'autoplay';
- autoplayButton.checked = true;
- const loopButton = document.createElement('input');
- loopButton.type = 'checkbox';
- loopButton.id = 'loop';
- loopButton.checked = true;
- const controlsButton = document.createElement('input');
- controlsButton.type = 'checkbox';
- controlsButton.id = 'controls';
- msg.appendChild(audioInput);
- msg.appendChild(newBr());
- msg.appendChild(createLabel('Autoplay: ', 'autoplay'));
- msg.appendChild(autoplayButton);
- msg.appendChild(newBr());
- msg.appendChild(createLabel('Loop: ', 'loop'));
- msg.appendChild(loopButton);
- msg.appendChild(newBr());
- msg.appendChild(createLabel('Show controls: ', 'controls'));
- msg.appendChild(controlsButton);
- msg.appendChild(newBr());
- window.MSPFA.dialog("Audio Player", msg, ["Okay", "Cancel"], (output, form) => {
- if (output == "Okay") {
- bbe.focus();
- const start = bbe.selectionStart;
- const end = bbe.selectionEnd;
- const properties = `"${autoplayButton.checked ? ' autoplay' : ''}${loopButton.checked ? ' loop' : ''}${controlsButton.checked ? ' controls' : ''}`;
- bbe.value = bbe.value.slice(0, start) + '<audio src="' + audioInput.value + properties +'>' + bbe.value.slice(start);
- bbe.selectionStart = start + properties.length + audioInput.value.length + 13;
- bbe.selectionEnd = end + properties.length + audioInput.value.length + 13;
- }
- });
- audioInput.select();
- }
- });
- flashButton.insertAdjacentElement('afterEnd', audioButton);
- // YouTube button
- const youtubeButton = document.createElement('input');
- Object.assign(youtubeButton, { title: 'YouTube Video', type: 'button', style: 'background-position: 0px -110px' });
- youtubeButton.addEventListener('click', evt => {
- const bbe = document.querySelector('#bbtoolbar').parentNode.querySelector('textarea');
- if (bbe) {
- const msg = window.MSPFA.parseBBCode('Video URL:<br>');
- const videoUrl = document.createElement('input');
- videoUrl.type = 'url';
- videoUrl.name = 'youtube';
- videoUrl.required = true;
- const autoplayButton = document.createElement('input');
- autoplayButton.type = 'checkbox';
- autoplayButton.checked = true;
- autoplayButton.id = 'autoplay';
- const controlsButton = document.createElement('input');
- controlsButton.type = 'checkbox';
- controlsButton.checked = true;
- controlsButton.id = 'controls';
- const fullscreenButton = document.createElement('input');
- fullscreenButton.type = 'checkbox';
- fullscreenButton.checked = true;
- fullscreenButton.id = 'fullscreen';
- const widthInput = document.createElement('input');
- Object.assign(widthInput, { type: 'number', required: true, value: 650, style: 'width: 5em' });
- const heightInput = document.createElement('input');
- Object.assign(heightInput, { type: 'number', required: true, value: 450, style: 'width: 5em' });
- msg.appendChild(videoUrl);
- msg.appendChild(newBr());
- msg.appendChild(createLabel('Autoplay: ', 'autoplay'));
- msg.appendChild(autoplayButton);
- msg.appendChild(newBr());
- msg.appendChild(createLabel('Show controls: ', 'controls'));
- msg.appendChild(controlsButton);
- msg.appendChild(newBr());
- msg.appendChild(createLabel('Allow fullscreen: ', 'fullscreen'));
- msg.appendChild(fullscreenButton);
- msg.appendChild(newBr());
- msg.appendChild(document.createTextNode('Embed size: '));
- msg.appendChild(widthInput);
- msg.appendChild(document.createTextNode('x'));
- msg.appendChild(heightInput);
- window.MSPFA.dialog("YouTube Embed", msg, ["Okay", "Cancel"], (output, form) => {
- if (output == "Okay") {
- let videoID = videoUrl.value.split('/');
- videoID = videoID[videoID.length-1].replace('watch?v=', '').split('&')[0];
- bbe.focus();
- const start = bbe.selectionStart;
- const end = bbe.selectionEnd;
- const iframeContent = `<iframe width="${widthInput.value}" height="${heightInput.value}" src="https://www.youtube.com/embed/${videoID}?autoplay=${+autoplayButton.checked}&controls=${+controlsButton.checked}" frameborder="0" allow="accelerometer; ${autoplayButton.checked ? 'autoplay; ' : ''}encrypted-media;"${fullscreenButton.checked ? ' allowfullscreen' : ''}></iframe>`;
- bbe.value = bbe.value.slice(0, start) + iframeContent + bbe.value.slice(start);
- bbe.selectionStart = start + iframeContent + 13;
- bbe.selectionEnd = end + iframeContent + 13;
- }
- });
- videoUrl.select();
- }
- });
- flashButton.insertAdjacentElement('afterEnd', youtubeButton);
- flashButton.insertAdjacentText('afterEnd', ' ');
- // Get preview link
- const getPreviewLink = (form) => {
- const page = parseInt(form.querySelector('a.major').textContent.replace('Page ', ''));
- return "/preview/?s=" + params.s + "&p=" + page + "&d=" + encodeURIComponent(JSON.stringify({
- p: page,
- c: form.querySelector('input[name=cmd]').value,
- b: form.querySelector('textarea[name=body]').value,
- n: form.querySelector('input[name=next]').value,
- k: !form.querySelector('input[name=usekeys]').checked
- }));
- }
- // -- Drafts --
- // Accessing draft text
- const accessDraftsButton = document.createElement('input');
- Object.assign(accessDraftsButton, { className: 'major', value: 'Saved Drafts', type: 'button' });
- replaceButton.parentNode.insertBefore(accessDraftsButton, replaceButton);
- accessDraftsButton.parentNode.insertBefore(newBr(), replaceButton);
- accessDraftsButton.parentNode.insertBefore(newBr(), replaceButton);
- accessDraftsButton.addEventListener('click', () => {
- loadDrafts();
- const draftDialog = window.MSPFA.parseBBCode('Use the textbox below to copy out the data and save to a file somewhere else, or click the download button below.\nYou can also paste in data to replace the current drafts to ones stored there.');
- const draftInputTextarea = document.createElement('textarea');
- draftInputTextarea.placeholder = 'Paste your draft data here';
- draftInputTextarea.style = 'width: 100%; box-sizing: border-box; resize: vertical;';
- const downloadLink = document.createElement('a');
- downloadLink.textContent = 'Download drafts';
- downloadLink.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(drafts[adventureID], null, 4)));
- downloadLink.setAttribute('download', `${adventureID}.json`);
- draftInputTextarea.rows = 8;
- draftDialog.appendChild(newBr());
- draftDialog.appendChild(newBr());
- draftDialog.appendChild(draftInputTextarea);
- draftDialog.appendChild(newBr());
- draftDialog.appendChild(newBr());
- draftDialog.appendChild(downloadLink);
- setTimeout(() => {
- draftInputTextarea.focus();
- draftInputTextarea.selectionStart = 0;
- draftInputTextarea.selectionEnd = 0;
- draftInputTextarea.scrollTop = 0;
- }, 1);
- draftInputTextarea.value = JSON.stringify(drafts[adventureID], null, 4);
- window.MSPFA.dialog('Saved Drafts', draftDialog, ["Load Draft", "Cancel"], (output, form) => {
- if (output === "Load Draft") {
- if (draftInputTextarea.value === '') {
- setTimeout(() => {
- window.MSPFA.dialog('Saved Drafts', window.MSPFA.parseBBCode('Are you sure you want to delete this adventure\'s draft data?\nMake sure you have it saved somewhere!'), ["Delete", "Cancel"], (output, form) => {
- if (output === "Delete") {
- loadDrafts();
- drafts[adventureID] = {};
- if (settings.drafts && settings.drafts[adventureID]) {
- delete settings.drafts[adventureID];
- saveData(settings);
- }
- saveDrafts(drafts);
- }
- });
- }, 1);
- } else if (draftInputTextarea.value !== JSON.stringify(drafts[adventureID], null, 4)) {
- setTimeout(() => {
- window.MSPFA.dialog('Saved Drafts', window.MSPFA.parseBBCode('Are you sure you want to load this draft data?\nAll previous draft data for this adventure will be lost!'), ["Load", "Cancel"], (output, form) => {
- if (output === "Load") {
- let newData = {};
- try { // Just in case the data given is invalid.
- newData = JSON.parse(draftInputTextarea.value);
- } catch (err) {
- console.error(err);
- setTimeout(() => {
- window.MSPFA.dialog('Error', window.MSPFA.parseBBCode('The entered data is invalid.'), ["Okay"]);
- }, 1);
- return;
- }
- loadDrafts();
- drafts[adventureID] = newData;
- saveDrafts(drafts);
- }
- });
- }, 1);
- }
- }
- });
- });
- // Draft stuff
- const showDraftDialog = (pageNum) => {
- loadDrafts();
- const msg = document.createElement('span');
- msg.appendChild(document.createTextNode('Command:'));
- msg.appendChild(document.createElement('br'));
- const commandInput = document.createElement('input');
- Object.assign(commandInput, { style: 'width: 100%; box-sizing: border-box;', readOnly: true, });
- msg.appendChild(commandInput);
- msg.appendChild(document.createElement('br'));
- msg.appendChild(document.createElement('br'));
- msg.appendChild(document.createTextNode('Body:'));
- const bodyInput = document.createElement('textarea');
- Object.assign(bodyInput, { style: 'width: 100%; box-sizing: border-box; resize: vertical;', readOnly: true, rows: 8 });
- msg.appendChild(bodyInput);
- const pageElement = document.querySelector(`#p${pageNum}`);
- let shownMessage = msg;
- let optionButtons = [];
- const commandElement = pageElement.querySelector('input[name="cmd"]');
- const pageContentElement = pageElement.querySelector('textarea[name="body"]');
- if (typeof drafts[adventureID][pageNum] === "undefined") {
- shownMessage = document.createTextNode('There is no draft saved for this page.');
- optionButtons = ["Save New", "Close"];
- } else {
- commandInput.value = drafts[adventureID][pageNum].command;
- bodyInput.textContent = drafts[adventureID][pageNum].pageContent;
- optionButtons = ["Save New", "Load", "Delete", "Close"];
- }
- window.MSPFA.dialog(`Page ${pageNum} Draft`, shownMessage, optionButtons, (output, form) => {
- if (output === "Save New") {
- if (typeof drafts[adventureID][pageNum] === "undefined") {
- loadDrafts();
- drafts[adventureID][pageNum] = {
- command: commandElement.value,
- pageContent: pageContentElement.value
- }
- saveDrafts(drafts);
- } else {
- setTimeout(() => {
- window.MSPFA.dialog('Overwrite current draft?', document.createTextNode('Doing this will overwrite your current draft with what is currently written in the page box. Are you sure?'), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- loadDrafts();
- drafts[adventureID][pageNum] = {
- command: commandElement.value,
- pageContent: pageContentElement.value
- }
- saveDrafts(drafts);
- }
- });
- }, 1);
- }
- } else if (output === "Load") {
- if (pageContentElement.value === '' && (commandElement.value === '' || commandElement.value === document.querySelector('#defaultcmd').value)) {
- commandElement.value = drafts[adventureID][pageNum].command;
- pageContentElement.value = drafts[adventureID][pageNum].pageContent;
- pageElement.querySelector('input[value="Save"]').disabled = false;
- } else {
- setTimeout(() => {
- window.MSPFA.dialog('Overwrite current page?', document.createTextNode('Doing this will overwrite the page\'s content with what is currently written in the draft. Are you sure?'), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- commandElement.value = drafts[adventureID][pageNum].command;
- pageContentElement.value = drafts[adventureID][pageNum].pageContent;
- pageElement.querySelector('input[value="Save"]').disabled = false;
- }
- });
- }, 1);
- }
- } else if (output === "Delete") {
- setTimeout(() => {
- window.MSPFA.dialog('Delete this draft?', document.createTextNode('This action is irreversable! Are you sure?'), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- loadDrafts();
- delete drafts[adventureID][pageNum];
- if (settings.drafts && settings.drafts[adventureID] && settings.drafts[adventureID][pageNum]) {
- delete settings.drafts[adventureID][pageNum];
- saveData(settings);
- }
- saveDrafts(drafts);
- }
- });
- }, 1);
- }
- });
- }
- const createDraftButton = (form) => {
- const draftButton = document.createElement('input');
- Object.assign(draftButton, { className: 'major draft', type: 'button', value: 'Draft' });
- draftButton.addEventListener('click', () => {
- showDraftDialog(form.id.replace('p', ''));
- });
- return draftButton;
- }
- pageLoad(() => {
- let allPages = document.querySelectorAll('#storypages form:not(#newpage)');
- if (allPages.length !== 0) {
- allPages.forEach(form => {
- const prevButton = form.querySelector('input[name="preview"]');
- prevButton.parentNode.insertBefore(createDraftButton(form), prevButton);
- prevButton.parentNode.insertBefore(document.createTextNode(' '), prevButton);
- // Preview
- const previewButton = form.querySelector('input[value=Preview]');
- const previewLink = addLink(previewButton, getPreviewLink(form), '_blank');
- previewButton.addEventListener('mousedown', () => {
- previewLink.href = getPreviewLink(form);
- });
- // "Enable keyboard shortcuts" label
- const shortcutCheck = form.querySelector('input[type="checkbox"]');
- shortcutCheck.previousSibling.textContent = '';
- shortcutCheck.id = `key-${form.id}`;
- shortcutCheck.parentNode.insertBefore(createLabel('Enable keyboard shortcuts: ', shortcutCheck.id), shortcutCheck);
- });
- document.querySelector('input[value="Add"]').addEventListener('click', () => {
- allPages = document.querySelectorAll('#storypages form:not(#newpage)');
- const form = document.querySelector(`#p${allPages.length}`);
- const prevButton = form.querySelector('input[name="preview"]');
- prevButton.parentNode.insertBefore(createDraftButton(form), prevButton);
- prevButton.parentNode.insertBefore(document.createTextNode(' '), prevButton);
- // Preview link
- const previewButton = form.querySelector('input[value=Preview]');
- const previewLink = addLink(previewButton, getPreviewLink(form), '_blank');
- previewButton.addEventListener('mousedown', () => {
- previewLink.href = getPreviewLink(form);
- });
- // "Enable keyboard shortcuts" label
- const shortcutCheck = form.querySelector('input[type="checkbox"]');
- shortcutCheck.previousSibling.textContent = '';
- shortcutCheck.id = `key-${form.id}`;
- shortcutCheck.parentNode.insertBefore(createLabel('Enable keyboard shortcuts: ', shortcutCheck.id), shortcutCheck);
- });
- const newForm = document.querySelector('#newpage');
- {
- // "Enable keyboard shortcuts" label
- const shortcutCheck = newForm.querySelector('input[type="checkbox"]');
- shortcutCheck.previousSibling.textContent = '';
- shortcutCheck.id = `key-${newForm.id}`;
- shortcutCheck.parentNode.insertBefore(createLabel('Enable keyboard shortcuts: ', shortcutCheck.id), shortcutCheck);
- }
- const newPreviewButton = newForm.querySelector('input[value=Preview]');
- const newPreviewLink = addLink(newPreviewButton, getPreviewLink(newForm), '_blank');
- newPreviewButton.addEventListener('mousedown', () => {
- newPreviewLink.href = getPreviewLink(newForm);
- });
- return true;
- }
- });
- if (params.click) {
- if (params.click === 's') {
- spoilerButton.click();
- } else if (params.click === 'd') {
- accessDraftsButton.click();
- }
- }
- // Don't scroll after pressing a BBToolbar button (awesome)
- let lastScroll = window.scrollY;
- pageLoad(() => {
- if (document.querySelectorAll('#storypages textarea').length > 1) {
- document.querySelectorAll('#storypages textarea').forEach(textarea => {
- textarea.addEventListener('focus', () => {
- window.scrollTo(window.scrollX, lastScroll);
- });
- });
- document.addEventListener('scroll', evt => {
- lastScroll = window.scrollY;
- });
- return true;
- }
- });
- // Focus on the text input when clicking on the Color or Background Color BBToolbar buttons
- const colourButtons = [document.querySelector('#bbtoolbar input[data-tag=color]'), document.querySelector('#bbtoolbar input[data-tag=background]')];
- colourButtons.forEach(button => {
- button.addEventListener('click', () => {
- document.querySelector('#dialog input[type=text]').select();
- });
- });
- }
- else if (location.pathname === "/my/profile/") {
- // Nothing
- }
- else if (location.pathname === "/user/") {
- // Button links
- pageLoad(() => {
- const msgButton = document.querySelector('#sendmsg');
- if (msgButton) {
- addLink(msgButton, `/my/messages/new/?u=${params.u}`);
- addLink(document.querySelector('#favstories'), `/favs/?u=${params.u}`);
- return true;
- }
- });
- // Add extra user stats
- pageLoad(() => {
- if (window.MSPFA) {
- const stats = document.querySelector('#userinfo table');
- const joinTr = stats.insertRow(1);
- const joinTextTd = joinTr.insertCell(0);
- joinTextTd.appendChild(document.createTextNode("Account created:"));
- const joinDate = joinTr.insertCell(1);
- const joinTime = document.createElement('b');
- joinTime.textContent = "Loading...";
- joinDate.appendChild(joinTime);
- const advCountTr = stats.insertRow(2);
- const advTextTd = advCountTr.insertCell(0);
- advTextTd.appendChild(document.createTextNode("Adventures created:"));
- const advCount = advCountTr.insertCell(1);
- const advCountText = document.createElement('b');
- advCountText.textContent = "Loading...";
- advCount.appendChild(advCountText);
- // Show user creation date
- window.MSPFA.request(0, {
- do: "user",
- u: params.u
- }, user => {
- if (typeof user !== "undefined") {
- joinTime.textContent = new Date(user.d).toString().split(' ').splice(1, 4).join(' ');
- }
- // Show created adventures
- window.MSPFA.request(0, {
- do: "editor",
- u: params.u
- }, s => {
- if (typeof s !== "undefined") {
- advCountText.textContent = s.length;
- }
- // Show favourites
- if (document.querySelector('#favstories').style.display !== 'none') {
- const favCountTr = stats.insertRow(3);
- const favTextTd = favCountTr.insertCell(0);
- favTextTd.appendChild(document.createTextNode("Adventures favorited:"));
- const favCount = favCountTr.insertCell(1);
- const favCountText = document.createElement('b');
- favCountText.textContent = "Loading...";
- window.MSPFA.request(0, {
- do: "favs",
- u: params.u
- }, s => {
- if (typeof s !== "undefined") {
- favCountText.textContent = s.length;
- }
- });
- favCount.appendChild(favCountText);
- }
- });
- });
- return true;
- }
- });
- }
- else if (location.pathname === "/favs/" && location.search) {
- const toggleButton = document.createElement('input');
- Object.assign(toggleButton, { className: "major", type: "button", value: "Toggle Muted Adventures" });
- const buttonRow = document.querySelector('table.container.alt').insertRow(2);
- const actionSpan = document.createElement('span');
- let stories = [];
- // Button links
- pageLoad(() => {
- stories = document.querySelectorAll('#stories tr');
- let favCount = 0;
- if (stories.length > 0) {
- stories.forEach(story => {
- favCount++;
- const id = story.querySelector('a').href.replace('https://mspfa.com/', '');
- pageLoad(() => {
- if (window.MSPFA.me.i) {
- addLink(story.querySelector('.edit.major'), `/my/stories/info/${id}`);
- return true;
- }
- if (pageLoaded) return true;
- });
- addLink(story.querySelector('.rss.major'), `/rss/${id}`);
- });
- // Fav count
- const username = document.querySelector('#username');
- username.parentNode.appendChild(newBr());
- username.parentNode.appendChild(newBr());
- username.parentNode.appendChild(document.createTextNode(`Favorited adventures: ${favCount}`));
- return true;
- }
- if (pageLoaded) return true;
- });
- pageLoad(() => {
- if (window.MSPFA && window.MSPFA.me) {
- if (window.MSPFA.me.i === params.u) {
- const cell = buttonRow.insertCell(0);
- cell.appendChild(toggleButton);
- cell.appendChild(newBr());
- cell.appendChild(actionSpan);
- return true;
- }
- }
- if (pageLoaded) return true;
- });
- let type = 0;
- toggleButton.addEventListener('click', () => {
- type++;
- if (type > 2) type = 0;
- stories.forEach(story => {
- const unmuted = story.querySelector('.notify').className.includes(' lit');
- story.style.display = '';
- if (type === 2 && unmuted || type === 1 && !unmuted) {
- story.style.display = 'none';
- }
- });
- if (type === 0) {
- // show all
- actionSpan.textContent = '';
- }
- else if (type === 1) {
- // hide muted
- actionSpan.textContent = 'Showing only unmuted favourites';
- }
- else {
- // only muted
- actionSpan.textContent = 'Showing only muted favourites';
- }
- });
- }
- else if (location.pathname === "/search/" && location.search) {
- // Character and word statistics
- const statTable = document.createElement('table');
- const statTbody = document.createElement('tbody');
- const statTr = statTbody.insertRow(0);
- const charCount = statTr.insertCell(0);
- const wordCount = statTr.insertCell(0);
- const statParentTr = document.querySelector('#pages').parentNode.parentNode.insertRow(2);
- const statParentTd = statParentTr.insertCell(0);
- const statHeaderTr = statTbody.insertRow(0);
- const statHeader = document.createElement('th');
- statHeader.colSpan = '2';
- statHeaderTr.appendChild(statHeader);
- statHeader.textContent = 'Statistics may not be entirely accurate.';
- statTable.style.width = "100%";
- charCount.textContent = "Character count: loading...";
- wordCount.textContent = "Word count: loading...";
- statTable.appendChild(statTbody);
- statParentTd.appendChild(statTable);
- pageLoad(() => {
- if (document.querySelector('#pages br')) {
- const bbc = window.MSPFA.BBC.slice();
- bbc.splice(0, 3);
- window.MSPFA.request(0, {
- do: "story",
- s: params.s
- }, story => {
- if (typeof story !== "undefined") {
- const pageContent = [];
- story.p.forEach(p => {
- pageContent.push(p.c);
- pageContent.push(p.b);
- });
- const storyText = pageContent.join(' ')
- .replace(/\n/g, ' ')
- .replace(bbc[0][0], '$1')
- .replace(bbc[1][0], '$1')
- .replace(bbc[2][0], '$1')
- .replace(bbc[3][0], '$1')
- .replace(bbc[4][0], '$2')
- .replace(bbc[5][0], '$3')
- .replace(bbc[6][0], '$3')
- .replace(bbc[7][0], '$3')
- .replace(bbc[8][0], '$3')
- .replace(bbc[9][0], '$3')
- .replace(bbc[10][0], '$2')
- .replace(bbc[11][0], '$1')
- .replace(bbc[12][0], '$3')
- .replace(bbc[13][0], '$3')
- .replace(bbc[14][0], '')
- .replace(bbc[16][0], '$1')
- .replace(bbc[17][0], '$2 $4 $5')
- .replace(bbc[18][0], '$2 $4 $5')
- .replace(bbc[19][0], '')
- .replace(bbc[20][0], '')
- .replace(/<(.*?)>/g, '');
- wordCount.textContent = `Word count: ${storyText.split(/ +/g).length}`;
- charCount.textContent = `Character count: ${storyText.replace(/ +/g, '').length}`;
- }
- });
- return true;
- }
- });
- }
- else if (location.pathname === "/stories/" && location.search) {
- // Click text to check/uncheck boxes
- ['Ongoing', 'Complete', 'Inactive'].forEach(t => {
- const check = document.querySelector(`input[name="${t.toLowerCase()}"]`);
- check.id = `check_${t.toLowerCase()}`;
- const label = createLabel(' ' + t + ' ', check.id);
- check.nextSibling.textContent = '';
- check.parentNode.insertBefore(label, check.nextSibling);
- });
- const adventureList = document.querySelector('#doit');
- const resultAmount = document.createElement('span');
- adventureList.parentNode.appendChild(resultAmount);
- pageLoad(() => {
- if (window.MSPFA) {
- window.MSPFA.request(0, {
- do: "stories",
- n: params.n,
- t: params.t,
- h: params.h,
- o: params.o,
- p: params.p,
- m: 20000
- }, (s) => {
- resultAmount.textContent = `Number of results: ${s.length}`;
- return true;
- });
- return true;
- }
- },1);
- pageLoad(() => {
- const stories = document.querySelector('#stories');
- if (stories.childNodes.length > 0) {
- if (params.load && stories.childNodes.length === 1) {
- stories.querySelector('a').click();
- }
- stories.querySelectorAll('tr').forEach(story => {
- const storyID = story.querySelector('a.major').href.split('&')[0].replace(/\D/g, '');
- addLink(story.querySelector('.rss'), `/rss/?s=${storyID}`);
- pageLoad(() => {
- if (window.MSPFA.me.i) {
- addLink(story.querySelector('.edit.major'), `/my/stories/info/?s=${storyID}`);
- return true;
- }
- if (pageLoaded) return true;
- });
- });
- return true;
- }
- if (pageLoaded) return true;
- });
- }
- })();