Custom WPBakery Carousel Element

User
create wp bakery custom element for caursel items grid for 3 columns in desktop and 1 column in mobile , wp bakery has already owl caursel installed
Assistant
To create a **custom WPBakery Page Builder element** for a carousel grid with 3 columns on desktop and 1 column on mobile using **Owl Carousel**, you need to:

1. **Register the new element** in WPBakery.
2. **Render the HTML structure** with Owl Carousel.
3. **Add custom CSS and JavaScript** to control the carousel.

### Steps to Create the Custom WPBakery Element:

#### 1. **Register the Element** in Your Theme
Add the following code to your theme's `functions.php` file or a custom plugin:

if (function_exists('vc_map')) {
    add_action('vc_before_init', 'custom_carousel_grid_element');

    function custom_carousel_grid_element() {
        vc_map(array(
            "name" => __("Custom Carousel Grid", "text-domain"),
            "base" => "custom_carousel_grid",
            "category" => __("Custom Elements", "text-domain"),
            "description" => __("Carousel with 3 columns on desktop and 1 column on mobile", "text-domain"),
            "params" => array(
                array(
                    "type" => "textfield",
                    "heading" => __("Element Title", "text-domain"),
                    "param_name" => "title",
                    "description" => __("Enter the title of the carousel.", "text-domain"),
                ),
                array(
                    "type" => "textarea_html",
                    "heading" => __("Carousel Items", "text-domain"),
                    "param_name" => "content",
                    "description" => __("Add the carousel items here. Use HTML or shortcodes.", "text-domain"),
                ),
                array(
                    "type" => "css_editor",
                    "heading" => __("CSS", "text-domain"),
                    "param_name" => "css",
                    "group" => __("Design Options", "text-domain"),
                ),
            )
        ));
    }

    // Shortcode Rendering
    function render_custom_carousel_grid($atts, $content = null) {
        $atts = shortcode_atts(array(
            'title' => '',
            'css' => ''
        ), $atts);

        $css_class = vc_shortcode_custom_css_class($atts['css'], ' ');

        // Output the carousel HTML
        ob_start();
        ?>
        <div class="custom-carousel-grid <?php echo esc_attr($css_class); ?>">
            <?php if (!empty($atts['title'])): ?>
                <h3 class="carousel-title"><?php echo esc_html($atts['title']); ?></h3>
            <?php endif; ?>

            <div class="owl-carousel owl-theme">
                <?php echo wpb_js_remove_wpautop($content, true); ?>
            </div>
        </div>
        <?php
        return ob_get_clean();
    }
    add_shortcode('custom_carousel_grid', 'render_custom_carousel_grid');
}

#### 2. **Enqueue Owl Carousel JS and CSS**
Ensure that **Owl Carousel** is loaded in your theme if it's not already loaded. Add the enqueue script in your `functions.php`:

function enqueue_custom_carousel_assets() {
    wp_enqueue_style('owl-carousel', get_template_directory_uri() . '/assets/css/owl.carousel.min.css');
    wp_enqueue_style('owl-theme-default', get_template_directory_uri() . '/assets/css/owl.theme.default.min.css');
    wp_enqueue_script('owl-carousel', get_template_directory_uri() . '/assets/js/owl.carousel.min.js', array('jquery'), null, true);
    wp_enqueue_script('custom-carousel-init', get_template_directory_uri() . '/assets/js/custom-carousel-init.js', array('jquery', 'owl-carousel'), null, true);
}
add_action('wp_enqueue_scripts', 'enqueue_custom_carousel_assets');

Place the `owl.carousel.min.css` and `owl.carousel.min.js` files into your theme’s `assets/css` and `assets/js` folders.

#### 3. **Initialize Owl Carousel**
Create a JS file named `custom-carousel-init.js` in your `assets/js` folder and add the following:

jQuery(document).ready(function ($) {
    $(".owl-carousel").owlCarousel({
        loop: true,
        margin: 30,
        responsive: {
            0: {
                items: 1 // 1 column for mobile
            },
            768: {
                items: 2 // 2 columns for tablets
            },
            1024: {
                items: 3 // 3 columns for desktop
            }
        },
        autoplay: true,
        autoplayTimeout: 3000,
        autoplayHoverPause: true,
        nav: true,
        dots: true
    });
});

#### 4. **Adding Content in WPBakery**
1. Go to WPBakery Page Builder.
2. Add the **Custom Carousel Grid** element.
3. Insert content such as:

<div class="carousel-item">Item 1</div>
<div class="carousel-item">Item 2</div>
<div class="carousel-item">Item 3</div>
<div class="carousel-item">Item 4</div>

#### 5. **Add Custom CSS for Styling**
Add some CSS to style the items and container. Place this in your theme's CSS file:

.custom-carousel-grid .carousel-title {
    text-align: center;
    margin-bottom: 20px;
    font-size: 24px;
}

.owl-carousel .carousel-item {
    background-color: #f7f7f7;
    text-align: center;
    padding: 30px;
    border: 1px solid #ddd;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    border-radius: 5px;
}

### Result:
– On **Desktop**, 3 carousel items will display side by side.
– On **Mobile**, only 1 carousel item will display at a time.
– Owl Carousel will handle the sliding behavior, autoplay, and navigation.

This structure integrates seamlessly with WPBakery, and you can reuse the **Custom Carousel Grid** element on any page.

User
allow multiple title and content for each item
Assistant
To allow **multiple titles and content for each item** in the custom WPBakery element, you can use the **param group** feature of WPBakery. This allows users to dynamically add multiple items with their own titles and content.

### Updated Code for WPBakery Custom Element:

Replace the previous code with the following. This version supports dynamic input for multiple items.

#### 1. **Register the Element with Param Group**

Update the `custom_carousel_grid_element` function in `functions.php`:

if (function_exists('vc_map')) {
    add_action('vc_before_init', 'custom_carousel_grid_element');

    function custom_carousel_grid_element() {
        vc_map(array(
            "name" => __("Custom Carousel Grid", "text-domain"),
            "base" => "custom_carousel_grid",
            "category" => __("Custom Elements", "text-domain"),
            "description" => __("Carousel with 3 columns on desktop and 1 column on mobile", "text-domain"),
            "params" => array(
                array(
                    "type" => "textfield",
                    "heading" => __("Element Title", "text-domain"),
                    "param_name" => "title",
                    "description" => __("Enter the main title of the carousel.", "text-domain"),
                ),
                array(
                    "type" => "param_group",
                    "heading" => __("Carousel Items", "text-domain"),
                    "param_name" => "items",
                    "description" => __("Add carousel items.", "text-domain"),
                    "params" => array(
                        array(
                            "type" => "textfield",
                            "heading" => __("Item Title", "text-domain"),
                            "param_name" => "item_title",
                            "description" => __("Title for this carousel item.", "text-domain"),
                        ),
                        array(
                            "type" => "textarea",
                            "heading" => __("Item Content", "text-domain"),
                            "param_name" => "item_content",
                            "description" => __("Content for this carousel item.", "text-domain"),
                        ),
                    ),
                ),
                array(
                    "type" => "css_editor",
                    "heading" => __("CSS", "text-domain"),
                    "param_name" => "css",
                    "group" => __("Design Options", "text-domain"),
                ),
            )
        ));
    }

    // Shortcode Rendering
    function render_custom_carousel_grid($atts) {
        $atts = vc_map_get_attributes('custom_carousel_grid', $atts);
        extract($atts);

        $css_class = isset($css) ? vc_shortcode_custom_css_class($css, ' ') : '';

        // Output the carousel HTML
        ob_start();
        ?>
        <div class="custom-carousel-grid <?php echo esc_attr($css_class); ?>">
            <?php if (!empty($title)): ?>
                <h3 class="carousel-main-title"><?php echo esc_html($title); ?></h3>
            <?php endif; ?>

            <div class="owl-carousel owl-theme">
                <?php 
                if (!empty($items)) {
                    $items = vc_param_group_parse_atts($items);
                    foreach ($items as $item) {
                        $item_title = isset($item['item_title']) ? esc_html($item['item_title']) : '';
                        $item_content = isset($item['item_content']) ? wp_kses_post($item['item_content']) : '';
                        ?>
                        <div class="carousel-item">
                            <?php if ($item_title): ?>
                                <h4 class="item-title"><?php echo $item_title; ?></h4>
                            <?php endif; ?>
                            <div class="item-content">
                                <?php echo $item_content; ?>
                            </div>
                        </div>
                        <?php
                    }
                }
                ?>
            </div>
        </div>
        <?php
        return ob_get_clean();
    }
    add_shortcode('custom_carousel_grid', 'render_custom_carousel_grid');
}

#### 2. **Add CSS for Styling**

Update the CSS to style the titles and content for each carousel item:

.custom-carousel-grid .carousel-main-title {
    text-align: center;
    margin-bottom: 20px;
    font-size: 28px;
}

.owl-carousel .carousel-item {
    background-color: #f9f9f9;
    padding: 20px;
    border: 1px solid #ddd;
    text-align: center;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
    margin: 10px;
}

.owl-carousel .item-title {
    font-size: 20px;
    margin-bottom: 10px;
    color: #333;
}

.owl-carousel .item-content {
    font-size: 16px;
    color: #555;
}

#### 3. **Enqueue JavaScript (Owl Carousel Initialization)**

Ensure you have the Owl Carousel JS properly initialized. The previous initialization script works fine:

jQuery(document).ready(function ($) {
    $(".owl-carousel").owlCarousel({
        loop: true,
        margin: 30,
        responsive: {
            0: {
                items: 1 // 1 column for mobile
            },
            768: {
                items: 2 // 2 columns for tablets
            },
            1024: {
                items: 3 // 3 columns for desktop
            }
        },
        autoplay: true,
        autoplayTimeout: 3000,
        autoplayHoverPause: true,
        nav: true,
        dots: true
    });
});

### How It Works in WPBakery:
1. Go to WPBakery Page Builder.
2. Add the **Custom Carousel Grid** element.
3. Input the **main title** of the carousel.
4. Add multiple carousel items by clicking **"Add"** in the "Carousel Items" group:
– Enter an **Item Title**.
– Enter **Item Content** (HTML or text).

### Result:
– You can now add multiple items, each with their **own title and content**.
– On **Desktop**, 3 items will display in a row.
– On **Mobile**, only 1 item will display at a time.
– Owl Carousel handles the carousel behavior with navigation and autoplay.

Let me know if you need further customization! 🚀

User
we are using
textarea_html but when click on add more textarea
Assistant
WPBakery does not allow the use of `textarea_html` inside `param_group`. Instead, we need to replace `textarea_html` with a simple `textarea`. This limitation is because `textarea_html` conflicts with dynamically added fields in the **param group**.

### Updated Code:
Replace `textarea_html` with `textarea` inside the `param_group` definition:

#### Fixed WPBakery `param_group` Registration:

if (function_exists('vc_map')) {
    add_action('vc_before_init', 'custom_carousel_grid_element');

    function custom_carousel_grid_element() {
        vc_map(array(
            "name" => __("Custom Carousel Grid", "text-domain"),
            "base" => "custom_carousel_grid",
            "category" => __("Custom Elements", "text-domain"),
            "description" => __("Carousel with 3 columns on desktop and 1 column on mobile", "text-domain"),
            "params" => array(
                array(
                    "type" => "textfield",
                    "heading" => __("Element Title", "text-domain"),
                    "param_name" => "title",
                    "description" => __("Enter the main title of the carousel.", "text-domain"),
                ),
                array(
                    "type" => "param_group",
                    "heading" => __("Carousel Items", "text-domain"),
                    "param_name" => "items",
                    "description" => __("Add carousel items.", "text-domain"),
                    "params" => array(
                        array(
                            "type" => "textfield",
                            "heading" => __("Item Title", "text-domain"),
                            "param_name" => "item_title",
                            "description" => __("Title for this carousel item.", "text-domain"),
                        ),
                        array(
                            "type" => "textarea",
                            "heading" => __("Item Content", "text-domain"),
                            "param_name" => "item_content",
                            "description" => __("Content for this carousel item (HTML supported).", "text-domain"),
                        ),
                    ),
                ),
                array(
                    "type" => "css_editor",
                    "heading" => __("CSS", "text-domain"),
                    "param_name" => "css",
                    "group" => __("Design Options", "text-domain"),
                ),
            )
        ));
    }

    // Shortcode Rendering
    function render_custom_carousel_grid($atts) {
        $atts = vc_map_get_attributes('custom_carousel_grid', $atts);
        extract($atts);

        $css_class = isset($css) ? vc_shortcode_custom_css_class($css, ' ') : '';

        // Output the carousel HTML
        ob_start();
        ?>
        <div class="custom-carousel-grid <?php echo esc_attr($css_class); ?>">
            <?php if (!empty($title)): ?>
                <h3 class="carousel-main-title"><?php echo esc_html($title); ?></h3>
            <?php endif; ?>

            <div class="owl-carousel owl-theme">
                <?php 
                if (!empty($items)) {
                    $items = vc_param_group_parse_atts($items);
                    foreach ($items as $item) {
                        $item_title = isset($item['item_title']) ? esc_html($item['item_title']) : '';
                        $item_content = isset($item['item_content']) ? wp_kses_post($item['item_content']) : '';
                        ?>
                        <div class="carousel-item">
                            <?php if ($item_title): ?>
                                <h4 class="item-title"><?php echo $item_title; ?></h4>
                            <?php endif; ?>
                            <div class="item-content">
                                <?php echo $item_content; ?>
                            </div>
                        </div>
                        <?php
                    }
                }
                ?>
            </div>
        </div>
        <?php
        return ob_get_clean();
    }
    add_shortcode('custom_carousel_grid', 'render_custom_carousel_grid');
}

### Key Fixes:
1. **Replaced `textarea_html`** with `textarea` in the `param_group` since WPBakery does not support rich text editors (TinyMCE) within dynamic groups.
2. The `textarea` still allows basic HTML input for content (e.g., “, “, etc.).
3. The shortcode now properly renders multiple items added dynamically.

### How It Works:
1. In **WPBakery**, when you add the `Custom Carousel Grid` element:
– Use the "Add" button in the **Carousel Items** section to add multiple items.
– Each item has fields for:
– **Item Title** (simple text input).
– **Item Content** (supports plain text or basic HTML).
2. On the frontend:
– Each item displays its title and content in a carousel slide.

### Result:
This fix ensures smooth behavior when adding multiple carousel items dynamically. Let me know if you need further refinements! 🚀

Leave a Comment

Your email address will not be published. Required fields are marked *