Lesson picker improvements
当前为
// ==UserScript==
// @name Better Lesson Picker
// @namespace better-lesson-picker
// @version 1.0.2
// @description Lesson picker improvements
// @author Mystery
// @license MIT
// @match https://www.wanikani.com/subject-lessons/picker
// @run-at document-end
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Insert CSS
document.head.insertAdjacentHTML('beforeend',`
<style name="better_lesson_picker" type="text/css">
.better-lesson-picker__input::-webkit-outer-spin-button,
.better-lesson-picker__input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.better-lesson-picker__input {
-moz-appearance: textfield;
margin-left: 10px;
width: 3em;
height: 48px;
font: inherit;
font-size: 20px;
text-align: center;
border-radius: var(--border-radius-tight);
}
.better-lesson-picker__input[disabled] {
background-color: var(--color-button-lesson-picker-disabled-background);
color: var(--color-button-lesson-picker-disabled-text);
user-select: none;
}
.better-lesson-picker__input--radical {
border: var(--color-radical) 2px solid;
}
.better-lesson-picker__input--kanji {
border: var(--color-kanji) 2px solid;
}
.better-lesson-picker__input--vocabulary {
border: var(--color-vocabulary) 2px solid;
}
</style>
`);
// variables
let currentEl;
let firstEl;
let dragged;
const items = {
radical: [],
kanji: [],
vocabulary: []
};
const inputs = {
radical: undefined,
kanji: undefined,
vocabulary: undefined
};
const inputFocusValue = {};
// main functions
populateItems();
addInputs();
addEventListeners();
function populateItems() {
document.querySelectorAll('div.lesson-picker__subjects').forEach(el => {
const type = el.querySelector('span').classList[1].split('--')[1];
items[type].push(...el.children);
});
}
function addInputs() {
const form = document.querySelector('form.lesson-picker__footer-content');
for (const key in inputs) {
inputs[key] = createNumberInput(form, key);
}
}
function addEventListeners() {
document.addEventListener('mousedown', handleMousedown);
// Update inputs when selecting all
document.querySelector('button.lesson-picker__section-toggle-all').addEventListener('click', () => setTimeout(updateInputs, 10));
document.querySelectorAll('button.lesson-picker__section-toggle').forEach(el => {
el.addEventListener('click', () => setTimeout(updateInputs, 10));
});
}
function handleMousedown(e) {
if (isItem(e)) {
dragged = false;
currentEl = undefined;
firstEl = e.target;
document.addEventListener('mousemove', handleDrag);
document.addEventListener('mouseup', handleMouseup);
}
}
function handleDrag(e) {
dragged = true;
if (currentEl !== e.target) {
currentEl = e.target;
if (isItem(e)) {
e.target.click();
updateInputs();
}
}
}
function handleMouseup(e) {
if (firstEl === e.target && dragged) {
// if you drag and release on the same item triggers the click event negating the drag click
e.target.click();
}
if (!dragged) {
setTimeout(updateInputs, 10);
}
document.removeEventListener('mousemove', handleDrag);
document.removeEventListener('mouseup', handleMouseup);
}
function handleInput(type) {
return function(e) {
const val = Number(e.target.value);
const list = items[type];
if (val >= 0) {
list.forEach((el, i) => {
if (i <= val - 1) {
if (el.ariaSelected === 'false') {
el.click();
}
} else {
if (el.ariaSelected === 'true') {
el.click();
}
}
});
}
if (val > list.length) {
e.target.value = list.length;
}
}
}
function isItem(e) {
return e.target.tagName === 'SPAN' && e.target.classList.contains('subject-character__characters');
}
function createNumberInput(form, type) {
const input = document.createElement('input');
input.type = 'number';
input.classList.add('better-lesson-picker__input');
input.classList.add(`better-lesson-picker__input--${type}`);
input.addEventListener('input', handleInput(type));
input.addEventListener('focus', e => {
inputFocusValue[type] = e.target.value;
e.target.value = '';
});
input.addEventListener('blur', e => {
if (e.target.value === '') {
e.target.value = inputFocusValue[type];
}
});
input.value = 0;
if (items[type].length === 0) {
input.disabled = true;
}
form.appendChild(input);
return input;
}
function updateInputs() {
for (const key in inputs) {
let count = 0;
items[key].forEach(el => {
if (el.ariaSelected === 'true') {
count++;
}
});
inputs[key].value = count;
}
}
})();