Duolingo input language switcher

This script allows you to type letters appropriate for current task without changing keyboard's layout

当前为 2018-06-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Duolingo input language switcher
  3. // @namespace https://www.duolingo.com/IVrL9
  4. // @author T1mL3arn
  5. // @match https://www.duolingo.com/*
  6. // @match https://www.example.com/*
  7. // @match https://example.com/*
  8. // @version 1.4.1
  9. // @description This script allows you to type letters appropriate for current task without changing keyboard's layout
  10. // @run-at document-start
  11. // @grant none
  12. // @license GPLv3
  13. // @homepageURL https://github.com/T1mL3arn/Duolingo-input-language-switcher
  14. // @supportURL https://greasyfork.org/en/scripts/37693-duolingo-input-language-switcher/feedback
  15. // ==/UserScript==/// Generated by Haxe 3.4.7
  16. (function () { "use strict";
  17. var HxOverrides = function() { };
  18. HxOverrides.substr = function(s,pos,len) {
  19. if(len == null) {
  20. len = s.length;
  21. } else if(len < 0) {
  22. if(pos == 0) {
  23. len = s.length + len;
  24. } else {
  25. return "";
  26. }
  27. }
  28. return s.substr(pos,len);
  29. };
  30. var Main = function() {
  31. this.document = window.document;
  32. this.console = { };
  33. this.initLanguages();
  34. if(this.document.readyState == "interactive" || this.document.readyState == "complete") {
  35. this.onready();
  36. } else {
  37. this.document.addEventListener("DOMContentLoaded",$bind(this,this.onready));
  38. }
  39. };
  40. Main.main = function() {
  41. new Main();
  42. };
  43. Main.prototype = {
  44. initLanguages: function() {
  45. this.keyCodes = ["Backquote","Digit1","Digit2","Digit3","Digit4","Digit5","Digit6","Digit7","Digit8","Digit9","Digit0","Minus","Equal","Backslash","KeyQ","KeyW","KeyE","KeyR","KeyT","KeyY","KeyU","KeyI","KeyO","KeyP","BracketLeft","BracketRight","KeyA","KeyS","KeyD","KeyF","KeyG","KeyH","KeyJ","KeyK","KeyL","Semicolon","Quote","KeyZ","KeyX","KeyC","KeyV","KeyB","KeyN","KeyM","Comma","Period","Slash"];
  46. this.languages = { };
  47. this.languages.ru = "ё1234567890-=\\йцукенгшщзхъфывапролджэячсмитьбю.Ё!\"№;%:?*()_+/ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,";
  48. this.languages.en = "`1234567890-=\\qwertyuiop[]asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+|QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?";
  49. var len = this.languages.ru.length;
  50. var _g = 0;
  51. var _g1 = Reflect.fields(this.languages);
  52. while(_g < _g1.length) {
  53. var f = _g1[_g];
  54. ++_g;
  55. var act = this.languages[f].length;
  56. if(act != len) {
  57. this.console.error("LangString test failed: expected len " + len + "; actual len " + act + "; lang name " + f);
  58. this.console.error(this.languages[f]);
  59. return;
  60. }
  61. if(act != this.keyCodes.length * 2) {
  62. this.console.error("KeyCodes and LangString test failed: expected lang string len " + this.keyCodes.length * 2 + "; actual len " + act + "; lang name " + f);
  63. return;
  64. }
  65. }
  66. }
  67. ,onready: function(e) {
  68. this.document.removeEventListener("DOMContentLoaded",$bind(this,this.onready));
  69. this.console.log("Duolingo input switcher is ready");
  70. window.document.body.addEventListener("keypress",$bind(this,this.onKeyPress));
  71. window.document.body.addEventListener("keydown",$bind(this,this.refocus));
  72. }
  73. ,onKeyPress: function(e) {
  74. if(e.ctrlKey) {
  75. return;
  76. }
  77. var sourceElt = e.target;
  78. if(this.isInput(sourceElt)) {
  79. var challengeType = sourceElt.dataset.test;
  80. switch(challengeType) {
  81. case "challenge-listen-input":case "challenge-listentap-input":case "challenge-name-input":
  82. this.setLanguagePair("en","ru");
  83. break;
  84. case "challenge-translate-input":
  85. this.nativeLanguage = "ru";
  86. this.foreignLanguage = "en";
  87. var lang = sourceElt.getAttribute("lang");
  88. if(lang == this.nativeLanguage) {
  89. this.setLanguagePair("ru","en");
  90. } else if(lang == this.foreignLanguage) {
  91. this.setLanguagePair("en","ru");
  92. }
  93. break;
  94. default:
  95. return;
  96. }
  97. var targetLangStr = this.languages[this.targetLanguage];
  98. var keyCodeInd = this.keyCodes.indexOf(e.code);
  99. if(keyCodeInd != -1) {
  100. var targetChar = e.shiftKey ? targetLangStr.charAt(keyCodeInd + this.keyCodes.length) : targetLangStr.charAt(keyCodeInd);
  101. var input = sourceElt;
  102. window.setTimeout($bind(this,this.replaceChar),1,input,targetChar,input.selectionStart);
  103. }
  104. }
  105. }
  106. ,isInput: function(elt) {
  107. if(elt.tagName != "TEXTAREA") {
  108. if(elt.tagName == "INPUT") {
  109. return elt.getAttribute("type") == "text";
  110. } else {
  111. return false;
  112. }
  113. } else {
  114. return true;
  115. }
  116. }
  117. ,setLanguagePair: function(target,source) {
  118. this.targetLanguage = target;
  119. this.sourceLanguage = source;
  120. }
  121. ,refocus: function(e) {
  122. if(this.isInput(e.target)) {
  123. if(e.keyCode == 13 || e.code == "Enter") {
  124. e.target.blur();
  125. }
  126. }
  127. }
  128. ,replaceChar: function(target,newChar,position) {
  129. var val = target.value;
  130. val = val.substring(0,position) + newChar + HxOverrides.substr(val,position + 1,null);
  131. target.innerText = val;
  132. target.value = val;
  133. target.setSelectionRange(position + 1,position + 1);
  134. }
  135. };
  136. var Reflect = function() { };
  137. Reflect.fields = function(o) {
  138. var a = [];
  139. if(o != null) {
  140. var hasOwnProperty = Object.prototype.hasOwnProperty;
  141. for( var f in o ) {
  142. if(f != "__id__" && f != "hx__closures__" && hasOwnProperty.call(o,f)) {
  143. a.push(f);
  144. }
  145. }
  146. }
  147. return a;
  148. };
  149. var $_, $fid = 0;
  150. function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $fid++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; o.hx__closures__[m.__id__] = f; } return f; }
  151. Main.main();
  152. })();