1
1

KeyHandler.ts 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /// <reference path="../Controls.ts" />
  2. /// <reference path="../Classes/StoredMemory.ts" />
  3. /// <reference path="../../Elements/Elements.ts" />
  4. interface KeyCode {
  5. evCode : string;
  6. representation : string;
  7. name : string;
  8. }
  9. module Controls.KeyHandler {
  10. let promiseStack : Array<(value?: KeyCode | PromiseLike<KeyCode>) => void> = [];
  11. let promiseOriginalStack : Array<Promise<KeyCode>> = [];
  12. export function rejectPromise (promise : (value?: KeyCode | PromiseLike<KeyCode>) => void) {
  13. promiseStack.splice(promiseStack.indexOf(promise), 1);
  14. promiseOriginalStack.splice(promiseStack.indexOf(promise), 1);
  15. }
  16. export function createKeyCode (ev : KeyboardEvent) {
  17. let name = ev.key.toUpperCase();
  18. let representation = name;
  19. let evCode = ev.code;
  20. if (ev.shiftKey) {
  21. name = "Shift + " + name;
  22. evCode = "Sh" + evCode;
  23. representation = "S" + representation;
  24. }
  25. if (ev.altKey) {
  26. name = "Alt + " + name;
  27. evCode = "Al" + evCode;
  28. representation = "A" + representation;
  29. }
  30. if (ev.ctrlKey) {
  31. name = "Control + " + name;
  32. evCode = "Ct" + evCode;
  33. representation = "C" + representation;
  34. }
  35. let keyCode : KeyCode = {
  36. evCode : evCode,
  37. name : name,
  38. representation : representation
  39. };
  40. return keyCode;
  41. }
  42. window.addEventListener("mousedown", function (event) {
  43. let keyCode : KeyCode = {
  44. representation : "Click",
  45. evCode : "Click",
  46. name : "Click"
  47. };
  48. let promise = promiseStack.shift();
  49. if (promise != undefined) {
  50. promise(keyCode);
  51. promiseOriginalStack.shift();
  52. return;
  53. }
  54. });
  55. window.addEventListener("keydown", function (event) {
  56. //event.preventDefault(); This fucks up browser control. Let's just assume that this is always going to be the last thing to catch a key.
  57. let keyCode = createKeyCode(event);
  58. let promise = promiseStack.shift();
  59. if (promise != undefined) {
  60. promise(keyCode);
  61. promiseOriginalStack.shift();
  62. return;
  63. }
  64. if (keyCode.evCode == scrollKeyCode.getValue().evCode) {
  65. Elements.CurrentTurnHandler.scrollSpace();
  66. return;
  67. } else if (keyCode.evCode == imageKeyCode.getValue().evCode) {
  68. if (SayImage.imageViewer.style.display == "block") {
  69. SayImage.imageViewer.style.display = "none";
  70. } else {
  71. let images = Elements.CurrentTurnHandler.currentTurnTab.getElementsByClassName("contentImage");
  72. if (images.length > 0) {
  73. (<HTMLElement> images[images.length - 1]).click();
  74. }
  75. }
  76. return;
  77. }
  78. let ele;
  79. Elements.getLinkElements().some((element : HTMLElement) => {
  80. let keyables = element.getElementsByClassName("keyable");
  81. for (let i = 0; i < keyables.length; i++) {
  82. if ((<HTMLElement> keyables[i]).dataset['shortcutcode'] == keyCode.evCode) {
  83. ele = keyables[i];
  84. return true;
  85. }
  86. }
  87. return false;
  88. });
  89. if (ele != undefined) {
  90. ele.click();
  91. }
  92. });
  93. export function createKeyCodes (codes : Array<string>, keys : Array<string>, mods? : Array<boolean>) {
  94. let arr = [];
  95. for (let mod = 0; mod < 4; mod++) {
  96. if (mod == 0 || mods[mod] == true) {
  97. for (let i = 0; i < codes.length; i++) {
  98. let name = keys[i];
  99. let representation = keys[i];
  100. let evCode = codes[i];
  101. if (mod == 1) {
  102. name = "Shift + " + name;
  103. evCode = "Sh" + evCode;
  104. representation = "S" + representation;
  105. }
  106. if (mod == 2) {
  107. name = "Alt + " + name;
  108. evCode = "Al" + evCode;
  109. representation = "A" + representation;
  110. }
  111. if (mod == 3) {
  112. name = "Control + " + name;
  113. evCode = "Ct" + evCode;
  114. representation = "C" + representation;
  115. }
  116. let keyCode: KeyCode = {
  117. evCode: evCode,
  118. representation: representation,
  119. name : name
  120. };
  121. arr.push(keyCode);
  122. }
  123. }
  124. }
  125. return arr;
  126. }
  127. export var scrollKeyCode = new StoredMemory("scrollKeyCode", <KeyCode> {
  128. evCode : "Space",
  129. representation : "Space"
  130. });
  131. export var imageKeyCode = new StoredMemory("imageKeyCode", <KeyCode> {
  132. evCode : "KeyI",
  133. representation : "I"
  134. });
  135. export var keyCodes1 = new StoredMemory(
  136. "keyCodesRoom",
  137. createKeyCodes( ["Digit1", "Digit2", "Digit3", "Digit4", "Digit5"],
  138. ["1", "2", "3", "4", "5"],
  139. [true, true, true, true])
  140. );
  141. export var keyCodes2 = new StoredMemory(
  142. "keyCodesActions",
  143. createKeyCodes( ["KeyQ", "KeyW", "KeyE", "KeyR", "KeyT"],
  144. ["Q", "W", "E", "R", "T"],
  145. [true, true, true, true])
  146. );
  147. export var keyCodes3 = new StoredMemory(
  148. "keyCodesGlobal",
  149. createKeyCodes( ["KeyF", "KeyV", "KeyG", "KeyB"],
  150. ["F", "V", "G", "B"],
  151. [true, true, true, true])
  152. );
  153. export var keyCodeNorth = new StoredMemory(
  154. "keyCodeNorth",
  155. <KeyCode> {
  156. evCode : "KeyS",
  157. representation : "S"
  158. }
  159. );
  160. export var keyCodeEast = new StoredMemory(
  161. "keyCodeEast",
  162. <KeyCode> {
  163. evCode : "KeyC",
  164. representation : "C"
  165. }
  166. );
  167. export var keyCodeSouth = new StoredMemory(
  168. "keyCodeSouth",
  169. <KeyCode> {
  170. evCode : "KeyX",
  171. representation : "X"
  172. }
  173. );
  174. export var keyCodeWest = new StoredMemory(
  175. "keyCodeWest",
  176. <KeyCode> {
  177. evCode : "KeyZ",
  178. representation : "Z"
  179. }
  180. );
  181. export var keyCodeUp = new StoredMemory(
  182. "keyCodeUp",
  183. <KeyCode> {
  184. evCode : "KeyA",
  185. representation : "A"
  186. }
  187. );
  188. export var keyCodeDown = new StoredMemory(
  189. "keyCodeDown",
  190. <KeyCode> {
  191. evCode : "KeyD",
  192. representation : "D"
  193. }
  194. );
  195. // TODO: Make this safer by creating it using Room.DIRECTIONS.
  196. var directionCodeByIndex = [keyCodeNorth, undefined, keyCodeEast, undefined,
  197. keyCodeSouth, undefined, keyCodeWest, undefined, keyCodeUp, keyCodeDown];
  198. export function getDirectionCode (direction : Direction) {
  199. return getDirectionCodeByIndex(Room.DIRECTIONS.indexOf(direction));
  200. }
  201. export function getDirectionCodeByIndex (index : number) {
  202. return directionCodeByIndex[index].getValue();
  203. }
  204. export var available1 : Array<KeyCode> = [];
  205. export var available2 : Array<KeyCode> = [];
  206. export var available3 : Array<KeyCode> = [];
  207. export function reset () {
  208. available1 = keyCodes1.getValue().slice();
  209. available2 = keyCodes2.getValue().slice();
  210. available3 = keyCodes3.getValue().slice();
  211. }
  212. let showKeys = new StoredMemory("ShowKeys", !Elements.isMobile);
  213. export function applyCode (element : HTMLElement, code : KeyCode) {
  214. if (code == undefined) {
  215. delete(element.dataset['shortcut']);
  216. delete(element.dataset['shortcutcode']);
  217. element.classList.remove("keyable");
  218. } else {
  219. element.dataset['shortcutcode'] = code.evCode;
  220. if (showKeys.getValue()) {
  221. element.dataset['shortcut'] = code.representation;
  222. }
  223. element.classList.add("keyable");
  224. }
  225. }
  226. export function getFirstKeyCode () {
  227. let chosen = available1.length > 0 ? available1 :
  228. available2.length > 0 ? available2 :
  229. available3.length > 0 ? available3 : undefined;
  230. if (chosen != undefined) {
  231. return chosen.shift();
  232. }
  233. return undefined;
  234. }
  235. export function getSecondKeyCode () {
  236. let chosen = available2.length > 0 ? available2 :
  237. available3.length > 0 ? available3 : undefined;
  238. if (chosen != undefined) {
  239. return chosen.splice(0, 1)[0];
  240. }
  241. return undefined;
  242. }
  243. export function getThirdKeyCode () {
  244. let chosen = available3.length > 0 ? available3 : undefined;
  245. if (chosen != undefined) {
  246. return chosen.splice(0, 1)[0];
  247. }
  248. return undefined;
  249. }
  250. /**
  251. * Returns a promise of a key press.
  252. * If after timeout seconds a key was not pressed, the promise fails.
  253. * @param {number} timeout
  254. */
  255. export function getNextKey (timeout? : number) : Promise<KeyCode> {
  256. let timeoutNumber;
  257. let promise = <Promise<KeyCode>> (new Promise((resolve, reject) => {
  258. promiseStack.push(resolve);
  259. if (timeout != undefined) {
  260. timeoutNumber = setTimeout(() => {
  261. KeyHandler.rejectPromise(resolve);
  262. reject();
  263. }, timeout * 1000);
  264. }
  265. }));
  266. promise.then(() => {
  267. clearTimeout(timeoutNumber);
  268. });
  269. return promise;
  270. }
  271. export function stopGivingNextKey (originalPromise : Promise<KeyCode>) {
  272. let index = promiseOriginalStack.indexOf(originalPromise);
  273. if (index != -1) {
  274. rejectPromise(promiseStack[index]);
  275. }
  276. }
  277. }