您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds custom quality of life features to MSPFA.
当前为
- // ==UserScript==
- // @name MSPFA extras
- // @namespace http://tampermonkey.net/
- // @version 1.6.1
- // @description Adds custom quality of life features to MSPFA.
- // @author seymour schlong
- // @icon https://raw.githubusercontent.com/GrantGryczan/MSPFA/master/www/images/ico.svg
- // @icon64 https://raw.githubusercontent.com/GrantGryczan/MSPFA/master/www/images/ico.svg
- // @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/
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- const currentVersion = "1.6.1";
- console.log(`MSPFA extras script v${currentVersion} by seymour schlong`);
- /**
- * https://github.com/GrantGryczan/MSPFA/projects/1?fullscreen=true
- * Github to-do completion list
- *
- * 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
- *
- * 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.
- */
- // 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);
- };
- // Encases an element within a link
- const addLink = (elm, url) => {
- const link = document.createElement('a');
- link.href = url;
- elm.parentNode.insertBefore(link, elm);
- link.appendChild(elm);
- };
- // Returns true if version 2 is newer
- const compareVer = (ver1, ver2) => {
- ver1 = ver1.split(/\./); // current version
- ver2 = ver2.split(/\./); // new version
- ver1.push(0);
- ver1.push(0);
- ver2.push(0);
- ver2.push(0);
- if (parseInt(ver2[0]) > parseInt(ver1[0])) { // 1.x.x
- return true;
- } else if (parseInt(ver2[1]) > parseInt(ver1[1])) { // x.1.x
- return true;
- } else if (parseInt(ver2[2]) > parseInt(ver1[2])) { // x.x.1
- return true;
- } else if (parseInt(ver2[3]) > parseInt(ver1[3])) { // x.x.1
- return true;
- }
- return false;
- }
- // Easy br element
- const newBr = () => {
- return document.createElement('br');
- }
- let settings = {};
- const defaultSettings = {
- autospoiler: false,
- style: 0,
- styleURL: "",
- night: false,
- auto502: true,
- textFix: false,
- pixelFix: false,
- intro: false,
- autoUpdate: false,
- version: currentVersion,
- spoilerValues: {},
- drafts: {}
- }
- // Load any previous settings from localStorage
- if (localStorage.mspfaextra) {
- Object.assign(settings, JSON.parse(localStorage.mspfaextra));
- }
- // 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();
- // Update saved version to the version used in the script to prevent unnecessary notifications
- if (compareVer(settings.version, currentVersion)) {
- settings.version = currentVersion;
- saveData(settings);
- }
- // 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));
- }
- },
- 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);
- }
- }
- // Delete any unchanged spoiler values or empty drafts
- 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];
- }
- });
- // Go through and remove adventures with empty drafts
- Object.keys(settings.drafts).forEach(adventure => {
- if (Object.keys(settings.drafts[adventure]).length === 0) {
- delete settings.drafts[adventure];
- }
- });
- }
- const styleOptions = ["Standard", "Low Contrast", "Light", "Dark", "Felt", "Trickster", "Custom"];
- const styleUrls = ['', '/css/theme1.css', '/css/theme2.css', '/css/?s=36237', '/css/theme4.css', '/css/theme5.css'];
- // Dropdown menu
- const myLink = document.querySelector('nav a[href="/my/"]');
- if (myLink) {
- const dropDiv = document.createElement('div');
- dropDiv.className = 'dropdown';
- Object.assign(dropDiv.style, {
- position: 'relative',
- display: 'inline-block',
- backgroundColor: 'inherit'
- });
- const dropContent = document.createElement('div');
- dropContent.className = 'dropdown-content';
- Object.assign(dropContent.style, {
- display: 'none',
- backgroundColor: 'inherit',
- position: 'absolute',
- textAlign: 'left',
- minWidth: '100px',
- marginLeft: '-5px',
- padding: '2px',
- zIndex: '1',
- borderRadius: '0 0 5px 5px'
- });
- dropDiv.addEventListener('mouseenter', evt => {
- dropContent.style.display = 'block';
- dropContent.style.color = getComputedStyle(myLink).color;
- });
- dropDiv.addEventListener('mouseleave', evt => {
- dropContent.style.display = 'none';
- });
- myLink.parentNode.insertBefore(dropDiv, myLink);
- dropDiv.appendChild(myLink);
- dropDiv.appendChild(dropContent);
- 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, or "Login" if you're not
- pageLoad(() => {
- if (window.MSPFA) {
- if (window.MSPFA.me.n) {
- const newLink = document.createElement('a');
- newLink.textContent = "My Profile";
- newLink.href = `/user/?u=${window.MSPFA.me.i}`;
- dropContent.appendChild(newLink);
- return true;
- }
- }
- });
- }
- const hashSearch = location.href.replace(location.origin + location.pathname, '').replace(location.search, '');
- if (hashSearch !== '') {
- pageLoad(() => {
- const idElement = document.querySelector(hashSearch);
- if (idElement) {
- document.querySelector(hashSearch).scrollIntoView();
- return true;
- }
- }, 1);
- }
- // Error reloading
- window.addEventListener("load", () => {
- // Reload the page if 502 CloudFlare error page appears
- if (settings.auto502 && document.querySelector('.cf-error-overview')) {
- 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);
- }
- // Replace "My MSPFA" with "Log in" if the user isn't logged in
- if (!window.MSPFA.me.i) {
- const dropContent = document.querySelector('.dropdown-content');
- console.log(window.MSPFA.me);
- dropContent.innerHTML = '';
- dropContent.style.padding = '0px';
- myLink.textContent = 'Log in';
- myLink.href = '/login/';
- return true;
- }
- });
- // 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 for updates by comparing currentVersion to text data from an adventure that has update text and info
- const checkForUpdates = (evt) => {
- window.MSPFA.request(0, {
- do: "story",
- s: "36596"
- }, story => {
- if (typeof story !== "undefined") {
- const ver = settings.version.split(/\./);
- const newVer = story.p[1].c.split(/\./);
- // compare versions
- if (compareVer(settings.version, story.p[1].c) || (evt && evt.type === 'click')) {
- const msg = window.MSPFA.parseBBCode(story.p[1].b);
- settings.version = story.p[1].c;
- saveData(settings);
- window.MSPFA.dialog(`MSPFA extras update! (${story.p[1].c})`, msg, ["Opt-out", "Dismiss", "Update"], (output, form) => {
- if (output === "Update") {
- window.open('https://greasyfork.org/en/scripts/396798-mspfa-extras', '_blank').focus();
- } else if (output === "Opt-out") {
- settings.autoUpdate = false;
- saveData(settings);
- }
- });
- }
- }
- });
- };
- // Check for updates and show intro dialog if needed
- pageLoad(() => {
- if (window.MSPFA) {
- if (settings.autoUpdate) {
- checkForUpdates();
- }
- if (!settings.intro) {
- showIntroDialog();
- settings.intro = true;
- saveData(settings);
- }
- return true;
- }
- });
- const linkColour = document.createElement('a');
- linkColour.href = "/";
- linkColour.id = "linkColour";
- document.body.appendChild(linkColour);
- 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.style = 'cursor: pointer; text-decoration: underline;';
- introLink.style.color = getComputedStyle(linkColour).color;
- introLink.className = 'intro-link';
- introLink.addEventListener('click', showIntroDialog);
- details.appendChild(introLink);
- // vbar!!!!
- const vbar = document.createElement('span');
- Object.assign(vbar, {className: 'vbar', style: 'padding: 0 5px', textContent: '|'});
- details.appendChild(vbar);
- // Add 'link' at the bottom to show the update dialog again
- const updateLink = document.createElement('a');
- updateLink.textContent = 'View Update';
- updateLink.style = 'cursor: pointer; text-decoration: underline;';
- updateLink.style.color = getComputedStyle(linkColour).color;
- updateLink.className = 'intro-link';
- updateLink.addEventListener('click', checkForUpdates);
- details.appendChild(updateLink);
- // vbar 2!!!!
- const vbar2 = document.createElement('span');
- Object.assign(vbar2, {className: 'vbar', style: 'padding: 0 5px', textContent: '|'});
- details.appendChild(vbar2);
- // 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;
- setTimeout(() => {
- introLink.style.color = getComputedStyle(linkColour).color;
- updateLink.style.color = getComputedStyle(linkColour).color;
- }, 1500);
- }
- if (!document.querySelector('#theme') && !/^\/css\/|^\/js\//.test(location.pathname)) {
- document.querySelector('head').appendChild(theme);
- if (settings.night) {
- updateTheme('/css/?s=36237');
- } else {
- updateTheme(settings.style == styleOptions.length - 1 ? settings.styleURL : styleUrls[settings.style]);
- }
- }
- // Dropdown menu and pixelated scaling
- const dropStyle = document.createElement('style');
- const pixelFixText = 'img, .mspfalogo, .major, .arrow, #flashytitle, .heart, .fav, .notify, .edit, .rss, input, #loading { image-rendering: pixelated !important; }';
- const dropStyleText = `#notification { z-index: 2; } .dropdown-content a { color: inherit; padding: 2px; text-decoration: underline; display: block;}`;
- if (!document.querySelector('#dropdown-style')) {
- dropStyle.id = 'dropdown-style';
- dropStyle.textContent = dropStyleText + (settings.pixelFix ? ' '+pixelFixText : '');
- //dropdownStyle.textContent = '#notification { z-index: 2;}.dropdown:hover .dropdown-content { display: block;}.dropdown { position: relative; display: inline-block; background-color: inherit;}.dropdown-content { display: none; position: absolute; text-align: left; background-color: inherit; min-width: 100px; margin-left: -5px; padding: 2px; z-index: 1; border-radius: 0 0 5px 5px;}.dropdown-content a { color: #fffa36; padding: 2px 2px; text-decoration: underline; display: block;}';
- document.querySelector('head').appendChild(dropStyle);
- }
- // Remove the current theme if the adventure has CSS (to prevent conflicts);
- pageLoad(() => {
- if (window.MSPFA) {
- if (window.MSPFA.story && window.MSPFA.story.y && window.MSPFA.story.y.replace(/^((?!import).)*/igm, '').length > 0) {
- updateTheme('');
- }
- return true;
- }
- });
- // Enabling night mode.
- document.querySelector('footer .mspfalogo').addEventListener('click', evt => {
- settings.night = !settings.night;
- saveData(settings);
- // Transition to make it feel nicer on the eyes
- dropStyle.textContent = dropStyleText + (settings.pixelFix ? ' '+pixelFixText : '') + '';
- dropStyle.textContent = dropStyleText + (settings.pixelFix ? ' '+pixelFixText : '') + ' *{transition:1s}';
- if (settings.night) {
- updateTheme('/css/?s=36237');
- } else {
- updateTheme(settings.style == styleOptions.length - 1 ? settings.styleURL : styleUrls[settings.style]);
- }
- setTimeout(() => {
- dropStyle.textContent = dropStyleText + (settings.pixelFix ? ' '+pixelFixText : '');
- }, 1000);
- console.log(`Night mode turned ${settings.night ? 'on' : 'off'}.`);
- });
- if (location.pathname === "/" || location.pathname === "/preview/") {
- if (location.search) {
- // 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());
- });
- }
- // 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', '#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') {
- 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) {
- 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);
- });
- window.MSPFA.page(currentPage);
- return true;
- }
- });
- }
- // Turn buttons into links
- const pageButton = document.createElement('button');
- const pageLink = document.createElement('a');
- const searchContent = location.search.split('&p=');
- pageLink.href = `/my/stories/pages/${searchContent[0]}#p${searchContent[1].split('#')[0]}`;
- pageButton.className = 'pages edit major';
- pageButton.type = 'button';
- pageButton.title = 'Edit Pages';
- pageLink.style.marginRight = '9.5px';
- pageButton.style.backgroundImage = 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAL1JREFUOI1jYKAQMCJzugoL/+NSePPhQ4a569YxoouzoAuU9vUx3AoLY1BbtYqBgYGB4d21a8jS/9ENwTBg/ezZDNpQGh2oy8szJAcFoRiCYUBgairDrd27Gdz9/Bh+vH2LInfn+nUMQ3G6YOemTRiKsQEMA9z9/Bie7N7NYG9tjaGYKBfs3LSJQZuBgeHg0aPkucDe2prhDSUuOHj06Ih3wdw5cxgYZGQYGObMId0FNx8+JKhBQlGRKIOJBgBpTFVYzRG//QAAAABJRU5ErkJggg==")';
- pageLink.appendChild(pageButton);
- pageLoad(() => {
- const infoButton = document.querySelector('.edit.major');
- if (infoButton) {
- pageLoad(() => {
- if (window.MSPFA.me.i) {
- infoButton.title = "Edit Info";
- infoButton.parentNode.insertBefore(pageLink, infoButton);
- addLink(infoButton, `/my/stories/info/${searchContent[0]}`);
- pageButton.style.display = document.querySelector('.edit.major:not(.pages)').style.display;
- return true;
- }
- });
- addLink(document.querySelector('.rss.major'), `/rss/${searchContent[0]}`);
- return true;
- }
- });
- window.addEventListener('load', evt => {
- const favButton = document.querySelector('.fav');
- window.MSPFA.slide.push(p => {
- const newSearch = location.search.split('&p=');
- pageLink.href = `/my/stories/pages/${newSearch[0]}#p${newSearch[1].split('#')[0]}`;
- });
- });
- // Add "Reply" button to comment gear
- document.body.addEventListener('click', evt => {
- if (evt.toElement.classList.contains('gear')) {
- const userID = evt.path[2].classList[2].replace('u', '');
- const reportButton = document.querySelector('#dialog button[data-value="Report"]');
- const replyButton = document.createElement('button');
- replyButton.classList.add('major');
- replyButton.type = 'submit';
- replyButton.setAttribute('data-value', 'Reply');
- replyButton.textContent = 'Reply';
- replyButton.style = 'margin-right: 9.5px';
- reportButton.parentNode.insertBefore(replyButton, reportButton);
- replyButton.addEventListener('click', evt => {
- document.querySelector('#dialog button[data-value="Cancel"]').click();
- const commentBox = document.querySelector('#commentbox textarea');
- commentBox.value = `[user]${userID}[/user], ${commentBox.value}`;
- commentBox.focus();
- // Weird bug where if you have JS console open it opens debugger?
- });
- } else return;
- });/**/
- }
- }
- 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) => {
- const optionTr = plusTbody.insertRow(plusTbody.childNodes.length);
- const optionTextTd = optionTr.insertCell(0);
- const optionInputTd = optionTr.insertCell(1);
- const optionInput = document.createElement('input');
- optionInputTd.appendChild(optionInput);
- optionTextTd.textContent = text;
- optionInput.type = "checkbox";
- optionInput.checked = checked;
- return optionInput;
- }
- const spoilerInput = createCheckbox("Automatically open spoilers:", settings.autospoiler);
- const errorInput = createCheckbox("Automatically reload Cloudflare 502 error pages:", settings.auto502);
- const updateInput = createCheckbox("Automatically check for updates:", settings.autoUpdate);
- const pixelFixInput = createCheckbox("Change pixel scaling to nearest neighbour:", settings.pixelFix);
- const textFixInput = createCheckbox("Attempt to fix text errors (experimental)*:", settings.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.style = 'margin: 0 9.5px;';
- draftButton.value = 'Clear Drafts';
- draftButton.className = 'major';
- draftButton.type = 'button';
- spoilerButton.value = 'Clear Spoiler Values';
- spoilerButton.className = 'major';
- spoilerButton.type = 'button';
- buttonSpan.appendChild(draftButton);
- buttonSpan.appendChild(spoilerButton);
- settingsTd.appendChild(buttonSpan);
- draftButton.addEventListener('click', () => {
- window.MSPFA.dialog('Delete all Drafts?', window.MSPFA.parseBBCode(`Doing this will delete all drafts saved for [b]${Object.keys(settings.drafts).length}[/b] adventure(s).\nAre you sure? This action is irreversible.`), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- setTimeout(() => {
- window.MSPFA.dialog('Delete all Drafts?', document.createTextNode('Are you really sure?'), ["No", "Yes"], (output, form) => {
- if (output === "Yes") {
- settings.drafts = {};
- saveData(settings);
- }
- });
- }, 1);
- }
- });
- });
- spoilerButton.addEventListener('click', () => {
- window.MSPFA.dialog('Delete all Spoiler Values?', window.MSPFA.parseBBCode(`Doing this will delete all spoiler values saved for [b]${Object.keys(settings.spoilerValues).length}[/b] adventure(s).\nAre you sure? This action is irreversible.`), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- settings.spoilerValues = {};
- saveData(settings);
- }
- });
- });
- // 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.autoUpdate = updateInput.checked;
- settings.night = false;
- console.log(settings);
- saveData(settings);
- updateTheme(settings.style == styleOptions.length - 1 ? settings.styleURL : styleUrls[settings.style]);
- dropStyle.textContent = dropStyleText + (settings.pixelFix ? ' '+pixelFixText : '');
- dropStyle.textContent = dropStyleText + (settings.pixelFix ? ' '+pixelFixText : '') + ' *{transition:1s}';
- setTimeout(() => {
- dropStyle.textContent = dropStyleText + (settings.pixelFix ? ' '+pixelFixText : '');
- }, 1000);
- });
- }
- else if (location.pathname === "/my/messages/") { // New buttons
- const btnStyle = "margin: 10px 5px;";
- // Select all read messages button.
- const selRead = document.createElement('input');
- selRead.style = btnStyle;
- selRead.value = "Select Read";
- selRead.id = "selectread";
- selRead.classList.add("major");
- selRead.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');
- selDupe.style = btnStyle;
- selDupe.value = "Select Same";
- selDupe.id = "selectdupe";
- selDupe.classList.add("major");
- selDupe.type = "button";
- 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) => {
- let title = msg.querySelector('a.major').textContent;
- if (/^New update: /.test(title)) { // Select only adventure updates
- 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();
- }
- }
- });
- });
- // Add buttons to the page.
- const del = document.querySelector('#deletemsgs');
- del.parentNode.appendChild(newBr());
- del.parentNode.appendChild(selRead);
- del.parentNode.appendChild(selDupe);
- }
- 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 = location.search.replace('?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}`);
- }
- });
- 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');
- guideLink.href = links[i];
- guideLink.textContent = guides[i];
- guideLink.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/${location.search}`);
- addLink(document.querySelector('#editpages'), `/my/stories/pages/${location.search}`);
- }
- else if (location.pathname === "/my/stories/pages/" && location.search) {
- const adventureID = /\?s=(\d{5})/.exec(location.search)[1];
- if (!settings.drafts[adventureID]) {
- settings.drafts[adventureID] = {}
- }
- // Button links
- addLink(document.querySelector('#editinfo'), `/my/stories/info/?s=${adventureID}`);
- // Default spoiler values
- const replaceButton = document.querySelector('#replaceall');
- const spoilerButton = document.createElement('input');
- spoilerButton.classList.add('major');
- spoilerButton.value = 'Default Spoiler Values';
- spoilerButton.type = 'button';
- replaceButton.parentNode.insertBefore(spoilerButton, replaceButton);
- replaceButton.parentNode.insertBefore(newBr(), replaceButton);
- replaceButton.parentNode.insertBefore(newBr(), replaceButton);
- 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);
- if (!settings.spoilerValues[adventureID]) {
- settings.spoilerValues[adventureID] = {
- open: 'Show',
- close: 'Hide'
- }
- }
- spoilerOpen.value = settings.spoilerValues[adventureID].open;
- spoilerClose.value = settings.spoilerValues[adventureID].close;
- spoilerButton.addEventListener('click', evt => {
- 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 = settings.spoilerValues[adventureID].open;
- document.querySelector('#dialog input[name="close"]').value = settings.spoilerValues[adventureID].close;
- document.querySelector('#dialog input[name="open"]').placeholder = settings.spoilerValues[adventureID].open;
- document.querySelector('#dialog input[name="close"]').placeholder = settings.spoilerValues[adventureID].close;
- });
- // Buttonless spoilers
- const flashButton = document.querySelector('input[title="Flash');
- const newSpoilerButton = document.createElement('input');
- newSpoilerButton.setAttribute('data-tag', 'Buttonless Spoiler');
- newSpoilerButton.title = 'Buttonless Spoiler';
- newSpoilerButton.type = 'button';
- newSpoilerButton.style = 'background-position: -66px -88px; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAAXNSR0IArs4c6QAAARNJREFUOI3V1LFqhEAQBuDfPaxcLkFwsbhgJ2STWlhQG4twvT7IWecZ8iB3L5In2BfIbaVNglaipMkQPAiBMAnkr2Zg52OZYoD/lg0AKKVMkiQmiqK7russ9cMwvPm+v03T9MHzvKtlWUD1OI5nrXVzOUO9AICyLA9cPzXGfFp1XR+54JWllDJcMFkCAIQQr1wwWQIAiqJouWCyBADM8/zCBa+sMAy3XDBZAgCqqnrkgsmiVVxzwSsrjuNbLpgsAQB5nt9zwWSJj77hgskSAOCcO3GpnNbX+Y0jJL57+NNsAEBKuTPGtFrrxlp7yrLsYIxp+74/B0Fws9/vn6SUu2maPKqdc891XR8vZwDAWvsHe+bOOy65ZXyuZ2jeAAAAAElFTkSuQmCC");';
- 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);
- // Open preview in new tab with middle mouse
- document.body.addEventListener('mouseup', evt => {
- if (evt.toElement.value === "Preview" && evt.button === 1) {
- evt.toElement.click(); // TODO: Find a way to prevent the middle mouse scroll after clicking there.
- evt.preventDefault();
- return false;
- }
- });
- // -- Drafts --
- // Accessing draft text
- const accessDraftsButton = document.createElement('input');
- accessDraftsButton.classList.add('major');
- accessDraftsButton.value = 'Saved Drafts';
- accessDraftsButton.type = 'button';
- replaceButton.parentNode.insertBefore(accessDraftsButton, replaceButton);
- accessDraftsButton.parentNode.insertBefore(newBr(), replaceButton);
- accessDraftsButton.parentNode.insertBefore(newBr(), replaceButton);
- accessDraftsButton.addEventListener('click', () => {
- const draftDialog = window.MSPFA.parseBBCode('Use the textbox below to copy out the data and save to a file somewhere else.\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;';
- draftInputTextarea.rows = 8;
- draftDialog.appendChild(newBr());
- draftDialog.appendChild(newBr());
- draftDialog.appendChild(draftInputTextarea);
- setTimeout(() => {
- draftInputTextarea.focus();
- draftInputTextarea.selectionStart = 0;
- draftInputTextarea.selectionEnd = 0;
- draftInputTextarea.scrollTop = 0;
- }, 1);
- draftInputTextarea.value = JSON.stringify(settings.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") {
- settings.drafts[adventureID] = {};
- saveData(settings);
- }
- });
- }, 1);
- } else if (draftInputTextarea.value !== JSON.stringify(settings.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;
- }
- settings.drafts[adventureID] = newData;
- saveData(settings);
- }
- });
- }, 1);
- }
- }
- });
- });
- // Draft stuff
- const msg = document.createElement('span');
- msg.appendChild(document.createTextNode('Command:'));
- msg.appendChild(document.createElement('br'));
- const commandInput = document.createElement('input');
- commandInput.style = 'width: 100%; box-sizing: border-box;';
- commandInput.readOnly = true;
- commandInput.value = 'yes';
- msg.appendChild(commandInput);
- msg.appendChild(document.createElement('br'));
- msg.appendChild(document.createElement('br'));
- msg.appendChild(document.createTextNode('Body:'));
- const bodyInput = document.createElement('textarea');
- bodyInput.style = 'width: 100%; box-sizing: border-box; resize: vertical;';
- bodyInput.readOnly = true;
- bodyInput.rows = 8;
- bodyInput.textContent = '';
- msg.appendChild(bodyInput);
- const showDraftDialog = (pageNum) => {
- 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 settings.drafts[adventureID][pageNum] === "undefined") {
- shownMessage = document.createTextNode('There is no draft saved for this page.');
- optionButtons = ["Save New", "Close"];
- } else {
- commandInput.value = settings.drafts[adventureID][pageNum].command;
- bodyInput.textContent = settings.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 settings.drafts[adventureID][pageNum] === "undefined") {
- settings.drafts[adventureID][pageNum] = {
- command: commandElement.value,
- pageContent: pageContentElement.value
- }
- saveData(settings);
- } 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") {
- settings.drafts[adventureID][pageNum] = {
- command: commandElement.value,
- pageContent: pageContentElement.value
- }
- saveData(settings);
- }
- });
- }, 1);
- }
- } else if (output === "Load") {
- if (pageContentElement.value === '' && (commandElement.value === '' || commandElement.value === document.querySelector('#defaultcmd').value)) {
- commandElement.value = settings.drafts[adventureID][pageNum].command;
- pageContentElement.value = settings.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 = settings.drafts[adventureID][pageNum].command;
- pageContentElement.value = settings.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 unreversable! Are you sure?'), ["Yes", "No"], (output, form) => {
- if (output === "Yes") {
- delete settings.drafts[adventureID][pageNum];
- saveData(settings);
- }
- });
- }, 1);
- }
- });
- }
- const createDraftButton = (form) => {
- const draftButton = document.createElement('input');
- draftButton.className = 'major draft';
- draftButton.type = 'button';
- draftButton.value = 'Draft';
- draftButton.style = 'margin-right: 9.5px;';
- 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);
- });
- 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);
- });
- return true;
- }
- });
- /* // Removed because apparently MSPFA already does this fine!
- if (hashSearch) {
- pageLoad(() => {
- const element = document.querySelector(hashSearch);
- if (element) {
- if (element.style.display === "none") {
- element.style = '';
- }
- return true;
- }
- });
- }/**/
- }
- else if (location.pathname === "/user/") {
- const id = location.search.slice(3);
- const statAdd = [];
- // Button links
- pageLoad(() => {
- const msgButton = document.querySelector('#sendmsg');
- if (msgButton) {
- addLink(msgButton, `/my/messages/new/${location.search}`);
- addLink(document.querySelector('#favstories'), `/favs/${location.search}`);
- 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);
- if (statAdd.indexOf('date') === -1) {
- window.MSPFA.request(0, {
- do: "user",
- u: id
- }, user => {
- if (typeof user !== "undefined") {
- statAdd.push('date');
- joinTime.textContent = new Date(user.d).toString().split(' ').splice(1, 4).join(' ');
- }
- });
- }
- if (statAdd.indexOf('made') === -1) {
- window.MSPFA.request(0, {
- do: "editor",
- u: id
- }, s => {
- if (typeof s !== "undefined") {
- statAdd.push('made');
- advCountText.textContent = s.length;
- }
- });
- }
- if (document.querySelector('#favstories').style.display !== 'none' && statAdd.indexOf('fav') === -1) {
- statAdd.push('fav');
- 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: id
- }, s => {
- if (typeof s !== "undefined") {
- favCountText.textContent = s.length;
- }
- });
- favCount.appendChild(favCountText);
- }
- return true;
- }
- });
- }
- else if (location.pathname === "/favs/" && location.search) {
- // Button links
- pageLoad(() => {
- const 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;
- }
- });
- 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;
- }
- });
- }
- 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: location.search.replace('?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;
- }
- });
- }
- })();