MODX Community

FRED RTE Config: Add custom button or menu?

I posted this on GitHub as well, but thought I’d check in here.

Is there a way or a plan to allow for some of the more advanced TinyMCE config options that require JS? Looking to add a custom menu and/or buttons to insert pre-fab custom code blocks into rich text editable areas. i.e. Allowing customer to select Bootstrap buttons to insert inline. I know I can add a button block as a fred element, but there are definitely times when inserting inline html snippets into a rich text block is preferred.

Custom button for example requires this config which doesn’t play nice with FRED’s JSON valid requirement:

setup: function (editor) { editor.addButton('mybutton', { text: 'My button', icon: false, onclick: function () { editor.insertContent('&nbsp;<b>It\'s my button!</b>&nbsp;'); } }); }

TinyMCE custom button example : https://www.tiny.cloud/docs-4x/demo/custom-toolbar-button/

Off-topic a little, but with Redactor you could configure the button classes as link styles (or use Clips, the widget plugin or the variables plugin) to accomplish the use case you describe.

It also let’s you have separate configuration sets for Fred vs instances in the manager. And also different sets per Fred element.

Just food for thought.

1 Like

Thanks Mark - just to clarify - Redactor can be used with Fred elements on the front-end in a similar manner as TinyMCE? RTE configs and all?

Yeah, though configuration is managed in its own component, and then linked via your Fred RTE config. TinyMCE might allow you to add options directly into the RTE config I think? For Redactor, you only add the ID of the configuration there. See the Redactor Fred documentation for how that works.

Fred support is new to Redactor 3, so I’d love to get feedback from people who have a little more experience with Fred on how it does (or doesn’t!) work for them.

1 Like

Having looked for a similar solution we ended up creating a work around whereby you create a link then add in the btn classes, then the btn type classes:

"style_formats": [
{
      "title": "Add button",
      "items": [
        {
          "title": "Create button",
          "selector": "a",
          "classes": "btn"
        }
      ]
    },
    {
      "title": "Solid button",
      "items": [
        {
          "title": "Primary button",
          "selector": "a",
          "classes": "btn-primary"
        },
        {
          "title": "Secondary button",
          "selector": "a",
          "classes": "btn-secondary"
        },
        {
          "title": "Success button",
          "selector": "a",
          "classes": "btn-success"
        },
        {
          "title": "Danger button",
          "selector": "a",
          "classes": "btn-danger"
        },
        {
          "title": "Warning button",
          "selector": "a",
          "classes": "btn-warning"
        },
        {
          "title": "Info button",
          "selector": "a",
          "classes": "btn-info"
        },
        {
          "title": "Light button",
          "selector": "a",
          "classes": "btn-light"
        },
        {
          "title": "Dark button",
          "selector": "a",
          "classes": "btn-dark"
        },
        {
          "title": "Link button",
          "selector": "a",
          "classes": "btn-link"
        }
      ]
    },
    {
      "title": "Outline button",
      "items": [
        {
          "title": "Primary button",
          "selector": "a",
          "classes": "btn-outline-primary"
        },
        {
          "title": "Secondary button",
          "selector": "a",
          "classes": "btn-outline-secondary"
        },
        {
          "title": "Success button",
          "selector": "a",
          "classes": "btn-outline-success"
        },
        {
          "title": "Danger button",
          "selector": "a",
          "classes": "btn-outline-danger"
        },
        {
          "title": "Warning button",
          "selector": "a",
          "classes": "btn-outline-warning"
        },
        {
          "title": "Info button",
          "selector": "a",
          "classes": "btn-outline-info"
        },
        {
          "title": "Light button",
          "selector": "a",
          "classes": "btn-outline-light"
        },
        {
          "title": "Dark button",
          "selector": "a",
          "classes": "btn-outline-dark"
        }
      ]
    },
    {
      "title": "Button size",
      "items": [
        {
          "title": "Button small",
          "selector": "a",
          "classes": "btn-sm"
        },
        {
          "title": "Button default",
          "selector": "a",
          "classes": "btn-norm"
        },
        {
          "title": "Button large",
          "selector": "a",
          "classes": "btn-lg"
        },
        {
          "title": "Button block",
          "selector": "a",
          "classes": "btn-block"
        }
      }
]

Not ideal but works for now

1 Like

Thanks for the insights - good workaround for now!

Hey there!

I managed to get this working! It’s definitely hacky, but it’s easy and it works.

  1. create a plugin that fires on “FredBeforeRender”
  2. inside the plugin I have this code. It adds some custom CSS (unrelated to this issue) that highlights fred drag and drop sections, as well as add the javascript that appends the buttons to my rich text areas in Fred. Both the CSS and the JS are saved in chunks
<?php $cust_styles = $modx->getChunk('fred-css'); $cust_js = $modx->getChunk('fred-js-test'); $modx->event->_output = [ 'includes' => $cust_styles.$cust_js ];
  1. The JS Chunk is where the magic happens. This script finds all rich text editors on the page (unfortunately the areas have to be saved for this to work - new drag/drops will not contain the button until saved and the editing page is reloaded.) and injects the new button/menu on there with custom code blocks. Adjust my code with your own. NOTE: this code waits a couple second after the page is loaded before it does it work. I found I needed to give the TinyMCE’s time to load for this to work properly. You may need to adjust the 2000 (2s) value up or down. Like I said… Hacky but it works :slight_smile:

Edit: I can’t seem to paste the JS here… weird. So here’s a link to a txt file in my dropbox with the code: