您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Streamlined login experience and localStorage-based preservation of comments.
当前为
// ==UserScript== // @name BootCampSpot v2 Improvements // @namespace https://jonas.ninja // @version 1.1.0 // @description Streamlined login experience and localStorage-based preservation of comments. // @author @iv_njonas // @match https://bootcampspot-v2.com/* // @grant none // ==/UserScript== (function preserveCommentsInLocalStorage() { /// BCS has a nasty habit of kicking out users after a certain time, usually a few moments /// before they submit a long and thoughtful comment on a student's homework. This has been /// a great source of workplace stress and psychological harm. This code prevents such /// heartache by auto-saving your comments at every keystroke, and presents a button to /// easily load a saved comment after BCS kicks you out. var localStorageKey = 'bootcampspotv2-comment'; var commentBoxSelector = 'textarea#commentEntry'; var loadButton = createLoadButton(); var infoAlert = createInfoAlert(); var noSavedComment = createNoSavedCommentAlert(); var oldText; $('body').on('keyup', commentBoxSelector, function(e) { // save the entered text if it has changed significantly. If the button happens to be visible, hide it. // give the user some feedback that their comments are saved. alert('keyup handler'); var text = e.target.value; if (text.length < 10) { return; } else { // read oldText from cache or from localStorage, and if it has not changed, don't do anything. oldText = oldText || window.localStorage.getItem(localStorageKey); if (oldText === text) { return; } } window.localStorage.setItem(localStorageKey, e.target.value); loadButton.remove(); if (e.target.value === '') { infoAlert.remove(); e.target.insertAdjacentElement('afterend', noSavedComment); } else { noSavedComment.remove(); e.target.insertAdjacentElement('afterend', infoAlert); } }); // inject a button that will load the comment window.setInterval(function() { var commentBox = document.querySelector(commentBoxSelector); if (!commentBox || commentBox.dataset.ijgDecorated) { return; } else { commentBox.dataset.ijgDecorated = true; // insert the load button if the comment box is empty if (commentBox.value === '' && window.localStorage.getItem(localStorageKey)) { commentBox.insertAdjacentElement('afterend', loadButton); } } }, 1000); function createLoadButton() { var loadButton = document.createElement('div'); loadButton.classList = 'btn btn-lg bcs-button ijg-bcs-loadButton'; loadButton.style.position = 'absolute'; loadButton.style.top = '20px'; loadButton.style.left = '50%'; loadButton.style.transform = 'translateX(-50%)'; loadButton.onclick = loadButtonClickHandler; loadButton.textContent = "Load comment from localStorage"; return loadButton; } function createInfoAlert() { var alertDiv = document.createElement('div'); alertDiv.classList = 'alert alert-info pull-left'; alertDiv.style.marginTop = '10px'; alertDiv.style.marginBottom = '-7px'; alertDiv.textContent = 'Your comment is saved in localStorage!'; return alertDiv; } function createNoSavedCommentAlert() { var infoDiv = createInfoAlert(); infoDiv.classList = 'alert alert-warning pull-left'; infoDiv.textContent = 'No comments in localStorage...'; return infoDiv; } function loadButtonClickHandler() { // when the load button is clicked, the contents of the comment box are replaced // and the button disappears permanently document.querySelector(commentBoxSelector).value = window.localStorage.getItem(localStorageKey); loadButton.remove(); } })(); (function streamlineLogin() { /// There is a pointless mandatory "click to login" button. Click that right away. /// Then wait for the browser's autofill and var loginWithUsernameIntervalId; var loginFormIntervalId; var autofillIntervalId; var autofillWaitingPeriodInMS = 3000; var autofillWaitingPeriodStartTime; loginWithUsernameIntervalId = window.setInterval(attemptClickLoginWithUsername, 100); /// Phase 1: wait for the first form to appear, or confirm that it will never appear. function attemptClickLoginWithUsername() { var loginWithUsernameButton = document.querySelector('.landing .btn-login'); if (loginWithUsernameButton === null) { // Either the page isn't loaded yet, or we're already logged in. // If already logged in, clear all intervals and exit. if ($('.header-menu .logout').length) { window.clearInterval(loginWithUsernameIntervalId); } } else { // The button is there. This function is done. Onward to the next phase. window.clearInterval(loginWithUsernameIntervalId); loginWithUsernameButton.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true})); loginFormIntervalId = window.setInterval(waitForLoginForm, 100); } } /// Phase 2: wait for the second form to appear. function waitForLoginForm() { var loginButton = document.querySelector('.landing button[type="submit"]'); var usernameField = document.getElementById('email'); var passwordField = document.getElementById('password'); if (loginButton !== null && usernameField !== null && passwordField !== null) { // Onward to next phase. window.clearInterval(loginFormIntervalId); autofillIntervalId = window.setInterval(waitForAutofill, 100); } if ($('.header-menu .logout').length) { window.clearInterval(loginFormIntervalId); } // if this function is fired once, it is guaranteed that it will hit its success // condition and clear its own interval. } /// Phase 3: wait for autofill to kick in, or timeout and exit. function waitForAutofill() { var loginButton = document.querySelector('.landing button[type="submit"]'); var usernameField = document.querySelector('#email'); var passwordField = document.querySelector('#password'); autofillWaitingPeriodStartTime = autofillWaitingPeriodStartTime || new Date(); var now = new Date(); if (now.getTime() > autofillWaitingPeriodStartTime.getTime() + autofillWaitingPeriodInMS) { // timeout triggered. Exit program. window.clearInterval(autofillIntervalId); } else if (usernameField.value.length > 0) { // autofill worked. Program completed successfully. window.clearInterval(autofillIntervalId); var style = loginButton.style; style.position = 'fixed'; style.width = style.height = '100%'; style.top = style.left = 0; style.fontSize = '30vmin'; loginButton.onmousemove = hoverHandler; } } function hoverHandler() { // this only works on Firefox because of a Chrome security "feature" var loginButton = document.querySelector('.landing button[type="submit"]'); loginButton.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true})); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址