Jisho stuff

Search the radical list by labels that you define.

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Jisho stuff
// @namespace    https://github.com/chumbucket/JishoStuff
// @version      0.4
// @description  Search the radical list by labels that you define.
// @author       chumbucket
// @match        https://jisho.org/*
// @grant        none
// ==/UserScript==

(function () {
	'use strict';
	const extraFunctions = function () {
		const hideFurigana = function () {
			if (-1 == location.href.indexOf('%23sentences')) {
				return;
			}
			var styleElement = document.createElement('style');
			styleElement.setAttribute('type', 'text/css');
			styleElement.innerHTML =
        '.furigana{opacity:0!important}' +
        '.furigana:hover{opacity:1!important}' +
        '.english{opacity:0!important}' +
        '.english:hover{opacity:1!important}';
			document.body.appendChild(styleElement);
		};
		hideFurigana();
		const searchSelectedWord = function (e) {
			if (13 == e.keyCode) {
				var selectedWord = window.getSelection().toString();
				if (selectedWord) {
					window.open('https://jisho.org/search/' + selectedWord);
				}
			}
		};
		window.addEventListener('keyup', searchSelectedWord);
	};
	const $ = window.jQuery || null;
	if (!$) {
		console.error('TM JishoStuff: jQuery is undefined');
		return;
	}
	const radicalInput = new window.RadicalInput() || null;
	if (!radicalInput) {
		console.error('TM JishoStuff: RadicalInput is undefined');
		return;
	}
	let radTable = $('.radical_table');
	let radicals = $('.radical', '.radical_table');
	radTable[0].addEventListener('click', function (evt) {
		let rad = $(evt.target);
		if (rad.hasClass('radical')) {
			let radindex = radicals.index(rad);
			if (rad.hasClass('selected')) {
				$('.search-term').each(function () {
					if (radindex == $(this).data('index')) {
						$(this).remove();
					}
				});
			}
		}
	});
	const defaultRadLabels =
    '一;one,|;line,丶;dot,ノ;no,乙;second rank,亅;putter,二;two,亠;lid,人;person,⺅;person left,' +
    '𠆢;roof,儿;legs,入;enter,ハ;eight,丷;together,冂;moustache,冖;bracket,冫;cold left,几;table,凵;open box,' +
    '刀;sword,⺉;sword right,力;power,勹;wrap,匕;hi,匚;side box,十;ten,卜;to,卩;fingerprint,厂;cliff,厶;mu,' +
    '又;crotch,マ;ma,九;round,ユ;yu,乃;sharp butt,𠂉;rifle,⻌;motion,口;mouth,囗;big mouth,土;dirt,' +
    '士;samurai,夂;each,夕;evening,大;big,女;woman,子;child,宀;crown,寸;stick,小;small,⺌;mohawk,' +
    '尢;crooked big,尸;corpse,屮;mountain tail,山;mountain,川;river,巛;river flow,工;construction,' +
    '已;self,巾;cloth,干;dry,幺;eazy,广;cave,廴;stretch,廾;letter h,弋;ceremony,弓;bow,ヨ;yo,' +
    '彑;reciprocal,彡;short hair,彳;go left,⺖;heart left,⺘;hand left,⺡;water left,⺨;animal,' +
    '⺾;flower top,⻏;boston right,⻖;boston left,也;scorpion,亡;deceased,及;reach,久;long time,' +
    '⺹;dig,心;heart,戈;spear,戸;door,手;hand,支;branch,攵;director,文;sentence,斗;spice rack,斤;axe,方;direction,' +
    '无;crooked heaven,日;sun,曰;flat sun,月;moon,木;tree,欠;lack,止;stop,歹;death,殳;nurse,比;compare,' +
    '毛;fur,氏;surname,气;steam,水;water,火;fire,⺣;fire bottom,爪;nail,父;father,爻;dos equis,' +
    '爿;left side,片;right side,牛;cow,犬;dog,⺭;ne,王;king,元;origin,井;hashtag,勿;rib,尤;crooked dog,' +
    '五;five,屯;fort,巴;nerd,毋;every,玄;deep,瓦;tile,甘;sweet,生;life,用;use,田;rice field,疋;incorrect,' +
    '疒;sick,癶;tent,白;white,皮;skin,皿;plate,目;eye,矛;beforehand,矢;arrow,石;stone,示;indicate,' +
    '禸;cow goatee,禾;wheat,穴;hole,立;stand,⻂;duck,世;world,巨;giant,冊;books,母;mother,⺲;net,牙;fang,' +
    '瓜;melon,竹;bamboo,米;rice,糸;thread,缶;can,羊;sheep,羽;feather,而;comb,耒;branch tree,耳;ear,' +
    '聿;brush,肉;meat,自;myself,至;climax,臼;mortar,舌;tongue,舟;boat,艮;good,色;color,虍;tiger,虫;bug,' +
    '血;blood,行;go,衣;clothes,西;west,臣;slave,見;see,角;corner,言;say,谷;valley,豆;bean,豕;pig,豸;snake,' +
    '貝;shellfish,赤;red,走;run,足;foot,身;somebody,車;car,辛;spicy,辰;shake,酉;sake,釆;come,' +
    '里;village,舛;dance,麦;barley,金;gold,長;long,門;gate,隶;extend,隹;turkey,雨;rain,青;blue,非;un,奄;big dragon,' +
    '岡;hill,免;excuse,斉;equal,面;surface,革;leather,韭;leek,音;sound,頁;page,風;wind,飛;fly,食;eat,首;neck,香;perfume,' +
    '品;goods,馬;horse,骨;bone,高;high,髟;hair,鬥;broken gate,鬯;herbs,鬲;tripod,鬼;demon,竜;dragon,韋;tanned leather,' +
    '魚;fish,鳥;bird,鹵;salt,鹿;deer,麻;hemp,亀;turtle,啇;drip,黄;yellow,黒;black,黍;millet,黹;sewing,無;nothing,歯;tooth,' +
    '黽;green frog,鼎;kettle,鼓;drum,鼠;mouse,鼻;nose,齊;alike,龠;flute';
	const initRadKeys = function () {
		let savedLabels = window.localStorage
			? localStorage.getItem('radLabels')
			: null;
		let radKeys = {};
		if (!savedLabels) {
			let radDef = defaultRadLabels.split(',');
			radDef.forEach(function (rad, index) {
				let radk = rad.split(';');
				if (radk.length < 2) {
					return;
				}
				radKeys[radk[1]] = index;
			});
		} else {
			radKeys = JSON.parse(savedLabels);
		}
		return radKeys;
	};
	let radKeys = initRadKeys();
	const saveRadLabels = function () {
		if (!window.localStorage) {
			return false;
		}
		try {
			localStorage.setItem('radLabels', JSON.stringify(radKeys));
			return true;
		} catch (e) {
			return false;
		}
	};
	saveRadLabels() || console.error('Error saving labels to localStorage');
	const liForRadKey = function (key) {
		let tableindex = radKeys[key];
		if (void 0 == tableindex) {
			return false;
		}
		return radicals[tableindex];
	};
	Object.keys(radKeys).forEach(function (key) {
		let radEl = liForRadKey(key);
		radEl.title = `*${key}`;
		$(radEl).data('label', key);
	});
	$('[title]').tooltip();
	const createRadSearch = function () {
		let input = document.createElement('div');
		input.id = 'rad-searchbar';
		input.setAttribute('contenteditable', 'true');
		let showlessdiv = $('.show_less', '#radical_area')[0];
		showlessdiv.insertAdjacentElement('afterend', input);
		return input;
	};
	Object.defineProperty(HTMLElement.prototype, 'value', {
		get: function () {
			return this.textContent;
		},
		set: function (x) {
			this.textContent = x;
		},
	});
	const createEditButton = function () {
		let radTable = $('.radical_table');
		let button = document.createElement('div');
		button.textContent = 'Edit';
		button.setAttribute('class', 'icon edit-label');
		radTable.prepend(button);
		return button;
	};
	const makeEditOverlay = function () {
		var editContainer = document.createElement('div');
		editContainer.id = 'edit-container';
		$(editContainer).click(function () {
			$(this).css('display', 'none');
			$('.save-result').text('');
		});
		let editbody = document.createElement('div');
		let bodyHtml =
      '<div class="rad-text"></div>' +
      '<div class="save-result"></div>' +
      '<input class="edit-input">';
		editbody.id = 'edit-body';
		$(editbody).click(function (evt) {
			evt.stopPropagation();
		});
		$(editbody).append(bodyHtml);
		$(editContainer).append(editbody);
		$(document.body).prepend(editContainer);
		$('.edit-input').data('radindex', '');
		$('.edit-input').data('label', '');
	};
	const makeRadOverlays = function () {
		$(radicalInput.radicals).each(function () {
			let radoverlay = document.createElement('div');
			radoverlay.setAttribute('class', 'rad-overlay');
			let clickedRadical = this;
			$(radoverlay).click(function () {
				$('#edit-container').css('display', 'flex');
				editRadLabel(clickedRadical);
			});
			$(this).prepend(radoverlay);
		});
	};
	const editRadLabel = function (rad) {
		let radLabel = $(rad).data('label');
		let radIndex = $(radicals).index(rad);
		if (radLabel) {
			$('.edit-input').val(radLabel);
		} else {
			$('.edit-input').val('');
		}
		$('.edit-input').data('radindex', radIndex);
		$('.edit-input').data('label', radLabel);
		$('.rad-text').text($(rad).text());
	};
	const showRadOverlays = function () {
		if (editMode) {
			$('.rad-overlay').css('display', 'inherit');
		} else {
			$('.rad-overlay').css('display', 'none');
		}
	};
	const makeSpanWithTerm = function (searchterm) {
		let span = document.createElement('span');
		span.setAttribute('class', 'search-term');
		span.textContent = searchterm[0];
		span = $(span);
		span.attr('data-index', radKeys[searchterm[0]]);
		span.click(
			(function (me) {
				return function () {
					let radical = radInfoFromTerm(me.text());
					radicalInput.selected_radicals = radicalInput.selected_radicals.subtract(
						radical.text
					);
					if (0 == radicalInput.selected_radicals.length) {
						radicalInput.reset();
					} else {
						radicalInput.getKanji();
					}
					radical.element.removeClass('selected');
					radical.text;
					radicalInput.selected_radicals;
					me.remove();
				};
			})(span)
		);
		let resultsarea = $('.results', '#radical_area');
		resultsarea.append(span);
		return span;
	};
	let radSearchBar = createRadSearch();
	let editButton = createEditButton();
	makeRadOverlays();
	makeEditOverlay();
	let editMode = false;
	$(editButton).on('click', function (evt) {
		evt.preventDefault();
		if (editMode) {
			editMode = false;
			$(radSearchBar).attr('contenteditable', 'true');
			$(this).css({ 'background-color': 'white', color: '#222' });
			$('.radical_table').css('background', '');
		} else {
			editMode = true;
			$('.results .search-term').remove();
			radicalInput.reset();
			$(radSearchBar).attr('contenteditable', 'false');
			$(this).css({ 'background-color': '#555', color: 'white' });
			$('.radical_table').css({
				background: 'none',
				'background-color': '#edf9ff',
			});
		}
		showRadOverlays();
	});
	let showSaveResultText = function (resulttext, bool) {
		if (bool) {
			$('.save-result').css('color', '#2ecb2e');
		} else {
			$('.save-result').css('color', 'red');
		}
		$('.save-result').text(resulttext);
	};
	$('.edit-input').on('keydown', function (e) {
		if (13 == e.keyCode) {
			if ('' == $(this).val()) {
				return;
			}
			e.preventDefault();
			let oldLabel = $(this).data('label');
			let newLabel = $(this).val();
			newLabel = newLabel.replace(/\s*$/, '');
			if (newLabel in radKeys) {
				showSaveResultText('This label is already taken');
				return;
			} else {
				delete radKeys[oldLabel];
				radKeys[newLabel] = $(this).data('radindex');
				$(this).data('label', newLabel);
				let radTableItem = radicals[radKeys[newLabel]];
				$(radTableItem).data('label', newLabel);
				$(radTableItem).attr('title', `*${newLabel}`);
				$(radTableItem).tooltip();
				if (saveRadLabels()) {
					showSaveResultText('Saved', true);
				} else {
					showSaveResultText('Couldn\'t save to local storage');
				}
				radKeys[newLabel];
			}
		}
	});
	const buttontoggle = function (_this) {
		return function () {
			if (_this.active) {
				return _this.deactivate();
			} else {
				return _this.activate();
			}
		};
	};
	radicalInput.table.off();
	radicalInput.area.off();
	radicalInput.button.off();
	radicalInput.list.off();
	radicalInput.setupEvents();
	radicalInput.resetRadicalsButton.off();
	radicalInput.button.on('click', buttontoggle(radicalInput));
	radicalInput.resetRadicalsButton.on(
		'click',
		(function (_this) {
			return function () {
				_this.reset();
				$('.results .search-term').remove();
			};
		})(radicalInput)
	);
	const updateOptionsArray = function (terms) {
		if (0 == terms.length) {
			return [];
		}
		let optionsarray = [];
		let searchTerm = terms.last();
		Object.keys(radKeys).forEach(function (key) {
			if (0 == searchTerm.length) {
				return;
			}
			let radTableItem = radInfoFromTerm(key);
			if (
				0 == key.indexOf(searchTerm) &&
        radTableItem.element.hasClass('available')
			) {
				optionsarray.push(key);
			} else {
				return;
			}
		});
		return optionsarray.sort();
	};
	const highlightRadicals = function (arr) {
		if (0 == arr.length) {
			return;
		}
		for (var i = 0; i < arr.length; i++) {
			let radTableItem = liForRadKey(arr[i]);
			radTableItem = $(radTableItem);
			if (
				radTableItem.hasClass('selected') ||
        !radTableItem.hasClass('available')
			) {
				continue;
			}
			radTableItem.addClass('selected');
		}
	};
	const clearHighlightRadicals = function (arr) {
		if (0 == arr.length) {
			return;
		}
		for (var i = 0; i < arr.length; i++) {
			let radTableItem = radInfoFromTerm(arr[i]).element;
			let radk = radInfoFromTerm(arr[i]).text;
			if (-1 != radicalInput.selected_radicals.indexOf(radk)) {
				continue;
			}
			if (radTableItem && radTableItem.hasClass('selected')) {
				radTableItem.removeClass('selected');
			}
		}
	};
	const radInfoFromTerm = function (term) {
		let radTableItem = liForRadKey(term);
		if (!radTableItem) {
			return false;
		}
		radTableItem = $(radTableItem);
		let radk = radTableItem.data('radk') || radTableItem.text();
		return { element: radTableItem, text: radk };
	};
	let lastAutoCompOpts = [];
	let currentSearch = '';
	let lastCaretLocation = 0;
	let optionsindex = 0;
	const radSearchInput = function (e) {
		let selection = window.getSelection();
		lastCaretLocation = selection.anchorOffset;
		if ((e.keyCode >= 65 && e.keyCode <= 90) || 32 == e.keyCode) {
			optionsindex = 0;
			if (!e.metaKey) {
				e.preventDefault();
			}
			if (32 == e.keyCode) {
				currentSearch += ' ';
			} else {
				currentSearch += e.key;
			}
		}
		let terms = [this.value];
		let optionsarray = updateOptionsArray([currentSearch]);
		if (13 == e.keyCode) {
			e.preventDefault();
			e.type;
			clickRadical(terms);
			this.value = '';
			currentSearch = '';
			terms = [];
			optionsarray = [];
			optionsindex = 0;
		}
		if (188 == e.keyCode) {
			e.type;
			clickRadical(terms);
			this.value = '';
			currentSearch = '';
			terms = [];
			optionsarray = [];
			optionsindex = 0;
		}
		if (8 == e.keyCode) {
			optionsindex = 0;
			e.preventDefault();
			e.type, radicalInput.selected_radicals;
			if (currentSearch.length > 0) {
				currentSearch = currentSearch.substr(0, currentSearch.length - 1);
				optionsarray = updateOptionsArray([currentSearch]);
			} else {
				this.value = '';
				currentSearch = '';
				optionsarray = [];
			}
		}
		if (9 == e.keyCode) {
			e.preventDefault();
			e.type;
			if (optionsarray.length) {
				optionsindex++;
				if (optionsindex > optionsarray.length - 1) {
					optionsindex = 0;
				}
			}
		}
		clearHighlightRadicals(lastAutoCompOpts);
		if (optionsarray.length > 0) {
			this.value = optionsarray[optionsindex];
			selection.collapse(this.childNodes[0], currentSearch.length);
		} else {
			this.value = currentSearch;
			selection.collapse(this.childNodes[0], currentSearch.length);
		}
		if ('' == this.value) {
			selection.collapse(this, 0);
		}
		lastAutoCompOpts = optionsarray;
		highlightRadicals(optionsarray);
		currentSearch.length;
	};
	radSearchBar.addEventListener('keydown', radSearchInput);
	radSearchBar.addEventListener('keyup', function (e) {
		if (
			(e.keyCode >= 65 && e.keyCode <= 90) ||
      32 == e.keyCode ||
      8 == e.keyCode ||
      9 == e.keyCode
		) {
			if (!e.metaKey) {
				e.preventDefault();
			}
		}
		if (13 == e.keyCode) {
			e.preventDefault();
		}
	});
	const clickRadical = function (search) {
		let searchterms = search;
		searchterms = searchterms.subtract('');
		searchterms.forEach(function (term) {
			let radical = radInfoFromTerm(term);
			if (!radical) {
				return;
			}
			if (!radical.element.hasClass('available')) {
				return;
			}
			radical.element.addClass('selected');
			if (-1 == radicalInput.selected_radicals.indexOf(radical.text)) {
				radicalInput.selected_radicals.push(radical.text);
				makeSpanWithTerm(searchterms);
			}
		});
		if (0 != radicalInput.selected_radicals.length) {
			let fetchResult = radicalInput.getKanji();
		}
		radicalInput.selected_radicals;
	};
	let globalStyle = document.createElement('style');
	globalStyle.innerHTML =
    '#rad-searchbar{display:block;font-size:22px;background-color:white;outline:none;width:70%;' +
    'height:33px;border-radius:3px;margin-bottom:10px;margin-top:10px;padding-left:5px;' +
    'padding-right:5px;}.icon.edit-label{margin:0px;padding:0px;padding-top:2px;padding-left:5px;' +
    'padding-right:5px;float:left;cursor:pointer;border-radius:5px;height:30px;}.icon.edit-label:hover{background-color:#555!important;' +
    'color:#fff!important;}#edit-container{width:100%;height:100%;background-color:rgba(0,0,0,0.5);' +
    'position:fixed;z-index:1000;top:0px;left:0px;display:none;align-items:center;justify-content:center;' +
    '}#edit-body{display:flex;flex-direction:column;align-items:center;justify-content:center;' +
    'width:200px;height:200px;border-radius:10px;background-color:white;}.edit-input{width:75%!important;' +
    'border-radius:5px!important;text-align:center;}.rad-text{font-size:70px;text-align:center;' +
    'cursor:default;}.save-result{font-size:12px!important;height:18px;}.rad-overlay{position:absolute;' +
    'width:32px;height:32px;margin-left:-2px;margin-top:-2px;display:none;}.search-term{background-color:gray;' +
    'color:white;border-radius:10px;padding:5px;cursor:pointer;margin-right:5px;}.search-input{display:block;' +
    'width:auto;background-color:white;outline:none;}';
	$('head').append(globalStyle);
})();