A script that allows you to cast a delete vote on a post immediately after casting a downvote that makes the post score negative, without having to refresh the whole page.
// ==UserScript== // @name Stack Exchange: “Delete” without refresh // @match https://*.stackexchange.com/* // @match https://*.superuser.com/* // @match https://*.stackoverflow.com/* // @match https://*.mathoverflow.net/* // @match https://*.serverfault.com/* // @match https://*.askubuntu.com/* // @exclude https://chat.stackexchange.com/* // @exclude https://api.stackexchange.com/* // @exclude https://data.stackexchange.com/* // @exclude https://openid.stackexchange.com/* // @exclude https://area51.stackexchange.com/* // @exclude https://stackexchange.com/* // @exclude https://contests.stackoverflow.com/* // @exclude /^https?:\/\/winterbash\d{4,}\.stackexchange\.com\// // ==/UserScript== document.addEventListener('click', ev => { const btn = ev.target.closest('.js-vote-down-btn'); if (!btn) return; const postContainer = btn.closest('.js-question, .js-answer'); if (!postContainer) return; const postId = postContainer.dataset.answerid ?? postContainer.dataset.questionid; const voteWasCast = new Promise((ok, ko) => { const handler = cloneInto((ev, jqxhr, opts) => { if (!opts.url.startsWith(`/posts/${postId}/vote/`)) return; if (jqxhr.statusText === 'success') ok(jqxhr.responseJSON); else ko(new Error(jqxhr.statusText)); }, unsafeWindow, { cloneFunctions: true }); unsafeWindow.eval(`((func) => { const cb = (...args) => { if (func(...args)) jQuery(document).off('ajaxComplete', cb); }; jQuery(document).on('ajaxComplete', cb); });`)(handler); }); (async () => { const response = await voteWasCast; if (!response.Success || response.NewScore > 0) return; const resp = await fetch(`${location.origin}/posts/ajax-load-realtime/${postId}`); const data = await resp.json(); const frag = document.createRange().createContextualFragment(data.Html); const newPostMenu = frag.querySelector('.js-post-menu'); if (!newPostMenu) { console.warn(`[SE:Dwr] post menu not found in `, frag); return; } const origPostMenu = postContainer.querySelector('.js-post-menu'); origPostMenu.parentNode.replaceChild(newPostMenu, origPostMenu); })().catch(e => { console.warn(`[SE:Dwr] `, e); }); });