// ==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 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // Insert CSS document.head.insertAdjacentHTML('beforeend',` `); // 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; } } })();