How to make WordPress Themes or Plugins Translation Ready

Translation Ready Themes Featured Image

It’s no secret that WordPress is used around the world. So it’s a good idea to ensure that themes and plugins can be easily translated into other languages. Adding internationalization and localization support by having a translation ready WordPress theme can greatly increase its market share.

Difference Between Internationalization and Localization

Internationalization is the process of developing a plugin/theme so it can easily be translated into other languages.

Localization describes the subsequent process of translating an internationalized plugin into a new language.

Side Note: It’s worth noting that internationalization is often abbreviated as i18n (because there are 18 letters between the ‘i’ and the ‘n’), and localization is shortened to l10n (because there are 10 letters between the ‘l’ and the ‘n’.)

The localization process can be done using a software called Poedit with three types of language files: the POT file (that contains a list of all translatable messages in the WordPress theme), the .PO file (created when you translate a POT file to a particular language) and the .MO file (a binary file that is created automatically by Poedit and is not human-readable).

Translation Ready Themes

There is some confusion about what a translation-ready theme actually means. So let’s clear up any possible confusion and explain what this entails:

  • Translation ready themes that only come with a .pot file

You can find translation ready themes that only come with a .pot file (and sometimes with an English version of .mo and .po files). These files can be used to translate the theme into other languages. These themes don’t provide translations to other languages, but you have the tools needed to localize the WordPress theme like the Poedit software or the Loco Translate plugin.

For example, in the Jupiter X theme, we provide the jupiterx.pot file and a user can translate the theme to their language.

  • Translation ready themes with translations into other languages

You can find translation ready themes that come with .pot file that also come with translations into other languages. These translations usually have been done by translators, volunteers or any other users.

For example, in the Jupiter 6 theme we provide .po and .mo files for some languages, meaning a customer doesn’t have to translate the theme themselves.

Translation Ready Themes Jupiter 6 Files

Steps to Create a Translation Ready Theme

  1. Create and load the text domain for your WordPress theme.
  2. Enclose the Translatable Text String with the WordPress gettext function.
  3. Create the POT file.

Create and Load the Text Domain

The Text Domain will be a part of the WordPress theme or plugin specification. The following code snippets show the theme and plugin specification with the text domain.

Note: The theme specification will be in the theme’s style.css

/*
 Theme Name: YOUR THEMENAME
 Theme URI: yourdomain/themes/yourthemename/
 …
 …
 Text Domain: yourthemename
 */
/*
 Plugin Name: Plugin Name
 Plugin URI: yourdomain
 …
 …
 Text Domain: yourthemename
 */

Load your theme’s text domain by using the load_theme_textdomain() function. This function has two parameters as the text domain name and the directory path where we will store the .pot, .po, .mo language files. Paste the code seen below in your theme’s functions.php to load the text domain.

load_theme_textdomain( ‘yourthemename’, language_file_path );

Enclose the Translatable Text String with the WordPress gettext Function

WordPress uses the gettext framework function to translate the text string into the specified target language. It has a set of functions in a core translation API file l10n.php located in the wp-includes directory. We have to enclose the text string with the appropriate function. The code below shows how to use the gettext function to localize your theme.

__()
This is one of the most basic translation functions. Like many of its siblings, it takes two parameters: the string to be translated and the text domain.

$name = __( ‘My Stats’, ‘textdomain’ );

It’s used when you want to mark a simple string for translation and return the value to use somewhere else. This is frequently the case within functions – think of registering post types.

_e()

This is almost the same as the function above, except it echoes the value. It can be used when you’re translating in the HTML content directory:

_n()

This function is used when translating strings with a conditional plural in them. This means that you don’t know in advance if the string will use the plural or singular form because it depends on the momentary value of some parameter. A good example would be a comment count.

For example, if a comment count is one, you would need to use a singular form: “One comment.” If a comment count is 0 or more than one, you would use the plural: “Many comments”. This can be done in one go by using the _n() function.

This takes four parameters: the singular form, the plural form, the number to check and the text domain:

$comment_count = get_comments_number();
$comment_count_text = _n( ‘One Comment’, ‘Many Comments’, $comment_count, ‘textdomain’ );

You can read more about the gettext function in the following articles:

https://codex.wordpress.org/Plugin_API/Filter_Reference/gettext
https://codex.wordpress.org/I18n_for_WordPress_Developers

Creating the POT file with the Translatable Text String

After applying appropriate gettext functions for all the translatable text strings of your theme files, create a .POT template file. This template will be the base consisting of all the translatable strings. This file will be referred to create language mapping file .po, .mo pair for each language translation. You can use any popular tool to create this file for getting the theme’s translatable strings.

Read more about making translation ready plugins in the WordPress Codex page.

Wrapping up:

One of the goals of WordPress is to make it easy for users across the world to publish content.
In this article, we took a look at the basics of translations, what a text domain is, the functions we can use and how to create translation files.

We hope this was helpful to you. Please share your experiences in the comments below!😉

Extend Elementor like a Pro: Creating a Custom Control

Creating a Custom Control Featured Image

Every Elementor’s widget is composed of different input types called a control. A control is used to construct the interface of a widget. Using controls allows us to customize and set our favorite settings for a widget and see a live preview of it.

Before diving headfirst into this article, we suggest that you check out the following articles.

Elementor control

In default, Elementor has several control types like Text, Color, Dimension, Select, Icon, Media, Typography and so on that meet most common usages. But sometimes we need to create a custom control to realize our needs.

Directory Structure of a Control

Normally, each control contains three files as PHP, JavaScript, and CSS:

  • control.php
  • js/control.js
  • css/control.css

PHP File

The PHP file generates HTML and constructs UI of control in Panel. To create the PHP file, we need to extend the Base_Control abstract class.

The Base_Control provides several methods.

  • get_type: retrieve the type of control.
  • content_template: render the HTML output in Panel.
  • enqueue: use to add CSS and JavaScript files to control.
  • get_default_settings: retrieve the default setting of control on initialisation.
  • get_default_value: retrieve the default value of control.
  • get_value: determine how the control returns its value.
  • get_style_value: interact with the CSS rule that passed with Selector argument.

Elementor allows for five base classes to extend Base_Control for different purposes. We can extend the following classes to create new controls. For more info, you can refer to this page about Elementor controls.

  • Base_UI_Control: creates a UI control that is visible in the panel and doesn’t return any value. For example, Heading control.
  • Base_Data_Control: a base class that returns a single value. For example, Number Control.
  • Control_Base_Multiple: a base class that returns multiple values. For example, Media control.
  • Control_Base_Units: a base class that returns unit based values. For example, Dimension control.
  • Group_Control_Base: a base class for creating group control. For example, Typography control.

JavaScript File

The JavaScript file is used for interacting between UI and live preview and manipulate events that are related to control.

The Elementor uses the Backbone.js library for JS manipulation. For more information about Backbone.js, you can check out backbonejs.org and https://www.javatpoint.com/backbonejs-tutorial

Also in Elementor, there is an exclusive JS file for each PHP file that interacts with them. For instance, the above base PHP classes have JS files such as:

  • base.js
  • base-data.js
  • base-multiple.js
  • base-units.js

To create a new control JS file, we need to extend one of the above JS files. You can find the source of the JS file at GitHub.

Note: For some reason, Elementor merges all JS files in the editor.js file. We can extend the above JS file from by using the elementor.modules.controls object.

CSS File

CSS allows us to style the UI of a control. In the following sections, we’ll go into detail about the actual usage of CSS.

Creating a Custom Control

Now that we have gained a basic understanding of an Elementor control, we are ready to create a custom control called MultiUnit, which is similar to Elementor’s Dimension control.

In the Dimension control, we can only set the same unit (px, em,…) for the top, right, bottom and left values, but in MultiUnit control, we can set a different unit for each value.

At the end of this article, we’re going to create the following control.

Default Values Return Values (Array)
[
‘top’ => ”,
‘right’ => ”,
‘bottom’ => ”,
‘left’ => ”,
‘top_unit’=>’px’,
‘right_unit’ =>’px’,
‘left_unit’ =>’px’,
‘bottom_unit’ =>’px’,
‘isLinked’ => true,
];
[
‘top’ => ”, //int
‘right’ => ”, //int
‘bottom’ => ”, //int
‘left’ => ”, //int
‘top_unit’=>”, //string
‘right_unit’ =>” //string
‘left_unit’ =>”, //string
‘bottom_unit’ =>”, //string
‘isLinked’ => ”, //bool
];

Directory Structure of a Custom Control

  • index.php
  • multi-unit.php
  • css/MultiUnit.css
  • js/MultiUnit.js

You can download the full source code from Github.

Creating the PHP File

To create a custom control, we need to have a unique type. For our control, we’ll choose spicy-multi-unit-control.

Our control extends Control_Base_Multiple and overrides essential functions, as well as creates custom functions to meet our needs.

In this section, we’ll go into detail of each function one-by-one:

1. The below function sets the control type.

public function get_type() {
     return 'spicy-multi-unit-control';
 }

2. This function returns the default values of the control.

public function get_default_value() {
     return [
         'top' => '',
         'right' => '',
         'bottom' => '',
         'left' => '',
         'top_unit'=>'px',
         'right_unit' =>'px',
         'left_unit' =>'px',
         'bottom_unit' =>'px',
         'isLinked' => true,
     ];
 }

3. The below function returns the default settings of the control.

protected function get_default_settings() {
   return [
       'size_units' => [ 'px' ],
       'label_block' => true,
       'range' => [
           'px' => [
               'min' => '',
               'max' => 100,
               'step' => 1,
           ],
           'em' => [
               'min' => 0.1,
               'max' => 10,
               'step' => 0.1,
               ],
           'rem' => [
               'min' => 0.1,
               'max' => 10,
               'step' => 0.1,
           ],
           '%' => [
               'min' => 0,
               'max' => 100,
               'step' => 1,
           ],
           'deg' => [
               'min' => 0,
               'max' => 360,
               'step' => 1,
               ],
           'vh' => [
               'min' => 0,
               'max' => 100,
               'step' => 1,
           ],
           'vw' => [
               'min' => 0,
               'max' => 100,
               'step' => 1,
           ],
       ],
   ];
}

4. This function is used for adding JavaScript and CSS files to the control:

public function enqueue() {
     wp_enqueue_script( 'spicy_multi_unit',plugins_url( '/js/MultiUnit.js', FILE ) );
     wp_enqueue_style( 'spicy_multi_unit' , plugins_url( '/css/MultiUnit.css', FILE ) );
 }

5. The below function renders a button that is used to sync all units together.

Creating a Custom Control 5
private function print_link_unit_template(){
    ?>
    <# if ( data.size_units && data.size_units.length > 1 ) { #>
                                                    Sync Unit                                    <# _.each( data.size_units, function( unit ) { #>                {{{unit}}}            <#});#>                    
     <#}#>
    <?php
 }

6. We’ll use the below function to create a unit for each input:

Creating a Custom Control 6
private function print_units_template($arg){
    ?>
    <# if ( data.size_units && data.size_units.length > 1 ) { #>
                    <# .each( data.size_units, function( unit ) {            if(unit=='px' && data.range.px.step < 1){                data.range.px.step=1;            }            #>                        {{{ unit }}}            <# } ); #>        
    <# } #>
    <?php
 } 

7. Finally, the essential function for creating the UI:

public function content_template() {        
    $dimensions = [
        'top' => __( 'Top', 'Spicy-extension' ),
        'right' => __( 'Right', 'Spicy-extension' ),
        'bottom' => __( 'Bottom', 'Spicy-extension' ),
        'left' => __( 'Left', 'Spicy-extension' ),
    ];
 ?>
   <div class="elementor-control-field">
    <label class="elementor-control-title">{{{ data.label }}}</label>
    <div class="spicy-control-input-wrapper">
     <div class="units-wrapper">
       <div>   
        <ul>
          <?php
            foreach ( $dimensions as $dimension_key => $dimension_title ) :
               echo '<li>';
          ?>
          <# if ( -1 !== _.indexOf( allowed_dimensions, '<?php echo $dimension_key; ?>' ) ) { #>
             <?php                      $this->print_units_template($dimension_key );
             ?>  
          <# } #>
                 <?php           
                   echo '</li>';
                   endforeach;
                 ?>
         </ul>
    </div>  
   </div>
            
   <div>
     <ul class="spicy-control-dimensions">
       <?php
         foreach ( $dimensions as $dimension_key => $dimension_title ) :
            $control_uid = $this->get_control_uid( $dimension_key );
       ?>
         <li class="spicy-control-multiunit">
         <#
          var unit=data.controlValue[<?php echo "'". $dimension_key.'_unit'."'"; ?>];
         #>
          <input id="<?php echo $control_uid; ?>" type="number"  data-name="{{data.name}}-<?php echo esc_attr( $dimension_key ); ?>" min="{{ data.range[unit].min}}" max="{{ data.range[unit].max}}" step="{{ data.range[unit].step}}" data-setting="<?php echo esc_attr( $dimension_key ); ?>"
    placeholder="<#
                   if ( _.isObject( data.placeholder ) ) {
                    if ( ! _.isUndefined( data.placeholder.<?php echo $dimension_key; ?> ) ) {
                       print( data.placeholder.<?php echo $dimension_key; ?> );
                       }
                      } else {
                              print( data.placeholder );
                             } 
                     #>"
                                
   <label for="<?php echo esc_attr( $control_uid ); ?>" class="spicy-control-multiunit-label"><?php echo $dimension_title; ?></label>
         </li>
       <?php endforeach; ?>
         <li>                    
          <div style="display: flex;">
           <button class="spicy-link-dimensions tooltip-target" data-tooltip="<?php echo esc_attr__( 'Link values together', 'Spicy-extension' ); ?>">
             <span id="spisy-{{data.name}}" class="spicy-linked">
               <i class="fa fa-link" aria-hidden="true"></i>
               <span class="elementor-screen-only"><?php echo __( 'Link values together', 'Spicy-extension' ); ?></span>
             </span>
             <span id="spisy-{{data.name}}" class="spicy-unlinked">
               <i class="fa fa-chain-broken" aria-hidden="true"></i>
               <span class="elementor-screen-only"><?php echo __( 'Unlinked values', 'Spicy-extension' ); ?></span>
             </span>
            </button>
            <?php       
             $this->print_link_unit_template();  
            ?>
           </li>
          </ul>
         </div>
        </div>
        </div>
        <# if ( data.description ) { #>
        <div class="elementor-control-field-description">{{{ data.description }}}</div>
        <# } #>
        <?php
    }

Creating the JavaScript File

Our JS file is named MultiUnit.js and extends the Elementor BaseMultiple module. This JS file contains a JavaScript class that has several functions, which are explained briefly below.

1. The below function defines the essential UI CSS selectors.

var ControlMultiUnitItemView=
    elementor.modules.controls.BaseMultiple.extend( {
    ui: function() {
     var ui = ControlBaseMultipleItemView.prototype.ui.apply( this, arguments );
         ui.controls = '.spicy-control-multiunit > input:enabled';
         ui.link = 'button.spicy-link-dimensions';
         ui.top_choices ='div.spicy-units-choices > input[type=radio][data-setting=top_unit]';   
         ui.right_choices = 'div.spicy-units-choices > input[type=radio][data-setting=right_unit]';
         ui.bottom_choices = 'div.spicy-units-choices > input[type=radio][data-setting=bottom_unit]';
         ui.left_choices = 'div.spicy-units-choices > input[type=radio][data-setting=left_unit]';
         ui.unitLink = '.spicy_link';
         ui.gear = '.spicy_link_first';
         ui.ranges_top = '.spicy-units-choices-label-top';
         ui.ranges_right = '.spicy-units-choices-label-right';
         ui.ranges_bottom = '.spicy-units-choices-label-bottom';
         ui.ranges_left = '.spicy-units-choices-label-left';
         ui.linked = '.spicy-linked';
         ui.unlinked = '.spicy-unlinked';
         return ui;
     }

2. This function defines the related event for each UI element.

events: function() {
  return _.extend( ControlBaseMultipleItemView.prototype.events.apply( this, arguments ), {
   'click @ui.ranges_top' : 'TopRangeToggle',
   'click @ui.ranges_right' : 'RightRangeToggle',
   'click @ui.ranges_bottom' : 'BottomRangeToggle',
    'click @ui.ranges_left' : 'LeftRangeToggle',
    'click @ui.link': 'onLinkDimensionsClicked',
    'change @ui.top_choices' : 'setTopInputRange',
    'change @ui.right_choices' : 'setRightInputRange',
    'change @ui.bottom_choices' : 'setBottomInputRange',
    'change @ui.left_choices' : 'setLeftInputRange',
    'click @ui.unitLink' : 'linkUnit',
    'click @ui.gear' : 'gearToggle',           
   } );
 }

3. This defines the essential variables.

defaultDimensionValue: 0,
 range_control:'',
 name_control:'',
 gear_check:true,
 range_all:true,
 Range_top:true,
 range_right:true,
 range_bottom:true,
 range_left:true,

4. This defines initial function for control initialization.

 initialize: function() {
 ControlBaseMultipleItemView.prototype.initialize.apply( this, arguments );
 this.model.set( 'allowed_dimensions', this.filterDimensions( this.model.get( 'allowed_dimensions' ) ) );
 this.range_control = this.model.get(['range']);
 this.name_control = this.model.get(['name']);
 }

5. We need a function to select the proper unit when it’s clicked. The below function is used for top_unit.

setTopInputRange : function( event ) {
  var val = $(event.target).val() ;
  var min = this.range_control[val].min;
  var max = this.range_control[val].max;
  var step = this.range_control[val].step;
        
  $('li.spicy-control-multiunit > input[type=number][data-name='+this.name_control+'-top]').attr({"min":min,"max":max,"step":step});
}

We’ve also declared similar functions for right_unit, bottom_unit, and left_unit that you can find in the source code.

6. We need other functions to show/hide units when clicked. The below function is used for the top_unit.

TopRangeToggle : function (event) {
  var cat = $(event.target).attr("data-cat");
  if(this.range_top==false){    $('.spicy-units-choices-label-top[data-cat='+cat+']').not(event.target).hide();
  this.range_top = true;
  }else if(this.range_top==true){
   $('.spicy-units-choices-label-top[data-cat='+cat+']').show();
   this.range_top=false;
 }   
 }

We also declared similar functions for right_unit, bottom_unit, and left_unit.

7. The function below syncs top_unit, right_unit, bottom_unit and left_unit together.

linkUnit : function(event) {
  var text=$(event.target).text();
  $('div.spicy-units-choices > input[type=radio][name=spicy-choose-'+this.name_control+'-top][value='+"'"+text+"'"+']').prop("checked", true).trigger('change');
  $('div.spicy-units-choices > input[type=radio][name=spicy-choose-'+this.name_control+'-right][value='+"'"+text+"'"+']').prop("checked", true).trigger('change');
  $('div.spicy-units-choices > input[type=radio][name=spicy-choose-'+this.name_control+'-bottom][value='+"'"+text+"'"+']').prop("checked", true).trigger('change');
  $('div.spicy-units-choices > input[type=radio][name=spicy-choose-'+this.name_control+'-left][value='+"'"+text+"'"+']').prop("checked", true).trigger('change');  
  $('div.spicy-units-choices > input[class='+this.name_control+']').not(':checked').next().hide();
  $('div.spicy-units-choices > input[class='+this.name_control+']:checked').next().show();

this.allRangeToggle(event);
 }

Finally, we have other functions that are similar to the JS file of the Dimension control and other custom functions that we haven’t explained. But you can find them in source code.

Creating the CSS File

To style the UI of control in the panel, we need CSS rules as seen below.

ul.spicy-control-dimensions {
 width: 100%;
}

.spicy-control-input-wrapper ul li {
 width: 20%;
 float: left;
}

div.spicy-units-choices > input {
 display: none;
}

div.spicy-units-choices > input:checked+label {
 color:red;
}
.spicy-control-multiunit > label {
 font-size: 11px;
}

div.spicy-units-choices > input:not(:checked)+label {
 display:none;
}

.spicy-link-dimensions {
 width:90%;
 height: 30px;
 border: 1px solid;
 border-color: black;
 background-color: #7a8791;
}

div.spicy-units-choices > label { 
 border-radius:50%;
 padding:3px;
 font-size:9px;
 background-color:#ebebeb;
 line-height: 16px;
}

.units-wrapper {
 height :29px;
 margin-top: 5px;
}

.units-wrapper ul li {
 margin-bottom: 0px;
 margin-top: 4px;
}

div.spicy-units-choices {
position: absolute;
}

.spicy_linkAllUnit {
 position: relative;
 height:30px;
 font-size: 14px;
 border-top-right-radius: 5px;
 border-bottom-right-radius: 5px;
 border: 1px solid;
 border-color: black;
 border-left: 0;
 background-color: #7a8791;
}

.spicy-control-multiunit > input {
 border-right : 0;
 border-radius: 0;
 border-color:rgb(58, 57, 57) !important;
 height:30px;
 padding-right: 0;
}

.spicy-control-dimensions >.spicy-control-multiunit:first-child input {
 border-top-left-radius: 5px;
 border-bottom-left-radius: 5px;
}

.spicy_link_first {
 display:block;
 border-radius:5px;
 padding:3px;
 font-size:13px;
 color: white;
}

.spicy_link {
 display:none;
 border-radius:50%;
 padding:3px;
 font-size: 12px;
 color: brown;
}

.spicy-unlinked {
 display: none;
}

.spicy_tooltip {
 width: max-content;
 background-color: #e6e9ec;
 text-align: center;
 border-radius: 6px;
 padding: 5px 0;
 position: absolute;
 z-index: 10;
 top: -1px;
 right: 100%;
}

.spicy-units-choices-label-top {
 position:relative;
 z-index: 5;
}

.spicy-units-choices-label-right {
 position:relative;
 z-index: 4;
}

.spicy-units-choices-label-bottom {
 position:relative;
 z-index: 3;
}

.spicy-units-choices-label-left {
 position:relative;
 z-index: 2;
}
.spicy_link_first:hover .spicy_link_tooltiptext {
 visibility: visible;
}
.spicy_linkAllUnit .spicy_link_tooltiptext {
 visibility: hidden;
 width: 88px;
 background-color: #373434;
 color: #fff;
 text-align: center;
 border-radius: 4px;
 padding: 5px;
 position: absolute;
 z-index: 1;
 right: 0;
 font-size: 9px;
 bottom: -26px;
}
.spicy_linkAllUnit .spicy_link_tooltiptext::after {
 content: " ";
 position: absolute;
 right: 5%;
 bottom: 94%;
 margin-left: -5px;
 border-width: 5px;
 border-style: solid;
 border-color: transparent transparent #373434 transparent;
}

How to Use the Custom Control

It’s time to put the control in action. Follow the steps below in order to use the control.

1. Register the custom control in our plugin using the following codes.

add_action( 'elementor/controls/controls_registered', [ $this,'init_controls']);

public function init_controls() {

  // Include Control files
  require_once( __DIR__ . '/controls/multi_unit.php' );

  // Register control
  \Elementor\Plugin::$instance->controls_manager->register_control( 'spicy-multi-unit-control', new Spicy_multi_unit());

}

2. Add the custom control to any widget. Now, it’s ready to use.

$this->add_responsive_control(
  'multiunit',
             [
              'label' => __( 'MultiUnit ', 'spicy' ),
              'type' => 'spicy-multi-unit-control',
              'size_units' => [ '%','em', 'px' ],
              'allowed_dimensions' =>'all',
              'selectors' => [
                '{{WRAPPER}} .elementor-widget-container' => 'padding: {{TOP}}{{TOP_UNIT}} {{RIGHT}}{{RIGHT_UNIT}} {{BOTTOM}}{{BOTTOM_UNIT}} {{LEFT}}{{LEFT_UNIT}};',
                             ],
            ]
 );

For more information, you can read this article.

Conclusion

In this article, we tried to explain how to create a custom control for Elementor. Also, we describe the essential files of control and the structure of them. Finally, we created a custom control named MultiUnit.

Feel free to share your experiences with us in the comments.

How to Perform a WordPress Backup in Jupiter X with BlogVault

WordPress Backup Featured Image

Building a WordPress website with Jupiter X is like taking a walk in the park – it’s easy. But building a website isn’t where the story ends. Websites could suddenly crash or get hacked, which could leave you with a rapid decline in traffic and revenue. Bad things happen when you least expect it. Better to be safe than sorry, right? You need to get your site a WordPress backup.

Taking regular backups is the best way to ensure that you have something to fall back on when things go wrong. A simple restoration can get your website up and running in no time.

So all you need to do is to have a good backup solution. But how do you go about choosing one? What does an ideal backup solution offer?

Choosing a Good Website Backup Solution

There are several WordPress backup services to choose from, which makes it difficult to select the right one. You either end up making a wrong choice or worse: you don’t choose at all.

But identifying a good backup service is not as difficult if you know what to look for. The backup solution should be able to provide the following:

  1. Complete backups
  2. Incremental backups
  3. Multiple backups
  4. Real-time backups
  5. Backup storage
  6. Restoration
  7. Independent dashboard
  8. Customer support

1. Complete backups

Your website contains different kinds of data. There are posts, pages, images, videos, tables, settings and configurations that should be backed up. A backup solution must be capable of backing up all these types of data and ensuring that it’s safely archived.

2. Incremental backups

Breaking the data into small chunks not only makes it easier to backup but also makes sure that nothing is left behind. This is called backing up your website incrementally. Incremental backups are best for large sites that contain a lot of data. The risk of leaving data behind is much higher for large websites.

3. Multiple backups

An ideal WordPress backup solution will take multiple backups of the same version and then store it in different locations. It can be stored in the solution’s own server or on cloud storage services like GDrive, DropBox or on your local system. It should also secure the backup copies by encrypting them so that if someone lays their hands on your backup, the copy will be illegible.

4. Real-time backups

Some websites need more than daily backups. Let’s say, for instance, that you run a very active photography blog. New pictures are being added and dozens of people are commenting and buying your prints. You’ll need to take backups in real-time for such a dynamic website. Every single change made on the site has to be backed up instantly. Failing to do so will cause loss of valuable data, such as prints that visitors added to cart but didn’t order. In such cases, you’ll lose orders when disaster strikes.

5. Backup storage

Simply taking backups is not enough: the data must be stored in an accessible location. Sometimes backups are stored on the site server, which makes it impossible to access them on certain occasions like when you can’t access your hosting account. Not just that, the server suffers because it’s burdened with storing backups on top of performing its regular processes.

6. Restoration

There are times when you need to restore your website. Many solutions don’t offer a reliable way to restore backups. Failing to implement a complete restore is a common complaint among website owners. Select a backup solution that comes with a good record for website recovery.

7. Independent dashboard

In a worst-case scenario, performing a backup is your fall back option. But what if you can’t access your backups when you need them? If the backup plugin is accessible only from the WordPress dashboard and if you lose access to wp-admin, then you won’t be able to access your WordPress backup either. Having a completely independent dashboard enables you to retrieve backups even when you can’t enter your website.

8. Customer support

Customer support is a primary benefit for a paid tool. But not all paid tools offer good customer service. A good backup solution values your time by offering reliable and agile customer service. Responses must be quick and easy to understand.

With that, we have covered everything that makes a good backup service. BlogVault Backup Solution is a service that checks all the boxes. Trusted by over 400,000 websites, BlogVault is the most reliable WordPress backup and restoration solution. Learn more about what the solution offers here.

You can use BlogVault to backup your Jupiter X website. In the next section, we’ll demonstrate how.

How to Perform a WordPress Backup with BlogVault

Step 1: First, sign up and add your website to BlogVault. From the dashboard, select Add New Site and enter your website address.

WordPress Backup Step 1
Add your site by selecting ‘Add New Site’

Step 2: Next, install the plugin to your site. There are two ways to do this. You can automate the installation or do it manually. We’ll show you both.

WordPress Backup Step 2
You can install the plugin manually or automate the process.

Install the BlogVault plugin manually

WordPress Backup Download Plugin
To download the plugin, click on Download Plugin

Download the plugin from your BlogVault dashboard. Then go over to your website and upload the plugin by navigating to Plugins > Add New > Upload Plugin.

WordPress Backup Upload Plugin
Upload the plugin to your Jupiter X site.

Alternatively, you can install the plugin like any other WordPress plugin. Head straight to your website dashboard and then go to the Add New plugins page. Search for BlogVault in the Search bar and then install and activate the plugin.

Auto-install the BlogVault plugin

The benefit of auto-installing the plugin is that you don’t need to go to your website. Simply enter your site credentials (BlogVault doesn’t save your admin credentials) and select Install plugin. That’s it. The plugin will be installed on your site automatically, and the WordPress backup process will begin instantly.

WordPress Backup Automatic Install
Insert the username and password of your Jupiter X website.

The plugin will backup your entire website and store it safely. Since your website is being backed up for the first time, it’ll take some time. Sit back and relax. You’ll get a notification once the process is complete.

Conclusion

You should be able to rely on backups for any unforeseen situations. Whether you want a new backup service or plan on upgrading your old service, you need to verify whether it offers all the essential features.

In this guide, we explained all these features to be on the lookout for and showed you how to install BlogVault, a WordPress backup solution that’s one of the best out there. We hope you found our guide useful. If you have any questions, feel free to leave us a comment below.

Socially Hosted vs. Locally Hosted Videos: Pros and Cons

Locally Hosted Videos Featured Image

So, let’s say that you own a website and know that videos have a better impact on your viewers. You provide an entertaining video including all the main points and you’re now ready to publish it onto your site. Now, what are your options in showing it to your visitors?

Generally speaking, you have two main options:

  • Using a socially hosted video
  • Using a locally hosted video on your own website

So you might be asking yourself the main advantages of each. If you can clearly grasp the benefits of socially hosted vs locally hosted videos, then you’ll be able to make an informed decision based on your requirements. Let’s review the costs and benefits for each one.

Socially Hosted Videos

YouTube and Vimeo are two famous video sharing websites. Chances are that you already know how to use them. Although other video sharing websites such as Wistia are trending these days, the most popular ones continue to be YouTube and Vimeo. The good news is that it’s easy to embed a video from these websites in Jupiter and Jupiter X.

The process of adding a video from any video sharing website to your WordPress website is as easy as inserting the link of the video into your content or using it in a proper widget in your page builder. Assuming that you have uploaded a video on YouTube and embedded it into your website, you’ll have the following benefits:

Losing fewer server resources

Your server is no longer responsible for responding to video requests, so it’ll for sure use fewer resources. It may save you some money, especially in the cloud-based web hosts that calculate the price based on server usage.

Prepared Statistics

Need some metrics to measure the impact that video made on your viewers? No worries, the video-sharing websites typically provide proper measurement tools so you can even see which countries your visitors are from or what your recent popular videos and comments on your channel were.

Socially Hosted Videos Statistics
Youtube Analytics inside the Youtube Studio where you can moderate your channel

Visibility and sharing options through a large community

Yes, the video-sharing website itself will allow for your video to be searched and viewed. This will help you grow your online visitors if you provide the correct description and link your customers to the proper places. Besides that, you’ll have sharing options too. This means that you’ll get a better visitor flow when some users like your video and share it on their social networks or their own websites (if you allow it, that is). This is actually one of the best reasons to use socially hosted videos on your website.

Some other benefits like the more advanced video players (similar to what YouTube offers) will choose the video’s quality depending on the user’s connection speed. Such options might also encourage you to use a socially hosted video over a locally hosted one. But let’s see how much it costs for you to go the social route.

Performance loss

It’s true – your website will have a lower performance if you try GTMetrix or other performance testers out there. The reason is that the video player needs to load, and it usually has a lot of dependencies on different domains which will be requested by your browser and will certainly increase the website loading time. If you use a lot of videos, the result would be even worse than you think.

Video player customization

You cannot customize or control the video player when using a socially hosted video. (However, while Wistia resolved it somehow, this is still valid for YouTube and Vimeo). This becomes worse when you want to show a video on a section background where users should not see the video controls and borders.

The YouTube border on the top and the controls at the bottom during the first three seconds of a Background video. Currently, the YouTube player does this, and there’s no way to prevent it.

Video not available for different visitors

Sometimes, you might be unaware that you have an issue (for example, a trademark issue) with your video. Video sharing websites will detect this and won’t allow users from certain locations to watch the video. If you don’t pay attention to the notifications from YouTube or Vimeo, then this could lead to a loss in your number of viewers.

In general, maintaining your content in separate places like on YouTube and your own website could be a bit tricky. You are hosting a part of your content somewhere else, meaning that you’ll need to maintain it properly and keep it updated based on the video-sharing terms of use. Also, you need to be careful about the ads that are played on your videos. By default, they are disabled for embedded videos, but if you enable them, you need to make sure that you won’t lose customers because of it.

Now let’s take a look at locally hosted videos.

Locally Hosted Videos

By locally hosted videos, I mean that you upload the video on the same website and web host. So, the video file has the same domain name as your main website. Now, assuming that you have prepared your video and want to show it to your customers, let’s see what you will get if you upload it onto your own website. In general, the benefits of socially hosted videos are the costs here and vice versa.

Better speed performance

While you host your video on the same websites, the requests going to your server will be resolved instantly on your own server, and the browsers will not have to deal with other domains to load a video player. It’ll speed up the server response time.

Controlling the Video Player

You’ll have full control of the video player with locally hosted videos. You can deactivate the controls, timelines, and titles, you can mute the video or add a loop to it or even use a very customized video player if you install a video player plugin.

Locally hosted videos Video Plater
The video is playing inside a laptop video frame mockup using Raven’s Video player without showing the controls.

You can make sure that your video is playing for all your users

You’ll no longer lose your customers over the “this video is not available in your region” error message. However, if you pay attention to the video-sharing website notifications, you won’t face it with that problem either. But in case any new terms show up, making your video unavailable for some of your users might cause you to lose some customers until you fix the issues. You won’t come across this issue at all when using locally hosted videos.

Now let’s take a look at some of the downsides of locally hosted videos.

Multiple formats required

You would need to provide two well-known formats for your video to keep your users around: MP4 and Webm. Unlike YouTube or Vimeo where you can freely upload any video format you like and then easily use them on your website, you have to convert your videos into the correct format and codec and then upload it onto your website.

Big files require big resources


Wondering why your monthly traffic usage increased suddenly? One of the reasons might be the videos you have hosted on your website. If each visitor plays the video to the end, the traffic used will be at least equal to the size of the video. So be careful about your server resources when you host a video. Actually, by 2021, probably more than 60% of web traffic will belong to videos.

Statistics are not easily available

Want to know the impression your video made when you uploaded it on your web host? You’ll need third-party plugins or services or extract the raw data from your server logs. This is a bit time consuming even for advanced users. So, if the statistics are very important for you and you don’t want to pay for other services, you might consider using socially hosted videos.

Final Thoughts

Based on the facts above, you need to decide whether socially hosted or locally hosted videos will work better for you. If you’ve already used locally hosted videos and think that the server usage is not worth keeping the videos on the same server, simply migrate your videos to video sharing websites such as YouTube or Vimeo.

On the contrary, if you think that the performance of your website is much more important and will outweigh the benefits of using socially hosted videos, start moving your videos to your own website. This article will help you decide wisely about the way you deal with your own videos.

Understanding WordPress Hooks

WordPress, the most popular CMS (Content Management System) is known for its flexibility. It’s highly customizable, and making any changes is incredibly easy. One of the most important aspects of WordPress and its flexibility is WordPress hooks. In this post, we are going to explore what exactly a WordPress hook is, how it works and how we can use them.

Users are able to extend WordPress functionality by using plugins. WordPress.org has more than 55,000 plugins in its repository – many of which are free. There are some premium plugins hosted by WordPress.org as well.

So, even by looking at the plugin’s stats, we see that a lot of developers create plugins for WordPress. This is due to the flexible nature of the WordPress structure. So where do hooks come into play? They are an integral part of how plugins work with WordPress core.

What is a WordPress hook?

Let’s break it down. A WordPress hook will let you know that something is happening. In other words, a hook will let you run custom codes when loading a WordPress website to add, remove or modify certain functionality or data. You can do the following with a hook:

  • Executing a code to send a welcome email right after a new user has registered to the site.
  • Running a custom code to clear site cache after saving new changes in customizer.
  • Modifying the default admin footer text.
  • Changing the label of the “Register” button on the registration page.
  • Modifying the markup of the page right before the page loads.
  • Including new styles in certain conditions.

The main point of using hooks is that you don’t need to touch WordPress core files that are required by WordPress to work. If you edit any file in WordPress core, you’ll lose it after updating WordPress.

These are some basic examples of WordPress hooks. As previously mentioned, they work with certain functionality or data. So, there are two different types of WordPress hooks:

  • Actions
  • Filters

WordPress Actions

Action hooks can be used to add custom functionality when needed. For instance, imagine that you want to run a code to log the last login time for each user. You’ll need to run a piece of code that records the time right after a user logs into the site. So you’ll need to run an additional functionality at a certain time. In this case, we would have to use action hooks. Action hooks work with functionality – they are doing something new.

How do action hooks work?

Action hooks are similar to informing everyone that you want to do a specific thing such as saying, “Hey buds, I’ve just arrived” or “Bye guys, I’m leaving.” When you inform others, they are aware of what you did or what you want to do, and they can say something in response, remind you of something or react in any other type of way.

While WordPress is loading and reaches a specific point, it’ll let us know about it. So, you can run your codes to add specific functionality or to extend existing functionality.
Some examples of actions include the following:

wp_head When you reach the <head> tag, WordPress lets you know by running the wp_head hook. Remember it as a name. We will provide you with some codes and an explanation about how to use hooks.

publish_post This runs when a post is published or if it is edited and its status is changed to “published.” So, Imagine that you want to tweet a post automatically after publishing it to your WordPress site. This hook makes it easy for you to do it.

wp_footer This action hook is triggered near the tag. That means you are reaching the end of document markup. Many developers use this hook to include their javascript files to the footer of the page.

WordPress Filters

Photo by Luca Bravo on Unsplash

Filter hooks work with data. By data, we mean a simple text, HTML markups and even a PHP variable that could be the value of an option. This means that you can change an option value on the fly. Or you can change a certain text in the admin dashboard without editing WordPress core files. Also, filters could be used to modify multiple things at the same time. For example, you can add a new class name and data attribute simultaneously to the navigation menu items using a filter.

How do filter hooks work?

Filter hooks differ from action hooks. When you reach a certain code, WordPress allows you to make changes to something. Imagine that your child wants to go to school and right before going out, you put an extra book in their backpack. In this example, you’ve changed the content of the backpack and filtered it when you had access to it. Filters work in the same way. They will let you know that content is going to be printed or when an option is going to be used – and you’ll be able to modify it if you want.

Some real example of filters are:

login_erros This runs whenever an error is going to be shown to the user in the login page.

body_class This fires (runs) while generating the tag. Use this filter hook if you want to modify the class names of the body tag.

pre_delete_post This fires right before deleting a post. You may want to avoid sending them to the trash and delete them completely. This filter hook will be useful for you.

How to use WordPress hooks

We’ve covered the basics of WordPress hooks. It’s time to learn code and use actions and filters in the real world. In this section, we’ll see some new things such as Hooked functions, Hook priority and Hook arguments.

Basic WordPress hooks usage

add_action( ‘init’, function(){
     // Do something.
 } );
Code explanation:

add_action: This is a function from WordPress. You’ll need to use this whenever you want to register a new action hook (run an action).

init: This is the hook name. Each event has a unique hook name. You can find a list of existing WordPress hooks on the Plugin API/Action reference page.

function(): This is the callback. The code that you want to execute when reaching the event.

For filters, it is a bit different:

add_filter( ‘excerpt_length’, function( $value ){
     // Do something and change $value.
     return $value
 } );

add_filter: Same as actions, this is a function name from WordPress. You’ll need to use this whenever you want to register a new filter hook.

excerpt_length: Again, this is the hook name. Hook names are meaningful. So, while using excerpt_length you can expect that it will change the excerpt length of the post excerpt.

function(): This is the callback and the code that you want to execute in order to change something.

And the big difference with actions:

return $value

Filters need to return something. Why? Because using filters, you’re going to change something, not destroy it. If you don’t return, your variable/value will be missed. So, keep in mind, always return in filter callback.

Another way to implement this:

add_action( ‘init’, ‘my_callback’ );

 Function my_callback(){
    // Do something.
}

In this mode, we have separated the callback function instead of using an anonymous function. There is no difference.

Hook Priority

add_action( ‘init’, ‘my_callback_early’, 9  );
add_action( ‘init’, ‘my_callback_normal’, 10 );
add_action( ‘init’, ‘my_callback_late’, 11 );

The priority determines when the callback function will be executed in relation to the other callback functions associated with a given hook.

In the above example, my_callback_early is the first function that runs when reaching the init hook. After that, the my_callback_normal will run and at the end my_callback_late.

When there are multiple registered callback functions for the same hook with the same priority, the order of registering them will be used to running callback functions.

Hook Arguments

A callback function can take some arguments. For example, the excerpt_length hook will pass the current length as a parameter. So you have access to it in your callback function.

add_filter( ‘excerpt_length’, ‘my_custom_excerpt_length’, 10, 1);

function my_custom_excerpt_length( $length ) {
  $length = 50;
  return $length;
}

In the above example, 10 is the priority of the running callback, and 1 is the number of the callback function parameters. Because both of them are like default values, you can avoid writing them. The following code does exactly the same thing:

add_filter( ‘excerpt_length’, ‘my_custom_excerpt_length’ );

Practical Examples of WordPress Hooks

Add new admin menu and page:
function register_my_custom_menu_page() {
     add_menu_page( 'Custom menu page title', 'Custom menu label', 'manage_options', 'myplugin-settings.php', '', '
 dashicons-menu-alt3', 6 );
 }
 add_action( 'admin_menu', 'register_my_custom_menu_page' );
Change the excerpt length
function my_custom_excerpt_length( $length ) {
     return 35;
 }
 add_filter( 'excerpt_length', 'my_custom_excerpt_length', 999 );
Insert custom content after each post
function my_custom_post_footer($content) {
        if(!is_feed() && !is_home()) {
                $content.= "<p>Share your idea about this post in comments.</p>";
        }
        return $content;
}
add_filter('the_content', 'my_custom_post_footer');
Disable autosave
function my_prefix_disable_auto_save(){
    wp_deregister_script( 'autosave' );
}
add_action( 'wp_print_scripts', 'my_prefix_disable_auto_save' );
Change the login page message
function my_prefix_the_login_message( $message ) {
    if ( empty($message) ){
        return "<p>Welcome to this site. Please log in to continue</p>";
    } else {
        return $message;
    }
}
add_filter( 'login_message', 'my_prefix_the_login_message' );
Remove login error messages
function my_prefix_remove_login_errors( $error ) {
    return "Incorrect login information";
}
add_filter( 'login_errors', 'my_prefix_remove_login_errors');

Final Thoughts

Wrapping up, WordPress hooks are one of the most important concepts that allow us to develop plugins and add new custom functionality to WordPress. Again, don’t forget to return when using a filter hook ;).

In this article, we guided you through the basics of WordPress hooks, including what they are and how they work. We also gave you some examples of how they are used in code to add further functionality to your website.

In the comments section below, please share your experiences and thoughts with us!

Extend Elementor like a pro: Creating a New Widget

Creating a New Widget Featured Image

Elementor is packed with various elements or widgets. Widgets allow us to build websites and display appropriate content. But sometimes we need specific functionality for our website. And to do this, we need to create a new widget or element.

What is a widget?

A widget or element is a section in the Graphical User Interface (GUI) that lets us display the information we want to showcase to users.

The Elementor widget is a combination of PHP, JavaScript, HTML and CSS codes that generate a custom output for us. We suggest visiting this link before reading this article.

Elementor Widgets

Each widget has custom controls like input, fields, buttons and more. With these controls, we can set our custom settings and see a live preview in the editor and render the final HTML in frontend.

Widget Structure

In order to create a new widget, we must extend the Widget_Base abstract class. This class has several methods that we first need to override.

<?php
class Elementor_Test_Widget extends \Elementor\Widget_Base {

    public function get_name() {}

    public function get_title() {}

    public function get_icon() {}

    public function get_categories() {}

    protected function _register_controls() {}

    protected function render() {}

    protected function _content_template() {}
}

Widget Name

With the get_name() method, we can set the name of a widget and return the name of the widget.

public function get_name() {
    return 'Widget Name';
}

Widget Title

With the get_title() method, we can set the label of the widget.

public function get_title() {
    return __( 'Widget Title', 'Plugin Name' );
}

Widget Icon

The get_icon() method set the icon for our widget that displayed in the panel.

public function get_icon() {
    return 'eicon-gallery-grid';
}

Widget Categories

The get_categories() method set the category that our widget must be placed on the panel’s categories. In default, there are several categories including the following:

  • Basic
  • Pro-elements
  • General
  • Woocommerce-elements
  • WordPress
  • And so on.
public function get_categories() {
    return [ 'basic' ];
}

We can also create custom categories with the elementor/elements/categories_registered action.

<?php
function create_custom_categories( $elements_manager ) {

    $elements_manager->add_category(
        'custom-category',
        [
         'title' => __( 'Custom Category', 'plugin-name' ),
         'icon' => 'fa fa-plug',
        ]
    );
}
add_action( 'elementor/elements/categories_registered', 'create_custom_categories' );

Widget Controls

With the _register_controls() method, we can set essential sections and controls for the widget.

There are several controls that we can use for widget settings, such as the following:

  1. UI Controls
    • Button
    • Divider
    • Heading
    • Raw Html
  2. Data Controls
    • Text
    • Select
    • Choose
    • Gallery
    • Slider
    • Typography
    • And so on.
  3. Multiple Controls
    • Url
    • Media
    • Image Dimensions
  4. Unit Controls
    • Slider
    • Dimensions
  5. Group Controls
    • Typography
    • Text Shadow
    • Box Shadow
    • Border
    • Background

For more information on Elementor controls, you can check out this link.

Widget Template

The render() method allows creating a frontend HTML code with the PHP.

The _content_template() method generates a live preview for the widget in the editor by using the Backbone JavaScript library.

How to add controls to our widget

In default, there are three tabs in the Elementor panel, which are the Content Tab, Style Tab, and Advanced Tab. To add controls to our widget, we should first create a section and assign it to one of the tabs. Then we can add our favorite controls to the section. As mentioned above, we must put our code in the _register_controls() method.

Creating a Section

To create a section, we need to set the following essential parameters:

  • Section Name
  • Section Settings(label ,tab)
$this->start_controls_section(
     'section_name',//set unique name

          //set setting of section
        [
         'label' => __( 'Section Label', 'plugin-name' ),
         'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
        ]
 );

  //THE CONTROLS COME HERE

$this->end_controls_section();

We must set the following parameters for each control as seen below:

  • Control Name
  • Control Setting(label,type)

Adding a normal control

Use the following control to add a normal control.

$this->add_control(
    'control_name',//set unique name for control

           //set essential settings
         [
        'label' => __( 'Control Label', 'plugin-name' ),

            //CONTROL_TYPE can be TEXT, SLIDER, ...
        'type' => \Elementor\Controls_Manager::CONTROL_TYPE,
         ]
    );

Adding a responsive control

This control type includes different settings value for desktop, tablet, and mobile devices.

$this->add_responsive_control(
     'control_name',
       [
        'label' => __( 'Control Name', 'plugin-name' ),
           //CONTROL_TYPE can be TEXT, SLIDER, …

         type' => \Elementor\Controls_Manager::CONTROL_TYPE,
           //SET FAVORITE RANGE LIKE PX, %, EM

         'range' => [
                 'px' => [
                        'min' => 0,
                        'max' => 100,
                       ],
                ],
            // SET FAVORITE DEVICES
          'devices' => [ 'desktop', 'tablet', 'mobile' ],
        'desktop_default' => [
                        'size' => 30,
                        'unit' => 'px',
                         ],
          'tablet_default' =>  [
                        'size' => 20,
                        'unit' => 'px',
                         ],
          'mobile_default' =>  [
                        'size' => 10,
                        'unit' => 'px',
                         ],
                
                ],
            ]
        );

Adding a group control

This control groups several normal controls in one control such as typography.

$this->add_group_control(
//Group_Control_Class can be       Group_Control_Typography,Group_Control_Border or other group controls

  Group_Control_Class::get_type(),
  [
   'name' => 'control_name',
   'label' => __( 'control Label', 'plugin-name' ),
  ]
);

Adding control tabs

Create a tab area to add various controls.

//start tabs area container
$this->start_controls_tabs();

  // create first tab area
  $this->start_controls_tab();

    $this->add_control();

      $this->end_controls_tab();

     // create second tab area
      $this->start_controls_tab();

    $this->add_control();

      $this->end_controls_tab();

$this->end_controls_tabs();
//end tabs area container

Adding control popovers

Create a popover window will allow you to display various controls.

$this->add_control(
   'control_name',
    [
     'label' => __( 'Control Label', 'plugin-name' ),
     'type' => \Elementor\Controls_Manager::POPOVER_TOGGLE,
     'label_off' => __( 'Default', 'plugin-name' ),
     'label_on' => __( 'Custom', 'plugin-name' ),
     'return_value' => 'yes',
    ]
  );

    $this->start_popover();

    $this->add_control();

    $this->add_control();

    $this->end_popover();

How to Display or Hide Sections and Controls in Widgets

At times, you might want to hide some sections or controls in your widget, but using if / else in the code is a hassle. Fortunately, now you can do this conveniently with the condition in the settings for sections or controls.

$this->start_controls_section(
  'my_section',
   [
    'label' => __( 'My Section', 'plugin-name' ),
    'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
    'condition' => [
                       'Name' => 'Value',
                      ]
      //name must be unique name of one control
      //Value must be the return value of control
   ]
);

Let’s say that we have one control named Choose_ Layout with two values first and second. After adding the code found below code to any section or control, our section or control will be displayed if the return value of the Choose_ Layout control is equal to first. And it will be hidden if the return value of Choose_ Layout control is equal to the second.

'condition' => [
                'Choose_ Layout' => 'first',
               ]

How to Change Widget Output Style Automatically from the Control Settings

One of Elementor’s amazing features is the ability to easily change the style of widget output with CSS code and selectors. For example, if we want to change the height of images in output, first we must assign a class attribute to our HTML tag. Then use this class with the selector in settings of control.

<img class="test-img">

$this->add_control(
          'test_height',
            [
             'label' => __( 'Height', 'Spicy-extension' ),
             'type' => \Elementor\Controls_Manager::SLIDER,
             'separator' => 'after',
             'show_label' => true,
             'selectors' => [
                '{{WRAPPER}} .test-img' => 'height: {{SIZE}}{{UNIT}};',
              ],
            ]
        );

How to Get Widget Settings

To create the final Html code in the render() method and live preview in the _content_template() we’ll need input the parameter from the widget controls like height, width, font-size and more. In Elementor, the input parameter is called Settings. We can arrange settings in render() using this method.

$widget_settings= $this->get_settings_for_display();
$widget_settings['control_name'];

For the _content_template() method the Elementor store setting in the settings variable.

settings.control_name

One important note that we must consider is the settings are saved in a multidimensional array. We can get an inner setting with the following code.

$widget_settings['control_name ']['option'];

settings.control_name.option 

Creating a Sample Widget

Below, we have illustrated how to build a gallery widget step-by-step so you can better understand how to cover the topics mentioned above and create an Elementor widget.

Our gallery widget is registered in the Spicy plugin and the root directory of the gallery widget is:

-Css
-gallery.css
-index.php
-widgets
-gallery.php
-index.php
-spicy.php
-index.php

Index.php file is an empty file that prevents a malicious hacker from directly accessing the plugin.
Spicy.php file is the main plugin file that we register our widget with.
Gallery.css file is a CSS file that sets the default style of a gallery widget.
Gallery.php is the main file that defines the functionality of a gallery widget.

Download the Source Code here.

Our gallery widget is based on the grid and has two layouts, which are classic and pro. Both layouts have the following controls:

  • Skin
  • Column gap
  • Row gap
  • Columns
  • Hover Animation
  • Box Shadow

The classic layout has a gallery control, and the image section contains the below controls:

  • Height
  • Image size behavior
  • Border type
  • Border radius

Also, the pro layout has an image repeater control with several sections such as the following:

  • Item section contains Border Type, Width, Color, and Border Radius controls.
  • Image section contains Height and Image Size behavior controls.
  • Text section contains Color, Typography, Alignment, and Spacing controls.
  • Avatar section contains Height, Width, Alignment, and Spacing controls.
  • Textarea section contains Color, Typography, Alignment, and Spacing controls.

Extending the Widget_Base Abstract Class

The main class of the gallery widget is similar to the code found below.

gallery.php
<?php
class Spicy_Gallery_Widget extends \Elementor\Widget_Base {
public function get_name() {
   return 'Gallery';
   }
public function get_title() {
    return __( 'Gallery', 'Spicy-extension' );
    }
public function get_icon() {
    return 'eicon-gallery-grid';
    }
public function get_categories() {
    return [ 'basic' ];
    }
protected function _register_controls() {

    //  start Content tab
        $this->start_controls_section(
            'content_section',
            [
             'label' => __( 'Content', 'Spicy-extension' ),
             'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
            ]
        );
        //add skin control
        $this->register_controls_skin();

        //add repeater for pro skin
        $this->register_controls_pro_repeater();

        //add gallery control
        $this->register_controls_Classic_gallery();

        //add column-gap slider
        $this->register_controls_column_gap();

        //add row-gap slider
        $this->register_controls_row_gap();


       
     
 //add columns number list
        $this->register_controls_column_number();

        $this->end_controls_section();
        // end content tab

        //start Style tab
        $this->register_controls_classic_style_image();

        //create pro item section
        $this->register_controls_pro_item();

      //create pro style section-image
        $this->register_controls_pro_style_image();

      //create pro style section-text
        $this->register_controls_pro_style_text();

      //create pro style section-avatar
        $this->register_controls_pro_style_avatar();

      //create pro style section-textarea
        $this->register_controls_pro_style_textarea();

      //Box Shadow
        $this->register_controls_pro_style_boxshadow();

        //hover animation
        $this->register_controls_pro_style_hoveranimation();
      //end style tab
    }

protected function render() {
        $settings = $this->get_settings_for_display();
        ?>
        <div class="spicy-gallery" width="100%">
        <?php
   
        if($settings['spicy_skin']=='classic'){
            $this->classic_render($settings);
        }else{
            $this->pro_render($settings);
  
                 }
        ?>
        </div>
        
        <?php
    }   

protected function _content_template() {
        ?>
        <div class="spicy-gallery">
        <#
         if(settings.spicy_skin=='classic'){
         _.each( settings.spicy_images, function( image ) {
        #>
        <div class="spicy-item elementor-animation-{{settings.spicyhover}}">
         <img  class="spicy-img" id="{{image.id}}" src="{{image.url}}"/>
        </div>
        <# }); } else{
         _.each( settings.spicy_image_list, function( image ) {
        #>
        <div class="spicy-item elementor-animation-{{settings.spicyhover}}">    
          <div class="spicy-pro-container">
            <img class="spicy-pro-img" src="{{image.spicy_pro_image.url}}" >
          </div>
          <p class="spicy-pro-text">{{image.spicy_pro_text}}</p>
          <div class="spicy-avatar-wrapper">
           <img class="spicy-avatar" src="{{image.spicy_pro_avatar.url}}" alt="Avatar">
          </div>
          <p class="spicy-pro-description">{{image.spicy_pro_description}}</p>
         </div>
        <# }); }#>
        </div>
     <?php
    }
?>

Creating Controls for a Gallery Widget

In the above code, you’ll see several functions in _register_controls() and render() functions.In fact, these methods assign sections and controls for the gallery widget. We can create these functions only for grouping codes and simplicity.

Common Controls

1. Skin control: This control’s type is Select with two options set as classic and pro. With this control, we have the ability to change the layout of the gallery widget.

protected function register_controls_skin(){
        $this->add_control(
               'spicy_skin',
               [
                'label' => __( 'Skin', 'spicy' ),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                'classic' => __( 'Classic', 'Spicy-extension' ),
                'pro' => __( 'Pro', 'spicy' ),
               ],
                'default' => 'classic',   
            ]
       );
}

2. Column Gap: This type of control is Slider, which allows us to change the space between columns of the gallery widget.

protected function register_controls_column_gap(){
        $this->add_responsive_control(
               'spicy_column_gap',
               [
                'label' => __( 'Column Gap', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SLIDER,
                'size_units' => [ '%','em', 'px' ],
                'range' => [
                    'px' => [
                        'min' => 0,
                        'max' => 50,
                        'step' => 1,
                    ],
                    '%' => [
                        'min' => 0,
                        'max' => 10,
                        'step' => 0.1,
                    ],
                    'em' => [
                        'min' => 0,
                        'max' => 10,
                        'step' => 0.1,
                    ],
                ],
                'default' => [
                    'unit' => '%',
                    'size' => 0.5,
                ],
                'show_label' => true,
                'selectors' => [
                    '{{WRAPPER}} .spicy-gallery' => 'grid-column-gap: {{SIZE}}{{UNIT}};',
                ],
            ]
        );
    }

3. Row Gap: This type of control is Slider, which we can use to change the space between rows of the gallery widget.

protected function register_controls_row_gap(){
        $this->add_responsive_control(
               'spicy_row_gap',
               [
                'label' => __( 'row Gap', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SLIDER,
                'size_units' => [ 'px','em','%' ],
                'range' => [
                    'px' => [
                        'min' => 0,
                        'max' => 50,
                        'step' => 1,
                    ],
                    '%' => [
                        'min' => 0,
                        'max' => 10,
                        'step' => 0.1,
                    ],
                    'em' => [
                        'min' => 0,
                        'max' => 10,
                        'step' => 0.1,
                    ],
                ],
                'default' => [
                    'unit' => 'px',
                    'size' => 5,
                ],
                'show_label' => true,
                'selectors' => [
                  '{{WRAPPER}} .spicy-gallery' => ' grid-row-gap: {{SIZE}}{{UNIT}};',
                ],
            ]
        );
    }

4. Columns: The type of control is Select, which lets us alter the number of columns of the gallery widget.

protected function register_controls_column_number(){
        $this->add_responsive_control(
               'spicy_columns',
               [
                'label' => __( 'Columns', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SELECT,
                'default' => 3,
                'options' => ['1'=>1,'1'=>1,'2'=>2,'3'=>3,'4'=>4,'5'=>5,'6'=>6,'7'=>7,'8'=>8,'9'=>9,'10'=>10],
                'devices' => [ 'desktop', 'tablet', 'mobile' ],
                'desktop_default' => [
                    'size' => '',
                ],
                'tablet_default' => [
                    'size' => '',
                ],
                'mobile_default' => [
                    'size' => '',
                ],
                'selectors' => [
                  '{{WRAPPER}} .spicy-gallery' => 'grid-template-columns: repeat({{SIZE}},1fr);',
                ],
            ]
            
       );
    }

5. Box Shadow: This section is used to add a box shadow effect to gallery items.

protected function register_controls_style_boxshadow(){
        $this->start_controls_section(
               'spicy_box_shadow',
               [
                'label' => __( 'Box Shadow', 'Spicy-extension' ),
                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
               ]
        );
        $this->add_group_control(
               Elementor\Group_Control_Box_Shadow::get_type(),
               [
                'name' => 'box_shadow',
                'label' => __( 'Box Shadow', 'Spicy-extension' ),
                'selector' => '{{WRAPPER}} .spicy-item',
               ]
        );
        $this->end_controls_section();
 }

6. Hover Animation: This section adds an animation effect to the gallery item.

protected function register_controls_style_hoveranimation(){
        $this->start_controls_section(
               'spicy_hover',
               [
                'label' => __( 'Hover Animation', 'Spicy-extension' ),
               'tab' => \Elementor\Controls_Manager::TAB_STYLE,
             ]
        );
        $this->add_control(
               'spicyhover',
               [
                'label' => __( 'Hover Animation', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::HOVER_ANIMATION,
                'default'=>'',
               ]
            
        );
        $this->end_controls_section();
    }

Classic Layout

The following controls or sections are only displayed in the classic layout.

1. Gallery Control: used to select multiple images for the gallery and displayed in the Content Tab.

protected function register_controls_Classic_gallery(){
        $this->add_control(
               'spicy_images',
              [
                'label' => __( 'Add Images', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::GALLERY,
                'separator' => 'default',
                'show_label' => false,
                'condition' => [
                                'spicy_skin' => 'classic',
                               ],
                'dynamic' => [
                              'active' => true,
                             ]
              ]
        );
 }

2. Image sections: This is displayed in the Style Tab to change the style of the image.

protected function register_controls_classic_style_image(){
        $this->start_controls_section(
               'style_section',
               [
                'label' => __( 'Image', 'Spicy-extension' ),
                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
                'condition'=>[
                              'spicy_skin' => 'classic'
                             ]
               ]
        );
        //classic height image control
        $this->add_responsive_control(
               'spicy_height',
               [
                'label' => __( 'Height', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SLIDER,
                'separator' => 'after',
                'size_units' => [ 'px','vw'],
                'range' => [
                            'px' => [
                                     'min' => 0,
                                     'max' => 500,
                                     'step' => 1,
                                    ],
                            'vw' => [
                                     'min' => 0,
                                     'max' => 100,
                                     'step' => 1,
                                    ],
                           ],
                'default' => [
                              'unit' => 'px',
                              'size' => 150,
                             ],
                'show_label' => true,
                'selectors' => [
                    '{{WRAPPER}} .spicy-img' => 'height: {{SIZE}}{{UNIT}};',
                ],
            ]
        );

        //image fitness classic
        $this->add_responsive_control(
               'spicy_image_fitness',
               [
                'label' => __( 'Image Size Behavior', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => ['cover'=> __( 'Cover', 'Spicy-extension' ),'fill'=>__( 'Fit', 'Spicy-extension' ),'contain'=>__( 'Contain', 'Spicy-extension' ),'scale-down'=>__( 'Scale Down', 'Spicy-extension' ),'none'=>__( 'None', 'Spicy-extension' )],
                'devices' => [ 'desktop', 'tablet', 'mobile' ],
                'desktop_default' => [
                                      'val' => '',
                                     ],
                'tablet_default' => [
                                      'val' => '',
                                    ],
                'mobile_default' => [
                                     'val' => '',
                                    ],
                'default' => 'cover',
                'selectors' => [
                    '{{WRAPPER}} .spicy-img' => 'object-fit: {{val}};',
                 ],
               ]
            
            );
        //border classic    
        $this->add_group_control(
               Elementor\Group_Control_Border::get_type(),
               [
                'name' => 'spicy_border',
                'label' => __( 'Border', 'Spicy-extension' ),
                'selector' => '{{WRAPPER}} .spicy-img',
               ]
        );
        //border radius classic
        $this->add_responsive_control(
               'spicy_image_border_radius',
               [
                'label' => __( 'Border Radius', 'Spicy-extension' ),
                'type' => Elementor\Controls_Manager::DIMENSIONS,
                'size_units' => [ 'px', '%' ],
                'selectors' => [
                    '{{WRAPPER}} .spicy-img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
                ],
            ]
        );
        $this->end_controls_section();
    }

Pro Layout

The following controls or sections are only displayed in the pro layout.

1. Repeater Section: This section has four controls, which are Image, Text, Avatar, and Textarea. It’s used for adding images individually and is displayed in the Content Tab.

protected function register_controls_pro_repeater(){
        $repeater = new \Elementor\Repeater();
        //add pro image control
        $repeater->add_control(
                   'spicy_pro_image',
                   [
                    'label' => __( 'Choose Image', 'Spicy-extension' ),
                    'type' => \Elementor\Controls_Manager::MEDIA,
                    'dynamic' => [
                                  'active' => true,
                                 ],
                    'default' => [
                     'url' => \Elementor\Utils::get_placeholder_image_src(),
                    ],
                  ]
        );
        //add pro text control
        $repeater->add_control(
                   'spicy_pro_text',
               [
                'label' => __( 'Text', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::TEXT,
                'label_block' => true,
                'placeholder' => __( 'Your Text', 'Spicy-extension' ),
                'default' => __( '', 'Spicy-extension' ),
                'dynamic' => [
                              'active' => true,
                             ],
               ]
        );
        //add avatar image control
        $repeater->add_control(
            'spicy_pro_avatar',
            [
                'label' => __( 'Choose Avatar', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::MEDIA,
                'dynamic' => [
                    'active' => true,
                ],
                'default' => [
                    'url' => \Elementor\Utils::get_placeholder_image_src(),
                ],
            ]
     );
        //pro textarea control
        $repeater->add_control(
               'spicy_pro_description',
               [
                'label' => __( 'Description', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::TEXTAREA,
                'rows' => 5,
                'default' => __( '', 'Spicy-extension' ),
                'placeholder' => __( 'Type your description here', 'spicy' ),
               ]
        );

        //add repeater control
        $this->add_control(
               'spicy_image_list',
               [
                'label' => __('Images','Spicy-extension'),
                'type' => \Elementor\Controls_Manager::REPEATER,
                'label_block' => true,
                'separator' => 'default',
                'fields' => $repeater->get_controls(),
                'title_field' => '{{{spicy_pro_text }}}',
                'condition' => [
                                'spicy_skin' => 'pro',
                            ],
             ]
        );
    }

2. Item Section: This is displayed in the Style Tab to change the border style of the gallery item.

protected function register_controls_pro_item(){
     $this->start_controls_section(
               'spicy_pro_item',
               [
                'label' => __( 'Item', 'Spicy-extension' ),
                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
                'condition'=>[
                              'spicy_skin' => 'pro'
                             ]
              ]
        );
        // pro item border
        $this->add_group_control(
               \Elementor\Group_Control_Border::get_type(),
               [
                'name' => 'spicy_item_border',
                'label' => __( 'Border', 'Spicy-extension' ),
                'selector' => '{{WRAPPER}} .spicy-item',
               ]
        );  
        //pro item border radius
        $this->add_responsive_control(
               'spicy_pro_item_border_radius',
               [
                'label' => __( 'Border Radius', 'Spicy-extension' ),
                'type' => Elementor\Controls_Manager::DIMENSIONS,
                'size_units' => [ 'px', '%' ],
                'selectors' => [
                    '{{WRAPPER}} .spicy-item' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
                ],
               ]
        );
        $this->end_controls_section();
    }

3. Image Section: This is displayed in the Style Tab to change the image size.

protected function register_controls_pro_style_image(){
        $this->start_controls_section(
               'spicy_pro_style_image',
               [
                'label' => __( 'Image', 'Spicy-extension' ),
                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
                'condition'=>[
                              'spicy_skin' => 'pro'
                             ]
               ]
        );
        //pro image size
        $this->add_responsive_control(
               'spicy_pro_image_height',
               [
                'label' => __( 'height', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SLIDER,
                'size_units' => [ 'px','em','vh' ],
                'range' => [
                            'px' => [
                                     'min' => 0,
                                     'max' => 800,
                                     'step' => 1,
                                    ],
                            'vh' => [
                                     'min' => 0,
                                     'max' => 100,
                                     'step' => 1,
                                    ],
                            'em' => [
                                     'min' => 0,
                                     'max' => 10,
                                     'step' => 0.1,
                                    ],
                          ],
                'default' => [
                              'unit' => 'px',
                              'size' => 150,
                             ],
                'show_label' => true,
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-img' => ' height: {{SIZE}}{{UNIT}};',
                ],
            ]
        );
        //pro image fitness
        $this->add_responsive_control(
            'spicy_pro_image_fitness',
            [
                'label' => __( 'Image Size Behavior', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => ['cover'=> __( 'Cover', 'Spicy-extension' ),'fill'=>__( 'Fill', 'Spicy-extension' ),'contain'=>__( 'Contain', 'Spicy-extension' ),'scale-down'=>__( 'Scale Down', 'Spicy-extension' ),'none'=>__( 'None', 'Spicy-extension' )],
                'devices' => [ 'desktop', 'tablet', 'mobile' ],
                'desktop_default' => [
                                      'val' => '',
                                     ],
                'tablet_default' => [
                                     'val' => '',
                                    ],
                'mobile_default' => [
                                     'val' => '',
                                    ],
                'default' => 'cover',
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-img' => 'object-fit: {{val}};',
                ],
            ]
            
      );
        $this->end_controls_section();

4. Text Section: This is displayed in the Style Tab to change the style of the text item.

protected function register_controls_pro_style_text(){
        $this->start_controls_section(
                'spicy_pro_style_text',
                [
                 'label' => __( 'Text', 'Spicy-extension' ),
                 'tab' => \Elementor\Controls_Manager::TAB_STYLE,
                 'condition'=>[
                    'spicy_skin' => 'pro'
                ]
            ]
        );

        //pro text color control
        $this->add_control(
               'spicy_pro_text_color',
               [
                'label' => __( 'Color', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::COLOR,
                'default' => '',
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-text' => 'color: {{VALUE}};',
                 ],
                'scheme' => [
                             'type' => \Elementor\Scheme_Color::get_type(),
                             'value' => \Elementor\Scheme_Color::COLOR_1,
                            ],
               ]
        );

        //pro text typography
        $this->add_group_control(
                \Elementor\Group_Control_Typography::get_type(),
                [
                 'name' => 'spicy_pro_text_typography',
                 'selector' => '{{WRAPPER}} .spicy-pro-text',
                 'scheme' => \Elementor\Scheme_Typography::TYPOGRAPHY_1,
                ]
        );

        //pro text alignment
        $this->add_responsive_control(
               'spicy_pro_text-_align',
               [
                'label' => __( 'Alignment', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::CHOOSE,
                'options' => [
                              'left' => [
                                          'title' => __( 'Left','Spicy-extension'),
                                          'icon' => 'fa fa-align-left',
                                        ],
                              'center' => [
                                            'title' => __( 'Center', 'Spicy-extension' ),
                                            'icon' => 'fa fa-align-center',
                                           ],
                              'right' => [
                                          'title' => __( 'Right', 'Spicy-extension' ),
                                          'icon' => 'fa fa-align-right',
                                         ],
                              'justify' => [
                                            'title' => __( 'Justified', 'Spicy-extension' ),
                                            'icon' => 'fa fa-align-justify',
                                           ],
                             ],
                'default' =>'',
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-text' => 'text-align: {{VALUE}};',
                ],
            ]
        );
        //pro text spacing control
        $this->add_responsive_control(
               'spicy_text_margin',
               [
                'label' => __( 'Spacing', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::DIMENSIONS,
                'size_units' => [ 'px', '%', 'em' ],
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-text' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
                ],
              ]
        );

        $this->end_controls_section();
    } 

5. Avatar Section: This is displayed in the Style Tab to change the style of the avatar.

protected function register_controls_pro_style_avatar(){
        $this->start_controls_section(
            'spicy_pro_style_avatar',
            [
                'label' => __( 'Avatar', 'Spicy-extension' ),
                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
                'condition'=>[
                    'spicy_skin' => 'pro'
                ]
            ]
        );
        //pro avatar height
        $this->add_responsive_control(
            'spicy_avatar_height',
             [
                'label' => __( 'height', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SLIDER,
                'size_units' => [ 'px','em','vh' ],
                'range' => [
                    'px' => [
                        'min' => 0,
                        'max' => 100,
                        'step' => 1,
                    ],
                    'vh' => [
                        'min' => 0,
                        'max' => 100,
                        'step' => 1,
                    ],
                    'em' => [
                        'min' => 0,
                        'max' => 10,
                        'step' => 0.1,
                    ],
                ],
                'default' => [
                    'unit' => 'px',
                    'size' => 50,
                ],
                'show_label' => true,
                'selectors' => [
                    '{{WRAPPER}} .spicy-avatar' => ' height: {{SIZE}}{{UNIT}};',
                ],
             ]
        );
        //pro avatar width
        $this->add_responsive_control(
            'spicy_avatar_width',
            [
                'label' => __( 'Width', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::SLIDER,
                'size_units' => [ 'px','em','vh' ],
                'range' => [
                    'px' => [
                        'min' => 0,
                        'max' => 100,
                        'step' => 1,
                    ],
                    'vh' => [
                        'min' => 0,
                        'max' => 100,
                        'step' => 1,
                    ],
                    'em' => [
                        'min' => 0,
                        'max' => 10,
                        'step' => 0.1,
                    ],
                ],
                'default' => [
                    'unit' => 'px',
                    'size' => 50,
                ],
                'show_label' => true,
                'selectors' => [
                    '{{WRAPPER}} .spicy-avatar' => ' width: {{SIZE}}{{UNIT}};',
                ],
            ]
        );
        //pro avatar align control
        $this->add_responsive_control(
            'spicy_avatar_align',
            [
                'label' => __( 'Alignment', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::CHOOSE,
                'options' => [
                    'left' => [
                        'title' => __( 'Left', 'Spicy-extension' ),
                        'icon' => 'eicon-h-align-left',
                    ],
                    'center' => [
                        'title' => __( 'Center', 'Spicy-extension' ),
                        'icon' => 'eicon-h-align-center',
                    ],
                    'right' => [
                        'title' => __( 'Right', 'Spicy-extension' ),
                        'icon' => 'eicon-h-align-right',
                    ],
                ],
                'selectors' => [
                    '{{WRAPPER}} .spicy-avatar-wrapper' => ' text-align: {{VALUE}};',
                ],
            ]
        );
        //pro avatar spacing control
        $this->add_responsive_control(
            'spicy_avatar_spacing',
            [
                'label' => __( 'Spacing', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::DIMENSIONS,
                'size_units' => [ 'px', '%', 'em' ],
                'selectors' => [
                    '{{WRAPPER}} .spicy-avatar' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
                ],
            ]
        );
        //pro border avatar
        $this->add_group_control(
            \Elementor\Group_Control_Border::get_type(),
            [
                'name' => 'spicy_avatar_border',
                'label' => __( 'Border', 'Spicy-extension' ),
                'selector' => '{{WRAPPER}} .spicy-avatar',
            ]
        );
        //pro border radius
        $this->add_responsive_control(
            'spicy_pro_border_radius',
            [
                'label' => __( 'Border Radius', 'Spicy-extension' ),
                'type' => Elementor\Controls_Manager::DIMENSIONS,
                'size_units' => [ 'px', '%' ],
                'selectors' => [
                    '{{WRAPPER}} .spicy-avatar' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
                ],
            ]
        );
        $this->end_controls_section();
    }

5. Textarea Section: This is displayed in the Style Tab to change the style of Textarea.

protected function register_controls_pro_style_textarea(){
        $this->start_controls_section(
               'spicy_pro_style_textarea',
               [
                'label' => __( 'Textarea', 'Spicy-extension' ),
                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
                'condition'=>[
                  'spicy_skin' => 'pro'
                ]
              ]
        );
        //pro textarea color control
        $this->add_control(
               'spicy_pro_textarea-color',
               [
                'label' => __( 'Color', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::COLOR,
                'default' => '',
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-description' => 'color: {{VALUE}};',
                ],
                'scheme' => [
                  'type' => \Elementor\Scheme_Color::get_type(),
                  'value' => \Elementor\Scheme_Color::COLOR_1,
                ],
               ]
        );
        //pro textarea typography control
        $this->add_group_control(
                \Elementor\Group_Control_Typography::get_type(),
                [
                 'name' => 'spicy_pro_textarea_typography',
                 'selector' => '{{WRAPPER}} .spicy-pro-description',
                 'scheme' => \Elementor\Scheme_Typography::TYPOGRAPHY_1,
             ]
        );
        //pro textarea align control
        $this->add_responsive_control(
               'spicy_pro_textarea-align',
                [
                 'label' => __( 'Alignment', 'Spicy-extension' ),
                 'type' => \Elementor\Controls_Manager::CHOOSE,
                 'options' => [
                               'left' => [
                                          'title' => __( 'Left','Spicy-extension' ),
                                          'icon' => 'fa fa-align-left',
                                         ],
                               'center' =>[
                                           'title'=>__('Center','Spicy-extension' ),
                                           'icon' => 'fa fa-align-center',
                                          ],
                               'right' =>[
                                          'title' => __( 'Right','Spicy-extension'),
                                          'icon' => 'fa fa-align-right',
                                         ],
                               'justify'=>[
                                           'title' => __( 'Justified','Spicy-extension'),
                                           'icon' => 'fa fa-align-justify',
                                          ],
                              ],
                'default' =>'',
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-description' => 'text-align: {{VALUE}};',
                ],
            ]
        );
        //pro textarea spacing control
        $this->add_responsive_control(
               'spicy_textarea_spacing',
               [
                'label' => __( 'Spacing', 'Spicy-extension' ),
                'type' => \Elementor\Controls_Manager::DIMENSIONS,
                'size_units' => [ 'px', '%', 'em' ],
                'selectors' => [
                  '{{WRAPPER}} .spicy-pro-description' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
                ],
            ]
        );
        $this->end_controls_section();
    } 

Create Final Html Output

To render our gallery output in the frontend, we must create the render function as the following:

protected function render() {
        $settings = $this->get_settings_for_display();
        ?>
        <div class="spicy-gallery" width="100%">
        <?php
   
        if($settings['spicy_skin']=='classic'){
            $this->classic_render($settings);
        }
         else{
          $this->pro_render($settings);
         }
        ?>
        </div>        
        <?php
    }
protected function classic_render($settings){
        if($settings['spicy_images']){
            foreach ( $settings['spicy_images'] as $image ) {
            echo '<div class="spicy-item elementor-animation-'. $settings['spicyhover'] .' ">';
               echo '<img id="'. $image['id'].'" class="spicy-img" src="' . $image['url'] . '">';
               echo '</div>';
            }
      }  
    }
protected function pro_render($settings){
        if($settings['spicy_image_list']){
            foreach ( $settings['spicy_image_list'] as $image ) {
                    echo '<div class="spicy-item elementor-animation-'. $settings['spicyhover'] .' ">';
                    echo '<div class="spicy-pro-container">';   
                        echo '<img class="spicy-pro-img" src="'.$image['spicy_pro_image']['url'].'" >';     
                    echo '</div>';  
                    echo '<p class="spicy-pro-text">'.$image['spicy_pro_text'].'</p>';
                    echo'<div class="spicy-avatar-wrapper">';
                        echo '<img class="spicy-avatar" src="'.$image['spicy_pro_avatar']['url'].'" alt="Avatar">';
                    echo'</div>';
                    echo '<p class="spicy-pro-description">'.$image['spicy_pro_description'].'</p>';
                    
                    
                echo '</div>';
            }
        }
    }

Create Live Preview in Editor

To generate a live preview of the gallery output, we must create the _content_template() method by using Javascript:

protected function _content_template() {
       ?>
        <div class="spicy-gallery">
        <#
         if(settings.spicy_skin=='classic'){
         _.each( settings.spicy_images, function( image ) {
        #>
        <div class="spicy-item elementor-animation-{{settings.spicyhover}}">
         <img  class="spicy-img" id="{{image.id}}" src="{{image.url}}"/>
        </div>
        <# }); } else{
            _.each( settings.spicy_image_list, function( image ) {
        #>
            <div class="spicy-item elementor-animation-{{settings.spicyhover}}">    
             <div class="spicy-pro-container">
                <img class="spicy-pro-img" src="{{image.spicy_pro_image.url}}" >
           </div>
              <p class="spicy-pro-text">{{image.spicy_pro_text}}</p>
                <div class="spicy-avatar-wrapper">
                 <img class="spicy-avatar" src="{{image.spicy_pro_avatar.url}}" alt="Avatar">
                </div>
                <p class="spicy-pro-description">{{image.spicy_pro_description}}</p>
            </div>
        <# }); }#>
        </div>
      <?php
    }

How to Register CSS Style to Widget

After creating a gallery widget, we need to register essential CSS style to our widget. To do this, we need to first create a CSS file, then register it in Spicy.php.

Gallery.css
.spicy-gallery{
 display:grid;
 grid-template-rows: auto;
 }
.spicy-gallery .spicy-img{
 width: 100%;
 object-fit: cover;
 margin: 0 auto;
 }

.spicy-gallery .spicy-pro-container{
 width:100%; 
 }
.spicy-gallery .spicy-pro-text{
 text-align:center;
 margin-top:-70px;
 margin-bottom: 10px;
 }
.spicy-gallery .spicy-pro-description{
 width:100%;
 text-align: center;
 padding-left: 10px;
 padding-right: 10px;
        
 }
.spicy-gallery .spicy-pro-img{
 width: 100%;
 }
.spicy-gallery .spicy-avatar{
 display:inline-block;
 margin-left:10px;
 margin-bottom: 20px;
 border-radius: 12px;
 }
.spicy-gallery .spicy-avatar.wrapper{
 display: block;
 }

In order to register our CSS file, we need to add below code to Spicy.php

// Register Widget Styles
add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'widget_styles' ] );
public function widget_styles() {
 wp_enqueue_style( 'spicyPluginStylesheet', plugins_url( '/css/gallery.css', __FILE__ ) );
}

Classic layout output

Creating a New Widget Classic Layout Output

Pro layout output

Creating a New Widget Pro Layout Output

Conclusion

In this blog post, we described how to extend Elementor like a pro in detail and explained the structure of an Elementor widget. We also illustrated how to create a section and control, how to display/hide a section or control, how to change the widget style from controls, how to get settings and how to render the final output in frontend and Elementor editor.

Finally, we walked you through the steps of developing a gallery widget. Feel free to share your ideas and experiences in the comments section below.

Creating A Brief For Your WordPress Developer: 8 Things To Remember

Creating a brief for your WordPress developer Featured Image

Writing a brief for your WordPress developer is something you must never overlook or discard as unnecessary. If you want to get a high-quality end product, you must be ready to put in some effort to phrase what you want this product to be. Here are the things to keep in mind when creating a brief for your WordPress developer.

Why Is It Important?

A brief for your WordPress developer is important for four main reasons:

  • It provides key details about what you want the developer to do and what you want the result to be.
  • It sets the tone of your project and gives a general idea of what it is that you have in mind.
  • It sets the timeframes and deadlines for the project describing when and what should be completed.
  • It specifies the requirements and additional features you might decide to add later on.

If your brief achieves all of these, then your WordPress developer will definitely know what you want from them and what they must do to get the results you need. Now, let’s get into the step-by-step guide.

1. General Project Information

The first section of your brief contains general project information. It functions as a kind of introduction to your document that aims to provide some of the key data about the client and the project.

First, include your personal details such as your full name, contact information, the company or organization you are representing, and so on. Anything that you consider necessary can be added. If you are not the client, then include the details of the person who you are working for and who will be the client.

Second, include the basic details about the project such as the project’s name, timeframes, and so on. Don’t go into much detail about any particular piece of information in this section as these will be discussed later on in your brief.

2. Goals & Estimates

The next section of your brief must contain the goals and estimates for your project. Think of what you want to achieve with this particular endeavor and then also include what your personal goals are if you are in charge of it.

Photo by Isaac Smith on Unsplash

In addition to that, talk about the problems that the project will solve. These can be both big and small, but make sure to include at least one problem. Also, include estimates for your project and what you think it will achieve that is not connected to solving problems.

If you haven’t set your goals yet, it’s a good idea to use a goal tracking app such as Aha! to do this and keep your aims in front of you at all times as well as check progress.

3. Target Audience

Creating a Brief for your WordPress Developer Target Audience
Photo by Austin Distel on Unsplash

The third section of your brief must contain the details about your target audience. If you haven’t researched this yet, then make sure to do it as soon as possible as this is a very important component of every successful project.

Describe such characteristics of your audience as its gender, age, occupation, location, interests, habits, and so on. Any relevant information will only be useful rather than a burden, so don’t be afraid to add something on top of that.

However, keep in mind that your audience may vary a lot and you may need to construct several customer personas. As long as you do this, you will be heading in the right direction with your project.

4. Detailed Project Description

This is the biggest section of your brief which goes into detail about every aspect of your project. Look back at your first section and elaborate on the points you made in it. You must be as precise and clear as possible. Otherwise, your developer won’t have a concrete picture of what you want and need.

If you don’t want to write your brief yourself, you can hire a professional from an online writing service such as Studicus to do this for you. Alternatively, you can ask only for this biggest part to be written for you and work on everything else yourself. If you decide to write your brief entirely on your own, make sure to check its grammar, spelling, and punctuation with the help of Grammarly.

5. Project Requirements

Right after the detailed project description, outline the project requirements. These include both functional and secondary requirements. Any tools, as well as resources, can also be added here in case you require those. Functional requirements are the ones that the project absolutely needs in order to be what you want it to be.

These include different features you want to be added and such. Secondary requirements are the ones that are not necessary right away and can be considered if there is enough time or resources for them. They serve as an additional advantage that your project may have in the future.

6. Timeline & Deadlines

Creating a Brief for your WordPress Developer Timeline and Deadlines
Photo by Alvaro Reyes on Unsplash

This section must include a timeline with all of the deadlines for your project. Even though you included a start and end date in the very first section of your brief, you must elaborate on it here and outline other dates. Make sure that you write about deadlines and timeframes for each stage of development. This will guarantee that the progress is steady and you can check back on how your developer is doing every once in a while.

Alternatively, you may want to ask your developer to report back on certain dates. You can also outline another timeline that can be used in case the first one fails due to an unexpected turn of events. This will work as a kind of a Plan B, so you don’t necessarily have to include it into the brief and can simply keep it for yourself.

7. Budget & Expenses

Creating a Brief for your WordPress Developer Budget and Expenses
Screenshot taken from Mint

The budget and expenses are always a sensitive topic for both sides. This is why you must treat this section with caution and make sure that all of the data you include here is as accurate as possible. Think of all the expenses you will have. If there are any additional ones that can happen out of the blue, describe them too as you wouldn’t want any surprises. You can use different apps such as Mint to help you keep track of your budget and manage your bank accounts at the same time.

8. Measures of Success

Creating a Brief for your WordPress Developer Measures of Success
Photo by Carlos Muza on Unsplash

The last section should include your measures of success. To put it simply, these are the standards that you will be comparing the result in order to check the project’s success. You must make them as realistic as possible, but not too high or too low at the same time.

You could say that these are similar to the second section of your brief where you mentioned your estimates. But unlike that section, this one should have more exact and concrete standards that you will stick to more seriously.

Final Thoughts on Creating a Brief for your WordPress Developer

In conclusion, writing a brief for your WordPress developer is definitely not as difficult once you know what it must include. Proper communication with your developer will ensure that both of you are aware of each other’s thoughts and intentions, so don’t hesitate to contact them if there is something you’d like to specify.

Google Maps Alternatives: Good or Bad?

Google Maps Alternatives Featured Image

Many websites created by Jupiter users include a Google Map element. They’re particularly helpful for businesses who have a set location that they would like their visitors to know about and visit. But in using Google Maps, you might run into difficulties such as error messages as seen in the image below. In the next paragraph, we’ll explain in detail why you’ve received this message and how you can begin using alternatives to Google Maps!

The launch of Google Maps Platform

As of 11 June 2018, Google Maps changed its name to Google Maps Platform. With this change, any site that uses Google Maps is required to have a valid API key and a Google Cloud Platform billing account. Featuring Google Maps on your website is still possible, but you’ll have to make some modifications to how it is set up, including giving Google your credit card.

You can read more about the restructuring of Google Maps here.

Without an API key, sites with Google Maps will no longer be supported, and any Maps requests will now show only low-resolution maps watermarked with “for development purposes only” unless a credit card is associated with it.

If you are unwilling to create a billing account with Google, you can still find some Google Maps alternatives. We’ll list some of them.

Open Street Maps as a Google Maps Alternative

Tons of sites all around the world are working on OSM. The WP OSM Plugin is an open-source plugin with a free license and without any pro version or a business plan.

Features of the WP OSM Plugin include:

  • Add geolocation to a post or a page
  • Add GPX and KML files or just a single marker to a map
  • Add maps as shortcode or widget to a post/page
  • Fullscreen map, maps with markers linked to post/page with geolocation
  • OpenStreetMap, OpenSeaMap, Stamen maps, basemap, etc.
Google Maps Alternatives Features

You can read their FAQ and documentation on their official site.
Read the “Display a simple map” article to find out how to add a map to your WordPress site.

MapBox

Another alternative to Google Maps is MapBox. Mapbox is an online mapping service that allows users to customize maps – much more than Google Maps ever did. You can change backgrounds, road colors, and a lot more directly with a simple interface.

WP Mapbox GL JS Maps is the only plugin that enables you to make highly customized maps with 3D features, custom icons, zooming, custom filters, among many more options. It has a free and an inexpensive premium version, which adds custom markers, better control over directions, and more advanced control over marker and popup behavior.

To get started with MapBox, visit http://mapbox.com/ and click “Sign Up.” There are different pricing options you can select when signing up for MapBox. For now, go ahead and sign up for a free account, which comes with more than enough to get started. Read more here on how to use it.

The plugin provides you with a live preview while building the map, so you’ll always be able to see what the map will be before it’s published onto the main site. You can embed your map with a shortcode or publish it directly!

We’ll now show you how to use these alternatives to Google Maps on the Jupiter X site and describe the Open Street Map.

How to use Open Street Maps on Jupiter X

You’ll first need to install the OSM plugin in your WordPress dashboard via Plugins > Add New as described in this Jupiter X article.

Then follow the instructions from the OSM article:

1. Create a page or a post where you want to show a map and open it to edit.

2. Find the “WP OSM Plugin shortcode generator” section in the page editor and customize the map to your liking.

3. Below, you’ll see a map that you’ll need to adjust. Click on the place where you want to show a marker on the map. It will generate the map latitude and longitude based on where you placed the marker.

4. The last step is saving your marker and generating the shortcode.

Google Maps Alternatives Last Step

5. You’ll see a shortcode above the button.

6. Copy it to be able to add it to the page in the Elementor editor.

7. Once you’ve copied the shortcode, you can go and edit the page with Elementor.

8. Look for the “Shortcode” widget in the Elementor editor.

Google Maps Alternatives Elementor Editor

9. Drag it to the page and paste the OSM shortcode you copied in the previous step.

10. You’ll see the map as you styled it. Here is the result you’ll see on the frontend:

Google Maps Alternatives Result

Wrapping Up

Open Street Maps and MapBox are fantastic free plugins for placing detailed, interactive maps on your website. If you take the time to read the instructions for the plugins, you’ll find that they are a useful way of enhancing any post or page.

Extend Elementor like a pro: Creating a new extension in Elementor

Creating a New Extension Featured Image

Elementor is a powerful drag and drop page builder that allows us to create pages conveniently. One of Elementor’s greatest features is extendibility. With this feature, we can build custom widgets/controls via creating a new extension in Elementor.

This extension implements object-oriented programming in which a main class and extra classes for smaller parts like custom Elementor Widgets or any other components are used.

Plugin Structure

The main plugin should have basic information about the extensions, to check basic requirements and to load the required files to activate the plugin functionality. In the following sections, we’ll take a deep dive into each part of the plugin.

Defining Variable

Variables are used to store information to be referenced and manipulated in a computer program.

In the main class, we must define three constants like:

  • VERSION: store the version of our plugin.
  • MINIMUM_ELEMENTOR_VERSION: store the essential version of Elementor.
  • MINIMUM_PHP_VERSION: store the PHP version used in the plugin.
const VERSION;
const MINIMUM_ELEMENTOR_VERSION;
const MINIMUM_PHP_VERSION;

Single Instance

The singleton pattern is used to restrict the instantiation of a class to a single object, which can be useful when only one object is required across the system.

When creating a new extension in Elementor, we can only have one instance of the main class. To do this, we use a singleton pattern. In this pattern, we must define a private static variable and public static function.

private static $_instance = null;

	public static function instance() {
            //check $_instance is null or not
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}
		return self::$_instance;

	}

Constructor

The Constructor or magic function is a special type of function that is automatically executed after a class is created or instantiated. Usually, the constructor starts with two underscore characters.

In the main class, the role of the constructor is to load localization functionality and initiate the plugin.

public function __construct() {

		add_action( 'init', [ $this, 'i18n' ] );
		add_action( 'plugins_loaded', [ $this, 'init' ] );

	}
public function i18n() {
		load_plugin_textdomain( 'our-plugin-name' );
	}
public function init() {
		// Plugin logic here...
	}

Check if Elementor is Installed

As the plugin extends Elementor functionality, you should first check whether Elementor is installed and activated before the main class loads.

If Elementor is activated, the main class will load. If it’s not activated, an admin notice will be displayed and the functionality won’t continue loading. This check must be done in the initialization stage of the main class.

public function init() {

		// Check if Elementor installed and activated
		if ( ! did_action( 'elementor/loaded' ) ) {
			add_action( 'admin_notices', [ $this, 'admin_notice_missing_main_plugin' ] );
			return;
		}

	}

	public function admin_notice_missing_main_plugin() {

		if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

		$message = sprintf(
			/* translators: 1: Our plugin name 2: Elementor */
			esc_html__( '"%1$s" requires "%2$s" to be installed and activated.', 'our-plugin-name' ),
			'<strong>' . esc_html__( 'Elementor our-plugin-name', 'our-plugin-name' ) . '</strong>',
			'<strong>' . esc_html__( 'Elementor', 'our-plugin-name' ) . '</strong>'
		);

		printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

	}

Check the Version of Elementor

After checking whether or not Elementor is installed, we must check the Elementor version for backward compatibility with older Elementor versions. If the defined minimum version of our plugin is not compatible with the installed version of Elementor, then the admin message will be displayed, and functionality will not be able to load.
This check is done in the initialisation stage of the main class.

const MINIMUM_ELEMENTOR_VERSION = '2.5.11';

	public function init() {

		// Check for required Elementor version
		if ( ! version_compare( ELEMENTOR_VERSION, self::MINIMUM_ELEMENTOR_VERSION, '>=' ) ) {
			add_action( 'admin_notices', [ $this, 'admin_notice_minimum_elementor_version' ] );
			return;
		}

	}

	public function admin_notice_minimum_elementor_version() {

		if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

		$message = sprintf(
			/* translators: 1: Our plugin name 2: Elementor 3: Required Elementor version */
			esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'our-plugin-name' ),
			'<strong>' . esc_html__( 'Elementor our-plugin-name', 'our-plugin-name' ) . '</strong>',
			'<strong>' . esc_html__( 'Elementor', 'our-plugin-name' ) . '</strong>',
			 self::MINIMUM_ELEMENTOR_VERSION
		);

		printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

	}

Check for the PHP Version

Finally, we must check our extension’s minimum PHP version, which . must be newer than the PHP version of the Elementor plugin. If there’s an older version, then the admin message will be displayed, and the functionality won’t load.

const MINIMUM_PHP_VERSION = '7.0';

	public function init() {

		// Check for required PHP version
		if ( version_compare( PHP_VERSION, self::MINIMUM_PHP_VERSION, '<' ) ) {
			add_action( 'admin_notices', [ $this, 'admin_notice_minimum_php_version' ] );
			return;
		}

	}

	public function admin_notice_minimum_php_version() {

		if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

		$message = sprintf(
			/* translators: 1: Our plugin name 2: PHP 3: Required PHP version */
			esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'our-plugin-name' ),
			'<strong>' . esc_html__( 'Elementor our-plugin-name', 'extension-name' ) . '</strong>',
			'<strong>' . esc_html__( 'PHP', 'our-plugin-name' ) . '</strong>',
			 self::MINIMUM_PHP_VERSION
		);

		printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

	}

Including Essential Files to Correctly Create a New Extension

After completing all checks, the extension must load essential files like widgets and controls in order for it to run correctly.

public function init() {

		// Add Plugin actions
		add_action( 'elementor/widgets/widgets_registered', [ $this, 'init_widgets' ] );
		add_action( 'elementor/controls/controls_registered', [ $this, 'init_controls' ] );
	}

	public function init_widgets() {

		// Include Widget files
		require_once( __DIR__ . '/widgets/our-plugin-name-widget.php' );

		// Register widget
		\Elementor\Plugin::instance()->widgets_manager->register_widget_type( new \Elementor_extension_Widget() );

	}

	public function init_controls() {

		// Include Control files
		require_once( __DIR__ . '/controls/our-plugin-name-control.php' );

		// Register control
		\Elementor\Plugin::$instance->controls_manager->register_control( 'control-type-', new \extension_Control() );

	}

Workflow Diagram

Create a New Extension - Workflow Diagram

In the end, if we want to create our extension named Spicy, we must have the following code in its entirety.

<?php
 /**
 * Plugin Name: Spicy Extension
 * Description: Custom Elementor extension.
 * Plugin URI:  https://spicy.test/
 * Version:     1.0.0
 * Author:      Spicy
 * Author URI:  https://spicy.test/
 * Text Domain: spicy-extension
 */

	if ( ! defined( 'ABSPATH' ) ) {
		exit; // Exit if accessed directly.
	}

	/**
	 * Main Spicy Extension Class
	 *
	 * The main class that initiates and runs the plugin.
	 *
	 * @since 1.0.0
	 */
	final class Spicy_Extension {

		/**
		 * Plugin Version
		 *
		 * @since 1.0.0
		 *
		 * @var string The plugin version.
		 */
		const VERSION = '1.0.0';

		/**
		 * Minimum Elementor Version
		 *
		 * @since 1.0.0
		 *
		 * @var string Minimum Elementor version required to run the plugin.
		 */
		const MINIMUM_ELEMENTOR_VERSION = '2.5.11';

		/**
		 * Minimum PHP Version
		 *
		 * @since 1.0.0
		 *
		 * @var string Minimum PHP version required to run the plugin.
		*/
		const MINIMUM_PHP_VERSION = '6.0';

		/**
		 * Instance
		 *
		 * @since 1.0.0
		 *
		 * @access private
		 * @static
		 *
		 * @var Spicy_Extension The single instance of the class.
		 */
		private static $_instance = null;

		/**
		 * Instance
		 *
		 * Ensures only one instance of the class is loaded or can be loaded.
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 * @static
		 *
		 * @return Spicy_Extension An instance of the class.
		 */
		public static function instance() {

			if ( is_null( self::$_instance ) ) {
				self::$_instance = new self();
			}

		 	return self::$_instance;
		}

		/**
		 * Constructor
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 */
		
		public function __construct() {	
			add_action( 'init', [ $this, 'i18n' ] );
			add_action( 'plugins_loaded', [ $this, 'init' ] );
		}

		/**
		 * Load Textdomain
		 *
		 * Load plugin localization files.
		 *
		 * Fired by `init` action hook.
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 */
		public function i18n(){}

		/**
		 * Initialize the plugin
		 *
		 * Load the plugin only after Elementor (and other plugins) are loaded.
		 * Checks for basic plugin requirements, if one check fail don't continue,
		 * if all check have passed load the files required to run the plugin.
		 *
		 * Fired by `plugins_loaded` action hook.
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 */
		public function init() {

			// Check if Elementor installed and activated
			if ( ! did_action( 'elementor/loaded' ) ) {
				add_action( 'admin_notices', [ $this, 'admin_notice_missing_main_plugin' ] );
				return;
			}

			// Check for required Elementor version			
			if ( ! version_compare( ELEMENTOR_VERSION, self::MINIMUM_ELEMENTOR_VERSION, '>=' ) ) {
				add_action( 'admin_notices', [ $this, 'admin_notice_minimum_elementor_version' ] );
				return;
			}

			// Check for required PHP version
			if ( version_compare( PHP_VERSION, self::MINIMUM_PHP_VERSION, '<' ) ) {
				add_action( 'admin_notices', [ $this, 'admin_notice_minimum_php_version' ] );
				return;
			}

			// Add Plugin actions
			add_action( 'elementor/widgets/widgets_registered', [ $this, 'init_widgets' ] );
			add_action( 'elementor/controls/controls_registered', [ $this, 'init_controls' ] );
			
			// Register Widget Styles
			add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'widget_styles' ] );

		}

		public function widget_styles() {
			//For Example
			//wp_enqueue_style( 'spicyPluginStylesheet', plugins_url( '/css/gallery.css', __FILE__ ) );
		}

		/**
		 * Admin notice
		 *
		 * Warning when the site doesn't have Elementor installed or activated.
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 */
		public function admin_notice_missing_main_plugin() {

			if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

			$message = sprintf(
				/* translators: 1: Plugin name 2: Elementor */
				esc_html__( '"%1$s" requires "%2$s" to be installed and activated.', 'Spicy-extension' ),
				'<strong>' . esc_html__( 'Elementor Spicy Extension', 'Spicy-extension' ) . '</strong>',
				'<strong>' . esc_html__( 'Elementor', 'Spicy-extension' ) . '</strong>'
			);		

			printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

		}

		/**
		 * Admin notice
		 *
		 * Warning when the site doesn't have a minimum required Elementor version.
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 */
		public function admin_notice_minimum_elementor_version() {

			if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

			$message = sprintf(
				/* translators: 1: Plugin name 2: Elementor 3: Required Elementor version */
				esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'Spicy-extension' ),
				'<strong>' . esc_html__( 'Elementor Spicy Extension', 'Spicy-extension' ) . '</strong>',
				'<strong>' . esc_html__( 'Elementor', 'Spicy-extension' ) . '</strong>',
				self::MINIMUM_ELEMENTOR_VERSION
			);

			printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

		}

		/**
		 * Admin notice
		 *
		 * Warning when the site doesn't have a minimum required PHP version.
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 */
		public function admin_notice_minimum_php_version() {		

			if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

			$message = sprintf(
				/* translators: 1: Plugin name 2: PHP 3: Required PHP version */
				esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'Spicy-extension' ),
				'<strong>' . esc_html__( 'Elementor Spicy Extension', 'Spicy-extension' ) . '</strong>',
				'<strong>' . esc_html__( 'PHP', 'Spicy-extension' ) . '</strong>',
				self::MINIMUM_PHP_VERSION
			);

			printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

		}

		/**
		 * Init Widgets
		 *
		 * Include widgets files and register them
		 *
		 * @since 1.0.0
		 *
		 * @access public
		 */
		public function init_widgets() {
			 // For Example
			// Include Widget files
			//require_once( __DIR__ . '/widgets/gallery.php' );

			// Register widget
			//\Elementor\Plugin::instance()->widgets_manager->register_widget_type( new \spicy_oEmbed_Widget() );
			//\Elementor\Plugin::instance()->widgets_manager->register_widget_type( new \spicy_gallery_Widget() );

		}

		/*
		 * Init Controls
		 *
		 * Include controls files and register them
		 *
		 * @since 1.0.0				
		 *
		 * @access public
		*/
		public function init_controls() {
			//For example
			
			//Include Control files
			//require_once( __DIR__ . '/controls/multi-unit.php' );

			// Register control
		    //\Elementor\Plugin::$instance->controls_manager->register_control( 'spicy-multi-unit-control', new spicy_multi_unit());

		}

    }

spicy_Extension::instance();

Also, you can download the entire code by clicking on this link.

Conclusion

In this article, we went into depth to illustrate the basic structure of the plugin that extends the functionality of Elementor. Also, we explained each essential part of the plugin code like Variable, Single Instance, Constructor, Checking steps and Include files. Finally, we included the entire code for the Spicy plugin.

We’d love to hear from you! Feel free to drop us a comment to share your experiences and ideas.

Create a scrollable tab like the WebFlow website using Jupiter X

Scrollable Tabs Post Featured Image

One way to provide visitors to your website with a seamless experience is through creating a scrollable parallax tab similar to the WebFlow.io homepage. Creating a scrollable parallax tab will allow users to access much of your site’s content as soon as they land on your homepage.

Many of our users asked about how to go about building a scrollable tab, and we’re here to answer! And what’s even better is that the Jupiter X theme has endless possibilities that can help you create a similar tab (as seen below) by using a simple trick. If you’re also curious about how you can build this amazing tab using Jupiter X, read this article to the end.

WebFlow sample scrollable tab.

What we need to create a scrollable tab:

  • Jupiter X Pro theme and its Elementor page builder
  • Jet Tricks from the Jupiter X bundled plugins
  • Raven, an exclusive Artbees plugin to extend the functionality of Elementor

First of all, allow me to briefly explain the whole process. We won’t use any tab elements to represent this. Instead, we’ll use the Raven Navigation Menu element and anchor links (#tab1, #tab2 …) as the tab titles. Then, we’ll use multiple sections that have the same ID as the anchor links (so when you click on the menu items, scroll to those sections).

And in the end, we’ll add the Sticky effect to the column container of the menu navigation element using the Jet Tricks plugin. Then, we’ll proceed to write a custom CSS snippet to add a transition to the menu items and make them bigger when they are active. Before starting, make sure you’ve already activated the above plugins from Jupiter X -> Control Panel -> plugins.

So, let’s start by building our menus. Navigate to Appearance -> Menus and create a new menu. Then add your Custom Link items. Remember to use the anchor links like #tab1, #tab2 … as the menu item link.

Add menu items with anchor link hashtags to be considered as Tab titles.

We are now done with this part of the process. Let’s create a page, and do the rest. From the Pages -> Add New, create a new page and start editing with Elementor.

Edit the page with Elementor.

In Elementor, drop a Section into your page, and divide it into two columns. Then drop a Navigation menu to your left column, and add a CSS class to the navigation menu.

Scrollable Tab Screenshot 3 - Add a CSS class to the menu in order to avoid conflict while wiring CSS snippets.
Add a CSS class to the menu in order to avoid conflict while wiring CSS snippets.

The next step is to add a custom CSS to make each menu stay in one line and also to enlarge them when they are active. So, from the page settings (bottom left corner of the page), choose the Advanced tab and then add the following CSS snippet in the Custom CSS section (JX).

/* Add Transition to the items */
.custom_tab_titles li a {transition: 0.2s all;}

/*make the items bigger when they are active while having transitions */
.custom_tab_titles li .raven-menu-item-active {transition: 0.2s all;
    transform: scale(1.3); margin-left: 0.8em;}
    
/* put each menu in one line */
.custom_tab_titles li {clear: both; display: block; width: 100%;}
Scrollable Tab Screenshot 4 - Add CSS snippet to make the menu items vertically aligned and add transition to them on mouse hover.
Add CSS snippet to make the menu items vertically aligned and add transition to them on mouse hover.

Now add some Inner Section elements to your other column. We need to assign an ID equivalent to the menu anchors in order to make them scrollable when clicked.

Scrollable Tab Screenshot 5 - Add a different ID to each inner section equivalent to each anchor link hashtag
Add a different ID to each inner section equivalent to each anchor link hashtag.

Add as much of your content as you want to your scrollable tabs. Here, I kept it empty in order to make it more understandable. I also added a min-height 400px to each inner section. You can avoid it or add more height. The styling part completely customizable, and you can do what you want with it.

The last step is selecting the Column container of the Navigation menu and adding the Sticky behavior to it.

Scrollable Tab Screenshot 6 -
Follow the steps in order to enable the sticky option for the navigation menu. It will be considered as the Tab titles later on.

I also added some typography settings and color changes to the navigation menu in order to make the scrollable tab more eye-catching. Take a look at what we have now:

Scrollable Tab Gif 2 - The scrollable tab made by Jupiter X and Elementor.
The scrollable tab made by Jupiter X and Elementor.

One of the great things about using Jupiter X to create a scrollable tab is that you have the flexibility to create a tab exactly to your liking. You have the option of adjusting the margins and paddings to fine tune the tab, as well as to style every corner of your new tab.

Additionally, you’re not limited by how many tabs you can have: you are free to add more and style them in any way you see fit. Don’t worry about getting carried away in adding too many new elements as this has been tested on all modern browsers, and it’s compatible with all of them.

In this blog post, we’ve provided you with the details on how to create a tailor-made scrollable parallax tab, similar to what can be seen on the WebFlow home. We also illustrated how to create this awesome tab with Jupiter X Pro (and the Elementor page builder), Jet Tricks and Raven.

Do not hesitate to ask any questions you may have in the comments below.

Different Ways to Add Custom Code Snippets in WordPress

Custom Code Snippets in WordPress Featured Image

Used by more than 60 million websites, WordPress is a popular, powerful and flexible Content Management System (CMS). One of WordPress’ valuable features is its extensibility architecture that allows users to expand WordPress features via plugins. In many cases, site owners need custom codes to improve the functionality of their website. In this way, custom code snippets plugins in WordPress can be a handy tool.

Sometimes when surfing the internet, we come across articles that explain how to add custom code snippets to the template files like index.php, footer.php or edit function.php files. These methods aren’t safe or recommended.

There are only two safe methods to add custom code snippets in WordPress:

  • Using plugins
  • Using the child theme

Adding Custom Code Snippets in WordPress Using Plugins

There are some plugins that allow you to add custom PHP, HTML, CSS and JavaScript codes in WordPress. In this article, we try to cover some of them with examples. Some of the plugins are listed below.

Insert the PHP Code Snippets Plugin

Custom Code Snippets in WordPress - Insert PHP Code Snippet

Using this plugin, we can add our PHP code conveniently to our pages, posts and widgets.

Features

  • Convert PHP snippets to shortcodes.
  • Insert PHP code easily using a shortcode.
  • Support for PHP snippet shortcodes in widgets.
  • Dropdown menu in TinyMCE editor to easily select snippet shortcodes.

Example

In this example, we want to display the number of content words in a post/page after a post or page.

1. After installing this plugin, click on PHPCode Snippet from the left sidebar of the admin page.

Custom Code Snippets in WordPress - PHP Code Snippets

2. On the new screen, click on the Add New PHP Code Snippet button.

Custom Code Snippets in WordPress - PHP Code Snippets 2

3. Set

  • Tracking Name: words-count
  • PHP code (this code displays the words count for a page or content post)
<?php

  function word_count() {
       $content = get_post_field( 'post_content', get_the_ID());
       $word_count = str_word_count( strip_tags( $content ) );
       return $word_count;
    }

  echo 'Words:', '  ' , word_count();

?>
Custom Code Snippets in WordPress - PHP Code Snippets 3

4. Click on the Create/Update button.

5. The plugin generates a shortcode as [xyz-ips snippet=”words-count”].

Custom Code Snippets in WordPress - PHP Code Snippets 4

6. Go to Posts > Add New. At the end of the text, insert the above shortcode.

Custom Code Snippets in WordPress - PHP Code Snippets 5

7. After publishing the post, we can see the number of words in the post.

Insert the HTML Snippet Plugin

custom code snippets in WordPress - Insert HTML Snippet

Inserting the HTML Snippet allows us to create shortcodes corresponding to HTML snippets. We can create a shortcode corresponding to any random HTML code such as JavaScript codes, video embedding codes, CSS codes, among others and use the same in posts, pages or widgets.

Features

  • Convert HTML snippets to shortcodes.
  • Convert Javascript codes to shortcodes.
  • Convert CSS codes to shortcodes.
  • Support for snippet shortcodes in widgets.
  • Dropdown menu in TinyMCE editor to pick snippet shortcodes easily.
  • Insert Adsense or any add codes.
  • Insert flash, videos, etc. to your posts, pages, and widgets.

Example

In this example, we want to generate a Google Translate button after our post.

1. Install the plugin, and go to XYZ HTML > HTML Snippets.

Custom Code Snippets in WordPress - HTML Code Snippets 1

2. On the new screen, click on the Add new HTML Snippet button.

Custom Code Snippets in WordPress - HTML Code Snippets 2

3. Set

  • Tracking Name: translate
  • HTML Code (this code generates the Google Translate button)
<div id="google_translate_element"></div>

<script type="text/javascript">
function googleTranslateElementInit() {
  new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element');
}
</script>

<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>

4. Click on the Create button.

Custom Code Snippets in WordPress - HTML Code Snippets 3

5. The plugin will generate the shortcode as [xyz-ihs snippet=”translate”].

Custom Code Snippets in WordPress - HTML Code Snippets 4

6. Go to Posts > Add New. Set the title and content the add [xyz-ihs snippet=”translate”] at the end of the post.

Custom Code Snippets in WordPress - HTML Code Snippets 5

7. Publish the post, and you will be able to see the Google Translate button after the post.

Custom Code Snippets in WordPress - HTML Code Snippets 6

Simple Custom CSS and JS Plugin

Custom code snippets in WordPress - Custom Css

Customizing your WordPress site’s appearance can easily be done by adding custom CSS and JS code without modifying the theme or plugin files.

Features

  • Text editor with syntax highlighting.
  • Print the code inline or include it into an external file.
  • Print the code in the header or the footer.
  • Add CSS or JS to the frontend or the admin side.
  • Add as many codes as you want.
  • Keep your changes when you change the theme.

Example

In this example, we want to change the background color of the admin bar with the CSS snippet.

1. Install the plugin and go to Custom CSS & JS > Add Custom CSS.

Custom Code Snippets - Custom CSS 1

2. On the new screen, in the options section, check the Internal, Header, In Admin radio button and set the following:

  • Title : admin-bar-background-color
  • Code (code change background color of admin bar in the admin page)
#wpadminbar {
    background-color: rebeccapurple;
}
Custom Code Snippets in WordPress - Custom CSS 2

3. Click on the Publish button. You’ll be able to see that the admin bar background menu changed.

Custom Code Snippets in WordPress - Custom CSS 3

Code Snippets Plugin

Custom Code Snippets in WordPress - Code Snippets Plugin Banner

This is a powerful, simple and handy plugin that lets us add our PHP, HTML, CSS and JavaScript snippets to our websites.

Features

  • Providing a GUI interface.
  • Snippets can be activated and deactivated.
  • Categorize snippets with tags.
  • Snippets can be exported for transfer to another site.
  • Full-featured code editor.

Example #1

In this example, we want to disable standard widgets like Archives, Recent Posts, Recent Comments with the simple PHP snippet. The default page is similar to the image below:

Custom Code Snippets in WordPress - Code Snippets Plugin 1

1. Install the plugin, and go to Snippets > Add New.

Custom Code Snippets in WordPress - Code Snippets Plugin 2

2. On the new screen, set:

  • Title: Remove standard widget
  • Code (Remove Archives, Recent Posts, Recent Comments from the right sidebar of the homepage).
function unregister_default_wp_widgets() { 

    unregister_widget('WP_Widget_Archives'); 
    unregister_widget('WP_Widget_Recent_Posts'); 
    unregister_widget('WP_Widget_Recent_Comments'); 
}

add_action( 'widgets_init', 'unregister_default_wp_widgets', 1 ); 

3. Save and activate the snippet.

Custom Code Snippets in WordPress - Code Snippets Plugin 3

4. After reloading the homepage, you’ll be able to see that the Archives, Recent Posts, Recent Comments have been removed.

Custom Code Snippets in WordPress - Code Snippets Plugin 4

Example #2

In this example, we want to change the font size of the post with the JavaScript code.

1. Go to Snippets > Add New.

2. Set

  • Title: change the font size
  • Code ( Increase the font size when clicking on the post text and decrease font size when holding down the SHIFT key and clicking.)
add_action( 'wp_head', function () { ?>

<script        src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">    </script>

    <script>	
    $(document).ready(function(){
    $(".jupiterx-post-content").click(function(){
        if (event.shiftKey) {
            $(this).css({"font-size": "-=10%"});  
        } else {
            $(this).css({"font-size": "+=10%"});
        }
    });

  });

  </script>

<?php } );

3. Check the Only run on site front-end radio button and save it.

Custom Code Snippets in WordPress - Code Snippets Plugin 5

At the end, when clicking on the post text, the font size will have been changed.

Custom Code Snippets in WordPress - Code Snippets Plugin 6

Adding Custom Code Snippets in WordPress Using Child Theme

In WordPress, a child theme is a sub-theme that inherits all the functionality, style and features from the parent theme. The child theme is a safe way to change or modify the parent theme without modifying parent theme files.

Example

Let’s add our default content to the WordPress editor.

Our default content: “This is some custom content. I’m adding it to the post editor because I hate re-typing it.”

1. Active the child theme on your site (for more information, read this article.)

2. Go to Appearance > Editor.

Custom Code Snippets in WordPress - Child Theme 1

3. Open the functions.php file.

Custom Code Snippets in WordPress - Child Theme 2

4. Add the below code at the end of functions.php, then update it.

add_filter( 'default_content', 'my_editor_content' ); 

  function my_editor_content( $content ) { 
    $content = "This is some custom content I'm adding to the post editor  because I hate re-typing it."; 
 
    return $content;
}
Custom Code Snippets in WordPress - Child Theme 3

5. After modifying functions.php, go to Posts > Add New or Pages > Add New. You’ll be able to see that our default text has been added to the editor.

Custom Code Snippets in WordPress - Child Theme 4

Conclusion

In this article, we first introduced several plugins for adding custom code snippets in WordPress. We also included some examples on how to use HTML, CSS, JavaScript and PHP snippets using the plugins.

Finally, we showed how to add custom code snippets in WordPress with the child theme. Feel free to share your experience with us in the comments.

More Than a Block Editor: Pros and Cons of WordPress 5.0

The new version of WordPress was already released in the market on the 27th of November 2018 and advanced editor for the CMS system called Gutenberg was also published on the same day. The newly released WordPress 5.0 is given the name ‘Bebo’ after the Cuban jazz composer Bebo Valdes.

Here, you will get to know about the pros and cons of WordPress 5.0 block editor. While recognizing the leading pros and cons of WordPress 5.0 block editor, you will be able to use the CMS more conveniently. As WordPress is one of the leading CMS platforms in the world, it is remarkable how the new version can be more attractive to users.

When it comes to the statistics, WordPress is backed by a prominent position. In a report by the W3 techs, WordPress holds a significant market share of 58.55%. This market share is much more significant than other CMS systems like Joomla and Drupal combined.

Meanwhile, Netcraft published a recent report which shows that WordPress dominates over nearly 27% of the entire internet. This data implies that over 20% of websites present on the internet in self-hosted style are built with WordPress.

In such a scenario, you can be sure that the latest update can help a large number of web developers. With the latest WordPress features, you can comfortably carry out the necessary tasks related to the web building process.

The Pros and Cons of WordPress 5.0 with the Gutenberg Block Editor

Pros

  • Better visualization for faster work

As we all know, Gutenberg is a block editor; thus, it can provide a more convenient display to the users. As a user, you can prominently use your creativity. You need not worry about the functionality of the site much while creating the web pages.

Pros and Cons of WordPress 5.0 Pro 1
  • The minimized dependency of TinyMCE

The new WordPress 5.0 version beside the block editor has a much lesser dependence on the TinyMCE. The TinyMCE is one of the online rich-text editors through which the earlier WordPress editor used to convert the HTML. In WordPress 5.0, the block editor is meant to deliver better integration of the plug-in’s cores and themes.

With the new Gutenberg editor, you can get a speedy editing experience as there is less need to visit the TinyMCE. As a result, there is a distinct chance of completing the work related to the page makeup faster.

  • All the benefits of Medium Editor are present

There is good news for most web developers who have earlier used the Medium Editor and worked conveniently in the WordPress. The Gutenberg editor contains similar benefits as the Medium Editor and gives the user a chance to create any content easily.

Thus, by the Bebo version of WordPress, the users can have full control over the content they are creating. One can also get total access to third-party tools whenever necessary.

  • Gadget-Friendly

While discussing the pros and cons of the WordPress 5.0 Gutenberg Editor, the central positive fact we came across is its gadget-friendliness. The interface you get is efficiently gadget-friendly. You can quickly work with this interface in tablets, smartphones, or laptops, as well as the traditional desktops.

Pros and Cons of WordPress 5.0 Pro Gadget
  • Friendly to the Users

You should be aware that user-friendliness is one of the leading pros that older versions of WordPress have forever possessed. Now, the latest version with the WordPress 5.0 Gutenberg Editor is easier to use. So, you should always consider the fact that the new version has better usability along with the Block Editor.

Cons

  • Compatibility Issues

As WordPress provides the benefits of working with numerous plug-ins, it is essential for the editing system to be compatible with them. The main con of the WordPress Bebo version is that it might not work well with several themes and plug-ins.

Moreover, the Gutenberg editor demands more work from the end of the developer. This happens due to the decreased use of TinyMCE. However, all the updates that will be made later can improve the backward situation of the compatibility of the editor.

  • No Full Meta Box Support

In the case of the Beta version of the Gutenberg, you cannot get many essential components of the Meta box. This is another con which might ruin your convenience of working with the WordPress 5.0 version. The only good thing that the Gutenberg editing system has is the Yoast SEO support. There is a prominent expectation that other Meta boxes might work efficiently with Gutenberg in the future.

Pros and Cons of WordPress 5.0 Con 1
  • No Markdown Support

However, working with WordPress is beneficial in many ways; the Gutenberg review might spoil the markdown support. The WordPress Bebo beside that block editor has a prominent con as Markdown is absent. It is a markup language of the lightweight with the ugly test syntax.

If you are the one who has so far used the Markdown language, there might be some problems in getting accustomed to the Gutenberg editor. You should nevertheless expect that the compatibility to the Markdown language will be added shortly.

  • Bad Accessibility

You must be aware that the Gutenberg Editor that comes with the WordPress Bebo is hard to access. In this editor, you cannot find the API that the CRM earlier used to rely upon for building the plug-ins as well as the themes.

So, these are some of the pros and cons of WordPress 5.0 along with the Gutenberg editor. You should always incorporate it only after thoroughly researching the worthiness of the WordPress Bebo. In case you have lighter jobs to do, and you are a beginner, the 5.0 version is best for you.

Verdict

In spite of all its shortcomings, you should be aware that the latest WordPress is the future. The CRM developers are trying their best to make the WordPress Bebo the best among all the versions available so far. You should also expect a quick road to perfection given the position which WordPress holds in the CRM market.

How To Create WordPress Custom Admin Pages

WordPress, the world’s most popular CMS is also quite beloved by developers. Among many of its possible customizations and flexibilities that can be pointed out is extending the admin side of WordPress. In this post, we will show you how to use WordPress custom admin pages to bring more options for the user.

What is WordPress Custom Admin Pages?

The WordPress admin dashboard is the first page you’ll see after logging in. Using the side menu, you can navigate to other admin pages like Appearance, Plugins, Settings, Users, etc.

You may also see new menu items after activating a theme or a plugin that redirects you to a new admin page. It can be a settings page for the plugin, control panel of your theme, a page to show the status of your site or even a document page. The custom admin page is a very helpful feature which allows the developer to extend admin rights with new options.

How to Add WordPress custom Admin Pages

In order to add a custom admin page in WordPress, we need 2 things:

  1. An admin menu (add_menu_page function)
  2. Page content (custom function)

In order to add a new admin menu item, we can use the following function:

add_menu_page( string $page_title, 
string $menu_title, string $capability, 
string $menu_slug, callable $function = '', 
string $icon_url = '', int $position = null )

Let’s dive into each item to learn what they are.

1. $page_title The text to be displayed in the title tags of the page when the menu is selected. Choose a meaningful page title. For example, if your custom admin page is an options page for the plugin, it could be “My plugin options”. Note that it should be translatable. So use _ function like the following example: _( ‘My Plugin Options’, ‘my-plugin-textdomain‘)

2. $menu_title The text to be used for the menu.

3. $capability The capability required for this menu to be displayed to the user. For example, if it contains some general options for the site, manage_option could be the best choice. Just set it carefully to avoid any possible security issue.

Check out the WordPress Roles and Capabilities page and see what the proper capability is for your custom admin page.

4. $menu_slug The slug name that refers to this menu. It should be unique for this menu page and only include lowercase alphanumeric, dashes, and underscores to be compatible with sanitize_key(). This will be used as a parameter in the URL of your custom admin page as it’s shown in the picture.

5. $function The function to be called to show the output content for this page. For a simple example, we can use the following code to show a header in the admin page:

function my_admin_page_contents() {
	?>
		<h1>
			<?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' );
		</h1>
	<?php
}

6. $icon_url The URL of the icon to be used for this menu. You can use an image, encoded SVG, or dash icons.

  • In order to use an image, simply pass the URL of the image.
  • If you want to have an icon like WordPress defaults, which has a different color on hover, you can pass an encoded SVG file. The http://b64.io/ can convert your SVG file to base64 encoded data. After uploading your SVG, simply copy the link that starts with data:image/svg+xml;base64, and paste it.
  • You can use existing WordPress icons. Find a proper icon from WordPress Dashicons page and pass the class name like dashicons-schedule as icon URL argument.
  • Also, you can use none value to leave div.wp-menu-image empty, so an icon can be added via CSS.

7. $position The position in the menu order should appear. Here is the list of numbers of default admin menus:

  • 2 – Dashboard
  • 4 – Separator
  • 5 – Posts
  • 10 – Media
  • 15 – Links
  • 20 – Pages
  • 25 – Comments
  • 59 – Separator
  • 60 – Appearance
  • 65 – Plugins
  • 70 – Users
  • 75 – Tools
  • 80 – Settings
  • 99 – Separator

So, if you want to show your menu after Dashboard, you should use 3.

In the following table, you can see a piece of brief information about each item.

Add_menu_page arguments

WordPress Custom Admin Pages Arguments
WordPress Custom Admin Pages 1

Putting it all together, you’ll have:

function my_admin_menu() {
		add_menu_page(
			__( 'Sample page', 'my-textdomain' ),
			__( 'Sample menu', 'my-textdomain' ),
			'manage_options',
			'sample-page',
			'my_admin_page_contents',
			'dashicons-schedule',
			3
		);
	}

	add_action( 'admin_menu', 'my_admin_menu' );


	function my_admin_page_contents() {
		?>
			<h1>
				<?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' ); ?>
			</h1>
		<?php
	}

You should know that it is possible to add a submenu to existing menus or newly added menu using the following functions:

  • add_posts_page Adds a submenu under Posts menu
  • add_pages_page Adds a submenu under Pages menu
  • add_media_page Adds a submenu under Media menu
  • add_comments_page Adds a submenu under Comments menu
  • add_theme_page Adds a submenu under the Appearance menu
  • add_plugin_page Adds a submenu under Plugins menu
  • add_users_page Adds a submenu under Users menu
  • add_management_page Adds a submenu under Tools menu
  • add_options_page Adds a submenu under Settings menu

And all of them are a wrapper of add_submenu_page function, so we use them in the same way:

add_submenu_page( string $parent_slug, string $page_title, 
string $menu_title, string $capability, 
string $menu_slug, callable $function = '' );

And that’s it. We have a custom admin page. But, what about adding custom styles and scripts for its content?

Adding Styles and Scripts to WordPress Custom Admin Pages

Let’s see how we can put styles after adding page content:

function load_custom_wp_admin_style($hook) {
	// Load only on ?page=mypluginname
	if( $hook != 'toplevel_page_mypluginname' ) {
		 return;
	}
	wp_enqueue_style( 'custom_wp_admin_css', 
plugins_url('admin-style.css', __FILE__) );
}
add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

The above code will load admin-styles.css file only in the mypluginname page. If you wonder why we should do this, the reason is that loading styles in all admin pages can cause unwanted changes in other admin pages. For example, you don’t want to change the size of texts in the dashboard.

If you’re unsure what your $hook name is, use this to determine your hook name. And then, change it to the code below.

function load_custom_wp_admin_style( $hook ) {
	wp_die( $hook );
}
add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

Note: Don’t use wp_die while you’re editing a file from the plugin editor. It can cause you to lose access to the admin page until you remove it.

You can also use default registered styles in WordPress, like this:

function load_custom_wp_admin_style( $hook ) {
	// Load only on ?page=mypluginname
	if( $hook != 'toplevel_page_mypluginname' ) {
		 return;
	}
	// Load color picker styles. 
	wp_enqueue_style( 'wp-color-picker' );
}
add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

In the above code, we are not specifying any URL for the style file because it has already been registered once, and WordPress knows it. By registering a style file, you introduce it to WordPress without loading it. And then, you can load it by using a style handler name anywhere in the code. Have a look at the following code:

function register_my_plugin_styles() {

wp_register_style( 'my-plugin', plugins_url( 'my-plugin/css/plugin.css' ) );

}



// Register style sheet.

add_action( 'admin_enqueue_scripts', 'register_my_plugin_styles' );



function load_custom_wp_admin_style($hook) {

// Load only on ?page=mypluginname

if( $hook != 'toplevel_page_mypluginname' ) {

return;

}

// Load style

wp_enqueue_style( 'my-plugin' );

}



add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

Same as above, we can load custom scripts in admin pages:



function register_my_plugin_scripts() {

wp_register_script( 'my-plugin', get_stylesheet_directory_uri() . 'https://d34b8fs2z18t5a.cloudfront.net/plugin-scripts.js', array( 'jquery' ) );

}



// Register style sheet.

add_action( 'admin_enqueue_scripts', 'register_my_plugin_scripts' );



function load_custom_wp_admin_scripts($hook) {

// Load only on ?page=mypluginname

if($hook != 'toplevel_page_mypluginname') {

return;

}

// Load style

wp_enqueue_script( 'my-plugin' );

}



add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' );

There are a lot of JavaScript libraries included in WordPress that you can use. There is also a list of default scripts included and registered by WordPress here.

Wrapping It Up in a Plugin

In this section, we put all codes in a single file, which you can install as a plugin to add new WordPress custom admin pages.

<?php

/*

Plugin Name: My custom admin page

Description: Adds a custom admin pages with sample styles and scripts.

Version: 1.0.0

Author: Artbees

Author URI: http://artbees.net

Text Domain: my-custom-admin-page

*/



function my_admin_menu() {

add_menu_page(

__( 'Sample page', 'my-textdomain' ),

__( 'Sample menu', 'my-textdomain' ),

'manage_options',

'sample-page',

'my_admin_page_contents',

'dashicons-schedule',

3

);

}



add_action( 'admin_menu', 'my_admin_menu' );



function my_admin_page_contents() {

?>

<h1>

<?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' ); ?>

</h1>

<?php

}



function register_my_plugin_scripts() {

wp_register_style( 'my-plugin', plugins_url( 'ddd/css/plugin.css' ) );

wp_register_script( 'my-plugin', plugins_url( 'ddd/js/plugin.js' ) );

}



add_action( 'admin_enqueue_scripts', 'register_my_plugin_scripts' );



function load_my_plugin_scripts( $hook ) {

// Load only on ?page=sample-page

if( $hook != 'toplevel_page_sample-page' ) {

return;

}

// Load style & scripts.

wp_enqueue_style( 'my-plugin' );

wp_enqueue_script( 'my-plugin' );

}



add_action( 'admin_enqueue_scripts', 'load_my_plugin_scripts' );

And the final result will be like this:

In the next post, we will show you how to add custom settings to WordPress Custom Admin Pages, how to process forms, and how to make them secure.

Master WordPress Language Translation: How To Translate your Jupiter X Website with WeGlot

With almost 75% of the Internet’s 4.1 billion users speaking a language other than English, WordPress language translation is a great way to expand your website’s reach and help you connect with your site’s visitors. But when it comes to creating a multilingual WordPress site, it can be difficult to know where to start.

To help, we’ve created this detailed WordPress language translation guide. First, we’ll take you through the benefits of going multilingual. Then, we’ll share a plugin to help you get the job done and show you step-by-step how to set everything up and translate your site.

Why WordPress Language Translation Matters

There are two “directions” in which WordPress language translation can make your site better. There are benefits for:

  • Your visitors, in the form of better user experience for them, while they browse your site
  • Your site, in the form of more marketing opportunities and a chance to reach new visitors

Let’s cover the visitor benefits first.

Your Visitors Prefer to Browse in Their Native Languages

As you’d expect, most people prefer to use their own native language when browsing the Internet. According to a Gallup survey commissioned by the European Commission, about 90% of those surveyed preferred to use their own language when visiting a site.

Perhaps more importantly, though, 45% of respondents in that same survey never use a language other than their own when browsing online. Now, you might be thinking this only matters if you target a global audience. But there are plenty of situations where you’ll have a multilingual audience even within the same geographic area.

For example, the US Census Bureau found that 21.6% of people ages 5 or older in the USA speak a language other than English when at home, with 40.5 million of those people speaking Spanish at home. So even if you only target the USA, a significant chunk of your visitors still might prefer a different language.

If you want to see how large that chunk is, you can get a good idea from the Languages report in the Audience area of Google Analytics:

Going Multilingual Opens Up New SEO Opportunities

WordPress language translation can also open up new opportunities for you to rank your content on Google. By translating all of your existing content, you’re essentially repurposing that same content, but for a whole new set of keywords (the same terms as before, but in a different language).

For example, if you’re using the Jupiter X Ananke template to create an eCommerce store for pet products, you might try ranking for the keyword “handmade dog toy” in Google search.

If you see that term gets 3,000 monthly searches in English, but the equivalent term in Spanish gets 1,000 monthly searches, you could increase your search visibility by 33% by creating a Spanish-language translation targeting that term.

To see how much potential SEO traffic you could gain, Google Market Finder gives you a high-level view, and most keyword research tools let you segment by language.

The Weglot Plugin Makes WordPress Language Translation Easy

Now for the next question – how can you make your WordPress site multilingual to capture those benefits? Weglot is a WordPress language translation plugin that can help you go multilingual with minimal effort.

It starts by using machine translation to translate your WordPress site as soon as you activate the plugin. Then, you can go back and have a human review those translations using the Weglot cloud dashboard.

Any edits to your translations that you make in the Weglot cloud dashboard will automatically sync with your live WordPress site. The big benefit of Weglot is convenience. Within just a few minutes, you can have a working multilingual website that your visitors can start benefiting from.

Beyond that, Weglot implements all the WordPress language translation SEO best practices to ensure that your translated content is ready to rank in Google in different languages. And Weglot also lets you place your language switcher button in a few different places on your site to create a user-friendly experience for your visitors.

Step-by-Step Guide to WordPress Language Translation With Weglot

Now that you know the “why” of WordPress language translation, here’s a step-by-step guide for how to create a multilingual site with Weglot…

Step 1: Sign Up For a Free Weglot Account

To get started, go to the Weglot registration page and create your Weglot account:

Once you register your account, Weglot will send you an activation email. After clicking the link in that email to activate your account, you’ll see a confirmation page that contains your API key (you can also go directly to your Weglot dashboard to find your API key):

Keep this API key handy because you’ll need it in the next step.

Step 2: Install Weglot Plugin and Add API Key

Go to Plugins → Add New in your WordPress dashboard and search for “Weglot”. Then, install and activate the Weglot plugin:

Once you’ve activated the Weglot WordPress language translation plugin, go to the new Weglot area in your WordPress dashboard and add your API key to the API Key box.

You should see a green checkmark appear, which means that your Jupiter X site is successfully connected to the Weglot service:

Step 3: Choose Language(s) and Activate WordPress Language Translation

Below the API Key box, you should see two other settings for:

  • Original language – this is the language that your site is currently in.
  • Destination languages – these are one or more languages into which you want to translate your site’s content.

For example, if you wanted to translate your site from English to Turkish, you’d configure it like this:

Once you’ve made your choices, click Save Changes to start the WordPress language translation process. Almost immediately, Weglot will use machine translation to translate your content and give you a working multilingual WordPress site:

Step 4: Configure Language Switcher Functionality

When you go multilingual, Weglot adds a language switcher button to the bottom-right corner of your site.

If you’d like to change that functionality, you’ll get a variety of new options in the Weglot area to do so. You can also add your language switcher as a menu item, widget, or shortcode:

Step 5: Review Translations from Weglot Dashboard

At this point, you have a working multilingual WordPress site powered by machine translation. You’ll probably want to manually manage those translations, though, in which case you’ll use the Weglot cloud dashboard.

There, you can use two interfaces to manage your translations. Both interfaces let you manage 100% of your site, including:

  • Regular post or page content
  • Jupiter X theme content
  • Elementor content

First, you can use the Visual Editor to make changes on a live preview of your site. All you do is hover over the text that you want to translate and click on the green pencil icon.

For example, if you want to translate your Jupiter X theme menu, you’d hover over it and click this icon:

That will open a popup where you can make your changes.

Second, you can use the Translations List, which offers a non-visual side-by-side view of the original text and the translated version.

You can use the filters on the left sidebar to find specific content, and you can also outsource content to professional translators from this interface:

Any changes you make in either interface will automatically sync to your live WordPress site.

Get Started With WordPress Language Translation Today

WordPress language translation is a great way to improve your WordPress site on two fronts:

  1. You can offer a better user experience by letting visitors browse your site in their native languages, which the vast majority of people prefer
  2. You can get more website visitors in the first place by ranking your translated content in Google search queries for new languages

To achieve those positives, the Weglot WordPress language translation plugin helps you translate your site in just a few minutes. Get started today!

How to Create a Guest Post Submission in WordPress

The purpose of creating a website is to introduce our business and services to reach more potential customers. In fact, the visitors to a website are the real asset of any website and one of the important factors of any good website is content. By having awesome content, you can:

  • Provide proper information about your products/services
  • Increase your ranking in search engines like Google
  • Engage visitors and convert them to customers

Creating content for a website requires lots of time and resources. With the right guest post submission technique, you can reduce your expenses and allow visitors to contribute and improve the contents of your website.

What does Guest Post Submission in WordPress Mean?

Guest post submissions, also referred to as frontend post or posting without logging in, is a technique that allows visitors to express their ideas, suggestions, tips, reviews, and ideas for your website. Using this technique, you can better engage customers on your website and allow them to help you scale your website.

There are several plugins available to help you do this. You can use one of the following plugins to create a guest post submission in WordPress:

In this article, we use AccessPress Anonymous Post for creating guest post submission in WordPress.

AccessPress Anonymous Post

This plugin is a responsive HTML5 form that allows your website users (guests/visitors/not logged in users) to submit a Standard WordPress Post and featured image in an easy and customized way.

There are two methods for creating a guest post submission form in the frontend.

  • Usage of [ap-form] shortcode.
  • Usage of < ?php echo do_shortcode( ‘[ap-form]’ );? > in a template file.

Features:

  • Submit post from frontend as a non-logged-in user or as a logged user
  • The user can customize settings
  • Category selection
  • Field selection ability
  • Mathematical captcha and Google captcha
  • Add one or more featured images to the post.
  • Add other media if the user is logged in
  • Required field selection ability
  • Email notification to admin after successful post submission
  • Using shortcode to display post submission anywhere
  • Admin will be able to review and approve the submitted post
  • HTML5 form with CSS style
  • Author’s name, author’s URL, and email will be added as a custom field
  • Option to assign a post to a specific category or let users choose a category from the frontend
  • Online support

How to Create a Guest Post Submission in WordPress Using AccessPress Anonymous Post

1. After installing and activating the plugin, you can see AccessPress Anonymous Post menu in the left sidebar of the dashboard.

2. Click on the AccessPress Anonymous Post menu to go to the settings screen.

3. In the General Settings tab, set the following settings:

Form Title: (empty because your page has a title by default)
Post-Publish Status: Draft (if we want the admin to approve the post)
Post Submission Message: Your Post was Submitted Successfully

4. In the Form Settings tab, choose the following settings:

  • Post Title: Check Show on Form and Required checkboxes.
  • Post Content: Check Show on Form and Required checkboxes.
  • Post Image: Check Show on Form checkbox.

5. In the Captcha settings tab, set the following settings, then click on the Save All Changes button.

  • Captcha Type: Mathematical Captcha
  • Captcha Label: Human Test
  • Captcha Error Message: Your answer is Incorrect.

6. Create a new page from Pages > Add New and below steps:

  • Set Title to Guest Post
  • Add Shortcode Block
  • Set the value to [ap-form]
  • Click on the Publish Button

7. Add your page to your website’s menu from Appearance > Menus.

8. Go to Guest Post page.

9. In this page, you can see the guest post submission form.

10. As you can see, the form fields have basic styling. You can add custom CSS from Customizer > Additional CSS section.

/* Fields spacing */
.ap-form-field-wrapper {
   margin-bottom: 20px;
}

/* Text fields */
.ap-form-field input[type=text] {
    padding: 10px;
    line-height: 1.5;
    color: #495057;
    background-color: #fff;
    border: 1px solid #ced4da;
    border-radius: .25rem;
}

/* Focus state of text fields */
.ap-form-field input[type=text]:focus {
    outline-width: 0;
}

/* Submit button */
.ap-form-submit-button {
    display: inline-block;
    font-weight: 400;
    text-align: center;
    border: 1px solid #0000;
    padding: 5px 13px;
    border-radius: 4px;
    color: #fff;
    background: #007bff;
    border-color: #007bff;
}

11. If a visitor submits a guest post successfully, he or she will see the value of Post Submission Message setting above the form.

12. The submitted posts are saved in your website’s database. You can see them on the dashboard as draft posts in Posts > All Posts.

Note: If you want users to publish their posts without admin approval, you can set Post Publish Status setting to Publish in the General Settings tab.

Conclusion

In this article, you learned how to create a guest post submission in WordPress with AccessPress Anonymous Post plugin. Additionally, you learned how to configure settings for the submission form.

AccessPress Anonymous Post plugin has many helpful settings to allow users to create a perfect guest post submission form. Feel free to share your experience with us about the usage of this or another plugin in the comments section.

Some Handy Elementor Plugins for Jupiter X

Elementor Plugins for Jupiter X featured image

Elementor page builder enables you to deliver high-end page designs with advanced capabilities, never before seen on WordPress. The standard and extendable nature of this plugin allow developers to create plugins to add new features to it.

Jupiter X theme is using Elementor as its default page builder. It’s also coded with standard practices so the Elementor community plugins are compatible with the theme. In this article, let’s cover some handy Elementor plugins for Jupiter X theme. The plugins are divided into two main categories:

  • Adding new widgets to Elementor
  • Extending functionalities of Elementor

Note: The compatibility of the plugins with Jupiter X theme have been tested at the time of writing this article.

HT Mega – Ultimate Addons for Elementor Page Builder

HT Mega extends Elementor with 80+ elements and 360 blocks with various styles. The live demo can show you the real usage of the elements.

Features:

  • Ability to enable/disable elements to improve performance
  • Unlimited Color and Typography options
  • Fully responsive and mobile ready
  • Cross Browser Compatible

Available Elements:

  • Team member
  • User login form
  • User register form
  • Litebox
  • Instagram
  • Twitter feed
  • Image magnifier
  • Etc.

Download here.

Premium Addons for Elementor

Premium Elementor add-ons and widgets with numerous customization options are available to extend the Elementor Page Builder capabilities and help you build impressive websites with no coding required. The live demo can show you the real usage of the elements.

Features:

  • 22+ Fully Customizable Elementor add-on widgets
  • Options panel for enabling desired widgets only for faster performance
  • Fully Responsive and Cross Browser Compatible

Available Elements:

  • Blog
  • Dual heading
  • Fancy text
  • Image separator
  • Counter
  • Modal box
  • Image button
  • And more.

Download here.

Image Hover Effects Add-on for Elementor

You can add 40+ Image hover effects with title and descriptions in a simple way, using this WordPress plugin image hover effects add-on for Elementor. The live demo can show you the real usage of the elements.

Features:

  • Easy to customize options
  • 40+ Image Hover Effects
  • Circle and Square border both come with all effects
  • Center the text horizontally
  • Control the spaces between elements

Effects:

  • Fade
  • Slide
  • Reveal
  • Push
  • Hinge
  • Flip
  • Shutter
  • Fold
  • Zoom
  • Blur

Download here.

Contact Form 7 Widget For Elementor Page Builder

This plugin adds a new element to Elementor Page Builder which helps you to easily drag and drop contact form 7 forms from a drop-down list. No need to go into your Contact Form 7 to copy the shortcode and add it to your Elementor widget anymore — simply drag and drop!

Features:

  • Add CSS directly from Elementor live preview to your contact form 7
  • Add any WordPress page as a thank you page directly from the Elementor edit screen when you add the VOID Contact Form 7 widget
  • Use single Contact Form 7 with different Style and redirect rule

Download here.

Toolbar Extras for Elementor – WordPress Admin Bar Enhanced

This plugin is a huge time saver. It enables you to have quick access to your site building resources. Using the Toolbar Extras plugin, you can add useful links to the top toolbar of your admin page and access links quickly to reduce scrolling and save time. Furthermore, with this plugin, you can access links when from the frontend.

Features:

Page Builder links: Elementor & Elementor Pro.
Links for Elementor Add-On Plugins.
Enhances the New Content section (under + New) with more links.
Support for creating an internal new Menu for Admins which hooks into the Toolbar.
Fully internationalized and translatable also for RTL language.

The main item has useful links.

This plugin enhances + New

Download here.

Custom Fonts

One of the important factors in typography is a good font. If you need to use your custom font in your website, you can use the Custom Fonts plugin. This plugin allows you to add a custom web font to Elementor font library.

Adding a Custom Font

1. To add your custom font, go to Appearance > Custom Fonts then upload your fonts. We downloaded Sonika and converted it to a web font using the Web font generator tool.

2. Use your custom font like other fonts. It’s added at the top of Fonts under Custom group.

Download here.

Custom Icons for Elementor

Elementor comes with Font Awesome icons by default and there’s no way to upload custom icons. But the Custom Icons for Elementor plugin enables you to add your custom icons to the built-in Elementor icon controls and elements.

How to Add Custom Icons

1. Select some icons in Fontello website, then download them.

2. Upload the downloaded zip file in Elementor > Custom Icons.

3. Use your custom icons.

Download here.

Elementor Blocks for Gutenberg

As you may know, Gutenberg is the default WordPress editor. But Elementor Blocks for Gutenberg allows you to easily insert any Elementor template into Gutenberg with just one click.  By using this plugin, you can benefit from both page builder features.

Add an Elementor Template in Gutenberg

1. Edit a page. Add Elementor Library block in the page, then select your template.  

2. You will see your Elementor template inside your Gutenberg page.

Download here.

Elementor Element Condition

This plugin gives you the ability to add conditions to sections and widgets so they can be shown or hidden. At the moment, it only supports two simple variables and one operator.

  • This plugin adds Condition section for all widgets in Style tab.
  • The Digital Solutions section will be only visible to logged in users based on the following condition.

Download here.

Make Column Clickable Elementor

This plugin adds a very handy and simple feature to the Elementor column. It allows you to make the whole column clickable.

This plugin adds a Custom Link setting in Column > Layout tab.

Download here.

Visibility Logic for Elementor

Hide or show an Elementor widget based on the user’s role. Based on your visibility setting for each widget, you can restrict rendering elements from the front-end, meaning that you can hide or show any Elementor widget based on the user role (Subscriber, Author, Administrator, etc), whether the user is Logged in or not.

This plugin adds a Visibility control section for all widgets in the Advanced tab with the following settings.

  • Enable conditions
  • Visible for
  • Hidden for

Download here.

Elementor Plugins for Jupiter X will make your life easier!

In this article, we introduced some handy Elementor plugins for Jupiter X. Some plugins add widgets, while some extend the functionality of Elementor page builder.

There are also some other plugins in the WordPress Community that you can try. Feel free to share your favorite one with us in the comments section!

Best Plugins for WordPress Meta Box

wordpress meta box featured image

WordPress uses a powerful and flexible framework that has wonderful features to help users create a website easily and quickly. WordPress provides necessary features for creating and editing content, but perhaps for a lot of websites, we need to add more information or data. In this situation, WordPress provides a Meta Box feature.

What is a WordPress Meta Box?

WordPress Meta Box is a group of custom fields which allows you to add more information to posts, pages and custom posts types. You can add custom meta boxes via custom codes in your theme/plugin, or use one of the following plugins for easier and faster workflow.

In this article, let’s cover three of the most popular WordPress Meta Box plugins.

Create WordPress Meta Box with Advanced Custom Fields Plugin

WordPress Meta Box 1

Nowadays, this Advanced Custom Fields is the most popular plugin for creating custom fields. The visual builder allows you to add fields to WordPress edit screens conveniently. Furthermore, with the builder, you can add fields all over your WordPress website including posts, pages, user, media, comments, and taxonomies.

Features

  • Simple & Intuitive
  • Powerful Functions
  • Over 30 Field Types
  • Extensive Documentation
  • Millions of Users

Field Types

  • Basic (Text, Text Area, Number, Range, Email, Url, Password)
  • Content (Image, File, Wysiwyg Editor, oEmbed)
  • Choice (Select, Checkbox, Radio Button, Button Group, True / False)
  • Relational (Link, Post Object, Page Link, Relationship, Taxonomy, User)
  • jQuery (Google Map, Date Picker, Date Time Picker, Time Picker, Color Picker)
  • Layout (Message, Accordion, Tab, Group)

Creating a WordPress Meta Box

Now that you have some information about Advanced Custom Fields plugin, it’s time to create four fields for an author of a post, then add the fields to the end of the post edit screen.

Author fields

  • Author age
  • Author profession
  • Author hobby
  • Author wish

1. From the left sidebar of WordPress admin menu, click on Custom Fields > Add New.

WordPress Meta Box 2

2. Click on the Add Field button for creating fields.

WordPress Meta Box 3

3. Fill out the Field Label, Field Name, Field Type and other fields based on your needs.

WordPress Meta Box 4

4. Add three other fields similar to the above step then click on Publish/Update button.

WordPress Meta Box 5

For showing the created fields in the edit post screen, configure the Location settings as shown below.

WordPress Meta Box 6

6. Edit a post to see the fields.

WordPress Meta Box 6

7. For showing the value of these fields, read this article about displaying values in your theme.

Useful Resources:

Awesome ACF lists many extensions for this plugin. For this article, let’s mention some of them.

Admin Columns allows you to display ACF custom fields for posts (post meta) and users (user meta) as columns on your list overview.

Automatically generates the code you need to implement ACF fields in your themes.

Add a Font Awesome icon field type to Advanced Custom Fields.

Allows you to add a Date and Time Picker field type.

Create flexible and developer-friendly forms using the power of Advanced Custom Fields.

Create a WordPress Meta Box with Meta Box plugin

WordPress Meta Box Plugin

Another powerful and lightweight plugin for creating unlimited custom fields is Meta Box. with this plugin, we can add custom fields to post, page, forms, etc. Furthermore, this plugin has over 40 field types.

The free version of Meta Box Plugin doesn’t have an admin page in WordPress dashboard. For creating a meta box, you need to use an Online Generator tool. This tool generates necessary codes to register a meta box in your child theme.

Features

  • Supports 40+ custom field types
  • Powerful options for custom fields
  • Lightweight and well-coded
  • Developer friendly

Field Types

  • Input fields (Text, Number, URL, Email, Range, Text List)
  • Basic fields (Checkbox, Checkbox List, Button, Password, Radio, Select, Select Advanced Textarea, Hidden, Image Select)
  • Advanced Fields (Color Picker, OEmbed, Slider, WYSIWYG, Autocomplete, Fieldset Text, Map, Heading, Divider)
  • Date & Time Fields (Date, Date-Time, Time)
  • WordPress Fields (Post, Taxonomy, Taxonomy Advanced, User)
  • Media Fields (HTML File, File Input, File Advanced, Image Advanced, HTML Image, Video)

How to Create a WordPress meta box

Now, it’s time to create four fields for an author of a post in Meta Box plugin.

Author Fields

  • Autor Phone Number
  • Autor Email
  • Autor Birthday
  • Autor Site Address

1. Go to the Online Generator tool.

2. In the General tab, set the Function Name and Text Domain.

3. In the Meta Box tab, set the ID and Title of your meta box. Configure the other options to show the meta box at an appropriate place.

4. In the Fields tab, create the fields as explained below:

Field 1: Create Field with Number Type and set ID to author_phone_number and NAME to Author Phone Number.

Field 2: Create Field with Email Type and set ID to author_email and NAME to Author Email.

Field 3: Create Field with Date Type and set ID to author_birthday and NAME to Author Birthday.

Field 4: Create Field with Url Type and set ID to author_website and NAME to Author Website.

5. For generating codes, click on the Generate button. Click on the Copy link to copy codes to the clipboard.

6. Go to Function.php of your child theme then paste the codes and save it.
7. Edit a post to see the fields.

8. For showing the value of these fields, read this article about displaying fields.

Useful Resources:

The Meta Box website has a dedicated page for extensions. For this article, let’s mention some of them:

Create and manage custom post types and taxonomies quickly with an easy-to-use interface.

Pull all meta values from posts and terms into the WP REST API responses.

Create and manage custom taxonomies in WordPress with a user-friendly interface.

Add WordPress custom fields to comments in WordPress. It supports all field types and options.

Create WordPress Meta Box with Pods plugin

WordPress Meta Box Pods Plugin

Pods is a framework to manage all your custom content needs in ONE location. This plugin allows you to create and edit custom post types, taxonomy, fields, and even extend existing WordPress objects like users, media, posts, and pages.

Features:

  • Create a type of content in WordPress
  • Extend existing content types
  • Different field types and build your own with extensible field type classes
  • Importers to help your transition from other plugins

Field Types

  • Date / Time (Date, Time, both)
  • Number (Plain Number, Currency)
  • Text (Plain Text, Website, Phone, E-mail, Password)
  • Paragraph Text (Plain Paragraph, WYSIWYG, Code)
  • Color Picker
  • Yes / No
  • File / Image / Video
  • Avatars
  • Relationships

Create a WordPress Meta Box

Now, let’s add a meta box with some author fields in WordPress pages.

Author fields:

  • Author age
  • Author position

1. From the left sidebar of WordPress admin menu, click on Pods Admin > Add New.
2. In the new screen, choose Extend Existing.

3. Set content Type to Post Types (Posts, Pages, Etc) and Post Type to Pages then click on Next Step.

4. Add a Text field type and set the label to Author Age then set Name to author_age.

5. Add a Text field type and set the label to Author Position then set Name to author_position. Click on Save Pod button to save your fields.

6. Edit a post to see the fields.

Useful Extensions:

Pods plugin is a developer-friendly framework so some developers develop extensions to enhance the plugin. For this article, let’s mention some of them:

Easily select Pods fields in Beaver-Themer field connections from a dropdown based on the currently displayed item (CPT).

This extension provides the ability to sync entries from a Form Submission and Entry Edit screen.

This extension provides optimal performance with Pods sites on hosts with no object caching or low limits.

Conclusion

In this article, we introduced three plugins to help you to create, manage and extend WordPress Meta Box easily and quickly. The ACF plugin is the most popular plugin at the moment. Some popular themes like Jupiter X rely on ACF to manage the Meta Box and custom fields.

There are also some other plugins in the WordPress Community for managing Meta Box. Feel free to share your favorite one with us in the comment section!

How to create custom 404 pages with Jupiter X

how to create custom 404 pages with Jupiter X featured image

Sometimes, when we surf the internet, we encounter a 404 page (Page Not Found). But, what exactly does it mean? A 404 page is displayed when we want to see a page that does not exist. We may follow a broken link or type an incorrect link so the server responds to the browser request with an HTTP 404 code, hence, we see a 404 page.

For all Content Management Systems (CMS) and websites, there’s a default 404 page that’s displayed on appropriate situations. In this article, we’ll show you how to create custom 404 pages with Jupiter X, and how to improve and customize them the best way.

Key points to have a better 404 page

We can add some helpful sections in a 404 page to improve the usability of the page. In this article, we’ll show you how to optimize sections of your 404 page. Here are some of the things you can do:

  • Display recent posts/portfolios
  • Add a call to action button
  • Add a search form

How to customize default 404 page

Jupiter X is backed by an extremely powerful API for customizations. For developers, it offers lots of opportunities to customize the look and feel of different sections of Jupiter X. Let’s explore some ideas on how to customize Jupiter X’s default 404 pages in a child theme.

We must add our codes in the functions.php file of the child theme. All the codes need to be added inside the following function so that it will only affect the 404 pages.

/**
 * Modify the 404 page.
 */
add_action( 'wp', function() {
    if ( ! is_404() ) {
        return;
    }

    // Add codes here.
} );

By default, the 404 page looks like the one below. Later, at the end of the section, you can see the customized one, after some tweaking.

how to create custom 404 pages with Jupiter X 1

Remove sections from page

Because not all 404 pages require a header, footer and title bar. We can clean the page by removing them.

…

// Remove header.
jupiterx_remove_action( 'jupiterx_header_partial_template' );

// Remove title bar.
jupiterx_remove_action( 'jupiterx_main_header' );


// Remove footer.
jupiterx_remove_action( 'jupiterx_footer_partial_template' );

… 

Change the title and description

Almost all of Jupiter X’s texts are changeable via the API. For this page, let’s change the title and description.

… 

// Change title.
add_action( 'jupiterx_no_post_article_title_text_output', function() {
    return 'Ooops! page not found.';
} );


// Change description.
add_action( 'jupiterx_no_post_article_content_text_output', function() {
    return "We can't seem to find the page you're looking for.";
} );

… 

Change layout

There are also different layouts in Jupiter X. In this case, let’s set the page to full width.

…

// Remove the sidebar.
add_filter( 'jupiterx_layout', function() {
return 'c';
} );

…

Add a graphic

Graphics play an important role to get the site visitor’s attention, so why not use a nice 404 graphic in our custom 404 page? This graphic is downloaded from the Drawkit website.

But first, we need to add the graphic to the child theme, so we can add it under the assets/img folder. If the img folder is missing, you can easily create it yourself. 

how to create custom 404 pages with Jupiter X 2

Now, we can add the graphic to the 404 page.

… 

// Add the graphic before the title.
add_action( 'jupiterx_post_title_before_markup', function() {
        echo '<img class="jupiterx-child-custom-404-graphic" src="' . 
get_stylesheet_directory_uri() . "/assets/img/error-404-colour.svg" . '"
 alt="Custom 404 graphic" />';
    } );

… 

Add some styles

The styles and scripts can easily be added in the child theme. To improve the design, we can add some CSS codes in assets/less/style.css

.error404 {
   text-align: center;

   .jupiterx-main {
       background-color: #f3f2f2;
   }

   .jupiterx-main-content .row {
       height: 100vh;
       align-items: center;
   }

   .jupiterx-content {
       max-width: 700px;
       margin: 0 auto;
   }

   .jupiterx-child-custom-404-graphic {
       max-width: 500px;
   }

   .jupiterx-post-title {
       margin-top: 2rem;
   }
}

How to create a 404 page in Elementor

Elementor allows us to build any layout so let’s use it to create a custom full width 404 page. The final page will look like the following image.

how to create custom 404 pages with Jupiter X 3

Create a new page

1. Create a new page from Pages > Add New menu in WordPress left sidebar then publish the page

how to create custom 404 pages with Jupiter X 4

2. In the page, set the Template to Elementor Canvas from Page Attributes. Update the page and click on Edit with Elementor button.

how to create custom 404 pages with Jupiter X 5

Add a new section in Elementor

1. Add a new Section and select the first structure.

how to create custom 404 pages with Jupiter X 6

2. Edit the section. On the Layout tab, set the following settings.

how to create custom 404 pages with Jupiter X 7

3. On the Style tab in the Background section set the following settings. You can download the image from Unsplash site for free.

how to create custom 404 pages with Jupiter X 8

Add headings in Elementor

1. Add a Heading element. On the Content tab, set the following settings.

how to create custom 404 pages with Jupiter X 9

2. On the Style tab, set Color to rgba(255,255,255,0.58).

3. On the Style tab, set Typography settings as follow.

how to create custom 404 pages with Jupiter X 10

4. Add other new Heading elements. Add the following text to in the Content setting:

Oops, we can not find the page you are looking for

5. On the Style tab, set Text Color to #ffffff.

6. On Advanced tab, set the following settings.

how to create custom 404 pages with Jupiter X 11

7. Add other new Heading elements. Add the following text to in Content setting:

– You may have mistyped the address or the page may have moved.

8. On Style tab,set Text Color to #ffffff.

9. On the Style tab, set Typography as follow.

how to create custom 404 pages with Jupiter X 12

10. On the Advanced tab, set the following setting.

how to create custom 404 pages with Jupiter X 13

Add a call to action button in Elementor

1. Add a Button element to page.

2. Edit the Button. On the Content tab in the Button section set the following settings.

3. On Style tab in Button section, set Text Color to #ffffff, set Background Color to rgba(153,76,0,0.53) and set Border Color to #e2574d then set the following settings.

Add recent posts/portfolios in Elementor

1. Add a Posts element from Raven elements to page.

2. Edit the Posts. On Content tab set the following settings.

3. On the Style tab in Post Title section, set the Color to #ffffff then set the following setting.

4. On Style tab in Excerpt, CTA Button sections, set Color to #ffffff.

Update the page

We are done with the custom 404 page, let’s update the page to save our changes.

How to assign custom 404 page in the customizer

To assign our page in customizer goes to Appearance > Customize in the left sidebar of the WordPress admin page.

1. In Customizer click on Pages.

In a new section click on 404 menus to open a popup, in the popup on Setting tab choose your page on Template dropdown.

3. Click on Publish button on top of Customize page.

NOTE: If you can’t see your page in Template dropdown perhaps you have not published your page. Go back to your page and hit the Publish button.

Common Issue

There are some common issues in WordPress 404 pages. In this section, we explain an issue and its solution.

Posts/pages returning 404 error

The problem may be related to permalinks cache. To fix the issue go to Permalinks settings (WordPress Admin > Settings > Permalinks) then click on the Save Changes button. In most cases, it solves the issue.

Conclusion

In this tutorial, we explained how to create custom 404 pages with Jupiter X in Elementor. In customizing default 404, you learned how to use Jupiter X actions and filters to modify HTML, attributes, and texts. In creating a custom 404 page via Elementor, we learned some features of Elementor and assigning the page in Jupiter X. If you have any questions please let me know in the comment section below😉

Meet JetTabs! The Best Way to Organize Your Content

Jupiter X comes with a great page builder named Elementor and it has powerful features that let you create advanced layouts and designs. But unfortunately, it lacks one hell of a feature: Nested elements inside the tabs and accordions.

If you’re not using Jupiter X, you will have to design the complex layouts inside your tabs and accordions using HTML and CSS, and put the code directly inside the tab or accordion content.

Fortunately, we came up with the best way to organize content with Jupiter X. You can now benefit from a bundled plugin called Jet Tabs, which adds the following features to your website — totally free of charge!

  • Accordion ( Advanced Accordion lets you add complex layouts inside its content)
  • Image Accordion
  • Switcher (Toggle between two complex contents)
  • Tabs

All of these elements are capable of showing and/or hiding part of your content. Indeed, it’s the best way to organize content for seamless user experience. Now, let’s take a closer look.

JetTabs is a premium plugin that’s free to use for Jupiter X users. It’s good to know that all of the elements added to your website when you install this plugin (except the Image Accordion) will use the Elementor Block Templates, which is also free in the standard version. You don’t need to pay for the Elementor Pro to benefit from it.

Accordion

Not to be confused with Elementor’s Accordion, this element is Classic Accordion. Classic Accordion widget is the perfect tool for adding content templates built with Elementor or adding your text to every accordion item. You can use this widget in your FAQ page or show the long text content in a more appropriate way.

After adding the classic Accordion element, you can add your items, titles, and icons then set the active element.
For adding the accordion items content, you can add simple text or tabs. It’s also possible to set a section template as accordion content.

In General, the process involves creating your complex content in a block template using Elementor, then assigning the template to the accordion items in the Classic Accordion Settings.

Check out the JetTabs documentation to get more information about the best way to organize content with Jupiter X.

Image Accordion

Image Accordion is a fancy element that lets you showcase your content or categories in a stylish way. You can also use this element to highlight your gallery categories, and so on.

You just need to add the Image Accordion element your page. After that, you can simply add your images with title and description. And in case you would like to add a call-to-action button, it’s possible as well.

There’s a cool option that allows you to change the open and close animation:

Content tab >  Settings > Show Effects

You can see more examples in the JetTabs documentation.

Switcher

Switcher can be considered as a Toggle element, too. The Switcher widget is the perfect asset for you if you need to display two different content blocks and show them under different circumstances. It’s quite practical to use, and it helps you show your site content in a creative way.

Now, there are two items that you can assign your section templates to and set the switch items effect as well.

Check this page out for more information about the Switcher element.

Tabs

And finally, the Tabs! It’s a very useful element, indeed. Tabs is a powerful element that allows you to add your section templates to each tab section. It’s customizable and very easy to use.

First, define your tab contents as a section template in Elementor Templates.

After adding your sections and content, you can assign them into your Tabs element.

Also, in case you would like to add simple text as your tab content, you can change the “content-type” drop-down field to “Editor”.

Feel free to play with the style and design options to get your awesome tab to work exactly the way you imagined.

Now that you and Jet Tabs introduced to each other, it’s time to install it for free on your website, so you can take advantage of the best way to organize content with Jupiter X.

Just follow up these steps:

  1. From WordPress left menu, go to Jupiter X.
  2. From the control panel left menu, go to Plugins.
  3. Next to JetTabs, click on Activate button.
  4. A new pop-up window will appear. click on the Continue button.
  5. After a couple of seconds, a new pop-up window will appear. Click on OK button.
  6. JetTabs plugin is now installed and activated on your website. It will be displayed above in the Active Plugins section.

In case you’re concerned about the compatibility of this plugin with your website features, you should know that:

JetTabs is Multilingual-ready.

Like any other Elementor plugins, you can freely use it on your multi-language website.

Easy-to-use, No Coding Skills Needed.

You can personalize everything without adding any codes. It’s fully customizable.

Compatible with RTL websites

It’s optimized for right-to-left websites.

Responsive layout

You can create vertical and horizontal layouts without having to worry about responsive challenges.

You can also check out our official bundled plugin overview page to access the plugin author website and community, in case you experience any issues with it.

Watch this video to learn how you can easily organize your content using Jupiter X and JetTabs:

Meet JetWooBuilder! The Ultimate Tool to Create Unique Product Page Templates With Jupiter X

JetWooBuilder is a great new feature in Jupiter X that allows you to create WooCommerce Single Product page templates and WooCommerce Product Archive templates with Elementor live page builder’s multiple dynamic content widgets.

You can create unique product page templates with Jupiter X using lots of special widgets and assign it to any product you need. JetWooBuilder is very simple to use. Anyone, from beginners to expert developers, can create attractive and professional-looking WooCommerce Single Product pages without ever touching a single line of code.

Like many other amazing features in Jupiter X, JetWooBuilder is a plugin that can easily be activated through Jupiter X plugin manager.

Customizability

With JetWooBuilder, you can create any layout and design using Elementor page builder and assign it to a product or create an archive template for Shop in your website. So, the options are limitless.

JetWooBuilder Overview – 

Check out samples here.

Powerful Global Widgets For WooCommerce Online Store

Some global widgets in JetWooBuilder can be used for showcasing products and their taxonomies on a custom page.

This widget displays the WooCommerce Product Categories in a Grid layout on the pages built with Elementor.

With this widget, you’ll display the products in a beautiful grid layout. Note that products should be created with featured images, descriptions, and prices in place, so you can set up the widget in the most fitting form.

Using this widget, you’ll showcase the WooCommerce products into stylish list layouts.

This widget allows you to display the taxonomy categories or tags for the WooCommerce products in the form of attractive tile layouts.

Creating a Single Product Page Template

With JetWooBuilder you can create a new or use a pre-designed single product template using dynamic WooCommerce widgets and set it for WooCommerce products.

The layouts that can be used are:

Left-side Product Image 1

Left-side Product Image 2

Right-side Product Image

Centered Product Image

The JetWooBuilder documentation will give you more information on how to create unique product page templates with Jupiter X.

Creating Product Archive Template

Another great feature is creating the Product Archive template to use for the Shop page or any other product layouts displaying related products, cross-sells or products in the shortcode.

Using special, easy-to-use WooCommerce widgets, you can build such archive layouts:

Products Grid with Left Sidebar

Products List with Left Sidebar 1

Products List with Left Sidebar 2

Products List with Right Sidebar

Find more details about creating archive templates in the JetWooBuilder documentation.

Other Features

There are numerous options you’ll discover once you start experimenting with this amazing Shop builder. Aside from that, you can create Categories Loop template, set advanced appearance settings of the widgets, define widget margins and padding, use entrance animation, change the background for the whole widget, and so much more.

When users search for a specific product, you can use the Archive template to show the relevant items they’re looking for. The Archive template will also allow you to display items using shortcode, or with Upsells or Cross-sells widgets in Elementor-built single product templates.

How to Create Unique Product Page Templates With Jupiter X

Watch this video to learn how you can easily create templates for your online store using Jupiter X and JetWooBuilder:

Meet Jupiter X v1.0.3! Blog, Menu and Popup Mega Features Are Added!

Is everyone back from the holidays? If you’re back at work like us, I’m going to kick off your year with great news about Jupiter X WordPress theme.

Just in the last days of 2018 when you’re preparing for your new year celebrations, our team was hard at work to deliver the last Jupiter X update release in 2018: Jupiter X v1.0.3.

Let’s see what’s important about it!

Jupiter X v1.0.3 introduces various improvements, additions, and fixes. You can see the detailed update log here, but I’m going to give you a glimpse of the most important feature added in this version:

  • Jet Menu
  • Jet Blog
  • Jet Popup

As you can guess from names, these features are related to menu, blog, and popup. But let’s have a closer look at each to better understand their capabilities.

Build professional blogs with JetBlog

JetBlog is a plugin that allows you to display Blog posts with different layouts using different dynamic modules such as Smart Tiles, Text Tickers, Video Playlists, Smart Posts List.

All these modules can be added on the page built with Elementor (so make sure Elementor plugin is installed).

Using JetBlog, you can:

  • Stylize the content appearance to match the general webpage style
  • Customize the module backgrounds, layouts, and responsiveness
  • Add borders
  • Apply shadows
  • Change typography
  • And more

There are many other options to discover for each of the content modules. Let’s describe every module for more information.

Smart Posts List

Smart Posts List widget displays your posts in the form of neat content blocks. You can change the listing max-width, featured post position, and image size. You can also stylize post excerpts and meta information without ever touching a single line of code.

Smart Post Tiles

Smart Post Tiles widget allows you to add posts to the website’s page in the form of an eye-catching tiles block. It has different style settings, allowing you to add a gap between boxes, create box overlays, and change the content appearance and meta information. It also has six pre-built layouts that will help you showcase your posts in a totally advantageous way.

Text Ticker

Text Ticker widget adds a captivating ticker content module to your website’s page while displaying the recent and most important post titles in order to engage more visitors to read the recent publications.

Video Playlist

Video Playlist widget allows you to add a video playlist to the web page. It’s very helpful if you want to showcase the videos in a stylish way. There are settings that allow changing the style of the thumbnails and scrollbar, as well as the thumbnail numbers or typography.

JetBlog feature will come in very handy for those who want to create a professional-looking blog and news websites. Jet Blog alone gives Jupiter X the capability of a newspaper theme! You can find more information about the JetBlog plugin in their documentation.

Customize your menus with JetMenu

JetMenu is another plugin that lets you create and style up your mega menu. You’ll be able to create content for the menu items and customize its appearance, add menu badges and icons, and change the menu item background.

The plugin works with the Elementor page builder, allowing you to add content to menu items in a drag-and-drop way. You’ll also get Vertical Mega Menu and Mega Menu widgets for Elementor, which lets you add a menu to any page section.

There are also Import and Export settings that allow you to export the JetMenu settings and use them on another site. You should note that in creating a mega menu, you will use the Elementor page builder, and the mega menu will be displayed instead of the submenu items. The default submenu will be disabled as it will be replaced by the Mega Menu content. In effect, you’ll be able to add any Elementor widget to your submenu and create any content you want.

JetMenu is a powerful plugin to customize your menus. Those who run heavy-duty websites with lots of content or e-commerce websites with a lot of product to showcase always make use of menus with rich content. More information about JetMenu plugin can be found in their documentation.

Build effective popups with JetPopup

JetPopup is an add-on for the Elementor page builder. It facilitates the addition of popups to the pages built with Elementor. With JetPopup you’ll be able to create new popups using all widgets available in Elementor. Also, it allows you to add popups to different widgets and its content, set the specific popup triggers, and choose the time when the popup appears on the page.

Preset Popup layouts

Another useful option is to select a preset layout. JetPopup plugin provides a variety of default presets that can help in creating popups with specific layouts:

Popup action button

There is also a Popup Action Button widget in Elementor page editor that allows you to create buttons that add Yes/No action to popup templates.

There are different actions you can choose from:

  • Leave Page
  • Close Popup
  • Link
  • Close Constantly

Usually, such buttons are added below the text blocks with questions like, “Are you sure you want to leave this page?”

Preset Popup Templates

What’s great in JetPopup plugin is you can use pre-designed popups from the Popup Library. You can import them and edit according to your needs with Elementor page builder, in the same way, you edit any other page.

There are a lot of other great features of JetPopup plugin like Mailchimp Form Integration, popup templates Export and Import, and Attaching Popups to any widget in Elementor (when you click on a widget or its button, a popup will appear).

JetPopup is most useful for websites that are designed to generate leads or sell products or services. With popups, you’ll facilitate the conversion process and make your website marketer happy! You can investigate other options deeply by reading the JetPopup documentation.

What’s next?

Well, a lot! There’s a lot happening in Artbees labs and more and more features are going to be added to Jupiter X very soon. Expect many brand new templates are going to be added in 2019. In fact, I’d like to share the insider tip that we are aiming to hit 300 templates count in 2019. So Stay tuned for a year packed with improvements, features, and templates and let us know what you think about the Jupiter X v1.0.3 in the comments.😉