anonymous_you

Endchan Mascot

Dec 29th, 2022 (edited)
456
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Endchan Mascot
  3. // @namespace    https://endchan.org/
  4. // @version      1.3
  5. // @description  Add a configurable mascot to endchan
  6. // @author       Anonymous (You)
  7. // @match        http://endchan.org/*/res/*
  8. // @match        https://endchan.org/*/res/*
  9. // @match        http://endchan.net/*/res/*
  10. // @match        https://endchan.net/*/res/*
  11. // @match        http://magrathea.endchan.net/*/thread/*
  12. // @match        https://magrathea.endchan.net/*/thread/*
  13. // @resource     fontAwesomeCSS https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css
  14. // @grant        none
  15. // @downloadURL  https://pastebin.com/raw/yjwXhRv2
  16. // @updateURL    https://pastebin.com/raw/yjwXhRv2
  17. // ==/UserScript==
  18.  
  19. /*
  20. How this works is you get 2 new elements on the page - one is the mascot, the other is a settings overlay.
  21. The mascot can get toggled into the foreground/background (in front/behind posts).
  22. When it's in the foreground it can be positioned anywhere in the window. Toggling it back into the background will lock its position.
  23.  
  24. Bottom right corner of the image has a hidden settings button that's revealed on mouseover.
  25. Click that to toggle the image into the foreground and show other settings. Click again to lock the mascot back into the background.
  26. The settings overlay travels with the image when it's repositioned.
  27.  
  28. The other settings button is an image picker, use that to replace the default mascot.
  29.  
  30. Settings are saved to localStorage (browser cache) so they should be more or less persistent.
  31. The things that are saved are mascot position (x, y) and the image src attribute. When selecting the image through the picker the src is the image encoded in base64.
  32. */
  33.  
  34. /*
  35. 1.3 - added endchan.net to @match
  36. 1.2 - support for magrathea
  37. 1.1 - added update urls
  38. */
  39.  
  40. // adjust this as you see fit, this is the max size the mascot is allowed to be
  41. let mascotWidth = 800;
  42. let mascotHeight = 600;
  43.  
  44. // init global vars to default
  45. let drag = false;
  46. let offsetX = 0;
  47. let offsetY = 0;
  48. let mascotPosX = 100;
  49. let mascotPosY = 100;
  50. let defaultMoveCallback = undefined;
  51. let mascotSrc = "https://static.wixstatic.com/media/32a1d6_391792dd70889caab5064b911d234eb7.png/v1/fit/w_2500,h_1330,al_c/32a1d6_391792dd70889caab5064b911d234eb7.png"
  52.  
  53. // override any vars that need overriding
  54. restoreSettings();
  55.  
  56. // create the mascot image tag
  57. let mascotImg = document.createElement("img");
  58. mascotImg.src = mascotSrc;
  59. mascotImg.className = "draggableMascot"
  60. mascotImg.style.maxWidth = mascotWidth + "px";
  61. mascotImg.style.maxHeight = mascotHeight + "px";
  62. mascotImg.style.position = "fixed";
  63. mascotImg.style.bottom = mascotPosY + "px";
  64. mascotImg.style.right = mascotPosX + "px";
  65. mascotImg.style.zIndex = -1;
  66. mascotImg.draggable = true;
  67.  
  68. // create the settings tag - this needs to stay in the foreground (uses opacity trickery to hide and still trigger mouseover events)
  69. let mascotSettings = document.createElement("div");
  70. mascotSettings.style.position = mascotImg.style.position;
  71. mascotSettings.style.bottom = mascotImg.style.bottom;
  72. mascotSettings.style.right = mascotImg.style.right;
  73. mascotSettings.style.zIndex = 2;
  74. mascotSettings.style.margin = "4px";
  75.  
  76. // toggle settings button - moves mascot into foreground so it can be moved around and shows other settings
  77. let settingsBtn = document.createElement("button");
  78. settingsBtn.style.opacity = 0;
  79. settingsBtn.style.minWidth = "28px";
  80. settingsBtn.style.minHeight = "28px";
  81. let settingsBtnContent = document.createElement("i");
  82. settingsBtnContent.classList.add("fa", "fa-gear");
  83. settingsBtn.appendChild(settingsBtnContent);
  84.  
  85. // image picker button - opens file picker dialog
  86. let imgPickerBtn = document.createElement("button");
  87. imgPickerBtn.style.opacity = 0;
  88. imgPickerBtn.style.minWidth = "28px";
  89. imgPickerBtn.style.minHeight = "28px";
  90. imgPickerBtn.style.marginRight = "4px";
  91. let imgPickerBtnContent = document.createElement("i");
  92. imgPickerBtnContent.classList.add("fa", "fa-image");
  93. imgPickerBtn.appendChild(imgPickerBtnContent);
  94.  
  95. // add buttons to settings overlay
  96. mascotSettings.appendChild(imgPickerBtn);
  97. mascotSettings.appendChild(settingsBtn);
  98.  
  99. // -- configure settings functionality
  100.  
  101. settingsBtn.onmouseover = function() {
  102.   setSettingsBtnVisibility(true);
  103. }
  104. settingsBtn.onmouseout = function() {
  105.   setSettingsBtnVisibility(false);
  106. }
  107. settingsBtn.onclick = toggleEditing;
  108. imgPickerBtn.onclick = selectImage;
  109.  
  110. function setSettingsBtnVisibility(isMouseOver) {
  111.   if (isMouseOver) {
  112.     settingsBtn.style.opacity = 1;
  113.   } else if (mascotImg.style.zIndex == -1) {
  114.     // hide on mouse out only if the mascot is locked (not in the foreground)
  115.     settingsBtn.style.opacity = 0;
  116.   }
  117. }
  118.  
  119. function toggleEditing() {
  120.   // if mascot is in the background bring it forward so it can be dragged, otherwise send it back
  121.   // also set the visibility of other settings buttons
  122.   if (mascotImg.style.zIndex == -1) {
  123.     mascotImg.style.zIndex = 1;
  124.     imgPickerBtn.style.opacity = 1;
  125.   } else {
  126.     mascotImg.style.zIndex = -1;
  127.     imgPickerBtn.style.opacity = 0;
  128.   }
  129. }
  130.  
  131. function selectImage() {
  132.   const fileInput = document.createElement("input");
  133.   fileInput.type = "file";
  134.   fileInput.addEventListener("change", () => {
  135.     const file = fileInput.files[0];
  136.     const reader = new FileReader();
  137.     reader.addEventListener("load", () => {
  138.       mascotImg.src = reader.result;
  139.       saveSettings(true);
  140.     });
  141.     reader.readAsDataURL(file);
  142.   });
  143.   fileInput.click();
  144. }
  145.  
  146. // -- mouse events
  147.  
  148. function mouseDown(e) {
  149.   // get the event target (mascot image)
  150.   let evt = e ? e : window.event;
  151.   // IE uses srcElement, others use target
  152.   let mascot = evt.target ? evt.target : evt.srcElement;
  153.   if (mascot.className != "draggableMascot") {
  154.     return false;
  155.   }
  156.  
  157.   // ensure mascot has a starting position
  158.   if (!mascot.style.right) {
  159.     mascot.style.right = "0px";
  160.   }
  161.   if (!mascot.style.bottom) {
  162.     mascot.style.bottom = "0px";
  163.   }
  164.  
  165.   // get the mouse current coords
  166.   offsetX = evt.clientX;
  167.   offsetY = evt.clientY;
  168.  
  169.   // get the mascot"s current coords
  170.   mascotPosX = parseInt(mascot.style.right);
  171.   mascotPosY = parseInt(mascot.style.bottom);
  172.   drag = true;
  173.  
  174.   // move the mascot
  175.   defaultMoveCallback = document.onmousemove;
  176.   document.onmousemove = mouseMove;
  177.   return true;
  178. }
  179.  
  180. function mouseMove(e) {
  181.   // ensure we are in fact dragging
  182.   if (!drag) {
  183.     return false;
  184.   }
  185.   // get the event target (mascot image)
  186.   let evt = e ? e : window.event;
  187.   // move the mascot
  188.   mascotImg.style.right = (mascotPosX - evt.clientX + offsetX) + "px";
  189.   mascotImg.style.bottom = (mascotPosY - evt.clientY + offsetY) + "px";
  190.   mascotSettings.style.right = mascotImg.style.right;
  191.   mascotSettings.style.bottom = mascotImg.style.bottom;
  192.   return false;
  193. }
  194.  
  195. function mouseUp() {
  196.   // stop dragging and reset move callback
  197.   drag = false;
  198.   document.onmousemove = defaultMoveCallback;
  199.   saveSettings();
  200.   return false;
  201. }
  202.  
  203. // -- settings persistency
  204.  
  205. function saveSettings(includeImage = false) {
  206.   localStorage.setItem("mascotPosX", mascotImg.style.right);
  207.   localStorage.setItem("mascotPosY", mascotImg.style.bottom);
  208.   if (includeImage) {
  209.     localStorage.setItem("mascotSrc", mascotImg.src);
  210.   }
  211. }
  212.  
  213. function restoreSettings() {
  214.   let x = localStorage.getItem("mascotPosX");
  215.   if (x) {
  216.     mascotPosX = parseInt(x);
  217.   }
  218.   let y = localStorage.getItem("mascotPosY");
  219.   if (y) {
  220.     mascotPosY = parseInt(y);
  221.   }
  222.   let src = localStorage.getItem("mascotSrc");
  223.   if (src) {
  224.     mascotSrc = src;
  225.   }
  226. }
  227.  
  228. // hook onto page's mouse events
  229. window.onload = function() {
  230.   document.addEventListener("mousedown", mouseDown);
  231.   document.addEventListener("mouseup", mouseUp);
  232. }
  233.  
  234. // add the mascot to the page
  235. document.body.appendChild(mascotImg);
  236. document.body.appendChild(mascotSettings);
  237.  
Add Comment
Please, Sign In to add comment