Skip to main content

Adding a copy button and language to code snippet, ckeditor in Drupal 8.

Updated by Tim Rabbetts on
white, desk, lifestyle

I wanted to have a language text and copy button couldn't find this anywhere in the code snippet module.  Like to get his added as an option in this module?  Maybe when you select the languages, a checkbox "Show toolbar".

buttons on code snippet

Works but a bit hacky.

First I added in the javascript.

In the theme add this entry to the .info.yml file.

libraries:
  - connect_theme/clipboardjs

Then define the library which is 2 files, 1 is the clipboard.js which does the copy to clipboard and the other is the init clipboard js code.  Add a .libraries.yml file with entry like this:

clipboardjs:
 js:
  src/js/clipboard.min.js: {}
  src/js/clipboard-init.js: {}

Download clipboard js from here https://clipboardjs.com and add it at src/js/clipboard.min.js.  Then we need to use it so add this code as the clipboard-init.js:

(function ($) {
  'use strict';

  Drupal.behaviors.main = {
    attach: function(context, settings) {

      console.log('clipboard js init');

      var clipboard = new ClipboardJS('.copy-btn');

      clipboard.on('success', function(e) {
        if ($('#copy-msg').length == 0) {
          $('body').append('<div id="copy-msg">Copied!</div>');
        }

        $('#copy-msg').show();

        setTimeout(function(e) {
          $('#copy-msg').hide();
        }, 2000);

        e.clearSelection();
      });

    }
  };
})(jQuery);




So in our markup, our copy buttons will have a class of "copy-btn".  On success, I show a "copied" message briefly and clear selection so the text is not selected on click.

Now we need the markup pre-processing so this will work.


function connect_theme_preprocess_field(&$variables, $hook) {

  // Pre process long text fields, rewrite code snippets for clipboard.js.
  if ($variables['field_type'] == 'text_with_summary') {

    // Get the text.
    $text = $variables['items'][0]['content']['#text'];

    // Replace all pre tags with id and button.
    $code_snips = explode('<pre>', $text);
    $new_text = '';
    $cid = 0;
    $first = TRUE;

    foreach ($code_snips as $code_snip) {

      // Add clipboard and language markup.
      if (!$first) {

        $new_text .= '<div class="snip-bar">';

        // While we are at it add a language label.
        if (strstr($code_snip, 'language-')) {
          $lang = explode('language-', $code_snip);
          $lang = explode('"', $lang[1]);
          $lang = $lang[0];
          $new_text .= '<label>Language: ' . $lang . '</label>';
        }

        // Add clipboard.js markup.
        $clip = '<button class="copy-btn" data-clipboard-target="#CID-' . $cid . '">copy</button>';
        $new_text .= $clip;
        $new_text .= '</div>';
        $new_text .= '<pre id="CID-' . $cid . '">' . $code_snip;
      }
      else {
        $new_text = $code_snip;
        $first = FALSE;
      }
      $cid++;
    }
    $variables['items'][0]['content']['#text'] = $new_text;

  }
}

The important bit here is that it adds a button and an ID to every pre-code snippet, like I said hacky but it works.

I'd like to use the clipboard js module but there was no documention about using the js not php process.  I'd also like to be able to change the code snippet module to do the rewrite.

Will update this if this gets done.

Add new comment