Duolingo input language switcher

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

当前为 2020-04-21 提交的版本,查看 最新版本

  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. // @version 2.0.2
  7. // @description This script allows you to type letters appropriate for current task without changing keyboard's layout
  8. // @run-at document-start
  9. // @grant none
  10. // @icon https://www.androidpolice.com/wp-content/uploads/2014/03/nexusae0_Duolingo-Thumb.png
  11. // @license GPLv3
  12. // @homepageURL https://github.com/T1mL3arn/Duolingo-input-language-switcher
  13. // @supportURL https://greasyfork.org/en/scripts/37693-duolingo-input-language-switcher/feedback
  14. // ==/UserScript==
  15.  
  16. // Generated by Haxe 4.0.5
  17. (function ($global) { "use strict";
  18. var Main = function() {
  19. this.document = window.document;
  20. this.console = window.console;
  21. this.initLanguages();
  22. if(this.document.readyState == "interactive" || this.document.readyState == "complete") {
  23. this.onready();
  24. } else {
  25. this.document.addEventListener("DOMContentLoaded",$bind(this,this.onready));
  26. }
  27. };
  28. Main.main = function() {
  29. new Main();
  30. };
  31. Main.prototype = {
  32. initLanguages: function() {
  33. 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"];
  34. this.languages = { };
  35. this.languages.ru = "ё1234567890-=\\йцукенгшщзхъфывапролджэячсмитьбю.Ё!\"№;%:?*()_+/ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,";
  36. this.languages.en = "`1234567890-=\\qwertyuiop[]asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+|QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?";
  37. var len = this.languages.ru.length;
  38. var _g = 0;
  39. var _g1 = Reflect.fields(this.languages);
  40. while(_g < _g1.length) {
  41. var f = _g1[_g];
  42. ++_g;
  43. var act = this.languages[f].length;
  44. if(act != len) {
  45. this.console.error("LangString test failed: expected len " + len + "; actual len " + act + "; lang name " + f);
  46. this.console.error(this.languages[f]);
  47. return;
  48. }
  49. if(act != this.keyCodes.length * 2) {
  50. this.console.error("KeyCodes and LangString test failed: expected lang string len " + this.keyCodes.length * 2 + "; actual len " + act + "; lang name " + f);
  51. return;
  52. }
  53. }
  54. }
  55. ,onready: function(e) {
  56. this.document.removeEventListener("DOMContentLoaded",$bind(this,this.onready));
  57. this.console.log("Duolingo input switcher is ready");
  58. window.document.body.addEventListener("keydown",$bind(this,this.onKeyDown));
  59. }
  60. ,onKeyDown: function(e) {
  61. if(e.ctrlKey) {
  62. return;
  63. }
  64. var pressedKeyCodeIndex = this.keyCodes.indexOf(e.code);
  65. if(pressedKeyCodeIndex == -1) {
  66. return;
  67. }
  68. var inputElt = e.target;
  69. switch(inputElt.dataset.test) {
  70. case "challenge-listen-input":case "challenge-listentap-input":case "challenge-name-input":
  71. this.setLanguagePair("en","ru");
  72. break;
  73. case "challenge-text-input":
  74. this.setLanguagePair("en","ru");
  75. break;
  76. case "challenge-translate-input":
  77. this.nativeLanguage = "ru";
  78. this.foreignLanguage = "en";
  79. var lang = inputElt.getAttribute("lang");
  80. if(lang == this.nativeLanguage) {
  81. this.setLanguagePair("ru","en");
  82. } else if(lang == this.foreignLanguage) {
  83. this.setLanguagePair("en","ru");
  84. }
  85. break;
  86. default:
  87. return;
  88. }
  89. e.preventDefault();
  90. this.replaceLetter(this.getLanguageLetter(this.targetLanguage,pressedKeyCodeIndex,e.shiftKey),inputElt);
  91. this.callReactOnChange(inputElt);
  92. }
  93. ,setLanguagePair: function(target,source) {
  94. this.targetLanguage = target;
  95. this.sourceLanguage = source;
  96. }
  97. ,getLanguageLetter: function(language,letterIndex,isUppercase) {
  98. var letters = this.languages[language];
  99. if(isUppercase) {
  100. return letters.charAt(letterIndex + this.keyCodes.length);
  101. } else {
  102. return letters.charAt(letterIndex);
  103. }
  104. }
  105. ,replaceLetter: function(letter,inputElt) {
  106. var start = inputElt.selectionStart;
  107. var end = inputElt.selectionEnd;
  108. var phrase = inputElt.value;
  109. phrase = phrase.substring(0,start) + letter + phrase.substring(end);
  110. inputElt.value = phrase;
  111. inputElt.setSelectionRange(start + 1,start + 1);
  112. }
  113. ,callReactOnChange: function(elt) {
  114. var _g = 0;
  115. var _g1 = Reflect.fields(elt);
  116. while(_g < _g1.length) {
  117. var fieldName = _g1[_g];
  118. ++_g;
  119. if(fieldName.indexOf("__reactEventHandlers") != -1) {
  120. Reflect.field(elt,fieldName).onChange({ target : elt});
  121. }
  122. }
  123. }
  124. };
  125. var Reflect = function() { };
  126. Reflect.field = function(o,field) {
  127. try {
  128. return o[field];
  129. } catch( e ) {
  130. return null;
  131. }
  132. };
  133. Reflect.fields = function(o) {
  134. var a = [];
  135. if(o != null) {
  136. var hasOwnProperty = Object.prototype.hasOwnProperty;
  137. for( var f in o ) {
  138. if(f != "__id__" && f != "hx__closures__" && hasOwnProperty.call(o,f)) {
  139. a.push(f);
  140. }
  141. }
  142. }
  143. return a;
  144. };
  145. var $_;
  146. function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $global.$haxeUID++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = m.bind(o); o.hx__closures__[m.__id__] = f; } return f; }
  147. $global.$haxeUID |= 0;
  148. Main.main();
  149. })(typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this);