- // ==UserScript==
- // @name Duolingo input language switcher
- // @namespace https://www.duolingo.com/IVrL9
- // @author T1mL3arn
- // @match https://www.duolingo.com/*
- // @version 2.0.2
- // @description This script allows you to type letters appropriate for current task without changing keyboard's layout
- // @run-at document-start
- // @grant none
- // @icon https://www.androidpolice.com/wp-content/uploads/2014/03/nexusae0_Duolingo-Thumb.png
- // @license GPLv3
- // @homepageURL https://github.com/T1mL3arn/Duolingo-input-language-switcher
- // @supportURL https://greasyfork.org/en/scripts/37693-duolingo-input-language-switcher/feedback
- // ==/UserScript==/// Generated by Haxe 4.0.3
- (function ($global) { "use strict";
- var Main = function() {
- this.document = window.document;
- this.console = window.console;
- this.initLanguages();
- if(this.document.readyState == "interactive" || this.document.readyState == "complete") {
- this.onready();
- } else {
- this.document.addEventListener("DOMContentLoaded",$bind(this,this.onready));
- }
- };
- Main.main = function() {
- new Main();
- };
- Main.prototype = {
- initLanguages: function() {
- 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"];
- this.languages = { };
- this.languages.ru = "ё1234567890-=\\йцукенгшщзхъфывапролджэячсмитьбю.Ё!\"№;%:?*()_+/ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,";
- this.languages.en = "`1234567890-=\\qwertyuiop[]asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+|QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?";
- var len = this.languages.ru.length;
- var _g = 0;
- var _g1 = Reflect.fields(this.languages);
- while(_g < _g1.length) {
- var f = _g1[_g];
- ++_g;
- var act = this.languages[f].length;
- if(act != len) {
- this.console.error("LangString test failed: expected len " + len + "; actual len " + act + "; lang name " + f);
- this.console.error(this.languages[f]);
- return;
- }
- if(act != this.keyCodes.length * 2) {
- this.console.error("KeyCodes and LangString test failed: expected lang string len " + this.keyCodes.length * 2 + "; actual len " + act + "; lang name " + f);
- return;
- }
- }
- }
- ,onready: function(e) {
- this.document.removeEventListener("DOMContentLoaded",$bind(this,this.onready));
- this.console.log("Duolingo input switcher is ready");
- window.document.body.addEventListener("keydown",$bind(this,this.onKeyDown));
- }
- ,onKeyDown: function(e) {
- if(e.ctrlKey) {
- return;
- }
- var pressedKeyCodeIndex = this.keyCodes.indexOf(e.code);
- if(pressedKeyCodeIndex == -1) {
- return;
- }
- var inputElt = e.target;
- switch(inputElt.dataset.test) {
- case "challenge-listen-input":case "challenge-listentap-input":case "challenge-name-input":
- this.setLanguagePair("en","ru");
- break;
- case "challenge-text-input":
- this.setLanguagePair("en","ru");
- break;
- case "challenge-translate-input":
- this.nativeLanguage = "ru";
- this.foreignLanguage = "en";
- var lang = inputElt.getAttribute("lang");
- if(lang == this.nativeLanguage) {
- this.setLanguagePair("ru","en");
- } else if(lang == this.foreignLanguage) {
- this.setLanguagePair("en","ru");
- }
- break;
- default:
- return;
- }
- e.preventDefault();
- this.replaceLetter(this.getLanguageLetter(this.targetLanguage,pressedKeyCodeIndex,e.shiftKey),inputElt);
- this.callReactOnChange(inputElt);
- }
- ,setLanguagePair: function(target,source) {
- this.targetLanguage = target;
- this.sourceLanguage = source;
- }
- ,getLanguageLetter: function(language,letterIndex,isUppercase) {
- var letters = this.languages[language];
- if(isUppercase) {
- return letters.charAt(letterIndex + this.keyCodes.length);
- } else {
- return letters.charAt(letterIndex);
- }
- }
- ,replaceLetter: function(letter,inputElt) {
- var start = inputElt.selectionStart;
- var end = inputElt.selectionEnd;
- var phrase = inputElt.value;
- phrase = phrase.substring(0,start) + letter + phrase.substring(end);
- inputElt.value = phrase;
- inputElt.setSelectionRange(start + 1,start + 1);
- }
- ,callReactOnChange: function(elt) {
- var _g = 0;
- var _g1 = Reflect.fields(elt);
- while(_g < _g1.length) {
- var fieldName = _g1[_g];
- ++_g;
- if(fieldName.indexOf("__reactEventHandlers") != -1) {
- Reflect.field(elt,fieldName).onChange({ target : elt});
- }
- }
- }
- };
- var Reflect = function() { };
- Reflect.field = function(o,field) {
- try {
- return o[field];
- } catch( e ) {
- return null;
- }
- };
- Reflect.fields = function(o) {
- var a = [];
- if(o != null) {
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- for( var f in o ) {
- if(f != "__id__" && f != "hx__closures__" && hasOwnProperty.call(o,f)) {
- a.push(f);
- }
- }
- }
- return a;
- };
- var $_;
- 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; }
- $global.$haxeUID |= 0;
- Main.main();
- })(typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this);