21
\$\begingroup\$

One of the more popular comments on our site goes something like this:

Hi, and welcome to PPCG! Your challenge was closed because it's a bit unclear/broad/whatever as it is now. I would recommend posting in the Sandbox so you can get constructive feedback before you post to main.

(Please excuse the sloppy wording, but we've all seen various examples of this comment)

When I'm at a PC, this is fairly simple. On mobile, while it's not exactly impossible, it's definitely more of a hassle. I usually just don't bother and hope someone else does. Even while at a PC though, it would be nice to not have to open another tab to grab the link.

The solution for many commonly commented links is a "magic link", which would automatically be converted to a proper link when posted. I think [sandbox] would be a good addition. It's probably the most common link on the whole site (in comments, that is), so it would simplify writing these introductions.

Now, I don't know how SE handles these things, or whether they even want to do custom links for each site, but I think it's worth proposing here first to gauge interest.

\$\endgroup\$
21
  • \$\begingroup\$ Possible duplicate of We're not a Q&A site. But what should be done about it? \$\endgroup\$ Commented Dec 8, 2016 at 22:06
  • 4
    \$\begingroup\$ I thought about adding it there, but I don't believe it has much to do with whether or not we're a strict Q/A site. \$\endgroup\$
    – Geobits
    Commented Dec 8, 2016 at 22:07
  • \$\begingroup\$ A tentative choice for the close voters... \$\endgroup\$ Commented Dec 8, 2016 at 22:08
  • 11
    \$\begingroup\$ Tentative? If you don't know whether or not you should close it, let others decide. There's no reason to tentatively cast a vote. \$\endgroup\$
    – Geobits
    Commented Dec 8, 2016 at 22:15
  • \$\begingroup\$ Related request on mother Meta \$\endgroup\$
    – DJMcMayhem
    Commented Dec 8, 2016 at 22:16
  • 1
    \$\begingroup\$ @CrazyPython That question should be closed as too broad, and you just demonstrated exactly why. \$\endgroup\$
    – Rainbolt
    Commented Dec 8, 2016 at 22:17
  • \$\begingroup\$ @DJMcMayhem Ah, I must have overlooked that in my search somehow. While the lack of response is disheartening, at least there's not a definite "no" from the dev team. \$\endgroup\$
    – Geobits
    Commented Dec 8, 2016 at 22:19
  • 1
    \$\begingroup\$ @CrazyPython in support of it not being about whether we're a Q&A site, several of the Q&A sites have a sandbox too. For example, worldbuilding's sandbox and math's sandbox (confusingly, that one is closed but still in active use). \$\endgroup\$ Commented Dec 8, 2016 at 22:26
  • 3
    \$\begingroup\$ While we're at it, I think magic links for standard loopholes and things to avoid when writing challenges would be nice. \$\endgroup\$
    – DJMcMayhem
    Commented Dec 8, 2016 at 22:47
  • \$\begingroup\$ @DJMcMayhem Yeah. The main reason I didn't include those is that I usually link to a specific answer when linking those, not the question in general. \$\endgroup\$
    – Geobits
    Commented Dec 8, 2016 at 22:52
  • \$\begingroup\$ We just need a magic link for each answer... \$\endgroup\$ Commented Dec 8, 2016 at 22:55
  • \$\begingroup\$ Hold up... I'm using a magic link! [meta] Open Source Code Golf help center \$\endgroup\$
    – Zizouz212
    Commented Dec 8, 2016 at 23:01
  • \$\begingroup\$ @Zizouz212 the magic doesn't appear to be working... \$\endgroup\$ Commented Dec 8, 2016 at 23:27
  • 1
    \$\begingroup\$ This would need to be hardcoded, and would vary from site to site. Given we're trying to prioritize changes that would impact many sites rather than a single one, @hyper-neutrino , I'm declining this. \$\endgroup\$
    – JNat StaffMod
    Commented Jun 9, 2021 at 15:04
  • 3
    \$\begingroup\$ @JNat Thanks for the response! It's not a very urgent concern and most people have userscripts or extensions to autocomment now or have templates copied, so this is fine. \$\endgroup\$
    – hyper-neutrino Mod
    Commented Jun 9, 2021 at 15:07

2 Answers 2

1
\$\begingroup\$

There's a super cool user script that I use to create auto comments, such as this one on Stack Overflow.

Yaar. Now where did I find it... Oh. Doorknob made it. I'll just copy the script since I don't have the link handy. You can set custom comments to your desire. I think it uses jQuery too!

I doubt SE would do something for the site, since it's very site specific, but hey. I don't know.

// ==UserScript==
// @name stackexchange-quickcomment2
// @namespace http://keyboardfire.com/
// @grant none
// @license MIT
// @description Quick SE comments for quick SE people. (Vastly improved)
// @version 1.0.0
// @match *://*.stackexchange.com/*
// @match *://*.stackoverflow.com/*
// @match *://*.superuser.com/*
// @match *://*.serverfault.com/*
// @match *://*.askububtu.com/*
// @match *://*.stackapps.com/*
// @match *://*.mathoverflow.net/*
// ==/UserScript==

var userscript = function($) {

var qc2;
function updateLS() { localStorage.qc2 = JSON.stringify(qc2); }
if (localStorage.qc2) {
    qc2 = JSON.parse(localStorage.qc2);
} else {
    qc2 = {
        trigger: {
            altKey: true,
            ctrlKey: false,
            shiftKey: false,
            which: 88
        },
        data: {
            naa: 'This is not an answer.',
            welcome: 'Welcome to $SITENAME!',
            lorem: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
        }
    };
    updateLS();
}

$(function() {
    $('<style>' +
        '.qc2_selected { background-color: #FF0; }' +
        '.qc2_popup { background-color: #E0EAF1; text-align: left; }' +
        '.qc2_popup > * { margin: 5px; word-wrap: break-word; }' +
    '</style>').appendTo('head');

    var dialog = $('<div>')
        .attr('id', 'qc2_dialog')
        .appendTo(document.body)
        .css({
            position: 'absolute',
            width: '250px',
            height: '350px',
            textAlign: 'left',
            overflowX: 'hidden',
            overflowY: 'scroll'
        })
        .addClass('qc2_popup')
        .append($('<button>')
            .text('settings')
            .mousedown(showSettings)
        )
        .append($('<input>')
            .attr('type', 'text')
            .keydown(function(e) {
                switch (e.which) {
                case 27: // esc
                    hideDialog();
                    break;
                case 40: // down arrow
                    e.preventDefault();
                    var toChange = $('.qc2_selected').nextAll('div:visible').eq(0);
                    if (toChange.length) {
                        $('.qc2_selected').removeClass('qc2_selected');
                        toChange.addClass('qc2_selected');
                    }
                    break;
                case 38: // up arrow
                    e.preventDefault();
                    var toChange = $('.qc2_selected').prevAll('div:visible').eq(0);
                    if (toChange.length) {
                        $('.qc2_selected').removeClass('qc2_selected');
                        toChange.addClass('qc2_selected');
                    }
                    break;
                }
            })
            .keyup(function(e) {
                if (e.which === 13) { // enter
                    var cmt = dialog.data('comment');
                    var str = $('span:last', '.qc2_selected').text()
                        .replace(/\$SITENAME/g, StackExchange.options.site.name)
                        .replace(/\$SITEURL/g, window.location.hostname);
                    cmt.val(cmt.val() + str);
                    hideDialog();
                } else if (e.which !== 40 && e.which !== 38) {
                    var txt = $('input', dialog).val(),
                        needToUpdateSelected = !$('>div:visible').length;
                    $('>div span:first-child', dialog).each(function() {
                        if (this.textContent.indexOf(txt) === -1) {
                            $(this).parent().hide();
                            if ($(this).parent().hasClass('qc2_selected')) {
                                needToUpdateSelected = true;
                            }
                        } else {
                            $(this).parent().show();
                        }
                    });
                    if (needToUpdateSelected) {
                        $('.qc2_selected').removeClass('qc2_selected');
                        $('>div:visible:first', dialog).addClass('qc2_selected');
                    }
                }
            })
            .blur(hideDialog)
        )
        .hide();

    // I don't know why I have to do this
    // but it works, so I'll just go with it
    dialog[0].scrollTop = 0;

    reloadDialogData();

    $(document).on('keydown', 'textarea[name="comment"]', function(e) {
        if (qc2.trigger.altKey === e.altKey &&
            qc2.trigger.ctrlKey === e.ctrlKey &&
            qc2.trigger.shiftKey === e.shiftKey &&
            qc2.trigger.which === e.which) {
            e.preventDefault();
            showDialog($(this));
        }
    });
});

function showDialog(commentBox) {
    $('#qc2_dialog').data('comment', commentBox).css({
        top: commentBox.offset().top,
        left: commentBox.offset().left
    }).show('fast');
    $('#qc2_dialog input').focus();
}

function hideDialog() {
    $('#qc2_dialog>div').show().removeClass('qc2_selected');
    $('#qc2_dialog>div:first').addClass('qc2_selected');
    $('#qc2_dialog input').val('');
    $('#qc2_dialog').hide().data('comment').focus();
}

function reloadDialogData() {
    $('#qc2_dialog>div').remove();
    for (var k in qc2.data) {
        var v = qc2.data[k];
        $('#qc2_dialog').append(kvpair(k, v));
    }
    $('#qc2_dialog>div:first').addClass('qc2_selected');
}

function showSettings() {
    var settingsDiv = $('<div>')
        .css({
            position: 'fixed',
            top: '50%',
            left: '50%',
            width: '400px',
            height: '400px',
            margin: '-200px 0px 0px -200px',
            overflowX: 'hidden',
            overflowY: 'scroll'
        })
        .addClass('qc2_popup')
        .appendTo(document.body)
        .append($('<button>')
            .text('Done')
            .click(function() {
                settingsDiv.remove();
            })
        )
        .append($('<br>'))
        .append($('<label>')
            .attr('for', 'qc2_trigger_input')
            .text('Trigger:')
        )
        .append($('<input>')
            .attr('id', 'qc2_trigger_input')
            .attr('type', 'text')
            .val(triggerStr())
            .keydown(function(e) {
                e.preventDefault();
                qc2.trigger = {
                    altKey: e.altKey,
                    ctrlKey: e.ctrlKey,
                    shiftKey: e.shiftKey,
                    which: e.which
                };
                updateLS();
                $(this).val(triggerStr());
            })
        );

    for (var k in qc2.data) {
        var v = qc2.data[k];
        settingsDiv.append(kvpair(k, v)
            .append(linkbtn('edit', function(e) {
                    settingsDiv.remove();
                    var editKey = $(e.target).siblings(':first').text();
                    getStr('New value for ' + editKey + ':', function(str) {
                        qc2.data[editKey] = str;
                        updateLS();
                        reloadDialogData();
                        showSettings();
                    }, qc2.data[editKey]);
                })
            )
            .append(linkbtn('delete', function(e) {
                    settingsDiv.remove();
                    var editKey = $(e.target).siblings(':first').text();
                    getStr('Are you sure you want to remove ' + editKey +
                        '? (yes/no)', function(str) {
                        if (str === 'yes') {
                            delete qc2.data[editKey];
                            updateLS();
                            reloadDialogData();
                        }
                        showSettings();
                    });
                })
            )
        );
    }

    settingsDiv.append(linkbtn('new...', function() {
            settingsDiv.remove();
            getStr('New shortcut key:', function(newKey) {
                getStr('New value for ' + newKey + ':', function(newVal) {
                    qc2.data[newKey] = newVal;
                    updateLS();
                    reloadDialogData();
                    showSettings();
                });
            });
        })
    )
    .append(linkbtn('export...', function() {
            settingsDiv.remove();
            getStr('Copy the following text:', function() {}, JSON.stringify(qc2));
        })
    )
    .append(linkbtn('import...', function() {
            settingsDiv.remove();
            getStr('Paste exported text here:', function(str) {
                qc2 = JSON.parse(str);
                updateLS();
                reloadDialogData();
            });
        })
    );
}

function triggerStr() {
    return (
        (qc2.trigger.altKey ? 'Alt+' : '') +
        (qc2.trigger.ctrlKey ? 'Ctrl+' : '') +
        (qc2.trigger.shiftKey ? 'Shift+' : '') +
        String.fromCharCode(qc2.trigger.which)
    );
}

function getStr(query, callback, placeholder) {
    if (!placeholder) placeholder = '';
    var getDiv = $('<div>')
        .css({
            position: 'fixed',
            top: '50%',
            left: '50%',
            width: '400px',
            marginLeft: '-200px'
        })
        .addClass('qc2_popup')
        .appendTo(document.body)
        .append($('<div>')
            .text(query)
        )
        .append($('<input>')
            .val(placeholder)
            .attr('type', 'text')
            .keydown(function(e) {
                if (e.which === 13) {
                    $(this).parent().remove();
                    callback($(this).val());
                }
            })
        );
    getDiv.css({
        height: getDiv.height() + 'px',
        marginTop: '-' + (getDiv.height() / 2) + 'px'
    });
    $('input', getDiv).focus().select();
}

function linkbtn(text, callback) {
    return $('<a>')
        .attr('href', '#')
        .text(text)
        .css('padding-left', '5px')
        .click(function(e) {
            e.preventDefault();
            callback(e);
        });
}

function kvpair(k, v) {
    return $('<div>')
        .css({
            borderBottom: '1px dotted grey',
            padding: '2px 0px'
        })
        .append($('<span>')
            .text(k)
            .css({
                fontWeight: 'bold',
                paddingRight: '5px'
            })
        )
        .append($('<span>')
            .text(v)
            .css({
                color: 'grey'
            })
        );
}

};

var el = document.createElement('script');
el.type = 'text/javascript';
el.text = '(' + userscript + ')(jQuery);';
document.head.appendChild(el);

So let's see:

  • Desktops/Laptops/Whatevertops................. YES!
  • Android............................................................. YES!
  • iOS..................................................................... Who knows.

Thanks to Nathan Merrill for talking about Android

\$\endgroup\$
3
  • 7
    \$\begingroup\$ That doesn't really address the inconvenience of mobile... \$\endgroup\$
    – DJMcMayhem
    Commented Dec 8, 2016 at 22:46
  • \$\begingroup\$ @DJMcMayhem If you use mobile, then you're screwed. It is a solution for people on laptops/desktops/what-tops. But who knows. Maybe you can add a user script to mobile... You folks are all pretty darn smart around here \$\endgroup\$
    – Zizouz212
    Commented Dec 8, 2016 at 22:47
  • \$\begingroup\$ Installing a separate mobile browser for use on SE is more inconvenient, not less. \$\endgroup\$
    – Geobits
    Commented Dec 8, 2016 at 23:41
1
\$\begingroup\$

While this would be nice to have on this site, it would require hardcoding and would not apply to other sites, and given that we are prioritizing changes that benefit the network or many sites rather than tailoring to specific ones, this has been declined.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .