3

I'm working on my WordPress website with Visual Composer.

I need to include a pageable container but it would be great if it can be like a slideshow.

This is my pageable container

Thanks in advance,

Regards :)

AlbertoV
  • 141
  • 2
  • 4
  • 14

3 Answers3

6

Based upon the current version of WP Bakery Page Builder the below works for me:

To build it I created a row with 3 columns, with the pageable container in the middle column and the left and right arrow images in the columns on either side.

Both arrow images and the pageable container were given IDs. In my example the IDs of the arrows were #arrow_prev and #arrow_next respectively. You can give your pageable container any unique ID.

(function ($) {

$(document).ready(function(){

    $( '#arrow_prev' ).click( function( e ) {
        var pageable_container = $(this).closest(".vc_row").find(".vc_tta-panels-container");
        move_pageable_container(pageable_container,'prev');
    });

    $( '#arrow_next' ).click( function( e ) {
        var pageable_container = $(this).closest(".vc_row").find(".vc_tta-panels-container");
        move_pageable_container(pageable_container,'next');
    });

    function move_pageable_container(pageable_container,direction){

        // Make a list of the panel IDs
        var panel_ids = $(pageable_container.find(".vc_tta-panel"))
            .map(function() { return this.id; }) // convert to set of IDs
            .get();

        // Find position of the active panel in list
        var current_active_pos = panel_ids.indexOf($(pageable_container).find(".vc_tta-panel.vc_active").attr('id'));

        var new_pos = 0;

        switch(direction) {
            case 'prev':
                if (current_active_pos > 0){
                    new_pos = current_active_pos-1;
                }else{
                    new_pos = panel_ids.length-1;
                }
                break;
            case 'next':
                if (current_active_pos < panel_ids.length-1){
                    new_pos = current_active_pos+1;
                }else{
                    new_pos = 0;
                }
            break;
        }

        // Clear active panels
        $(pageable_container.find(".vc_tta-panel")).each(function(i,a) {
            $(this).removeClass("vc_active");
        });

        var new_active_panel = $(pageable_container).find('#'+ panel_ids[new_pos]);

        $(new_active_panel).addClass("vc_animating");
        $(new_active_panel).addClass("vc_active");

        setTimeout(
            function(){
                $(new_active_panel).removeClass("vc_animating");
        }, 350);
    }

}
);
})(jQuery);

If you want a pseudo fading-in effect then you can use this additional CSS in your style sheet:

#id_of_pageable_container .vc_tta-panel.vc_animating {
     opacity: 0!important;
}

Where #id_of_pageable_container is the ID that you gave your pageable container

Chaz
  • 114
  • 1
  • 3
  • Thank you for this solution! :) – DaniPilot Sep 13 '19 at 11:46
  • This seems a bit buggy, did you optimize it after? Like slow anymation (sometime don't load, crops) – FilipeOS Jul 02 '20 at 15:44
  • I can't seem to get a pageable container inside of a row/column - it is not even an option for me. What am I missing? – Dustin Sep 03 '20 at 06:09
  • @Dustin - In WP Bakery you cannot put a pageable container within a nested row - could this be your issue? – Chaz Oct 12 '20 at 09:22
  • @FilipeOS - sorry you're having problems - the animation effects are leveraged from WP Bakery itself, the script just triggers them. I'd get a vanilla pageable container working smoothly first and then work from there. – Chaz Oct 12 '20 at 09:38
2

A simpler solution with vanilla js only:

The idea is to find the target page button and press it programmatically, so that there is no need to mimic the plugin's animations as in Chaz's solution.

  1. Add js (via Raw JS widget / other means):
function prevSlide () {
    const slides = document.getElementsByClassName('vc_pagination-item');
    for (let i = 0; i < slides.length; i++) {
        if (slides[i].className.includes('vc_active')) {
            if (i - 1 < 0) return;
            slides[i - 1].firstChild.click();
            return;
        }
    }
}
function nextSlide () {
    const slides = document.getElementsByClassName('vc_pagination-item');
    for (let i = 0; i < slides.length; i++) {
        if (slides[i].className.includes('vc_active')) {
            if (i + 1 >= slides.length) return;
            slides[i + 1].firstChild.click();
            return;
        }
    }
}
  1. Add button widgets and set href to call js:

For left arrow button,

javascript:prevSlide();

For right arrow button,

javascript:nextSlide();

Hope this helps.

Elliot Ng
  • 21
  • 1
  • 1
0

I prefer to use the Post Grid widget for that. Keep in mind that the pageable container is not totally responsive, it doesn't react to swipe touching, but the Post Grid does.

Post Grid is really powerful, although it also has its caveouts. You can create your content with posts and pages, or a custom post type and then filter what you want to show in your slider from the widget options.

In "advanced mode" you can use the Grid Builder to create your own template and control the output.

The only problems that I've found with this method is to set a variable height in sliders and that sometimes it is slow loading content and is not possible to do a lazyload.

Jorge
  • 831
  • 13
  • 18