12
\$\begingroup\$

The following code will add to each code block a 'Select Code' button that will select the code belonging to that block. Please review for maintainability.

In order to use this, visit http://codereviewcommunity.github.io/CodeReviewBookmarklet/

javascript: if ($('button').length === 0) { 
  /* Stack Exchange does not do buttons, this does */
  $(".prettyprint").each( function()
  { 
    /* Thank you http://stackoverflow.com/a/2838358/7602 */
    function selectCode(el, win) 
    {
      win = win || window;
      var doc = win.document, sel, range;
      if (win.getSelection && doc.createRange) 
      {
        sel = win.getSelection();
        range = doc.createRange();
        range.selectNodeContents(el);
        sel.removeAllRanges();
        sel.addRange(range);
      } 
      else if (doc.body.createTextRange) 
      {
        range = doc.body.createTextRange();
        range.moveToElementText(el);
        range.select();
      }
    }

    var buttonText  = 'Select Code',
        length      = buttonText.length,
        codeBlock   = this,
        $link       = $('<button type="button">' + buttonText + '</button><br>').click(function()
        {
          console.log( $(codeBlock).text().substring( length ) );
          selectCode(codeBlock);
        });
    $(codeBlock).prepend( $link );
  });
}

I have tested this on FF and Chrome and it works for me.

\$\endgroup\$
  • \$\begingroup\$ Works on Safari 7. \$\endgroup\$ – 200_success Dec 30 '13 at 23:13
  • \$\begingroup\$ How do you test this with Chrome? \$\endgroup\$ – Jamal Dec 30 '13 at 23:25
  • 1
    \$\begingroup\$ Select the test, then mouse-down for half a second, and then drag the code into the bookmark-bar. \$\endgroup\$ – konijn Dec 30 '13 at 23:50
  • \$\begingroup\$ Nice! You could consider putting the updated code below the original, while clearly marking it as such. \$\endgroup\$ – Jamal Dec 30 '13 at 23:53
  • \$\begingroup\$ @Jamal I don't like the button size with before, I will have to play with it a bit. \$\endgroup\$ – konijn Dec 31 '13 at 0:21
10
\$\begingroup\$

You inject the button using jQuery.prepend(), which inserts the button as the first child of the .prettyprint code block. Therefore, when the bookmarklet is invoked, and it selects the contents of the code block, the "Select Code" button is inadvertently included in the selection. I recommend using jQuery.before() instead.

\$\endgroup\$
  • \$\begingroup\$ You are right, will fix. On FF, the text of the button does not actually make it into the clipboard. \$\endgroup\$ – konijn Dec 30 '13 at 23:50
  • 1
    \$\begingroup\$ This works on Chrome. \$\endgroup\$ – Jamal Dec 31 '13 at 0:09
7
+50
\$\begingroup\$

Since StackExchange can refresh page contents dynamically, the following sequence of events is possible:

  1. Page contains some code block(s).
  2. Bookmarklet is invoked, adding the button to existing code block(s).
  3. Page contents are updated, for example, with a new answer that contains a new code block.
  4. Bookmarklet is invoked again, but it refuses add a Select Code button to the new code block.

Therefore, I suggest that the overall structure be changed such that it can be invoked again after a content update. Here is one approach (assuming that you also take my previous advice to use jQuery.before()):

javascript:$("pre.prettyprint").not("button + *").each(function() { 
    …

    var buttonText  = 'Select Code',
        length      = buttonText.length,
        codeBlock   = this,
        $link       = $('<button type="button">' + buttonText + '</button>').click(…);
    $(codeBlock).before( $link );
  });

I've changed the selector $(".prettyprint") to $("pre.prettyprint") because class-only selectors are reputed to be slower.

For the .not("button + *") next-sibling filter to work, the button must not be inserted with a <br> afterwards. The <br> is unnecessary anyway, since <pre> is a block element.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.