您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
1. 取消复制限制; 2. 选择题显示序号(一般情况最小的几个是答案); 3. 跳过强制等待; 4. 双击单行或块代码区域复制代码; 5. 跳过点击直接复制提示内容
当前为
// ==UserScript== // @name 计蒜客助手 Jisuanke Helper // @namespace http://tampermonkey.net/ // @version 1.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== (function () { 'use strict'; // Run continually setInterval(() => { // Remove disabled and oncopy attribute removeCls('jsk-disabled'); for (let elem of ['disabled', 'oncopy', 'oncut']) { removeAttr(elem); } // Delete line numbers to avoid its being copied for (let selector of ['#guide', '#lint', '#container-content']) { for (let elem of document.querySelectorAll(`${selector} .CodeMirror-linenumber`)) { elem.remove(); } } // Remove mousedown event handler for (let selector of ['#guide', '#lint', '#container-content']) { for (let elem of document.querySelectorAll(`${selector} .CodeMirror-scroll`)) { customRemoveEventLister(elem, 'mousedown'); } } // Remove selectstart event handler for (let selector of ['#guide', '#lint', '#container-content']) { for (let elem of document.querySelectorAll(`${selector} .CodeMirror-lines`)) { customRemoveEventLister(elem.querySelector('div'), 'selectstart'); } } // Double click to copy for (let i of ['#guide', '#lint', '#container-content']) { for (let j of ['code', '.CodeMirror-scroll']) { for (let elem of document.querySelectorAll(`${i} ${j}`)) { elem.ondblclick = () => { copyTextWithFeedback(elem.innerText); } } } } // Skip waiting for (let elem of document.querySelectorAll('[data-unlocked]')) { elem.setAttribute('data-unlocked', '999'); } }, 500); window.onload = () => { // Add number prompts for multiple choice problem for (let elem of document.querySelectorAll('[num]')) { 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(); for (let elem of hint.querySelectorAll('.CodeMirror-linenumber')) { elem.remove(); } // Copy last code area if multiple code areas in #lint 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') { for (let event of listeners) { target.removeEventListener(event.type, event.listener, event.useCapture); } } } function removeCls(cls) { for (let elem of document.querySelectorAll(`.${cls}`)) { elem.classList.remove(cls); } } function removeAttr(attr) { for (let elem of document.querySelectorAll(`[${attr}]`)) { 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); } else { // 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; } })();