Skip to content

Instantly share code, notes, and snippets.

@SathyaBhat
Forked from Benjol/autoreviewcomments.user.js
Created November 24, 2011 09:09

Revisions

  1. SathyaBhat revised this gist Nov 24, 2011. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -43,7 +43,7 @@ with_jquery(function ($) {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.1.5'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.6'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
  2. SathyaBhat revised this gist Nov 24, 2011. 1 changed file with 13 additions and 4 deletions.
    17 changes: 13 additions & 4 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,35 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.1.5
    // @version 1.1.6
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*stackoverflow.com/review*
    // @include http://*stackoverflow.com/admin/dashboard*
    // @include http://*serverfault.com/questions*
    // @include http://*serverfault.com/review*
    // @include http://*serverfault.com/admin/dashboard*
    // @include http://*superuser.com/questions*
    // @include http://*superuser.com/review*
    // @include http://*superuser.com/admin/dashboard*
    // @include http://*stackexchange.com/questions*
    // @include http://*stackexchange.com/review*
    // @include http://*stackexchange.com/admin/dashboard*
    // @include http://*askubuntu.com/questions*
    // @include http://*askubuntu.com/review*
    // @include http://*askubuntu.com/admin/dashboard*
    // @include http://*answers.onstartups.com/questions*
    // @include http://*answers.onstartups.com/review*
    // @include http://mathoverflow.net/questions*
    // @include http://mathoverflow.net/review*
    // @include http://*answers.onstartups.com/admin/dashboard*
    // @include http://*mathoverflow.net/questions*
    // @include http://*mathoverflow.net/review*
    // @include http://*mathoverflow.net/admin/dashboard*
    // @include http://discuss.area51.stackexchange.com/questions/*
    // @include http://discuss.area51.stackexchange.com/review/*
    // @include http://discuss.area51.com/admin/dashboard*
    // @include http://stackapps.com/questions*
    // @include http://stackapps.com/review*
    // @include http://stackapps.com/admin/dashboard*
    // ==/UserScript==

    function with_jquery(f) {
    @@ -426,7 +435,7 @@ with_jquery(function ($) {

    //This is where the real work starts - add the 'auto' link next to each comment 'help' link
    //use most local root-nodes possible (have to exist on page load) - #questions is for review pages
    $(".question, .answer, #questions").delegate(".comments-link", "click", function() {
    $(".question, .answer, #questions, .flag-container").delegate(".comments-link", "click", function() {
    var divid = $(this).attr('id').replace('-link', '');
    if($('#' + divid).find('.comment-auto-link').length > 0) return; //don't create auto link if already there
    var newspan = $('<span class="lsep"> | </span>').add($('<a class="comment-auto-link">auto</a>').click(function () {
  3. @Benjol Benjol revised this gist Nov 22, 2011. 1 changed file with 67 additions and 59 deletions.
    126 changes: 67 additions & 59 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,17 +1,26 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.1.4
    // @version 1.1.5
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*stackoverflow.com/review*
    // @include http://*serverfault.com/questions*
    // @include http://*serverfault.com/review*
    // @include http://*superuser.com/questions*
    // @include http://*superuser.com/review*
    // @include http://*stackexchange.com/questions*
    // @include http://*stackexchange.com/review*
    // @include http://*askubuntu.com/questions*
    // @include http://*askubuntu.com/review*
    // @include http://*answers.onstartups.com/questions*
    // @include http://*answers.onstartups.com/review*
    // @include http://mathoverflow.net/questions*
    // @include http://mathoverflow.net/review*
    // @include http://discuss.area51.stackexchange.com/questions/*
    // @include http://discuss.area51.stackexchange.com/review/*
    // @include http://stackapps.com/questions*
    // @include http://stackapps.com/review*
    // ==/UserScript==

    function with_jquery(f) {
    @@ -25,7 +34,7 @@ with_jquery(function ($) {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.1.4'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.5'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
    @@ -414,65 +423,64 @@ with_jquery(function ($) {
    }
    SetStorage("LastUpdateCheckDay", today);
    }

    //This is where the real work starts - add the 'auto' link next to each comment 'help' link
    $(".comments-link").each(function () {
    //use most local root-nodes possible (have to exist on page load) - #questions is for review pages
    $(".question, .answer, #questions").delegate(".comments-link", "click", function() {
    var divid = $(this).attr('id').replace('-link', '');
    $(this).click(function () {
    if($('#' + divid).find('.comment-auto-link').length > 0) return; //don't create auto link if already there
    var newspan = $('<span class="lsep"> | </span>').add($('<a class="comment-auto-link">auto</a>').click(function () {
    //Create popup and wire-up the functionality
    var popup = $(markupTemplate);
    popup.find('.popup-close').click(function () { popup.fadeOutAndRemove(); });

    //Reset this, otherwise we get the greeting twice...
    showGreeting = false;

    //create/add options
    WriteComments(popup);

    //Add handlers for command links
    popup.find('.popup-actions-cancel').click(function () { popup.fadeOutAndRemove(); });
    popup.find('.popup-actions-reset').click(function () { ResetComments(); WriteComments(popup); });
    popup.find('.popup-actions-see').hover(function () {
    popup.fadeTo('fast', '0.4').children().not('#close').fadeTo('fast', '0.0')
    }, function () {
    popup.fadeTo('fast', '1.0').children().not('#close').fadeTo('fast', '1.0')
    });
    popup.find('.popup-actions-impexp').click(function () { ImportExport(popup); });
    popup.find('.popup-actions-toggledesc').click(function () {
    var hideDesc = GetStorage('hide-desc') || "show";
    SetStorage('hide-desc', hideDesc == "show" ? "hide" : "show");
    ShowHideDescriptions(popup);
    });

    //on submit, convert html to markdown and copy to comment textarea
    popup.find('.popup-submit').click(function () {
    var selected = popup.find('input:radio:checked');
    var markdown = htmlToMarkDown(selected.parent().find('.action-desc').html());
    $('#' + divid).find('textarea').attr('value', markdown).focus(); //focus provokes character count test
    var caret = markdown.indexOf('[type here]')
    if(caret >= 0) $('#' + divid).find('textarea')[0].setSelectionRange(caret, caret + '[type here]'.length);
    popup.fadeOutAndRemove();
    });

    //check if we need to show annoucement, if so, some wiring to be performed
    //CheckForAnnouncement(popup); //Not ready yet

    //add popup and center on screen
    $('#' + divid).append(popup);
    popup.center();

    //Get user info and inject
    var userid = getUserId($(this));
    getUserInfo(userid, popup);

    //We only actually perform the updates check when someone clicks, this should make it less costly, and more timely
    //also wrap it so that it only gets called the *FIRST* time we open this dialog on any given page (not much of an optimisation).
    if(!window.VersionChecked) { CheckForNewVersion(popup); window.VersionChecked = true; }
    }));
    $('#' + divid).find('.comment-help-link').parent().append(newspan);
    });
    if($('#' + divid).find('.comment-auto-link').length > 0) return; //don't create auto link if already there
    var newspan = $('<span class="lsep"> | </span>').add($('<a class="comment-auto-link">auto</a>').click(function () {
    //Create popup and wire-up the functionality
    var popup = $(markupTemplate);
    popup.find('.popup-close').click(function () { popup.fadeOutAndRemove(); });

    //Reset this, otherwise we get the greeting twice...
    showGreeting = false;

    //create/add options
    WriteComments(popup);

    //Add handlers for command links
    popup.find('.popup-actions-cancel').click(function () { popup.fadeOutAndRemove(); });
    popup.find('.popup-actions-reset').click(function () { ResetComments(); WriteComments(popup); });
    popup.find('.popup-actions-see').hover(function () {
    popup.fadeTo('fast', '0.4').children().not('#close').fadeTo('fast', '0.0')
    }, function () {
    popup.fadeTo('fast', '1.0').children().not('#close').fadeTo('fast', '1.0')
    });
    popup.find('.popup-actions-impexp').click(function () { ImportExport(popup); });
    popup.find('.popup-actions-toggledesc').click(function () {
    var hideDesc = GetStorage('hide-desc') || "show";
    SetStorage('hide-desc', hideDesc == "show" ? "hide" : "show");
    ShowHideDescriptions(popup);
    });

    //on submit, convert html to markdown and copy to comment textarea
    popup.find('.popup-submit').click(function () {
    var selected = popup.find('input:radio:checked');
    var markdown = htmlToMarkDown(selected.parent().find('.action-desc').html());
    $('#' + divid).find('textarea').attr('value', markdown).focus(); //focus provokes character count test
    var caret = markdown.indexOf('[type here]')
    if(caret >= 0) $('#' + divid).find('textarea')[0].setSelectionRange(caret, caret + '[type here]'.length);
    popup.fadeOutAndRemove();
    });

    //check if we need to show annoucement, if so, some wiring to be performed
    //CheckForAnnouncement(popup); //Not ready yet

    //add popup and center on screen
    $('#' + divid).append(popup);
    popup.center();

    //Get user info and inject
    var userid = getUserId($(this));
    getUserInfo(userid, popup);

    //We only actually perform the updates check when someone clicks, this should make it less costly, and more timely
    //also wrap it so that it only gets called the *FIRST* time we open this dialog on any given page (not much of an optimisation).
    if(!window.VersionChecked) { CheckForNewVersion(popup); window.VersionChecked = true; }
    }));
    $('#' + divid).find('.comment-help-link').parent().append(newspan);
    });
    });
    });
  4. @Benjol Benjol revised this gist Oct 25, 2011. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.1.3
    // @version 1.1.4
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -25,7 +25,7 @@ with_jquery(function ($) {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.1.3'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.4'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
    @@ -451,6 +451,8 @@ with_jquery(function ($) {
    var selected = popup.find('input:radio:checked');
    var markdown = htmlToMarkDown(selected.parent().find('.action-desc').html());
    $('#' + divid).find('textarea').attr('value', markdown).focus(); //focus provokes character count test
    var caret = markdown.indexOf('[type here]')
    if(caret >= 0) $('#' + divid).find('textarea')[0].setSelectionRange(caret, caret + '[type here]'.length);
    popup.fadeOutAndRemove();
    });

  5. @Benjol Benjol revised this gist Sep 16, 2011. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.1.2
    // @version 1.1.3
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -25,7 +25,7 @@ with_jquery(function ($) {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.1.2'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.3'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
    @@ -207,8 +207,8 @@ with_jquery(function ($) {
    showGreeting = true;
    container.find('.action-desc').prepend(greeting);
    }

    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    var usertype = user['user_type'].charAt(0).toUpperCase() + user['user_type'].slice(1);
    var html = usertype + ' user <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    last seen <strong>' + lastseen(user['last_access_date']) + '</strong>, \
    reputation <strong>' + repNumber(user['reputation']) + '</strong>';
  6. @Benjol Benjol revised this gist Jul 21, 2011. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.1.1
    // @version 1.1.2
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -25,7 +25,7 @@ with_jquery(function ($) {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.1.1'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.2'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
    @@ -272,7 +272,7 @@ with_jquery(function ($) {
    }

    function markDownToHtml(markdown) {
    html = markdown.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>');
    html = markdown.replace(/\[([^\]]+)\]\((.+?)\)/g, '<a href="$2">$1</a>');
    return html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>').replace(/\*(.+?)\*/g, '<em>$1</em>');
    }

  7. @Benjol Benjol revised this gist Jul 20, 2011. 1 changed file with 11 additions and 7 deletions.
    18 changes: 11 additions & 7 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.1.0
    // @version 1.1.1
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -25,7 +25,7 @@ with_jquery(function ($) {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.1.0'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.1'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
    @@ -355,16 +355,20 @@ with_jquery(function ($) {
    //add click handler to radio buttons
    popup.find('input:radio').click(function () {
    popup.find('.popup-submit').attr("disabled", ""); //enable submit button
    //unset/set selected class
    $(this).parents('ul').find(".action-selected").removeClass("action-selected");
    $(this).parent().addClass('action-selected');
    //}
    //unset/set selected class, hide others if necessary
    $(this).parents('ul').find('.action-selected').removeClass('action-selected');
    if(GetStorage('hide-desc') == "hide") {
    $(this).parents('ul').find('.action-desc').hide();
    }
    $(this).parent().addClass('action-selected')
    .find('.action-desc').show();
    });
    }

    //Adjust the descriptions so they show or hide based on the user's preference.
    function ShowHideDescriptions(popup) {
    var descriptions = popup.find("ul.action-list span[id*='desc-']");
    //get list of all descriptions except the currently selected one
    var descriptions = popup.find("ul.action-list li:not(.action-selected) span[id*='desc-']");

    if(GetStorage('hide-desc') == "hide") {
    descriptions.hide();
  8. @Benjol Benjol revised this gist May 11, 2011. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.1.00
    // @version 1.1.0
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -25,7 +25,7 @@ with_jquery(function ($) {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.1.00'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.0'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
  9. @Benjol Benjol revised this gist May 11, 2011. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.9
    // @version 1.1.00
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -22,10 +22,10 @@ function with_jquery(f) {
    };

    with_jquery(function ($) {
    $(function () {
    StackExchange.ready(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.0.9'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.1.00'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
  10. @Benjol Benjol revised this gist Mar 29, 2011. 1 changed file with 66 additions and 43 deletions.
    109 changes: 66 additions & 43 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.8
    // @version 1.0.9
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -23,8 +23,9 @@ function with_jquery(f) {

    with_jquery(function ($) {
    $(function () {
    var ANNOUNCEMENT = 'NA';
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.0.8'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var VERSION = '1.0.9'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
    @@ -48,13 +49,13 @@ with_jquery(function ($) {
    var greeting = 'Welcome to ' + sitename + '! ';
    var showGreeting = false;

    var markup = ' \
    var markupTemplate = ' \
    <div id="popup" class="popup" style="width:690px; position: absolute; display: block"> \
    <div id="close" class="popup-close"><a title="close this popup (or hit Esc)">&#215;</a></div> \
    <h2>Which review comment to insert?</h2> \
    <div style="overflow:hidden" id="main"> \
    <div class="popup-active-pane"> \
    <div id="userinfo" class="owner" style="padding:5px"> \
    <div id="userinfo" style="padding:5px;background:#EAEFEF"> \
    <img src="http://sstatic.net/img/progress-dots.gif"/> \
    </div> \
    <ul class="action-list" style="height:440;overflow-y:auto" > \
    @@ -81,7 +82,15 @@ with_jquery(function ($) {
    </div> \
    </div>';

    var option = ' \
    var messageTemplate = ' \
    <div id="announcement" style="background:orange;padding:7px;margin-bottom:10px;font-size:15px"> \
    <span class="notify-close" style="border:2px solid black;cursor:pointer;display:block;float:right;margin:0 4px;padding:0 4px;line-height:17px"> \
    <a title="dismiss this notification" style="color:black;text-decoration:none;font-weight:bold;font-size:16px">x</a> \
    </span> \
    <strong>$TITLE$</strong> $BODY$ \
    </div>';

    var optionTemplate = ' \
    <li> \
    <input id="comment-$ID$" type="radio" name="commentreview"/> \
    <label for="comment-$ID$"> \
    @@ -114,13 +123,6 @@ with_jquery(function ($) {
    if(key.indexOf(prefix + startsWith) == 0) localStorage.removeItem(key);
    }
    }
    function UpgradeStorage(key) { //<---- remove this in V1.0.9
    var val = localStorage[key];
    if(val != null) {
    localStorage.removeItem(key);
    SetStorage(key, val);
    }
    }

    //Calculate and format datespan for "Member since/for"
    function datespan(date) {
    @@ -224,8 +226,9 @@ with_jquery(function ($) {
    var tohide = popup.find('#main');
    var div = $('<div><textarea/><a class="save">save</a><span class="lsep"> | </span><a class="cancel">cancel</a></div>');
    //Painful, but shortest way I've found to position div over the tohide element
    div.css('position', 'absolute').css('left', tohide.position().left).css('top', tohide.position().top)
    .css('width', tohide.css('width')).css('height', tohide.css('height')).css('background', 'white');
    div.css({ position: 'absolute', left: tohide.position().left, top: tohide.position().top,
    width: tohide.css('width'), height: tohide.css('height'), background: 'white'
    });

    var txt = '';
    for(var i = 0; i < GetStorage("commentcount"); i++) {
    @@ -243,7 +246,7 @@ with_jquery(function ($) {

    //Import complete text into comments
    function DoImport(text) {
    //first time through on V1.0.8, clear out any existing stuff
    //clear out any existing stuff
    ClearStorage("name-"); ClearStorage("desc-");
    var arr = text.split('\n');
    var nameIndex = 0, descIndex = 0;
    @@ -255,7 +258,7 @@ with_jquery(function ($) {
    }
    else if(arr[i].length > 0) {
    var desc = markDownToHtml(arr[i]);
    SetStorage('desc-' + descIndex, TagHtml(desc));
    SetStorage('desc-' + descIndex, Tag(desc));
    descIndex++;
    }
    }
    @@ -273,15 +276,19 @@ with_jquery(function ($) {
    return html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>').replace(/\*(.+?)\*/g, '<em>$1</em>');
    }

    function TagHtml(html) {
    function UnTag(text) {
    return text.replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl)
    }

    function Tag(html) {
    //put tags back in
    var regname = new RegExp(sitename, "g"), regurl = new RegExp('http://' + siteurl, "g");
    return html.replace(regname, '$SITENAME$').replace(regurl, 'http://$SITEURL$');
    }

    //Replace contents of element with a textarea (containing markdown of contents), and save/cancel buttons
    function ToEditable(el) {
    var html = el.html();
    var html = Tag(el.html());
    if(html.indexOf('<textarea') > -1) return; //don't want to create a new textarea inside this one!
    var txt = $('<textarea />').css('height', 2 * el.height())
    .css('width', el.css('width'))
    @@ -309,13 +316,14 @@ with_jquery(function ($) {
    //Save textarea contents, replace element html with new edited content
    function SaveEditable(el) {
    var html = markDownToHtml(el.find('textarea').attr('value'));
    SetStorage(el.attr('id'), TagHtml(html));
    el.html((showGreeting ? greeting : "") + html);
    SetStorage(el.attr('id'), Tag(html));
    el.html((showGreeting ? greeting : "") + UnTag(html));
    }

    function CancelEditable(el, backup) {
    el.html(backup);
    }

    //Empty all custom comments from storage and rewrite to ui
    function ResetComments() {
    ClearStorage("name-"); ClearStorage("desc-");
    @@ -326,29 +334,14 @@ with_jquery(function ($) {
    SetStorage("commentcount", defaultcomments.length);
    }

    //<-----Delete this in V1.0.9---->
    function UpgradeComments() {
    //this adds default comments, but with prefix in front of key (so it's not squashing old ones)
    ResetComments();
    //this checks for 'old' custom comments and overwrites them onto prefixed-key storage
    for(var i = 0; i < defaultcomments.length; i++) {
    //this shouldn't break anything, but it is a bit fragile....
    if(localStorage["desc-" + i] != null) {
    localStorage["desc-" + i] = localStorage["desc-" + i].replace(/\$SITEURL\$/g, "http://$SITEURL$");
    }
    UpgradeStorage("name-" + i);
    UpgradeStorage("desc-" + i);
    }
    }

    //rewrite all comments to ui (typically after import or reset)
    function WriteComments(popup) {
    if(!GetStorage("commentcount")) UpgradeComments(); // << change this to ResetComments in V1.0.9
    if(!GetStorage("commentcount")) ResetComments();
    var ul = popup.find('.action-list');
    ul.empty();
    for(var i = 0; i < GetStorage("commentcount"); i++) {
    var desc = GetStorage('desc-' + i).replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl);
    var opt = option.replace(/\$ID\$/g, i)
    var opt = optionTemplate.replace(/\$ID\$/g, i)
    .replace("$NAME$", GetStorage('name-' + i))
    .replace("$DESCRIPTION$", (showGreeting ? greeting : "") + desc);
    ul.append(opt);
    @@ -381,15 +374,38 @@ with_jquery(function ($) {
    }
    }

    //Show a message (like notify.show) inside popup
    function ShowMessage(popup, title, body, callback) {
    var html = body.replace(/\n/g, '<BR/>');
    var message = $(messageTemplate.replace("$TITLE$", title)
    .replace('$BODY$', html));
    message.find('.notify-close').click(function () {
    $(this).parent().fadeOutAndRemove();
    callback();
    });
    popup.find('h2').before(message);
    }

    //We only show announcement once for each version
    function CheckForAnnouncement(popup) {
    var previous = GetStorage("LastMessage");
    if(previous != ANNOUNCEMENT) {
    ShowMessage(popup, "Service announcement", ANNOUNCEMENT, function () { SetStorage("LastMessage", ANNOUNCEMENT); });
    }
    }

    //Check to see if a new version has become available since last check
    // only checks once a day, and won't notify user twice
    function CheckForNewVersion() {
    UpgradeStorage("LastUpdateCheckDay"); ///<<<<--- Remove this for 1.0.9
    // only checks once a day
    function CheckForNewVersion(popup) {
    var today = (new Date().setHours(0, 0, 0, 0));
    var lastCheck = GetStorage("LastUpdateCheckDay");
    if(lastCheck != null && lastCheck != today) {
    var lastVersion = GetStorage("LastVersionAcknowledged");
    updateCheck(function (newver, oldver, url) {
    notify.show('A new version (' + newver + ') of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> userscript is now available (this notification will only appear once per new version).', -123456);
    if(newver != lastVersion) {
    ShowMessage(popup, "New Version!", 'A new version (' + newver + ') of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> userscript is now available (this notification will only appear once per new version, and per site).',
    function () { SetStorage("LastVersionAcknowledged", newver); });
    }
    });
    }
    SetStorage("LastUpdateCheckDay", today);
    @@ -402,9 +418,12 @@ with_jquery(function ($) {
    if($('#' + divid).find('.comment-auto-link').length > 0) return; //don't create auto link if already there
    var newspan = $('<span class="lsep"> | </span>').add($('<a class="comment-auto-link">auto</a>').click(function () {
    //Create popup and wire-up the functionality
    var popup = $(markup);
    var popup = $(markupTemplate);
    popup.find('.popup-close').click(function () { popup.fadeOutAndRemove(); });

    //Reset this, otherwise we get the greeting twice...
    showGreeting = false;

    //create/add options
    WriteComments(popup);

    @@ -430,6 +449,10 @@ with_jquery(function ($) {
    $('#' + divid).find('textarea').attr('value', markdown).focus(); //focus provokes character count test
    popup.fadeOutAndRemove();
    });

    //check if we need to show annoucement, if so, some wiring to be performed
    //CheckForAnnouncement(popup); //Not ready yet

    //add popup and center on screen
    $('#' + divid).append(popup);
    popup.center();
    @@ -440,7 +463,7 @@ with_jquery(function ($) {

    //We only actually perform the updates check when someone clicks, this should make it less costly, and more timely
    //also wrap it so that it only gets called the *FIRST* time we open this dialog on any given page (not much of an optimisation).
    if(!window.VersionChecked) { CheckForNewVersion(); window.VersionChecked = true; }
    if(!window.VersionChecked) { CheckForNewVersion(popup); window.VersionChecked = true; }
    }));
    $('#' + divid).find('.comment-help-link').parent().append(newspan);
    });
  11. @Benjol Benjol revised this gist Mar 17, 2011. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -332,10 +332,12 @@ with_jquery(function ($) {
    ResetComments();
    //this checks for 'old' custom comments and overwrites them onto prefixed-key storage
    for(var i = 0; i < defaultcomments.length; i++) {
    //this shouldn't break anything, but it is a bit fragile....
    if(localStorage["desc-" + i] != null) {
    localStorage["desc-" + i] = localStorage["desc-" + i].replace(/\$SITEURL\$/g, "http://$SITEURL$");
    }
    UpgradeStorage("name-" + i);
    UpgradeStorage("desc-" + i);
    //this shouldn't break anything, but it is a bit fragile....
    SetStorage("desc-" + i, GetStorage("desc-" + i).replace(/\$SITEURL\$/g, "http://$SITEURL$"));
    }
    }

  12. @Benjol Benjol revised this gist Mar 17, 2011. 1 changed file with 25 additions and 17 deletions.
    42 changes: 25 additions & 17 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -231,7 +231,7 @@ with_jquery(function ($) {
    for(var i = 0; i < GetStorage("commentcount"); i++) {
    var name = GetStorage('name-' + i);
    var desc = GetStorage('desc-' + i);
    txt += '###' + name + '\n' + desc + '\n\n'; //the leading ### makes prettier if pasting to markdown, and differentiates names from descriptions
    txt += '###' + name + '\n' + htmlToMarkDown(desc) + '\n\n'; //the leading ### makes prettier if pasting to markdown, and differentiates names from descriptions
    }

    div.find('textarea').width('100%').height('95%').attr('value', txt);
    @@ -254,8 +254,8 @@ with_jquery(function ($) {
    nameIndex++;
    }
    else if(arr[i].length > 0) {
    var desc = arr[i];
    SetStorage('desc-' + descIndex, desc);
    var desc = markDownToHtml(arr[i]);
    SetStorage('desc-' + descIndex, TagHtml(desc));
    descIndex++;
    }
    }
    @@ -272,6 +272,13 @@ with_jquery(function ($) {
    html = markdown.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>');
    return html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>').replace(/\*(.+?)\*/g, '<em>$1</em>');
    }

    function TagHtml(html) {
    //put tags back in
    var regname = new RegExp(sitename, "g"), regurl = new RegExp('http://' + siteurl, "g");
    return html.replace(regname, '$SITENAME$').replace(regurl, 'http://$SITEURL$');
    }

    //Replace contents of element with a textarea (containing markdown of contents), and save/cancel buttons
    function ToEditable(el) {
    var html = el.html();
    @@ -302,12 +309,10 @@ with_jquery(function ($) {
    //Save textarea contents, replace element html with new edited content
    function SaveEditable(el) {
    var html = markDownToHtml(el.find('textarea').attr('value'));
    var regname = new RegExp(sitename, "g"), regurl = new RegExp('http://' + siteurl, "g");
    //put tags back in (in preparation for import/export)
    var taggedhtml = html.replace(regname, '$SITENAME$').replace(regurl, 'http://$SITEURL$');
    SetStorage(el.attr('id'), taggedhtml);
    SetStorage(el.attr('id'), TagHtml(html));
    el.html((showGreeting ? greeting : "") + html);
    }

    function CancelEditable(el, backup) {
    el.html(backup);
    }
    @@ -347,6 +352,19 @@ with_jquery(function ($) {
    ul.append(opt);
    }
    ShowHideDescriptions(popup);
    AddOptionEventHandlers(popup);
    }

    function AddOptionEventHandlers(popup) {
    popup.find('label > span').dblclick(function () { ToEditable($(this)); });
    //add click handler to radio buttons
    popup.find('input:radio').click(function () {
    popup.find('.popup-submit').attr("disabled", ""); //enable submit button
    //unset/set selected class
    $(this).parents('ul').find(".action-selected").removeClass("action-selected");
    $(this).parent().addClass('action-selected');
    //}
    });
    }

    //Adjust the descriptions so they show or hide based on the user's preference.
    @@ -388,16 +406,6 @@ with_jquery(function ($) {
    //create/add options
    WriteComments(popup);

    popup.find('label > span').dblclick(function () { ToEditable($(this)); });
    //add click handler to radio buttons
    popup.find('input:radio').click(function () {
    popup.find('.popup-submit').attr("disabled", ""); //enable submit button
    //unset/set selected class
    $(this).parents('ul').find(".action-selected").removeClass("action-selected");
    $(this).parent().addClass('action-selected');
    //}
    });

    //Add handlers for command links
    popup.find('.popup-actions-cancel').click(function () { popup.fadeOutAndRemove(); });
    popup.find('.popup-actions-reset').click(function () { ResetComments(); WriteComments(popup); });
  13. @Benjol Benjol revised this gist Mar 17, 2011. 1 changed file with 167 additions and 113 deletions.
    280 changes: 167 additions & 113 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.7
    // @version 1.0.8
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -23,42 +23,62 @@ function with_jquery(f) {

    with_jquery(function ($) {
    $(function () {
    var scriptVersion = '1.0.7'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var siteurl = 'http://' + window.location.hostname; //include http in here so we don't get confusion between so and meta.so
    //**selfupdatingscript starts here (see https://gist.github.com/raw/874058/selfupdatingscript.user.js)
    var VERSION = '1.0.8'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var URL = "https://gist.github.com/raw/842025/autoreviewcomments.user.js";

    if(window["selfUpdaterCallback:" + URL]) {
    window["selfUpdaterCallback:" + URL](VERSION);
    return;
    }

    function updateCheck(notifier) {
    window["selfUpdaterCallback:" + URL] = function (newver) {
    if(newver > VERSION) notifier(newver, VERSION, URL);
    }
    $("<script />").attr("src", URL).appendTo("head");
    }
    //**selfupdatingscript ends here (except for call to updateCheck further down in code)

    //autoreviewcomments script starts here
    var siteurl = window.location.hostname;
    var arr = document.title.split(' - ');
    var sitename = arr[arr.length - 1];
    if(sitename == "Stack Exchange") sitename = arr[arr.length - 2]; //workaround for SE sites..
    var greeting = 'Welcome to ' + sitename + '! ';
    var showGreeting = false;

    var markup = ' \
    <div id="popup" class="popup" style="width:690px; position: absolute; display: block"> \
    <div class="popup-close"><a title="close this popup (or hit Esc)">&#215;</a></div> \
    <h2>Which review comment to insert?</h2> \
    <div style="overflow:hidden" id="main"> \
    <div class="popup-active-pane"> \
    <div id="userinfo" class="owner" style="padding:5px"> \
    <img src="http://sstatic.net/img/progress-dots.gif"/> \
    </div> \
    <ul class="action-list" > \
    </ul> \
    </div> \
    <div class="popup-actions"> \
    <div style="float: left; margin-top: 18px;"> \
    <a title="close this popup (or hit Esc)" class="popup-actions-cancel">cancel</a> \
    <span class="lsep"> | </span> \
    var markup = ' \
    <div id="popup" class="popup" style="width:690px; position: absolute; display: block"> \
    <div id="close" class="popup-close"><a title="close this popup (or hit Esc)">&#215;</a></div> \
    <h2>Which review comment to insert?</h2> \
    <div style="overflow:hidden" id="main"> \
    <div class="popup-active-pane"> \
    <div id="userinfo" class="owner" style="padding:5px"> \
    <img src="http://sstatic.net/img/progress-dots.gif"/> \
    </div> \
    <ul class="action-list" style="height:440;overflow-y:auto" > \
    </ul> \
    </div> \
    <div class="popup-actions"> \
    <div style="float: left; margin-top: 18px;"> \
    <a title="close this popup (or hit Esc)" class="popup-actions-cancel">cancel</a> \
    <span class="lsep"> | </span> \
    <a title="see info about this popup" class="popup-actions-help" href="http://stackapps.com/q/2116" target="_blank">info</a> \
    <span class="lsep"> | </span> \
    <a class="popup-actions-see">see-through</a> \
    <span class="lsep"> | </span> \
    <a title="reset any custom comments" class="popup-actions-reset">reset</a> \
    <span class="lsep"> | </span> \
    <span class="lsep"> | </span> \
    <a class="popup-actions-see">see-through</a> \
    <span class="lsep"> | </span> \
    <a title="reset any custom comments" class="popup-actions-reset">reset</a> \
    <span class="lsep"> | </span> \
    <a title="use this to import/export all comments" class="popup-actions-impexp">import/export</a> \
    </div> \
    <div style="float:right"> \
    <span class="lsep"> | </span> \
    <a title="use this to hide/show all comments" class="popup-actions-toggledesc">show/hide desc</a> \
    </div> \
    <div style="float:right"> \
    <input class="popup-submit" type="button" disabled="disabled" style="float:none; margin-left: 5px" value="Insert"> \
    </div> \
    </div> \
    </div> \
    </div> \
    </div> \
    </div> \
    </div>';

    var option = ' \
    @@ -71,18 +91,37 @@ with_jquery(function ($) {
    </li>';

    //default comments
    var comments = [
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="$SITEURL$/privileges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    var defaultcomments = [
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="http://$SITEURL$/privileges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, <a href="http://meta.stackoverflow.com/q/8259">it would be preferable</a> to include the essential parts of the answer here, and provide the link for reference.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="http://$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "OP using an answer for further information", Description: 'Please use the <em>Post answer</em> button only for actual answers. You should modify your original question to add additional information.' },
    { Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the <a href="$SITEURL$/questions/ask">Ask Question</a> button.' },
    { Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the <a href="$SITEURL$/questions/ask">Ask Question</a> button. If you have sufficient reputation, <a href="$SITEURL$/privileges/vote-up">you may upvote</a> the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
    { Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button.' },
    { Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button. If you have sufficient reputation, <a href="http://$SITEURL$/privileges/vote-up">you may upvote</a> the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
    ];

    var weekday_name = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    var minute = 60, hour = 3600, day = 86400, sixdays = 518400, week = 604800, month = 2592000, year = 31536000;

    //Wrap local storage access so that we avoid collisions with other scripts
    var prefix = "AutoReviewComments-"
    function GetStorage(key) { return localStorage[prefix + key]; }
    function SetStorage(key, val) { localStorage[prefix + key] = val; }
    function RemoveStorage(key) { localStorage.removeItem(prefix + key); }
    function ClearStorage(startsWith) {
    for(var i = localStorage.length - 1; i >= 0; i--) {
    var key = localStorage.key(i);
    if(key.indexOf(prefix + startsWith) == 0) localStorage.removeItem(key);
    }
    }
    function UpgradeStorage(key) { //<---- remove this in V1.0.9
    var val = localStorage[key];
    if(val != null) {
    localStorage.removeItem(key);
    SetStorage(key, val);
    }
    }

    //Calculate and format datespan for "Member since/for"
    function datespan(date) {
    var now = new Date() / 1000;
    @@ -136,7 +175,11 @@ with_jquery(function ($) {

    //Get userId for post
    function getUserId(el) {
    return el.parents('div').find('.post-signature:last').find('.user-details > a').attr('href').split('/')[2];
    // a bit complicated, but we have to avoid edits (:last), not trip on CW questions (:not([id])), and not bubble
    // out of post scope for deleted users (first()).
    var userlink = el.parents('div').find('.post-signature:last').first().find('.user-details > a:not([id])');
    if(userlink.length) return userlink.attr('href').split('/')[2];
    return "[NULL]";
    }
    function isNewUser(date) {
    return (new Date() / 1000) - date < week
    @@ -146,15 +189,22 @@ with_jquery(function ($) {
    //http://soapi.info/code/js/stable/soapi-explore-beta.htm
    function getUserInfo(userid, container) {
    var userinfo = container.find('#userinfo');
    if(isNaN(userid)) {
    userinfo.fadeOutAndRemove();
    return;
    }
    $.ajax({
    type: "GET",
    url: siteurl.replace('http://', 'http://api.') + '/1.0/users/' + userid + '?jsonp=?',
    url: 'http://api.' + siteurl + '/1.0/users/' + userid + '?jsonp=?',
    dataType: "jsonp",
    timeout: 2000,
    success: function (data) {
    if(data['users'].length > 0) {
    var user = data['users'][0];
    if(isNewUser(user['creation_date'])) container.find('.action-desc').prepend(greeting);
    if(isNewUser(user['creation_date'])) {
    showGreeting = true;
    container.find('.action-desc').prepend(greeting);
    }

    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    @@ -178,35 +228,39 @@ with_jquery(function ($) {
    .css('width', tohide.css('width')).css('height', tohide.css('height')).css('background', 'white');

    var txt = '';
    $.each(comments, function (index, value) {
    var name = localStorage['name-' + index] || value["Name"];
    var desc = localStorage['desc-' + index] || value["Description"];
    for(var i = 0; i < GetStorage("commentcount"); i++) {
    var name = GetStorage('name-' + i);
    var desc = GetStorage('desc-' + i);
    txt += '###' + name + '\n' + desc + '\n\n'; //the leading ### makes prettier if pasting to markdown, and differentiates names from descriptions
    });
    }

    div.find('textarea').width('100%').height('95%').attr('value', txt);
    div.find('.cancel').click(function () { div.fadeOutAndRemove(); });
    div.find('.save').click(function () { DoImport(div.find('textarea').attr('value')); RewriteComments(popup); div.fadeOutAndRemove(); });
    div.find('.save').click(function () { DoImport(div.find('textarea').attr('value')); WriteComments(popup); div.fadeOutAndRemove(); });

    popup.append(div);
    }

    //Import complete text into comments
    function DoImport(text) {
    //first time through on V1.0.8, clear out any existing stuff
    ClearStorage("name-"); ClearStorage("desc-");
    var arr = text.split('\n');
    var nameIndex = 0, descIndex = 0;
    for(var i = 0; i < arr.length; i++) {
    if(arr[i].indexOf('#') == 0) {
    var name = arr[i].replace(/^#+/g, '');
    Save('name-' + nameIndex, name);
    SetStorage('name-' + nameIndex, name);
    nameIndex++;
    }
    else if(arr[i].length > 0) {
    var desc = arr[i];
    Save('desc-' + descIndex, desc);
    SetStorage('desc-' + descIndex, desc);
    descIndex++;
    }
    }
    //This is de-normalised, but I don't care.
    SetStorage("commentcount", Math.min(nameIndex, descIndex));
    }

    function htmlToMarkDown(html) {
    @@ -225,7 +279,7 @@ with_jquery(function ($) {
    var txt = $('<textarea />').css('height', 2 * el.height())
    .css('width', el.css('width'))
    .attr('value', htmlToMarkDown(html).replace(greeting, '')); //remove greeting before editing..

    BorkFor(el); //this is a hack
    //save/cancel links to add to textarea
    var commands = $('<a>save</a>').click(function () { SaveEditable($(this).parent()); UnborkFor(el); })
    @@ -248,80 +302,79 @@ with_jquery(function ($) {
    //Save textarea contents, replace element html with new edited content
    function SaveEditable(el) {
    var html = markDownToHtml(el.find('textarea').attr('value'));
    var regname = new RegExp(sitename, "g"), regurl = new RegExp(siteurl, "g");
    var regname = new RegExp(sitename, "g"), regurl = new RegExp('http://' + siteurl, "g");
    //put tags back in (in preparation for import/export)
    var taggedhtml = html.replace(regname, '$SITENAME$').replace(regurl, '$SITEURL$');
    Save(el.attr('id'), taggedhtml);
    el.html(html);
    var taggedhtml = html.replace(regname, '$SITENAME$').replace(regurl, 'http://$SITEURL$');
    SetStorage(el.attr('id'), taggedhtml);
    el.html((showGreeting ? greeting : "") + html);
    }
    function CancelEditable(el, backup) {
    el.html(backup);
    }
    //only insert into storage if not same as default
    function Save(id, value) {
    var def = GetDefaultOf(id);
    if(def != value)
    localStorage.setItem(id, value);
    else
    localStorage.removeItem(id);
    }
    //Get default name/desc of given id
    function GetDefaultOf(id) {
    var index = id.replace(/[^\d]*/g, '');
    if(id.indexOf('name') > -1)
    return comments[index]["Name"];
    else
    return comments[index]["Description"];
    }
    //Empty all custom comments from storage and rewrite to ui
    function ResetComments(popup) {
    for(var i = 0; i < comments.length; i++) {
    localStorage.removeItem('name-' + i);
    localStorage.removeItem('desc-' + i);
    function ResetComments() {
    ClearStorage("name-"); ClearStorage("desc-");
    $.each(defaultcomments, function (index, value) {
    SetStorage('name-' + index, value["Name"]);
    SetStorage('desc-' + index, value["Description"]);
    });
    SetStorage("commentcount", defaultcomments.length);
    }

    //<-----Delete this in V1.0.9---->
    function UpgradeComments() {
    //this adds default comments, but with prefix in front of key (so it's not squashing old ones)
    ResetComments();
    //this checks for 'old' custom comments and overwrites them onto prefixed-key storage
    for(var i = 0; i < defaultcomments.length; i++) {
    UpgradeStorage("name-" + i);
    UpgradeStorage("desc-" + i);
    //this shouldn't break anything, but it is a bit fragile....
    SetStorage("desc-" + i, GetStorage("desc-" + i).replace(/\$SITEURL\$/g, "http://$SITEURL$"));
    }
    RewriteComments(popup);
    }

    //rewrite all comments to ui (typically after import or reset)
    function RewriteComments(popup) {
    $.each(comments, function (index, value) {
    var name = localStorage['name-' + index] || value["Name"];
    var desc = localStorage['desc-' + index] || value["Description"];
    popup.find('#name-' + index).html(name);
    popup.find('#desc-' + index).html(desc.replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    });
    function WriteComments(popup) {
    if(!GetStorage("commentcount")) UpgradeComments(); // << change this to ResetComments in V1.0.9
    var ul = popup.find('.action-list');
    ul.empty();
    for(var i = 0; i < GetStorage("commentcount"); i++) {
    var desc = GetStorage('desc-' + i).replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl);
    var opt = option.replace(/\$ID\$/g, i)
    .replace("$NAME$", GetStorage('name-' + i))
    .replace("$DESCRIPTION$", (showGreeting ? greeting : "") + desc);
    ul.append(opt);
    }
    ShowHideDescriptions(popup);
    }
    //Gist doesn't yet provide a jsonp api, so we hack by looking for my comments on the stackapps question
    function GetLatestVersion(site, question, user, callback) {
    $.ajax({
    type: "GET",
    url: "http://api." + site + "/1.0/posts/" + question + "/comments?jsonp=?",
    dataType: "jsonp",
    success: function (data) {
    for(var i = 0; i < data["comments"].length; i++) {
    var comment = data["comments"][i];
    if(comment["owner"]["display_name"] == user
    && comment["body"].match(/^V\d+\.\d+\.\d+/i)) { //i.e. comment starts with V1.0.0 or similar
    callback(comment["body"].replace(/^V(\d+\.\d+\.\d+).*/i, '$1'));
    break;
    }
    }
    }
    });

    //Adjust the descriptions so they show or hide based on the user's preference.
    function ShowHideDescriptions(popup) {
    var descriptions = popup.find("ul.action-list span[id*='desc-']");

    if(GetStorage('hide-desc') == "hide") {
    descriptions.hide();
    }
    else {
    descriptions.show();
    }
    }

    //Check to see if a new version has become available since last check
    // only checks once a day, and won't notify user twice
    function CheckForNewVersion(site, question, user) {
    function CheckForNewVersion() {
    UpgradeStorage("LastUpdateCheckDay"); ///<<<<--- Remove this for 1.0.9
    var today = (new Date().setHours(0, 0, 0, 0));
    var lastCheck = localStorage["LastUpdateCheckDay"];
    var lastCheck = GetStorage("LastUpdateCheckDay");
    if(lastCheck != null && lastCheck != today) {
    GetLatestVersion(site, question, user, function (latestVersion) {
    if(latestVersion != scriptVersion)
    notify.show('A new version (' + latestVersion + ') of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> is now available (this notification will only appear once per new version).', -123456);
    updateCheck(function (newver, oldver, url) {
    notify.show('A new version (' + newver + ') of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> userscript is now available (this notification will only appear once per new version).', -123456);
    });
    }
    localStorage.setItem("LastUpdateCheckDay", today);
    SetStorage("LastUpdateCheckDay", today);
    }

    //This is where the real work starts - add the 'auto' link next to each comment 'help' link
    $(".comments-link").each(function () {
    var divid = $(this).attr('id').replace('-link', '');
    @@ -333,32 +386,33 @@ with_jquery(function ($) {
    popup.find('.popup-close').click(function () { popup.fadeOutAndRemove(); });

    //create/add options
    $.each(comments, function (index, value) {
    var name = localStorage['name-' + index] || value["Name"];
    var desc = localStorage['desc-' + index] || value["Description"];
    var opt = option.replace(/\$ID\$/g, index)
    .replace("$NAME$", name)
    .replace("$DESCRIPTION$", desc.replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    popup.find('.action-list').append(opt);
    });
    WriteComments(popup);

    popup.find('label > span').dblclick(function () { ToEditable($(this)); });
    //add click handler to radio buttons
    popup.find('input:radio').click(function () {
    popup.find('.popup-submit').attr("disabled", ""); //enable submit button
    //unset/set selected class
    $(this).parents('ul').find(".action-selected").removeClass("action-selected");
    $(this).parent().addClass('action-selected');
    //}
    });

    //Add handlers for command links
    popup.find('.popup-actions-cancel').click(function () { popup.fadeOutAndRemove(); });
    popup.find('.popup-actions-reset').click(function () { ResetComments(popup); });
    popup.find('.popup-actions-reset').click(function () { ResetComments(); WriteComments(popup); });
    popup.find('.popup-actions-see').hover(function () {
    popup.fadeTo('fast', '0.4').find('.popup-active-pane').fadeTo('fast', '0.0')
    popup.fadeTo('fast', '0.4').children().not('#close').fadeTo('fast', '0.0')
    }, function () {
    popup.fadeTo('fast', '1.0').find('.popup-active-pane').fadeTo('fast', '1.0')
    popup.fadeTo('fast', '1.0').children().not('#close').fadeTo('fast', '1.0')
    });
    popup.find('.popup-actions-impexp').click(function () { ImportExport(popup); });
    popup.find('.popup-actions-toggledesc').click(function () {
    var hideDesc = GetStorage('hide-desc') || "show";
    SetStorage('hide-desc', hideDesc == "show" ? "hide" : "show");
    ShowHideDescriptions(popup);
    });

    //on submit, convert html to markdown and copy to comment textarea
    popup.find('.popup-submit').click(function () {
    var selected = popup.find('input:radio:checked');
    @@ -375,8 +429,8 @@ with_jquery(function ($) {
    getUserInfo(userid, popup);

    //We only actually perform the updates check when someone clicks, this should make it less costly, and more timely
    //also wrap it so that it only gets called the *FIRST* time.
    if(!window.VersionChecked) { CheckForNewVersion("stackapps.com", 2116, "Benjol"); window.VersionChecked = true; }
    //also wrap it so that it only gets called the *FIRST* time we open this dialog on any given page (not much of an optimisation).
    if(!window.VersionChecked) { CheckForNewVersion(); window.VersionChecked = true; }
    }));
    $('#' + divid).find('.comment-help-link').parent().append(newspan);
    });
  14. @Benjol Benjol revised this gist Mar 4, 2011. 1 changed file with 106 additions and 32 deletions.
    138 changes: 106 additions & 32 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.6
    // @version 1.0.7
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*serverfault.com/questions*
    @@ -23,7 +23,7 @@ function with_jquery(f) {

    with_jquery(function ($) {
    $(function () {
    var scriptVersion = '1.0.6'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var scriptVersion = '1.0.7'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var siteurl = 'http://' + window.location.hostname; //include http in here so we don't get confusion between so and meta.so
    var arr = document.title.split(' - ');
    var sitename = arr[arr.length - 1];
    @@ -33,9 +33,9 @@ with_jquery(function ($) {
    var markup = ' \
    <div id="popup" class="popup" style="width:690px; position: absolute; display: block"> \
    <div class="popup-close"><a title="close this popup (or hit Esc)">&#215;</a></div> \
    <div style="overflow:hidden"> \
    <h2>Which review comment to insert?</h2> \
    <div style="overflow:hidden" id="main"> \
    <div class="popup-active-pane"> \
    <h2>Which review comment to insert?</h2> \
    <div id="userinfo" class="owner" style="padding:5px"> \
    <img src="http://sstatic.net/img/progress-dots.gif"/> \
    </div> \
    @@ -50,7 +50,9 @@ with_jquery(function ($) {
    <span class="lsep"> | </span> \
    <a class="popup-actions-see">see-through</a> \
    <span class="lsep"> | </span> \
    <a title="reset any custom messages" class="popup-actions-reset">reset</a> \
    <a title="reset any custom comments" class="popup-actions-reset">reset</a> \
    <span class="lsep"> | </span> \
    <a title="use this to import/export all comments" class="popup-actions-impexp">import/export</a> \
    </div> \
    <div style="float:right"> \
    <input class="popup-submit" type="button" disabled="disabled" style="float:none; margin-left: 5px" value="Insert"> \
    @@ -70,7 +72,7 @@ with_jquery(function ($) {

    //default comments
    var comments = [
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="$SITEURL$/priveleges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="$SITEURL$/privileges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, <a href="http://meta.stackoverflow.com/q/8259">it would be preferable</a> to include the essential parts of the answer here, and provide the link for reference.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "OP using an answer for further information", Description: 'Please use the <em>Post answer</em> button only for actual answers. You should modify your original question to add additional information.' },
    @@ -81,6 +83,7 @@ with_jquery(function ($) {
    var weekday_name = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    var minute = 60, hour = 3600, day = 86400, sixdays = 518400, week = 604800, month = 2592000, year = 31536000;

    //Calculate and format datespan for "Member since/for"
    function datespan(date) {
    var now = new Date() / 1000;
    var then = new Date(date * 1000);
    @@ -105,6 +108,7 @@ with_jquery(function ($) {
    return strout;
    }

    //Calculate and format datespan for "Last seen"
    function lastseen(date) {
    var now = new Date() / 1000;
    var today = new Date().setHours(0, 0, 0) / 1000;
    @@ -119,6 +123,7 @@ with_jquery(function ($) {
    return then.toDateString();
    }

    //Format reputation string
    function repNumber(r) {
    if(r < 1E4) return r;
    else if(r < 1E5) {
    @@ -129,16 +134,18 @@ with_jquery(function ($) {
    else return Math.round(r / 1E3) + "k"
    }

    //Get userId for post
    function getUserId(el) {
    return el.parents('div')
    .find('.post-signature:last')
    .find('.user-details > a')
    .attr('href').split('/')[2];
    return el.parents('div').find('.post-signature:last').find('.user-details > a').attr('href').split('/')[2];
    }
    function isNewUser(date) {
    return (new Date() / 1000) - date < week
    }

    //Ajax to Stack Exchange api to get basic user info, and paste into userinfo element
    //http://soapi.info/code/js/stable/soapi-explore-beta.htm
    function getUserInfo(userid, container) {
    var userinfo = container.find('#userinfo');
    //http://soapi.info/code/js/stable/soapi-explore-beta.htm
    $.ajax({
    type: "GET",
    url: siteurl.replace('http://', 'http://api.') + '/1.0/users/' + userid + '?jsonp=?',
    @@ -147,11 +154,9 @@ with_jquery(function ($) {
    success: function (data) {
    if(data['users'].length > 0) {
    var user = data['users'][0];
    if(isNewUser(user['creation_date'])) {
    container.find('.action-desc').prepend(greeting);
    }
    if(isNewUser(user['creation_date'])) container.find('.action-desc').prepend(greeting);

    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    last seen <strong>' + lastseen(user['last_access_date']) + '</strong>, \
    reputation <strong>' + repNumber(user['reputation']) + '</strong>';
    @@ -163,8 +168,45 @@ with_jquery(function ($) {
    error: function () { userinfo.fadeOutAndRemove(); }
    });
    }
    function isNewUser(date) {
    return (new Date() / 1000) - date < week

    //Show textarea in front of popup to import/export all comments (for other sites or for posting somewhere)
    function ImportExport(popup) {
    var tohide = popup.find('#main');
    var div = $('<div><textarea/><a class="save">save</a><span class="lsep"> | </span><a class="cancel">cancel</a></div>');
    //Painful, but shortest way I've found to position div over the tohide element
    div.css('position', 'absolute').css('left', tohide.position().left).css('top', tohide.position().top)
    .css('width', tohide.css('width')).css('height', tohide.css('height')).css('background', 'white');

    var txt = '';
    $.each(comments, function (index, value) {
    var name = localStorage['name-' + index] || value["Name"];
    var desc = localStorage['desc-' + index] || value["Description"];
    txt += '###' + name + '\n' + desc + '\n\n'; //the leading ### makes prettier if pasting to markdown, and differentiates names from descriptions
    });

    div.find('textarea').width('100%').height('95%').attr('value', txt);
    div.find('.cancel').click(function () { div.fadeOutAndRemove(); });
    div.find('.save').click(function () { DoImport(div.find('textarea').attr('value')); RewriteComments(popup); div.fadeOutAndRemove(); });

    popup.append(div);
    }

    //Import complete text into comments
    function DoImport(text) {
    var arr = text.split('\n');
    var nameIndex = 0, descIndex = 0;
    for(var i = 0; i < arr.length; i++) {
    if(arr[i].indexOf('#') == 0) {
    var name = arr[i].replace(/^#+/g, '');
    Save('name-' + nameIndex, name);
    nameIndex++;
    }
    else if(arr[i].length > 0) {
    var desc = arr[i];
    Save('desc-' + descIndex, desc);
    descIndex++;
    }
    }
    }

    function htmlToMarkDown(html) {
    @@ -176,23 +218,25 @@ with_jquery(function ($) {
    html = markdown.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>');
    return html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>').replace(/\*(.+?)\*/g, '<em>$1</em>');
    }
    //Replace contents of element with a textarea (containing markdown of contents), and save/cancel buttons
    function ToEditable(el) {
    var html = el.html();
    if(html.indexOf('<textarea') > -1) return; //don't want to create a new textarea inside this one!
    var txt = $('<textarea />').css('height', 2 * el.height())
    .css('width', el.css('width'))
    .attr('value', htmlToMarkDown(html).replace(greeting, ''));
    //This is to stop the input pinching focus when I click inside textarea
    //Could have done something clever with contentEditable, but this is evil, and it annoys Yi :P
    BorkFor(el);
    .attr('value', htmlToMarkDown(html).replace(greeting, '')); //remove greeting before editing..

    BorkFor(el); //this is a hack
    //save/cancel links to add to textarea
    var commands = $('<a>save</a>').click(function () { SaveEditable($(this).parent(), html); UnborkFor(el); })
    var commands = $('<a>save</a>').click(function () { SaveEditable($(this).parent()); UnborkFor(el); })
    .add('<span class="lsep"> | </span>')
    .add($('<a>cancel</a>').click(function () { CancelEditable($(this).parent(), html); UnborkFor(el); }));
    //set contents of element to textarea with links
    el.html(txt.add(commands));
    }

    //This is to stop the input pinching focus when I click inside textarea
    //Could have done something clever with contentEditable, but this is evil, and it annoys Yi :P
    function BorkFor(el) {
    var label = el.parent('label');
    label.attr('for', 'borken');
    @@ -201,20 +245,49 @@ with_jquery(function ($) {
    var label = el.parent('label');
    label.attr('for', label.prev().attr('id'));
    }
    function SaveEditable(el, backup) {
    //Save textarea contents, replace element html with new edited content
    function SaveEditable(el) {
    var html = markDownToHtml(el.find('textarea').attr('value'));
    if(html != backup) localStorage.setItem(el.attr('id'), html);
    var regname = new RegExp(sitename, "g"), regurl = new RegExp(siteurl, "g");
    //put tags back in (in preparation for import/export)
    var taggedhtml = html.replace(regname, '$SITENAME$').replace(regurl, '$SITEURL$');
    Save(el.attr('id'), taggedhtml);
    el.html(html);
    }
    function CancelEditable(el, backup) {
    el.html(backup);
    }
    //only insert into storage if not same as default
    function Save(id, value) {
    var def = GetDefaultOf(id);
    if(def != value)
    localStorage.setItem(id, value);
    else
    localStorage.removeItem(id);
    }
    //Get default name/desc of given id
    function GetDefaultOf(id) {
    var index = id.replace(/[^\d]*/g, '');
    if(id.indexOf('name') > -1)
    return comments[index]["Name"];
    else
    return comments[index]["Description"];
    }
    //Empty all custom comments from storage and rewrite to ui
    function ResetComments(popup) {
    for(var i = 0; i < comments.length; i++) {
    localStorage.removeItem('name-' + i);
    localStorage.removeItem('desc-' + i);
    }
    RewriteComments(popup);
    }
    //rewrite all comments to ui (typically after import or reset)
    function RewriteComments(popup) {
    $.each(comments, function (index, value) {
    localStorage.setItem('name-' + index, '');
    localStorage.setItem('desc-' + index, '');
    popup.find('#name-' + index).html(value["Name"]);
    popup.find('#desc-' + index).html(value["Description"].replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    var name = localStorage['name-' + index] || value["Name"];
    var desc = localStorage['desc-' + index] || value["Description"];
    popup.find('#name-' + index).html(name);
    popup.find('#desc-' + index).html(desc.replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    });
    }
    //Gist doesn't yet provide a jsonp api, so we hack by looking for my comments on the stackapps question
    @@ -247,9 +320,9 @@ with_jquery(function ($) {
    notify.show('A new version (' + latestVersion + ') of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> is now available (this notification will only appear once per new version).', -123456);
    });
    }
    localStorage["LastUpdateCheckDay"] = today;
    localStorage.setItem("LastUpdateCheckDay", today);
    }

    //This is where the real work starts - add the 'auto' link next to each comment 'help' link
    $(".comments-link").each(function () {
    var divid = $(this).attr('id').replace('-link', '');
    $(this).click(function () {
    @@ -262,10 +335,10 @@ with_jquery(function ($) {
    //create/add options
    $.each(comments, function (index, value) {
    var name = localStorage['name-' + index] || value["Name"];
    var desc = localStorage['desc-' + index] || value["Description"].replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl);
    var desc = localStorage['desc-' + index] || value["Description"];
    var opt = option.replace(/\$ID\$/g, index)
    .replace("$NAME$", name)
    .replace("$DESCRIPTION$", desc);
    .replace("$DESCRIPTION$", desc.replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    popup.find('.action-list').append(opt);
    });
    popup.find('label > span').dblclick(function () { ToEditable($(this)); });
    @@ -285,6 +358,7 @@ with_jquery(function ($) {
    }, function () {
    popup.fadeTo('fast', '1.0').find('.popup-active-pane').fadeTo('fast', '1.0')
    });
    popup.find('.popup-actions-impexp').click(function () { ImportExport(popup); });
    //on submit, convert html to markdown and copy to comment textarea
    popup.find('.popup-submit').click(function () {
    var selected = popup.find('input:radio:checked');
  15. @Benjol Benjol revised this gist Mar 4, 2011. 1 changed file with 9 additions and 7 deletions.
    16 changes: 9 additions & 7 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,17 +1,19 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.5
    // @version 1.0.6
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*.stackexchange.com/questions*
    // @include http://*.askubuntu.com/questions*
    // @include http://*.serverfault.com/questions*
    // @include http://*.superuser.com/questions*
    // @include http://*serverfault.com/questions*
    // @include http://*superuser.com/questions*
    // @include http://*stackexchange.com/questions*
    // @include http://*askubuntu.com/questions*
    // @include http://*answers.onstartups.com/questions*
    // @include http://mathoverflow.net/questions*
    // @include http://discuss.area51.stackexchange.com/questions/*
    // @include http://stackapps.com/questions*
    // ==/UserScript==


    function with_jquery(f) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    @@ -21,7 +23,7 @@ function with_jquery(f) {

    with_jquery(function ($) {
    $(function () {
    var scriptVersion = '1.0.5'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var scriptVersion = '1.0.6'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var siteurl = 'http://' + window.location.hostname; //include http in here so we don't get confusion between so and meta.so
    var arr = document.title.split(' - ');
    var sitename = arr[arr.length - 1];
  16. @Benjol Benjol revised this gist Mar 3, 2011. 1 changed file with 13 additions and 10 deletions.
    23 changes: 13 additions & 10 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.4
    // @version 1.0.5
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*.stackexchange.com/questions*
    @@ -11,6 +11,7 @@
    // @include http://stackapps.com/questions*
    // ==/UserScript==


    function with_jquery(f) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    @@ -20,6 +21,7 @@ function with_jquery(f) {

    with_jquery(function ($) {
    $(function () {
    var scriptVersion = '1.0.5'; //<<<<<<<<<<<<*********************** DON'T FORGET TO UPDATE THIS!!!! *************************
    var siteurl = 'http://' + window.location.hostname; //include http in here so we don't get confusion between so and meta.so
    var arr = document.title.split(' - ');
    var sitename = arr[arr.length - 1];
    @@ -126,9 +128,10 @@ with_jquery(function ($) {
    }

    function getUserId(el) {
    var div = el.parents('div');
    var selector = div.hasClass('answer') ? '.post-signature:last' : '.post-signature.owner';
    return div.find(selector).find('.user-details > a').attr('href').split('/')[2];
    return el.parents('div')
    .find('.post-signature:last')
    .find('.user-details > a')
    .attr('href').split('/')[2];
    }

    function getUserInfo(userid, container) {
    @@ -213,7 +216,7 @@ with_jquery(function ($) {
    });
    }
    //Gist doesn't yet provide a jsonp api, so we hack by looking for my comments on the stackapps question
    function GetLatestVersionDate(site, question, user, callback) {
    function GetLatestVersion(site, question, user, callback) {
    $.ajax({
    type: "GET",
    url: "http://api." + site + "/1.0/posts/" + question + "/comments?jsonp=?",
    @@ -222,8 +225,8 @@ with_jquery(function ($) {
    for(var i = 0; i < data["comments"].length; i++) {
    var comment = data["comments"][i];
    if(comment["owner"]["display_name"] == user
    && comment["body"].match(/^V\d\.\d\.\d/i)) { //i.e. comment starts with V1.0.0 or similar
    callback(new Date(comment["creation_date"] * 1000));
    && comment["body"].match(/^V\d+\.\d+\.\d+/i)) { //i.e. comment starts with V1.0.0 or similar
    callback(comment["body"].replace(/^V(\d+\.\d+\.\d+).*/i, '$1'));
    break;
    }
    }
    @@ -237,9 +240,9 @@ with_jquery(function ($) {
    var today = (new Date().setHours(0, 0, 0, 0));
    var lastCheck = localStorage["LastUpdateCheckDay"];
    if(lastCheck != null && lastCheck != today) {
    GetLatestVersionDate(site, question, user, function (date) {
    if(date > lastCheck)
    notify.show('A new version of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> is now available (this notification will only appear once per new version).', -123456);
    GetLatestVersion(site, question, user, function (latestVersion) {
    if(latestVersion != scriptVersion)
    notify.show('A new version (' + latestVersion + ') of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> is now available (this notification will only appear once per new version).', -123456);
    });
    }
    localStorage["LastUpdateCheckDay"] = today;
  17. @Benjol Benjol revised this gist Mar 1, 2011. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.3
    // @version 1.0.4
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*.stackexchange.com/questions*
    @@ -127,8 +127,8 @@ with_jquery(function ($) {

    function getUserId(el) {
    var div = el.parents('div');
    var selector = div.hasClass('answer') ? '.post-signature' : '.post-signature.owner';
    return div.find(selector).find('.user-details > a').attr('href').replace(/[^\d]/g, '');
    var selector = div.hasClass('answer') ? '.post-signature:last' : '.post-signature.owner';
    return div.find(selector).find('.user-details > a').attr('href').split('/')[2];
    }

    function getUserInfo(userid, container) {
  18. @Benjol Benjol revised this gist Mar 1, 2011. 1 changed file with 42 additions and 5 deletions.
    47 changes: 42 additions & 5 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.2
    // @version 1.0.3
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*.stackexchange.com/questions*
    @@ -42,7 +42,7 @@ with_jquery(function ($) {
    <div style="float: left; margin-top: 18px;"> \
    <a title="close this popup (or hit Esc)" class="popup-actions-cancel">cancel</a> \
    <span class="lsep"> | </span> \
    <a title="see info about this popup" class="popup-actions-help" href="http://stackapps.com/questions/2116/pro-forma-comments-for-review-educating-users-before-flagging" target="_blank">info</a> \
    <a title="see info about this popup" class="popup-actions-help" href="http://stackapps.com/q/2116" target="_blank">info</a> \
    <span class="lsep"> | </span> \
    <a class="popup-actions-see">see-through</a> \
    <span class="lsep"> | </span> \
    @@ -67,7 +67,7 @@ with_jquery(function ($) {
    //default comments
    var comments = [
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="$SITEURL$/priveleges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, <a href="http://meta.stackoverflow.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers/8259#8259">it would be preferable</a> to include the essential parts of the answer here, and provide the link for reference.' },
    { Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, <a href="http://meta.stackoverflow.com/q/8259">it would be preferable</a> to include the essential parts of the answer here, and provide the link for reference.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "OP using an answer for further information", Description: 'Please use the <em>Post answer</em> button only for actual answers. You should modify your original question to add additional information.' },
    { Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the <a href="$SITEURL$/questions/ask">Ask Question</a> button.' },
    @@ -119,7 +119,7 @@ with_jquery(function ($) {
    if(r < 1E4) return r;
    else if(r < 1E5) {
    var d = Math.floor(Math.round(r / 100) / 10);
    r = Math.round((a - d * 1E3) / 100);
    r = Math.round((r - d * 1E3) / 100);
    return d + (r > 0 ? "." + r : "") + "k"
    }
    else return Math.round(r / 1E3) + "k"
    @@ -150,6 +150,7 @@ with_jquery(function ($) {
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    last seen <strong>' + lastseen(user['last_access_date']) + '</strong>, \
    reputation <strong>' + repNumber(user['reputation']) + '</strong>';

    userinfo.html(html.replace(/ +/g, ' '));
    }
    else userinfo.fadeOutAndRemove();
    @@ -211,6 +212,39 @@ with_jquery(function ($) {
    popup.find('#desc-' + index).html(value["Description"].replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    });
    }
    //Gist doesn't yet provide a jsonp api, so we hack by looking for my comments on the stackapps question
    function GetLatestVersionDate(site, question, user, callback) {
    $.ajax({
    type: "GET",
    url: "http://api." + site + "/1.0/posts/" + question + "/comments?jsonp=?",
    dataType: "jsonp",
    success: function (data) {
    for(var i = 0; i < data["comments"].length; i++) {
    var comment = data["comments"][i];
    if(comment["owner"]["display_name"] == user
    && comment["body"].match(/^V\d\.\d\.\d/i)) { //i.e. comment starts with V1.0.0 or similar
    callback(new Date(comment["creation_date"] * 1000));
    break;
    }
    }
    }
    });
    }

    //Check to see if a new version has become available since last check
    // only checks once a day, and won't notify user twice
    function CheckForNewVersion(site, question, user) {
    var today = (new Date().setHours(0, 0, 0, 0));
    var lastCheck = localStorage["LastUpdateCheckDay"];
    if(lastCheck != null && lastCheck != today) {
    GetLatestVersionDate(site, question, user, function (date) {
    if(date > lastCheck)
    notify.show('A new version of the <a href="http://stackapps.com/q/2116">AutoReviewComments</a> is now available (this notification will only appear once per new version).', -123456);
    });
    }
    localStorage["LastUpdateCheckDay"] = today;
    }

    $(".comments-link").each(function () {
    var divid = $(this).attr('id').replace('-link', '');
    $(this).click(function () {
    @@ -261,9 +295,12 @@ with_jquery(function ($) {
    var userid = getUserId($(this));
    getUserInfo(userid, popup);

    //We only actually perform the updates check when someone clicks, this should make it less costly, and more timely
    //also wrap it so that it only gets called the *FIRST* time.
    if(!window.VersionChecked) { CheckForNewVersion("stackapps.com", 2116, "Benjol"); window.VersionChecked = true; }
    }));
    $('#' + divid).find('.comment-help-link').parent().append(newspan);
    });
    });
    });
    });
    });
  19. @Benjol Benjol revised this gist Feb 28, 2011. 1 changed file with 119 additions and 60 deletions.
    179 changes: 119 additions & 60 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.1
    // @version 1.0.2
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*.stackexchange.com/questions*
    @@ -20,10 +20,12 @@ function with_jquery(f) {

    with_jquery(function ($) {
    $(function () {
    var siteurl = window.location.hostname;
    var siteurl = 'http://' + window.location.hostname; //include http in here so we don't get confusion between so and meta.so
    var arr = document.title.split(' - ');
    var sitename = arr[arr.length - 1];
    if(sitename == "Stack Exchange") sitename = arr[arr.length - 2]; //workaround for SE sites..
    var greeting = 'Welcome to ' + sitename + '! ';

    var markup = ' \
    <div id="popup" class="popup" style="width:690px; position: absolute; display: block"> \
    <div class="popup-close"><a title="close this popup (or hit Esc)">&#215;</a></div> \
    @@ -38,11 +40,13 @@ with_jquery(function ($) {
    </div> \
    <div class="popup-actions"> \
    <div style="float: left; margin-top: 18px;"> \
    <a class="popup-actions-cancel">cancel</a> \
    <a title="close this popup (or hit Esc)" class="popup-actions-cancel">cancel</a> \
    <span class="lsep"> | </span> \
    <a class="popup-actions-help" href="http://meta.stackoverflow.com/questions/74194/how-to-review-can-we-agree-on-a-review-policy" target="_blank">info</a> \
    <a title="see info about this popup" class="popup-actions-help" href="http://stackapps.com/questions/2116/pro-forma-comments-for-review-educating-users-before-flagging" target="_blank">info</a> \
    <span class="lsep"> | </span> \
    <a class="popup-actions-see">see-through</a> \
    <span class="lsep"> | </span> \
    <a title="reset any custom messages" class="popup-actions-reset">reset</a> \
    </div> \
    <div style="float:right"> \
    <input class="popup-submit" type="button" disabled="disabled" style="float:none; margin-left: 5px" value="Insert"> \
    @@ -51,22 +55,23 @@ with_jquery(function ($) {
    </div> \
    </div>';

    var option = ' \
    <li> \
    <input id="$ID$" type="radio" name="commentreview"/> \
    <label for="$ID$"> \
    <span class="action-name">$NAME$</span> \
    <span class="action-desc">$DESCRIPTION$</span> \
    </label> \
    var option = ' \
    <li> \
    <input id="comment-$ID$" type="radio" name="commentreview"/> \
    <label for="comment-$ID$"> \
    <span id="name-$ID$" class="action-name">$NAME$</span> \
    <span id="desc-$ID$" class="action-desc">$DESCRIPTION$</span> \
    </label> \
    </li>';

    //default comments
    var comments = [
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="http://$SITEURL$/priveleges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="$SITEURL$/priveleges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, <a href="http://meta.stackoverflow.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers/8259#8259">it would be preferable</a> to include the essential parts of the answer here, and provide the link for reference.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="http://$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "OP using an answer for further information", Description: 'Please use the <em>Post answer</em> button only for actual answers. You should modify your original question to add additional information.' },
    { Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button.' },
    { Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button. If you have sufficient reputation, <a href="http://$SITEURL$/privileges/vote-up">you may upvote</a> the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
    { Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the <a href="$SITEURL$/questions/ask">Ask Question</a> button.' },
    { Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the <a href="$SITEURL$/questions/ask">Ask Question</a> button. If you have sufficient reputation, <a href="$SITEURL$/privileges/vote-up">you may upvote</a> the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
    ];

    var weekday_name = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    @@ -126,24 +131,116 @@ with_jquery(function ($) {
    return div.find(selector).find('.user-details > a').attr('href').replace(/[^\d]/g, '');
    }

    function getUserInfo(userid, container) {
    var userinfo = container.find('#userinfo');
    //http://soapi.info/code/js/stable/soapi-explore-beta.htm
    $.ajax({
    type: "GET",
    url: siteurl.replace('http://', 'http://api.') + '/1.0/users/' + userid + '?jsonp=?',
    dataType: "jsonp",
    timeout: 2000,
    success: function (data) {
    if(data['users'].length > 0) {
    var user = data['users'][0];
    if(isNewUser(user['creation_date'])) {
    container.find('.action-desc').prepend(greeting);
    }

    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    last seen <strong>' + lastseen(user['last_access_date']) + '</strong>, \
    reputation <strong>' + repNumber(user['reputation']) + '</strong>';
    userinfo.html(html.replace(/ +/g, ' '));
    }
    else userinfo.fadeOutAndRemove();
    },
    error: function () { userinfo.fadeOutAndRemove(); }
    });
    }
    function isNewUser(date) {
    return (new Date() / 1000) - date < week
    }

    function htmlToMarkDown(html) {
    html = html.replace(/<a href="(.+?)">(.+?)<\/a>/g, '[$2]($1)');
    return html.replace(/<em>(.+?)<\/em>/g, '*$1*');
    markdown = html.replace(/<a href="(.+?)">(.+?)<\/a>/g, '[$2]($1)');
    return markdown.replace(/<em>(.+?)<\/em>/g, '*$1*').replace(/<strong>(.+?)<\/strong>/g, '**$1**');
    }

    function markDownToHtml(markdown) {
    html = markdown.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>');
    return html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>').replace(/\*(.+?)\*/g, '<em>$1</em>');
    }
    function ToEditable(el) {
    var html = el.html();
    if(html.indexOf('<textarea') > -1) return; //don't want to create a new textarea inside this one!
    var txt = $('<textarea />').css('height', 2 * el.height())
    .css('width', el.css('width'))
    .attr('value', htmlToMarkDown(html).replace(greeting, ''));
    //This is to stop the input pinching focus when I click inside textarea
    //Could have done something clever with contentEditable, but this is evil, and it annoys Yi :P
    BorkFor(el);
    //save/cancel links to add to textarea
    var commands = $('<a>save</a>').click(function () { SaveEditable($(this).parent(), html); UnborkFor(el); })
    .add('<span class="lsep"> | </span>')
    .add($('<a>cancel</a>').click(function () { CancelEditable($(this).parent(), html); UnborkFor(el); }));
    //set contents of element to textarea with links
    el.html(txt.add(commands));
    }

    function BorkFor(el) {
    var label = el.parent('label');
    label.attr('for', 'borken');
    }
    function UnborkFor(el) {
    var label = el.parent('label');
    label.attr('for', label.prev().attr('id'));
    }
    function SaveEditable(el, backup) {
    var html = markDownToHtml(el.find('textarea').attr('value'));
    if(html != backup) localStorage.setItem(el.attr('id'), html);
    el.html(html);
    }
    function CancelEditable(el, backup) {
    el.html(backup);
    }
    function ResetComments(popup) {
    $.each(comments, function (index, value) {
    localStorage.setItem('name-' + index, '');
    localStorage.setItem('desc-' + index, '');
    popup.find('#name-' + index).html(value["Name"]);
    popup.find('#desc-' + index).html(value["Description"].replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    });
    }
    $(".comments-link").each(function () {
    var divid = $(this).attr('id').replace('-link', '');
    $(this).click(function () {
    var newspan = $('<span class="lsep"> | </span>').add($('<a>auto</a>').click(function () {
    if($('#' + divid).find('.comment-auto-link').length > 0) return; //don't create auto link if already there
    var newspan = $('<span class="lsep"> | </span>').add($('<a class="comment-auto-link">auto</a>').click(function () {
    //Create popup and wire-up the functionality
    var popup = $(markup);
    popup.find('.popup-close').click(function () { popup.fadeOutAndRemove(); });

    //create/add options
    $.each(comments, function (index, value) {
    var name = localStorage['name-' + index] || value["Name"];
    var desc = localStorage['desc-' + index] || value["Description"].replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl);
    var opt = option.replace(/\$ID\$/g, index)
    .replace("$NAME$", name)
    .replace("$DESCRIPTION$", desc);
    popup.find('.action-list').append(opt);
    });
    popup.find('label > span').dblclick(function () { ToEditable($(this)); });
    //add click handler to radio buttons
    popup.find('input:radio').click(function () {
    popup.find('.popup-submit').attr("disabled", ""); //enable submit button
    //unset/set selected class
    $(this).parents('ul').find(".action-selected").removeClass("action-selected");
    $(this).parent().addClass('action-selected');
    });

    //Add handlers for command links
    popup.find('.popup-actions-cancel').click(function () { popup.fadeOutAndRemove(); });
    //set opacity on mousedown/mouseup of 'see-through' link
    popup.find('.popup-actions-reset').click(function () { ResetComments(popup); });
    popup.find('.popup-actions-see').hover(function () {
    popup.fadeTo('fast', '0.4').find('.popup-active-pane').fadeTo('fast', '0.0')
    }, function () {
    @@ -156,52 +253,14 @@ with_jquery(function ($) {
    $('#' + divid).find('textarea').attr('value', markdown).focus(); //focus provokes character count test
    popup.fadeOutAndRemove();
    });
    //create/add options
    $.each(comments, function (index, value) {
    var opt = option.replace(/\$ID\$/g, "comment-" + index)
    .replace("$NAME$", value["Name"])
    .replace("$DESCRIPTION$", value["Description"].replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    popup.find('.action-list').append(opt);
    });
    //add click handler to radio buttons
    popup.find('input:radio').click(function () {
    popup.find('.popup-submit').attr("disabled", ""); //enable submit button
    //unset/set selected class
    $(this).parents('ul').find(".action-selected").removeClass("action-selected");
    $(this).parent().addClass('action-selected');
    });
    //add popup and scroll into view
    //add popup and center on screen
    $('#' + divid).append(popup);
    popup.center();

    //Get user info and inject
    var userid = getUserId($(this));
    var userinfo = popup.find('#userinfo');
    //http://soapi.info/code/js/stable/soapi-explore-beta.htm
    $.ajax({
    type: "GET",
    url: 'http://api.' + siteurl + '/1.0/users/' + userid + '?jsonp=?',
    dataType: "jsonp",
    timeout: 2000,
    success: function (data) {
    if(data['users'].length > 0) {
    var user = data['users'][0];
    if(isNewUser(user['creation_date'])) {
    var greeting = 'Welcome to ' + sitename + '! ';
    popup.find('.action-desc').prepend(greeting);
    }

    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    last seen <strong>' + lastseen(user['last_access_date']) + '</strong>, \
    reputation <strong>' + repNumber(user['reputation']) + '</strong>';
    userinfo.html(html);
    }
    else userinfo.fadeOutAndRemove();
    },
    error: function () { userinfo.fadeOutAndRemove(); }
    });
    getUserInfo(userid, popup);

    popup.center();
    }));
    $('#' + divid).find('.comment-help-link').parent().append(newspan);
    });
  20. @Benjol Benjol revised this gist Feb 25, 2011. 1 changed file with 42 additions and 28 deletions.
    70 changes: 42 additions & 28 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.0
    // @version 1.0.1
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*.stackexchange.com/questions*
    @@ -69,53 +69,70 @@ with_jquery(function ($) {
    { Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button. If you have sufficient reputation, <a href="http://$SITEURL$/privileges/vote-up">you may upvote</a> the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
    ];

    var weekday_name = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    var weekday_name = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    var minute = 60, hour = 3600, day = 86400, sixdays = 518400, week = 604800, month = 2592000, year = 31536000;

    function datespan(date) {
    var now = new Date() / 1000;
    var then = new Date(date * 1000);
    var today = new Date().setHours(0, 0, 0) / 1000;
    var nowseconds = now - today;
    var elapsedSeconds = now - date;
    var strout = "";
    if(now - date < 6000) strout = "since today";
    else if(now - date < 86400) strout = "since yesterday";
    else if(now - date < 518400) strout = "since " + weekday_name[then.getDay()];
    else if(now - date > 31536000) {
    strout = "for " + Math.round((now - date) / 31536000) + " years";
    if(((now - date) % 31536000) > 2592000) strout += ", " + Math.round(((now - date) % 31536000) / 2592000) + " months";
    if(elapsedSeconds < nowseconds) strout = "since today";
    else if(elapsedSeconds < day + nowseconds) strout = "since yesterday";
    else if(elapsedSeconds < sixdays) strout = "since " + weekday_name[then.getDay()];
    else if(elapsedSeconds > year) {
    strout = "for " + Math.round((elapsedSeconds) / year) + " years";
    if(((elapsedSeconds) % year) > month) strout += ", " + Math.round(((elapsedSeconds) % year) / month) + " months";
    }
    else if(now - date > 2592000) {
    strout = "for " + Math.round((now - date) / 2592000) + " months";
    if(((now - date) % 2592000) > 604800) strout += ", " + Math.round(((now - date) % 2592000) / 604800) + " weeks";
    else if(elapsedSeconds > month) {
    strout = "for " + Math.round((elapsedSeconds) / month) + " months";
    if(((elapsedSeconds) % month) > week) strout += ", " + Math.round(((elapsedSeconds) % month) / week) + " weeks";
    }
    else {
    strout = "for " + Math.round((now - date) / 604800) + " weeks";
    strout = "for " + Math.round((elapsedSeconds) / week) + " weeks";
    }
    return strout;
    }

    function lastseen(date) {
    var now = new Date() / 1000;
    if(now - date < 60) return (Math.round(now - date) + " seconds ago");
    if(now - date < 3600) return (Math.round((now - date) / 60) + " minutes ago");
    if(now - date < 6000) return (Math.round((now - date) / 3600) + " hours ago");
    if(now - date < 86400) return ("yesterday");
    var today = new Date().setHours(0, 0, 0) / 1000;
    var nowseconds = now - today;
    var elapsedSeconds = now - date;
    if(elapsedSeconds < minute) return (Math.round(elapsedSeconds) + " seconds ago");
    if(elapsedSeconds < hour) return (Math.round((elapsedSeconds) / minute) + " minutes ago");
    if(elapsedSeconds < nowseconds) return (Math.round((elapsedSeconds) / hour) + " hours ago");
    if(elapsedSeconds < day + nowseconds) return ("yesterday");
    var then = new Date(date * 1000);
    if(now - date < 518400) return ("on " + weekday_name[then.getDay()]);
    if(elapsedSeconds < sixdays) return ("on " + weekday_name[then.getDay()]);
    return then.toDateString();
    }

    function repNumber(r) {
    if(r < 1E4) return r;
    else if(r < 1E5) {
    var d = Math.floor(Math.round(r / 100) / 10);
    r = Math.round((a - d * 1E3) / 100);
    return d + (r > 0 ? "." + r : "") + "k"
    }
    else return Math.round(r / 1E3) + "k"
    }

    function getUserId(el) {
    var div = el.parents('div');
    var selector = div.hasClass('answer') ? '.post-signature' : '.post-signature.owner';
    return div.find(selector).find('.user-details > a').attr('href').replace(/[^\d]/g, '');
    }

    function isNewUser(date) {
    return (new Date() / 1000) - date < 518400
    return (new Date() / 1000) - date < week
    }

    function htmlToMarkDown(html) {
    html = html.replace(/<a href="(.+)">(.+)<\/a>/g, '[$2]($1)');
    return html.replace(/<em>(.+)<\/em>/g, '*$1*');
    html = html.replace(/<a href="(.+?)">(.+?)<\/a>/g, '[$2]($1)');
    return html.replace(/<em>(.+?)<\/em>/g, '*$1*');
    }

    $(".comments-link").each(function () {
    @@ -127,13 +144,10 @@ with_jquery(function ($) {
    popup.find('.popup-close').click(function () { popup.fadeOutAndRemove(); });
    popup.find('.popup-actions-cancel').click(function () { popup.fadeOutAndRemove(); });
    //set opacity on mousedown/mouseup of 'see-through' link
    popup.find('.popup-actions-see').mousedown(function () {
    popup.css('opacity', '0.4')
    popup.find('.popup-active-pane').css('opacity', '0.0')
    });
    popup.find('.popup-actions-see').mouseup(function () {
    popup.css('opacity', '1.0')
    popup.find('.popup-active-pane').css('opacity', '1.0')
    popup.find('.popup-actions-see').hover(function () {
    popup.fadeTo('fast', '0.4').find('.popup-active-pane').fadeTo('fast', '0.0')
    }, function () {
    popup.fadeTo('fast', '1.0').find('.popup-active-pane').fadeTo('fast', '1.0')
    });
    //on submit, convert html to markdown and copy to comment textarea
    popup.find('.popup-submit').click(function () {
    @@ -179,7 +193,7 @@ with_jquery(function ($) {
    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    last seen <strong>' + lastseen(user['last_access_date']) + '</strong>, \
    reputation <strong>' + user['reputation'] + '</strong>';
    reputation <strong>' + repNumber(user['reputation']) + '</strong>';
    userinfo.html(html);
    }
    else userinfo.fadeOutAndRemove();
  21. @Benjol Benjol revised this gist Feb 24, 2011. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,7 @@
    // @include http://*.askubuntu.com/questions*
    // @include http://*.serverfault.com/questions*
    // @include http://*.superuser.com/questions*
    // @include http://stackapps.com/questions*
    // ==/UserScript==

    function with_jquery(f) {
    @@ -63,7 +64,7 @@ with_jquery(function ($) {
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="http://$SITEURL$/priveleges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, <a href="http://meta.stackoverflow.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers/8259#8259">it would be preferable</a> to include the essential parts of the answer here, and provide the link for reference.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="http://$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "OP providing using answer for further information", Description: 'Please use the <em>Post answer</em> button only for actual answers. You should modify your original question to add additional information.' },
    { Name: "OP using an answer for further information", Description: 'Please use the <em>Post answer</em> button only for actual answers. You should modify your original question to add additional information.' },
    { Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button.' },
    { Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button. If you have sufficient reputation, <a href="http://$SITEURL$/privileges/vote-up">you may upvote</a> the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
    ];
  22. @Benjol Benjol created this gist Feb 24, 2011.
    195 changes: 195 additions & 0 deletions autoreviewcomments.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,195 @@
    // ==UserScript==
    // @name AutoReviewComments
    // @namespace benjol
    // @version 1.0.0
    // @description Add pro-forma comments dialog for reviewing (pre-flag)
    // @include http://*stackoverflow.com/questions*
    // @include http://*.stackexchange.com/questions*
    // @include http://*.askubuntu.com/questions*
    // @include http://*.serverfault.com/questions*
    // @include http://*.superuser.com/questions*
    // ==/UserScript==

    function with_jquery(f) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.textContent = "(" + f.toString() + ")(jQuery)";
    document.body.appendChild(script);
    };

    with_jquery(function ($) {
    $(function () {
    var siteurl = window.location.hostname;
    var arr = document.title.split(' - ');
    var sitename = arr[arr.length - 1];
    if(sitename == "Stack Exchange") sitename = arr[arr.length - 2]; //workaround for SE sites..
    var markup = ' \
    <div id="popup" class="popup" style="width:690px; position: absolute; display: block"> \
    <div class="popup-close"><a title="close this popup (or hit Esc)">&#215;</a></div> \
    <div style="overflow:hidden"> \
    <div class="popup-active-pane"> \
    <h2>Which review comment to insert?</h2> \
    <div id="userinfo" class="owner" style="padding:5px"> \
    <img src="http://sstatic.net/img/progress-dots.gif"/> \
    </div> \
    <ul class="action-list" > \
    </ul> \
    </div> \
    <div class="popup-actions"> \
    <div style="float: left; margin-top: 18px;"> \
    <a class="popup-actions-cancel">cancel</a> \
    <span class="lsep"> | </span> \
    <a class="popup-actions-help" href="http://meta.stackoverflow.com/questions/74194/how-to-review-can-we-agree-on-a-review-policy" target="_blank">info</a> \
    <span class="lsep"> | </span> \
    <a class="popup-actions-see">see-through</a> \
    </div> \
    <div style="float:right"> \
    <input class="popup-submit" type="button" disabled="disabled" style="float:none; margin-left: 5px" value="Insert"> \
    </div> \
    </div> \
    </div> \
    </div>';

    var option = ' \
    <li> \
    <input id="$ID$" type="radio" name="commentreview"/> \
    <label for="$ID$"> \
    <span class="action-name">$NAME$</span> \
    <span class="action-desc">$DESCRIPTION$</span> \
    </label> \
    </li>';

    var comments = [
    { Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient <a href="http://$SITEURL$/priveleges">privileges</a> to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
    { Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, <a href="http://meta.stackoverflow.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers/8259#8259">it would be preferable</a> to include the essential parts of the answer here, and provide the link for reference.' },
    { Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, <a href="http://$SITEURL$/privileges/comment">you will be able to post comments</a>. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
    { Name: "OP providing using answer for further information", Description: 'Please use the <em>Post answer</em> button only for actual answers. You should modify your original question to add additional information.' },
    { Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button.' },
    { Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the <a href="http://$SITEURL$/questions/ask">Ask Question</a> button. If you have sufficient reputation, <a href="http://$SITEURL$/privileges/vote-up">you may upvote</a> the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
    ];

    var weekday_name = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

    function datespan(date) {
    var now = new Date() / 1000;
    var then = new Date(date * 1000);
    var strout = "";
    if(now - date < 6000) strout = "since today";
    else if(now - date < 86400) strout = "since yesterday";
    else if(now - date < 518400) strout = "since " + weekday_name[then.getDay()];
    else if(now - date > 31536000) {
    strout = "for " + Math.round((now - date) / 31536000) + " years";
    if(((now - date) % 31536000) > 2592000) strout += ", " + Math.round(((now - date) % 31536000) / 2592000) + " months";
    }
    else if(now - date > 2592000) {
    strout = "for " + Math.round((now - date) / 2592000) + " months";
    if(((now - date) % 2592000) > 604800) strout += ", " + Math.round(((now - date) % 2592000) / 604800) + " weeks";
    }
    else {
    strout = "for " + Math.round((now - date) / 604800) + " weeks";
    }
    return strout;
    }

    function lastseen(date) {
    var now = new Date() / 1000;
    if(now - date < 60) return (Math.round(now - date) + " seconds ago");
    if(now - date < 3600) return (Math.round((now - date) / 60) + " minutes ago");
    if(now - date < 6000) return (Math.round((now - date) / 3600) + " hours ago");
    if(now - date < 86400) return ("yesterday");
    var then = new Date(date * 1000);
    if(now - date < 518400) return ("on " + weekday_name[then.getDay()]);
    return then.toDateString();
    }

    function getUserId(el) {
    var div = el.parents('div');
    var selector = div.hasClass('answer') ? '.post-signature' : '.post-signature.owner';
    return div.find(selector).find('.user-details > a').attr('href').replace(/[^\d]/g, '');
    }

    function isNewUser(date) {
    return (new Date() / 1000) - date < 518400
    }

    function htmlToMarkDown(html) {
    html = html.replace(/<a href="(.+)">(.+)<\/a>/g, '[$2]($1)');
    return html.replace(/<em>(.+)<\/em>/g, '*$1*');
    }

    $(".comments-link").each(function () {
    var divid = $(this).attr('id').replace('-link', '');
    $(this).click(function () {
    var newspan = $('<span class="lsep"> | </span>').add($('<a>auto</a>').click(function () {
    //Create popup and wire-up the functionality
    var popup = $(markup);
    popup.find('.popup-close').click(function () { popup.fadeOutAndRemove(); });
    popup.find('.popup-actions-cancel').click(function () { popup.fadeOutAndRemove(); });
    //set opacity on mousedown/mouseup of 'see-through' link
    popup.find('.popup-actions-see').mousedown(function () {
    popup.css('opacity', '0.4')
    popup.find('.popup-active-pane').css('opacity', '0.0')
    });
    popup.find('.popup-actions-see').mouseup(function () {
    popup.css('opacity', '1.0')
    popup.find('.popup-active-pane').css('opacity', '1.0')
    });
    //on submit, convert html to markdown and copy to comment textarea
    popup.find('.popup-submit').click(function () {
    var selected = popup.find('input:radio:checked');
    var markdown = htmlToMarkDown(selected.parent().find('.action-desc').html());
    $('#' + divid).find('textarea').attr('value', markdown).focus(); //focus provokes character count test
    popup.fadeOutAndRemove();
    });
    //create/add options
    $.each(comments, function (index, value) {
    var opt = option.replace(/\$ID\$/g, "comment-" + index)
    .replace("$NAME$", value["Name"])
    .replace("$DESCRIPTION$", value["Description"].replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl));
    popup.find('.action-list').append(opt);
    });
    //add click handler to radio buttons
    popup.find('input:radio').click(function () {
    popup.find('.popup-submit').attr("disabled", ""); //enable submit button
    //unset/set selected class
    $(this).parents('ul').find(".action-selected").removeClass("action-selected");
    $(this).parent().addClass('action-selected');
    });
    //add popup and scroll into view
    $('#' + divid).append(popup);

    //Get user info and inject
    var userid = getUserId($(this));
    var userinfo = popup.find('#userinfo');
    //http://soapi.info/code/js/stable/soapi-explore-beta.htm
    $.ajax({
    type: "GET",
    url: 'http://api.' + siteurl + '/1.0/users/' + userid + '?jsonp=?',
    dataType: "jsonp",
    timeout: 2000,
    success: function (data) {
    if(data['users'].length > 0) {
    var user = data['users'][0];
    if(isNewUser(user['creation_date'])) {
    var greeting = 'Welcome to ' + sitename + '! ';
    popup.find('.action-desc').prepend(greeting);
    }

    var html = 'User <strong><a href="/users/' + userid + '" target="_blank">' + user['display_name'] + '</a></strong>, \
    member <strong>' + datespan(user['creation_date']) + '</strong>, \
    last seen <strong>' + lastseen(user['last_access_date']) + '</strong>, \
    reputation <strong>' + user['reputation'] + '</strong>';
    userinfo.html(html);
    }
    else userinfo.fadeOutAndRemove();
    },
    error: function () { userinfo.fadeOutAndRemove(); }
    });

    popup.center();
    }));
    $('#' + divid).find('.comment-help-link').parent().append(newspan);
    });
    });
    });
    });