This is one of the website project from my friend at Rokin. His name his Martin and he is a a videographer for his own company MotionPark. For this project he had a clear idea what the website should look like. He had already made the design therefore everything was quite straight forward for me.

Website Overview

The website is the compilation of his portfolio. In the homepage will be a glimpse of what his expertises are. Moreover, he divided all of his past previous into 3 main categories. They are Experience, Showcases, and Broadcasting.  In each of this page, there will be a collage of his recent projects belonging for each category.  In addition, he also wants another section to list all of his expertises. These are animation, video editing, sound design, directing, and video sfx.

 

The Challenges

For me personally the challenge was for each of the project he has a specific templates. Every project in his portfolio has description, vimeo video and small picture. Therefore, it is a component based. For this website I decided to use make custom element in visual composer (width the option to select the title) as a results he can place it wherever he wants. These are the templates:

1. Big Project (title, video, description, image) – video on the left.

motionpark-showcases-template-1-2

2. Big Project (title, video, description, image) – video on the right.

motionpark-showcases-template-1-1

3. Small Project (title, video, description) – two per row

motionpark-showcases-template-1-3

 

The Solutions

After searching on the internet, these were the steps:

1. Create a new custom post type with CPT UI plugin, I called this post type “Showcases”

2. Create a custom field with ACF plugin for Showcases post type, this is a filed to placed vimeo embed url. I decided to use the default featured image, description, and title field.

This is what it looks like after the step 1 and 2. As you can see here we have created new custom post type with an extra field. Therefore, It is now very convenient for the user just to placed the embedded vimeo link here.

motion-park-showcases-cpt

3. Make a custom element in Visual Composer plugin.

The Backend

I have another post explaining how to make custom element in visual composer. In brief,  you need a class to extend the WPBakeryShortcode. These are vc_**_mapping element and the vc_**_html element. Please see the example below. In this case I decided to name the class vcShowcase extending the WPBakeryShortcode and for the elements vc_showcase_mapping and vc_showcase_html.

Registering the custom element

/*
Element Description: Get featured Showcases
*/
 
// Element Class 
class vcShowcase extends WPBakeryShortCode {
     
    // Element Init
    function __construct() {
        add_action( 'init', array( $this, 'vc_showcase_mapping' ) );
        add_shortcode( 'vc_showcase', array( $this, 'vc_showcase_html' ) );
    }
     
    // Element Mapping
    public function vc_showcase_mapping() {
        
    } 
     
    // Element HTML
    public function vc_showcase_html( $atts ) {

    } 
     
} // End Element Class
 
// Element Class Init
new vcShowcase ();

The next thing is to define what are these two functions, the first one (vc_shocase_mapping()) is what we will see in the backend. We use this mapping to get input from the user. In this case, what we want is the title of the showcase, whether it is a big or small project (with or without picture), and the position of the video (left or right). We will do this by defining the parameter of the mapping.

Collecting user input

public function vc_showcase_mapping() {
     // Stop all if VC is not enabled
        if ( !defined( 'WPB_VC_VERSION' ) ) {
                return;
        }

        // query for your post type
        $post_type_query  = new WP_Query(  
            array (  
                'post_type'      => 'showcases',  
                'posts_per_page' => -1  
            )  
        );   
        // we need the array of posts
        $posts_array      = $post_type_query->posts;   
        // create a list with needed information
        // the key equals the ID, the value is the post_title

        $lists = array( __( ' ', 'js_composer' ) => 'id' );
        foreach ($posts_array as $posts) {
            $lists[$posts->post_title]= $posts->ID;
        };

        ksort($lists);
        // Map the block with vc_map()
        vc_map( 

            array(
                'name' => __('Showcase ', 'text-domain'),
                'base' => 'vc_showcase',
                'description' => __('Showcase', 'text-domain'), 
                'category' => __('Motion Park Custom Elements', 'text-domain'),   
                'icon' => get_template_directory_uri().'/assets/img/vc-motion-park-icon.png',            
                'params' => array(   
                    array(
                        'type' => 'dropdown',
                        'holder' => 'h3',
                        'class' => 'title-class',
                        'heading' => __( 'Title', 'text-domain' ),
                        'param_name' => 'id',
                        'value' => $lists,
                        'description' => __( 'Select the title', 'text-domain' ),
                        'admin_label' => false,
                        'weight' => 0,
                        'group' => 'Custom Group',
                    ),        
                    array(
                        'type' => 'dropdown',
                        'holder' => 'h3',
                        'class' => 'title-class',
                        'heading' => __( 'is this a big or small project', 'text-domain' ),
                        'param_name' => 'size',
                        'value' => array ('','big','small'),
                        'description' => __( 'is this a big or small project', 'text-domain' ),
                        'admin_label' => false,
                        'weight' => 0,
                        'group' => 'Custom Group',
                    ), 
                    array(
                        'type' => 'dropdown',
                        'holder' => 'h3',
                        'class' => 'title-class',
                        'heading' => __( 'video left or right', 'text-domain' ),
                        'param_name' => 'position',
                        'value' => array ('','left','right'),
                        'description' => __( 'video-position', 'text-domain' ),
                        'admin_label' => false,
                        'weight' => 0,
                        'group' => 'Custom Group',
                    ),   
                                
                )
            )
        );                                        
        //.. the Code is in the next steps ..//                           
    }

Code line 8-24 is to get all the titles already registered in the databases. In this case, we want all to the post belonging to post type “showcase” and from every post we want to get all the title and ID and placed them in an array. We named this array $lists. Line 34 is to sort the array therefore it is easier to select. We then define the mapping in line 28-70.  There are several fields you can filled in, such as name, base, description, category, icon. But the parameter is the most important, it contains what the user can fill in the backend.

User view

motion-park-backend

 

Here, we except three parameters (title:id, big/small, and position). This is what the user will see in the backend. There, you can select based on the title and also whether it is a big project and where the position of the video. Which is very neat!

The Frontend

The next thing to do is determine what the outcome will be. This is handled by vc_showcase_html(). Depending on the input we filled in, we can do conditional statements. Here is the code for it and return the $html element. We extract all the parameters and make them a variable. Based on the title and the id selected, we can get all the information for that particular posts.

   // Element HTML
    public function vc_showcase_html( $atts ) {
         
        extract(
            shortcode_atts(
                array(
                    'id'=> '',
                    'size'    => '',
                    'position'=> '',
                ), 
                $atts
            )
        );   // Params extraction
        $post  = get_post($id, OBJECT);
        $ID = $post->ID;
        $title = $post->post_title;
        $description = $post->post_content;
        $vimeo_embed = get_post_meta($ID,'video_url',true);
        $pict_url = get_the_post_thumbnail($ID);
        wp_reset_postdata();
        if ($size == 'big' && $position == 'right') {
            $html ='
            <div class="wpb_wrapper showcase-featured showcase-featured-big">
                <h2 class="vc_custom_heading vc_custom_1484839000727">'.$title.'</h2>
                <div class="vc_row wpb_row vc_inner vc_row-fluid vc_row-o-content-bottom vc_row-flex">
                    <div class="wpb_column vc_column_container vc_col-sm-5">
                        <div class="vc_column-inner ">
                            <div class="wpb_wrapper">
                                <div class="wpb_text_column wpb_content_element  home-paragraph">
                                    <div class="wpb_wrapper">
                                        <p style="text-align: left;">'.$description.'</p>
                                    </div>
                                </div>
                                <div class="wpb_single_image wpb_content_element vc_align_center">
                                    <figure class="wpb_wrapper vc_figure">
                                        <div class="vc_single_image-wrapper vc_box_border_grey home-page-cropped"><img class="vc_single_image-img " src="'.$pict_url.'">
                                        </div>
                                    </figure>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="wpb_column vc_column_container vc_col-sm-7">
                        <div class="vc_column-inner ">
                            <div class="wpb_wrapper">
                                <div class="vimeo-wrapper wpb_raw_code wpb_content_element wpb_raw_html">
                                    <div class="wpb_wrapper">
                                        '.$vimeo_embed.'
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            ';
        } elseif ($size == 'big' && $position == 'left'){
            $html ='
            <div class="wpb_wrapper showcase-featured showcase-featured-big">
                <h2 class="vc_custom_heading vc_custom_1484839000727 ">'.$title.'</h2>
                <div class="vc_row wpb_row vc_inner vc_row-fluid vc_row-o-content-bottom vc_row-flex">
                    <div class="wpb_column vc_column_container vc_col-sm-7">
                        <div class="vc_column-inner ">
                            <div class="wpb_wrapper">
                                <div class="vimeo-wrapper wpb_raw_code wpb_content_element wpb_raw_html">
                                    <div class="wpb_wrapper">
                                        '.$vimeo_embed.'
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="wpb_column vc_column_container vc_col-sm-5">
                        <div class="vc_column-inner ">
                            <div class="wpb_wrapper">
                                <div class="wpb_text_column wpb_content_element  home-paragraph">
                                    <div class="wpb_wrapper">
                                        <p style="text-align: left;">'.$description.'</p>
                                    </div>
                                </div>
                                <div class="wpb_single_image wpb_content_element vc_align_center">
                                    <figure class="wpb_wrapper vc_figure">
                                        <div class="vc_single_image-wrapper vc_box_border_grey home-page-cropped"><img class="vc_single_image-img " src="'.$pict_url.'">
                                        </div>
                                    </figure>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            ';
        } elseif ($size == 'small') {
            $html ='
                <div class="vc_column-inner ">
                    <div class="wpb_wrapper showcase-featured showcase-featured-small">
                        <h2 class="vc_custom_heading">'.$title.'</h2>
                        <div class="wpb_raw_code wpb_content_element wpb_raw_html vimeo-wrapper">
                            <div class="wpb_wrapper">
                                '.$vimeo_embed.'
                            </div>
                        </div>
                        <div class="wpb_text_column wpb_content_element home-paragraph">
                            <div class="wpb_wrapper">
                                <p style="text-align: left;">'.$description.'</p>
                            </div>
                        </div>
                    </div>
                </div>
            ';
        }
         
        return $html;
         
    }

After all that effort, this is what it looks like on the website. What is so special about this element is that the user have freedom to play around with the website because it is very super friendly.

motion-park-final

Finally, please visit MotionPark.nl. This is truly one of the first website that I talk to the client and custom-built it from nothing. I really learnt a lot about WordPress and working with visual composer. While at the same time, also thinking about how user-friendly it is for the owner to update the website in the future. See you in my next post!

 

About the Author

Damar Anggoro

Voyager lv. 0

Born and raised in Indonesia. I have spent 10 years in Europe and wandered around. Currently living and exploring Bali but have to spend 1 month per year in Europe. Father of one amazing baby girl.

View All Articles