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

Shows a select-button on mouse over on code-blocks to select the whole block for easier copying.

Sorry to not provide a file for download but i am sure you will manage somehow, adjust includes as needed:

// ==UserScript==
// @name           Select Code Block Buttons
// @namespace      stackoverflow
// @include        *stackoverflow.com*
// ==/UserScript==

(function ()
{
    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 ($)
    {
        addButtons();

        function selectText(element)
        {
            var doc = document;
            if (doc.body.createTextRange)
            {
                var range = doc.body.createTextRange();
                range.moveToElementText(element);
                range.select();
            } else if (window.getSelection)
            {
                var selection = window.getSelection();
                var range = doc.createRange();
                range.selectNodeContents(element);
                selection.removeAllRanges();
                selection.addRange(range);
            }
        }

        function addButtons()
        {
            $("pre").each(function (i, codeBlock)
            {
                var qContainer = $("<div></div>");
                var id = "select-button-" + i;
                $(codeBlock).replaceWith(qContainer);
                qContainer.append(codeBlock);

                qContainer.mouseenter(function ()
                {
                    var qButton = $('<div style="position: absolute; opacity: 0; display: inline; cursor: pointer;' +
                                     'background-color: #000; color: #fff; font-size: 12pt; padding: 3px;">' +
                                     'Select</div>');
                    qButton.attr("id", id);
                    qContainer.append(qButton);
                    var left = $(codeBlock).offset().left + $(codeBlock).width() - qButton.width();
                    var top = $(codeBlock).offset().top;
                    qButton.css("left", left);
                    qButton.css("top", top);
                    qButton.click(function ()
                    {
                        selectText(codeBlock);
                    });
                    qButton.stop(true, true).animate({ opacity: '+=0.6' });
                });
                qContainer.mouseleave(function ()
                {
                    $("#" + id).stop(true, true).animate({ opacity: '-=0.6' }, function () { $("#" + id).remove(); });
                });
            });
        }
    });
})();

Edits:

  • Buttons are now created on mouse-over, making sure that the placement is correct as the layout may change (e.g. by expanding a comment thread).
  • Changed text selection code to be a bit more browser-independent.
  • Added the jQuery frame from the SE keyboard shortcuts script.

Bugs:

  • Sometimes a button will be displayed permanently.
share|improve this question
    
Has anyone successfully used this in Google-Chrome on MacOSX or Linux? –  halirutan Nov 12 '12 at 16:09
    
@halirutan: Text selection unfortunately is a bit browser dependent, i changed the code to alleviate that but i did not expect chrome to behave differently in the first place so i do not know if this will change anything for you... –  H.B. Nov 12 '12 at 19:35
    
Unfortunately it does not help. When I have time I may try to read JavaScript ;-) –  halirutan Nov 12 '12 at 20:13

2 Answers 2

Foreword: I have absolutely no idea what I did.

The above script did not work in Chrome. Therefore, I read through some documentation about user-scripts and found that Chrome does not support unsafeWindow. Digging further, I found this answer where @tghw describes how to mimic the behavior. Combining your selector with the approach in the answer gives a script which seems to work in Chrome.

It would be very nice, if you could look over the code and bring it in a clean form.

// ==UserScript==
// @name         Select Code Block Buttons
// @namespace    stack
// @match        http://stackoverflow.com/*
// @match        http://mathematica.stackexchange.com/*
// ==/UserScript==

function addJQuery(callback) {
    var script = document.createElement("script");
    script.setAttribute("src", "//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js");
    script.addEventListener('load', function() {
        var script = document.createElement("script");
        script.textContent = "(" + callback.toString() + ")();";
        document.body.appendChild(script);
    }, false);
    document.body.appendChild(script);
}

function main()
{

    $(document).ready(addButtons);

    function selectText(element)
    {
        var doc = document;
        if (doc.body.createTextRange)
        {
            var range = doc.body.createTextRange();
            range.moveToElementText(element);
            range.select();
        } else if (window.getSelection)
        {
            var selection = window.getSelection();
            var range = doc.createRange();
            range.selectNodeContents(element);
            selection.removeAllRanges();
            selection.addRange(range);
        }
    }

    function addButtons()
    {
        $("pre").each(function (i, codeBlock)
        {
            var qContainer = $("<div></div>");
            var id = "select-button-" + i;
            $(codeBlock).replaceWith(qContainer);
            qContainer.append(codeBlock);

            qContainer.mouseenter(function ()
            {
                var qButton = $('<div style="position: absolute; opacity: 0; display: inline; cursor: pointer;' +
                                 'background-color: #000; color: #fff; font-size: 12pt; padding: 3px;">' +
                                 'Select</div>');
                qButton.attr("id", id);
                qContainer.append(qButton);
                var left = $(codeBlock).offset().left + $(codeBlock).width() - qButton.width();
                var top = $(codeBlock).offset().top;
                qButton.css("left", left);
                qButton.css("top", top);
                qButton.click(function ()
                {
                    selectText(codeBlock);
                });
                qButton.stop(true, true).animate({ opacity: '+=0.6' });
            });
            qContainer.mouseleave(function ()
            {
                $("#" + id).stop(true, true).animate({ opacity: '-=0.6' }, function () { $("#" + id).remove(); });
            });
        });
    }
}

// load jQuery and execute the main function
addJQuery(main);

Update

As I see now, the Official Keyboard Shortcut Script uses a similar technique. This is maybe a better template how to make it work in both, Chrome and Firefox.

share|improve this answer
    
Thanks for debugging this. I now added the code from the SE keyboard shortcuts. If you want you can test it to see if that also works for you... –  H.B. Nov 13 '12 at 18:11
    
@H.B. Yes, it works. Thanks. –  halirutan Nov 14 '12 at 22:16

Or how about a simple script to select all on double-click? This is my preferred method, since I have terrible aim with my couch keyboard and my large font size often means I've scrolled part of the code block out of view -- namely the part with the "click me" button.

I tried halirutan's script but it seemed to interfere with "add comment" links. So I decided to write my own. Seems to work just fine in Firefox with Greasemonkey and Chrome with Tampermonkey.

// ==UserScript==
// @name        Dbl-Click Select All in Stack Exchange code blocks
// @namespace   http://stackapps.com/
// @description Double-click a code block to select all
// @include     /^https?:\/\/stackoverflow\.com\/.+/
// @include     /^https?:\/\/.*\.stackexchange\.com\/.+/
// @include     /^https?:\/\/stackapps\.com\/.+/
// @version     1
// @grant       none
// ==/UserScript==

function selectAll() {
    var range = document.createRange();
    range.selectNodeContents(this.childNodes[0]);
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
}

var pre = document.getElementsByTagName('pre');
for (var i=0; i<pre.length; i++) {
    pre[i].addEventListener('dblclick', selectAll, true);
    pre[i].title = 'double-click to select all';
}

And what's with all the jQuery stuff? These other scripts on this page are much more complicated than they need to be. Not everything has to be done with jQuery, you know. My stars and garters!

share|improve this answer
    
I am not a fan of jQuery, in fact i really dislike it, but if you get into the messy business of modifying pages in hindsight it helps. Ideally you just never do that of course. –  H.B. Dec 7 at 19:30
    
As far as I've seen, most of the benefits of jQuery come from allowing modern features to degrade gracefully in older web browsers, and for the various plugins people have written. Otherwise, IMHO, requiring an 85k library to call a function with one line of code that might've taken 5 or 6 lines to write without the library is just lazy and wasteful. The minimal benefit does not justify the cost. I guess I'm too much a crotchety old luddite to understand why jQuery is so popular. My prejudice against jQuery may not be fair, but I just want jQuery to get off my lawn. :) –  rojo Dec 7 at 19:51
    
Laziness is a virtue for a programmer, to me writing 5 lines of code when it could be replaced by one is just wasteful. I don't really care much about library size, JavaScript files can be cached by the browser like anything else; people worry about things like that too much in my opinion. My biggest issue with jQuery is that it is usually the wrong tool for the tasks it is used and designed for. It is the best hammer for "cutting" planks there is, of course the results will be mediocre at best for obvious reasons. jQuery should die and things like KnockOut and Angular are to take its place. –  H.B. Dec 8 at 2:50

You must log in to answer this question.

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