您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a delay after wrong answers to prevent double-tapping <enter>
当前为
// ==UserScript== // @name Wanikani Double-Check // @namespace wkdoublecheck // @description Adds a delay after wrong answers to prevent double-tapping <enter> // @include https://www.wanikani.com/review/session* // @version 2.0.0 // @author Robin Findley // @copyright 2017+, Robin Findley // @license MIT; http://opensource.org/licenses/MIT // @run-at document-end // @grant none // ==/UserScript== // CREDITS: This is a replacement for an original script by Wanikani user @Ethan. // Ethan's script stopped working due to some Wanikani changes. The code below is // 100% my own, but it closely replicates the functionality of Ethan's original script. // HOTKEYS: "!" - Toggles an answer between 'correct' and 'incorrect'. // SEE SETTINGS BELOW. window.wkdoublecheck = {}; (function(gobj) { //==[ Settings ]===================================================== var settings = { // Delay when answer is wrong. delay_wrong: 1, // Delay when answer has multiple meanings. delay_multi_meaning: 0, // Delay when answer is slightly off (e.g. minor typo). delay_slightly_off: 1, // Amount of time to delay (in milliseconds) before allowing the // user to move on after an accepted typo or rejected answer. delay_period: 1500, }; // Make the settings accessible from the console via 'wkdoublecheck.settings' gobj.settings = settings; //=================================================================== // Theory of operation: // ==================== // Wanikani's normal process: // 1) User clicks 'submit' // a) Wanikani checks answer and updates screen with the result. // b) If both reading and meaning have been answered, Wanikani immediately sends the result to the server. (<-- BAD!!) // 2) User clicks 'submit' (or enter) again to move to the next question. // a) Wanikani updates the screen to show the next question. // // Our modified process: // 1) User clicks 'submit' // a) We intercept the click, check the answer ourself, and update the screen. // Wanikani's code is unaware of what we're doing. // b) User now has the opportunity to modify their answer. // 2) User clicks 'submit' (or enter) again to move to the next question. // a) We intercept the click again. // b) We reset the display back to pre-submitted state, so Wanikani's code won't be confused. // c) We call Wanikani's normal 'submit' function, but we intercept the answer-checker function, // so Wanikani will see whatever result the user requested. // Wanikani's updates the screen with the result. // d) Keep in mind, the user has clicked the 'submit' button twice, but Wanikani has only // seen one click. So, we have to send a third hidden click so Wanikani will catch up to // where the user thinks we are (i.e. 'next question'). // 3) We intercept the hidden click, and forward it to Wanikani's code. // a) Wanikani updates the screen to show the next question. var old_submit_handler, old_answer_checker, ignore_submit = false, state = 'first_submit'; var item, itype, item_id, item_status, qtype, valid_answers, wrong_cnt, question_cnt, completed_cnt, answer, new_answer; //------------------------------------------------------------------------ // toggle_result() - Toggle an answer from right->wrong or wrong->right. //------------------------------------------------------------------------ function toggle_result() { if ($('#option-double-check').hasClass('disabled')) return false; if (new_answer.passed) new_answer = {passed:false, accurate:false, multipleAnswers:false, exception:false}; else new_answer = {passed:true, accurate:true, multipleAnswers:false, exception:false}; set_answer_state(new_answer, false /* show_msgs */); } //------------------------------------------------------------------------ // do_delay() - Disable the submit button briefly to prevent clicking past wrong answers. //------------------------------------------------------------------------ function do_delay() { ignore_submit = true; setTimeout(function() { ignore_submit = false; }, settings.delay_period); } //------------------------------------------------------------------------ // return_new_answer() - Alternate answer checker that overrides our results. //------------------------------------------------------------------------ function return_new_answer() { return new_answer; } //------------------------------------------------------------------------ // set_answer_state() - Update the screen to show results of answer-check. //------------------------------------------------------------------------ function set_answer_state(answer, show_msgs) { // If answer is invalid for some reason, do the shake thing. if (answer.exception) { if (!$("#answer-form form").is(":animated")) { $("#reviews").css("overflow-x", "hidden"); var xlat = {onyomi:"on'yomi", kunyomi:"kun'yomi", nanori:"nanori"}; var emph = xlat[item.emph]; $("#answer-form form").effect("shake", {}, 400, function() { $("#reviews").css("overflow-x", "visible"); $("#answer-form form").append($('<div id="answer-exception" class="answer-exception-form"><span>WaniKani is looking for the '+emph+" reading</span></div>").addClass("animated fadeInUp")); }).find("input").focus(); } return; } // Draw 'correct' or 'incorrect' results, enable Double-Check button, and calculate updated statistics. $("#user-response").blur(); if (answer.passed) { $("#answer-form fieldset").removeClass('incorrect').addClass("correct"); $('#option-double-check').removeClass('disabled').find('span').attr('title','Mark Wrong').find('i').attr('class','icon-thumbs-down'); new_wrong_cnt = wrong_cnt; new_completed_cnt = completed_cnt + ((((itype==='r' || ((item_status.rc || 0) >= 1)) ? 1 : 0) + ((item_status.mc || 0) >= 1 ? 1 : 0) + 1) >= 2 ? 1 : 0); } else { $("#answer-form fieldset").removeClass('correct').addClass("incorrect"); $('#option-double-check').removeClass('disabled').find('span').attr('title','Mark Right').find('i').attr('class','icon-thumbs-up'); new_wrong_cnt = wrong_cnt + 1; new_completed_cnt = completed_cnt + ((((itype==='r' || ((item_status.rc || 0) >= 1)) ? 1 : 0) + ((item_status.mc || 0) >= 1 ? 1 : 0)) >= 2 ? 1 : 0); } new_question_cnt = question_cnt + 1; $.jStorage.set('wrongCount', new_wrong_cnt); $.jStorage.set('questionCount', new_question_cnt); $.jStorage.set('completedCount', new_completed_cnt); $("#user-response").prop("disabled", !0); additionalContent.enableButtons(); lastItems.disableSessionStats(); $("#answer-exception").remove(); // When user is submitting an answer, display the on-screen message that Wanikani normally shows. if (show_msgs) { var msg; if (answer.passed) { if (!answer.accurate) { msg = 'Your answer was a bit off. Check the '+qtype+' to make sure you are correct'; } else if (answer.multipleAnswers) { msg = 'Did you know this item has multiple possible '+qtype+'s?'; } } else { msg = 'Need help? View the correct '+qtype+' and mnemonic'; } if (msg) $("#additional-content").append($('<div id="answer-exception"><span>'+msg+'</span></div>').addClass("animated fadeInUp")); } } //------------------------------------------------------------------------ // new_submit_handler() - Intercept handler for 'submit' button. Overrides default behavior as needed. //------------------------------------------------------------------------ function new_submit_handler(e) { // Don't process 'submit' if we are ignoring temporarily (to prevent double-tapping past important info) if (ignore_submit) return false; // For more information about the state machine below, // see the "Theory of operation" info at the top of the script. switch(state) { case 'first_submit': // We intercept the first 'submit' click, and simulate normal Wanikani screen behavior. state = 'second_submit'; // Capture the state of the system before submitting the answer. item = $.jStorage.get('currentItem'); itype = (item.rad ? 'r' : (item.kan ? 'k' : 'v')); item_id = itype + item.id; item_status = $.jStorage.get(item_id) || {}; qtype = $.jStorage.get('questionType'); wrong_cnt = $.jStorage.get('wrongCount'); question_cnt = $.jStorage.get('questionCount'); completed_cnt = $.jStorage.get('completedCount'); // Ask Wanikani if the answer is right (but we don't actually submit the answer). answer = old_answer_checker(qtype, $("#user-response").val()); // Update the screen to reflect the results of our checked answer. $('#option-double-check').removeClass('disabled'); $("html, body").animate({scrollTop: 0}, 200); new_answer = Object.assign({},answer); set_answer_state(answer, true); if (answer.exception) return false; // Optionally (according to settings), temporarily ignore any additional clicks on the // 'submit' button to prevent the user from clicking past important info about the answer. if ((!answer.passed && settings.delay_wrong) || (answer.passed && ((!answer.accurate && settings.delay_slightly_off) || (answer.multipleAnswers && settings.delay_multi_meaning)) ) ) { do_delay(); } return false; case 'second_submit': // We take the user's second 'submit' click (after they've optionally toggled the answer result), // and send it to Wanikani's code as if it were the first click. // Then we send a hidden third 'submit', which Wanikani will see as the second 'submit', which moves us to the next question. state = 'third_submit'; // Reset the screen to pre-submitted state, so Wanikani won't get confused when it tries to process the answer. // Wanikani code will then update the screen according to our forced answer-check result. $('#option-double-check').addClass('disabled').find('span').attr('title','Double-Check').find('i').attr('class','icon-thumbs-up'); $('#user-response').removeAttr('disabled'); $.jStorage.set('wrongCount', wrong_cnt); $.jStorage.set('questionCount', question_cnt); $.jStorage.set('completedCount', completed_cnt); // Prepare a hidden third click, which tells Wanikani to move to the next question. setTimeout(function(){ $("#answer-form button").trigger('click'); }, 1); // We want Wanikani to see our forced answer-check result, // so we set up to intercept the answer-checker here. return old_submit_handler.apply(this, arguments); case 'third_submit': // This is hidden third click from above, which Wanikani thinks is the second click. // Wanikani will move to the next question. state = 'first_submit'; // We need to disable the input field, so Wanikani will see this as the second click. $('#user-response').attr('disabled','disabled'); return old_submit_handler.apply(this, arguments); default: return false; } return false; } //------------------------------------------------------------------------ // startup() - Install our intercept handlers, and add our Double-Check button and hotkey ("!") //------------------------------------------------------------------------ function startup() { // Check if we can intercept the submit button handler. try { old_submit_handler = $._data( $('#answer-form button')[0], 'events').click[0].handler; old_answer_checker = answerChecker.evaluate; } catch(err) {} if (typeof old_submit_handler !== 'function' || typeof old_answer_checker !== 'function') { alert('Wanikani Mistake Delay script is not working.'); return; } // Replace the handler. $._data( $('#answer-form button')[0], 'events').click[0].handler = new_submit_handler; var btn_count = $('#additional-content ul').children().length + 1; $('#additional-content ul').css('text-align','center').append('<li id="option-double-check" class="disabled"><span title="Double-Check"><i class="icon-thumbs-up"></i></span></li>'); $('#additional-content ul > li').css('width',Math.floor(9950/btn_count)/100 + '%'); $('#option-double-check').on('click', toggle_result); $('body').on('keypress', function(event){ if (event.key === '!') toggle_result(); return true; }); answerChecker.evaluate = return_new_answer; } // Run startup() after window.onload event. if (document.readyState === 'complete') startup(); else window.addEventListener("load", startup, false); })(window.wkdoublecheck);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址