Informations

Ingredients

  • WordPress v4.5+required
  • Visual Composer Plugin v4.x+required
  • Directly related tutorialrequired
  • Basic PHP/WP knowledge

STEPS

Most of themes today are based on Google Fonts so I always needed to build by myself a select with the list of Fonts. Then I stopped to waste my time discovering the Visual Composer’s Google Font integrated field. Well, this tutorial will explain how to use it, but before to start I strongly suggest you read the basic tutorial to Create a new Element in Visual Composerrequired
Note: the Tutorial will improve the code already explained in the related tutorial I just linked.

1. Where to include your code

We’ll edit the custom element we just created through the related tutorial (our amazing “VC Infobox“). At the end of tutorial we’ll be able to apply a Google Font to the text of our element. We’ll edit the code in 3 points: improving the mapping, adding some functions and editing the HTML.

2. Add the Google Fonts field to your custom element

Visual Composer already has a Google Fonts field and we only need to add it in the vc_map() function. Below I propose the entire mapping code from the related tutorial adding the field we need to the end:
// Map the block with vc_map()
vc_map( 
	array(
		'name' => __('VC Infobox', 'text-domain'),
		'base' => 'vc_infobox',
		'description' => __('Another simple VC box', 'text-domain'), 
		'category' => __('My Custom Elements', 'text-domain'),	
		'icon' => get_template_directory_uri().'/assets/img/vc-icon.png',	 		
		'params' => array(	
				
			array(
				'type' => 'textfield',
				'holder' => 'h3',
				'class' => 'title-class',
				'heading' => __( 'Title', 'text-domain' ),
				'param_name' => 'title',
				'value' => __( 'Default value', 'text-domain' ),
				'description' => __( 'Box Title', 'text-domain' ),
				'admin_label' => false,
				'weight' => 0,
				'group' => 'Custom Group',
			),  
			
			array(
				'type' => 'textarea',
				'holder' => 'div',
				'class' => 'text-class',
				'heading' => __( 'Text', 'text-domain' ),
				'param_name' => 'text',
				'value' => __( 'Default value', 'text-domain' ),
				'description' => __( 'Box Text', 'text-domain' ),
				'admin_label' => false,
				'weight' => 0,
				'group' => 'Custom Group',
			),
			
			array(
				'type' => 'google_fonts',
				'param_name' => 'text_font',
				'settings' => array(
					'fields' => array(
						'font_family_description' => __( 'Select Font Family.', 'text-domain' ),
						'font_style_description' => __( 'Select Font Style.', 'text-domain' ),
					),
				), 
				'weight' => 0,
				'group' => 'Custom Group',                    
			),				
			   
		),
	)
);					  			  				  		

Code explanation

I will skip all code already explained.
  • row 38: This is the type name to include the Google Font field in your element.
  • rows 40-45: This is the strange way it uses to add the friendly descriptions below the fields
Now your Element will display a complete a and professional Google Fonts option (with its preview panel):

3. Add some useful functions to manage the Font Data

The field you just included in your Element will save many informations about the font in a simple encoded string so now we have to create 3 useful functions that will simplify the Font Data managing.
You can add them before to close the element’s Class.
Note: at the end of Tutorial you’ll find the complete code
//********************************//
// GOOGLE FONTS PRIVATE FUNCTIONS // 
//********************************//

// Build the string of values in an Array
protected function getFontsData( $fontsString ) {	

	// Font data Extraction
	$googleFontsParam = new Vc_Google_Fonts();		
	$fieldSettings = array();
	$fontsData = strlen( $fontsString ) > 0 ? $googleFontsParam->_vc_google_fonts_parse_attributes( $fieldSettings, $fontsString ) : '';
	return $fontsData;
	
}

// Build the inline style starting from the data
protected function googleFontsStyles( $fontsData ) {
	
	// Inline styles
	$fontFamily = explode( ':', $fontsData['values']['font_family'] );
	$styles[] = 'font-family:' . $fontFamily[0];
	$fontStyles = explode( ':', $fontsData['values']['font_style'] );
	$styles[] = 'font-weight:' . $fontStyles[1];
	$styles[] = 'font-style:' . $fontStyles[2];
	
	$inline_style = '';		
	foreach( $styles as $attribute ){			
		$inline_style .= $attribute.'; ';		
	}	
	
	return $inline_style;
	
}

// Enqueue right google font from Googleapis
protected function enqueueGoogleFonts( $fontsData ) {
	
	// Get extra subsets for settings (latin/cyrillic/etc)
	$settings = get_option( 'wpb_js_google_fonts_subsets' );
	if ( is_array( $settings ) && ! empty( $settings ) ) {
		$subsets = '&subset=' . implode( ',', $settings );
	} else {
		$subsets = '';
	}
	
	// We also need to enqueue font from googleapis
	if ( isset( $fontsData['values']['font_family'] ) ) {
		wp_enqueue_style( 
			'vc_google_fonts_' . vc_build_safe_css_class( $fontsData['values']['font_family'] ), 
			'//fonts.googleapis.com/css?family=' . $fontsData['values']['font_family'] . $subsets 
		);
	}
	
}

Code explanation

I used private functions because I only need theme here in my element, but they can be public too.
  • rows 06-14: This function transform the encoded string saved in the db in a handy array of data. You can print this array to understand what informations the array will contain (font family, font style, font weight, etc)
  • rows 17-27: This function instead transform the data array into a string for the inline style. Printing the result you will see someting like: font-family:’Abril fatface’; font-style: normal; font-weight: 400; etc etc..
  • rows 30-48: Here it’s maybe the most important function. It allow to enqueue the right font to the page using the Google Fonts apis.

4. Manage the Font Data and edit the element’s HTML

For the final step I attach the entire vc_infobox_html() function explaining the additional rows:
// Element HTML
public function vc_infobox_html( $atts ) {
	
	// Params extraction
	extract(
		shortcode_atts(
			array(
				'title'   => '',
				'text' => '',
				'text_font' => '',
			), 
			$atts
		)
	);
	
	//******************//
	// MANAGE FONT DATA //
	//******************//
	
	// Build the data array
	$text_font_data = $this->getFontsData( $text_font );
	
	// Build the inline style
	$text_font_inline_style = $this->googleFontsStyles( $text_font_data );	
			
	// Enqueue the right font   
	$this->enqueueGoogleFonts( $text_font_data );

	
	// Fill $html var with data
	$html = '
	<div class="vc-infobox-wrap">
	
		<h2 class="vc-infobox-title">' . $title . '</h2>
		
		<div class="vc-infobox-text" style="'.$text_font_inline_style.'">' . $text . '</div>
	
	</div>';		
	
	return $html;
	
} 

Code explanation

  • row 10: I added also new parameter “text_font” to the extraction function
  • row 21: I transformed the $text_font string into a data array using my custom function getFontsData()
  • row 24: I built the inline style passing the data array to my custom function googleFontsStyles()
  • row 24: I enqueued the font style passing the data array to my custom function enqueueGoogleFonts()
  • row 36: Finally I added the inline style to my text div style="'.$text_font_inline_style.'"

5. Result and Complete Code

This is our frontend result:
And this the complete code for your my-first-custom-element.php file:
/*
Element Description: VC Info Box
*/

// Element Class 
class vcInfoBox extends WPBakeryShortCode {
    
    // Element Init
	function __construct() {
        add_action( 'init', array( $this, 'vc_infobox_mapping' ) );
        add_shortcode( 'vc_infobox', array( $this, 'vc_infobox_html' ) );
    }
 	
    // Element Mapping
    public function vc_infobox_mapping() {
        
		// Stop all if VC is not enabled
		if ( !defined( 'WPB_VC_VERSION' ) ) {
            return;
        }
		
		// Map the block with vc_map()
		vc_map( 
			array(
				'name' => __('VC Infobox', 'text-domain'),
				'base' => 'vc_infobox',
				'description' => __('Another simple VC box', 'text-domain'), 
				'category' => __('My Custom Elements', 'text-domain'),	
				'icon' => get_template_directory_uri().'/assets/img/vc-icon.png',	 		
				'params' => array(	
						
					array(
						'type' => 'textfield',
						'holder' => 'h3',
						'class' => 'title-class',
						'heading' => __( 'Title', 'text-domain' ),
						'param_name' => 'title',
						'value' => __( 'Default value', 'text-domain' ),
						'description' => __( 'Box Title', 'text-domain' ),
						'admin_label' => false,
						'weight' => 0,
						'group' => 'Custom Group',
					),  
					
					array(
						'type' => 'textarea',
						'holder' => 'div',
						'class' => 'text-class',
						'heading' => __( 'Text', 'text-domain' ),
						'param_name' => 'text',
						'value' => __( 'Default value', 'text-domain' ),
						'description' => __( 'Box Text', 'text-domain' ),
						'admin_label' => false,
						'weight' => 0,
						'group' => 'Custom Group',
					),
					
					array(
						'type' => 'google_fonts',
						'param_name' => 'text_font',
						'settings' => array(
							'fields' => array(
								'font_family_description' => __( 'Select Font Family.', 'text-domain' ),
								'font_style_description' => __( 'Select Font Style.', 'text-domain' ),
							),
						), 
						'weight' => 0,
						'group' => 'Custom Group',                    
					),				
					   
				),
			)
		);					  			  
	   
    }
	
	
	// Element HTML
	public function vc_infobox_html( $atts ) {
		
		// Params extraction
		extract(
			shortcode_atts(
				array(
					'title'   => '',
					'text' => '',
					'text_font' => '',
				), 
				$atts
			)
		);
		
		//******************//
		// MANAGE FONT DATA //
		//******************//
		
		// Build the data array
		$text_font_data = $this->getFontsData( $text_font );
		
		// Build the inline style
		$text_font_inline_style = $this->googleFontsStyles( $text_font_data );	
				
		// Enqueue the right font   
		$this->enqueueGoogleFonts( $text_font_data );
		
	
		
		// Fill $html var with data
		$html = '
		<div class="vc-infobox-wrap">
		
			<h2 class="vc-infobox-title">' . $title . '</h2>
			
			<div class="vc-infobox-text" style="'.$text_font_inline_style.'">' . $text . '</div>
		
		</div>';		
		
		return $html;
		
	}
		
	//********************************//
	// GOOGLE FONTS PRIVATE FUNCTIONS // 
	//********************************//
	
	// Build the string of values in an Array
	protected function getFontsData( $fontsString ) {	
	
		// Font data Extraction
		$googleFontsParam = new Vc_Google_Fonts();		
		$fieldSettings = array();
		$fontsData = strlen( $fontsString ) > 0 ? $googleFontsParam->_vc_google_fonts_parse_attributes( $fieldSettings, $fontsString ) : '';
		return $fontsData;
		
	}
	
	// Build the inline style starting from the data
	protected function googleFontsStyles( $fontsData ) {
		
		// Inline styles
		$fontFamily = explode( ':', $fontsData['values']['font_family'] );
		$styles[] = 'font-family:' . $fontFamily[0];
		$fontStyles = explode( ':', $fontsData['values']['font_style'] );
		$styles[] = 'font-weight:' . $fontStyles[1];
		$styles[] = 'font-style:' . $fontStyles[2];
		
		$inline_style = '';		
		foreach( $styles as $attribute ){			
			$inline_style .= $attribute.'; ';		
		}	
		
		return $inline_style;
		
	}
	
	// Enqueue right google font from Googleapis
	protected function enqueueGoogleFonts( $fontsData ) {
		
		// Get extra subsets for settings (latin/cyrillic/etc)
		$settings = get_option( 'wpb_js_google_fonts_subsets' );
		if ( is_array( $settings ) && ! empty( $settings ) ) {
			$subsets = '&subset=' . implode( ',', $settings );
		} else {
			$subsets = '';
		}
		
		// We also need to enqueue font from googleapis
		if ( isset( $fontsData['values']['font_family'] ) ) {
			wp_enqueue_style( 
				'vc_google_fonts_' . vc_build_safe_css_class( $fontsData['values']['font_family'] ), 
				'//fonts.googleapis.com/css?family=' . $fontsData['values']['font_family'] . $subsets 
			);
		}
		
	}
	
} // End Element Class


// Element Class Init
new vcInfoBox();	

Your Personal Notes