10

Before WP 3.9 i had the following two filters applied in the functions.php:

function my_mce_buttons_2( $buttons ) {
    array_unshift( $buttons, 'styleselect' );
    return $buttons;
}
add_filter('mce_buttons_2', 'my_mce_buttons_2');

function mce_mod( $init ) {
    $init['theme_advanced_blockformats'] = 'p,h3,h4';
    $init['theme_advanced_styles'] = "Header gross=mus-bi news-single-bighead; Header klein=mus-bi news-single-smallhead; Link=news-single-link; List Items=news-single-list";
    return $init;
}
add_filter('tiny_mce_before_init', 'mce_mod');

so that the paragraph formats dropdown only shows p, h3 and h4 while the custom styles dropdown shows "Header gross", "Header klein" and so on. But unfortunately wp and tinymce don't bother anymore since wp 3.9, i only see the standard paragraph formats dropdown now

paragraph

as well as the standard styles format dropdown:

styles

So far i haven't found any docs about if any hooks have changed with the update to tinymce 4. Anyone knows? Best regards Ralf

Update: Ok based on a little more research and the comments beneath i guess i've figured things out:

//Creating the style selector stayed the same
function my_mce_buttons( $buttons ) {
   array_unshift( $buttons, 'styleselect' );
   return $buttons;
}
add_filter('mce_buttons', 'my_mce_buttons');

function mce_mod( $init ) {
   //theme_advanced_blockformats seems deprecated - instead the hook from Helgas post did the trick
   $init['block_formats'] = "Paragraph=p; Heading 3=h3; Heading 4=h4";

   //$init['style_formats']  doesn't work - instead you have to use tinymce style selectors
   $style_formats = array(
    array(
        'title' => 'Header 3',
        'classes' => 'mus-bi news-single-bighead'
    ),
    array(
        'title' => 'Header 4',
        'classes' => 'mus-bi news-single-smallhead'
    ),
    array(
        'title' => 'Link',
        'block' => 'a',
        'classes' => 'news-single-link',
        'wrapper' => true
    )
   );
   $init['style_formats'] = json_encode( $style_formats );
   return $init;
}
add_filter('tiny_mce_before_init', 'mce_mod');
3

1 Answer 1

19

If you look in class-wp-editor.php you'll find that the filter you are using is still there, however the settings are different.

self::$first_init = array(
                    'theme' => 'modern',
                    'skin' => 'lightgray',
                    'language' => self::$mce_locale,
                    'formats' => "{
                        alignleft: [
                            {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'left'}},
                            {selector: 'img,table,dl.wp-caption', classes: 'alignleft'}
                        ],
                        aligncenter: [
                            {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'center'}},
                            {selector: 'img,table,dl.wp-caption', classes: 'aligncenter'}
                        ],
                        alignright: [
                            {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'right'}},
                            {selector: 'img,table,dl.wp-caption', classes: 'alignright'}
                        ],
                        strikethrough: {inline: 'del'}
                    }",
                    'relative_urls' => false,
                    'remove_script_host' => false,
                    'convert_urls' => false,
                    'browser_spellcheck' => true,
                    'fix_list_elements' => true,
                    'entities' => '38,amp,60,lt,62,gt',
                    'entity_encoding' => 'raw',
                    'keep_styles' => false,
                    'paste_webkit_styles' => 'font-weight font-style color',

                    // Limit the preview styles in the menu/toolbar
                    'preview_styles' => 'font-family font-size font-weight font-style text-decoration text-transform',

                    'wpeditimage_disable_captions' => $no_captions,
                    'wpeditimage_html5_captions' => current_theme_supports( 'html5', 'caption' ),
                    'plugins' => implode( ',', $plugins ),
                );

I'm guessing, but I think you need to change the array key you are targeting to formats.

EDIT Leaving this in place, but the OP confirms that this does not do what he is attempting.

function mce_mod( $init ) {
        $init['formats'] = "{
                            alignleft: [
                                {selector: 'p,h3,h4,td,th,div,ul,ol,li', styles: {textAlign:'left'}},
                                {selector: 'img,table,dl.wp-caption', classes: 'alignleft'}
                            ],
                            aligncenter: [
                                {selector: 'p,h3,h4,td,th,div,ul,ol,li', styles: {textAlign:'center'}},
                                {selector: 'img,table,dl.wp-caption', classes: 'aligncenter'}
                            ],
                            alignright: [
                                {selector: 'p,h3,h4,td,th,div,ul,ol,li', styles: {textAlign:'right'}},
                                {selector: 'img,table,dl.wp-caption', classes: 'alignright'}
                            ],
                            strikethrough: {inline: 'del'}
                        }";
    return $init;
}
add_filter('tiny_mce_before_init', 'mce_mod');

Keep in mind that this is totally untested, so your mileage may vary. (And don't use on a production site until you've tested it).

Continuing onwards

Digging deeper the formats appear to be a custom tinyMCE button. You can see that the formatselect button is added to mce_buttons_2 in the class-wp-editor.php. And then I tracked that to tinymce.js :

    editor.addButton('formatselect', function() {
        var items = [], blocks = createFormats(editor.settings.block_formats ||
            'Paragraph=p;' +
            'Address=address;' +
            'Pre=pre;' +
            'Heading 1=h1;' +
            'Heading 2=h2;' +
            'Heading 3=h3;' +
            'Heading 4=h4;' +
            'Heading 5=h5;' +
            'Heading 6=h6'
        );

With that in mind, I think the new target would be to 1. (ideally) change the editor.settings.block_formats or 2. remove that button by filtering mce_buttons_2 and adding your own custom version.

Tested and working

function mce_mod( $init ) {
    $init['block_formats'] = 'Paragraph=p;Heading 3=h3;Heading 4=h4';

    $style_formats = array (
        array( 'title' => 'Bold text', 'inline' => 'b' ),
        array( 'title' => 'Red text', 'inline' => 'span', 'styles' => array( 'color' => '#ff0000' ) ),
        array( 'title' => 'Red header', 'block' => 'h1', 'styles' => array( 'color' => '#ff0000' ) ),
        array( 'title' => 'Example 1', 'inline' => 'span', 'classes' => 'example1' ),
        array( 'title' => 'Example 2', 'inline' => 'span', 'classes' => 'example2' )
    );

    $init['style_formats'] = json_encode( $style_formats );

    $init['style_formats_merge'] = false;
    return $init;
}
add_filter('tiny_mce_before_init', 'mce_mod');

function mce_add_buttons( $buttons ){
    array_splice( $buttons, 1, 0, 'styleselect' );
    return $buttons;
}
add_filter( 'mce_buttons_2', 'mce_add_buttons' );

Small caveat: I'm not sure where to add the styles for the drop-down items themselves. In the TinyMCE sample, the "Red Headline" option is red. I couldn't figure this out. If you do please let me know.

13
  • thanks helga! i've looked into the class-wp-editor before too. But was unsure what the syntax had to be (there isn't much wp related documentation for the updated tinymceapi) . tried your suggestion now. same results like with my initial snippets. TinyMCE doesn't mind what the init looks like. on the tinymce site i've found an example for custom formats, js only, and i failed to adapt it towards wp and php: tinymce.com/tryit/custom_formats.php
    – rkoller
    Apr 17, 2014 at 12:06
  • 1
    Great help, thanks! Just wanted to add that the block_formats option can't have a trailing ; . I was building the value from saved configurable options and had a trailing ; that borked the list. Hope that saves somebody a few minutes.
    – Adam Pope
    May 15, 2014 at 9:07
  • 1
    @indextwo yup, I solved it here (as best as I could) and decided... hey... blog post! You don't get the class on a span even if you define it as inline? array( 'title' => 'Red text', 'inline' => 'span', 'styles' => array( 'color' => '#ff0000' ) ),? May 22, 2014 at 13:51
  • 2
    The items in the format menu inherit the styles from your editor-styles.css, except for the color styles. If you want the color styles as well, adding this code to the mce_mod() function worked for me: unset($init['preview_styles']); Jul 8, 2014 at 14:17
  • 1
    @helgatheviking regarding your small caveat: you can enable all styles if you set $init['preview_styles'] = 'font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow';. I guess this is essentially the same as @Dalton suggested, albeit in a more explicit way. This simply sets the default values, as per tmce documentation
    – robro
    Jan 14, 2017 at 15:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.