Using sorting functionality along with DIVI Filterable Portfolio module

Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInPrint this page

DIVI provided by Elegant Themes is just great! Excellent functionality provided through their visual composer and modules, make things easy to manage and stunning layout creation a breeze.

Advanced Post Types order plugin provide total control over the content sorting for your DIVI powered website. Sorts are maintained easily through lists, which can apply globally or to different areas, independently, without conflicting with each other.

Recently we received questions upon the possibility to apply sorting for Filterable Portfolio module. Since the filtering is done on front side through a JavaScript code, the page does not refresh, making the customized order to do not apply for categories, except the All tab. The following code makes that possible. This create a new module called Filterable Portfolio – Sortable which should be used instead the default module.

First, we need to prepare the module loader. The following code should be placed within your theme child functions.php file:

    function DS_Custom_Modules()
        {
            if(class_exists("ET_Builder_Module"))
                {
                    include("divi-modules/filtrable-portfolio-sortable.php");
                }
        }

    function Prep_DS_Custom_Modules()
        {
            global $pagenow;

            $is_admin = is_admin();
            $action_hook = $is_admin ? 'wp_loaded' : 'wp';
            $required_admin_pages = array( 'edit.php', 'post.php', 'post-new.php', 'admin.php', 'customize.php', 'edit-tags.php', 'admin-ajax.php', 'export.php' ); // list of admin pages where we need to load builder files
            $specific_filter_pages = array( 'edit.php', 'admin.php', 'edit-tags.php' );
            $is_edit_library_page = 'edit.php' === $pagenow && isset( $_GET['post_type'] ) && 'et_pb_layout' === $_GET['post_type'];
            $is_role_editor_page = 'admin.php' === $pagenow && isset( $_GET['page'] ) && 'et_divi_role_editor' === $_GET['page'];
            $is_import_page = 'admin.php' === $pagenow && isset( $_GET['import'] ) && 'wordpress' === $_GET['import']; 
            $is_edit_layout_category_page = 'edit-tags.php' === $pagenow && isset( $_GET['taxonomy'] ) && 'layout_category' === $_GET['taxonomy'];

            if ( ! $is_admin || ( $is_admin && in_array( $pagenow, $required_admin_pages ) && ( ! in_array( $pagenow, $specific_filter_pages ) || $is_edit_library_page || $is_role_editor_page || $is_edit_layout_category_page || $is_import_page ) ) ) 
                {
                    add_action($action_hook, 'DS_Custom_Modules', 9789);
                }
        }
    Prep_DS_Custom_Modules();

The following code is the module. Since the above calls divi-modules/filtrable-portfolio-sortable.php file, the code should be placed within filtrable-portfolio-sortable.php inside a folder named divi-modules.

<?php
class ET_Builder_Module_Filterable_Portfolio_Sortable extends ET_Builder_Module_Type_PostBased {
function init() {
$this->name       = esc_html__( 'Filterable Portfolio Sortable', 'et_builder' );
$this->slug       = 'et_pb_filterable_portfolio_sortable';
$this->vb_support = 'on';
$this->main_css_element = '%%order_class%%.et_pb_filterable_portfolio';
$this->settings_modal_toggles = array(
'general'  => array(
'toggles' => array(
'main_content' => esc_html__( 'Content', 'et_builder' ),
'elements'     => esc_html__( 'Elements', 'et_builder' ),
),
),
'advanced' => array(
'toggles' => array(
'layout'  => esc_html__( 'Layout', 'et_builder' ),
'overlay' => esc_html__( 'Overlay', 'et_builder' ),
'text'    => array(
'title'    => esc_html__( 'Text', 'et_builder' ),
'priority' => 49,
),
'image' => esc_html__( 'Image', 'et_builder' ),
),
),
);
$this->advanced_fields = array(
'fonts'                 => array(
'title'   => array(
'label'    => esc_html__( 'Title', 'et_builder' ),
'css'      => array(
'main' => "{$this->main_css_element} h2, {$this->main_css_element} .et_pb_module_header",
'plugin_main' => "{$this->main_css_element} h2, {$this->main_css_element} h2 a, {$this->main_css_element} h1.et_pb_module_header, {$this->main_css_element} h1.et_pb_module_header a, {$this->main_css_element} h3.et_pb_module_header, {$this->main_css_element} h3.et_pb_module_header a, {$this->main_css_element} h4.et_pb_module_header, {$this->main_css_element} h4.et_pb_module_header a, {$this->main_css_element} h5.et_pb_module_header, {$this->main_css_element} h5.et_pb_module_header a, {$this->main_css_element} h6.et_pb_module_header, {$this->main_css_element} h6.et_pb_module_header a",
'important' => 'all',
),
'header_level' => array(
'default' => 'h2',
),
),
'filter' => array(
'label'    => esc_html__( 'Filter Criteria', 'et_builder' ),
'hide_text_align' => true,
'css'      => array(
'main' => "{$this->main_css_element} .et_pb_portfolio_filter",
'plugin_main' => "{$this->main_css_element} .et_pb_portfolio_filter, {$this->main_css_element} .et_pb_portfolio_filter a",
'color' => "{$this->main_css_element} .et_pb_portfolio_filter a",
),
),
'caption' => array(
'label'    => esc_html__( 'Meta', 'et_builder' ),
'css'      => array(
'main' => "{$this->main_css_element} .post-meta, {$this->main_css_element} .post-meta a",
),
),
'pagination' => array(
'label'    => esc_html__( 'Pagination', 'et_builder' ),
'css'      => array(
'main' => "{$this->main_css_element} .et_pb_portofolio_pagination a",
'text_align' => "{$this->main_css_element} .et_pb_portofolio_pagination ul",
),
'text_align' => array(
'options' => et_builder_get_text_orientation_options( array( 'justified' ), array() ),
),
),
),
'background'            => array(
'settings' => array(
'color' => 'alpha',
),
),
'borders'               => array(
'default' => array(
'css' => array(
'main' => array(
'border_radii' => "{$this->main_css_element} .et_pb_portfolio_item",
'border_styles' => "{$this->main_css_element} .et_pb_portfolio_item",
),
),
),
'image' => array(
'css'          => array(
'main' => array(
'border_radii'  => "{$this->main_css_element} .et_portfolio_image",
'border_styles' => "{$this->main_css_element} .et_portfolio_image",
),
),
'label_prefix' => esc_html__( 'Image', 'et_builder' ),
'tab_slug'      => 'advanced',
'toggle_slug'   => 'image',
),
),
'box_shadow'            => array(
'default' => array(),
'image'   => array(
'label'           => esc_html__( 'Image Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug'        => 'advanced',
'toggle_slug'     => 'image',
'css'             => array(
'main'         => '%%order_class%% .project .et_portfolio_image',
'custom_style' => true,
),
'default_on_fronts'  => array(
'color'    => '',
'position' => '',
),
),
),
'margin_padding' => array(
'css' => array(
'important' => array( 'custom_margin' ), // needed to overwrite last module margin-bottom styling
),
),
'max_width'             => array(
'css' => array(
'module_alignment' => '%%order_class%%.et_pb_filterable_portfolio.et_pb_module',
),
),
'text'                  => array(
'use_background_layout' => true,
'options' => array(
'background_layout' => array(
'default' => 'light',
),
),
),
'filters'               => array(
'css' => array(
'main' => '%%order_class%%',
),
'child_filters_target' => array(
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
),
),
'image'                 => array(
'css' => array(
'main' => '%%order_class%% .et_portfolio_image',
),
),
'button'                => false,
);
$this->custom_css_fields = array(
'portfolio_filters' => array(
'label'    => esc_html__( 'Portfolio Filters', 'et_builder' ),
'selector' => '.et_pb_filterable_portfolio .et_pb_portfolio_filters',
'no_space_before_selector' => true,
),
'active_portfolio_filter' => array(
'label'    => esc_html__( 'Active Portfolio Filter', 'et_builder' ),
'selector' => '.et_pb_filterable_portfolio .et_pb_portfolio_filters li a.active',
'no_space_before_selector' => true,
),
'portfolio_image' => array(
'label'    => esc_html__( 'Portfolio Image', 'et_builder' ),
'selector' => '.et_portfolio_image',
),
'overlay' => array(
'label'    => esc_html__( 'Overlay', 'et_builder' ),
'selector' => '.et_overlay',
),
'overlay_icon' => array(
'label'    => esc_html__( 'Overlay Icon', 'et_builder' ),
'selector' => '.et_overlay:before',
),
'portfolio_title' => array(
'label'    => esc_html__( 'Portfolio Title', 'et_builder' ),
'selector' => '.et_pb_portfolio_item h2',
),
'portfolio_post_meta' => array(
'label'    => esc_html__( 'Portfolio Post Meta', 'et_builder' ),
'selector' => '.et_pb_portfolio_item .post-meta',
),
'portfolio_pagination' => array(
'label'    => esc_html__( 'Portfolio Pagination', 'et_builder' ),
'selector' => '.et_pb_portofolio_pagination',
),
'portfolio_pagination_active' => array(
'label'    => esc_html__( 'Pagination Active Page', 'et_builder' ),
'selector' => '.et_pb_portofolio_pagination a.active',
),
);
$this->help_videos = array(
array(
'id'   => esc_html( 'AZheY1hVcJc' ),
'name' => esc_html__( 'An introduction to the Filterable Portfolio module', 'et_builder' ),
),
);
}
function get_fields() {
$fields = array(
'fullwidth' => array(
'label'           => esc_html__( 'Layout', 'et_builder' ),
'type'            => 'select',
'option_category' => 'layout',
'options'         => array(
'on'  => esc_html__( 'Fullwidth', 'et_builder' ),
'off' => esc_html__( 'Grid', 'et_builder' ),
),
'affects' => array(
'hover_icon',
'zoom_icon_color',
'hover_overlay_color',
),
'description'      => esc_html__( 'Choose your desired portfolio layout style.', 'et_builder' ),
'computed_affects' => array(
'__projects',
),
'tab_slug'         => 'advanced',
'toggle_slug'      => 'layout',
'default_on_front' => 'on',
),
'posts_number' => array(
'default'          => 10,
'label'            => esc_html__( 'Posts Number', 'et_builder' ),
'type'             => 'text',
'option_category'  => 'configuration',
'description'      => esc_html__( 'Define the number of projects that should be displayed per page.', 'et_builder' ),
'computed_affects' => array(
'__projects',
),
'toggle_slug'      => 'main_content',
),
'include_categories' => array(
'label'            => esc_html__( 'Include Categories', 'et_builder' ),
'type'             => 'categories',
'option_category'  => 'basic_option',
'description'      => esc_html__( 'Select the categories that you would like to include in the feed.', 'et_builder' ),
'computed_affects' => array(
'__project_terms',
'__projects',
),
'taxonomy_name'    => 'project_category',
'toggle_slug'      => 'main_content',
),
'show_title' => array(
'label'             => esc_html__( 'Show Title', 'et_builder' ),
'type'              => 'yes_no_button',
'option_category'   => 'configuration',
'options'           => array(
'on'  => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'toggle_slug'       => 'elements',
'description'       => esc_html__( 'Turn project titles on or off.', 'et_builder' ),
'default_on_front'  => 'on',
),
'show_categories' => array(
'label'             => esc_html__( 'Show Categories', 'et_builder' ),
'type'              => 'yes_no_button',
'option_category'   => 'configuration',
'options'           => array(
'on'  => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'toggle_slug'       => 'elements',
'description'       => esc_html__( 'Turn the category links on or off.', 'et_builder' ),
'default_on_front'  => 'on',
),
'show_pagination' => array(
'label'             => esc_html__( 'Show Pagination', 'et_builder' ),
'type'              => 'yes_no_button',
'option_category'   => 'configuration',
'options'           => array(
'on'  => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'toggle_slug'       => 'elements',
'description'       => esc_html__( 'Enable or disable pagination for this feed.', 'et_builder' ),
'default_on_front'  => 'on',
),
'hover_icon' => array(
'label'               => esc_html__( 'Hover Icon Picker', 'et_builder' ),
'type'                => 'select_icon',
'option_category'     => 'configuration',
'class'               => array( 'et-pb-font-icon' ),
'depends_show_if'     => 'off',
'tab_slug'            => 'advanced',
'toggle_slug'         => 'overlay',
),
'zoom_icon_color' => array(
'label'             => esc_html__( 'Zoom Icon Color', 'et_builder' ),
'type'              => 'color-alpha',
'custom_color'      => true,
'depends_show_if'   => 'off',
'tab_slug'          => 'advanced',
'toggle_slug'       => 'overlay',
),
'hover_overlay_color' => array(
'label'             => esc_html__( 'Hover Overlay Color', 'et_builder' ),
'type'              => 'color-alpha',
'custom_color'      => true,
'depends_show_if'   => 'off',
'tab_slug'          => 'advanced',
'toggle_slug'       => 'overlay',
),
'__project_terms' => array(
'type'                => 'computed',
'computed_callback'   => array( 'ET_Builder_Module_Filterable_Portfolio', 'get_portfolio_terms' ),
'computed_depends_on' => array(
'include_categories',
),
),
'__projects' => array(
'type'                => 'computed',
'computed_callback'   => array( 'ET_Builder_Module_Filterable_Portfolio', 'get_portfolio_item' ),
'computed_depends_on' => array(
'show_pagination',
'posts_number',
'include_categories',
'fullwidth',
),
),
);
return $fields;
}
static function get_portfolio_item( $args = array(), $conditional_tags = array(), $current_page = array() ) {
global $et_fb_processing_shortcode_object;
$global_processing_original_value = $et_fb_processing_shortcode_object;
$defaults = array(
'show_pagination'    => 'on',
'include_categories' => '',
'fullwidth'          => 'on',
'nopaging'           => true,
);
$query_args = array();
$args = wp_parse_args( $args, $defaults );
$include_categories = self::filter_invalid_term_ids( explode( ',', $args['include_categories'] ), 'project_category' );
if ( ! empty( $include_categories ) ) {
$query_args['tax_query'] = array(
array(
'taxonomy' => 'project_category',
'field'    => 'id',
'terms'    => $include_categories,
'operator' => 'IN',
)
);
}
$default_query_args = array(
'post_type'   => 'project',
'post_status' => 'publish',
'posts_per_page' => -1,
);
$query_args = wp_parse_args( $query_args, $default_query_args );
// Get portfolio query
$query = new WP_Query( $query_args );
// Format portfolio output, and add supplementary data
$width     = 'on' === $args['fullwidth'] ?  1080 : 400;
$width     = (int) apply_filters( 'et_pb_portfolio_image_width', $width );
$height    = 'on' === $args['fullwidth'] ?  9999 : 284;
$height    = (int) apply_filters( 'et_pb_portfolio_image_height', $height );
$classtext = 'on' === $args['fullwidth'] ? 'et_pb_post_main_image' : '';
$titletext = get_the_title();
// Loop portfolio item and add supplementary data
if( $query->have_posts() ) {
$post_index = 0;
while ( $query->have_posts() ) {
$query->the_post();
$categories = array();
$category_classes = array( 'et_pb_portfolio_item' );
if ( 'on' !== $args['fullwidth'] ) {
$category_classes[] = 'et_pb_grid_item';
}
$categories_object = get_the_terms( get_the_ID(), 'project_category' );
if ( ! empty( $categories_object ) ) {
foreach ( $categories_object as $category ) {
// Update category classes which will be used for post_class
$category_classes[] = 'project_category_' . urldecode( $category->slug );
// Push category data
$categories[] = array(
'id'        => $category->term_id,
'slug'      => $category->slug,
'label'     => $category->name,
'permalink' => get_term_link( $category ),
);
}
}
// need to disable processnig to make sure get_thumbnail() doesn't generate errors
$et_fb_processing_shortcode_object = false;
// Get thumbnail
$thumbnail = get_thumbnail( $width, $height, $classtext, $titletext, $titletext, false, 'Blogimage' );
$et_fb_processing_shortcode_object = $global_processing_original_value;
// Append value to query post
$query->posts[ $post_index ]->post_permalink     = get_permalink();
$query->posts[ $post_index ]->post_thumbnail     = print_thumbnail( $thumbnail['thumb'], $thumbnail['use_timthumb'], $titletext, $width, $height, '', false, true );
$query->posts[ $post_index ]->post_categories     = $categories;
$query->posts[ $post_index ]->post_class_name     = array_merge( get_post_class( '', get_the_ID() ), $category_classes );
// Append category classes
$category_classes = implode( ' ', $category_classes );
$post_index++;
}
} else if ( wp_doing_ajax() ) {
// This is for the VB
$query = array( 'posts' => self::get_no_results_template() );
}
wp_reset_postdata();
return $query;
}
static function get_portfolio_terms( $args = array(), $conditional_tags = array(), $current_page = array() ) {
$portfolio = self::get_portfolio_item( $args, $conditional_tags, $current_page );
$terms = array();
if ( ! empty( $portfolio->posts ) ) {
foreach ( $portfolio->posts as $post ) {
if ( ! empty( $post->post_categories ) ) {
foreach ( $post->post_categories as $category ) {
$terms[ $category['slug'] ] = $category;
}
}
}
}
return $terms;
}
function render( $attrs, $content = null, $render_slug ) {
$fullwidth          = $this->props['fullwidth'];
$posts_number       = $this->props['posts_number'];
$include_categories = $this->props['include_categories'];
$show_title         = $this->props['show_title'];
$show_categories    = $this->props['show_categories'];
$show_pagination    = $this->props['show_pagination'];
$background_layout  = $this->props['background_layout'];
$hover_icon          = $this->props['hover_icon'];
$zoom_icon_color     = $this->props['zoom_icon_color'];
$hover_overlay_color = $this->props['hover_overlay_color'];
$header_level        = $this->props['title_level'];
wp_enqueue_script( 'hashchange' );
if ( '' !== $zoom_icon_color ) {
ET_Builder_Element::set_style( $render_slug, array(
'selector'    => '%%order_class%% .et_overlay:before',
'declaration' => sprintf(
'color: %1$s !important;',
esc_html( $zoom_icon_color )
),
) );
}
if ( '' !== $hover_overlay_color ) {
ET_Builder_Element::set_style( $render_slug, array(
'selector'    => '%%order_class%% .et_overlay',
'declaration' => sprintf(
'background-color: %1$s;
border-color: %1$s;',
esc_html( $hover_overlay_color )
),
) );
}
$current_category   =   isset($_GET['f'])   ?   $_GET['f']  :   '';
$posts_include_categories =   !empty($current_category)    ?   $current_category  :  $include_categories;
$projects = self::get_portfolio_item( array(
'show_pagination'    => $show_pagination,
'posts_number'       => $posts_number,
'include_categories' =>  $posts_include_categories,
'fullwidth'          => $fullwidth,
) );
$categories_included = array();
ob_start();
if( $projects->post_count > 0 ) {
while ( $projects->have_posts() ) {
$projects->the_post();
$category_classes = array();
$categories = get_the_terms( get_the_ID(), 'project_category' );
if ( $categories ) {
foreach ( $categories as $category ) {
$category_classes[] = 'project_category_' . urldecode( $category->slug );
$categories_included[] = $category->term_id;
}
}
$category_classes = implode( ' ', $category_classes );
$main_post_class = sprintf(
'et_pb_portfolio_item%1$s %2$s',
( 'on' !== $fullwidth ? ' et_pb_grid_item' : '' ),
$category_classes
);
?>
<div id="post-<?php the_ID(); ?>" <?php post_class( $main_post_class ); ?>>
<?php
$thumb = '';
$width = 'on' === $fullwidth ?  1080 : 400;
$width = (int) apply_filters( 'et_pb_portfolio_image_width', $width );
$height = 'on' === $fullwidth ?  9999 : 284;
$height = (int) apply_filters( 'et_pb_portfolio_image_height', $height );
$classtext = 'on' === $fullwidth ? 'et_pb_post_main_image' : '';
$titletext = get_the_title();
$permalink = get_permalink();
$post_meta = get_the_term_list( get_the_ID(), 'project_category', '', ', ' );
$thumbnail = get_thumbnail( $width, $height, $classtext, $titletext, $titletext, false, 'Blogimage' );
$thumb = $thumbnail["thumb"];
if ( '' !== $thumb ) : ?>
<a href="<?php echo esc_url( $permalink ); ?>">
<span class="et_portfolio_image">
<?php print_thumbnail( $thumb, $thumbnail["use_timthumb"], $titletext, $width, $height ); ?>
<?php if ( 'on' !== $fullwidth ) :
$data_icon = '' !== $hover_icon
? sprintf(
' data-icon="%1$s"',
esc_attr( et_pb_process_font_icon( $hover_icon ) )
)
: '';
printf( '<span class="et_overlay%1$s"%2$s></span>',
( '' !== $hover_icon ? ' et_pb_inline_icon' : '' ),
$data_icon
);
?>
<?php endif; ?>
</span>
</a>
<?php
endif;
?>
<?php if ( 'on' === $show_title ) : ?>
<<?php echo et_pb_process_header_level( $header_level, 'h2' ) ?> class="et_pb_module_header"><a href="<?php echo esc_url( $permalink ); ?>"><?php echo $titletext; ?></a></<?php echo et_pb_process_header_level( $header_level, 'h2' ) ?>>
<?php endif; ?>
<?php if ( 'on' === $show_categories ) : ?>
<p class="post-meta"><?php echo $post_meta; ?></p>
<?php endif; ?>
</div><!-- .et_pb_portfolio_item -->
<?php
}
}
wp_reset_postdata();
if ( ! $posts = ob_get_clean() ) {
$posts            = self::get_no_results_template();
$category_filters = '';
} else {
$actual_link    = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$query_str      = parse_url($actual_link, PHP_URL_QUERY);
$actual_link    =   str_replace("?" . $query_str , "" ,  $actual_link);
$categories_included = explode ( ',', $include_categories );
$terms_args = array(
'include' => $categories_included,
'orderby' => 'name',
'order' => 'ASC',
);
$terms = get_terms( 'project_category', $terms_args );
$category_filters = '<ul class="clearfix">';
$class_current  =   empty($current_category)    ?   'active'    :   '';
$category_filters .= sprintf( '<li class="et_pb_portfolio_filter et_pb_portfolio_filter_all"><a href="'.$actual_link.'" class="'.$class_current.'" data-category-slug="all">%1$s</a></li>',
esc_html__( 'All', 'et_builder' )
);
foreach ( $terms as $term  ) {
$class_current  =   !empty($current_category)   &&  $term->term_id  == $current_category     ?   'active'    :   '';
$category_filters .= sprintf( '<li class="et_pb_portfolio_filter"><a href="'.$actual_link.'?f='. $term->term_id.'" class="'.$class_current.'" data-category-slug="%1$s">%2$s</a></li>',
esc_attr( urldecode( $term->slug ) ),
esc_html( $term->name )
);
}
$category_filters .= '</ul>';
}
$video_background = $this->video_background();
$parallax_image_background = $this->get_parallax_image_background();
// Images: Add CSS Filters and Mix Blend Mode rules (if set)
if ( isset( $this->advanced_fields['image']['css'] ) ) {
$this->add_classname( $this->generate_css_filters(
$render_slug,
'child_',
self::$data_utils->array_get( $this->advanced_fields['image']['css'], 'main', '%%order_class%%' )
) );
}
// Module classnames
$this->add_classname( array(
'et_pb_portfolio',
"et_pb_bg_layout_{$background_layout}",
$this->get_text_orientation_classname(),
) );
if ( 'on' === $fullwidth ) {
$this->add_classname( 'et_pb_filterable_portfolio_fullwidth' );
} else {
$this->add_classname( array(
'et_pb_filterable_portfolio_grid',
'clearfix',
) );
}
$output = sprintf(
'<div%4$s class="et_pb_filterable_portfolio et_pb_portfolio %1$s" data-posts-number="%5$d"%8$s>
%10$s
%9$s
<div class="et_pb_portfolio_filters clearfix">%2$s</div><!-- .et_pb_portfolio_filters -->
<script type="text/javascript">
/* <![CDATA[ */
jQuery(".et_pb_filterable_portfolio .et_pb_portfolio_filters a").on("click", function( event ) {
event.stopPropagation();
window.location.href    =   jQuery(this).attr("href");
})
/* ]]> */
</script>
<div class="et_pb_portfolio_items_wrapper %6$s">
<div class="et_pb_portfolio_items">%3$s</div><!-- .et_pb_portfolio_items -->
</div>
%7$s
</div> <!-- .et_pb_filterable_portfolio -->',
$this->module_classname( $render_slug ),
$category_filters,
$posts,
$this->module_id(),
esc_attr( $posts_number),
('on' === $show_pagination ? 'clearfix' : 'no_pagination' ),
('on' === $show_pagination ? '<div class="et_pb_portofolio_pagination"></div>' : '' ),
is_rtl() ? ' data-rtl="true"' : '',
$video_background,
$parallax_image_background
);
return $output;
}
}
new ET_Builder_Module_Filterable_Portfolio_Sortable;
?>

The new module setting are the same as default one, they should be used accordingly to this article.