您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Dinosaur Comics has a fairly hidden feature where you can get an overlay that replaces the regular characters with, for instance, XKCD or Problem Sleuth images. This script makes it easier to get to those overlays by providing a drop-down box to select from.
// ==UserScript== // @name Dinosaur Comics Overlay Chooser // @namespace http://userscripts.org/users/didero // @description Dinosaur Comics has a fairly hidden feature where you can get an overlay that replaces the regular characters with, for instance, XKCD or Problem Sleuth images. This script makes it easier to get to those overlays by providing a drop-down box to select from. // @include http*://www.qwantz.com/index.php* // @include http*://qwantz.com/index.php* // @include http*://qwantz.com/ // @include http*://www.qwantz.com/ // @version 1.10.0 // @grant none // ==/UserScript== //Name of each overlay. If you discover more, feel free to add them. Send them to me too, so I can add them myself. // The entries here are how they will be shown in the drop-down box. // When you select an option, the spaces will be removed and it will be converted to lower case. That string will then be added to the URL. // If there is a special way the option should be added to the URL (like the RIAA one, where 'RIAA' needs to be capitalized), // add the way it should be displayed, then add '|' and then the way it should be added to the URL. Look at the RIAA one for an example. const listOfOverlays = ["A Lesson Is Learned But The Damage Is Irreversible", "About Pirates", "Achewood", "Brodyquest", "Before The Special Effects Are Added", "Buttercup Festival", "Daisy Owl", "DC Comics", "Dr McNinja", "Just About T-Rex", "Mr Boop", "Nedroid", "On April Fools Day 2014", "One Done In Watercolours", "One Where T-Rex Got Assimilated", "One Where T-Rex Swears More", "One Where T-Rex Wears More", "Penny Arcade", "Pokey", "Problem Sleuth", "Registered Weapon", "Shortpacked", "Sister Claire", "Something More Historically Accurate", "Something That Will Destroy My Brain", "Sweet Bro And Hella Jeff", "The Last Dinosaur Comic Ever", "The RIAA Version Of The Internet|theRIAAversionoftheinternet", "The Same Pictures", "webcomic name", "Wigu", "Winnie The Pooh", "With Less White", "Wondermark", "XKCD"]; //The label in front of the drop-down box. (Not always used, depends on position) const label = 'But I Would Rather Be Reading: '; //The topmost option in the dropdown box, that when selected shows the comic without any overlays, as nature intended const optionNoOverlayText = 'Default Dinosaur Discourse'; //The text for the custom overlay option, if there is one set const optionCustomOverlayText = 'Something Of My Own Choosing'; //If a URL is specified as overlay, a separate entry is added to the dropdown list. This text will be used as that entry const optionUrlOverlayText = 'The Input Of The Internet'; //There's an overlay called 'surpriseme', which uses a random overlay each refresh. Put it in a separate choice instead of in the main lineup, because it's different const optionRandomOverlayText = 'Something More Surprising'; /********************** DON'T EDIT UNDER THIS LINE UNLESS YOU KNOW WHAT YOU'RE DOING IF YOU MAKE IMPROVEMENTS, PLEASE LET ME KNOW. THANKS **********************/ //Some functions to replace built-in Greasemonkey functions, for portability function setValue(key, value) { localStorage.setItem("DCOC_"+key, value); } function getValue(key, defaultValue) { let value = localStorage.getItem("DCOC_"+key); if (value) { return value; } return defaultValue; } function keyExists(key) { return localStorage.getItem(key) !== null; } function deleteValue(key) { localStorage.removeItem("DCOC_"+key); } function deleteAllValues() { //Don't use 'localStorage.clear()' since that also clears the data of other scripts for (let i = 0, len = localStorage.length; i < len; i++) { let key = localStorage.key(i); if (key.indexOf("DCOC_") === 0) { localStorage.removeItem(key); } } } function isValueStored() { for (let i = 0, len = localStorage.length; i < len; i++) { if (localStorage.key(i).indexOf("DCOC_") === 0) { return true; } } return false; } //Utility functions function createLink(text, parent, addNewLineToParent, onclick) { let link = document.createElement('a'); link.href = document.location.href; link.innerHTML = text; link.style.cssText = 'font-weight: normal; font-size: 12px; color: #000000;'; //Make sure it displays properly in all possible locations parent.appendChild(link); if (addNewLineToParent) { parent.appendChild(document.createElement('br')); } if (onclick) { link.onclick = onclick; } return link; } //This function retrieves the GET value of the provided key, if it exists (Source: http://stackoverflow.com/questions/827368/use-the-get-paramater-of-the-url-in-javascript) function getQueryVariable(variable) { //Split up the part of the url after the question mark in key-value pairs let vars = window.location.search.substring(1).split("&"); //Go through each of the pairs to see if it matches the provided variable for (let i = 0; i < vars.length; i++) { let pair = vars[i].split("="); if (pair[0] === variable) { return pair[1]; } } //If the requested variable wasn't found, return null return null; } //A function to test if a string is a URL. Simply checking if it starts with 'http' isn't good enough, since it throws an error if the string is null function isUrl(line) { return line !== null && line.search('http') === 0; } //Set and/or retrieve some initial values, needed in the rest of the script var url = "http://www.qwantz.com/index.php?"; var comicNumber = getQueryVariable("comic"); if (comicNumber !== null) { url += "comic=" + comicNumber + "&"; } var overlayName = getQueryVariable('butiwouldratherbereading'); var dropdownLocation = getValue('location', 3); //If a specific overlay is set to 'remember', redirect to that if we're not there already var savedOverlay = getValue('overlay', ''); if (savedOverlay !== '' && savedOverlay !== 'none') { if (overlayName !== savedOverlay) { window.location.href = url + 'butiwouldratherbereading='+savedOverlay; } } //If the overlay name has been set to the custom overlay or if a URL has been set, use that as overlay if (overlayName === 'custom' || isUrl(overlayName)) { let overlayLocation = ''; if (overlayName === 'custom') { overlayLocation = getValue('customOverlay', ''); } else { overlayLocation = overlayName; } //If there's no custom overlay set, redirect to the overlay-less page if (overlayLocation === '') { window.location.href = url.substring(0, url.length-1); } //Otherwise, immitate the official overlays by setting the overlay as the main comic image and the actual comic as background through CSS else { let comic = document.getElementsByClassName('comic'); //Sometimes there's multiple comics per page (#2340), account for that and apply the overlay to all of them if (comic.length > 0) { for (let i = 0, len = comic.length; i < len; i++) { comic[i].style.backgroundImage = 'url("'+comic[i].src+'")'; comic[i].src = overlayLocation; comic[i].className = ''; } } } } //Create the dropdown list var selectBox = document.createElement('select'); selectBox.onchange = function() { //Store the overlay as favourite, if that is enabled by the user if (getValue('overlay', '') !== '') { //Only store it if the user isn't going to the default overlay-less page setValue('overlay', selectBox.value); } //Then redirect to the appropriate overlay if (selectBox.value === 'none' || selectBox.value === '') { window.location.href = url.substring(0, url.length-1); } else { window.location.href = url + 'butiwouldratherbereading=' + selectBox.value; } //return false; } //Fill the select box with the provided overlay options selectBox.add(new Option(optionNoOverlayText, 'none'), null); //If there's a custom overlay set, add the option to choose that if (getValue('customOverlay', '') !== '') { selectBox.add(new Option(optionCustomOverlayText, 'custom'), null); if (overlayName === 'custom') { selectBox.selectedIndex = selectBox.length - 1; } } //If the current overlay is a URL, add a seperate option for that, for clarity's sake if (isUrl(overlayName)) { selectBox.add(new Option(optionUrlOverlayText, overlayName), null); selectBox.selectedIndex = selectBox.length-1; } //Add the choice for a random overlay selectBox.add(new Option(optionRandomOverlayText, 'surpriseme'), null); if (overlayName === 'surpriseme') { selectBox.selectedIndex = selectBox.length-1; } selectBox.add(new Option("----", ""), null); selectBox.options[selectBox.length-1].disabled = "disabled"; //The dashed line shouldn't be selectable for (let i=0, len = listOfOverlays.length; i < len; i++) { let displayName = listOfOverlays[i]; let valueName; //If there's a special value name, retrieve that let sepPos = displayName.indexOf('|'); if (sepPos > -1) { valueName = displayName.substring(sepPos + 1); displayName = displayName.substring(0, sepPos); } else { valueName = displayName.toLowerCase().replace("-", "").split(" ").join(""); } selectBox.add(new Option(displayName, valueName), null); //If the overlay specified in the URL is the same as the one currently being added to the dropdownlist, select it if (overlayName === valueName) { selectBox.selectedIndex = selectBox.length - 1; } } //Then create the mouse-over options menu var menu = document.createElement('div'); menu.style.cssText = 'position: absolute; border: solid #000000; border-width: 2px 2px 4px 3px; visibility: hidden; background-color: #FFFFFF; z-index: 100; left: 0px; top: 75%; width: 200px;'; //Border is set to match the comic's menu.isMousedOver = false; menu.onmouseover = function() { this.isMousedOver = true; } menu.onmouseout = function() { this.isMousedOver = false; this.style.visibility = 'hidden'; } //Let's add some entries to the menu! // First to set the location of the dropdown box if (dropdownLocation !== 1) { createLink('Move To Header', menu, true, function() {setLocation(1); return false;}); } if (dropdownLocation !== 2) { createLink('Move To Above The Comic', menu, true, function() {setLocation(2); return false;}); } if (dropdownLocation !== 3) { createLink('Move To Below The Comic', menu, true, function() { //Below comic is standard, no need to store location anymore deleteValue('location'); window.location.reload(); return false; }); } // Then to set a favourite overlay if (getValue('overlay', '') === '' && overlayName !== null) { createLink('Always Use Current Overlay', menu, true, function() { setValue('overlay', overlayName); alert('The next time you visit Dinosaur Comics, you will be automatically redirected to this overlay.'); return false; }); } // If there already is a stored overlay, allow it to be cleared else if (getValue('overlay', '') !== '') { createLink('Stop Always Using Current Overlay', function() { deleteValue('overlay'); alert('You will no longer be automatically redirected to an overlay.'); return false; }); } //Custom overlay if (getValue('customOverlay', '') !== '') { createLink('Change Custom Overlay', menu, true, function() {setCustomOverlay(); return false;}); } else { createLink('Set Custom Overlay', menu, true, function() {setCustomOverlay(); return false;}); } // Also allow the option to clear values stored by this script, if there are any if (isValueStored() > 0) { createLink('Delete All Data Stored By This Script', menu, true, function() { deleteAllValues(); alert('All stored data was successfully deleted'); window.location.reload(); return false; }); } //And add functions to handle those choices // Location choices function setLocation(location) { setValue('location', location); window.location.reload(); } // Custom overlay function setCustomOverlay() { let customOverlay = prompt('Enter the exact location of the overlay image\nLeave empty to clear the stored value', getValue('customOverlay','http://')); //Ask the user which URL they want to use, as default use the current one if applicable if (customOverlay !== null ) { //If the user didn't cancel //If empty return, clear stored value if (customOverlay === '' || customOverlay === 'http://') { deleteValue('customOverlay'); window.location.reload(); } else { setValue('customOverlay', customOverlay); window.location.href = url + 'butiwouldratherbereading=custom'; } } } //Create an image to mouse-over to display the menu var img = document.createElement('span'); img.style.cssText = "position: relative; background-image: url('http://i.imgur.com/Bp5pU.png'); background-repeat: no-repeat; width: 20px;"; img.innerHTML = ' '; img.appendChild(menu); img.menu = menu; img.onmouseover = function() { this.menu.style.visibility = 'visible'; } img.onmouseout = function() { if (!this.menu.isMousedOver) { this.menu.style.visibility = 'hidden'; } } //Tie it all together var selectBoxDisplay = document.createElement('span'); selectBoxDisplay.appendChild(selectBox); selectBoxDisplay.appendChild(img); /*DISPLAY THE DROPDOWN IN THE TOP MENU*/ if (dropdownLocation === 1) { //Find the 'About' link, since our dropdown box will be added just after it let aboutLink = document.evaluate( "//a[@href='http://www.qwantz.com/about.php']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ); if (aboutLink.snapshotLength === 1) { aboutLink = aboutLink.snapshotItem(0); let aboutParent = aboutLink.parentNode.parentNode; //Insert a separating bullet, like with the other links let separator = document.createElement('li'); separator.className = 'paddedbullet'; separator.innerHTML = '\u2022'; //the '\u2022' is the bullet character used to separate the links aboutParent.appendChild(separator); //since all other menu items are contained in an 'li', this one should be no different var selectContainer = document.createElement("li"); selectContainer.appendChild(selectBoxDisplay); //Finally, display the dropdown box aboutParent.appendChild(selectContainer); } } //Display the dropdown between the header and the comic else if (dropdownLocation === 2) { let newRow = document.getElementById('header').getElementsByTagName('table')[0].insertRow(2); //Below the Utahr.-Rex conversation (1 = above) let newCell = newRow.insertCell(0); newCell.colSpan=2; newCell.className = 'white'; newCell.align = 'center'; newCell.style.fontWeight = 'bold'; newCell.innerHTML = label; newCell.appendChild(selectBoxDisplay); } //Display the dropdown below the comic else { let comic = document.getElementsByClassName('comic'); //Some pages have multiple comics (page 2340). Allow for that (hence length-1 instead of just '0' if (comic.length >= 1) { comic = comic[comic.length-1]; } else { //If there's an overlay active, the image tag changes. Now it's the only image with a 'style' tag comic = document.evaluate( "//img[contains(@style, 'background')]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ); if (comic.snapshotLength === 1) { comic = comic.snapshotItem(0); } else { comic = null; } } if (comic) { let display = document.createElement('div'); display.innerHTML = label; display.appendChild(selectBoxDisplay); display.style.fontWeight = 'bold'; let comicParent = comic.parentNode; //If the comic is a link, put the dropdown outside the link. With multiple comics, the dropdown has to go one further up the hierarchy if (comicParent.tagName === 'A' || comicParent.tagName === 'DIV') { comicParent = comicParent.parentNode; } comicParent.appendChild(display); } }