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);
});
});