HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

GooglePrettify - Select All Code

jackmaessenjackmaessen ✭✭✭
edited December 2015 in Feedback

I was looking for a way to catch all the code inside the pre tags form GooglePrettify (embedded plugin).
So i added some code inside class.googleprettify.plugin.php
What did i do:

  1. make difference between a comment with code and without code;
    In every comment with code, the code is between pre tags.
    So i made a div surround the pre tags in which i could add an anchor that corresponds with the pre tag:
    Every pre tag has a class named CodeBlock
    $('.Message .CodeBlock', this).wrap('<div class=surroundpre></div>');
    So this div is only created in comments with code inside it
  2. Make an anchor just before the pre tag, inside div class="surroundpre"
    I made a php string ike this:
    $SelectAnchor = '<a href="javascript:fnSelect(\\\'id\\\');">[Select All Code]</a>';
    Now the ID should be the same as the ID for the pre tag:

    $('pre').each(function(){
                    var id;
                    if ($(this).attr('id') == undefined){
                    id = 'id'+Math.floor((Math.random() * 99999999) + 1);
                    $(this).attr('id',id);
                    $(this).prev('a').attr('href','javascript:fnSelect(\"' + id + '\")');
                    }
                  });
    

    You can see the unique ID is created for the pre and also for the previous anchor attribute. Both are the same

  3. Finally , we create the anchor attr inside the surround div just before the pre tags:
    Our php string is added via a prepend

$('.surroundpre').prepend('$SelectAnchor');

All these additions are created in the public function getJs() {

and now looks like this:

public function getJs() {

        $Class = '';


        if (c('Plugins.GooglePrettify.LineNumbers')) {
            $Class .= ' linenums';
        }
        if ($Language = c('Plugins.GooglePrettify.Language')) {
            $Class .= " lang-$Language";
        }

        $SelectAnchor = '<a href="javascript:fnSelect(\\\'id\\\');">[Select All Code]</a>';

        $Result = "jQuery(document).ready(function($) {

           $('.Message .CodeBlock', this).wrap('<div class=surroundpre></div>');
           $('.surroundpre').prepend('$SelectAnchor');

           var pp = false;

           $('.Message').livequery(function () {

              $('pre', this).addClass('prettyprint$Class');


              $('pre').each(function(){
                var id;
                if ($(this).attr('id') == undefined){
                id = 'id'+Math.floor((Math.random() * 99999999) + 1);
                $(this).attr('id',id);
                $(this).prev('a').attr('href','javascript:fnSelect(\"' + id + '\")');
                }
              });

              if (pp)

              prettyPrint();
              $('pre', this).removeClass('prettyprint')

           });


            prettyPrint();
            pp = true;


          });";

        return $Result;

    }

And last, but not least, the javascript on the background: this is loaded in the head tag

function fnSelect(objId) {
        fnDeSelect();
        if (document.selection) {
        var range = document.body.createTextRange();
            range.moveToElementText(document.getElementById(objId));
        range.select();
        }
        else if (window.getSelection) {
        var range = document.createRange();
        range.selectNode(document.getElementById(objId));
        window.getSelection().addRange(range);
        }
    }

    function fnDeSelect() {
        if (document.selection) document.selection.empty(); 
        else if (window.getSelection)
                window.getSelection().removeAllRanges();
    }

Snapshot below:

You can see that also the linenumbers are selected but when copy the selected area, these will NOT be copied to the clipboard!

It would be great if i could put all of this inside a plugin so you don't have to modify the original plugin. Still thinking about it how to do it...

Feedback very welcome!

Comments

  • This is a great addition.
    It can be simplified to this:

    jQuery(function ($) {
    
        function selectText() {
            var range = document.createRange(),
                selection = window.getSelection();
            range.selectNode(this);
            selection.removeAllRanges();
            selection.addRange(range);
        }
    
        function addSelectLinks() {
            $('.Message pre')
                .filter(function () {
                    return !$(this).data('hasSelectLink');
                })
                .data('hasSelectLink', '1')
                .each(function () {
                    $('<a href="javascript:">[Select All Code]</a>')
                        .click(selectText.bind(this))
                        .insertBefore(this);
                });
        }
    
        $(document).on('CommentAdded CommentEditingComplete', addSelectLinks);
        addSelectLinks();
    
    });
    

    Note that this also works on added and edited comments. It is independent of the GooglePrettify plugin so it can be included separately.

Sign In or Register to comment.