Toggle Me Divi


The people at Elegant Themes are moving forward (IMO) on cleaning up the Divi code base for the developer’s addition, but at the same time, responding to user’s feedback to make the front-end build experience a little easier. This has resulted in some changes to the code base in the ‘main-modules.php’ file. I wrote a series of posts, starting here, dissecting this file with an idea toward writing custom modules. This post is the first in a series of posts updating this series of tutorials for the Divi theme starting with 3.0.45. 

So, the big change introduced in Divi 3.0.45 is the appearance of toggles on the front-end builder, along with a rearrangement of various module options into a more logical order. Clicking on any of these causes a set of options to toggle open. This is an improvement (IMO) over the old version where the options were open in a large list (see the image at the top of the post). This feature might even entice me to using the front-end more, we’ll see. This rearrangement is slightly more subtle on the back-end. 

First up, you can see that the tabs at the top of the module settings have been changed from: ‘General Settings’, ‘Advanced Design Settings’, and ‘Custom CSS’, to the sleeker: ‘Content’, ‘Design’, and ‘Advanced’. So let’s look at the code and see how they did this. First, looking at the pre-3.0.45 ‘class-et-builder-element.php’ file (located in the theme /includes/builder folder).  

function get_main_tabs() {
        $tabs = array(
            'general'    => esc_html__( 'General Settings', 'et_builder' ),
            'advanced'   => esc_html__( 'Advanced Design Settings', 'et_builder' ),
            'custom_css' => esc_html__( 'Custom CSS', 'et_builder' ),

        return apply_filters( 'et_builder_main_tabs', $tabs );

So this method exposes a set of properties that map the names of each tab in a set of key=>value pairs. The new code, thankfully and with the kindness of the ET folks, uses the same key naming and only changes the values.

function get_main_tabs() {
        $tabs = array(
            'general'    => esc_html__( 'Content', 'et_builder' ),
            'advanced'   => esc_html__( 'Design', 'et_builder' ),
            'custom_css' => esc_html__( 'Advanced', 'et_builder' ),

        return apply_filters( 'et_builder_main_tabs', $tabs );

This means that in pre-existing custom modules that use

 'tab_slug' => 'advanced', 

will just map to the ‘Design’ tab, instead of the ‘Advanced Design Settings’ tab. No breaking of old code, yeah!!!!

Just as a point of interest, note how they are adding the tab names – using an apply_filters() WordPress function. This would be a tempting place to hook in an ‘add_filter()’ function to modify the tab names. The only thing to be aware of is that you have to be careful of how you call the add_filter, otherwise you will change the tab names for all filters. Additionally, the builder currently uses a script to determine the number of tabs to put at the top, simply adding to the array won’t allow for additional tabs.  

Moving back to the ‘main-modules.php’ file, the really big change in Divi 3.0.45 are those toggles. That controls how the options are presented and impacts both the ‘init()’ and the ‘get_fields()’ methods.


For the ‘init()’ method there is an addition of a new section. Setting the name, slug, fb_support, whitelisted_fields, fields_defaults, advanced_options, and other misc. keys are exactly the same. The new key added in is called ‘options_toggle’. It is set just like the rest of the keys in this method. Let’s look at this section of code for the Image module.

$this->options_toggles = array(
    'general'  => array(
      'toggles' => array(
         'main_content' => esc_html__( 'Image', 'et_builder' ),
         'link'         => esc_html__( 'Link', 'et_builder' ),
    'advanced' => array(
      'toggles' => array(
         'overlay'    => esc_html__( 'Overlay', 'et_builder' ),
         'alignment'  => esc_html__( 'Alignment', 'et_builder' ),
         'width'      => array(
        'title'    => esc_html__( 'Sizing', 'et_builder' ),
                'priority' => 65,
    'custom_css' => array(
      'toggles' => array(
         'animation' => array(
           'title'    => esc_html__( 'Animation', 'et_builder' ),
                'priority' => 90,
        'attributes' => array(
             'title'    => esc_html__( 'Attributes', 'et_builder' ),
                      'priority' => 95,

On the very top line, we are saying that the ‘options_toggles’ key for the Image module (designated by $this since we are within the Image module class) is equal to a large array as a value. We then define three key=>value subarrays. The first is ‘general’, the second is ‘advanced’, and the third is ‘custom_css’. You should recognize these as the $tabs that were defined in our structure file. In each of these, we define a set of option holder areas that have the titles that will display on the front-end when the toggle is closed, or above the options in the back-end. These are held in the ‘toggles’ key=>value pair – which is just another array.

Looking at the ‘general’ key=>value pair first. We can see that the ‘toggles’ key=>value is an array with two additional key=>value pairs. The first has the key ‘main_content’ followed by a value of “esc_html__( ‘Image’, ‘et_builder’ )”. Let’s remember what this means from the earlier tutorial. The WordPress ‘esc_html__()’ function does two things – takes the string that is passed as the first argument and escapes it for safe HTML output. Secondly -and importantly in this case since we are unlikely to have put in unsafe characters – it translates the string into other languages based on the domain passed in as the second argument. If you don’t use this in a custom module, the nice users in Germany, Italy, or Poland will be cross with you! So this line sets up a holding area titled ‘Image’ under the ‘General’ tab. The next line sets up one called ‘Link’. Basically, you need one of these key=>value pairs for each custom field you want. Be careful with naming, each of the keys in the ‘toggles’ must be unique in the entire ‘options_toggles’ array. 

Those of you that are more astute will point out that there are three toggles under the ‘General’ tab for the Image module. ET helpfully has prepopulated each of the tabs with a couple of key=>value pairs already, including the ‘Admin Label’ titled one seen in the picture above.

Moving to the ‘Advanced’ key=>value pair, we see a slight alteration. The third set is an array with two key=>value pairs. This would work perfectly fine if we were to write it as:

'width' => esc_html__( 'Sizing', 'et_builder' ),

just like the others. As far as I can tell, ET has done it this way just to be able to change the order in which it is displayed. The ‘Advanced’ tab has two additional default option holders, ‘Border’ and ‘Spacing’. By storing it as an array with a ‘title’ key, then a ‘priority’ key can also be added. In this case, the value of 65 causes it to be displayed after the ‘Border’ holder, but before’Spacing’. I haven’t tracked down the priorities of each field as yet, so you will have to experiment a little if you want to change the order in a custom module.

Okay, so that is it for the changes to the ‘init()’ method. The only other thing to note is that you don’t have to supply additional fields for each of the three tabs. The builder will still fill in the default holders assigned by ET.


In comparing the pre- and post-3.0.45 method, you can easily see that there are very few changes. The main one is the use of a new key within the ‘$fields’ array, ‘toggle_slug’. This key is used to assign the field to a toggle defined in the options_toggles array defined in the init() method. If the toggle_slug is not located on the ‘general tab’, you must also specify a value for another key, ‘tab_slug’. The value here will be one of the two other tabs, either ‘advanced’, or ‘custom_css’. As examples from the Image module:

$fields = array(
  'src' => array(
      'label'      => esc_html__( 'Image URL', 'et_builder' ),
      'type'       => 'upload',
      'option_category'    => 'basic_option',
      'upload_button_text' => esc_attr__( 'Upload an image', 'et_builder' ),
      'choose_text'        => esc_attr__( 'Choose an Image', 'et_builder' ),
      'update_text'        => esc_attr__( 'Set As Image', 'et_builder' ),
      'affects'            => array(
      'description'        => esc_html__( 'Upload your desired image, or type in the URL to the image you would like to display.', 'et_builder' ),
      'toggle_slug'        => 'main_content',
 'alt' => array(
      'label'    => esc_html__( 'Image Alternative Text', 'et_builder' ),
      'type'            => 'text',
      'option_category' => 'basic_option',
      'depends_default' => true,
      'depends_to'      => array(
  'description'     => esc_html__( 'This defines the HTML ALT text. A short description of your image can be placed here.', 'et_builder' ),
  'tab_slug'        => 'custom_css',
  'toggle_slug'     => 'attributes',

The first field ‘src’ is on the ‘Content’ tab, so it does not have a ‘tab_slug’ key=>value pair defined, while the second field ‘alt’ has a ‘tab_slug’ => ‘custom_css’ pair, forcing it to show up on the third tab, ‘Advanced’. Note, you still need to assign it a value for the ‘toggle_slug’ to have it show up at the right place in the builder.  

In looking through the Image module code, I realized that there are three key=>value pairs I forgot to explain in my original set of tutorials. The first two are the ‘choose_text’ and ‘update_text’ that go along with the ‘upload_button text’. The ‘upload_button_text’ gives a label to the button that the user sees in the direct module. The ‘choose_text’ gives a label to the button that the user sees in the “Media Library” tab of the image selector screen. The ‘update_text’ key gives a label to the button that the user sees in the ‘Upload Files’ tab of the image selector screen.

The third key is ‘depends_to’. To be honest, this one is a little mysterious to me and I haven’t spent the time digging through the code to figure it out.  I found that in several cases I can remove it without impacting the behavior of the module. 

Overall, this latest iteration of the Divi theme adds in some extra styling and altered presentation of options on the front-end to speed work-flow. While the code has changed slightly to support this new presentation, older code doesn’t seem to break. I’m betting that this is because none of the custom modules I tried can be used in front-end builder, which seems more dependant on the toggles for functionality, rather than styling. Looking at some of the code refactoring, I feel like there are some fairly sizable changes in stock for Divi. In other words, I’m going to be updating these tutorials again!! 

I hope this helps someone out. As always, give me a shout by e-mail or in the comments if there is something you want further explained, suggestions for improvement, or outright corrections! 



Published: 05.13.2017

In: Legacy, Programming

2 thoughts on “Toggle Me Divi”

  1. Good to see some Divi-related backend articles among the ocean of CSS tweaks for Divi)

    1. Bob Means says:

      Thanks! Sometimes I feel like that old adage, “You can lead a horse to water…” 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.