0

I'm adding a custom button in the TinyMCE that opens a textarea where I can add code.

Now since CodeMirror is included in the core, how do I make my textarea into a proper code editor?

Currently I have this:

/**
 * Class Editor
 */
class Editor {
  /**
   * Add theme specific styles to editor
   *
   * @since 1.1.0
   */
  public function add_editor_styles() {
    add_editor_style( plugin_dir_url( __DIR__ ) . '/skin/public/styles/editor.css' );
  }

  /**
   * Add button JavaScript file
   *
   * @param  array $plugin_array Existing tinmyce button array.
   * @return array               Udated button array.
   *
   * @since 1.1.0
   */
  public function add_custom_buttons( $plugin_array ) {
    if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
      return;
    }

    if ( get_user_option( 'rich_editing' ) !== 'true' ) {
      return;
    }

    $plugin_array['code_button'] = plugin_dir_url( __DIR__ ) . '/skin/public/scripts/editor.js';

    return $plugin_array;
  }

  /**
   * Add button name
   *
   * @param  array $buttons Buttons array.
   * @return array          Updated buttons array.
   *
   * @since 1.1.0
   */
  public function register_custom_buttons( $buttons ) {
    if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
      return;
    }

    if ( get_user_option( 'rich_editing' ) !== 'true' ) {
      return;
    }

    $buttons[] = 'code_button';

    return $buttons;
  }

  /**
   * Add document button to ACF editor toolbars
   *
   * @param array $toolbars Available toolbars.
   *
   * @since 1.1.0
   */
  public function add_button_to_toolbar( $toolbars ) {
    $toolbars['Basic'][1][]       = 'code_button';
    $toolbars['Very Simple'][1][] = 'code_button';

    return $toolbars;
  }
}

$editor           = new Editor();

// Editor.
add_action( 'admin_init', $editor, 'add_editor_styles' );
add_filter( 'mce_external_plugins', $editor, 'add_custom_buttons' );
add_filter( 'mce_buttons', $editor, 'register_custom_buttons' );
add_filter( 'acf/fields/wysiwyg/toolbars', $editor, 'add_button_to_toolbar', 100 );

editor.js

/* global tinymce */
/* global localization */

(function() {
  const codeTinyMCEButton = (function() {
    return function(tinyMCE) {
      tinyMCE.PluginManager.add('code_button', function(editor) {
        editor.addButton('code_button', {
          icon: 'code',
          id: 'custom-code',
          tooltip: localization.tinymceEditCodeButtonTitle,
          onclick() {
            editor.windowManager.open({
              title: localization.tinymceEditCodeButtonTitle,
              body: [
                {
                  type: 'textbox',
                  multiline: true,
                  value: '',
                  minHeight: 120,
                  minWidth: 560,
                  name: 'code',
                  spellcheck: false,
                  classes: 'js-code-editor',
                  style: 'direction: ltr; text-align: left',
                },
              ],
              onsubmit(e) {
                if (e.data.code.length) {
                  editor.insertContent(`<pre>${e.data.code}</pre>`);
                }
              },
            });
          },
        });
      });
    };
  })();

  if (typeof tinymce !== 'undefined') {
    codeTinyMCEButton(tinymce);
  }
})();

enter image description here

I tried checking out the global wp object, but the problem is that I don't see wp.codeMirror in it, so I don't know how I can use it to initialize it on my custom textarea field.

Ideas?

EDIT:

So I added a method

/**
   * Add code mirror enqueue
   *
   * @since 1.1.0
   */
  public function add_code_mirror() {
    if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
      return;
    }

    if ( get_user_option( 'rich_editing' ) !== 'true' ) {
      return;
    }

    $settings = wp_enqueue_code_editor(
      array(
        'type' => 'text/html'
      )
    );

    if ( false === $settings ) {
        return;
    }

    wp_add_inline_script(
      'code-editor',
      sprintf(
        'jQuery( function() { wp.codeEditor.initialize( "description", %s ); } );',
        wp_json_encode( $settings )
      )
    );
  }

add_action( 'admin_enqueue_scripts', $editor, 'add_code_mirror' );

And now I can see wp.CodeMirror, but I am also getting an error

Uncaught TypeError: Cannot read property 'value' of undefined

In codemirror.min.js.

Your Answer

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

Browse other questions tagged or ask your own question.