Last active
August 27, 2021 14:56
-
-
Save panzy/d0c8437f6a423a153fc37d64de55f5ef to your computer and use it in GitHub Desktop.
Tampermonkey userscript: modify the delete buttons of Cambridge Dictionary word list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Modify Cambridge Dictionary word list: | |
| * 1. change the delete button's behavior, preventing it from reloading the list, | |
| * to avoid losing the scrolling position; | |
| * 2. move the delete button from the bottom of a item to the top of it, so that | |
| * it's possible to delete a word and see the next word but not its explanation, | |
| * provided that you have scrolled the deleted word's explanation to below the | |
| * page bottom. | |
| * | |
| * Usage: run this script on word list page, a "delete" link should appear inside each word entry. | |
| * Or run with Tampermonkey. | |
| * -- | |
| * by Pan Zhiyong | |
| * 2020-04-23 | |
| */ | |
| // ==UserScript== | |
| // @name Enhance Cambridge Dictionary word list. | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.1 | |
| // @description Allow deleting words from Cambridge Dictionary word list without reloading the list. | |
| // @author Pan Zhiyong | |
| // @match https://dictionary.cambridge.org/plus/wordlist/* | |
| // @grant none | |
| // @require http://code.jquery.com/jquery-1.12.4.min.js | |
| // @run-at document-body | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| if (typeof window.delete_word === 'undefined') { | |
| window.delete_word = (wordId) => { | |
| $(`[data-word-id=${wordId}]`).hide(); | |
| let url = 'https://dictionary.cambridge.org/plus/api/deleteWordlistEntry'; | |
| fetch(url, { | |
| method: 'POST', | |
| headers: { 'content-type': 'application/json' }, | |
| body: `{"id": "${wordId}", "wordlistId": "${wordlistId}"}`, // wordlistId is global | |
| }).then(r => { | |
| if (r.ok) { | |
| console.log(`word #${wordId} deleted`); | |
| } else { | |
| alert(`failed to delete word #${wordId}`); | |
| } | |
| }).catch(e => { | |
| console.error(e); | |
| alert(`failed to delete word #${wordId}`); | |
| }); | |
| } | |
| } | |
| // enhance word entry DOM | |
| function enhanceWordEntry(node) { | |
| let id = $(node).attr('data-word-id'); | |
| if ($('.x.lmb-10 .hfl .delete_link', node).length == 0) { | |
| $('.x.lmb-10 .hfl', node).append(`<button class="bt hfr lb0 lpb-0 delete_link" onclick="delete_word('${id}')" title="delete without reloading"> <i class="i i-trash"/></button>`); | |
| } | |
| // hide original trash buttons | |
| $('.delete').css('display', 'none'); | |
| } | |
| // monitor word list loading | |
| function startMonitor() { | |
| // Select the node that will be observed for mutations | |
| const targetNode = document.getElementById('wordlistEntries'); | |
| if (!targetNode) { | |
| console.error('#wordlistEntries not found. Will retry later.'); | |
| setTimeout(startMonitor, 1000); | |
| return; | |
| } | |
| // Options for the observer (which mutations to observe) | |
| const config = { childList: true }; | |
| // Callback function to execute when mutations are observed | |
| const callback = function(mutationsList, observer) { | |
| // Use traditional 'for loops' for IE 11 | |
| for(let mutation of mutationsList) { | |
| if (mutation.type === 'childList') { | |
| // console.log('A child node has been added or removed.'); | |
| if (mutation.addedNodes) { | |
| enhanceWordEntry(mutation.addedNodes[0]); | |
| } | |
| } | |
| } | |
| }; | |
| // Create an observer instance linked to the callback function | |
| const observer = new MutationObserver(callback); | |
| // Start observing the target node for configured mutations | |
| observer.observe(targetNode, config); | |
| } | |
| startMonitor(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment