Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save panzy/d0c8437f6a423a153fc37d64de55f5ef to your computer and use it in GitHub Desktop.

Select an option

Save panzy/d0c8437f6a423a153fc37d64de55f5ef to your computer and use it in GitHub Desktop.
Tampermonkey userscript: modify the delete buttons of Cambridge Dictionary word list
/**
* 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">&nbsp;&nbsp;<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