Pr0gramm Joystick Controls

Enables joystick controls for pr0gramm.

当前为 2014-07-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Pr0gramm Joystick Controls
  3. // @namespace http://skipcast.net
  4. // @version 0.21
  5. // @description Enables joystick controls for pr0gramm.
  6. // @match *pr0gramm.com/*
  7. // @copyright 2014+, Jonathan Lindahl
  8. // ==/UserScript==
  9.  
  10. /*
  11. * Controls:
  12. * DPad Left = Previous Image.
  13. * DPad Right = Next Image.
  14. * DPad Up/Down = Scroll up/down the page.
  15. * L1 + R1 = Reload page to latest entries.
  16. * Y = Toggle mode.
  17. *
  18. * Scroll mode:
  19. * Left stick = Scroll up/down the page with better accuracy.
  20. * Right stick = Scroll up/down the page faster combined with left stick.
  21. *
  22. * Mouse mode:
  23. * Left stick = Scroll up/down the page.
  24. * Right stick: Move mouse.
  25. * X: Click.
  26. * B: Back.
  27. * */
  28.  
  29. // Use this to get button indices: http://www.html5rocks.com/en/tutorials/doodles/gamepad/gamepad-tester/tester.html
  30. var BTN_X = 0;
  31. var BTN_B = 1;
  32. var BTN_Y = 3;
  33. var BTN_TAB_LEFT = 4;
  34. var BTN_TAB_RIGHT = 5;
  35. var BTN_UP = 12;
  36. var BTN_DOWN = 13;
  37. var BTN_LEFT = 14;
  38. var BTN_RIGHT = 15;
  39. var SCROLL_SPEED = 15;
  40. var MOUSE_SPEED = 20;
  41.  
  42. var oldLeft = false;
  43. var oldRight = false;
  44. var oldX = false;
  45. var oldY = false;
  46. var oldB = false;
  47.  
  48. var State = {
  49. scroll: 0,
  50. mouse: 1
  51. };
  52.  
  53. var currentState = State.scroll;
  54. var cursorNode = null;
  55. var overlayNode = null;
  56. var mousePosition = [0.5, 0.5];
  57. var mouseHotzone = [0, 0];
  58.  
  59. function scrollUp(multiplier)
  60. {
  61. var top = $("body").scrollTop();
  62. $("body").scrollTop(top - (SCROLL_SPEED * multiplier));
  63. }
  64.  
  65. function scrollDown(multiplier)
  66. {
  67. var top = $("body").scrollTop();
  68. $("body").scrollTop(top + (SCROLL_SPEED * multiplier));
  69. }
  70.  
  71. function scrollLeft()
  72. {
  73. var streamPrevNode = $("#stream-prev");
  74. if (window.location.pathname != "/")
  75. streamPrevNode.click();
  76. }
  77.  
  78. function scrollRight()
  79. {
  80. var streamNextNode = $("#stream-next");
  81. if (window.location.pathname != "/")
  82. {
  83. try
  84. {
  85. streamNextNode.click();
  86. }
  87. catch (error) {}
  88. }
  89. else
  90. {
  91. $(".stream-row a img").first().click();
  92. }
  93. }
  94.  
  95. function pollJoystickInput()
  96. {
  97. var gamepads = navigator.getGamepads();
  98. for(var i = 0; i < gamepads.length; ++i)
  99. {
  100. var gamepad = gamepads.item(i);
  101. if (gamepad != null)
  102. {
  103. var buttons = gamepad.buttons;
  104. var axes = gamepad.axes;
  105. var upKey = buttons[BTN_UP];
  106. var downKey = buttons[BTN_DOWN];
  107. var leftKey = buttons[BTN_LEFT];
  108. var rightKey = buttons[BTN_RIGHT];
  109. var tabLeft = buttons[BTN_TAB_LEFT];
  110. var tabRight = buttons[BTN_TAB_RIGHT];
  111. var yKey = buttons[BTN_Y];
  112. var xKey = buttons[BTN_X];
  113. var bKey = buttons[BTN_B];
  114. if (leftKey.pressed && !oldLeft)
  115. {
  116. scrollLeft();
  117. }
  118. else if (rightKey.pressed && !oldRight)
  119. {
  120. scrollRight();
  121. }
  122. if (upKey.pressed)
  123. {
  124. scrollUp(1);
  125. }
  126. if (downKey.pressed)
  127. {
  128. scrollDown(1);
  129. }
  130. if (Math.abs(axes[0]) > 0.01 || Math.abs(axes[1]) > 0.01 || Math.abs(axes[2]) > 0.01 || Math.abs(axes[3]) > 0.01)
  131. {
  132. var multiplier = axes[3];
  133. if (currentState == State.scroll)
  134. multiplier += axes[1];
  135. if (Math.abs(multiplier) > 1)
  136. multiplier *= (Math.abs(multiplier) - 1) + 1;
  137. if (currentState == State.mouse)
  138. {
  139. moveMouse(axes[0] * MOUSE_SPEED, axes[1] * MOUSE_SPEED);
  140. }
  141. scrollDown(multiplier);
  142. }
  143. if (tabLeft.pressed && tabRight.pressed)
  144. {
  145. window.location.href = "/";
  146. }
  147. if (yKey.pressed && !oldY)
  148. {
  149. toggleState();
  150. }
  151. if (bKey.pressed && !oldB)
  152. {
  153. if (window.location.pathname != "/")
  154. window.history.back();
  155. else
  156. window.location.reload();
  157. }
  158. if (currentState == State.mouse && xKey.pressed && !oldX)
  159. {
  160. var mousePos = getFixedMousePos();
  161. cursorNode.hide(); // Prevent elementFromPoint from getting cursor element.
  162. var elmAtMouse = document.elementFromPoint(mousePos[0] + mouseHotzone[0], mousePos[1] + mouseHotzone[1]);
  163. cursorNode.show();
  164. $(elmAtMouse).click();
  165. }
  166. oldLeft = leftKey.pressed;
  167. oldRight = rightKey.pressed;
  168. oldY = yKey.pressed;
  169. oldX = xKey.pressed;
  170. oldB = bKey.pressed;
  171. }
  172. }
  173. requestAnimationFrame(pollJoystickInput);
  174. }
  175.  
  176. requestAnimationFrame(pollJoystickInput);
  177.  
  178. var overlayTimeout = null;
  179. function alertOverlay(message)
  180. {
  181. if (overlayTimeout != null)
  182. clearTimeout(overlayTimeout);
  183. $("#joystickOverlay").html(message);
  184. $("#joystickOverlay").stop().fadeIn(50, function()
  185. {
  186. overlayTimeout = setTimeout(function()
  187. {
  188. $("#joystickOverlay").fadeOut(200);
  189. }, 1250);
  190. });
  191. }
  192.  
  193. function toggleState(doAlert)
  194. {
  195. doAlert = doAlert != null ? doAlert : true;
  196. if (currentState == State.scroll)
  197. {
  198. $("#cursor").show();
  199. currentState = State.mouse;
  200. if (doAlert)
  201. alertOverlay("Changed mode to mouse.");
  202. }
  203. else
  204. {
  205. $("#cursor").hide();
  206. currentState = State.scroll;
  207. if (doAlert)
  208. alertOverlay("Changed mode to scroll.");
  209. }
  210. saveState();
  211. }
  212.  
  213. function saveState()
  214. {
  215. localStorage.setItem("joystick_LastState", currentState);
  216. }
  217.  
  218. function loadState()
  219. {
  220. var lastState = parseInt(localStorage.joystick_LastState);
  221. var lastMousePosX = parseFloat(sessionStorage.getItem("joystick_LastMousePosX"));
  222. var lastMousePosY = parseFloat(sessionStorage.getItem("joystick_LastMousePosY"));
  223. mousePosition[0] = isNaN(lastMousePosX) ? 0.5 : lastMousePosX;
  224. mousePosition[1] = isNaN(lastMousePosY) ? 0.5 : lastMousePosY;
  225. setMousePos();
  226. if (isNaN(lastState))
  227. {
  228. localStorage.setItem("joystick_LastState", State.scroll);
  229. }
  230. else
  231. {
  232. if (lastState == State.mouse) // Is scroll by default.
  233. toggleState(false);
  234. }
  235. }
  236.  
  237. function moveMouse(x, y)
  238. {
  239. var addX = x / window.innerWidth;
  240. var addY = y / window.innerHeight;
  241. mousePosition = [mousePosition[0] + addX, mousePosition[1] + addY];
  242. if (mousePosition[0] < 0)
  243. mousePosition[0] = 0;
  244. else if (mousePosition[0] > 1)
  245. mousePosition[0] = 1;
  246. if (mousePosition[1] < 0)
  247. mousePosition[1] = 0;
  248. else if (mousePosition[1] > 1)
  249. mousePosition[1] = 1;
  250. sessionStorage.setItem("joystick_LastMousePosX", mousePosition[0]);
  251. sessionStorage.setItem("joystick_LastMousePosY", mousePosition[1]);
  252. setMousePos();
  253. }
  254.  
  255. function setMousePos()
  256. {
  257. $("#cursor").css(
  258. {
  259. left: (window.innerWidth * mousePosition[0]) - mouseHotzone[0],
  260. top: (window.innerHeight * mousePosition[1]) - mouseHotzone[1]
  261. });
  262. }
  263.  
  264. function getFixedMousePos()
  265. {
  266. var cursorNode = $("#cursor");
  267. var pos = cursorNode.position();
  268. return [pos.left, pos.top];
  269. }
  270.  
  271. $(function()
  272. {
  273. cursorNode = $(document.createElement("div"));
  274. cursorNode.attr("id", "cursor");
  275. cursorNode.css(
  276. {
  277. backgroundImage: "url(http://i.imgur.com/asuC1of.png)", // Better way to get image? base64 strings doesn't work for some reason.
  278. position: "fixed",
  279. top: "50%",
  280. left: "50%",
  281. width: 16,
  282. height: 24,
  283. "z-index": 1000001,
  284. display: "none"
  285. });
  286. $("body").append(cursorNode);
  287. overlayNode = $(document.createElement("div"));
  288. overlayNode.attr("id", "joystickOverlay");
  289. overlayNode.css(
  290. {
  291. backgroundColor: "rgba(0, 0, 0, 0.75)",
  292. position: "fixed",
  293. left: 0,
  294. right: 0,
  295. top: 200,
  296. height: 100,
  297. "line-height": "100px",
  298. color: "#FFF",
  299. "text-align": "center",
  300. "font-size": 30,
  301. "z-index": 1000000,
  302. display: "none"
  303. });
  304. $("body").append(overlayNode);
  305. $(window).resize(function()
  306. {
  307. setMousePos();
  308. });
  309. loadState();
  310. });