In today's ever-evolving digital landscape, the demand for intuitive and customizable content management tools is surging. For Joomla enthusiasts, SP Page Builder has emerged as the preeminent choice, allowing for seamless page-building experiences. For those who've been using SP Page Builder and have considered the idea of creating a bespoke addon - this guide is for you.

How to Create a Custom Addon for SP Page Builder

Delving Deeper into SP Page Builder Addons

Contrary to common misconceptions, you don’t need to be a seasoned developer or the mastermind behind SP Page Builder to design your own addon. If you're equipped with a basic understanding of programming, and can craft functions to achieve specific tasks, then you're just steps away from creating a tailor-made addon for SP Page Builder 5 Pro.

What's more, these addons can also serve as a lucrative source of income if you opt to market and sell them.

Embarking on the Addon Creation Journey

While we do provide the complete source code at the conclusion of this guide, to truly grasp the intricacies of the process, we'll walk you through each step to craft an addon from the ground up.

For the purpose of this tutorial, our hypothetical addon will be termed “Sample Addon”.

Step 1: Plugin Genesis

Before diving headfirst into the creation process, it's paramount to comprehend the foundational role of a plugin. Essentially, our custom addon will be installed via this plugin. Here's how to initiate:

  1. Folder Creation: Start by fabricating a new folder which will eventually hold the necessary files.
  2. File Integration: Populate this folder with the requisite files.
  3. Plugin Packaging: Convert this folder into a zip format. This zipped version is what will be recognized and installed as a plugin.

Contents of the Plugin Folder:

  • The pivotal PHP installer file.
  • A supportive XML file tailored for the plugin.
  • A dedicated folder earmarked for storing the addon(s).

To ensure seamless integration, it’s vital to adhere to the prescribed naming conventions. Case-sensitivity is paramount here. Taking cue from this, our folder would be christened plg_sppagebuilder_demo, where "demo" signifies the plugin name.

Step 2: Crafting Plugin-specific Files

PHP File Creation:

Kickstart this step by launching your preferred text or code editor. Then:

  1. Craft a new file. Name alignment is crucial here. For instance, if the plugin name is "Demo", your file should be christened demo.php.
  2. Infuse this file with the subsequent code snippet.
<?php
/**
* @package SP Page Builder
* @author JoomShaper http://www.joomshaper.com
* @copyright Copyright (c) 2010 - 2019 JoomShaper
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
*/

//no direct accees
defined('_JEXEC') or die('Restricted Aceess');

class PlgSppagebuilderDemo extends JPlugin {
    protected $autoloadLanguage = true;
}

It's pivotal to adapt the PlgSppagebuilderDemo class name in alignment with your specific preferences. "Demo" here corresponds to our plugin's name, which you can replace with your choice.

XML File Creation:

Following the same protocol:

  1. Forge a fresh XML file within your code editor. Taking cue from our previous example, this should be named demo.xml.
  2. Embed the subsequent code snippet into this XML file.
<?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 Nov 2019</creationDate>
    <authorEmail>support(at)joomshaper.com</authorEmail>
    <authorUrl>https://www.joomshaper.com</authorUrl>
    <copyright>Copyright (C) 2010 - 2019 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>

Ensure to tweak certain sections of this code:

  1. Modify the <name> tag to reflect your addon's name.
  2. Crucially, adjust the <filename> tag to correlate with your chosen plugin PHP file name.
  3. In the <folder> tag, input the folder name "addons" (this will become clearer in the upcoming step).

Pro Tip: Always use lowercase letters and substitute spaces with underscores for best compatibility.

Step 3: Addon Folder Creation

Having equipped ourselves with the essential PHP and XML files, we now venture into constructing our addon storage space. This folder, aptly named "addons", can house numerous addon units. If you’re envisioning a suite of addons, each should reside within its individual folder inside the “addons” main folder. To exemplify, as our addon of choice is “Sample Addon”, it would have its personal space named “sample_addon”.

Depicting the structured approach to curating your custom addon.

Figure: Depicting the structured approach to curating your custom addon.

Peeking inside our addon folder, we find:

  • The admin.php file: This is the heart of our addon, powering its functionalities.
  • The site.php file: This brings our addon to life visually.
  • An "assets" folder: A dedicated space to store all visual and functional elements essential for the addon's operation.

With the foundational steps in place, we are now poised to delve into crafting the core functionalities for our addon.

Step 4: Crafting Functionalities for Your Addon

With the foundation set, it's time to dive deeper and begin the process of coding the additional functionalities (features) that our addon requires. This step-by-step guide will meticulously take you through the creation of fields and functions that are at the core of your addon's utility.

Setting Up the Admin File

Begin by creating a new PHP file; let's label it admin.php. This file will serve as the hub for incorporating feature-specific coding that tailors your addon.

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

//no direct accees
defined('_JEXEC') or die('Restricted Aceess');

SpAddonsConfig::addonConfig(
    array(
        'type'=>'content',
        'addon_name'=>'sample_addon',
        'title'=> 'Sample Addon',
        'desc'=> 'Sample addon for SP Page Builder (Now you can edit or modify this)',
        'icon'=>JURI::root() . 'plugins/sppagebuilder/demo/addons/sample_addon/assets/images/icon.png',
        'category'=>'MyAddons',
        'attr'=>array(
            'general' => array(
                'admin_label'=>array(
                    'type'=>'text',
                    'title'=>JText::_('COM_SPPAGEBUILDER_ADDON_ADMIN_LABEL'),
                    'desc'=>JText::_('COM_SPPAGEBUILDER_ADDON_ADMIN_LABEL_DESC'),
                    'std'=> ''
                ),
                // Title
                'title'=>array(
                    'type'=>'textarea',
                    'title'=>JText::_('COM_SPPAGEBUILDER_ADDON_TITLE'),
                    'desc'=>JText::_('COM_SPPAGEBUILDER_ADDON_TITLE_DESC'),
                    'std'=>  'This is sample title'
                ),
                'addon_icon'=>array(
                    'type'=>'icon',
                    'title'=>'Icon',
                    'depends'=>array(array('title', '!=', '')),
                ),
                'addon_link'=>array(
                    'type'=>'media',
                    'format'=>'attachment',
                    'title'=>'Link',
                    'placeholder'=>'http://',
                    'std'=>'',
                    'hide_preview'=>true,
                ),
                'addon_font_family'=>array(
                    'type'=>'fonts',
                    'title'=>'Font Family',
                    'depends'=>array(array('title', '!=', '')),
                    'selector'=> array(
                        'type'=>'font',
                        'font'=>'{{ VALUE }}',
                        'css'=>'.sppb-addon-title { font-family: {{ VALUE }}; }'
                    )
                ),
                'addon_fontsize'=>array(
                    'type'=>'slider',
                    'title'=>'Font Size',
                    'std'=>'',
                    'max'=>400,
                    'responsive'=>true
                ),
                'addon_lineheight'=>array(
                    'type'=>'slider',
                    'title'=>'Line Height',
                    'std'=>'',
                    'max'=>400,
                    'responsive'=>true
                ),

                'addon_font_style'=>array(
                    'type'=>'fontstyle',
                    'title'=>'Font Style',
                    'depends'=>array(array('title', '!=', '')),
                ),
                'addon_margin'=>array(
                    'type'=>'margin',
                    'title'=>'Margin',
                    'std' => '0px 0px 30px 0px',
                    'responsive'=>true
                ),
                'addon_padding'=>array(
                    'type'=>'padding',
                    'title'=>'Padding',
                    'std' => '0px 0px 0px 0px',
                    'responsive'=>true
                ),

                // Content
                'content'=>array(
                    'type'=>'editor',
                    'title'=>JText::_('COM_SPPAGEBUILDER_GLOBAL_CONTENT'),
                    'std'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer adipiscing erat eget risus sollicitudin pellentesque et non erat. Maecenas nibh dolor, malesuada et bibendum a, sagittis accumsan ipsum. Pellentesque ultrices ultrices sapien, nec tincidunt nunc posuere ut. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam scelerisque tristique dolor vitae tincidunt. Aenean quis massa uada mi elementum elementum. Nec sapien convallis vulputate rhoncus vel dui.'
                ),

                'class'=>array(
                    'type'=>'text',
                    'title'=>JText::_('COM_SPPAGEBUILDER_ADDON_CLASS'),
                    'desc'=>JText::_('COM_SPPAGEBUILDER_ADDON_CLASS_DESC'),
                    'std'=>''
                ),

            ),
        ),
    )
);

Breaking down the components of this file:

  1. 'addon_name': This represents the unique identifier of your addon. Ensure it matches exactly with the name of the addon's folder.
  2. 'title': A friendly display name for your addon.
  3. 'desc': Provides a brief description, often showcased as a tooltip to users.
  4. 'icon': A URL pointing to the icon you've chosen for the addon.
  5. 'category': Enables categorization, particularly useful if you plan on creating a series of addons.
  6. The 'general' array is an essential section. This is where you'll script the fields, or more technically, the functions that drive your addon.

The output generated from the admin.php file can be visualized below:

Crafting Functionalities for Your Addon

Visualizing Your Addon's Presence

The essence of this step is to bring your addon to life visually. To achieve this, let's initialize another file, titled site.php, and embed the subsequent code snippet:

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

//no direct accees
defined('_JEXEC') or die('Restricted Aceess');

class SppagebuilderAddonSample_addon extends SppagebuilderAddons {

    public function render() {
        $class      = (isset($this->addon->settings->class) && $this->addon->settings->class) ? ' ' . $this->addon->settings->class : '';
        $title      = (isset($this->addon->settings->title) && $this->addon->settings->title) ? $this->addon->settings->title : '';
        $addon_link = (isset($this->addon->settings->addon_link) && $this->addon->settings->addon_link) ? $this->addon->settings->addon_link : '';
        $addon_icon = (isset($this->addon->settings->addon_icon) && $this->addon->settings->addon_icon) ? $this->addon->settings->addon_icon : '';
        $content    = (isset($this->addon->settings->content) && $this->addon->settings->content) ? $this->addon->settings->content : '';

        $output = '';
        $output .= '<div>';
            if($title) {
                $output .= '<h1>';
                    $output .= (!empty($addon_link)) ? '<a href="' . $addon_link . '">' : '';
                    $output .= (!empty($addon_icon)) ? '<i></i> ' : '';
                    $output .= (!empty($title)) ? $title : '';
                    $output .= (!empty($addon_link)) ? '</a>' : '';
                $output .= '</h1>';
            }

            if($content) {
                $output .= '<div>';
                    $output .= $content;
                $output .= '</div>';
            }
        $output .= '</div>';

        return $output;
    }

    public function css() {
        $addon_id = '#sppb-addon-' . $this->addon->id;

        $style = '';
        $style_sm = '';
        $style_xs = '';

        $style .= (isset($this->addon->settings->addon_margin) && $this->addon->settings->addon_margin) ?  SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_margin, 'margin') : '';
        $style_sm .= (isset($this->addon->settings->addon_margin_sm) && $this->addon->settings->addon_margin_sm) ?  SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_margin_sm, 'margin') : '';
        $style_xs .= (isset($this->addon->settings->addon_margin_xs) && $this->addon->settings->addon_margin_xs) ?  SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_margin_xs, 'margin') : '';

        $style .= (isset($this->addon->settings->addon_padding) && $this->addon->settings->addon_padding) ? SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_padding, 'padding') : '';
        $style_sm .= (isset($this->addon->settings->addon_padding_sm) && $this->addon->settings->addon_padding_sm) ? SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_padding_sm, 'padding') : '';
        $style_xs .= (isset($this->addon->settings->addon_padding_xs) && $this->addon->settings->addon_padding_xs) ? SppagebuilderHelperSite::getPaddingMargin($this->addon->settings->addon_padding_xs, 'padding') : '';
        
        $style .= (isset($this->addon->settings->addon_fontsize) && $this->addon->settings->addon_fontsize) ? 'font-size: ' . $this->addon->settings->addon_fontsize  . 'px; ' : '';
        $style_sm .= (isset($this->addon->settings->addon_fontsize_sm) && $this->addon->settings->addon_fontsize_sm) ? 'font-size: ' . $this->addon->settings->addon_fontsize_sm  . 'px; ' : '';
        $style_xs .= (isset($this->addon->settings->addon_fontsize_xs) && $this->addon->settings->addon_fontsize_xs) ? 'font-size: ' . $this->addon->settings->addon_fontsize_xs  . 'px; ' : '';
        
        $style .= (isset($this->addon->settings->addon_lineheight) && $this->addon->settings->addon_lineheight) ? 'line-height: ' . $this->addon->settings->addon_lineheight  . 'px; ' : '';
        $style_sm .= (isset($this->addon->settings->addon_lineheight_sm) && $this->addon->settings->addon_lineheight_sm) ? 'line-height: ' . $this->addon->settings->addon_lineheight_sm  . 'px; ' : '';
        $style_xs .= (isset($this->addon->settings->addon_lineheight_xs) && $this->addon->settings->addon_lineheight_xs) ? 'line-height: ' . $this->addon->settings->addon_lineheight_xs  . 'px; ' : '';

        // Font Style
        if(isset($addon->settings->addon_font_style->underline) && $addon->settings->addon_font_style->underline) {
            $style .= 'text-decoration: underline;';
        }

        if(isset($addon->settings->addon_font_style->italic) && $addon->settings->addon_font_style->italic) {
            $style .= 'font-style: italic;';
        }

        if(isset($addon->settings->addon_font_style->uppercase) && $addon->settings->addon_font_style->uppercase) {
            $style .= 'text-transform: uppercase;';
        }

        if(isset($addon->settings->addon_font_style->weight) && $addon->settings->addon_font_style->weight) {
            $style .= 'font-weight: ' . $addon->settings->addon_font_style->weight . ';';
        }

        $css = '';
        if ($style) {
            $css .= $addon_id . ' .sppb-addon-title {' . $style . '}';
        }

        if ($style_sm) {
            $css .= '@media (min-width: 768px) and (max-width: 991px) {';
                $css .= $addon_id . ' .sppb-addon-title {' . $style_sm . '}';
            $css .= '}';
        }

        if ($style_xs) {
            $css .= '@media (max-width: 767px) {';
                $css .= $addon_id . ' .sppb-addon-title {' . $style_xs . '}';
            $css .= '}';
        }

        return $css;
    }

    public static function getTemplate() {
        $output = '
        <#
            var margin = window.getMarginPadding(data.addon_margin, "margin");
            var padding = window.getMarginPadding(data.addon_padding, "padding");
        #>
        <style type="text/css">
            #sppb-addon-{{ data.id }} .sppb-addon-title{
                <# if(_.isObject(data.addon_fontsize)){ #>
                    font-size: {{ data.addon_fontsize.md }}px;
                <# } #>

                <# if(_.isObject(data.addon_lineheight)){ #>
                    line-height: {{ data.addon_lineheight.md }}px;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.underline) { #>
                    text-decoration: underline;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.italic) { #>
                    font-style: italic;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.uppercase) { #>
                    text-transform: uppercase;
                <# } #>

                <# if(_.isObject(data.addon_font_style) && data.addon_font_style.weight) { #>
                    font-weight: {{ data.addon_font_style.weight }};
                <# } #>
                
                <# if(_.isObject(margin)){ #>
                    {{{ padding.md }}}
                    {{{ margin.md }}}
                <# } #>
            }

            @media (min-width: 768px) and (max-width: 991px) {
                #sppb-addon-{{ data.id }} .sppb-addon-title{
                    <# if(_.isObject(margin)){ #>
                        {{{ padding.sm }}}
                        {{{ margin.sm }}}
                    <# } #>
                }
            }
            @media (max-width: 767px) {
                #sppb-addon-{{ data.id }} .sppb-addon-title{
                    <# if(_.isObject(margin)){ #>
                        {{{ padding.xs }}}
                        {{{ margin.xs }}}
                    <# } #>
                }
            }
        </style>
        <div>
            <h1>
                <# if(!_.isEmpty(data.addon_link)){ #>
                    <a href="/{{ data.addon_link }}">
                <# } #>
                <# if(!_.isEmpty(data.addon_icon)){ #>
                    <i></i>
                <# } #>
                {{{ data.title }}}
                <# if(!_.isEmpty(data.addon_link)){ #>
                    </a>
                <# } #>
            </h1>
            <# if(!_.isEmpty(data.content)){ #>
                <div id="addon-sample-{{data.id}}" data-id={{data.id}} data-fieldName="content">{{{ data.content }}}</div>
            <# } #>
        </div>
        ';

        return $output;
    }
}

Crucial pointers to remember:

  • Modify the class name from “SppagebuilderAddonSample_addon” to a more personalized name, for instance, “SampleBuilderAddonYour_addon”.
  • Adhere to a naming convention when labeling divs, such as “sppb-addon-sample-addon” to maintain consistency and clarity.

The rendered output, originated from the site.php file, can be observed here:

Visualizing Your Addon's Presence

Delving into the site.php file's coding intricacies:

  1. The render() function: This is the showstopper. It displays the finalized version of your addon.
  2. The css() function: This underpins the styling and aesthetic presentation of your addon.
  3. The getTemplate() function: Integral for those wishing to offer front-end editing capabilities. If live editing isn't on your radar, you can effortlessly swap the getTemplate() function with the subsequent code:
public static function getTemplate() {
        return false;
    }

Organizing Your Assets

Now, let's address the assets directory, a pivotal element especially if you're incorporating visuals like icons. Here's what to do:

  • Construct a dedicated folder named "images" within the assets directory.
  • Deposit your chosen icon here. Adhering to standards, ensure your icon's dimensions are 76x76 pixels and it's named icon.png.
  • If you ever feel the need for an icon refresh, simply replace the existing image.

For quick navigation, the directory structure is as follows: sample_addon > assets > images > icon.

By following this enriched guide, you're not just writing code; you're crafting a comprehensive and intuitive experience for your addon users. Whether you're a seasoned developer or a beginner, understanding and implementing these steps will be instrumental in your web development journey.

Step 5: Packaging Your Addon for Deployment

Once you've meticulously navigated through the earlier stages of creating your addon, the next logical step is to package it into a distributable format. This will allow for a smooth installation on your website or any other Joomla - powered platform.

Assembling Your Addon into a ZIP Archive

With the conclusion of your coding journey, your immediate task is to consolidate all your hard work into a single, compressed file. This facilitates not only the distribution but also the installation of your addon.

Here's how you can accomplish this:

  • Directly compress the plg_sppagebuilder_demo directory. Most operating systems and file management tools offer right-click options to "Compress" or "Archive" folders.
  • Ensure that the output of this compression is a .zip file format. This format is universally recognized and simplifies the installation process for end-users.

The visual representation of the compressed addon file can be observed below:

Packaging Your Addon for Deployment

Deploying and Activating Your Addon on Joomla

With your compressed addon in hand, it's time to breathe life into it by integrating it with your Joomla website.

  • Navigate to the Joomla administrative dashboard.
  • Choose Extensions from the top menu, followed by Manage, then Install.
  • Click on Upload Package File and select your .zip addon file for upload.

The snapshot of the upload interface within Joomla is available here:

Deploying and Activating Your Addon on Joomla

Post-upload, it's crucial to ensure your addon is active and functioning as intended:

  • On the Joomla dashboard, select Extensions, then Plugins.
  • Locate your recently installed plugin in the list.
  • Click on it to activate or "publish" it, ensuring it's operational for your site visitors.

Should you venture into developing an array of addons, remember this: the process remains constant. This uniformity offers developers a streamlined and intuitive experience, regardless of the number or complexity of the addons they craft.

Leveraging Pre-existing Source Code

Recognizing that custom addon development may feel daunting for some, there's a shortcut available. Rather than starting from scratch, you can download the source code provided:

[Link to Source Code]

Once downloaded, all that's needed is to make modifications as per the guidelines mentioned in the preceding sections. This accelerates the development cycle, ensuring rapid deployment for urgent requirements.

At any stage, should you find yourself tangled in the intricacies of addon development or seek clarifications on any step, don't hesitate. Our community thrives on collaboration and knowledge sharing. Drop your queries in the comments section below, and either our team or fellow developers will promptly assist you in your endeavors. Remember, in the world of web development, you're never alone!


Share with your friends!

 
4.4085365853659 1 1 1 1 1 (164 Votes)
Published: 24-11-2019

You are not logged in to post comments.