Did you know that the vast universe of SP Page Builder offers an option to create your very own custom addon? While the platform boasts an impressive library of premade addons that are tailored for functionality and user experience, harnessing the ability to shape your custom addon opens a door to boundless possibilities for your Joomla website.

Creating Your Own Custom Addon in SP Page Builder

If the notion of manifesting your own addon sounds intimidating, especially if coding and development aren't your forte, fear not! You’re about to discover that with just a foundational understanding of coding, you can bring your addon vision to life.

Setting the Stage: What You Need to Know First

Before diving deep, there are some best practices to consider:

  • For the sake of safety and flexibility, always begin by setting up a local web development environment. This sandbox approach ensures you can experiment and iterate without any fear of inadvertently disrupting your live site.
  • If SP Page Builder is new terrain for you, consider going through our exhaustive guide on downloading and installing SP Page Builder Pro. Now, with the initial advisory note out of the way, it’s time to embark on this enriching tutorial journey.

Step 1: Crafting a Custom Plugin

Hold on a second! We’re talking about creating a custom plugin first, even though our primary aim is to design a custom addon. Why? Simply because a plugin serves as a vessel, allowing you to house one or even multiple addons. Strategically, establishing a plugin for your custom addons ensures they remain independent of the SP Page Builder core component. Hence, even if you decide to update SP Page Builder later on, your bespoke addons remain intact and unaffected.

To initiate the process, create a directory named plg_sppagebuilder_demo. Here, the suffix 'demo' represents the plugin name. Feel free to modify 'demo' to any name that aligns with your project.

Within the plg_sppagebuilder_demo directory, you should establish the following:

  • A PHP file dubbed: demo.php
  • An XML file named: demo.xml
  • A dedicated directory named: addons

Step 2: Breathing Life into the demo.php File within the Custom Plugin

Starting with the PHP file, choose a text/code editor of your liking. Though the market offers a plethora of options, for this tutorial, our pick is Sublime Text. Known for its lightweight nature and the added advantage of a free version, it's a trusted companion for many developers.

Upon navigating to the recently created folder via the editor, curate a file termed demo.php. Note that the name 'Demo' is emblematic of our plugin, hence the file is aptly named demo.php. However, if you're veering towards a unique name, adjust the filename to yourPluginName.php.

Now, it’s time to infuse life into this file with the following code:

<?php
/**
* @package SP Page Builder
* @author JoomShaper http://www.joomshaper.com
* @copyright Copyright (c) 2010 - 2022 JoomShaper
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
*/

//no direct accees
defined('_JEXEC') or die('Restricted Access);
use Joomla\CMS\Plugin\CMSPlugin;
class PlgSppagebuilderDemo extends CMSPlugin {
    protected $autoloadLanguage = true;
}

A pro-tip: Ensure that the 'Demo' within the Class name PlgSppagebuilderDemo mirrors the name of your plugin for consistency and clarity.

Step 3: Crafting the demo.xml File in the Custom Plugin

The next step is dedicated to the XML file of our plugin. Establish a new file, christen it demo.xml, and then embed the following code snippet:

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.8" type="plugin" group="sppagebuilder" method="upgrade">
    <name>Demo Addon Plugin - SP Page Builder</name>
    <author>JoomShaper</author>
    <creationDate>22 Sep 2022</creationDate>
    <authorEmail>support[@]joomshaper.com</authorEmail>
    <authorUrl>https://www.joomshaper.com</authorUrl>
    <copyright>Copyright (C) 2010 - 2022 JoomShaper. All rights reserved.</copyright>
    <license>GNU/GPL V2 or Later</license>
    <description>Demo addon plugin for SP Page Builder</description>
    <version>1.0</version>

    <files>
        <filename plugin="demo">demo.php</filename>
        <folder>addons</folder>
    </files>

</extension>

A couple of lines demand your attention:

  1. In the <name> tag, input the name symbolic of your plugin.
  2. Within the <description> tag, switch “demo” with the chosen name for your plugin.
  3. For the <filename> tag, adapt the filename demo.php to the PHP file dedicated to your plugin.
  4. Lastly, for the <folder> tag, solidify the folder name as "addons". The next steps will delve deeper into this.

Step 4: Establishing the "addons" Directory

Delving deeper into the process, the next agenda is to set up a directory within our custom plugin. This directory is vital as it will act as the home for all our tailored addons. Name this directory 'addons'.

Delving even further, within the 'addons' directory, create a sub-directory and name it rich_text. For the purpose of this tutorial, 'Rich Text' has been chosen as the archetype for our custom addon.

The subsequent steps involve populating the rich_text directory:

  • Introduce a PHP file and name it admin.php
  • Add another PHP file termed site.php
  • Lastly, fashion a directory labeled 'assets'. This will serve as the storage space for all the essential assets linked to the addon.

For a holistic visualization, here's a glimpse of the meticulously crafted file structure:

File Structure Visualization

A noteworthy mention: The flexibility of this structure permits the inclusion of multiple addons within a single plugin. So, if you harbor aspirations of launching another custom addon in the future, the process is streamlined. Simply forge a directory within the 'addons' folder and christen it with the name of your new addon.

Step 5: Crafting the Custom Addon - Rich Text Capabilities

Let's dive deeper into how we can leverage coding to power our custom Rich Text addon. Before you delve into the actual code, it’s essential to clarify the purpose of your Rich Text addon.

The primary function of the Rich Text web element is to allow users to produce long, coherent content seamlessly. Rather than inserting components like Heading, Paragraph, Button, and Image one by one, Rich Text offers a more integrated approach, letting you incorporate these elements all at once.

For this demonstration, our focus will be on constructing a simple yet effective Rich Text. It will be composed of a title, a descriptive paragraph, and an action button, as illustrated:

Rich Text Layout

Create the Addon Icon

Begin by adding a dedicated icon for your addon. Within the assets folder, carve out a new directory and label it 'images'. Then, place your chosen icon.png file inside this directory. For this guide, we've kept the dimensions of the icon at 76x76 px. If you wish to tweak the icon design later, simply substitute the existing image with your preferred one.

Formulate the admin.php File

Next, inside the rich_text directory, set up a new PHP file titled admin.php and embed the subsequent code snippet.

<?php
/**
 * @package SP Page Builder
 * @author JoomShaper http://www.joomshaper.com
 * @copyright Copyright (c) 2010 - 2022 JoomShaper
 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
 */

// No direct access
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Language\Text;

/**
 * Inline editor settings rules:
 * 1. The inline array must have an attribute named `buttons`
 * 2. The buttons array contains all the editor buttons. The key of the array must be unique.
 * 3. Every button contains some attributes like-
 *         a. action (string) (required) [The action will perform after clicking the button]
 *         b. type (string) (required) [The type of the button. valid values are `placeholder`, `icon-text`]
 *         c. placeholder (string) (optional) [If the button is dynamic and this cannot be expressed as icon/text.]
 *         d. icon (string) (optional) [A valid icon name available in the pagebuilder]
 *         e. text (string) (optional) [A text value to show as the button text]
 *         f. icon_position (string) (optional) [`left` or `right` position of the icon to the text. Default `left`]
 *         g. tooltip (string) (optional) [Tooltip text to show on the button hover.]
 *         h. fieldset (array) (conditional) [An conditional array (which is required if action is dropdown) for representing the fieldset fields.
 *             This is valid only if the action is `dropdown`.
 *             The direct children of the fieldset array would be the tabs.
 *             Inside the tabs name you should define the fields descriptions.
 *             If there is only one fieldset child then that means no tabs]
 *         i. options (array) (conditional) [This is a conditional field. This is required if the action is dropdown
 *             but you need to show some options not fields.]
 *         j. default (mixed) (conditional) [This is required if there is the options key. This indicates the default value of the button from the options array.]
 */

SpAddonsConfig::addonConfig(
    [
        'type' => 'content',
        'addon_name' => 'rich_text',
        'title' => 'Rich Text',
        'desc' => 'Rich Text Custom addon',
        'category' => 'Custom',
        'icon' => '',
        'inline' => [
            'buttons' => [
                'rich_text_general_settings' => [
                    'action' => 'dropdown',
                    'icon' => 'addon::rich_text',
                    'tooltip' => 'Rich Text',
                    'fieldset' => [
                        'tab_groups' => [
                            'title' => [
                                'fields' => [
                                    [
                                        'title' => [
                                            'type' => 'text',
                                            'title' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE_DESC'),
                                            'std' => 'This is a advanced heading',
                                        ],
                                        'heading_selector' => [
                                            'type' => 'headings',
                                            'title' => Text::_('COM_SPPAGEBUILDER_ADDON_HEADINGS'),
                                            'std' => 'h3',
                                        ],
                                    ],
                                ],
                            ],
                            'content' => [
                                'fields' => [
                                    [
                                        'content' => [
                                            'type' => 'editor',
                                            'title' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_ADDON_TITLE_DESC'),
                                            'std' => "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.",
                                        ],
                                    ],
                                ],
                            ],
                            'button' => [
                                'fields' => [
                                    [
                                        'button' => [
                                            'type' => 'text',
                                            'title' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_TEXT'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_TEXT_DESC'),
                                            'std' => 'Button',
                                        ],
                                        'type' => [
                                            'type' => 'select',
                                            'title' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_STYLE'),
                                            'desc' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_STYLE_DESC'),
                                            'values' => [
                                                'default' => Text::_('COM_SPPAGEBUILDER_GLOBAL_DEFAULT'),
                                                'primary' => Text::_('COM_SPPAGEBUILDER_GLOBAL_PRIMARY'),
                                                'secondary' => Text::_('COM_SPPAGEBUILDER_GLOBAL_SECONDARY'),
                                                'success' => Text::_('COM_SPPAGEBUILDER_GLOBAL_SUCCESS'),
                                                'info' => Text::_('COM_SPPAGEBUILDER_GLOBAL_INFO'),
                                                'warning' => Text::_('COM_SPPAGEBUILDER_GLOBAL_WARNING'),
                                                'danger' => Text::_('COM_SPPAGEBUILDER_GLOBAL_DANGER'),
                                                'dark' => Text::_('COM_SPPAGEBUILDER_GLOBAL_DARK'),
                                                'link' => Text::_('COM_SPPAGEBUILDER_GLOBAL_LINK'),
                                            ],
                                            'std' => 'default',
                                        ],
                                        'url' => [
                                            'type' => 'link',
                                            'title' => Text::_('COM_SPPAGEBUILDER_GLOBAL_BUTTON_URL'),
                                            'mediaType' => 'attachment',
                                        ],
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
                'rich_text_alignment_separator' => [
                    'action' => 'separator',
                ],

                'rich_text_alignment_options' => [
                    'action' => 'dropdown',
                    'type' => 'placeholder',
                    'style' => 'inline',
                    'showCaret' => true,
                    'tooltip' => Text::_('COM_SPPAGEBUILDER_GLOBAL_ALIGNMENT'),
                    'placeholder' => [
                        'type' => 'list',
                        'options' => [
                            'left' => ['icon' => 'textAlignLeft'],
                            'center' => ['icon' => 'textAlignCenter'],
                            'right' => ['icon' => 'textAlignRight'],
                        ],
                        'display_field' => 'alignment',
                    ],
                    'default' => [
                        'xl' => 'center',
                    ],
                    'fieldset' => [
                        'basic' => [
                            'alignment' => [
                                'type' => 'alignment',
                                'inline' => true,
                                'responsive' => true,
                                'available_options' => ['left', 'center', 'right'],
                                'std' => [
                                    'xl' => 'center',
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],

        'attr' => [],
    ],
);

To shed light on the code, each SP Page Builder Addon boasts a tailored inline editor fine-tuned to its individual features. This particular chunk of code is essential as it lays out the fields our custom addon's inline editor will possess.

It starts with key details about the addon, such as its type, name, visible title, brief description, and more. For instance:

  • type points out the nature of the addon.
  • addon_name resonates with the folder's name where the addon is housed.
  • title signifies the name that'll be visible to users.
  • desc provides a hint about the addon when hovered over.
  • category groups our addon under the 'Custom' category for better organization.
  • icon is deliberately left blank, as it will automatically source the icon image stored in our assets.

To elaborate further, beneath the 'inline' pointer, we chalk out the fields for our addon’s inline editor. These fields, like Title, Content, and Button, are neatly organized under the rich_text_general_settings tab. Subsequently, the alignment options for the addon are defined.

Inline Editor Layout

Composing the site.php File

Having set up our fields, it's time to pen down the code that will render our addon visually appealing. Create a file termed site.php within the rich_text directory and incorporate the succeeding code snippet:

<?php
/**
 * @package SP Page Builder
 * @author JoomShaper http://www.joomshaper.com
 * @copyright Copyright (c) 2010 - 2022 JoomShaper
 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
 */
//no direct access
defined('_JEXEC') or die('Restricted access');

class SppagebuilderAddonRich_text extends SppagebuilderAddons
{
 /**
 * The addon frontend render method.
 * The returned HTML string will render to the frontend page.
 *
 * @return string The HTML string.
 * @since 1.0.0
 */
 public function render()
 {
 $settings = $this->addon->settings;
 $class = (isset($settings->class) && $settings->class) ? ' ' . $settings->class : '';
 $title = (isset($settings->title) && $settings->title) ? $settings->title : '';
 $heading_selector = (isset($settings->heading_selector) && $settings->heading_selector) ? $settings->heading_selector : 'h2';
 $content = (isset($settings->content) && $settings->content) ? $settings->content : '';
 $button = (isset($settings->button) && $settings->button) ? $settings->button : '';
 $button_type = (isset($settings->type) && $settings->type) ? $settings->type : '';

 $output = '';

 // Link Parse
 list($link, $target) = AddonHelper::parseLink($settings, 'url');

 $output .= '<div>';

 // Title
 $output .= '<' . $heading_selector . '>';
 $output .= nl2br($title);
 $output .= '</' . $heading_selector . '>';

 // Content
 $output .= '<p>' . $content . '</p>';

 // Button
 $output .= !empty($link) ? '<a ' . $target . ' href="' . $link . '">' : '';
 $output .= '<button>' . $button . '</button>';
 $output .= !empty($link) ? '</a>' : '';

 $output .= '</div>';

 return $output;
 }

 /**
 * Generate the CSS string for the frontend page.
 *
 * @return string The CSS string for the page.
 * @since 1.0.0
 */
 public function css()
 {
 $addon_id = '#sppb-addon-' . $this->addon->id;
 $cssHelper = new CSSHelper($addon_id);

 $css = '';

 $settings = $this->addon->settings;
 $settings->alignment = CSSHelper::parseAlignment($settings, 'alignment');
 $alignment = $cssHelper->generateStyle('.sppb-addon.sppb-addon-rich_text', $settings, ['alignment' => 'text-align'], false);

 $css .= $alignment;

 return $css;
 }

 /**
 * Generate the lodash template string for the frontend editor.
 *
 * @return string The lodash template string.
 * @since 1.0.0
 */
 public static function getTemplate()
 {
 $lodash = new Lodash('#sppb-addon-{{ data.id }}');

 // Inline Styles
 $output = '<style type="text/css">';
 $output .= $lodash->alignment('text-align', '.sppb-addon-rich_text', 'data.alignment');
 $output .= '</style>';

 $output .= '
 <#
 let btnUrl = "";
 let target = "";
 let rel = "";
 if (!_.isEmpty(data.url) && _.isObject(data.url)){
 const {url, page, menu, type, new_tab, nofollow} = data?.url;
 if(type === "url") btnUrl = url;
 if(type === "menu") btnUrl = menu;
 if(type === "page") btnUrl = page ? `index.php?option=com_sppagebuilder&view=page&id=${page}` : "";
 
 target = new_tab ? "_blank": "";
 rel = nofollow ? "noopener noreferrer": "";
 }
 
 #>
 ';

 $output .= '<div>';

 // Title
 $output .= '<{{ data.heading_selector }}>';
 $output .= '<span data-id={{data.id}} data-fieldName="title" contenteditable="true">{{{ data.title }}}</span>';
 $output .= '</{{ data.heading_selector }}>';

 // Content
 $output .= '<p>';
 $output .= '<span data-id={{data.id}} data-fieldName="content" contenteditable="true">{{{ data.content }}}</span>';
 $output .= '</p>';

 // Button
 $output .= '<a href=\'{{ btnUrl }}\' target=\'{{ target }}\' rel=\'{{ rel }}\'>';
 $output .= '<button id="btn-{{ data.id }}">';
 $output .= '<span data-id={{data.id}} data-fieldName="button" contenteditable="true" data-placeholder="Add text...">{{{ data.button }}}</span>';
 $output .= '</button>';
 $output .= '</a>';

 $output .= '</div>';

 return $output;
 }
}

This portion of the code is pivotal. It declares a class, which is essentially an extension of the abstract class SppagebuilderAddons. This class, in turn, contains functions like:

  • render(): Showcases the final visual output.
  • css(): Determines the visual styling.
  • getTemplate(): Grants front-end editing capabilities.

Step 6: Bundling Everything into an Installable Archive

You're nearing the finish line! Safeguard all your diligent coding efforts by zipping the entire project directory named plg_sppagebuilder_demo. To achieve this, right-click on the directory and select 'compress', and voila, your zip file is ready!

Step 7: Plugin Integration and Activation

The meticulously crafted plugin can now be integrated into your website in a manner similar to any standard Joomla plugin. Follow these steps:

  1. Navigate to Joomla Backend > System > Install > Extension > Upload Package File.
  2. Upon successful installation, activate (or publish) the plugin via Joomla Backend > System > Manage > Extensions. Locate your plugin using the search function, and activate it.

Final Results

Congratulations on this significant achievement! You've handcrafted a custom addon tailored to your needs. To utilize the addon, switch to the SP Page Builder's editing mode. Here, within the 'Custom' category, your creation awaits.

Conclusion

We trust that this comprehensive guide has empowered you to craft a bespoke Addon for SP Page Builder effortlessly. While the journey might seem intricate initially, remember that practice fosters perfection. Familiarize yourself with the code, experiment, and soon you'll be adept at molding any custom addon to align with your vision. To expedite your future endeavors, you can download the source code of this custom addon.

If you're grappling with doubts or seeking further guidance, don't hesitate to share your thoughts in the comments section. Wishing you success in your web development voyage!


Share with your friends!

 
4.5275590551181 1 1 1 1 1 (127 Votes)
Published: 22-04-2023

You are not logged in to post comments.