Gutenberg Block Patterns: Next Awesome Gutenberg Feature

When it comes to the features of the Gutenberg – the new WordPress block editor – the sky’s the limit. The Gutenberg development team is continuing to enhance the editor after each release to bring users more features. One of those features is Gutenberg block patterns, which is a game changer. Before you know it, we’ll be able to create a full site right inside the editor. 

In this article, we’ll cover the Gutenberg block patterns feature and walk you through how we can quickly create our very own custom ones.

Note: To use the block patterns feature, you’ll need to install the latest Gutenberg plugin on your site.

Why block patterns?

If you’re familiar with Elementor, they have a Template feature that allows theme and plugin authors to create reusable combinations of elements/blocks and distribute them for users. This is not only the case for Elementor but nearly every popular page builder has a similar feature. 

This feature was missing in the WordPress new editor and it was proposed in Github. This feature got enough attention and the initial version was released in Gutenberg v7.7 and was stable enough when v8.0 was released.

Creating custom Gutenberg block patterns

This feature starts to shine more when we can create our own block patterns and release them for others to use. Let’s start to create our first pattern. 

It’s worth mentioning that we omitted some technical and other explanations, so you can more easily follow this post’s flow in making your first pattern.

1. Install the Code Snippets plugin

Install and activate the Code Snippets plugin. We’ll use this plugin to add the pattern registration codes in the following sections. You may also use a child theme or plugin to add the codes.

gutenberg block patterns

2. Create a pattern in the editor

Creating a pattern is a fairly easy job. We only need to create a new page and add some blocks in the editor. We used Image, Columns and Paragraph blocks to create the previously shown pattern.

3. Export the pattern codes

For registering a pattern, we need to export the created pattern as explained below.

1. Switch to Code editor and copy the codes.

gutenberg block patterns

2. Escape them by using the Onlinestringtools site.

<!-- wp:image {\"id\":158,\"sizeSlug\":\"large\"} -->\n<figure class=\"wp-block-image size-large\"><img src=\"http://tutorial.test/wp-content/uploads/2020/05/steve-huntington-XT1BJhMkHy4-unsplash-1024x683.jpg\" alt=\"\" class=\"wp-image-158\"/></figure>\n<!-- /wp:image -->\n\n<!-- wp:columns -->\n<div class=\"wp-block-columns\"><!-- wp:column -->\n<div class=\"wp-block-column\"><!-- wp:paragraph -->\n<p>Rapidiously optimize B2B opportunities for interoperable benefits. Intrinsicly underwhelm world-class leadership skills before sticky imperatives.</p>\n<!-- /wp:paragraph --></div>\n<!-- /wp:column -->\n\n<!-- wp:column -->\n<div class=\"wp-block-column\"><!-- wp:paragraph -->\n<p>Phosfluorescently architect equity invested convergence through integrated markets. Enthusiastically incentivize professional systems after quality channels.</p>\n<!-- /wp:paragraph --></div>\n<!-- /wp:column --></div>\n<!-- /wp:columns -->

4. Register your pattern

To display our pattern in the list of patterns, we need to register it via the register_pattern PHP function. This function, as described in the WordPress handbook, receives the name of the pattern as the first argument and an array describing properties of the pattern as the second argument.

Add a new snippet from Snippets > Add New then fill in the settings as shown below. Make sure to click on the Save Changes and Activate button.

gutenberg block patterns
if ( ! function_exists( 'register_pattern' ) ) {
	return;
}

register_pattern(
    'my-custom-patterns/pattern-1',
    [
        'title'   => __( 'Pattern 1' ),
        'content' => "<!-- wp:image {\"id\":158,\"sizeSlug\":\"large\"} -->\n<figure class=\"wp-block-image size-large\"><img src=\"http://tutorial.test/wp-content/uploads/2020/05/steve-huntington-XT1BJhMkHy4-unsplash-1024x683.jpg\" alt=\"\" class=\"wp-image-158\"/></figure>\n<!-- /wp:image -->\n\n<!-- wp:columns -->\n<div class=\"wp-block-columns\"><!-- wp:column -->\n<div class=\"wp-block-column\"><!-- wp:paragraph -->\n<p>Rapidiously optimize B2B opportunities for interoperable benefits. Intrinsicly underwhelm world-class leadership skills before sticky imperatives.</p>\n<!-- /wp:paragraph --></div>\n<!-- /wp:column -->\n\n<!-- wp:column -->\n<div class=\"wp-block-column\"><!-- wp:paragraph -->\n<p>Phosfluorescently architect equity invested convergence through integrated markets. Enthusiastically incentivize professional systems after quality channels.</p>\n<!-- /wp:paragraph --></div>\n<!-- /wp:column --></div>\n<!-- /wp:columns -->",
    ]
);

Finally, you should be able to see the pattern at the end of the Patterns section.

gutenberg block patterns

Conclusion

By now, it’s probably dawned on you the significance of Gutenberg block patterns and how to create a custom pattern in WordPress. We recommend that you keep up-to-date with the Gutenberg Github project to stay informed about developments regarding the feature. 

We’d love to hear about your experiences with the Gutenberg block patterns feature, so please share your patterns with us in the comment section below.

How to Create a Custom Gutenberg Block with the Block Lab Plugin

With the rising popularity of Gutenberg, building tailored Gutenberg blocks is becoming an essential skill for every developer. Throughout time, the WordPress community has made some great contributions to Gutenberg. Today, let’s take a look at the Block Lab plugin. Creating a custom Gutenberg block with the Block Lab plugin is much easier than standard custom block creation via the native Gutenberg API.

In this article, let’s see how we can create a custom Gutenberg block with the Block Lab plugin. But before going forward, you might want to check out the following articles we posted about Gutenberg if you haven’t done so already.

Before diving into codes

First thing’s first. Let’s get familiar with the Block Lab plugin and then we can start creating an example block with this plugin to explore its features.

Features:

  • WordPress- and Gutenberg-friendly UI.
  • 19 available field types.
  • Highly flexible in creating different types of blocks from easy to complex ones.
  • Developer-friendly functions.
  • Good documentation and tutorials.

Creating a custom Gutenberg block with the Block Lab plugin

To demonstrate how this plugin works, let’s create a posts loop block in a few steps. Almost all websites need to use these types of blocks to show posts, portfolios, news and other types of content. Now imagine that you can create any type of posts loop block by yourself using this plugin.

For this article, we are going to create the following posts loop block called Modern Posts. It allows you to fetch posts from different post types and to specify the number of the posts.

custom Gutenberg block with Block Lab

1. Install a child theme

We need to use a child theme for our PHP and JavaScript codes. For the purposes of this article, we’re going to use the Jupiter X Child theme.

custom Gutenberg block with Block Lab

2. Plugin installation

Go to Plugins > Add New, search for the block lab, then install and activate the plugin.

custom Gutenberg block with Block Lab

3. Configuring the block

To configure the essential settings for the Modern Posts block, go to Block Lab > Add New then fill in the Title and Icon settings as shown below. You may change other settings based on your needs.

custom Gutenberg block with Block Lab

4. Add the block fields

Fields allow us to set different settings for each block. Almost all blocks benefit from the flexibility the fields offer. We suggest that you read the Fields documentation.

To create the Modern Posts block’s fields based on the initial design (as shown above), we need the following Post Type and Number of Posts fields. You may add more controls based on your needs. Let’s create them.

1. Click on the Add Field button to add the fields.
2. Add the Post Type field as shown below.

custom Gutenberg block with Block Lab

3. Add the Number of Posts field as shown below.

custom Gutenberg block with Block Lab

4. Click on the Publish button. Afterward, you’ll see the following message which tells you where to create your PHP file in the child theme.

5. Write the block code

Now it’s time to create the PHP and CSS files to make the block show the posts loop. 
1. Create the block-modern-posts.php file in blocks folder in the child theme as shown below.

  • block_value() function gets the value from the fields that we created in the previous section.
  • We used a custom WP_Query to create a custom loop.
<div class="block-modern-posts <?php block_field( 'className') ?>">

	<?php
	// Variables
	$post_type  = block_value( 'post-type' );
	$post_count = block_value( 'number-of-posts' );

	// WP_Query arguments
	$args = array(
		'post_type'      => $post_type,
		'posts_per_page' => $post_count,
	);

	// The Query
	$modern_post_query = new WP_Query( $args );

	// The Loop
	while ( $modern_post_query->have_posts() ) {
		$modern_post_query->the_post();
		?>

		<div class="block-modern-posts--post">
			<img class="block-modern-posts--post-thumbnail" src="<?php the_post_thumbnail_url(); ?>" alt="<?php the_title(); ?>">
			<div class="block-modern-posts--post-content">
				<h4 class="block-modern-posts--post-title"><?php the_title(); ?></h4>
				<div class="block-modern-posts--post-excerpt"><?php the_excerpt(); ?></div>
				<a class="block-modern-posts--post-more" href="<?php the_permalink(); ?>">Read More</a>
			</div>
		</div>

		<?php
	}

	// Restore original Post Data
	wp_reset_postdata();
	?>

</div>

2. Create the block-modern-posts.css file in the blocks folder in the child theme as shown below.

.block-modern-posts--post {
	display: flex;
	margin-bottom: 40px;
	align-items: center;
}

.block-modern-posts--post-thumbnail {
	width: 28%;
	height: 400px !important;
	object-fit: cover;
	border-radius: 30px;
}

.block-modern-posts--post .block-modern-posts--post-content {
	font-family: "Helvetica Neue";
	background: #fff;
	padding: 50px 40px;
	margin-left: -60px;
	box-shadow: 0 0 20px #0000001c;
	border-radius: 30px;
}

.block-modern-posts--post .block-modern-posts--post-title {
	font-family: "Helvetica Neue";
	font-size: 26px;
	font-weight: 400;
	line-height: 1.2;
	margin: 0 0 0.5rem;
}

.block-modern-posts--post .block-modern-posts--post-excerpt {
	margin-top: 20px;
	margin-bottom: 45px;
	color: #999;
	line-height: 1.8;
}

.block-modern-posts--post-more {
	background-color: #7882ff;
	border-radius: 50px;
	padding: 12px 22px;
	color: #fff;
	font-size: 14px;
	text-decoration: none;
}

/* Featured */
.block-modern-posts--post:first-child {
	display: block;
	margin-bottom: 60px;
}

.block-modern-posts--post:first-child .block-modern-posts--post-thumbnail {
	width: 100%;
	height: 550px !important;
}

.block-modern-posts--post:first-child .block-modern-posts--post-content {
	margin: -70px 50px 0;
	position: relative;
}

3. After adding the files, you can now play with the block in the WordPress editor.

Wrapping up

As outlined in this post, we walked you through how you can build a custom Gutenberg block with Block Lab, which is much easier than creating the blocks with the native Gutenberg API. In other words, the Block Lab plugin is a huge timesaver when it comes to creating custom blocks. 

We’d love to hear about your experiences with the Block Lab plugin, so please share your custom blocks with us in the comment section below.

How to Create a Custom Gutenberg Block with Lazy Blocks Plugin

custom Gutenberg block with Lazy Blocks - featured

Every day, we’re seeing more and more plugins extending Gutenberg in different directions. This is great news for Gutenberg lovers since they can enjoy using it even more. One of those handy plugins that we’re going to cover today is called Lazy Blocks
In this article, we’ll look at how we can create a custom Gutenberg block with Lazy Blocks. It’s worth mentioning that we also published similar articles.

Before diving into writing codes

The user-friendly architecture of this plugin will help us to easily create custom Gutenberg blocks. The following sums up the plugin’s key features:

  • User and Gutenberg friendly UI.
  • Various controls (checkbox, email, file, gallery, image, repeater, …).
  • Usage of Handlebars, which makes writing PHP codes a breeze.
  • Separate editor and frontend code blocks to help us write different outputs.
  • Custom templates for your posts.
  • Many hooks for PHP and JS codes.
  • Good documentation.

We recommend that you check out the following resources to become more familiar with this plugin:

Create a custom Gutenberg block with Lazy Blocks

The mentality behind this plugin is to spend your time and energy on the result, not on learning how to create blocks. This mentality will allow you to unleash your potential in creating custom Gutenberg blocks.

In this article, we omitted some technical and extra explanations, so you can more easily follow this post’s flow in making your first block. To learn even more about the process, you might want to read the plugin documentation.

So let’s dive into it and create an attention-grabbing Gutenberg Blockquote block in a few simple steps.

custom Gutenberg block with Lazy Blocks

1. Plugin installation

Go to Plugins > Add New, search for lazy blocks. Then install and activate the plugin.

custom Gutenberg block with Lazy Blocks

1. Configuring the block

To configure the essential settings for the Blockquote block, go to Lazy Blocks > Add New then fill the Title and Icon settings as shown below. You may change other settings based on your needs.

custom Gutenberg block with Lazy Blocks

2. Add the block controls

Controls allow us to specify dynamic settings for a block, and it’s almost necessary for all the blocks to have controls. They offer flexibility for the blocks. We suggest that you read the Controls documentation.

To create the Blockquote block’s controls based on the initial design (as shown above), we need the following Icon Background, Avatar, Text and Author controls. You may add more controls based on your needs. Let’s create them.

1. Under the Controls section, go to the Content tab and click on the + icon to add the controls.

2. Add the controls one by one as shown below.

custom Gutenberg block with Lazy Blocks

3. At the end, your controls should look like below.

3. Write the block code

Now we need to write the actual codes based on the design to make the Blockquote block work. In this section, we also use the created controls in the block to make it dynamic based on the settings.

1. Under the Controls section, go to the Frontend tab and add the following codes. The controls names have been wrapped in curly brackets {{control-name}} then added inside the following code. We recommend that you read the Codes documentation.

<blockquote class="lazyblocks-blockquote">
    <span class="dashicons dashicons-format-quote" style="background-color:{{icon-background}};"></span>
    <p class="lazyblocks-blockquote-text">{{text}}</p>
    <footer class="lazyblocks-blockquote-footer">
        <img class="lazyblocks-blockquote-avatar" src="{{avatar.url}}" alt="{{author}} quote" />
        <span>{{author}}</span>
    </footer>
</blockquote>

2. Update the block and go to a page to see how the block works. You may add different texts, names, avatars and icon backgrounds to the block. All this can also be added in different layouts like columns.

Conclusion

In this blog post, we easily created a custom Gutenberg block with Lazy Blocks without the hassle of creating a separate plugin, child theme or other development obstacle. This Lazy Blocks plugin will definitely help actualize your ideas about custom Gutenberg blocks in no time. 

We’d love to hear from you, so please share your custom blocks with us in the comment section below.

How to Create a Community Poll Website with Jupiter X – Part 2

create a community poll website

In the previous article, we stopped right after we created a community poll website, which enables users to submit their own polls. . In this post, we’ll walk you through the rest of the process.  The next step is setting up a homepage where users will be able to see the latest votes, filter them based on their tags and also be able to search between them. After that, we’ll need to design the single poll page.

Step Four: Implement the single polls page and the homepage

This is what I want from the homepage: a list of the latest approved polls, which includes the title, subtitle, latest vote date and created date. In case the poll was closed, it should also show a lock icon in the top right corner.

create a community poll website
Logged out view of the desired homepage.

Also, if the user is  logged in, the polls that I’ve already voted on should turn green, so it becomes possible to distinguish between the polls that I’ve participated in and the ones that I haven’t.

create a community poll website
Logged in view of the desired homepage.

At first look, it seems possible to implement this by using a simple listing with the help of Jet Engine and Jet Smart Filter plugin. Well, this is true for sure.  However, one thing that is missing is the conditional logic of colors. Jet Engine doesn’t give me the ability to distinguish between the polls I’ve voted in and the ones I haven’t.

So, the trick here would be to define a custom shortcode, place it inside a listing and then use it to have smart filters. The following code will give me a shortcode that I can use inside a Listing template on Jet Engine. It represents a single topic with the desired conditions that let me style it as I wish:

add_shortcode( 'custom_poll_item', 'custom_poll_item_function' );


function custom_poll_item_function( $atts ) {
   global $_gdpol_poll;
   $topic_id =  get_the_id();
   $poll_id = gdpol_get_topic_poll_id($topic_id);
   $custom_clasees = " " . get_post_status($topic_id) . " " . " poll_list_item";
   $topic_title = get_the_title($topic_id);
   $topuc_desc = get_the_content($topic_id);
   $uploads = wp_upload_dir();
   $upload_path = $uploads['baseurl']; 
   $topic_thumbnail = get_the_post_thumbnail($topic_id) ? get_the_post_thumbnail_url($topic_id) : $upload_path . 'https://d34b8fs2z18t5a.cloudfront.net/2020/01/chart.png' ;
   $topic_post_date = get_the_date('U', $topic_id);
   $topic_url = get_post_permalink($topic_id);
   $last_active = strtotime( get_post_meta( $topic_id, '_bbp_last_active_time', true ) );   
   $topic_button_text = "I want to Vote!";

   

  if(is_user_logged_in())
  {
  	$user_id = get_current_user_id();
  	$has_voted_or_not = gdpol_db()->user_voted_in_poll($poll_id, $user_id);
  	if($has_voted_or_not) 
  	{
        $custom_clasees .= " voted ";
        $topic_button_text = "Already Voted";
  	}
  	else {
  		 $custom_clasees .= " not_voted ";
  	}
  }
  else {
  	$custom_clasees .= " not_voted ";
  }


  $output = "
			    <a href=\"" . $topic_url .  "\"  class=\"poll_link_list_big\" >
	  				<div class='" . $custom_clasees . "' >
		  				<div class='thumbnail_poll' >
		  					<img src='".$topic_thumbnail."' />
		  					<div class='topic_date' >Created: " .  esc_html( human_time_diff($topic_post_date, current_time('timestamp') ) ) . ' ago' . "</div>
		  					<div class='topic_date_last_activity' >Last activity: " .  esc_html( human_time_diff(date('U', $last_active), current_time('timestamp') ) ) . ' ago' . "</div>
		  				</div>
		  				<div class='poll_body' >
		  					<h3>". $topic_title."</h3>
		  					<div>". $topuc_desc."</div>
		  				</div>
		  				<div class='poll_list_last_column'>
		  					<div class='poll_permalink_button'   >".$topic_button_text. "</div>
		  				</div>
	  				</div>
  			    </a>
  			 " ;

	return $output;
   
}

Just put this in your child theme’s functions.php, and the shortcode will be available. I also need to style it a little bit, so I’ll go ahead and add this CSS fix into the jupiterx-child/assets/less/style.css:

.poll_link_list_big .poll_list_item {
    display: flex;
    justify-content: space-between;
    width: 100%;
    align-items: center;
}

.thumbnail_poll {
    max-width: 100px;
    padding: 6px;
    background: #E0E0E0;
}

.topic_date {
    /* font-size: 7px; */
    /* margin-top: 7px; */
}

.thumbnail_poll {
    min-width: 100px;
    font-size: 7px;
    color: #777575;
    text-align: center;
}

.thumbnail_poll img {
    max-width: 48px !important;
    margin: 9px;
}

.poll_body {
    justify-content: flex-start !important;
    text-align: left;
    width: 80%;
    padding: 5px 15px;
}

.poll_link_list_big {
    display: flex;
    background: rgba(224, 224, 224, 0.48);
    position: relative;
}

.poll_body >h3 {
    color: black;
    font-size: 18px;
}

.poll_body > div {
    color: grey;
    font-size: 12px;
}

.poll_list_last_column {
    padding: 10px;
}

.poll_permalink_button {
    background: #fb6800;
    color: white;
    padding: 12px 10px;
    border-radius: 10px;
    font-size: 13px;
    text-align: center;
}


.publish.poll_list_item.voted {
    background: rgba(84, 218, 100, 0.14);
}

.voted .poll_permalink_button {
    background: #00ab00;
}





body .poll_link_list_big .closed:before {
    font-family: "Font Awesome\ 5 Free" !important;
    display: block;
    width: 16px;
    hright: 16px;
    color: #ababab;
    font-size: 16px;
    font-weight: 900;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    font-style: normal;
    font-variant: normal;
    text-rendering: auto;
    line-height: 1;
     content: "\f023";
     position: absolute;
     right: -7px; top: -4px;
}

Now, go to Jet Engine -> Listings and add a new Listing Item. I named it as “polls.”

create a community poll website
Adding the “polls” Listing template.

While editing the listing, set the Listing Source as “Posts” and assign the “Topics” post type to it. You can set the whole item to be clickable as well.

Configuring the “Polls” Listing template to show the “Topics” post type.

Now drop the Shortcode element into the page, and add this shortcode to it:

[custom_poll_item]

This is the name of the shortcode that we previously built in the functions.php file.

Adding the custom shortcode to the listing template. 

As soon as the shortcode is added, you should be able to see the result in the preview. It’s better to set the margin and column gap of the sections here to 0. Now that you added the listing template, you need to use it on a Listing Grid and put it on your page. 

Go to your homepage and drop a Listing Grid element into the content. Then configure it as follows:

Configuring the Listing Grid to show the latest polls. 

In order to load more polls, you need to add a button and set it’s ID as “loadmore_latest,” which is the ID you set in the Load More Element ID section of the listing grid.

Adding the proper ID to the Load More button.

Now it’s time to add the search box on top of the polls list and then add the tags filter at the bottom. I’ll use a Smart Filter plugin to do that.

Go to Smart Filters and add two filters: 

  • Tags Selection filter 
  • Search for polls
Adding a new Smart Filter.

For the search box, use the Search filter type:

Setting up the search filter type (text box).

And for the tags, use a Radio type as follows:

Setting up the tags filter using a Radio filter.

Update the filters and go back to the homepage. Now drag and drop the search filter and radio filter into the page.

Adding the Search and Radio filter elements to the homepage.

And assign the filters as you wish. Then style them using their styling options.

Configuring the filters to work with the smart filters created earlier.

Also, this CSS snippet is needed to remove the radio circles and to also show a different color on the selected tag:

.elementor-element .jet-radio-list__input:checked ~.jet-radio-list__label {
    background: #ff5c08;
    color: white !important;
}

.elementor-element .jet-radio-list__input ~.jet-radio-list__label {
    background: white;
    padding: 2px 20px 8px;
    color: #0a0a0a !important;
}

The homepage is ready now! Publish the changes, assign this page as your homepage in WordPress Settings -> Readings and check your website. 

‌By clicking on every vote item, you’ll be directed to the polls page where you can participate in the polls. Styling this page requires some modifications in the child theme. 

In the previous article, we showed how to override the bbPress template files in a child theme. Just like before, I would need to override gdpol-poll-content.php from wp-content/plugins/gd-bbpress-toolbox/templates/default/bbpress/ in wp-content/themes/jupiterx-child/bbpress/gdpol-poll-content.php. 

Also I need to override content-single-topic.php from wp-content/plugins/bbpress/templates/default/bbpress/ in the same directory of my Jupiter X child theme (bbPress). 

You can edit the rest of the template files in order to get the look you’re going for. You can find more information here.

Editing the content-single-topic.php file.

Instead of the poll title and description, we used the topic title and description in the previous article. So, we need to show the topic title and description in the poll single page template.

Editing the gdpol-poll-content.php

In the end, adding this CSS snippet to jupiterx-child/assets/less/style.less will give you a better look in the single topics page:

.gdpol-choices-list legend {
    font-size: 12px;
}

.gdpol-topic-poll header h2 {
    font-size: 2em;
}

.gdpol-topic-poll header p {
    margin-top: 20px;
    /* background: #fffdfd; */
    padding: 20px 0;
}
.gdpol-topic-poll footer, .gdpol-topic-poll header {background: none; }

.gdpol-topic-poll {
    border: none;
    background: #fff;table.wp-list-table.widefat.fixed.striped.posts {
    width: 100% !important;
}
}
.um-dropdown-b li:nth-child(2) {
    display: none !important;
}


a.gdpol-action-show {
    margin-left: 8px;
}


.gdpol-poll-choices label span {float: right;}
.gdpol-poll-choices label input {float: left  !important;margin: 4px 6px 0 0px !important;}


.gdpol-fields-wrapper {
    display: block !important;
    border: none !important;
}

#gdpol-poll-status, #wc-comment-header, .wc_stick_btn.wc-cta-button, .wc_close_btn.wc-cta-button, .bbp-form.gdpol-topic-poll-form legend, .d4p-attachment-addfile
,a.gdbbx-attachment-add-file, .gdbbx-attachment-control >div:nth-child(3), .gdbbx-attachment-control >div:nth-child(4),
.wc-field-submit .wpd_label{
    display: none !important;
}



table.wp-list-table.widefat.fixed.striped.posts {
    width: 100% !important;
}


.bbp-form .gdbbx-attachments-form .gdbbx-validation-active .gdbbx-attachment-preview  {
   float: left !important;
   margin-left:  0 !important;
}

.bbp-form .gdbbx-attachments-form .gdbbx-validation-active .gdbbx-attachment-control {float: left; margin-left: 15px;}
.gdbbx-attachments-form {
    text-align: left !important;
}


.jupiterx-post-image picture{
    display: flex;
    text-align: center;
    margin-bottom: 50px
}
.jupiterx-post-image img {
    width: auto;
    height: 100%;
    max-height: 400px;
    margin: auto;
}



.single-topic #bbpress-forums ul.gdpol-poll-choices, .single-topic  #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li {
    padding: 12px;
    font-size: 1.2em;
    color: white;
    list-style-type: none !important;
    margin: 0 !important;
    vertical-align: middle;
    padding-top: 24px;
    position: relative; min-height: 75px;
    display: flex;  align-items: center; width: 100%; columns: 1;  flex-direction: column;
    flex-wrap: wrap;
}

.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li label {position: absolute;  top: 0; bottom: 0; right: 0; left: 0; text-align: right; width: 100%; display: flex;  align-items: center; padding: 10px; cursor: pointer;}

/* different colors on the poll choices */
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(odd) { background-color: #292ab1; }
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(even) { background-color: #1e7b48; }
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(3n) { background-color: darkcyan; }
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(4n) { background-color: mediumorchid; }
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(5n) { background-color: dodgerblue; }
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(6n) { background-color: darkorange; }
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(7n) { background-color: firebrick; }
.single-topic #bbpress-forums.bbpress-wrapper ul.gdpol-poll-choices li:nth-child(8n) { background-color: lightseagreen; }

This is the final look on the single polls page:

Final look of the single polls page. 

Step Five: Design the header and footer with Jupiter X and Raven

The next part when you create a community poll website involves designing the headers and footers of the website. There’s nothing special in this section since everything is possible with the Jupiter X’s Custom Header and Custom Footer capability. You may want to put menus and call to actions in the header and ensure they are looking as they should. More information about this section can be found here.

Adding a custom header template with a call-to-action for creating the polls. 

Step Six: Install Ultimate Member and its add-ons and configure

Using a membership plugin can help you create a membership directory and add social networking features to your app. This will also help you monetize your project. For this particular website, we used the Ultimate Member plugin.

Ultimate member plugin in WordPress plugins repository. 

Dozens of add-ons offered by this plugin can help you build a social network. Imagine that the users of your community create polls, share them on social media, and others vote in the polls and join your community. They interact with each other, see their profiles and receive notifications with each interaction. This is all possible with this plugin. Remember that in order to have an integration on the user profiles and the bbPress forums, you would need to use this add-on on Ultimate Member which is premium:

https://ultimatemember.com/extensions/bbpress/

Profile page view and the integration with the forums. We should change the “Forums” to “Polls” later on using translations.

Later on, you can use localization and change the “Topics” word to “Polls.” After installing the Ultimate Member plugin, you need to define some pages as the membership directory page, single profile page and etc. Here you can find more information on how to configure that.

Step Seven: Add custom notification on the poll votes

 Notifications are a must-have for any social poll website. As soon as any sort of interaction occurs, users should be notified. In order to have a notification system, we used the Real Time Notification add-on for the Ultimate Member plugin and configured it as we wanted. By default, it gives you these notifications, and you have full control of the options to enable/disable them and show the texts as you like. 

  • Notify users when the user role has changed.
  • Notify users when someone comments on their post.
  • Notify users when someone replies to one of their comments.
  • Notify users when another member views their profile.
  • Notify users when guests view their profile.
  • bbPress – Notify users when someone replies to them on topics they created.
  • bbPress – Notify users when someone replies to them on a specific topic.

You can find information on how to configure it here:

I want to also notify the owner of the poll whenever his/her poll receives a vote. In order to do that, I’ll write a code with the help of the notification API included in the Ultimate Member add-on called Real-Time Notification.

/*

This code sample shows you how to use the API to create
and add custom notifications (for real-time notifications) in the plugin.

STEP 1: You need to extend the filter: um_notifications_core_log_types with your
new notification type as follows. For example:

*/

add_filter('um_notifications_core_log_types', 'add_custom_notification_type', 200 );
function add_custom_notification_type( $array ) {
		
	$array['new_action'] = array(
		'title' => 'When something happens', // title for reference in backend settings
		'template' => '<strong>{member}</strong> has just did some action.', // the template, {member} is a tag, this is how the notification will appear in your notifications
		'account_desc' => 'When member does some action on my profile', // title for account page (notification settings)
	);
		
	return $array;
}

/*

STEP 2: Add an icon and color to this new notification type.

*/

add_filter('um_notifications_get_icon', 'add_custom_notification_icon', 10, 2 );
function add_custom_notification_icon( $output, $type ) {
	
	if ( $type == 'new_action' ) { // note that our new action id is "new_action" from previous filter
		$output = '<i class="um-icon-android-person-add" style="color: #336699"></i>';
	}
	
	return $output;
}

/*

STEP 3: Now you just need to add the notification trigger when a user does some action on
another user’s profile. I assume you can trigger that in some action hooks.
For instance, when a user views another user’s profile, you can hook like this.



$who_will_get_notification : is user ID who will get notification
'new_action' is our new notification type
$vars is array containing the required template tags, user photo and url when that notification is clicked

UM()->Notifications_API()->api()->store_notification( $who_will_get_notification, 'new_action', $vars );

*/

add_action('gdpol_vote_saved', 'trigger_new_notification', 100);
function trigger_new_notification( $args ) {
	 global  $_gdpol_poll, $um_notifications, $post, $topic;
	 $_poll = gdpol_get_topic_poll_id();
			$poll_author_id =  bbp_get_topic_author_id($args->topic_id); // die();
				update_post_meta( $args->topic_id, '_bbp_last_active_time', date( 'Y-m-d H:i:s', current_time( 'timestamp', 0 )));

	if ( is_user_logged_in() ) {
		
		$vars['member'] = $args->topic_id;
		$vars['notification_uri'] = get_the_permalink($args->topic_id);

		UM()->Notifications_API()->api()->store_notification( $poll_author_id, 'new_action', $vars );
		
	}

	else {
				UM()->Notifications_API()->api()->store_notification( $poll_author_id, 'new_action', get_the_permalink($args->topic_id) );


	}


}

After adding the above code, a new notification will be added to the Ultimate Member -> Settings -> Extensions. Remember to activate it and save the settings.

Activating the newly added notification.

In the meantime, I want to update the topic’s last activity meta field with the latest vote time. So, in the last function, you’ll see this line of code:

update_post_meta( $args->topic_id, '_bbp_last_active_time', date( 'Y-m-d H:i:s', current_time( 'timestamp', 0 )));

This will help you update the latest activity on each poll which is showing on the homepage within the listing you created before. Just add the above code to your child theme’s functions.php file. It’ll give you a look like below. As soon as someone votes on the poll:

create a community poll website
Voting on a poll by a user. 

It’ll send a notification to the user who created the poll.

create a community poll website
The notification received on the other user panel. 

And by clicking on the notification icon, it’ll show you the text that you have provided in your custom function and the configuration of the plugin.

create a community poll website
Custom notification shows up when a vote is submitted on a poll.

More configurations and stylings are possible using custom CSS.

Step Eight: Localize and translate to your own language

The last section in creating a community poll website is translating and localizing the words into your own language. Using the Loco Translate plugin, you can change every single piece of text within this app just as you like. Remember that the texts are located on different plugins, and you need to dig into the plugins to find the source of the text. Mostly, you need to change the word “Topic” to “Poll” wherever it is showing up because of the logic behind this app.

create a community poll website
Translating the Topics to Polls via LocoTranslate.
Results of translating Topics to Polls in the Profile page.

Results, further development and roadmap

We created a social network application based on social polling features. Certainly, there are tons of further considerations to make it like a production app. But the thing is that the base is prepared, meaning that you can add as many features as you want simply by using different plugins and configurations. 

This method will save a lot of money if you aim to build such a community – and compared to the social polling platforms out there, it can be considered almost a free platform. The good thing about this method is that you can keep everything updated and secured with one single click. 

Additional features such as Login by Phone (using two-factor authentication) or the discussion below the threads can be applied to the app using the following plugins:

  • wpDiscuz: advanced commenting plugin. 
  • Digits : WordPress Mobile Number Signup and Login

Adding more plugins may require configurations and, in some parts, or even writing some codes to integrate it with your base. For example, bbPress uses three post types such as “forum,” “topic” and “reply.” You would need to enable the comments for the “topic” post type using custom development because by default, the topics don’t receive any comments. Or you may need to configure the Digits plugin to work with your own SMS platform. 

Also, you may want to push your notification to the users who subscribed to your app or website. This can be done by using FireBase or any other push notification service. However, it may require custom development in some parts to make sure it triggers correctly whenever an interaction happens on your website. 

The last thing you want to do is to wrap the website on a webview and publish it on app stores such as Google Play or iTunes. There are dozens of tutorials out there that can help you with that.

Wrapping Up

Creating a community poll website has never been easier than now. It can be done using bbPress and WordPress and using handy tools such as the Jupiter X theme. Its bundled plugins will ease the process and reduce the cost of development. 
In this series, we provided an overview of how to create a social polling website using their tools we had. Check out the first article of this series here if you’ve come across this post using a search engine.c

Tweaks Made to Improve Jupiter X Performance

For developers, time is of the essence when it comes to delivering a project on a tight deadline. Every second matters – this is the philosophy that helps the Jupiter X team propel itself forward with every new version it releases. After running some performance checks, we noticed that a couple of factors were hindering the Jupiter X performance from reaching its peak potential. So we set out on a mission to fix the inefficient codes, which then in turns saves valuable time for our users.

This post will provide an overview of the recent tweaks we’ve made, and we’ll further look at the efficacy of those changes in our test cases after the 1.15.0 update.

Inefficient codes

While checking the Jupiter X performance, we noticed that one of the themes’ components – called Compiler – was performing poorly, which affected different parts of user experience.

In the Jupiter X theme, the Compiler is responsible for generating and caching CSS and JavaScript. When there’s no cache, it compiles LESS, CSS and JS files and generates the necessary assets in the upload directory.

The Compiler offers some valuable benefits for developers, allowing them to:

  • Add styles and scripts to the theme on the fly.
  • Filter or override the LESS variables used for generating styles.
  • Exclude/include different styles and scripts.
  • Generate automatic RTL styles.

At the start of the Jupiter X road, these benefits seemed quite promising in terms of bringing lots of customizability to the themes. But throughout the years, it appears that the theme industry is moving toward lightweight themes and relying on page builders to increasingly do the job.

All in all, we started to optimize the Compiler to bring faster-compiling assets for the new version of Jupiter X. We did the following optimizations until v1.17.0.

Reduce calling Customizer variables

The Jupiter X Customizer settings rely on the Compiler to generate styles for the frontend. In this way, we send the Customizer settings as an array (variables) to the Compiler, and it generates the proper styles.

That said, it works pretty well – however, we found out we were calling the variables multiple times during each page load. Now, it’s limited to only when generating the styles.

Single post compiling preview/update asset

There are a few post meta options (build via ACF) for single posts. Some of them are styling options. To generate styles for the frontend, we were sending the styles to the Compiler and recompiling the main CSS file.

It turned out that this caused unnecessary recompiling for each post update/preview. We decided to generate separate CSS files for each post (e.g. jupiterx-post-12.css) when necessary.

Refactoring the CSS parser function

We have a CSS parser in the theme which is responsible for the following actions:

  1. Removing empty CSS properties. (Replaced by standard PHP functions)
  2. Minifying CSS. (Replaced by standard PHP functions)
  3. Adding necessary vendor prefixes. (Dropped adding automatic vendor prefixes)
  4. Generating automatic RTL CSS. (Replaced by a faster PHP class)

Using static script

The theme’s main JavaScript file was generated via the Compiler from smaller files, and we came to the conclusion that we don’t need to have on-the-fly compiling for the script file. That said, we replaced it with a Gulp solution to build and distribute the static script in the theme.

Jupiter X Performance test cases

We measured the loading time in the following 5 test cases for comparison. To have a stable testing result for all the tests, the factors below were considered.

  • The comparison was done between version 1.15.0 and 1.17.0. You can check the release notes.
  • Each test was run 3 times (with 30s interval) to calculate the average load time.
  • Development mode (Control Panel > Settings) was set to off.
  • Tested on load environment.
  • Tested on a fresh installation.
  • Activated Jupiter X Core, Advanced Custom Fields and Elementor plugins.

1. Default home page

Improve Jupiter X Performance

This test was completed on a default Jupiter X homepage. The page was loaded 3 times without a cache, and the loading time was recorded.

Result

The v1.17.0 is almost one second faster than v1.15.0, so there was a one-second improvement (30%) in loading without a cache.

2. Loading Customizer

Improve Jupiter X Performance

This test was completed on Customizer loading the default Hello world single post page. The page was loaded 3 times without a cache, and the loading time was recorded.

Result

The loading time in v1.17.0 is almost one second faster than v1.15.0, which is the equivalent to 15% faster loading without a cache.

3. Reloading the Customizer preview

This test was done on Customizer > Blog > Blog Single when changing the Typography settings of the Author Box. The test was done 3 times.

Result

It’s not possible to measure the loading time in Customizer preview, but based on the checks, v1.17.0 is about 40% faster than v1.15.0.

4. Loading the Elementor editor

This loading test was conducted with Elementor on a page with 9 sections. The page was loaded 3 times without a cache, and the loading time was recorded.

Result

The loading time in v1.17.0 is almost 2s faster than v1.15.0, which is the equivalent to a 25% faster loading time without a cache.

5. Elementor previewing

Improve Jupiter X Performance

This test was done on Elementor previewing on a page with 9 sections. The page was previewed 3 times, and the loading time was recorded.

Result

The loading time in v1.17.0 is almost 2s faster than v1.15.0. This is the equivalent to a 50% faster loading time without a cache.

Conclusion

As mentioned before, we strived to enhance Jupiter X performance in various areas of the theme. By improving the code base without sacrificing current features, we were able to significantly decrease loading times, which translates into time saved for our users. 

In the table below, you’ll be able to see the summary of all the test cases mentioned in this article.

Test caseAverage improvement
Default home page30%
Loading Customizer15%
Customizer preview reloading40%
Loading Elementor editor25%
Elementor previewing50%

Last but not least, since we improved the codes to run more efficiently, the usage of CPU and RAM of your server will be decreased.

Of course, there’s still room for performance enhancement, and we’re continually working to improve the theme to make it as performant as possible.

We’d love it if you could share your feedback with us in the comments section.

A Beginner’s Guide to Create a Custom Block for WordPress Gutenberg

Gutenburg, the new WordPress editor, is the future of WordPress. In no time, it’s going to bring a full-site editing experience for users. That said, learning how to create a custom block for WordPress Gutenberg is a fantastic investment. These days, more and more themes (such as the Twenty Twenty theme) are taking advantage of what Gutenberg has to offer.

This post will go over a general introduction of Gutenburg blocks and will then explain how to create a custom block for WordPress Gutenberg.

What are Gutenberg blocks?

Blocks are the core building functionality of the new editor. The idea is that you can add blocks anywhere you want. Blocks are created mostly in JavaScript (sad news for PHP lovers).

Learning a few concepts is necessary before diving into writing codes.

Block registration

First things first – we need to register a block. To register, we need to use the registerBlockType function.

// Registering my block with a unique name
registerBlockType( 'mcb/call-to-action', {} );

Edit and Save

After registering a block, the next step is to tell the editor how to show the block in the editor and how to save it in the database.

Having a proper understanding of the edit and save functions is essential to create a custom block for WordPress Gutenberg.
The edit function is responsible for making the block editable in the editor, and the save function is responsible for saving the block in the database for showing it in the frontend.

// A static div
edit: function() {
    return wp.element.createElement(
        'div',
        null,
        'My custom block.'
    );
}

save: function() {
    return wp.element.createElement(
        'div',
        null,
        'My custom block.'
    );
}

Attributes

Almost all blocks need to have attributes. Think of them as a way to talk to the block to change the color, text or spacing for instance.

{
    url: {
        type: 'string',
        source: 'attribute',
        selector: 'img',
        attribute: 'src',
    }
}
// { "url": "https://lorempixel.com/1200/800/" }

Are you a PHP lover?

If so, sorry to tell you that Gutenburg is a React.js based editor. The JavaScript frameworks have taken a leap in popularity among developers. Nowadays, JavaScript is an essential skill to have under your belt.

Take every opportunity to really beef up your JavaScript chops.
– Matt Mullenweg, Creator of WordPress

Available built-in blocks

Following are the list of built-in Gutenberg blocks in WordPress. If you need more blocks, you can read this article about free blocks.

Common blocks

This includes Paragraph, Image, Heading, Gallery, List, Quote, Audio, Cover, File, Video blocks.

custom block for WordPress Gutenberg

Formatting

This includes Code, Classic, Custom HTML, Preformated, Pullquote, Table, Verse blocks.

Layout elements

This includes Buttons, Columns, Group, Media & Text, More, Page Break, Separator, Spacer blocks.

custom block for WordPress Gutenberg

Widgets

This includes Shortcode, Archives, Calendar, Categories, Latest Comments, Latest Posts, RSS, Search, Tag Cloud blocks.

Embeds

This includes Embed, Twitter, YouTube and 29+ blocks.

custom block for WordPress Gutenberg

How to create a custom block for WordPress Gutenberg

Enough is enough – let’s get our hands dirty and start coding! There are different techniques for creating a custom block for WordPress Gutenberg. For the purpose of this article, let’s use one of the most straightforward techniques to build a tailored Call to Action block.

Note: It’s worth mentioning that many detailed explanations have been intentionally omitted to help you follow the flow of the article easily. The intention is to help you create your first block without being weighed down in the minutiae of block creation.

1. Prepare a base plugin

Before doing anything else, we need a plugin to place our codes. Depending on your preferences, you can use a child theme instead of a plugin.
1. Go to your plugins folder on your site, then create a my-custom-blocks folder.

custom block for WordPress Gutenberg

2. Create a plugin.php file as shown below.

3. Activate the plugin from WordPress admin.

custom block for WordPress Gutenberg

2. Enqueue block script and style

Using the register_block_type function, we can enqueue the block’s script and style it with the Guttenberg.

1. Add the following function in the plugin.php file to enqueue the style and script.

function mcb_register_blocks() {

	// Check if Gutenberg is active.
	if ( ! function_exists( 'register_block_type' ) ) {
		return;
	}

	// Add block script.
	wp_register_script(
		'call-to-action',
		plugins_url( 'blocks/call-to-action/call-to-action.js', __FILE__ ),
		[ 'wp-blocks', 'wp-element', 'wp-editor' ],
		filemtime( plugin_dir_path( __FILE__ ) . 'blocks/call-to-action/call-to-action.js' )
	);

	// Add block style.
	wp_register_style(
		'call-to-action',
		plugins_url( 'blocks/call-to-action/call-to-action.css', __FILE__ ),
		[],
		filemtime( plugin_dir_path( __FILE__ ) . 'blocks/call-to-action/call-to-action.css' )
	);

	// Register block script and style.
	register_block_type( 'mcb/call-to-action', [
		'style' => 'call-to-action', // Loads both on editor and frontend.
		'editor_script' => 'call-to-action', // Loads only on editor.
	] );
}

add_action( 'init', 'mcb_register_blocks' );

2. Create the following files in the plugin folder to hold the style and script.

blocks/call-to-action/call-to-action.css
blocks/call-to-action/call-to-action.js

3. Register the block

After preparing the base, it’s now time to create the actual block.

1. In the call-to-action.js file, add the following function to register an empty block.

( function( blocks, editor, element ) {
	var el = element.createElement;

	blocks.registerBlockType( 'mcb/call-to-action', {
		title: 'MCB: Call to Action', // The title of block in editor.
		icon: 'admin-comments', // The icon of block in editor.
		category: 'common', // The category of block in editor.
		attributes: {},
		edit: function( props ) {
			return null;
		},
		save: function( props ) {
			return null;
		},
	} );
} )( window.wp.blocks, window.wp.editor, window.wp.element );
custom block for WordPress Gutenberg

2. For this block, we need both the content and button attributes. Add them as shown below.

attributes: {
	content: {
		type: 'string',
		default: 'Collaboratively customize web-enabled supply chains and turnkey collaboration and idea-sharing Assertively cultivate.'
	},
	button: {
		type: 'string',
		default: 'Join Today'
	}
},

3. In the edit function, we’re going to use the RichText component to create a div to hold the content and a span to hold the button. Basically, this component allows to create an editable text area.

The onChange function is responsible for updating the attributes when you change the block content.

edit: function( props ) {
	return (
		el( 'div', { className: props.className },
			el(
				editor.RichText,
				{
					tagName: 'div',
					className: 'mcb-call-to-action-content',
					value: props.attributes.content,
					onChange: function( content ) {
						props.setAttributes( { content: content } );
					}
				}
			),
			el(
				editor.RichText,
				{
					tagName: 'span',
					className: 'mcb-call-to-action-button',
					value: props.attributes.button,
					onChange: function( content ) {
						props.setAttributes( { button: content } );
					}
				}
			),
		)
	);
},
custom block for WordPress Gutenberg

4. In the edit function, we’re going to use the RichText component to generate the content and a HTML button to generate the button.

save: function( props ) {
	return (
		el( 'div', { className: props.className },
			el( editor.RichText.Content, {
				tagName: 'p',
				className: 'mcb-call-to-action-content',
				value: props.attributes.content,
			} ),
			el( 'button', { className: 'mcb-call-to-action-button' },
				props.attributes.button
			)
		)
	);
},

4. In the call-to-action.css, add the following codes to add some visual styling to the block.

.wp-block-mcb-call-to-action {
	background: #3f39ff;
	padding: 45px;
	text-align: center;
	border-radius: 10px;
}

.mcb-call-to-action-content {
	font-family: serif;
	font-size: 24px;
	color: #fff;
	padding-bottom: 30px;
	margin-bottom: 0;
}

.mcb-call-to-action-button {
	background: #000;
	border: 0px;
	border-radius: 5px;
	padding: 12px 35px;
	color: #fff;
	font-family: sans-serif;
}
custom block for WordPress Gutenberg

5. Now, you should be able to play with the block in the editor.

Wrapping Up

This post provided a basic introduction of what Gutenburg is and how we can create a custom block for WordPress Gutenberg. In other words, think about this article as the very first step in entering the Gutenberg world.

We recommend that you read the WordPress official handbook in order to gain a deeper understanding of the Gutenberg editor.

We’d love it if you would share your custom block with us in the comment section below!

How to Create a Custom Gutenberg Block Using the ACF Plugin

Due to its popularity – as well as its popularity in the WordPress community – the Advanced Custom Fields (ACF) plugin needs no introduction. In a nutshell, ACF has made the developer’s job a breeze for adding custom fields anywhere in WordPress, now it’s time to help them create a custom Gutenberg block using ACF.

Not surprisingly, Elliot Condon (the creator of ACF) hasn’t stopped there. He introduced a groundbreaking feature called ACF Blocks for Gutenberg in the ACF PRO version 5.8, which is a game changer for ACF and Gutenberg players.

In this article, let’s see how we can implement this in real life and create a custom Gutenberg block using ACF.

Note: This article requires the ACF PRO plugin version 5.8.0 and above. If you’re a Jupiter X user, you can activate the plugin from Control Panel > Plugins.

Before diving into writing codes

ACF is a simple yet advanced plugin. If you’re unfamiliar with the ACF plugin, we recommend that you read the following articles to build a good foundation before proceeding any further.

Create a custom Gutenberg block using ACF

Creating native custom Gutenberg blocks requires decent knowledge of JavaScript, which is not ideal for many users. The ACF Blocks feature is here to save time and help you to unlock your potential for creating custom Gutenberg blocks.

Let’s create a Blockquote block in a few simple steps.

custom Gutenberg block using the ACF

1. Prepare a base plugin

Let’s create a base plugin to hold the block codes. Depending on your preferences, you can use a child theme instead of a plugin.

1. Go to your plugins folder on your site, then create a my-acf-blocks folder.

custom Gutenberg block using the ACF

2. Create a plugin.php file as shown below.

custom Gutenberg block using the ACF

3. Activate the plugin from WordPress admin.

custom Gutenberg block using the ACF

2. Register a block

Using the acf_register_block_type() function, we can add a new block in Guttenberg with PHP. 

1. Add the following function in the plugin.php file to define the block properties.

function mab_register_acf_block_types() {
    acf_register_block_type( [
        'name'            => 'blockquote',
        'title'           => __( 'Blockquote' ),
        'description'     => __( 'My blockquote block.' ),
        'render_template' => dirname( __file__ ) . '/blocks/blockquote/blockquote.php',
        'category'        => 'formatting',
        'icon'            => 'format-quote',
    ] );
}

2. Hook into acf/init action to register the block.

if ( function_exists( 'acf_register_block_type' ) ) {
    add_action( 'acf/init', 'mab_register_acf_block_types' );
}
custom Gutenberg block using the ACF

3. Now you should be able to see the block in the Gutenberg editor. As you see, the block is empty and has no settings. In the next step, we’ll add some settings.

custom Gutenberg block using the ACF

3. Create a field group

To create the block settings, you need to register your settings in a field group.

1. Add a field group called Block: Blockquote in Custom Fields > Fields Group, then add the following fields (settings). There’s no limitation to add the fields but it’s recommended to keep it as few as possible.

2. In the Location, set the Block to Blockquote. By doing so, ACF will show the created fields (settings) for the Blockquote block.

3. Now, you should be able to see the settings in the Gutenberg editor. If you change the settings, nothing will happen. In the next step, we’ll implement the settings.

4. Render the block

Finally, we need to tell ACF how to render the block. This is just a standard process to get the settings and generate the HTML properly.

1. Create blockquote.php in the blocks/blockquote folder in your plugin, then add the following codes. The codes are based on standard ACF docs.

<?php

// Create id attribute allowing for custom "anchor" value.
$id = 'blockquote-' . $block['id'];
if ( ! empty( $block['anchor'] ) ) {
    $id = $block['anchor'];
}

// Create class attribute allowing for custom "className" and "align" values.
$className = 'blockquote';
if ( ! empty( $block['className'] ) ) {
    $className .= ' ' . $block['className'];
}
if ( ! empty( $block['align'] ) ) {
    $className .= ' align' . $block['align'];
}

// Load values and assign defaults.
$color = get_field( 'color' );
$quote = get_field( 'quote' ) ?: 'Your blockquote here...';
$author = get_field( 'author' ) ?: 'Author name';

?>
<div id="<?php echo esc_attr( $id ); ?>" class="<?php echo esc_attr( $className ); ?>">
    <blockquote class="mab-blockquote">
        <span class="mab-blockquote-text"><?php echo $quote; ?></span>
        <span class="mab-blockquote-author"><?php echo $author; ?></span>
    </blockquote>
</div>

2. Now you should be able to see the block in the Gutenberg editor. By default, it has some default values, which you can change by altering the Quote and Author settings.

3. Now, let’s spice it up by adding some styling. Add blockquote.css in the blocks/blockquote folder in your plugin, then add the following codes.

.mab-blockquote {
    padding: 50px 30px;
    text-align: center;
    border: 8px solid #ff3131;
}

.mab-blockquote-text {
    display: block;
    padding-bottom: 30px;
    font-size: 26px;
    font-family: serif;
}

.mab-blockquote-author {
    color: #777;
    font-family: sans-serif;
    font-size: 18px;
}

4. ACF can’t automatically detect the styling files. In other words, we need to tell it where to find the file. Add the enqueue_style param in the plugin.php file.

'enqueue_style'   => plugin_dir_url( __FILE__ ) . '/blocks/blockquote/blockquote.css',

5. Now, you should be able to see the block in the Gutenberg editor as shown below.

6. Now, let’s take another step and make the border color dynamic based on the Color setting. Open the blockquote.php file then do the following modifications.

<blockquote class="mab-blockquote" style="border-color:<?php echo $color; ?>;">

7. Now you should be able to set a different border color from the block settings.

Conclusion

Now that you have enough knowledge to create a custom Gutenberg block using ACF, you can create any type of custom blocks for Gutenberg.

We’d love to hear from you, so please share your custom blocks with us in the comment section below.

How to Create a Website with Google Sheets for Free

Honestly, I can’t believe my eyes, and I have to share what I just found out with you.  I recently stumbled across a service that I can use to power websites, apps or whatever else I want – all with a simple Google Sheet. This service is called Sheety, which I found on Product Hunt. In short, Sheety allows you to create a website with any Google Sheet and instantly turn it into an API – all for free.

Why build a website with Google Sheets

You’re probably wondering why you should build a website with Google Sheets when there are numerous services out there like WordPress.

And that’s a fair question. So let’s break it down: the idea behind Sheety and comparable tools is definitely not to replace services like WordPress as they are irreplaceable. That said, let’s briefly go over some benefits of building a website with Google Sheets, so you can decide if this is the tool for your project.

  • Google Sheet is basically a spreadsheet – and it’s free.
  • Almost anyone knows how to create/update a spreadsheet.
  • Spreadsheets can be easily stored and backed up.
  • Good for creating a quick and free personal site.
  • Suitable for rapid website prototyping.
  • Ideal for building a newsletter list.
  • No need to export/import your spreadsheets data.

Which service should I use?

As mentioned before, Sheety is one of these available services. There are alternatives to Sheety ranging from free to premium to help you to create your website.

For the purpose of this article, let’s use the Sheety service which is free yet powerful.

Sheety – turn your Google Sheet into an API

The Sheety service turns any Google Sheets into an API, so you can fetch your data in any website. Before getting the ball rolling, it’s a good idea to read the following articles to get more familiar with this service.

How to create a simple portfolio website with Google Sheets

Because nearly everyone needs a way to show off their work, portfolios are one of the most popular types of website. So then let’s create a simple portfolio website like the one you see below.

You can see the final live version on CodePen.

create a website with Google Sheets

Prepare a Google Sheet

1. Create a new Google Sheet, then add two sheets called Meta and Items.

create a website with Google Sheets

2. In the Meta sheet, add the Title, Read more and Footer data as shown below.

create a website with Google Sheets

3. In the Items sheet, add Title, Description, Tags and Screenshot columns as shown below. These columns will function as dummy data to populate the portfolio items.

create a website with Google Sheets

Connect the Google Sheet to Sheety

1. Sign into Sheety with your Gmail login information.
2. Add a new project, then set Project Name to Portfolio and Spreadsheet URL to your Google sheet and click on the Create button.

create a website with Google Sheets

3. Click on the Sync button to generate the API endpoints. After doing so, you should be able to see the Meta and Items endpoints.

create a website with Google Sheets

Prepare the website

For this article, I used the CodePen website. You can use any other services or create your own HTML in your local host.

1. Create a pen in CodePen and call it Sheety Portfolio.
2. Add Tailwind CSS framework. This is used to quickly create a visually appealing layout.

https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.2.0/tailwind.min.css

3. Add the Vue.js framework and Axios library, which are used to fetch data from API and populate the HTML properly.

https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js
https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js

4. Copy and paste the HTML and JS from this pen to your pen. There’s no need to explain the HTML and JS codes here since it’s outside the scope of this article. However, I did add some comments in the codes to help you understand the codes.

create a website with Google Sheets

5. Now, you should be able to see a website like in the first screenshot. From now on, as soon as you update your Google Sheet and refresh your pen, the new data will be automatically shown.

Conclusion

All-in-all, I’m glad that I found this Sheety website and shared this service with you. In this article, we first learned about a cool service to create a website with Google Sheets. Secondly, we created a simple websites to grasp the potential of these services.

It’d be cool to share your websites powered by Google Sheets with us in the comment section below.

How to Create a Community Poll Website with Jupiter X – Part 1

Recently, I was about to build an online community where users could create their own polls and share them on their social networks. Search results show that there are plenty of community poll platforms out there but none of them were what I actually needed. I wanted to create a community poll website that is:

  1. Cheap or free of charge
  2. Actively maintained and updatable
  3. Independent and installable on shared hostings
  4. Customizable with a minimum amount of coding
  5. Community based, meaning that the community of users should populate it with their content
  6. Loaded with a function that allows users to share the polls in their social networks
  7. Fully responsive and adaptable to mobile devices

After digging a lot and testing dozens of demos, I realized each platform lacks one of my requirements or the other. Then suddenly an idea popped into my mind: why not build up the community using WordPress? We recently moved our support platform to a community built by WordPress, BBpress and Jupiter X, which is working quite well.

Then why not build another community using the same tools? So then I thought that BBPress is a community builder and probably has tools I can customize to achieve what I want. The more I looked, the more I realized that it’s exactly what I want.

  1. It uses WordPress, which is free. The BBPress is also free.
  2. Both BBPress and WordPress are actively maintained.
  3. I can install both of them on any shared hostings.
  4. I can customize everything with the minimum amount of coding.
  5. It’s where the users will create polls with their own content. It’s a community after all.
  6. It allows me to share the polls with specific permalinks wherever I want.
  7. By using Jupiter X, it’ll be fully responsive and customizable.

So, I decided to give it a try and start building up my community using the tools I’ve got. The BBPress and WordPress definitely were not enough, and I needed more. Fortunately, nearly all of them were available, and I was able to easily access and use them.

In this article, I’m going to share my experience of creating a community poll website on a budget.

Defining the UX

More than anything, I wanted the website to be mobile friendly. I thought that maybe later I would want  to wrap the whole website into a webview and publish it for Android or iOS. This meant that I needed to consider everything to be fully responsive and think mobile first. I wanted something like the following:

Wireframe of the online community poll website

I also wanted the poll single pages to be something like this:

So, the experience would be like:

  • Viewers will enter the website and see the content and announcements that they need to register and login to vote and participate in the discussions below each poll. 
  • The registration will be completed as quickly as possible and without any unnecessary steps after clicking on the registration or login button on top.
  • After registration, the logged-in user will be redirected back to the page they were on before.
  • Voting and commenting under the votes are visible now after logging in
  • If user got back to the homepage, he can use Ajax search and filters to find an interesting poll and participate
  • The poll list in the homepage is showing the voted polls and not voted with a different color
  • After participating in each poll, whether the user votes on it or added a comment under it, it should send a notification to the user who created the poll.

Also, users have their own profile and clicking on the user name will navigate you to the user profile where you can see the user details, avatar and cover image, created polls, comments, favorite and followed polls. I didn’t want to create membership plans to monetize the website, but it should be possible to do it easily in future. 

So, things got complicated, huh? Don’t worry. We will get through this and see how we can do it step by step.

Prepare the tools

Creating a community poll website required two major functionalities:

  • Community
  • Membership profiles

I chose these two plugins that are absolutely free and popular among users:

Each of these plugins can extend their functionalities using add-ons. So I needed the following:

  • The GD Topic Polls for BBPress plugin makes it possible for the users to create polls.
  • The Real-time notifications for Ultimate Member plugin allows users to receive notifications whenever something happens (premium plugin).
  • GD bbPress Toolbox Pro. The only use for this plugin is to let users upload images and use the image as the poll thumbnail. While I could have developed this another way, this was the easiest solution and worth trying (premium plugin).
  • Comments – wpDiscuz is an advanced commenting plugin and adds functionality to the discussions. 
  • Optional: Digits : WordPress Mobile Number Signup and Login makes it possible to change the WordPress login and allows users to register with their phone numbers instead of emails and also verify the phone numbers using SMS (premium).
  • Jet Engine for its listing feature (premium)
  • The Jet Smart Filters plugin can be used for its advanced Ajax search and filtering features (premium).
  • The free version of Elementor can be used as the page builder
  • Raven (bundled with Jupiter X) was used for creating the custom header and footer.

I wanted to use the Jupiter X theme that already comes bundled with the Jet Engine and Jet Smart Filters. So, this means that two premium plugins were already provided for free. Also, it gave me the ability to build up my custom header and footer and visuals that I needed. So, I would definitely consider this theme as a base and choose the plugins that are compatible with it.

Creating a community poll website like this also requires some coding, which I’ll explain in the following paragraphs.

Step One: Install Jupiter X, Jet Engine and Jet Smart Filter and activate the child theme

The first step is to install Jupiter X and its bundled plugins, which provides an easy way to list the latest polls based on your design and allows you to use the smart filters to create an Ajax search. Also, since Jupiter X is a fully responsive theme, it allows you to implement the whole website to easily use as a mobile app.

After downloading the Jupiter X theme from ThemeForest, install it from Appearance -> Themes and register the product. A complete guide on how you can install and activate the theme is provided here.

Since we need to modify some files and add some customization here and there, it’s better to use a child theme to avoid change loss in the theme and plugin updates. So, right after installing the theme, you need to install and activate the Jupiter X child theme. You can find out how to do this by reading this article. It’s as simple as finding and installing the jupiterx-child.zip file inside the same package you downloaded from ThemeForest.Net.

The Jupiter X child theme package
Make sure the Jupiter X Child theme is your active theme

In order to install the bundled plugins, you need to register the theme first. So, try registering the theme like the guide provided here and make sure you can see that the theme is activated.

The Jupiter X theme is activated

Now you can install the bundled plugins. Simply navigate to Jupiter X -> Control Panel -> Plugins and install and then activate these plugins:

  • Elementor
  • Raven
  • Jet Engine
  • Jet Smart Filters
  • Advanced Custom Fields
The list of required active bundled plugins in Jupiter X for a community poll website

The Jupiter X Core plugin is mandatory, and you’ll need to install it right after installing the theme, so it’s also on the list. 

So, we are done here. Let’s move onto the next step.

Step Two: Install BBPress and its addons and configure

We’ll use BBPress as the main community builder on our website. Whenever you want your users to engage and provide content for your website and actually create a community of users, no matter what functionality you require, the BBPress is the best choice if you’re going to use a WordPress website as the backbone.

What we’re going to build with BBPress is one forum named Polls, then let the users create topics inside this forum and add a poll to their topics and publish it. Then, the other users can vote on each other’s polls and share it on their social networks. Also, we’re going to implement a notification and discussion board for each topic. So this means that the author is notified as soon as other users vote or add a comment to the poll. So, let’s start by adding the BBPress plugin.

In WordPress -> Plugins -> Add New, search for BBPress. Simply install and activate.

Activating the BBPress plugin

Now navigate to Settings -> Forums and change the Forum Root and Topic slugs to “polls” and “poll.” It’ll give you a better permalink structure for your polls as each topic means a poll on your website.

Configuring the main slugs for the forums and topics

After that, go to Forums and add a new forum to the website. This is our main forum that contains all of the polls. So, call it “Polls” again.

Adding the “Polls” forum to the website

Now that the main forum is added, we need to provide a way so our users can add their own topics that contain polls in this forum. But how can we do that? First let’s add a plugin that allows the topics to have polls inside. It’s called GD Topic Polls for BBPress

Go to Plugins -> Add New, search for it and then install and activate it.

Activating GD Topic Polls for the BBPress plugin

The next step is to create a page and add a form to it where users can create topics and polls.

Step Three: Add the “Create Poll” page

We need the polls to be created by the users – but all from the front end. We don’t want them to come to the WordPress dashboard to be able to create a new poll. That’s one of the reasons we wanted to create our website using a community builder.

So, create a page and add this BBPress shortcode to it:

[bbp-topic-form forum_id=29 ]
Adding the new poll page

Remember to change the 29 with the forum ID.

Getting the forum ID for the [ bbp-topic-forms ] shortcode.

The result will be a page like this in the front end:

create a community poll website
New topic form

As you can see, the form is created and that page and the Create New Topic Poll is located at the end. Check the “Add poll to this topic” to see the poll form.

create a community poll website
Default Add New Poll form

Try sending a new poll, and see the results. You’ll be able to add as many responses as you want or choose how many responses are allowed.

create a community poll website
Submitting the topic with the poll

After submitting the form, you’ll be redirected to the topic, and you’ll be able to see the topic with the poll above that.

create a community poll website
Topic with its poll after creation

Congratulations! We’re nearly there. Before finishing, there are a few more things we need to take care of. First, I don’t want users to create a topic and then the polls. I only want Polls. So I need to somehow hide the topic or the poll title and description since I have two of them.

create a community poll website
Extra fields and notices to remove

Technically, I just need to hide the extra fields and notices. Some of them can hide via CSS and some of them can get hidden by actions. However, the easiest solution would be to use the child theme and override the BBPress and GD Polls for BBPress Topics template files in it. It’s as easy as copying/pasting the proper files and the plugin template folder to my “jupiterx-child” folder and editing them.

So, from wp-content/plugins/bbpress/templates/default/bbpress/ I’ll copy the form-topic.php to wp-content/themes/jupiterx-child/bbpress/form-topic.php and then edit its codes and remove the extra fields and notices and save the file.

I should also do the same for the poll form files that are located in wp-content/plugins/gd-bbpress-toolbox/templates/default/bbpress/ and named as

  • gdpol-poll-edit.php
  • gdpol-poll-form.php
  • gdpol-poll-new.php

So I’ll copy them to the jupiterx-child/bbpress/ folder as well.

create a community poll website
Hiding the poll title and description fields

In the gdpol-poll-form.php I commented out the poll title and description fields, and instead, created two hidden fields with constant values to fill the poll description and title. This is required since the poll will not be created if the values are empty. I’ll use the Topic title and description on the polls page.

The result is now like the following:

create a community poll website

I would like to let the users add a thumbnail to their polls as well. This thumbnail can be used in asking users’ opinions if they want to see an image before answering the poll. Adding an image to the topics are not allowed by default, so I need to find a plugin to add it or develop this part on my own.

By using the GD BBPress Toolbox Pro plugin, it’s entirely possible to attach media to the topics and assign the first attachment as the topic thumbnail. It also allows you to control the attachment for the different roles. You can control the size of the image and choose from the allowed extensions. It also provides safety and security for the user file uploads. So, I’ll use this plugin and configure it like this:

create a community poll website
Configuring the attachment settings for the BBPress topics

Also, I would like to only allow the gif, png, and jpg mime types to be uploaded. So from the top General button, I’ll choose the “Allowed Types” and then select my desired file types.

create a community poll website
Allowing certain mime types to be uploaded by the users

There is also another setting that needs to be configured. We need to make sure the attachment will be considered as the topic thumbnail. So, simply choose the “Integration” from the button above and then check the “Auto Generate Featured Image” for the Topics and save the settings.

create a community poll website

Now I’ll need to style the topic creation form a little bit and hide some fields via CSS. In order to do that, I’ll write this CSS fix in jupiterx-child/assets/less/style.less and let the Jupiter X built in compiler enque it to the website. Remember to uncomment this line in jupiterx-child/functions.php before doing that:

jupiterx_add_smart_action( ‘wp_enqueue_scripts’, ‘jupiterx_child_enqueue_scripts’, 8 );

jupiterx-child/assets/less/style.less:

#gdpol-poll-status,
#wc-comment-header,
.wc_stick_btn.wc-cta-button,
.wc_close_btn.wc-cta-button,
.bbp-form.gdpol-topic-poll-form legend,
.d4p-attachment-addfile,
a.gdbbx-attachment-add-file,
.gdbbx-attachment-control>div:nth-child(3),
.gdbbx-attachment-control>div:nth-child(4),
.wc-field-submit .wpd_label {
    display: none !important;
}

.gdpol-fields-wrapper {
    display: block !important;
    border: none !important;
}

.bbp-form .gdbbx-attachments-form .gdbbx-validation-active .gdbbx-attachment-preview {
    float: left !important;
    margin-left: 0 !important;
}

.bbp-form .gdbbx-attachments-form .gdbbx-validation-active .gdbbx-attachment-control {
    float: left;
    margin-left: 15px;
}

.gdbbx-attachments-form {
    text-align: left !important;
}

ul.gdpol-responses-list li span._button:last-of-type {
    padding-left: 4px;
    width: 38px
}

form#new-post {
    max-width: 500px;
    margin: auto;
}

input#bbp_topic_tags,
#bbp_topic_title {
    width: 100%;
}

select.gdpol-select-choices.gdpol-field-extra-select {
    width: 100% !important;
    max-width: 100%;
}

.gdpol-field.gdpol-field-regular label {
    width: 100%;
}

Now let’s take a look at our poll creation page:

create a community poll website
The poll creation page after removing extra fields and styling

Simple, clean and quick as desired. Try submitting a new topic with the attachment and watch it work.

Stay tuned for the second part of this two-part blog series as I’ll show you how to style the single topics page, add membership profiles and implement a notification system. Also, we’ll need to display a list of the polls (topics) created and add filters and search options to it and show it on the homepage.

Extend Gutenberg with Free Blocks

Released in late 2018, the WordPress Gutenberg editor is getting more and more popular by the day. By default, it has some blocks for you to kickstart creating a website, but they are far from enough to create a professional website. To do this, you’ll need to install some add-ons to access advanced blocks.In this article, we’ve included some popular, free plugins to help you extend Gutenberg with free blocks. Now let’s briefly name and introduce the plugins.

Note: It’s worth mentioning that the following statistics are relevant to when this article was written. These figures might have changed by the time you read this article.

Page Builder Gutenberg Blocks – CoBlocks

extend Gutenberg with free blocks - coblocks

CoBlocks contains an amazing archive of page building blocks to be used with the Gutenberg WordPress block editor.

One of the best features of CoBlocks is that the page builder is robust but lightweight, which means that you’ll be able to get maximum functionality without compromising on performance.

Read more about CoBlocks on WordPress.org

Specifications

Gutenberg Blocks – Ultimate Addons for Gutenberg

This add-on simplifies that website building process. It provides you with several  unique and creative blocks for Gutenberg that help you create pages or posts without writing a single line of code.

Read more about Gutenberg Blocks on WordPress.org

Specifications

  • 200,000+ active installations
  • 20 blocks
  • Frequent updates
  • 5 star rating
  • Translated to 6 languages
  • Compatible with free popular Gutenberg ready themes
  • Pre-built templates
  • Documentation and support friendly.
  • Block management to help you enable/disable the blocks.
  • Developed by Brainstorm Force.

Kadence Blocks – Gutenberg Page Builder Toolkit

extend Gutenberg with free blocks - kadence

This plugin adds custom blocks and options to extend Gutenberg’s editing capabilities so you can create custom layouts and more engaging content.

This plugin is meant to be a toolkit that makes the WordPress block editor capable of creating content usually only possible through popular page builder plugins.

Read more about Kadence Blocks on WordPress.org

Specifications

  • 50,000+ active installations
  • 12 blocks (interactive demo).
  • Frequent updates
  • 5 stars rating.
  • Translated to 3 languages.
  • Compatible with free popular Gutenberg ready themes.
  • Block management to help you enable/disable the blocks.
  • Documentation and support friendly.
  • Developed by Kadence WP.

Atomic Blocks – Gutenberg Blocks Collection

extend Gutenberg with free blocks - atomic blocks

Atomic Blocks is a collection of page building blocks for the new Gutenberg block editor.

On top of the handy, time-saving blocks already found in Atomic Blocks, this plugin has a new Section and Layout block! This block comes with a library of pre-designed sections and layouts to help you quickly and easily build a beautiful site with the new block editor.

Read more about Atomic Blocks on WordPress.org

Specifications

  • 40,000+ active installations
  • 15 blocks
  • Frequent updates
  • 4.5 stars rating.
  • Translated to 7 languages.
  • Default theme and compatible with free popular Gutenberg ready themes.
  • Pre-designed sections and layouts.
  • Documentation and support friendly.
  • Block management to help you enable/disable the blocks.

Stackable – Gutenberg Blocks

extend Gutenberg with free blocks - stackable

Stackable is one of the first and most expansive block libraries made specifically for the new WordPress Block Editor (Gutenberg).

It adds essential custom blocks to Gutenberg’s arsenal to achieve a smooth page building experience.

Read more about Stackable on WordPress.org

Specifications

  • 20,000+ active installations
  • 23 blocks (interactive demo)
  • Frequent updates
  • 5 stars rating.
  • Translated to 5 languages
  • Default theme and compatible with free popular Gutenberg ready themes.
  • Documentation and support friendly.
  • Block management to help you enable/disable the blocks.

Advanced Gutenberg

advanced gutenberg

Advanced Gutenberg adds the missing blocks and configuration you need to build professional websites.

This plugin helps you to take control of the new Gutenberg editor with a user edition profile configuration.

Read more about Advanced Gutenberg on WordPress.org

Specifications

  • 20,000+ active installations
  • 27 blocks
  • Frequent updates
  • 4.5 stars rating.
  • Translated to 3 languages
  • Compatible with free popular Gutenberg ready themes.
  • Documentation and support friendly.
  • Block management to help you enable/disable the blocks.

Conclusion

In this article, we did our homework and briefly presented some helpful plugins to extend Gutenberg with free blocks. Gutenberg is becoming more and more popular in the WordPress community, which will lead to the development of more add-ons.

Feel free to share your favorite Gutenberg add-on with us in the comments.

Two Techniques to Crop Images in CSS

During the past couple of years, CSS has been improved rapidly with many features now possible in pure CSS. There are several websites that provide tutorials and introductions for CSS features. One of the best among all of them is MDN Web Docs.

The MDN site contains interactive examples, allowing you to learn many of the current and upcoming features. It also shows the browser compatibility table so you can understand the coverage of whichever feature in different browsers.

One of the features needed for nearly all websites is cropping images. Many websites rely on PHP, Node and other programming languages to crop images. But let’s not get bogged down in programming languages and focus on two CSS techniques that rely less on these languages. Sometimes, we just need to hide a part of an image instead of actually cropping the image.

Using object-fit and object-position to crop images in CSS

The object-fit and object-position properties in CSS allow developers to have control over images and videos similar to the way they have control of background images. These two properties offer a wide range of usages in pure to crop images in CSS and position them within a container.

Exploring the object-fit property

The object-fit property tells the content – like an image – to respond in certain ways to its content box (the black border in the below images). By using object-fit, you can tell an image to fill the content box by keeping or ignoring its aspect ratio.

This property can accept five values according to the standards. You can view the following examples live in CodePen. Each example shows an image that is contained in a content box that has a different width.

The contain value

The image is scaled to maintain its aspect ratio while fitting within the content box. The entire image is made to fill the box while preserving its aspect ratio.

img { object-fit: contain; }
Crop Images in CSS 1

The cover value

The image is sized to keep its aspect ratio to fill the entire content box. If the image’s aspect ratio isn’t the same as the aspect ratio of the box, then the image will be clipped to fit.

img { object-fit: cover; }
Crop Images in CSS 2

The fill value

The image is sized to fill the content box. If the object’s aspect ratio isn’t the same as the box’s aspect ratio, then the image will be stretched to fit it.

img { object-fit: fill; }
Crop Images in CSS 3

The none value

The image will not be resized.

img { object-fit: none; }
Crop Images in CSS 4

The scale-down value

The image is sized as if none or contain were specified, which results in smaller concrete image size.

img { object-fit: scale-down; }
Crop Images in CSS 5

Putting the object-position property into practice

This property is a game-changer in positioning the images when using object-fit. It works similarly to the background-position property.

This property can accept different values according to the standards. You can view the following examples live in CodePen.

Values can be directions (top, left, right) or numeric (10px, 20%).

img { object-position: top left; }
img { object-position: 100px 50px; }

Using width, height and overflow to crop images in CSS

This method sounds like a workaround but it has its own use cases. In this technique, we use width, height and overflow properties in CSS.

You can view the following example live in CodePen.

  1. Add a div can give it class container.
  2. Set width and height to 150px then set the overflow to hidden.
  3. Use margin to position the image based on your needs. In this case, set it to -100px 0 0 -150px.

Conclusion

The object-fit property is a popular and modern method used to crop images in CSS. This feature is well supported among modern browsers, meaning that you can make use of it without worrying about compatibility issues.

The object-fit technique can be used in many different cases, but it might not be a perfect solution for every website. In some websites, we need actual background cropping to prevent loading large images.

We’ve used the object-fit technique in the Raven plugin for the Jupiter X theme, which made the development a breeze. Feel free to share your use cases in the comment section below.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

Everything You Need to Know about WordPress Development Workflow

WordPress Development Workflow Featured

It’s no secret that WordPress is the most popular CMS in the world. Due to its popularity, there are a number of tools and services out there you can use to simplify your WordPress development workflow and improve the delivery time of your project. In this blog post, we’re going to take a look at these tools and services, as well as a few methods you can use to better develop websites.

Local or remote development

When it comes to developing WordPress themes, you’ll need to set up a development environment suited to WordPress. To get started, you’ll need to choose a decent hosting environment for your project, which can be a local environment or a live website. Both have their advantages and disadvantages as well as different methods and tools. Let’s take a closer look.

Local environment – Ideally, the web development for any project always flows in one direction: local → staging → production. This is a proven method for avoiding collisions. All core, plugin and theme updates are first done locally, then tested in staging and finally deployed to production.

A local environment or local server is a web server that runs on a personal computer and is used for development. In other words, it’s not used to make the website available for others on the internet.

Benefits of a local environment:

  • Themes and plugins testing: In your local environment, you can try out as many themes and plugin combinations as you want without risking taking your live site out due to incompatibilities.
  • Safe updates: With a local environment, you can update WordPress core and components to see if there are any problems before applying the updates to your live site.
  • No internet needed to work: With the WordPress site on your computer, you can work on it without being connected to the internet. This means that you can get work done even if there is no WiFi.
  • Best performance: Since site performance is not limited by an online connection, local sites usually run much faster, which makes for a better WordPress development workflow.
  • Low or no cost: You can set everything up with free software and eliminate the need for a paid staging area.

Furthermore, there is a variety of services that you can make use of:

1. Local by Flywheel – This is the easiest way to install and deploy your website from local to remote.

WordPress Development Workflow Flywheel

2. MAMP – This stands for Macintosh, Apache, MySQL, and PHP and allows you to set up a localhost environment on OS X. A beta version is also available for Windows. MAMP is free, but there’s also a premium version available with the ability to set up any number of virtual servers, as well as the option to install WordPress automatically.

WordPress Development Workflow Mamp

3. XAMPP – This is a free and open-source localhost PHP development environment available for Windows, OS X, and Linux. The Apache Friends website includes a fantastic forum for users who run into trouble and need some help.

4. DesktopServer – DesktopServer is extremely easy to set up as it can take as little as five minutes to get WordPress up and running on your local machine. Unfortunately, if you want to use a multisite setup then you’ll have to upgrade to the premium version.

5. WampServer – WampServer is a popular Windows web development environment that allows you to create web applications with Apache2, PHP and MySQL.

The above five services don’t make up a comprehensive list but instead are the most popular. Of course, other local services exist on the market that enables you to work on a project in the local environment.

Remote environment – The remote environment is made up of hosting providers. In this case, if you’re working directly on a live website, any changes you make are published immediately (that is, as long as you’re not using Staging). This setup is the easiest to maintain, as new configuration options or software need to be deployed in one place only.

Hosting companies today offer the best technologies ever, starting from syncing in multiple servers to CLI technology. There is also dedicated WordPress hosting that is focused only on WordPress website hosting and their infrastructure is specially optimized to host WordPress CMS. We are not going to review hosting companies because there are thousands of reviews on the net.

Choosing a starter theme?

When building a WordPress site, one of the most significant decisions you’ll make is which theme to use. There is a plethora of themes available for you to choose from – each of which has its own pros and cons. This post will break down and compare two major theme types, frameworks and starter themes.

What exactly is a WordPress starter theme? It’s a blank theme with minimal design. It comes with either a basic layout or without a layout at all. Usually, such themes come with the most commonly used templates in a WordPress theme.

In WordPress starter themes, you’ll find all the required template files, including the basic CSS styles and functionalities that are required to create a WordPress theme. These themes come with the code to help you display posts, comments, and archive pages, with minimum or no styling. This saves you the effort of creating everything from scratch.

With these themes, developers can start adding their own styles to create an entirely new and fresh theme. These differ from the parent themes that usually completely style WordPress themes, which can be directly installed and used on live websites. A starter theme or child theme can be used to create a parent theme. As discussed, starter themes come with no styling, but you can add those.

Let’s check some starter themes to see what they offer:

Underscores – Underscores is one of the most popular WordPress starter themes. It comes with an ultra-minimal CSS, which means that you’re free to write your own CSS stylesheets when creating your WordPress theme as there is less stuff to bother the developer.

A large number of WordPress developers have already used Underscore to create both free and premium WordPress themes. The majority of the codebase in _s is well-optimized with comments on nearly every function and call. It is one of the best options for SASS users as it comes with a SASS configuration as well.

Sage – Sage – formerly known as Roots – is a more feature-heavy starter theme that focuses on offering a few different capabilities from the start. It ships with Gulp/Bower supporting a “modern WordPress development workflow,” which means that you can quickly compile SASS into the normal CSS.

This means that you are able to spot any possible bugs or mistakes as you make them as opposed to writing a ton of code, then compiling and testing later, only to struggle to find out what’s breaking your site when everything is put together the way it will be when it goes live. (With the CSS compiled and JS minified into a single file etc.)

Genesis – Genesis is a long-time staple of the WordPress general user – and more importantly – the developer community. It’s a premium framework made for working with child themes.

Genesis has a big community of developers working with it, which means that not only are there lots of people you can connect with and learn from (with lots of tutorials available online), there are also a ton of genesis specific plugins.

If you’re looking to work with a trusted framework, Genesis is the right choice for you. While Genesis is not free, there is no developer option and the basic price ($59.99) includes unlimited domains, even if you’re developing sites for clients.

Bones – This is a bare-bones (no pun intended) starter theme that is perfect for a starting developer. The well-documented CSS makes it easy for beginners to go in and make significant changes to mold the theme into their own design.

Bones is a great choice if you’re a beginner to WordPress but already know some CSS/HTML and can’t wait to get your hands dirty.

So, this leads us to a question: What is the Best WordPress Starter Theme?

There’s no one theme that is universally the best choice for everyone. While there are a lot of great starter themes and frameworks out there, these stand out from the pack in many ways. If you’ve picked a starter theme or framework to work with, please let us know in the comments. We would also love to hear about your progress as a WP developer.

Best plugins for development

WordPress plugins for developers are rated highly by developers since they help ease their WordPress development workflow. I’ve done the research (so you don’t have to!) and found that the following 10 WordPress plugins stand out as the most useful plugins for developers.

Theme Check – This plugin checks your new theme against the current coding standards and all the requirements for the theme to be functional. If you want to develop themes that are up to WordPress standards, this plugin is a must-have. It helps you keep up with the WordPress coding standards without worrying about likely mistakes in your code.

Debug Bar – This adds an admin bar to your WordPress admin, providing a central location for debugging. I like this plugin since I can tell from a single click the total queries, total queried time and memory usage – all of which is absolutely useful for debugging. This plugin also shows you PHP warnings and notices, but you need to ensure your WordPress error reporting is enabled in wp-config.php

Query Monitor – This allows for the debugging of database queries, API request and AJAX called used to generate theme pages and theme functionality.

Monster Widget – The Monster Widget consolidates the core WordPress widgets into a single widget, which allows you to test widgets styling and functionality in your theme.

Developer – This is the ultimate plugin for testing your WordPress development environment. This plugin checks and ensures that your development environment is configured correctly including the plugins, constants and other settings.

What The File – This plugin allows you to see the files being used to render a particular page. The best thing about this plugin is that when you’re on the frontend of the page on the WordPress bar, you can actually see the template files list used for building this page. You can also click on the files, and you’ll be directed to the file editor page.

Version Control – No more cowboy coding

Do you know what cowboy coding means? Well, if you don’t, then let me tell you. Cowboy coding is when you or your team download a file from the FTP and then upload the changed files and refreshes the page in the hope to see the changes. This is not only inefficient but dangerous!

This WordPress version control helps you track changes to your WordPress site to monitor what’s happening and roll back those changes if needed. Those changes could be simple tweaks like edits to a post or more technical changes like edits to your site’s codebase. Something like a demo version of version control is a built-in WordPress feature that you may know as a WordPress revision feature.

WordPress Development Workflow Feature

This feature enables you to compare the current state of the post to the previous version. This is how version control works. Aside from this, you can also implement a third-party version control system in your project which will highly improve control over your project. For starters, let’s explore why you would use version control and what it can offer in improving your WordPress development workflow.

First of all, version control is used to protect you from unexpected changes. Did you make changes that messed something up? No worries, you can restore your site with a few clicks. The second major benefit of version control is working with a team. Your work will be more efficient, and you’ll be able to control everything everywhere. Moreover, if you are using branching and merging, you’ll be able to copy part of your site’s code to work on and then “merge” that code back into your live site when it’s ready for production.

Best use cases for WordPress Version Control

There are several methods and tools to use in WordPress for version controlling. I’ve gone ahead and listed the best below:

Git – It’s a little more technical, but it’s one of the most popular version control systems. Git is used by all types of developers. If you want to use Git, you have to use hosted repositories like Github, Bitbucket or Gitlab and then deploy your site from that repository to your live server.
To automate the deployment of your code onto the live server, you have several options at your disposal. WP Pusher and Revisr are some of the popular tolls.

VersionPress is an open-source project that aims to “bring the full power of Git to WordPress” by version controlling both your site’s files and database. Though, it also relies on Git. The unique thing about VersionPress is that it tracks every little change and does it in natural human language.

For example, instead of just logging a change to your database, VersionPress will tell you that someone “updated the Hello World!” post. Obviously, this makes Git a lot more useful and accessible in the context of a WordPress website.

WordPress Development Workflow VersionPress

WP Rollback – This only works for themes and plugins from WordPress.org, which means that you can roll back the previous version of your theme or plugins that were downloaded from the WordPress repository. Let’s say that your plugin update breaks something that you can’t fix immediately. (First of all, you have to use the staging site for this) WP Rollback can be used to roll back to the previous version of the plugin.

The plugin adds a rollback button to any WordPress theme or plugin, which makes the rollback feature very easy to operate.

WordPress Development Workflow Final

Final thoughts

The methods and tools that we reviewed in this post – plus dozens of others – can be found on the internet, but we compiled a list of the most popular ones to help dramatically improve your WordPress development workflow.

The tools used in developing your projects might change from one to another, however certain methods and approaches should be kept the same – such as version control in any situation and always backing up before updating your site.

If you enjoyed this article, please share with us the tools and methods that you are using to develop your projects. We’d love to hear from you!

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

How to Create a Shortcode in WordPress – Beginner’s Guide

Shortcodes are the swiss knife feature in the WordPress world. They allow you to add dynamic content to any page, post or sidebar easily. They look like small pieces of codes, but they enable you to run a small or big function on any place of your site quickly.

Shortcodes are displayed inside square brackets like: [ gallery ] and they can accept attributes depending on their features like: [ gallery id=”123″ size=”medium” ]

Built-in Shortcodes

By default, WordPress includes a few built-in shortcodes. Some of them are helpful for daily use.

  • [ caption ] – allows you to wrap captions around content.
  • [ gallery ] – shows image galleries.
  • [ audio ] – embeds and plays audio files.
  • [ video ] – embeds and plays video files.
  • [ playlist ] – displays a collection of audio or video files.
  • [ embed ] – allows you to wrap embedded items.

Useful Ready-to-use Shortcodes

The WordPress community has created many plugins to offer ready-to-use shortcodes for users. Most of the plugins are free and only one click away from your site. Here, we mention a few of them, and you can find more in WordPress plugin directory.

Using a Shortcode in WordPress

Thanks to the nature of shortcodes, there are different methods to use them almost anywhere in WordPress.

Use in Gutenberg (new WordPress editor)

As you know, Gutenburg is the new default editor in WordPress, and it provides a user-friendly UI to create your content. To use a shortcode, just add a Shortcode block.

Shortcode in WordPress Gutenburg

Use in TinyMCE (old WordPress editor)

TinyMCE was the default WordPress editor before and some people still prefer to use it. To use a shortcode, simply add your shortcode in the editor.

Shortcode in WordPress Tiny

Use in Elementor

Elementor is a popular page builder for WordPress. The Jupiter X theme also uses this page builder as the primary page builder.

Using shortcodes in Elementor is straightforward by using the Shortcode element.

Shortcode in WordPress Elementor

Use in Sidebars/Widget Areas

The text widget allows you to use shortcodes in sidebars/widget areas.

Shortcode in WordPress Widgets

Use in the WordPress Menu

By default, there is no way to use shortcodes in the WordPress Menu, to enable this feature, you need to install and active Shortcode in Menus plugin.

Use in Theme/Plugin Files

In some cases, we need to use the shortcodes in theme/plugins PHP files. Fortunately, WordPress provided a built-in function to help us.

<?php echo do_shortcode( '[your-shortcode]' ); ?>

Different Methods to Create a Shortcode in WordPress

Normally, there are two methods to create a shortcode in WordPress. Each method has its own pros and cons depending on your needs.

  • Using plugins (intended for normal users)
  • Writing code (intended for developers)

Using Plugins to Create a Shortcode in WordPress

The WordPress community is highly active and created some free plugins to help normal users create shortcodes directly from the WordPress dashboard. Let’s cover two of them from there.

Shortcoder Plugin

This plugin allows users to create a custom shortcode and store HTML, JavaScript and other snippets in it.

Features

  • Create custom shortcodes easily and use them within WordPress.
  • Use any kind of HTML as shortcode content.
  • Insert custom/WordPress parameters in the shortcode.
  • Visual editor for adding shortcode content.
  • Globally disable the shortcode when not needed.

Create a Basic Shortcode

1. Install and activate the Shortcoder plugin.

2. Go to Settings > Shortcoder page, then click on the Create a new shortcode button.

3. Fill out the settings as shown below then click on the Create shortcode button.

Shortcode in WordPress Shortcode

4. Voila! Now you can use the shortcode as previously explained.

Shortcode Maker Plugin

This plugin helps you to create a shortcode by yourself or choose built-in shortcodes to use them easily.

Features

  • You can use built-in shortcodes to create widgets like tabs, alerts, accordions, tables, etc…
  • Add as many attributes as you want with the ability to define a default value.
  • You can write the PHP code in definition. To use code, use [php_code][/php_code] in your shortcode definition and place the code inside it.
  • Bootstrap v4.0.0 compatible

Create a Basic Shortcode

1. Install and activate the Shortcode Maker plugin.

2. Go to Shortcode > Add New Shortcode page then fill out the settings as shown below and hit the Publish button.

3. Voila! Now you can use the shortcode as previously explained.

Writing Codes to Create a Shortcode in WordPress.

Being able to write codes in WordPress, opens an infinite possibility for creating shortcodes. Let’s create a basic shortcode in WordPress in 2 simple steps. After following the steps, you can use the shortcode in WordPress as explained before.

For this tutorial, we’ll use the Code Snippets plugin to add the codes. You may use a child theme or write a plugin to add the codes.

1. Write the Shortcode Callback Function

Each shortcode requires a function to run when it is called. This function can be a basic/advanced function.

function artbees_hello_wordpress() {
     return 'Hello WordPress';
 }

2. Registering the Shortcode

Now that we have the function, we’ll register the shortcode with the add_shortcode function in WordPress and start to use it. This function accepts two parameters: The name of the shortcode and the callback function that we wrote in the previous section.

Add the following codes in a new snippet then click on the Save Changes and Activate button.

function artbees_hello_wordpress() {
     return 'Hello WordPress';
 } 

add_shortcode( 'hello_wordpress', 'artbees_hello_wordpress' );

Shortcodes vs. Gutenberg Blocks

Shortcodes and Gutenburg blocks have some similarities in concept, and both can help you to get the job done faster.

If you find the shortcodes helpful, you’ll like Gutenburg blocks. Popular plugins switch to Gutenburg blocks instead of shortcodes since they are more innovative and user-friendly.

Summary

The handy shortcode feature in WordPress has helped many people to write fewer codes in their daily job. In this article, we introduced shortcodes and covered two methods to create a basic shortcode in WordPress. Shortcodes have a wide-ranging use in WordPress, so feel free to share yours in the comment section below!

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

How to Add a Custom Setting Page in WordPress

In the previous post about WordPress custom admin pages, we defined a custom admin page and explained how to add a new admin page to WordPress.

One of the most important usages of WordPress custom admin pages is the Settings Pages. Almost every plugin has custom setting pages, which allows developers to have an option page for their plugin. Some plugins like Akismet ask for integration codes and others have the option to enable or disable their features. WooCommerce has several options to customize shop, and all of them are implemented using Settings API.

In this post, we’ll delve into how to create a custom setting page in WordPress for what we created in the previous post. We’ll also add a new setting and the required UI for it. We’ll then save and use this saved value on the site.

Adding a new setting in WordPress

In order to add new settings to WordPress, we have to use WordPress Settings API. Settings API is a core API that allows developers to add a new custom setting page in WordPress.

This includes functions to register settings, setting the section and setting fields, form rendering and error handling.

Before adding settings

For the first step, we need to make sure we have a form and that it’s set to work with options.php. In the following code that we have a call back function to generate the heading, we need to load settings for the API functions to let our custom settings work with WordPress.

The code from the previous post about how to have a custom admin page can be accessed here.

We need to change the my_admin_page_contents function to the following:

function my_admin_page_contents() {
    ?>
    <h1> <?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' ); ?> </h1>
    <form method="POST" action="options.php">
    <?php
    settings_fields( 'sample-page' );
    do_settings_sections( 'sample-page' );
    submit_button();
    ?>
    </form>
    <?php
}

We just loaded the setting fields and the setting sections (which we will create) and added a submit button to save them.

Settings section

A setting section is part of the WordPress settings API which allows developers to have a group of settings under a heading. It’s possible to add a setting section to an existing WordPress admin page or to a new custom admin page.

Here, we are going to add a new setting section to our custom admin page.

Adding a new setting section

Now, we’ll go ahead and use the add_settings_section function to have a new setting section in our custom admin page which have sample-page as the slug.

add_settings_section(
	'sample_page_setting_section',
	__( 'Custom settings', 'my-textdomain' ),
	'my_setting_section_callback_function',
	'sample-page'
);

In the above code, we have added a new setting section and the arguments are:

<?php add_settings_section( $id, $title, $callback, $page ); ?>

$id A custom slug for the setting section.
$title Setting section title. Make sure it is translatable.
$callback A function that adds markups to the settings section.
$page The page slug that we want to add our settings section.

As we have used a callback function (my_setting_section_callback_function), let’s define it.

my_setting_section_callback_function( $args ) {
	echo '<p>Intro text for our settings section</p>';
}

And let’s wrap our codes to a new function to call it on admin_init.

add_action( 'admin_init', 'my_settings_init' );

function my_settings_init() {

    add_settings_section(
        'sample_page_setting_section',
        __( 'Custom settings', 'my-textdomain' ),
        'my_setting_section_callback_function',
        'sample-page'
    );
}

function my_setting_section_callback_function() {
    echo '<p>Intro text for our settings section</p>';
}

The result will be like the following:

Custom Setting Page in WordPress 1

Note that WordPress automatically adds a Save Changes button.

Settings fields

After having a section for our settings, which includes a title, custom markup and save button, it’s time to have some real settings that will allow us to get some inputs. In order to do that, we’ll use the settings_fields function.

settings_fields function is not only for having settings and input markups, but it also adds nonce and takes care of security as well as adds the required actions and functionality to make sure our settings will work.

Adding a new setting field

The usage of the settings_fields function is like

add_settings_field(
   'my_setting_field',
   __( 'My custom setting field', 'my-textdomain' ),
   'my_setting_markup',
   'sample-page',
   'sample_page_setting_section'
);

which is actually

<?php add_settings_field( $id, $title, $callback, $page, $section, $args ); ?>

and the arguments are:

$id A custom slug for the setting field.
$title Setting the field title.
$page The page slug of which we want to show setting field on it.
$section The section that we want to show setting field under it.
$args Extra arguments. See more here.

Like adding a setting section, we have a callback function that generates the markup.

function my_setting_markup() {
    ?>
    <label for="my_setting_field"><?php _e( 'My Input', 'my-textdomain' ); ?></label>
    <input type="text" id="my_setting_field" name="my_setting_field">
    <?php
}

We should wrap the settings_fields function to our my_settings_init function. So our code will be:

add_action( 'admin_init', 'my_settings_init' );

function my_settings_init() {

    add_settings_section(
        'sample_page_setting_section',
        __( 'Custom settings', 'my-textdomain' ),
        'my_setting_section_callback_function',
        'sample-page'
    );

		add_settings_field(
		   'my_setting_field',
		   __( 'My custom setting field', 'my-textdomain' ),
		   'my_setting_markup',
		   'sample-page',
		   'sample_page_setting_section'
		);

		register_setting( 'sample-page', 'my_custom_settings_options' );
}


function my_setting_section_callback_function() {
    echo '<p>Intro text for our settings section</p>';
}


function my_setting_markup() {
    ?>
    <label for="my_setting_field"><?php _e( 'My Input', 'my-textdomain' ); ?></label>
    <input type="text" id="my_setting_field" name="my_setting_field">
    <?php
}

And the output will be

Custom Setting Page in WordPress 2

If you try to save the settings, you may see some errors like option page not found. The reason is that we just added markups, but our settings are not registered to WordPress yet, and we’re not ready to save values to the WordPress database.

Registering custom settings in WordPress and saving values

The WordPress settings API has the needed functionality for getting and saving values from a setting. So we should use the register_setting function. Using the following code, we’ll register our settings in WordPress.

register_setting( 'sample-page', 'my_setting_field' );

Again, we need to use that in the init. So our code will be:

add_action( 'admin_init', 'my_settings_init' );

function my_settings_init() {

    add_settings_section(
        'sample_page_setting_section',
        __( 'Custom settings', 'my-textdomain' ),
        'my_setting_section_callback_function',
        'sample-page'
    );

		add_settings_field(
		   'my_setting_field',
		   __( 'My custom setting field', 'my-textdomain' ),
		   'my_setting_markup',
		   'sample-page',
		   'sample_page_setting_section'
		);

		register_setting( 'sample-page', 'my_setting_field' );
}


function my_setting_section_callback_function() {
    echo '<p>Intro text for our settings section</p>';
}


function my_setting_markup() {
    ?>
    <label for="my_setting_field"><?php _e( 'My Input', 'my-textdomain' ); ?></label>
    <input type="text" id="my_setting_field" name="my_setting_field">
    <?php
}

As a final step, we need to make sure we are showing the saved value in the form after getting back to our custom setting page in WordPress.

Let’s add the following code to the my_setting_markup function

value="<?php echo get_option( 'my_setting_field' ); ?>"

And it will be

function my_setting_markup() {
    ?>
    <label for="my_setting_field"><?php _e( 'My Input', 'my-textdomain' ); ?></label>
    <input type="text" id="my_setting_field" name="my_setting_field" value="<?php echo get_option( 'my_setting_field' ); ?>">
    <?php
}

Wrapping it up, we’ll have our plugin:

<?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>
    <form method="POST" action="options.php">
    <?php
    settings_fields( 'sample-page' );
    do_settings_sections( 'sample-page' );
    submit_button();
    ?>
    </form>
    <?php
}


add_action( 'admin_init', 'my_settings_init' );

function my_settings_init() {

    add_settings_section(
        'sample_page_setting_section',
        __( 'Custom settings', 'my-textdomain' ),
        'my_setting_section_callback_function',
        'sample-page'
    );

		add_settings_field(
		   'my_setting_field',
		   __( 'My custom setting field', 'my-textdomain' ),
		   'my_setting_markup',
		   'sample-page',
		   'sample_page_setting_section'
		);

		register_setting( 'sample-page', 'my_setting_field' );
}


function my_setting_section_callback_function() {
    echo '<p>Intro text for our settings section</p>';
}


function my_setting_markup() {
    ?>
    <label for="my-input"><?php _e( 'My Input' ); ?></label>
    <input type="text" id="my_setting_field" name="my_setting_field" value="<?php echo get_option( 'my_setting_field' ); ?>">
    <?php
}

Now, we have a custom admin page that includes a custom settings page in WordPress. We can save options in the database and retrieve and use it to implement complex functionalities in our plugins.

In order to get the saved value of the added setting, we can use the get_option function. The following code will return the saved value for setting that we have added in this post:

get_option( 'my_setting_field' );

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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!😉

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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( 'https://d34b8fs2z18t5a.cloudfront.net/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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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!

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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!

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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.

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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!

subscribe

Subscribe to Artbees Themes Blog for the best WordPress tips and insights.

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!

<