2

I am trying to create an accordion shortcode builder for WordPress using TinyMCE's editor.addCommand / windowManager.open function. I'd like to be able to add a repeatable region within the popup window to add a title & a text-area for each accordion-item so that, upon submit, each accordion item shortcode is output with those 2 parameters (title & text-area).

i.e.:
[accordion][accordion-item title=""]content[/accordion-item][accordion-item title=""]content[/accordion-item][accordion-item title=""]content[/accordion-item][/accordion]

Here is an example code of my mce-button using a panel shortcode builder which is similar to the accordion button I wish to build.

(function() {
    tinymce.PluginManager.add('shortcode_mce_button', function( editor, url ) {
        editor.addButton( 'shortcode_mce_button', {
            tooltip: 'Add custom shortcode',
            image: '/wp-content/plugins/wdst-shortcodes/public/images/shortcodes.gif',
            type: 'menubutton',
            menu: [
                {
                    text: 'panel',
                    onclick: function() {
                        editor.execCommand('panel_shortcode_mce_button_popup','',{
                            header     : '',
                            footer     : '',
                            type       : 'default',
                            content    : '',
                            panelclass : ''
                        });
                    }
                },
            ]
        });

        var panel_tag = 'panel'; //Add to the panel shortcode naming; in our case panel works fine.

        //add panel popup
        editor.addCommand('panel_shortcode_mce_button_popup', function(ui, v) {
            //setup defaults
            var header = '';
            if (v.header)
                header = v.header;
            var footer = '';
            if (v.footer)
                footer = v.footer;
            var type = 'default';
            if (v.type)
                type = v.type;
            var content = '';
            if (v.content)
                content = v.content;
            var panelclass = '';
            if (v.panelclass)
                panelclass = v.panelclass;
            //open the popup
            editor.windowManager.open( {
                title: 'Panel Shortcode Builder',
                body: [
                    {//add header input
                        type: 'textbox',
                        name: 'header',
                        label: 'Header',
                        value: header,
                        tooltip: 'Leave blank for none.'
                    },
                    {//add footer input
                        type: 'textbox',
                        name: 'footer',
                        label: 'Footer',
                        value: footer,
                        tooltip: 'Leave blank for none.'
                    },
                    {//add type select
                        type: 'listbox',
                        name: 'type',
                        label: 'Type',
                        value: type,
                        'values': [
                            {text: 'Default', value: 'default'},
                        ],
                        tooltip: 'Select the type of panel you want.'
                    },
                    {//add content textarea
                        type: 'textbox',
                        name: 'content',
                        label: 'Content',
                        value: content,
                        multiline: true,
                        minWidth: 300,
                        minHeight: 100
                    },
                    {//add class input
                        type: 'textbox',
                        name: 'panelclass',
                        label: 'Class',
                        value: panelclass,
                        tooltip: 'Add custom classes to the panel wrapper.'
                    },
                ],
                onsubmit: function( e ) { // when the ok button is clicked
                    //start the shortcode tag
                    var panel_str = '<p>[' + panel_tag + ' type="'+e.data.type+'" class="'+e.data.panelclass+'"]</p>';

                    //check for header
                    if (typeof e.data.header != 'undefined' && e.data.header.length)
                        panel_str += '<p>[' + panel_tag + '-header class=""][' + panel_tag + '-title class=""]' + e.data.header + '[/' + panel_tag + '-title][/' + panel_tag + '-header]</p>';

                    //add panel content
                    panel_str += '<p>[' + panel_tag + '-content class=""]' + e.data.content + '[/' + panel_tag + '-content]</p>';

                    //check for footer
                    if (typeof e.data.footer != 'undefined' && e.data.footer.length)
                        panel_str += '<p>[' + panel_tag + '-footer class=""]' + e.data.footer + '[/' + panel_tag + '-footer]</p>';

                    //start the shortcode tag
                    panel_str += '<p>[/' + panel_tag + ']</p>';

                    //insert shortcode to TinyMCE
                    editor.insertContent( panel_str );
                }
            });
        });
    });
})();

Image of a tinymce panel shortcode builder

For the accordion shortcode builder, the footer field would be replaced with title and the type dropdown goes away. Title & Content Area would be the sections I would want to repeat.

1 Answer 1

2

I wasn't able to directly add a repeating field (with let's say a + button) but I was able to create a 2 step process whereby the end-user can use a numeric field to set the number of repeatable areas on the next screen:

Step 1 - Select Shortcode Step 2 - Shortcode Builder Step 1/2 Step 3 - Shortcode Builder Step 2/2 Step 4 - Shortcode Output into WYSIWYG Editor

Step 1 - Select Shortcode
Step 2 - Shortcode Builder Step 1/2
Step 3 - Shortcode Builder Step 2/2
Step 4 - Shortcode Output into WYSIWYG Editor

Code:

(function() {
    tinymce.PluginManager.add('shortcode_mce_button', function( editor, url ) {
        editor.addButton( 'shortcode_mce_button', {
            tooltip: 'Add custom shortcode',
            image: '/wp-content/plugins/wdst-shortcodes/public/images/shortcodes.gif',
            type: 'menubutton',
            menu: [
                {
                    text: 'accordion',
                    onclick: function() {
                        editor.execCommand('accordion_shortcode_mce_button_popup','',{
                            type:           'default',
                            accordionclass: '',
                            numberofitems:  '2',
                        });
                    }
                },
            ]
        });

        var accordion_tag = 'accordion'; //Add to the accordion shortcode naming; in our case accordion works fine.

        //add accordion popup
        editor.addCommand('accordion_shortcode_mce_button_popup', function(ui, v) {
            //setup defaults
            var type = 'default';
            if (v.type)
                type = v.type;
            var accordionclass = '';
            if (v.accordionclass)
                accordionclass = v.accordionclass;
            var numberofitems = '';
            if (v.numberofitems)
                numberofitems = v.numberofitems;
            //open the popup
            editor.windowManager.open( {
                title: 'Accordion Shortcode Builder (Step 1 of 2)',
                classes: 'items-panel',
                body: [
                    {//add type select
                        type: 'listbox',
                        name: 'type',
                        label: 'Type',
                        value: type,
                        minWidth:300,
                        'values': [
                            {text: 'Default', value: 'default'},
                        ],
                        tooltip: 'Select the type of accordion you want.'
                    },
                    {//add class input
                        type: 'textbox',
                        name: 'accordionclass',
                        label: 'Class',
                        value: accordionclass,
                        minWidth:300,
                        tooltip: 'Add custom classes to the accordion wrapper.'
                    },
                    {//add class input
                        type: 'textbox',
                        name: 'numberofitems',
                        label: 'Number of Items',
                        value: numberofitems,
                        minWidth:300,
                        tooltip: 'Set the number of accordion items needed.'
                    },
                ],
                onsubmit: function(e) { // when the ok button is clicked
                    var finaltype = e.data.type;
                    var finalclass = e.data.accordionclass;
                    var totalitems = e.data.numberofitems;
                    var generalFormItems = [];
                    for(var i = 1; i <= totalitems; i++)
                    {
                        generalFormItems.push(
                            {
                                title: 'Accordion-Item '+i,
                                name:'item'+i,
                                type: 'form',
                                items:[
                                    {
                                        label: 'Accordion-Item ' +i,
                                        name: 'itemhtml'+i,
                                        type: 'container',
                                        minWidth:300
                                    },
                                    {
                                        label: 'Title',
                                        name: String('title'+i),
                                        type: 'textbox',
                                        minWidth:300,
                                        tooltip: 'Leave blank for none.'
                                    },
                                    {
                                        label: 'Content',
                                        name: 'content'+i,
                                        multiline: true,
                                        type: 'textbox',
                                        minWidth:300
                                    }]
                            })
                    }
                    win = editor.windowManager.open({
                        autoScroll: true,
                        minWidth: 600,
                        resizable: true,
                        classes: 'largemce-panel',
                        title: 'Insert Accordion-Items (Step 2 of 2)',
                        body: generalFormItems,
                        onsubmit: function( e ) { // when the ok button is clicked
                            //start the shortcode tag
                            var accordion_str = '<p>[' + accordion_tag + ' type="'+finaltype+'" class="'+finalclass+'"]</p>';

                            for(var i = 1; i <= totalitems; i++) {
                                var gettitle = String('e.data.title' + i);
                                var title = eval(gettitle);
                                var getcontent = String('e.data.content' + i);
                                var content = eval(getcontent);
                                accordion_str += '<p>[' + accordion_tag + '-header]';
                                accordion_str += '[' + accordion_tag + '-title]' + title + '[/' + accordion_tag + '-title]';
                                accordion_str += '[/' + accordion_tag + '-header]</p>';

                                accordion_str += '<p>[' + accordion_tag + '-content]' + content + '[/' + accordion_tag + '-content]</p>';
                            }

                            //start the shortcode tag
                            accordion_str += '<p>[/' + accordion_tag + ']</p>';

                            //insert shortcode to TinyMCE
                            editor.insertContent( accordion_str );
                        }
                    });
                }

            });

        });
    });
})();

Additional Notes:

On the second option screen, I used the autoScroll parameter to create a scrollbar but in WordPress, this conflicts with their TinyMCE styles so I had to add the 'classes' parameter to set a class on this window and then use css to fix the display issues.

/*Fix Accordion Window scroll effect*/
.mce-largemce-panel {
    top: 22% !important;
    max-height: 500px !important;
}
.mce-largemce-panel .mce-reset {
    height: 500px !important;;
    overflow: auto !important;
    margin-left: -16px !important;
    margin-right: -16px !important;
}

.mce-largemce-panel .mce-window-head {
    margin-left: 16px !important;
    margin-right: 16px !important;
}

.mce-largemce-panel .mce-foot {
    margin-left: 15px !important;
}

I also used some jquery validation on the number field on the first pop-up window. It's not the prettiest code, and I'm sure someone else could find a better way to target this window, but this is what I am currently using to validate that a number has been input.

$(document).on('keyup', '.mce-items-panel .mce-reset .mce-container-body .mce-last .mce-container-body .mce-last .mce-container-body input.mce-last', function(event) {
    var v = this.value;
    if($.isNumeric(v) === false) {
        //chop off the last char entered
        this.value = this.value.slice(0,-1);
    }
});

So, this just about covers everything. If there are any further updates, I'll post those at that time. Hopefully this will atleast help some people who need a repeating field solution and can improve upon what I have shown here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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