Take the 2-minute tour ×
Stack Apps is a question and answer site for apps, scripts, and development with the Stack Exchange API. It's 100% free, no registration required.

About

Automatically adds a comment when closing a question, with the text taken directly from the close reason you chose, so that the OP can see why their question may be being downvoted, and improve it, before it is closed

It is disabled for Duplicate and Off-topic > Other since they already add a comment.

It's also disabled for Off-topic > Migrate since they don't really give much text.

The script automatically converts the HTML to Markdown, so links, italics etc. are also preserved.

Screenshots

First click

Second click

Result

With a formatted close reason:

Installing: Firefox

  1. Install Greasemonkey
  2. Click to install the script

Installing: Chrome (with Tampermonkey)

  1. Click to install the script

Installing: Chrome (no Tampermonkey):

  1. Copy the code below and save it to a file called anything.user.js
  2. In Chrome, go to Tools > Extensions
  3. Open the folder you saved the script to and drag it on to the Extensions dialog.

Source code

// ==UserScript==
// @name        Auto-Add A Comment When Closing
// @description Automatically adds a comment with details of the close reason, so that the OP can see why their question may be being downvoted, and improve it, before it is closed (disabled for Duplicate, Off-topic > Migrate, and Off-topic > Other)
// @namespace   http://stackoverflow.com/users/1563422/danny-beckett
// @version     1.4
// @grant
// @match       http://*.askubuntu.com/questions/*
// @match       http://*.mathoverflow.net/questions/*
// @match       http://*.onstartups.com/questions/*
// @match       http://*.serverfault.com/questions/*
// @match       http://*.stackapps.com/questions/*
// @match       http://*.stackexchange.com/questions/*
// @match       http://*.stackoverflow.com/questions/*
// @match       http://*.superuser.com/questions/*
// ==/UserScript==

// Hijacks all AJAX requests, and adds stateChanged() to the close popup
XMLHttpRequest.prototype.originalOpen = XMLHttpRequest.prototype.open;
function hijackAJAX(method, url, async, username, password)
{
    if(url.indexOf("/close/popup") > 0)
        this.addEventListener("readystatechange", function(){ stateChanged(this); });
    this.originalOpen(method, url, async, username, password);
}
XMLHttpRequest.prototype.open = hijackAJAX;

// Receives an XHR's state changes, and runs popupLoaded() when the popup is open
function stateChanged(XHR)
{
    if(XHR.readyState === 4 && XHR.status === 200)
        setTimeout(popupLoaded, 1);
}

// Adds a submit listener to the close popup
function popupLoaded()
{
    var popup = document.getElementById('close-question-form');
    popup.addEventListener("submit", function(){ getText(popup); });
}

// On submit, receives a popup and gets the text for the close reason chosen
function getText(popup)
{
    var text, reasons;
    var reason = popup.elements["close-reason"].value;

    // Skip duplicates
    if(reason === "Duplicate")
        return;

    else if(reason === "OffTopic")
    {
        reason = popup.elements["close-as-off-topic-reason"].value;
        reasons = document.getElementsByName("close-as-off-topic-reason");
        for(var i = 0; i < reasons.length; i++)
        {
            if(reasons[i].value === reason)
            {
                // Skip migrations & other
                if(reasons[i].getAttribute("data-subpane-name") === "migration" || typeof reasons[i].parentNode.parentNode.getElementsByClassName("off-topic-other-comment-container")[0] !== "undefined")
                    return;

                text = reasons[i].parentNode.getElementsByClassName("action-name")[0].innerHTML;
            }
        }
    }

    else
    {
        reasons = document.getElementsByName("close-reason");
        for(var i = 0; i < reasons.length; i++)
            if(reasons[i].value === reason)
                text = reasons[i].parentNode.getElementsByClassName("action-desc")[0].innerHTML;
    }

    addComment(text);
}

// Receieves the close reason text, formats it in Markdown, and adds it to a new comment
function addComment(text)
{
    text = text.replace(/<span(.*)<\/span>/gim, "");                                // Remove [2] counter, showing how many other users voted on this reason
    text = text.trim();                                                             // Trim whitespace, newlines and tabs
    text = text.replace(/<b>|<\/b>/gim, "**");                                      // Bold
    text = text.replace(/<i>|<\/i>/gim, "*");                                       // Italics
    text = text.replace(/<a href="(.*?)"( target=".*?"){0,}( rel=".*?"){0,}>(.*?)<\/a>/gim, "[$4]($1)");    // Links (strip rel and target attrs if present)

    document.getElementsByClassName("comments-link")[0].click();
    document.getElementsByName("comment")[0].innerText = text;
    setTimeout(submitComment, 250);
}

// After a short delay, submits the comment
function submitComment()
{
    document.getElementsByName("comment")[0].parentNode.parentNode.getElementsByTagName("input")[0].click();
}
share|improve this question
    
I'm not sure I'd want the comment to be automatically added. Would it be possible for your script to stop just short of that, perhaps with the comment text pasted in the "Add Comment" box, ready to go? –  Duncan Jul 2 '13 at 8:23
1  
Yes. Remove the last function. That is what clicks the button. –  Cody Guldner Jul 4 '13 at 11:15
2  
This seriously needs more upvotes. –  Kermit Dec 17 '13 at 15:41

You must log in to answer this question.

Browse other questions tagged .