Greasy Fork

Duolingo - add keyboard support to kana/kanji exercises

This script adds keyboard control to kana/kanji exercises, as requested here: https://www.reddit.com/r/duolingo/comments/7v9veq/duolingo_please_do_this_part_keyboard_compatible/

目前为 2020-07-18 提交的版本。查看 最新版本

// ==UserScript==
// @name         Duolingo - add keyboard support to kana/kanji exercises
// @namespace    https://github.com/ciekawylogin/
// @version      0.3.1
// @description  This script adds keyboard control to kana/kanji exercises, as requested here: https://www.reddit.com/r/duolingo/comments/7v9veq/duolingo_please_do_this_part_keyboard_compatible/
// @author       Michał Artur Krawczak (ciekawylogin@github), good5209@github
// @match        https://www.duolingo.com/*
// @require      https://code.jquery.com/jquery-3.5.1.min.js
// ==/UserScript==

var numberStyle = 'position: absolute; top: 1px; right: 1px; font-size: 7pt; color: gray; padding: 1px 3px; border: 1px solid #ccc;';
var buttonStyle = 'position:relative;';
var keys = '1234567890qwertyuiopasdfghjklzxcvbnm[]';

function getButtons() {
	var name = '_1HcF0';
	try {
		var button = $("button[data-test='challenge-tap-token']");
		var classes = button.className.split(' ');
		if (classes.length > 0) {
			name = classes[0];
		}
	} catch (e) {}
	return document.getElementsByClassName(name);
}

function appendNum(elem, num) {
	var para = document.createElement("p");
	var node = document.createTextNode(num);

	para.className = "mk-keycode";
	para.appendChild(node);
	para.style.cssText = numberStyle;
	elem.style.cssText = buttonStyle;
	elem.appendChild(para);
}

function addNumbers() {
	var buttons = Array.from(getButtons());
	for(var i in buttons) {
		appendNum(buttons[i], keys[i]);
	}
}

function addNumbersIfNotPresent() {
	var buttonsWithoutCodes = Array.from(getButtons());
	var buttonsWithCodes = Array.from(document.getElementsByClassName("mk-keycode"));
	if(buttonsWithoutCodes.length > 0 && buttonsWithCodes.length === 0) {
		addNumbers();
	}
}

function addEvent(element, eventName, callback) {
	if (element.addEventListener) {
		element.addEventListener(eventName, callback, false);
	} else if (element.attachEvent) {
		element.attachEvent("on" + eventName, callback);
	} else {
		element["on" + eventName] = callback;
	}
}

addEvent(document, "keydown", function (e) {
	var key = e.key;
	var idx = keys.indexOf(key.toLowerCase());
	if (idx >= 0) { // select word button
		var word_bank = $("div[data-test='word-bank']"); // check kana/kanji exercises
		var buttons = (word_bank.length > 0) ? $("button", word_bank) : Array.from(getButtons());
		if (idx < buttons.length) {
			buttons[idx].click();
		}
	} else { // other key
		if (key === "Backspace") { // delete last answer
			var answer_bank = $('._1Cx0i');
			var buttons = $("button", answer_bank);
			if (buttons.length > 0) {
				buttons[buttons.length - 1].click();
			}
		}
	}
});

setInterval(addNumbersIfNotPresent, 250);
console.debug('Load duolingo shortcut script');