Firefox Hide Scrollbars

Hide Scrollbars in Firefox

目前为 2018-07-24 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Firefox Hide Scrollbars
  3. // @namespace http://qashto.com/
  4. // @version 2.1.2
  5. // @description Hide Scrollbars in Firefox
  6. // @author qashto
  7. // @match *://*/*
  8. // @exclude *://www.youtube.com/*
  9. // @run-at document-start
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. console.log('hiding scrollbars...');
  14.  
  15. // if used as userscript add style with GM_addStyle
  16. if (typeof GM_addStyle !== 'undefined') {
  17. GM_addStyle(`
  18. :root {
  19. --scrollbar-height: 0;
  20. --scrollbar-width: 0;
  21. height: 100vh !important;
  22. overflow: hidden !important;
  23. position: relative !important;
  24. width: 100vw !important;
  25. }
  26.  
  27. :root,
  28. body {
  29. max-height: initial !important;
  30. max-width: initial !important;
  31. min-height: initial !important;
  32. min-width: initial !important;
  33. position: relative;
  34. }
  35.  
  36. body {
  37. height: calc(100vh + var(--scrollbar-height)) !important;
  38. overflow: auto !important;
  39. width: calc(100vw + var(--scrollbar-width)) !important;
  40. }
  41. `);
  42. }
  43.  
  44. /**
  45. * Compatibility with userscripts. Userscripts run in a different context to
  46. * content scripts and don't need to make structured clones to pass objects
  47. * to page scripts.
  48. */
  49. if (!exportFunction && !cloneInto) {
  50. function exportFunction(func, targetScope, options = {}) {
  51. if (options.defineAs) {
  52. targetScope[options.defineAs] = func;
  53. }
  54.  
  55. return func;
  56. }
  57.  
  58. function cloneInto(obj) {
  59. return obj;
  60. }
  61.  
  62. window.wrappedJSObject = window;
  63.  
  64.  
  65. // Userscript-specific definition of document getters/setters
  66. let documentScrollHandler;
  67. Object.defineProperties(Document.prototype, {
  68. scrollingElement: {
  69. get() {
  70. return document.body;
  71. }
  72. },
  73. onscroll: {
  74. get() {
  75. return documentScrollHandler;
  76. },
  77. set(listener) {
  78. if (documentScrollHandler) {
  79. document.body.removeEventListener("scroll", documentScrollHandler);
  80. }
  81. if (listener) {
  82. documentScrollHandler = listener;
  83. document.body.addEventListener('scroll', documentScrollHandler);
  84. }
  85. }
  86. }
  87. });
  88. } else if (browser && browser.runtime && browser.runtime.id) {
  89. /**
  90. * getters/setters cannot be passed via structured clone, so we have to inject
  91. * a script into the page context.
  92. */
  93. const scriptElement = document.createElement("script");
  94. scriptElement.src = browser.runtime.getURL("js/pageContext.js");
  95. scriptElement.addEventListener("load", () => {
  96. scriptElement.remove();
  97. });
  98.  
  99. document.documentElement.appendChild(scriptElement);
  100. }
  101.  
  102. function getScrollbarSize() {
  103. const div = document.createElement('div');
  104. div.style.visibility = 'hidden';
  105. div.style.overflow = 'scroll';
  106. document.documentElement.appendChild(div);
  107.  
  108. const scrollbarHeight = div.offsetHeight - div.clientHeight;
  109. const scrollbarWidth = div.offsetWidth - div.clientWidth;
  110.  
  111. div.remove();
  112.  
  113. return [
  114. scrollbarWidth,
  115. scrollbarHeight
  116. ];
  117. }
  118.  
  119. document.addEventListener('DOMContentLoaded', () => {
  120. const [scrollbarWidth, scrollbarHeight] = getScrollbarSize();
  121.  
  122. document.body.style.setProperty(
  123. '--scrollbar-height', `${scrollbarHeight}px`);
  124. document.body.style.setProperty(
  125. '--scrollbar-width', `${scrollbarWidth}px`);
  126.  
  127.  
  128. document.body.addEventListener('scroll', ev => {
  129. const scrollLeft = cloneInto(document.body.scrollLeft, window);
  130. const scrollTop = cloneInto(document.body.scrollTop, window);
  131.  
  132. window.wrappedJSObject.scrollX = scrollLeft;
  133. window.wrappedJSObject.pageXOffset = scrollLeft;
  134. window.wrappedJSObject.scrollY = scrollTop;
  135. window.wrappedJSObject.pageYOffset = scrollTop;
  136. });
  137.  
  138. exportFunction(document.body.scroll.bind(document.body), window, {
  139. defineAs: 'scroll'
  140. });
  141. exportFunction(document.body.scrollTo.bind(document.body), window, {
  142. defineAs: 'scrollTo'
  143. });
  144. exportFunction(document.body.scrollBy.bind(document.body), window, {
  145. defineAs: 'scrollBy'
  146. });
  147. });
  148.  
  149. function handleAddScrollEvent() {
  150. if (arguments[0] === 'scroll') {
  151. document.body.addEventListener(...arguments);
  152. return;
  153. }
  154. }
  155.  
  156. function handleRemoveScrollEvent() {
  157. if (arguments[0] === 'scroll') {
  158. document.body.removeEventListener(...arguments);
  159. return;
  160. }
  161. }
  162.  
  163.  
  164. const initial_windowAddEventListener = Window.prototype.addEventListener;
  165. const initial_windowRemoveEventListener = Window.prototype.removeEventListener;
  166. const initial_documentAddEventListener = Document.prototype.addEventListener;
  167. const initial_documentRemoveEventListener = Document.prototype.removeEventListener;
  168.  
  169. function windowAddEventListener() {
  170. handleAddScrollEvent(...arguments);
  171. initial_windowAddEventListener.apply(this, arguments);
  172. }
  173.  
  174. function windowRemoveEventListener() {
  175. handleRemoveScrollEvent(...arguments);
  176. initial_windowRemoveEventListener.apply(this, arguments);
  177. }
  178.  
  179. function documentAddEventListener() {
  180. handleAddScrollEvent(...arguments);
  181. initial_documentAddEventListener.apply(this, arguments);
  182. }
  183.  
  184. function documentRemoveEventListener() {
  185. handleRemoveScrollEvent(...arguments);
  186. initial_documentRemoveEventListener.apply(this, arguments);
  187. }
  188.  
  189. exportFunction(windowAddEventListener, Window.prototype, {
  190. defineAs: 'addEventListener'
  191. });
  192. exportFunction(windowRemoveEventListener, Window.prototype, {
  193. defineAs: 'removeEventListener'
  194. });
  195. exportFunction(documentAddEventListener, Document.prototype, {
  196. defineAs: 'addEventListener'
  197. });
  198. exportFunction(documentRemoveEventListener, Document.prototype, {
  199. defineAs: 'removeEventListener'
  200. });
  201.  
  202. console.log('scrollbars hidden!');