Create A Custom Module in the Enfold Advanced Layout Builder

If you’ve done any custom WordPress development in the past 10 years, you’ve probably stumbled upon or worked on the Enfold theme which uses the Advanced Layout Builder.  This is a proprietary page editor used by the popular theme developed by the theme’s creators.  The theme alone has 200k sales, so it’s fairly common. It comes with a lot of built in modules and elements, but there may come a point where you’d like to extend this editor to allow for custom elements.

Below is an example code snippet that builds this custom element.  I’m going to describe how to use it in more detail below.

<?php
/**
* EXAMPLE CUSTOM ADVANCED LAYOUT BUILDER ELEMENT
* 
* 
*/
if ( ! defined( 'ABSPATH' ) ) {  exit;  }
if ( ! class_exists( 'avia_your_new_custom_element' ) ) {
class avia_your_new_custom_element extends aviaShortcodeTemplate {
/**
 * Create the config array for the shortcode button
 */
function shortcode_insert_button() {
	$this->config['version']		= '1.0';
	$this->config['self_closing']	= 'yes';

	$this->config['name']			= __( 'Title of Your Custom Element', 'avia_framework' );
	$this->config['tab']			= __( 'Custom Elements Tab', 'avia_framework' );
	$this->config['icon']			= AviaBuilder::$path['imagesURL'] . 'sc-accordion-slider.png';
	$this->config['order']			= 100;
	$this->config['target']			= 'avia-target-insert';
	$this->config['shortcode'] 		= 'av_your_new_custom_shortcode';
	$this->config['tinyMCE'] 	    = array('disable' => true);
	$this->config['tooltip'] 	    = __( 'Tooltip for your new custom element!', 'avia_framework' );
	$this->config['preview'] 		= 'large';
	$this->config['id_name']		= 'id';
	$this->config['id_show']		= 'yes';
}

/**
 * Custom Fields
 *
 * Here are the fields you can use for the element that a content editor can fill out
 *
 * @return void
 */
function popup_elements() {			
	$this->elements = array(				
		array(
				'type' 	=> 'tab_container', 
				'nodescription' => true
			),						
		array(
				'type' 	=> 'tab',
				'name'  => __( 'Content', 'avia_framework' ),
				'nodescription' => true
			),						
			array(	
				'name'			=> __( 'Field 1', 'avia_framework' ),
				'desc'			=> __( 'Put your field value here', 'avia_framework' ),
				'id'			=> 'field_1',
				'fetch'			=> 'id',
				'container_class' => 'avia-element-fullwidth',
				'type'  => 'input',
				'std'			=> ''
			),
		array(
				'type' 	=> 'tab_close',
				'nodescription' => true
			),	
		array(
				'type' 	=> 'tab_container_close',
				'nodescription' => true
			),	
		);				
}

/**
 * Editor Element - this function defines the visual appearance of an element on the AviaBuilder Canvas
 * Most common usage is to define some markup in the $params['innerHtml'] which is then inserted into the drag and drop container
 * Less often used: $params['data'] to add data attributes, $params['class'] to modify the className
 *
 *
 * @param array $params this array holds the default values for $content and $args.
 * @return $params the return array usually holds an innerHtml key that holds item specific markup.
 */
function editor_element( $params )
{
	$params['class'] = '';
	$params['innerHtml'] = "<div class='avia_textblock avia_textblock_style' data-update_with='content' style='padding:12px 0;text-align:center'><h1>CUSTOM ELEMENT</h1></div>";
	return $params;
}

/**
 * Frontend Shortcode Handler
 *
 * @param array $atts array of attributes
 * @param string $content text within enclosing form of shortcode element
 * @param string $shortcodename the shortcode found, when == callback name
 * @return string $output returns the modified html string
 */
function shortcode_handler( $atts, $content = '', $shortcodename = '', $meta = '' ) {			
	$output = '';		
	$output .= '<div class="your-custom-element">';	
			$output .= '<h2>' . $atts['field_1'] . '</h2>'; 
	$output .= '</div>';						
	return $output;
}

}
}
?>

There are 4 parts to this code snippet and they all play an important role in how your element appears and functions.

  1. Declaring the element and defining its name, description, icon, etc
  2. Determining what fields the user can edit while using this element
  3. Determining what the element looks like inside the editor when used
  4. Determining what is output on the front-end with your element

We are going to describe how and where to set this up in greater detail.

Setting up your files and calling them

The first step in extending this custom builder is determining where these files are going to live.  In my case, I set them up in my WordPress theme and then referenced them in my functions.php  file.  That is what I would recommend.

So, in your theme, set up a directory called “custom-elements”.  You are probably going to make multiple custom elements and they all need a separate file.  You would place them inside this directory.  Here is the code snippet you would place in your functions.php  file to call that directory so Advanced Layout Builder knows where to find them:

add_filter('avia_load_shortcodes', 'avia_include_shortcode_template', 15, 1);
function avia_include_shortcode_template($paths) {
  $template_url = get_stylesheet_directory();
  array_unshift($paths, $template_url.'/custom-elements/');
  return $paths;
}

That declares that going forward, check out “/custom-elements/” to see if there are files.

Next, let’s set up a demo custom element file within that directory.  Any custom element files in that directory going forward will be recognized and included when the Advanced Layout Builder loads on the back-end.

Make a file in that directory called “custom-element.php”.  Copy the entire code snippet that builds the custom element in there and save.  You should now see a custom element when you refresh the page editor in the back end on it’s own tab.

Let’s break down those parts to see how you can re-purpose those for your needs.

Extending the Avia Shortcodes Class

This part of the code defines your custom element’s name and function:

if ( ! class_exists( 'avia_your_new_custom_element' ) ) {
class avia_your_new_custom_element extends aviaShortcodeTemplate {

You are going to need to make avia_your_new_custom_element  a unique function name for each of the custom elements you make.  Make sure you update it on both lines.

Customize the element declaration

Let’s look at this piece of the code:

function shortcode_insert_button() {
	$this->config['version']		= '1.0';
	$this->config['self_closing']	= 'yes';

	$this->config['name']			= __( 'Title of Your Custom Element', 'avia_framework' );
	$this->config['tab']			= __( 'Custom Elements Tab', 'avia_framework' );
	$this->config['icon']			= AviaBuilder::$path['imagesURL'] . 'sc-accordion-slider.png';
	$this->config['order']			= 100;
	$this->config['target']			= 'avia-target-insert';
	$this->config['shortcode'] 		= 'av_your_new_custom_shortcode';
	$this->config['tinyMCE'] 	    = array('disable' => true);
	$this->config['tooltip'] 	    = __( 'Tooltip for your new custom element!', 'avia_framework' );
	$this->config['preview'] 		= 'large';
	$this->config['id_name']		= 'id';
	$this->config['id_show']		= 'yes';
}

This section is defining a lot of important details about your new custom element.  Most are self explanatory, but the key things are the name, icon, shortcode, and tooltip.  These all need to be unique and help identify what they are and do to to your content editor.

I got the icon by literally “Right Click > Inspect Element > Image Name” of the icon I wanted to steal from another Advanced Layout Builder Module.  They almost always start with “sc-” and you can find the best one that fits your element.

Another important piece is the “tab” section.  If you notice in the editor, you can separate the custom modules by “Layouts Elements, Content Elements, etc”.  Do you want this element to be in one of those?  If so, label it the same.  If you want it to be on a separate tab, give that definition a different name.  Other custom elements you make can also reference that exact tab name to group them together.  Feel free to experiment!

Customize the Editable Fields

We move on to the next chunk of code:

function popup_elements() {			
$this->elements = array(				
array(
		'type' 	=> 'tab_container', 
		'nodescription' => true
	),						
array(
		'type' 	=> 'tab',
		'name'  => __( 'Content', 'avia_framework' ),
		'nodescription' => true
	),						
	array(	
		'name'			=> __( 'Field 1', 'avia_framework' ),
		'desc'			=> __( 'Put your field value here', 'avia_framework' ),
		'id'			=> 'field_1',
		'fetch'			=> 'id',
		'container_class' => 'avia-element-fullwidth',
		'type'  => 'input',
		'std'			=> ''
	),
array(
		'type' 	=> 'tab_close',
		'nodescription' => true
	),	
array(
		'type' 	=> 'tab_container_close',
		'nodescription' => true
	),	
);				
}

In this example, I’ve only made 1 field, called “Field 1”, where a user can add some custom content in the element.  The “type = input” describes if this is a text field, a text area, a radio button, image, etc.  There isn’t a ton of documentation on your options, but the best way to explore more is to dig into the Advanced Layout Builder.  If you look at the code for other default elements, they will have a similar set up with waaaaaaay more fields and you can cut/paste parts of those to set up your editor how you wish.

One important note, the ID for each should be unique.  You can also group them in tabs which is what the 2nd array in this code snippet does.  You can start new tabs and place other editable fields on those.  It’s just a nice way to group things and as your custom modules become more complex, you can make editing content easier.

Define what your element looks like in the editor

This piece of code does exactly that:

function editor_element( $params ) {
	$params['class'] = '';
	$params['innerHtml'] = "<div class='avia_textblock avia_textblock_style' data-update_with='content' style='padding:12px 0;text-align:center'><h1>CUSTOM ELEMENT</h1></div>";
	return $params;
}

I simplify this a lot of times.  You can call the editable field’s content and spit it out, but for my case, I just liked having the element’s name displayed and only that.  When a content editor wants to see how the page is structured and where certain content blocks are, they can easily identify the module’s name and that is sufficient for me.

Determine What Your New Element Outputs

The important stuff, right?  What does the actual element output on the front-end when used.  Let’s take a look at that function:

function shortcode_handler( $atts, $content = '', $shortcodename = '', $meta = '' ) {			
	$output = '';		
	$output .= '<div class="your-custom-element">';	
			$output .= '<h2>' . $atts['field_1'] . '</h2>'; 
	$output .= '</div>';						
	return $output;
}

This is a fairly simple example, but you can get a really good reference on how to modify it for what you need.  Remember that earlier function where you defined the editable fields?  Well we made one called “Field 1” and gave it an ID of “field_1”.

While we output the HTML we want, you can called that value with the syntax $atts[‘field_1’] .  As you begin to build more complex elements, you will need to give those unique identifiers and reference them in the same way.

Conclusion

Hopefully, this is a simplistic example to get you started on building custom Advanced Layout Builder elements.  Here is a great reference that helped me immensly in starting out on this endeavor and I believe there may be more valueable information in that article, as well.  I hope this helps.  Leave your comments and questions in the section below.  Happy Coding!

1 Comment

  • Great post. could this be done via a plugin?

Leave A Comment

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