Skip to content

Instantly share code, notes, and snippets.

@yusanshi
Last active March 17, 2020 08:41
Show Gist options
  • Save yusanshi/981b5926851d4cde3d67536b279cbf34 to your computer and use it in GitHub Desktop.
Save yusanshi/981b5926851d4cde3d67536b279cbf34 to your computer and use it in GitHub Desktop.
计蒜客助手 Jisuanke Helper
// ==UserScript==
// @name 计蒜客助手 Jisuanke Helper
// @namespace http://tampermonkey.net/
// @version 1.2.2
// @description 1. 取消复制限制; 2. 选择题显示序号(一般情况最小的几个是答案); 3. 跳过强制等待; 4. 双击单行或块代码区域复制代码; 5. 跳过点击直接复制提示内容
// @author yusanshi
// @source https://gist.github.com/yusanshi/981b5926851d4cde3d67536b279cbf34
// @match http://www.jisuanke.com/course/*
// @match https://www.jisuanke.com/course/*
// @grant none
// @run-at document-start
// @require https://cdn.jsdelivr.net/gh/colxi/getEventListeners/src/getEventListeners.min.js
// ==/UserScript==
/* eslint-disable no-use-before-define */
/* eslint-disable strict */
(function () {
'use strict';
// Run continually
setInterval(() => {
// Remove disabled and oncopy attribute
removeCls('jsk-disabled');
['disabled', 'oncopy', 'oncut'].forEach((elem) => {
removeAttr(elem);
});
// Delete line numbers to avoid its being copied
['#guide', '#container-content'].forEach((selector) => {
document.querySelectorAll(
`${selector} .CodeMirror-linenumber`,
).forEach((elem) => elem.remove());
});
// Remove mousedown event handler
['#guide', '#container-content'].forEach((selector) => {
document.querySelectorAll(
`${selector} .CodeMirror-scroll`,
).forEach((elem) => { customRemoveEventLister(elem, 'mousedown'); });
});
// Remove selectstart event handler
['#guide', '#container-content'].forEach((selector) => {
document.querySelectorAll(
`${selector} .CodeMirror-lines`,
).forEach((elem) => {
customRemoveEventLister(elem.querySelector('div'), 'selectstart');
});
});
// Double click to copy
['#guide', '#container-content'].forEach((i) => {
['code', '.CodeMirror-scroll'].forEach((j) => {
document.querySelectorAll(`${i} ${j}`).forEach((elem) => {
elem.ondblclick = () => {
copyTextWithFeedback(elem.innerText);
};
});
});
});
// Skip waiting
document.querySelectorAll('[data-unlocked]').forEach((elem) => {
elem.setAttribute('data-unlocked', '999');
});
}, 500);
window.onload = () => {
// Add number prompts for multiple choice problem
document.querySelectorAll('[num]').forEach((elem) => {
const span = document.createElement('span');
span.style.color = 'green';
span.innerText = elem.getAttribute('num');
elem.insertAdjacentElement('afterbegin', span);
});
// Skip clicking hint to copy its text directly
const hint = document.querySelector('#hint');
if (hint) {
const button = document.createElement('button');
button.innerText = 'Copy hint directly';
button.className = 'jsk-btn jsk-btn-success hint-btn';
button.style.marginBottom = '0.5rem';
button.onclick = () => {
// Simulate clicking and closing the popup window, in order to
// make hint.querySelector('.CodeMirror-scroll') fullfilled.
// Looks argly, a better approach may exist
document.querySelector('#hint-btn').click();
hint.querySelector('.jsk-close').click();
hint.querySelectorAll('.CodeMirror-linenumber').forEach((elem) => {
elem.remove();
});
// Copy last code area if multiple code areas in #hint are present
const allCode = hint.querySelectorAll('.CodeMirror-scroll');
copyTextWithFeedback(allCode[allCode.length - 1].innerText);
};
hint.insertAdjacentElement('afterbegin', button);
}
};
function customRemoveEventLister(target, listenerType) {
const listeners = target.getEventListeners(listenerType);
if (typeof listeners !== 'undefined') {
listeners.forEach((event) => {
target.removeEventListener(
event.type,
event.listener,
event.useCapture,
);
});
}
}
function removeCls(cls) {
document.querySelectorAll(`.${cls}`).forEach((elem) => {
elem.classList.remove(cls);
});
}
function removeAttr(attr) {
document.querySelectorAll(`[${attr}]`).forEach((elem) => {
elem.removeAttribute(attr);
});
}
function copyTextWithFeedback(text) {
copyTextToClipboardAsync(text).then(
() => {
// window.alertSuccess('Copied successfully');
},
() => {
window.alertError('Failed to copy');
},
);
}
// Based on https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
function copyTextToClipboardAsync(text) {
if (navigator.clipboard) {
return navigator.clipboard.writeText(text);
}
// Async copying is not available, turn to sync copying
return fallbackCopyTextToClipboard(text)
? Promise.resolve()
: Promise.reject();
}
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed'; // avoid scrolling to bottom
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
let returnValue;
try {
document.execCommand('copy');
returnValue = true;
} catch (err) {
returnValue = false;
}
document.body.removeChild(textArea);
return returnValue;
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment