• Resolved amschlag

    (@amschlag)


    I love your plugin, mostly because of the easy to use flexible content selection or permission settings, but I have a serious problem when adding custom buttons to the wysiwyg editor, like described here, and that works fine – as long as ACF Extended is not activated.

    The Wysiwyg Delayed Fields feature in flexible content breaks these custom buttons.
    I looked for the responsible function in the acfe plugin code and found it in acfe-input.js lines 1949, 1967.

    In both lines the editor is re-initialized with editor.initializeEditor(), although the user-defined buttons have been removed.

    Even if I remove the lines 1973-1974

    
    acf.addAction ('show_field / type = wysiwyg', acfeFlexibleDelayInit);
    acf.addAction ('ready_field / type = wysiwyg', acfeFlexibleDelayInit);
    

    works fine too.

    Don’t you have a hook, variable or switch to disable this “feature” via theme code or remove/overwrite the acf.addAction of the function “acfeFlexibleDelayInit”?

    Removing it in the plugin code itself would be the worst case … šŸ™
    Thanks for help!

    • This topic was modified 2 years, 6 months ago by amschlag.
    • This topic was modified 2 years, 6 months ago by amschlag.
    • This topic was modified 2 years, 6 months ago by amschlag.
    • This topic was modified 2 years, 6 months ago by Yui.
Viewing 6 replies - 1 through 6 (of 6 total)
  • Thread Starter amschlag

    (@amschlag)

    This topic is marked as spam. WHY?

    Plugin Author Konrad Chmielewski

    (@hwk-fr)

    Hello,

    Thanks for the feedback!

    Your account seems to be pretty new, and there is an external link to the ACF forum in your report. Maybe you triggered some sort of antispam filter. If you need further information, please contact the WP Forum Moderation team.

    Regarding your report, I just tested it and the WYSIWYG Editor inside a Flexible Content works nicely with custom buttons. It looks like there was an issue with the initial code of the user in the topic you linked.

    As the user explained himself later, you should not use the admin_head hook to add custom buttons and enqueue custom JS file into TinyMCE. But rather use TinyMCE hooks at top level, or at least within the init hook. This also reflect the documentation of the mce_external_plugins filter.

    Here is the video demo of my test: https://i.imgur.com/Lqc5YEd.mp4

    Here is the code I used during my test:

    add_action('init', 'my_init');
    function my_init(){
        
        add_filter('mce_external_plugins', 'my_mce_external_plugins');
        add_filter('mce_buttons', 'my_mce_buttons');
        
    }
    
    function my_mce_external_plugins($plugin_array){
        
        $plugin_array['shortcodes_button'] = get_template_directory_uri() . '/assets/js/shortcodes.js';
        return $plugin_array;
        
    }
    
    function my_mce_buttons($buttons){
        
        array_push($buttons, "shortcodes_button");
        return $buttons;
        
    }
    

    Note that you can also directly call the hooks at top level like this, if you don’t need the init hook:

    add_filter('mce_external_plugins', 'my_mce_external_plugins');
    function my_mce_external_plugins($plugin_array){
        
        $plugin_array['shortcodes_button'] = get_template_directory_uri() . '/assets/js/shortcodes.js';
        return $plugin_array;
        
    }
    
    add_filter('mce_buttons', 'my_mce_buttons');
    function my_mce_buttons($buttons){
        
        array_push($buttons, "shortcodes_button");
        return $buttons;
        
    }
    

    Regarding your question about the Automatic Delayed Init when using a WSYIWYG field inside a Flexible Content, this feature is builtin ACF Extended as it enhance general performance during the admin page load, especially when having a lot of TinyMCE instances.

    Historically, this improvement has been here since 2 years and has been field tested on a lot of production websites. Unfortunately, I cannot provide hooks or settings to disable/enable everything within ACF Extended, especially for a feature like this one which is a objectively a QOL improvement and favourable to everyone.

    Hope it helps!

    Have a nice day!

    Regards.

    Thread Starter amschlag

    (@amschlag)

    Hi hwk-fr,
    thanks a lot for your feedback. I understand your code history and reason for this feature. But maybe you could spend some time again to take a look a the problem:

    I already used the init hook, but it wasn’t successful.
    Also the hint using the mce_external_plugin filter outside any hook, doesn’t work.

    I’m using the classic editor (no blocks).

    When I add a Layout, the custom buttons in the wysiwyg fields inside those new layouts are visible (only until next reload).
    If the Layout is collapsed by user or by setting ‘Default Layout State’, when loaded, the buttons are visible.
    When I edit a layout inside a modal, the custom buttons are visible.

    I tried it without delayed and with delayed initialization – both without success.

    The Custom Buttons are only not visible, when loaded inside flexible field, placed in a layout initially opened… Maybe I oversee something.

    My Code

    
    add_filter( 'acf/fields/wysiwyg/toolbars', 'od_toolbars' );
    	
    	function od_toolbars( $toolbars ) {
    
    		$toolbars['Text Default'] = array();
    		$toolbars['Text Default'][1] = array(
    			// 'od_mce_btn_headline_h1',
    			'od_mce_btn_headline_h2',
    			'od_mce_btn_headline_h3',
    			'od_mce_btn_headline_h4',
    			//'od_mce_btn_categ',
    			'od_mce_btn_style_xxl',
    			'od_mce_btn_style_xl',
    			'od_mce_btn_style_lg',
    			'od_mce_btn_style_sm',
    			'od_mce_btn_cite',
    			// 'styleselect',
    			'od_mce_btn_cta',
    			'bold', 
    			'italic',
    			'link',
    			'unlink',
    			'bullist', 
    			'od_mce_btn_list_check',
    			'charmap', 
    			'removeformat', 
    			'pastetext',
    			'visualchars',
    			'visualblocks'
    		);
    
    		return $toolbars;
    	}
    
    add_action( 'init', 'od_mce_buttons' );
    
    	function od_mce_buttons() {
    		// check user permissions
    		if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
    			return;
    		}
    		// check if WYSIWYG is enabled
    		if ( get_user_option( 'rich_editing' ) !== 'true' ) {
    			return;
    		}
    
    		add_filter( 'mce_external_plugins', 'od_mce_add_buttons' );
    		add_filter( 'mce_buttons', 'od_mce_register_buttons' );
    	}
    
    	function od_mce_add_buttons( $plugin_array ) {
    		$plugin_array['od_mce_btn_formats'] = get_template_directory_uri() . '/assets/admin/mce-btn-formats.js';
    		
    		return $plugin_array;
    	}
    
    	function od_mce_register_buttons( $buttons ) {
    		array_push( $buttons, 'od_mce_btn_categ' );
    		array_push( $buttons, 'od_mce_btn_headline_h1' );
    		array_push( $buttons, 'od_mce_btn_headline_h2' );
    		array_push( $buttons, 'od_mce_btn_headline_h3' );
    		array_push( $buttons, 'od_mce_btn_headline_h4' );
    		array_push( $buttons, 'od_mce_btn_style_xl' );
    		array_push( $buttons, 'od_mce_btn_style_lg' );
    		array_push( $buttons, 'od_mce_btn_style_sm' );
    		array_push( $buttons, 'od_mce_btn_style_xs' );
    		array_push( $buttons, 'od_mce_btn_cta' );
    		array_push( $buttons, 'od_mce_btn_cite' );
    		array_push( $buttons, 'od_mce_btn_list_check' );
    
    		return $buttons;
    	}
    

    The mce-btn-formats.js

    jQuery( function( $ ) {
    
    /*	================================================== 
    	MCE Custom Buttons
    	================================================== */
    
    	tinymce.PluginManager.add( 'od_mce_btn_formats', function( editor, url ) {
    		
    		let formats = {
    			'h1' 	: {
    				id 			: 'headline_h1',
    				name 		: 'Headline h1',
    				image		: 'mce-btn-headline-h1.png',
    				disabledSel : 'span, blockquote, ul, ol, li',
    				opts 		: {
    					block 		: 'h1',
    					exact		: true
    				}
    			},
    			'h2' 	: {
    				id 			: 'headline_h2',
    				name 		: 'Headline h2',
    				image		: 'mce-btn-headline-h2.png',
    				disabledSel : 'span, blockquote, ul, ol, li',
    				opts 		: {
    					block 		: 'h2',
    					exact		: true
    				}
    			},
    			'h3' 	: {
    				id 			: 'headline_h3',
    				name 		: 'Headline h3',
    				image		: 'mce-btn-headline-h3.png',
    				disabledSel : 'span, blockquote, ul, ol, li',
    				opts 		: {
    					block 		: 'h3',
    					exact		: true
    				}
    			},
    			'h4' 	: {
    				id 			: 'headline_h4',
    				name 		: 'Headline h4',
    				image		: 'mce-btn-headline-h4.png',
    				disabledSel : 'span, blockquote, ul, ol, li',
    				opts 		: {
    					block 		: 'h4',
    					exact		: true
    				}
    			},
    			'categ' 	: {
    				id 			: 'categ',
    				name 		: 'Category',
    				image		: 'mce-btn-categ.png',
    				disabledSel : 'span, blockquote, ul, ol, li',
    				opts 		: {
    					inline		: 'em',
    					selector	: 'h1, h2, h3, h4',
    					classes		: 'categ',
    					exact		: true
    				}
    			},
    			'style_xxl' 	: {
    				id 			: 'style_xxl',
    				name 		: 'Text xxlarge',
    				image		: 'mce-btn-style-xxl.png',
    				disabledSel : 'h1, h2, h3, h4, blockquote',
    				opts 		: {
    					selector	: 'p, li',
    					classes		: 'xxl',
    					exact		: true
    				}
    			},
    			'style_xl' 	: {
    				id 			: 'style_xl',
    				name 		: 'Text xlarge',
    				image		: 'mce-btn-style-xl.png',
    				disabledSel : 'h1, h2, h3, h4, blockquote',
    				opts 		: {
    					selector	: 'p, li',
    					classes		: 'xl',
    					exact		: true
    				}
    			},
    			'style_lg' 	: {
    				id 			: 'style_lg',
    				name 		: 'Text large',
    				image		: 'mce-btn-style-lg.png',
    				disabledSel : 'h1, h2, h3, h4, blockquote',
    				opts 		: {
    					selector	: 'p, li',
    					classes		: 'lg',
    					exact		: true
    				}
    			},
    			'style_sm' 	: {
    				id 			: 'style_sm',
    				name 		: 'Text small',
    				image		: 'mce-btn-style-sm.png',
    				disabledSel : 'h1, h2, h3, h4, blockquote',
    				opts 		: {
    					selector	: 'p, li',
    					classes		: 'sm',
    					exact		: true
    				}
    			},
    			'cite' 	: {
    				id 			: 'cite',
    				name 		: 'Zitat',
    				image		: 'mce-btn-cite.png',
    				disabledSel : 'h1, h2, h3, h4',
    				opts 		: {
    					block 		: 'blockquote',
    					exact		: true,
    					wrapper		: true,
    				}
    			},
    			'cta' 	: {
    				id 			: 'cta',
    				name 		: 'CTA Button',
    				image		: 'mce-btn-cta.png',
    				disabledSel : 'h1, h2, h3, h4',
    				opts 		: {
    					selector 	: 'a',
    					classes		: 'btn',
    					exact		: true
    				}
    			},
    			'list_check' 	: {
    				id 			: 'list_check',
    				name 		: 'Checkliste',
    				image		: 'mce-btn-list-check.png',
    				disabledSel : 'h1, h2, h3, h4, blockquote, a, p, span, em, strong',
    				opts 		: {
    					selector 	: 'ul',
    					classes		: 'list--check',
    					exact		: true
    				}
    			}
    		};
    
    		$.each( formats, function( index, format ) {
    
    			editor.on( 'init', function () {
    				editor.formatter.register( '_'+ format['id'], format['opts'] );
    			} );
    
    			editor.addButton( 'od_mce_btn_'+ format['id'], {
    				title					: format['name'],
    				image 					: url +'/'+ format['image'],
    				disabledStateSelector 	: format['disabledSel'],
    				onPostRender			: function() {
    					var self = this;
    					var setup = function() {
    						editor.formatter.formatChanged( '_'+ format['id'], function( state ) {
    							self.active( state );
    						});
    					};
    					editor.formatter ? setup() : editor.on( 'init', setup );
    					this.disabled( false );
    				},
    				onClick					: function() {
    					editor.formatter.toggle( '_'+ format['id'] );
    				}
    			} );
    		} );
    	} );
    });
    Plugin Author Konrad Chmielewski

    (@hwk-fr)

    Hello,

    The problem doesn’t come from the PHP hooks, but from your Javascript TinyMCE plugin code. In fact, your JS plugin wait for document ready before running the function, which is not the recommended method to add a TinyMCE plugin.

    Here is your TinyMCE plugin code simplified:

    jQuery(function($){
    
        tinymce.PluginManager.add('od_mce_btn_formats', function(editor, url){
            editor.addButton('od_mce_btn_headline_h1', {
                title: 'Button',
                type: 'button',
                icon: 'plus',
            });
        });
    
    });
    

    The jQuery(function($){ part is a shorthand of jQuery(document).ready(function($){ which is a hook that will wait for document ready before running the code.

    While your code may work in some cases, the recommend method to initialize a tinyMCE plugin is to use a self-invoked function like this:

    (function(){
    
        tinymce.PluginManager.add('od_mce_btn_formats', function(editor, url){
            editor.addButton('od_mce_btn_headline_h1', {
                title: 'Button',
                type: 'button',
                icon: 'plus',
            });
        });
    
    })();
    

    You’ll find that logic on all online WordPress tutorials:

    In your case, you want to use jQuery in your TinyMCE plugin, so you should add jQuery as an alias to the self-invoked function. That solution will fix your issue:

    (function($){
    
        tinymce.PluginManager.add('od_mce_btn_formats', function(editor, url){
            editor.addButton('od_mce_btn_headline_h1', {
                title: 'Button',
                type: 'button',
                icon: 'plus',
            });
        });
    
    })(jQuery);
    

    You can read more about difference between self invoked function vs document ready here.

    Hope it helps!

    Have a nice day!

    Regards.

    Thread Starter amschlag

    (@amschlag)

    You’re right!
    I know and tried most of you examples, But this “jquery” initialization initially came from another file where I need this and after that I didn’t pay attention to it every time I compared the code.

    Thanks a lot!

    Plugin Author Konrad Chmielewski

    (@hwk-fr)

    Hello,

    You’re welcome! I’m glad to hear it now works as expected!

    Also thanks for the nice review šŸ™‚

    Have a nice day!

    Regards.

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘ACF Flexible Content / Wysiwyg / Custom Buttons not showing’ is closed to new replies.