Advertisement
Steve5451

Web Terminal 1.2

Sep 23rd, 2016
1,304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Web Terminal
  3. // @namespace    http://thepotato.net/
  4. // @version      1.2
  5. // @description  Fallout aesthetic
  6. // @author       Steve5451
  7. // @include      *
  8. // @downloadURL  http://pastebin.com/raw/U0rpZQLb
  9. // @updateURL    http://pastebin.com/raw/U0rpZQLb
  10. // @run-at       document-start
  11. // @grant        GM_xmlhttpRequest
  12. // @connect      *
  13. // ==/UserScript==
  14.  
  15. var color = rgb(0,255,0);
  16.  
  17. // rgb color. (red, green, blue) from 0-255. red = (255,0,0), eye rape pink = (255,0,255), white = (255,255,255)
  18. // Too confusing? http://www.w3schools.com/colors/colors_picker.asp
  19. // pick a color and copy the numbers
  20.  
  21. // ---------------------------------------------------------------------------------------------------------------- //
  22.  
  23. // Although this is super niche and no one is going to use it for more than five minutes I will comment every line
  24.  
  25. // So that a seperate stylesheet isn't required I'm just going to poll the page as soon as it begins loading until the body is created. That's when it'll be placed at the bottom of the <head>
  26. // This is undesirable but not terrible. I'm doing this so the page doesn't go from normal to *~POP GREEN~* when the page has finished loading.
  27.  
  28. var checkInterval = setInterval(function() { // Create an interval
  29.     if(document.body) { // If the body exists that means the head is done.
  30.         var terminalStyle = document.createElement("style"); // Create our style element
  31.         terminalStyle.innerHTML = styleSheet; // Set style
  32.         document.head.appendChild(terminalStyle); // Place style in head
  33.         document.body.appendChild(effectCanvas); // Place our canvas
  34.  
  35.         clearInterval(checkInterval); // We don't need this interval anymore. Get rid of it.
  36.     }
  37. }, 1); // 1ms?? why not use while(true) steve???? because the 1ms gives our page time to process stuff.
  38.  
  39. // Style has been placed. On to the important bits...
  40. var canvas = document.createElement("canvas"),
  41.     ctx = canvas.getContext("2d"),
  42.     effectCanvas = document.createElement("canvas"), // Create a canvas. This will be used for the scrolling line effects.
  43.     effect = effectCanvas.getContext("2d"),
  44.     lineOffset = 0, // offset of the line things
  45.     images; // This will contain our pages images
  46.  
  47. effectCanvas.width = window.innerWidth; // Set its size to match the browser
  48. effectCanvas.height = window.innerHeight;
  49. effectCanvas.style.position = "fixed"; // fix it to the top
  50. effectCanvas.style.left = "0px";
  51. effectCanvas.style.top = "0px";
  52. effectCanvas.style.zIndex = "100"; // Make sure it's the topmost layer
  53. effectCanvas.setAttribute("id","effectCanvas");
  54.  
  55. window.onresize = function() { // When we resize the window we want the canvas to resize too.
  56.     effectCanvas.width = window.innerWidth;
  57.     effectCanvas.height = window.innerHeight;
  58. };
  59.  
  60. window.addEventListener("load", function() {
  61.     images = document.getElementsByTagName("img"); // Get every image on the page
  62.     for(var i = 0; i < images.length; i++) { // For every image...
  63.         GM_xmlhttpRequest({
  64.             ///////////// So this is a hack. The cross origin policy doesn't allow me to modify images from another site (eg. imgur) so this is what I've done:
  65.             // (?) GM_xmlhttpRequest is a userscript method that functions the same way as an xmlHttpRequest(), however it ignores the cross-origin policy.
  66.             // Get image url
  67.             // Open a new request in plain text
  68.             // Place every byte into a unit8array
  69.             // Create a blob from the data array
  70.             // Use a file reader to create a base64 string from the data
  71.             // Create a new image and set the image source to the base64 string
  72.             // We now have an image loaded from another origin. (all that to load an image????)
  73.  
  74.             method: "GET",
  75.             url: images[i].src + "#imgnum" + i,
  76.             overrideMimeType: "text/plain; charset=x-user-defined", // couldn't figure out a way to load the image without plaintext -> base64
  77.             onload: function(response) { // once loaded...
  78.                 var img = images[parseInt(response.finalUrl.split("#imgnum")[1])];
  79.  
  80.                 var data = new Uint8Array(response.responseText.length); // Creat the unit8array
  81.                 for(var a = 0; a < response.responseText.length; a++) { // For each byte in the loaded image
  82.                     data[a] = response.responseText.charCodeAt(a); // Place in the unit8array
  83.                 }
  84.  
  85.                 var contentType = img.src.split("."); // We'll just get the content type (aka imag extension) from the beginning of the image
  86.                 contentType = "image/" + contentType[contentType.length - 1].replace("jpg","jpeg"); // jpg = jpeg
  87.  
  88.                 var blob = new Blob([data], {type: contentType}); // Create a blob
  89.  
  90.                 var fr = new FileReader(); // Create a file reader
  91.                 fr.orig = img; // to read: our image data
  92.                 fr.onload = function() { // Once loaded...
  93.                     var newImage = new Image(); // Create an image
  94.                     newImage.orig = fr.orig; // doing this to pass along data
  95.                     newImage.src = fr.result; // Set the source to a base64 of the requested image
  96.  
  97.                     newImage.onload = function() { // Once it has finished loading
  98.                         canvas.width = newImage.naturalWidth; // set canvas to size of image
  99.                         canvas.height = newImage.naturalHeight;
  100.                         ctx.drawImage(newImage,0,0,canvas.width,canvas.height); // This is where things actually happen. Draw image to the canvas
  101.  
  102.                         processImage(canvas, ctx); // Let's start modifying the image. goto: processImage()
  103.  
  104.                         newImage.orig.src = canvas.toDataURL();
  105.                         newImage.orig.style.visibility = "visible";
  106.                     };
  107.                 };
  108.  
  109.                 fr.readAsDataURL(blob);
  110.             }
  111.         });
  112.     }
  113. });
  114.  
  115. // Constants for the Loyd–Steinberg dithering that will be applied to the images. I don't really understand entirely how it works but I managed to impliment it.
  116. var lumR = [];
  117. var lumG = [];
  118. var lumB = [];
  119. for (var i = 0; i < 256; i++) {
  120.     lumR[i] = i * 0.299;
  121.     lumG[i] = i * 0.587;
  122.     lumB[i] = i * 0.114;
  123. }
  124.  
  125. function processImage(canvas, ctx) { // This is the method where our images are actually colored and stuff. (I really wish I could use workers as to not tax the main thread and have a laggy loading experience but with userscripts the browser won't allow that as a violation of the dreaded cross-origin policy)
  126.     var imgData = ctx.getImageData(0,0,canvas.width,canvas.height); // Get image data of the canvas which really just gets the individual pixel colors of the image
  127.  
  128.     for(var i = 0; i < imgData.data.length; i += 4) { // Loop through the pixels (that's a lot of for loops. I must be crazy.
  129.         var avg = (imgData.data[i] + imgData.data[i + 1] + imgData.data[i + 2]) / 3; // Get the average color of the pixel
  130.  
  131.         imgData.data[i] = Math.floor(lumR[imgData.data[i]] + lumG[imgData.data[i+1]] + lumB[imgData.data[i+2]]); // Make image 16 bit. This helps a lot with preventing an extremely grainy image.
  132.  
  133.         // Loyd-Steinberg dithering
  134.         var newPixel = imgData.data[i] < 129 ? 0 : 255; // If the pixel is less than half then make it black, otherwise fully colored.
  135.         var err = Math.floor((imgData.data[i] - newPixel) / 16);
  136.         imgData.data[i] = newPixel;
  137.  
  138.         imgData.data[i + 4 ] += err * 7;
  139.         imgData.data[i + 4 * canvas.width - 4] += err * 3;
  140.         imgData.data[i + 4 * canvas.width] += err * 5;
  141.         imgData.data[i + 4 * canvas.width + 4] += err * 1;
  142.  
  143.         imgData.data[i + 1] = imgData.data[i + 2] = imgData.data[i]; // Make the image greyscale again
  144.         imgData.data[i] *= (color.red / 255); // Set red
  145.         imgData.data[i + 1] *= (color.green / 255); // Set green
  146.         imgData.data[i + 2] *= (color.blue / 255); // Set blue
  147.     }
  148.  
  149.     ctx.putImageData(imgData, 0, 0); // Place the modified pixel data back on our canvas. It is now 2bit green.
  150. }
  151.  
  152. function update() { // This is for the animation of the lines running down the screen
  153.     requestAnimationFrame(update); // We want a frame after this, duh. Request it.
  154.  
  155.     effect.clearRect(0,0,window.innerWidth,window.innerHeight); // Clear our previous lines
  156.  
  157.     effect.fillStyle = "rgb(" + color.red + "," + color.green + "," + color.blue + ")"; // I'd set these globally but I was having some strange issues. No matter, two lines won't hurt our 60fps of lines running down our screen.
  158.     effect.globalAlpha = 0.07;
  159.  
  160.     for(var i = lineOffset - 50; i < window.innerHeight + 100; i += 100) { // Space the lines 100px away from eachother
  161.         effect.fillRect(0, i, window.innerWidth, 30); // fill it, 30 pixels thick/
  162.     }
  163.  
  164.     lineOffset += 1; // set the offset + 1 pixel so they run down the screen on the next frame
  165.  
  166.     if(lineOffset >= 100) { // If it's below the screen send it back to the top
  167.         lineOffset = 0;
  168.     }
  169. }
  170.  
  171. update(); // Now let's begin the animation
  172.  
  173. function rgb(r, g, b) {
  174.     return {red: r, green: g, blue: b};
  175. }
  176.  
  177. // This is our stylesheet. I put it at the bottom for readability purposes.
  178. var styleSheet = `
  179. @import 'https://fonts.googleapis.com/css?family=VT323';
  180.  
  181. *:not(#effectCanvas) {
  182. background-color: #000 !important;
  183. background-image: none !important;
  184. border-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
  185. color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
  186. font-family: 'VT323', monospace !important;
  187. font-size: 16pt;
  188. }
  189.  
  190. #effectCanvas {
  191. pointer-events: none;
  192. }
  193.  
  194. a, a:link, a:visited {
  195. color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
  196. text-decoration: underline !important;
  197. }
  198.  
  199. ::-webkit-scrollbar {
  200. display: none;
  201. }
  202.  
  203. .bordercolor {
  204. background-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
  205. border: 1px solid rgb(${color.red}, ${color.green}, ${color.blue});
  206. }
  207.  
  208. #effectCanvas {
  209. background-image:url(http://i.imgur.com/NwGZfUP.png) !important;
  210. background-size: 100% 100% !important;
  211. }
  212.  
  213. input[type='radio'] {
  214. -webkit-appearance: none;
  215. border: 1px solid rgb(${color.red}, ${color.green}, ${color.blue});
  216. padding: 5px;
  217. }
  218.  
  219. input[type='radio']:checked {
  220. background-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
  221. }
  222.  
  223. *, *:hover {
  224. //cursor: url(https://i.imgur.com/jHZgg47.png), default !important;
  225. outline: none !important;
  226. }
  227.  
  228. .quote {
  229. font-size: 15pt;
  230. padding: 2px;
  231. margin-top: 10px;
  232. }
  233.  
  234. .smalltext {
  235. font-size: 10pt;
  236. }
  237.  
  238. img {
  239. visibility: hidden;
  240. }
  241.  
  242. ::selection {
  243. color: #000;
  244. background-color: rgb(${color.red}, ${color.green}, ${color.blue});
  245. }
  246.  
  247. ::-moz-selection {
  248. color: #000;
  249. background-color: rgb(${color.red}, ${color.green}, ${color.blue});
  250. }
  251.  
  252. a:active {
  253. background-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
  254. color: #000 !important;
  255. //cursor: url(https://i.imgur.com/jHZgg47.png), default !important;
  256. }
  257. `;
  258.  
  259. /* Changelog
  260. 1.0   - Initial release
  261. 1.0.1 - Changed text selection color and curors
  262. 1.0.2 - Link styling
  263. 1.1   - Dithering and less poppy loading
  264. 1.1.1 - Added option for "Always allow all domains" so that you don't need to hit accept every time a new image domain is accessed
  265. 1.2   - Custom color support, optimiztion, and works on every page
  266. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement