Auto Scroll Mouse [fork]

No mousewheel? No problem! This script will scroll the page if you place your mouse near the top or bottom of the window and wiggle it.

  1. // ==UserScript==
  2. // @name Auto Scroll Mouse [fork]
  3. // @namespace http://www.marcbelmont.com
  4. // @description No mousewheel? No problem! This script will scroll the page if you place your mouse near the top or bottom of the window and wiggle it.
  5. // @version 2.1.10
  6. // @license ISC
  7. // @include http://*/*
  8. // @include https://*/*
  9. // @grant GM_addStyle
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. // Originally "Auto Scroll!" by Marc Belmont on userscripts.org
  14. // Tweaked by joeytwiddle
  15.  
  16. // TODO: Do not scroll after/during a mousedown (so it won't interfere when dragging/selecting)
  17. // BUG: Does not trigger when mouse is over an iframe (window does not receive the mousemove event)
  18. // We could solve this by listening for mousemove events on the region divs instead of on the document.
  19. // But that could be more disruptive, as it prevents events from reaching the window like they normally would.
  20.  
  21. //////////////////////
  22. // Constants //
  23. //////////////////////
  24.  
  25. // Which key should be held to enable scrolling. Possible values are 0 | 1
  26. // Enable more than one to require a combination be held.
  27. var ONLY_WHEN_HOLDING_SHIFT = 0;
  28. var ONLY_WHEN_HOLDING_CTRL = 0;
  29. var ONLY_WHEN_HOLDING_ALT = 0;
  30.  
  31. var NOSCROLL_PERCENT = 80; // Area in the middle of the page where there won't be scrolling
  32. var SCROLLSTEP = 5; // Scrolling speed
  33. var ONLYLEFTRIGHT = 1; // Scrolling will happen only when you move left or right in the top or bottom areas. Possible values are 0 | 1
  34. var ONLYLEFTRIGHT_MOUSESPEED = 1.5; // Acceleration
  35. var ONLYLEFTRIGHT_DONTSCROLL = 100; // if no event for too long, no scrolling
  36. var DELAY_TIME = 5; // This tries to reduce the number of scroll operations, to reduce load on the browser
  37. var SHOW_ACTIVE_REGION = 1;
  38.  
  39. //////////////////////
  40. // Some Code //
  41. //////////////////////
  42.  
  43. var _mX = 0;
  44. var _mXOld = 0;
  45. var _mYOld = 0;
  46. var _mY = 0;
  47. var _go = 0;
  48. var _mNow = new Date();
  49. var _mThen = new Date();
  50.  
  51. // 2. scroll the window
  52. function ScrollWindow() {
  53. // don't scroll if we're in the middle of the page
  54. var end = ((_mY - window.pageYOffset) - window.innerHeight/2);
  55. if (Math.abs(end) < window.innerHeight*NOSCROLL_PERCENT/200) {
  56. regionUI.hideRegions();
  57. return;
  58. }
  59. /* var down = (_mY - window.pageYOffset) / window.innerHeight;
  60. if (Math.abs(down - 0.5)*2 < NOSCROLL_PERCENT/100) {
  61. return;
  62. } */
  63.  
  64. // if ONLYLEFTRIGHT is on, scroll only when you move left or right,
  65. //if (ONLYLEFTRIGHT && (Math.abs(_mY - _mYOld) > 2)) {
  66. // return;
  67. //}
  68. // if you want scrolling, mouse have to go start moving slowly
  69. if (Math.abs(_mY - _mYOld) < 7 && Math.abs(_mX - _mXOld) < 7)
  70. _go = 1;
  71.  
  72.  
  73. // scroll the page
  74. var way = end > 0 ? 1 : -1;
  75. var val = SCROLLSTEP;
  76. if (ONLYLEFTRIGHT) {
  77. if (_go) {
  78. val = Math.pow(Math.abs(_mX - _mXOld), ONLYLEFTRIGHT_MOUSESPEED);
  79. } else {
  80. val = 0;
  81. }
  82. }
  83. if (val != 0) {
  84. window.scrollTo(window.pageXOffset, window.pageYOffset + val*way);
  85. }
  86. if (ONLYLEFTRIGHT && SHOW_ACTIVE_REGION /*&& val != 0*/) {
  87. if (end > 0) {
  88. regionUI.showBottomRegion();
  89. } else {
  90. regionUI.showTopRegion();
  91. }
  92. }
  93. }
  94.  
  95. function maybe(scrollWindow) {
  96. var timer;
  97. return function(){
  98. if (!timer) {
  99. timer = setTimeout(function(){
  100. timer = null;
  101. scrollWindow();
  102. _mXOld = _mX;
  103. _mYOld = _mY;
  104. _mThen = _mNow;
  105. }, DELAY_TIME);
  106. }
  107. };
  108. }
  109.  
  110. var maybeScrollWindow = maybe(ScrollWindow);
  111.  
  112. // 1. Catch mouse movement
  113. document.addEventListener('mousemove', mousemove, true);
  114. function mousemove(e)
  115. {
  116. // get mouse pos and the date
  117. if (!e)
  118. e = window.event || window.Event;
  119. if('undefined'!=typeof e.pageX) {
  120. _mX = e.pageX;
  121. _mY = e.pageY;
  122. } else {
  123. _mX = e.clientX + document.body.scrollLeft;
  124. _mY = e.clientY + document.body.scrollTop;
  125. }
  126. _mNow = Date.now();
  127.  
  128. // Hack to avoid unwanted scrolling when the mouse enters a window
  129. // if no event for too long, no scrolling
  130. if (_mNow - _mThen > ONLYLEFTRIGHT_DONTSCROLL)
  131. _go = 0;
  132.  
  133. if (ONLY_WHEN_HOLDING_SHIFT && !e.shiftKey) return;
  134. if (ONLY_WHEN_HOLDING_CTRL && !e.ctrlKey) return;
  135. if (ONLY_WHEN_HOLDING_ALT && !e.altKey) return;
  136.  
  137. // Scroll the window
  138. maybeScrollWindow();
  139. }
  140.  
  141. var regionUI = (function() {
  142. var FADE_IN_DURATION = 300;
  143.  
  144. var topRegion = null;
  145. var bottomRegion = null;
  146.  
  147. function ensureRegionsExist() {
  148. if (!bottomRegion) {
  149. topRegion = document.createElement('div');
  150. topRegion.className = 'ASM_region';
  151. topRegion.style.top = 0;
  152. topRegion.style.width = '100%';
  153. topRegion.style.height = (100 - NOSCROLL_PERCENT) / 2 + '%';
  154. document.body.appendChild(topRegion);
  155. bottomRegion = document.createElement('div');
  156. bottomRegion.className = 'ASM_region';
  157. bottomRegion.style.bottom = 0;
  158. bottomRegion.style.width = '100%';
  159. bottomRegion.style.height = (100 - NOSCROLL_PERCENT) / 2 + '%';
  160. document.body.appendChild(bottomRegion);
  161. GM_addStyle(`
  162. .ASM_region {
  163. position: fixed;
  164. z-index: 99999999;
  165. background: #09c4;
  166. pointer-events: none;
  167. transition: opacity 0.3s 0s;
  168. opacity: 0;
  169. }
  170. .ASM_region.ASM_show {
  171. display: block;
  172. transition: opacity ${FADE_IN_DURATION}ms;
  173. opacity: 1;
  174. }
  175. `);
  176. }
  177. }
  178.  
  179. function showRegion(regionElement) {
  180. regionElement.classList.add('ASM_show');
  181. //regionElement.offsetWidth;
  182. // We need to wait long enough for the new state to fade in before we remove the class.
  183. //setTimeout(() => {
  184. // regionElement.classList.remove('ASM_show');
  185. //}, FADE_IN_DURATION);
  186. }
  187.  
  188. function showTopRegion() {
  189. ensureRegionsExist();
  190. showRegion(topRegion);
  191. }
  192.  
  193. function showBottomRegion() {
  194. ensureRegionsExist();
  195. showRegion(bottomRegion);
  196. }
  197.  
  198. function hideRegions() {
  199. topRegion.classList.remove('ASM_show');
  200. bottomRegion.classList.remove('ASM_show');
  201. }
  202.  
  203. return {
  204. ensureRegionsExist: ensureRegionsExist,
  205. showTopRegion: showTopRegion,
  206. showBottomRegion: showBottomRegion,
  207. hideRegions: hideRegions,
  208. };
  209. }());
  210.  
  211. if (SHOW_ACTIVE_REGION) {
  212. // It's good to create them at the start, otherwise the first animation won't fade in (because the region will be given the 'ASM_show' class on the same tick that it was created).
  213. document.addEventListener('DOMContentLoaded', function() {
  214. regionUI.ensureRegionsExist();
  215. });
  216. }