您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Allows custom components for kanji
当前为
- // ==UserScript==
- // @name Jpdb custom components
- // @namespace http://tampermonkey.net/
- // @version 0.1
- // @description Allows custom components for kanji
- // @author Calonca
- // @match https://jpdb.io/kanji/*
- // @match https://jpdb.io/review
- // @match https://jpdb.io/edit_mnemonic*
- // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
- // @require http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
- // @grant GM_addStyle
- // @grant GM_setValue
- // @grant GM_getValue
- // @license GPLv2
- // ==/UserScript==
- (function() {
- 'use strict';
- //#Utility functions
- //
- function getCCList(){//returns custom component array from mnemonic
- let mnemonic = document.getElementsByClassName("mnemonic")[0];
- if (mnemonic == null){
- return [];
- }else {
- let componetsPharagraph =
- Array.from(mnemonic.childNodes)
- .filter(p=>p.nodeName=="P")
- .map(p=>p.innerHTML)
- .find(t=>t.includes("Composed of: "));
- if (componetsPharagraph){
- return componetsPharagraph.substring(componetsPharagraph.indexOf(':') + 2).split(",");
- }else return [];
- }
- }
- /**
- * @param {String} HTML representing a single element
- * @return {Element}
- */
- function htmlToElement(html) {
- var template = document.createElement('template');
- html = html.trim(); // Never return a text node of whitespace as the result
- template.innerHTML = html;
- return template.content.firstChild;
- }
- //#Dom update functions
- //
- function updateComponents(){
- const componentsList = document.getElementsByClassName("subsection-composed-of-kanji")[0].getElementsByClassName("subsection")[0].childNodes;
- const componentsLen = componentsList.length;
- let customSpellingList = getCCList();
- const customSpellingLen = customSpellingList.length;
- if (customSpellingLen>0){
- let nodesToRemove = componentsLen-customSpellingLen;
- console.log(nodesToRemove);
- //Removes nodes if the custom componets are less then the original ones
- for (let i=0;i<nodesToRemove;i++){
- componentsList[0].parentNode.removeChild(componentsList[customSpellingLen])
- }
- //Replaces the kanji/radical/spelling and the keyword/description
- for (let i=0;i<customSpellingLen;i++){
- if (i>=componentsLen){//Duplicates nodes if we have more custom componets then the original ones
- componentsList[0].parentNode.appendChild(componentsList[0].cloneNode(true));
- }
- let plain = componentsList[i].querySelector(".spelling .plain")
- plain.innerHTML = customSpellingList[i];
- plain.href = "/kanji/"+customSpellingList[i]+"#a"
- //Gets the keyword for each compnent
- $.get( plain.href, function( data ) {
- let doc22 = $(data);
- let containerBugFix = doc22[24];
- let desc = containerBugFix.querySelector(".vbox.gap .subsection").innerHTML;
- componentsList[i].querySelector(".description").innerHTML = desc;
- });
- }
- }
- }
- function addEditButton(){
- let div =document.querySelector("a[href*='/edit_mnemonic']").parentNode.parentNode;
- let memEditButton = div.querySelector(".subsection-label a");
- let coSubsectionLabel = document.querySelector(".subsection-composed-of-kanji .subsection-label");
- let memEditButtonClone = memEditButton.cloneNode(true);
- memEditButtonClone.href += "&co=1";
- coSubsectionLabel.appendChild(htmlToElement('<span style="opacity: 0.5">*</span>'));
- coSubsectionLabel.appendChild(htmlToElement(' '));
- coSubsectionLabel.appendChild(memEditButtonClone);
- }
- function updateMemLine(){
- if (getCCList().length==0){
- let textArea = document.getElementsByTagName("textarea")[0];
- let componentsStr = "\n\nComposed of: "+Array.from(document.querySelectorAll(".spelling .plain")).map(a=>a.innerHTML).join(',');
- textArea.innerHTML += componentsStr;
- }
- }
- function updateComponentsAndAddButton (){
- updateComponents();
- addEditButton();
- }
- //#Running different functions based on the current page
- //
- if(window.location.href.indexOf("https://jpdb.io/kanji") > -1) {
- updateComponentsAndAddButton();
- } else if (window.location.href.indexOf("https://jpdb.io/review") > -1){//If reviewing wait for mnemonic to show up before adding the components
- waitForKeyElements (
- ".mnemonic"
- , updateComponentsAndAddButton
- );
- } else if (window.location.href.indexOf("https://jpdb.io/edit_mnemonic") > -1){
- const urlParams = new URLSearchParams(document.location.href);
- if (urlParams.get('co')=="1"){
- updateMemLine();
- }
- }
- })();
- //Put the function here instead of requires due to GreasyFolk rules, original can be found at https://gist.github.com/BrockA/2625891
- /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
- that detects and handles AJAXed content.
- Usage example:
- waitForKeyElements (
- "div.comments"
- , commentCallbackFunction
- );
- //--- Page-specific function to do what we want when the node is found.
- function commentCallbackFunction (jNode) {
- jNode.text ("This comment changed by waitForKeyElements().");
- }
- IMPORTANT: This function requires your script to have loaded jQuery.
- */
- function waitForKeyElements (
- selectorTxt, /* Required: The jQuery selector string that
- specifies the desired element(s).
- */
- actionFunction, /* Required: The code to run when elements are
- found. It is passed a jNode to the matched
- element.
- */
- bWaitOnce, /* Optional: If false, will continue to scan for
- new elements even after the first match is
- found.
- */
- iframeSelector /* Optional: If set, identifies the iframe to
- search.
- */
- ) {
- var targetNodes, btargetsFound;
- if (typeof iframeSelector == "undefined")
- targetNodes = $(selectorTxt);
- else
- targetNodes = $(iframeSelector).contents ()
- .find (selectorTxt);
- if (targetNodes && targetNodes.length > 0) {
- btargetsFound = true;
- /*--- Found target node(s). Go through each and act if they
- are new.
- */
- targetNodes.each ( function () {
- var jThis = $(this);
- var alreadyFound = jThis.data ('alreadyFound') || false;
- if (!alreadyFound) {
- //--- Call the payload function.
- var cancelFound = actionFunction (jThis);
- if (cancelFound)
- btargetsFound = false;
- else
- jThis.data ('alreadyFound', true);
- }
- } );
- }
- else {
- btargetsFound = false;
- }
- //--- Get the timer-control variable for this selector.
- var controlObj = waitForKeyElements.controlObj || {};
- var controlKey = selectorTxt.replace (/[^\w]/g, "_");
- var timeControl = controlObj [controlKey];
- //--- Now set or clear the timer as appropriate.
- if (btargetsFound && bWaitOnce && timeControl) {
- //--- The only condition where we need to clear the timer.
- clearInterval (timeControl);
- delete controlObj [controlKey]
- }
- else {
- //--- Set a timer, if needed.
- if ( ! timeControl) {
- timeControl = setInterval ( function () {
- waitForKeyElements ( selectorTxt,
- actionFunction,
- bWaitOnce,
- iframeSelector
- );
- },
- 300
- );
- controlObj [controlKey] = timeControl;
- }
- }
- waitForKeyElements.controlObj = controlObj;
- }