Using The TinyMCE Text Editor In A Rails Application

Alexander Paterson
|
Posted almost 7 years ago
|
7 minutes
Using The TinyMCE Text Editor In A Rails Application
The TinyMCE text editor is amazing -- it's really your only choice for most applications

I spent hours trying to figure out which embedded text-editor to use for this blog. Quill.js proved poorly documented and lacking functionality, and after giving up on that I came across TinyMCE. This text-editor is truly beautiful, and fully-featured.

Ruby On Rails Setup

This blog is built with Ruby on Rails, and conveniently enough, TinyMCE has a well-maintained rails gem.

# Gemfile

gem 'tinymce-rails'

Having installed the gem with bundle install, we import some javascript it provides by putting //= require tinymce-jquery in our app/assets/application.js imports.

// app/assets/javascripts/application.js
//
//= require jquery
//= require tinymce-jquery
//= require_tree .

tinymce-rails requires we create a default config file at config/tinymce.yml. Just use the configuration below. We'll define our actual configuration in our javascript.

# config/tinymce.yml

toolbar:
  - styleselect | bold italic | undo redo
  - image | link
plugins:
  - image
  - link

Config

Now create app/assets/javascripts/tinymce.js with the following content:

$(document).on('ready page:load', function () {
  if (typeof tinyMCE != 'undefined') {
    tinyMCE.init({
      selector: "textarea.tinymce",
      toolbar: [
        "styleselect | bold italic | alignleft aligncenter alignright alignjustify",
        "bullist numlist outdent indent | link image | code | codesample"
      ],
      plugins: "image,link,code,codesample,autoresize,imagetools,media,table,insertdatetime,charmap,print,preview,anchor,searchreplace,visualblocks,fullscreen"
    });
  } else {
    setTimeout(arguments.callee, 50);
  }
});

Note the 'selector' arribute of the object passed to the initialiser. This selects the textarea to turn into a TinyMCE editor. We wrap the initialisation process in a jQuery event listener that executes whenever the window reloads -- this is for compatibility with turbolinks (a ruby gem that makes our site act as a single page application, enabled by default in rails).

My configuration includes many plugins and toolbar items; probably all you need. There are many other plugins, though.

Now we just need to render a text area matching our TinyMCE selector. If you're using it in a form, there's a convenient rails helper:

# app/views/posts/_form.html.erb

<%= f.text_area :content, :class => "tinymce", :rows => 20, :cols => 120 %>

This textarea is for the content attribute of my post object, specified as the first argument. You can see we've added the tinymce class as specified in our javascript. We can also create our text editor with some simple HTML:

<textarea class="tinymce"></textarea>

And it's as simple as that. Our text editor will behave exactly as any other textarea form field, and it will simply generate HTML. The inner HTML can be accessed quickly with jQuery ($('textarea.tinymce').html()). Some toolbar items and plugins generate HTML tags, some generate classes, and some generate inline CSS. It's all still affected by your global styling when you render it out.

Big Warning

If you try to render text from a TinyMCE form into a rails template, by default, the HTML is going to be escaped and you'll be left looking at plaintext HTML. To avoid this, you'll probably need to call html_safe on the text you're rendering as follows:

<%= @post.content.html_safe %>

This introduces a very real security vulnerability into your application, because doing this will also prevent <script> tags from being escaped. What this means is that somebody could easily embed some javascript into any TinyMCE text on your website and it would execute on your readers' machines. To fix this, you need to implement logic either in your controller or your view that sanitizes the post content. I would recommend doing this in your view with the rails sanitize helpers. Filter out any script tags, for a start.

If your blog has protected routes, and the public cannot alter the content of your website through a TinyMCE text editor, you don't need to worry for now.

Advanced Config

By default, TinyMCE text formats include only basic HTML elements and attributes, but it's easy to create your own. In the snippet below, I'm adding two new formats which will appear in the Formats dropdown menu of my text editor.

$(document).on('ready page:load', function () {
  if (typeof tinyMCE != 'undefined') {
    tinyMCE.init({
      selector: "textarea.tinymce",
      toolbar: [
        "..."
      ],
      style_formats_merge: true,
      style_formats: [
        {
          title: 'Spaced-para',
          selector: 'p',
          styles: {
            'margin': '42px 0px'
          },
          classes: "custom-class"
        },
        {
          title: 'Red-header',
          selector: 'h2',
          styles: {
            'color': 'red'
          },
          classes: "red-item header-item"
        }
      ],
      plugins: "..."
    });
  } else {
    setTimeout(arguments.callee, 50);
  }
});

style_formats_merge: true keeps the default styles. What you're specifying with each of these styles is the exact inline HTML that will be applied when you apply the style to some highlighted text, or the text you're currently typing.



-->
ALEXANDER
PATERSON