I have this shortcode structure:

   [type1]some content[/type1]
   [type2]some more content[/type2]
   [typeN]some other content[/typeN]

I would like to have the $content of the sub shortcodes stored in an array. What I am doing at the moment is, in their function, I pass $content to a global variable and then create an array out of them, but it is not very elegant.

Also, I cannot have them as attributes of the main shortcode tag as this:

[component type1="some content" type2="some more content"]

as I need to have the attributes on new lines for readability - something I'm trying to get addressed here: wpautop() when shortcode attributes are on new lines break args array

EDIT - I'm not looking for a list-like structure, but to have these values in a key-value array to populate a complex markup, and also use the array as a JSON object in my javascript functions.

1 Answer 1


Your data structure appears to be very list like. The reason you're running into difficulties is because you're trying to fix a fix, which is never a good thing. Instead I would suggest you seek alternative solutions to your problem.

For example, instead it would be more logical to use something like:

<ul class="component">
    <li>content 1</li>
    <li>content 2</li>

Using this kind of structure you can implement everything from JQuery accordions, tabs, blocks of content, etc etc

.component {
.component > li {
    /* style each list element here

Or using ol even. Then coupling this with editor styles to mark it out as different from a normal unordered list.

To further differentiate it, use an extra button using TinyMCE.

function add_component_button() {
   if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') )
   if ( get_user_option('rich_editing') == 'true') {
     add_filter('mce_external_plugins', 'add_component_tinymce_plugin');
     add_filter('mce_buttons', 'register_component_button');

function register_component_button($buttons) {
   array_push($buttons, "|", "componentlist");
   return $buttons;

function add_component_tinymce_plugin($plugin_array) {
   $plugin_array['componentlist'] = get_bloginfo('template_url').'/custom/editor_plugin.js';
   return $plugin_array;

add_action('init', 'add_component_button');

function my_refresh_mce($ver) {
  $ver += 3;
  return $ver;

add_filter( 'tiny_mce_version', 'my_refresh_mce');

Here's editor_plugin.js:

(function() {
    tinymce.create('tinymce.plugins.componentul', {
        init : function(ed, url) {
            ed.addButton('componentul', {
                title : 'componentul',
                image : url+'/component.png',
                onclick : function() {
                    ed.execCommand('mceInsertContent', false, '<ul class="component"><li>Start typing here</li></ul>');
        createControl : function(n, cm) {
            return null;
        getInfo : function() {
            return {
                longname : "Component UL",
                author : 'Tom J Nowell',
                authorurl : 'http://tomjn.com/',
                infourl : 'http://tomjn.com/',
                version : "1.0"
    tinymce.PluginManager.add('componentul', tinymce.plugins.componentul);
  • thanks, this is an impressive answer that deserves a +1 at least. I probably had to be more specific - I am having a list-like structure but my pure target is to get a key-value array, as I need it its contents to both populate a complex markup structure, and create a JSON object with the same values to be used in a javascript method.
    – Luca
    Nov 6, 2012 at 11:31
  • var components = $('.component > li ');?
    – Tom J Nowell
    Nov 6, 2012 at 14:17
  • 1
    Perhaps if you're pulling it in via AJAX too then it would be best to use post meta instead, and simply do a single shortcode like [displaycomponents] rather than have the data structure itself in the content ( and all the problems it brings with it )
    – Tom J Nowell
    Nov 6, 2012 at 14:18
  • I agree, I think that a custom post is probably the best way for my case. thanks for your help!
    – Luca
    Nov 6, 2012 at 14:34

Your Answer

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

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