您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Makes it easier to give explanations on downvotes
// ==UserScript== // @name StackOverflow: Downvote helper // @description Makes it easier to give explanations on downvotes // @namespace ClasherKasten // @version 0.6.1 // @include https://stackoverflow.com/questions/* // @grant none // @license MIT // ==/UserScript== /* TODO: - add optional/additional infos (how to {mre,ask}) */ const options = { beingunresponsive: "Being unresponsive", imageofanexception: "Image of an exception", imageofcode: "Image of code", itsnotworking: "It's not working", noattempt: "No attempt", nocode: "No code", nodebugging: "No debugging", noexceptiondetails: "Missing exception details", nomcve: "No MCVE/MRE", noresearch: "No research", toomuchcode: "Too much code", toomuchinfo: "Too much information", unclearquestion: "Unclear what you're asking", unreadablecode: "Unreadable code", wronglanguage: "Wrong language", }; const downvotedListHTML = Object.keys(options) .map((key) => { return ` <li> <label> <input type="checkbox" name="downvote-reason-form" value="${key}"> <span class="action-name"><a href="https://idownvotedbecau.se/${key}" target="_blank">${options[key]}</a></span> </label> </li> `; }) .join(""); const modalHTML = ` <div id="popup-flag-post" class="popup responsively-horizontally-centered-legacy-popup z-modal" data-controller="se-draggable" style="max-width: 600px; position: absolute; top: ${ window.innerHeight / 5 }px; left: calc(50% - 300px); display: block;"> <div class="popup-close"> <a title="close this popup (or hit Esc)"> × </a> </div> <form id="dv-explanation" data-showretract=""> <div> <h2 style="margin-bottom:12px;" class="c-move" data-se-draggable-target="handle"> I downvoted because: </h2> <div class="flag-description"></div> <ul class="action-list"> ${downvotedListHTML} </ul> </div> <div class="popup-actions"> <div class="d-flex gs8 gsx ai-center"> <button class="s-btn s-btn__primary flex--item js-popup-submit"> Downvote with explanation(s) </button> </div> </div> </form> </div> `; const downvote_btn = document.querySelector(".js-vote-down-btn"); if (downvote_btn !== null && downvote_btn !== undefined) { console.log('registering event'); downvote_btn.addEventListener("click", (event) => { // pre-check up event.preventDefault(); if (downvote_btn.getAttribute('aria-pressed') === 'true') { return; } // set up modal const element = document.querySelector(".js-menu-popup-container"); element.innerHTML = modalHTML; // modal actions const form = document.querySelector("#dv-explanation"); const cancel_btn = document.querySelector('.popup-close'); form.onsubmit = (event) => { event.preventDefault(); const comment_btn = document.querySelector(".js-add-link.comments-link"); const question_id = window.location.href.match("questions/(\\d+)")[1]; const commentParts = []; const selected = []; const checkBoxes = document.querySelectorAll( 'input[name="downvote-reason-form"]' ); let idx = 0; for (const checkBox of Array.from(checkBoxes)) { if (checkBox.checked) { selected.push(idx); } idx++; } selected.forEach((sidx) => { const key = Object.keys(options)[sidx]; commentParts.push( `[${options[key]}](https://idownvotedbecau.se/${key})` ); }); if (commentParts.length === 0) { element.innerHTML = ''; return } // write default comment comment_btn.click(); const comment_field = document.querySelector( `textarea#comment-input-${question_id}` ); comment_field.value = `Downvoted because: ${commentParts.join(", ")}`; element.innerHTML = ''; }; cancel_btn.onclick = (event) => { element.innerHTML = ''; downvote_btn.click(); }; }); }