FF Ajax

  • Name : FF Ajax
  • Version : 2.3.9
  • File : Login to download file

Changelog:

v2.1.0
* added feature - query strings

v1.1.2
* added functionality to pass custom_data (setting) to ajax item template (acessed in $custom_data) https://prnt.sc/69GKiA3ZuKhh

v1.1.0
* added sort field

v1.0.3
* added before_render_modify_html js method = for modifying the html, e.g: adding group containers

v1.0.2
* multiple instance render issue fix

v1.0.1
* added filter_checkboxes for multiple checkboxes

How to use:

Download and install the plugin

This contains the php class and the js file.

Check the module files for example codes including raw versions. 

Sample codes

				
					<?php
if( !class_exists('FF_Ajax') ) return;

$query_args = [
    'post_type' => 'post',
    'showposts' => 8,
    'no_found_rows' => true,
];

$settings = [
    
    'item_template' => FF_DIR . '/modules/ff-ajax/item-templates/sample.php',
    // this will be used to render the items on ajax
    // this will have a reference to the $post object in a query loop

    'query_args' => $query_args, // wp query args
 
    'initial_query' => true,
    // true = run the query(php) on load
    // false = will not run the php query, load the initial items via ajax
];

$ff_ajax = new FF_Ajax($settings);

echo '<div id="'. $ff_ajax->id .'" class="ff_ajax">';

    // render html & js
    $ff_ajax->render();

echo '</div>';
				
			
Other default settings:
				
					// default settings
$settings = [
    'initial_query' => false,

    'filter_on_load' => false,
    // set this to true if you change the filter field values on load
    // for example, pre-select a value on a dropdown filter, it will then run the query applying that filter

    'query_on_change' => true,
    // set this to false if you don't want to run the query when the filter fields change/selected
    // add custom code to run the query, example below

    'load_more_text' => 'Load more', // load more button text
    
    'no_results_html' => 'No results found, try different filters', // html to display when the query has no results
];
				
			

PHP Item template

the php item template would have access to a $post object inside a WP query->posts foreach

				
					$q = new WP_Query($args);
foreach( $q->posts as $post ) {
    include 'item-template.php';
}
				
			

Filters

Dropdown

				
					$settings = [
    // common settings
    'label' => 'STRING', // set to empty or ommit to hide the label html
    'placeholder' => 'STRING', // first option on the select with value = ""
    'filter_key' => 'STRING', // useful for having multiple filters for a single meta_key, e.g: for date range = date_from & date_to 
    'multiple' => BOOLEAN, // true = select multiple options, renders extra indicator html
    'indicator_prefix' => 'STRING', // if multiple is true, adds a prefix text to the indicator html

    // tax_query specific
    'taxonomy' => 'STRING',
    'taxonomy_field' => 'STRING', // default: "slug", other options: 'term_taxonomy_id', 'name'

    // meta_query specific
    'meta_key' => 'STRING',
    'meta_type' => 'STRING', // default: "CHAR", change to NUMERIC for numbers and DATE for dates. Check wp meta_query for other options
    'compare' => 'STRING', // default: "=", check wp meta_query for other options
];
$ff_ajax->filter_dropdown($settings);
				
			
Dropdown - tax_query sample
				
					// filter - tax_query
$ff_ajax->filter_dropdown([
    'taxonomy' => 'category',
    'placeholder' => 'Category',
    'exclude' => ['uncategorized'],
]);


// you can also set the 'choices' to customize the options, e.g
$choices = [];
$terms = get_terms(['taxonomy' => 'category']);
foreach( $terms as $term ) {
    $choices[$term->slug] = $term->name;
}
$ff_ajax->filter_dropdown([
    'taxonomy' => 'category',
    'placeholder' => 'Category',
    'choices' => $choices,
]);
				
			
Dropdown - meta_query sample
				
					// filter - meta_query
$choices = [
    'format_1' => 'Format 1',
    'format_2' => 'Format 2',
    'format_3' => 'Format 3',
];
$ff_ajax->filter_dropdown([
    'meta_key' => 'format',
    'placeholder' => 'Format',
    'choices' => $choices,
]);


// sample choices from acf field
$acf_field = get_field_object('field_65c40d5fbc428');
$choices = $acf_field['choices'];
				
			

Buttons

				
					// taxonomy = single select
$ff_ajax->filter_buttons([
    'taxonomy' => 'region',
]);

// meta - multiple select
$field = get_field_object('field_65c40d5fbc428');
$ff_ajax->filter_buttons([
    'meta_key' => 'size',
    'multiple' => true,
    'choices' => $field['choices'],
]);
				
			

Checkbox

				
					$ff_ajax->filter_checkbox([
    'meta_key' => 'featured',
    'label' => 'Meta - checkbox - Featured',
]);
				
			

Checkboxes

different from single checkbox, filter_checkboxes (with es)

				
					$ff_ajax->filter_checkboxes([
    'taxonomy' => 'category',
    'multiple' => true,
]);
				
			

Search field

				
					// uses native WP Query with "s" => 'SEARCH_STRING',
$ff_ajax->search_field([
    'placeholder' => 'Search...',
    'with_clear' => true,
]);
				
			

Custom UI - datepicker(with jquery ui datepicker)

				
					<?php
// filter - meta_query - date - from
// set data-compare and data-filter_key explicitly
$ff_ajax->filter_input([
    'meta_key' => 'date',
    'placeholder' => 'Date from',
    'class' => 'filter-date', // for initializing datepicker
    'compare' => '>=',
    'filter_key' => 'date_from',
]);

// filter - meta_query - date - to
// different filter_key from the date field above
$ff_ajax->filter_input([
    'meta_key' => 'date',
    'placeholder' => 'Date to',
    'class' => 'filter-date',
    'compare' => '<=',
    'filter_key' => 'date_to',
]);

// Sample JS
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    if( typeof FF_Ajax === 'undefined' ) return;

    var el = document.getElementById('<?php echo $ff_ajax->id; ?>');
    var ff_ajax = el.ff_ajax;

    // with datepicker
    <?php
    wp_enqueue_script('jquery-ui-datepicker');
    wp_enqueue_style('jquery-ui', 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css');
    ?>
    jQuery('.filter-date input').datepicker({
        onSelect: function(dateText, datepicker){
            ff_ajax.filter_datepicker(this, datepicker);
        }
    });
});
</script>
				
			

Custom UI - slider (with noUISlider)

				
					<?php
// Sample HTML
echo '<div class="field-con">';
    echo '<div id="price_slider" style="width:300px;"></div>';
    echo '<div id="price_slider_value"></div>';
echo '</div>';


// Sample JS
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    if( typeof FF_Ajax === 'undefined' ) return;

    var el = document.getElementById('<?php echo $ff_ajax->id; ?>');
    var ff_ajax = el.ff_ajax;
    
    // with custom ui - slider
    <?php
    wp_enqueue_script('nouislider', FF_URL . '/vendors/nouislider/nouislider.min.js', [], null, true);
    wp_enqueue_style('nouislider', FF_URL . '/vendors/nouislider/nouislider.min.css');
    ?>
    function slider_init(){
        var slider = document.getElementById('price_slider');
        var slider_value = document.getElementById('price_slider_value');
        var max = 300;

        // init slider
        noUiSlider.create(slider, {
            start: [1, max],
            connect: true,
            step: 10,
            range: {
                'min': 1,
                'max': max
            }
        });

        // render selected values
        slider.noUiSlider.on('update', function ( values ) {
            slider_value.innerHTML = '$'+ values[0] +' - $'+ values[1];
        });

        // on value change, trigger filter update
        slider.noUiSlider.on('set', function ( values ) {
            
            if( ff_ajax.container.classList.contains('filter_loading') ) return;

            // price from - update query_args
            ff_ajax.custom_filter_update({
                key: 'price',
                value: parseInt(values[0]),
                type: 'NUMERIC',
                compare: '>=',
                filter_key: 'price_from',
            });
            
            // price_to - update query_args
            ff_ajax.custom_filter_update({
                key: 'price',
                value: parseInt(values[1]),
                type: 'NUMERIC',
                compare: '<=',
                filter_key: 'price_to',
            });

            // run filter
            ff_ajax.filter_query();
        });

        ff_ajax.on_clear_filters = function(){
            // on ajax clear, reset slider ui
            slider.noUiSlider.set([1, 300]);
        }
    }
    slider_init();
    
});
</script>
				
			

Sort field

				
					$ff_ajax->sort_dropdown([
    'placeholder' => 'Sort',
    'choices' => [
        [
            'label' => 'Latest',
            'orderby' => 'date',
            'order' => 'DESC',
        ],
        [
            'label' => 'Oldest',
            'orderby' => 'date',
            'order' => 'ASC',
        ],
        [
            'label' => 'Title A-Z',
            'orderby' => 'title',
            'order' => 'ASC',
        ],
        [
            'label' => 'Title Z-A',
            'orderby' => 'title',
            'order' => 'DESC',
        ],
        [
            'label' => 'META - Date ASC',
            'meta_key' => 'date',
            'orderby' => 'meta_value_num',
            'order' => 'ASC',
        ],
        [
            'label' => 'META - Date DESC',
            'meta_key' => 'date',
            'orderby' => 'meta_value_num',
            'order' => 'DESC',
        ],
        [
            'label' => 'META - Price ASC',
            'meta_key' => 'price',
            'orderby' => 'meta_value_num',
            'order' => 'ASC',
        ],
        [
            'label' => 'META - Price DESC',
            'meta_key' => 'price',
            'orderby' => 'meta_value_num',
            'order' => 'DESC',
        ],
    ],
]);
				
			

With Clear Button

				
					<?php
echo '<div id="'. $ff_ajax->id .'" class="ff_ajax">';
    // ...
    echo '<button class="clear_filters" style="display:none;">Clear filters</button>';
    // ...
echo '</div>';

?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    if( typeof FF_Ajax === 'undefined' ) return;

    var el = document.getElementById('<?php echo $ff_ajax->id; ?>');
    var ff_ajax = el.ff_ajax;

    ff_ajax.after_render = function(){
        // hide/show clear button after filter change
        if( ff_ajax.clear_filters_button ) {
            ff_ajax.clear_filters_button.style.display = !ff_ajax.have_filters() ? 'none' : '';
        }
    }
    
});
</script>
				
			

Manual filter on button click, not on input change

				
					<?php
// set query_on_change to false, so it wont run the query when the filter fields change
// you can then trigger the query on button click instead
$settings = [
    // ...
    'query_on_change' => false, 
];

$ff_ajax = new FF_Ajax($settings);

echo '<div id="'. $ff_ajax->id .'" class="ff_ajax">';
    // ...
    echo '<button class="filter_query">Filter</button>';
    // ...
echo '</div>';

?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    if( typeof FF_Ajax === 'undefined' ) return;

    var el = document.getElementById('<?php echo $ff_ajax->id; ?>');
    var ff_ajax = el.ff_ajax;
    
    // manual trigger query on click - not on filter change
    document.querySelector('.filter_query').addEventListener('click', function(){
        ff_ajax.filter_query();
    });
    
});
</script>
				
			

JS Hooks / Events

before_render

Before the html items render, useful for adding intro animations or other DOM manipulations

				
					<script>
document.addEventListener('DOMContentLoaded', function(){
    if( typeof FF_Ajax === 'undefined' ) return;

    var el = document.getElementById('<?php echo $ff_ajax->id; ?>');
    var ff_ajax = el.ff_ajax;
    
    // add custom classes to items before rendering
    // useful for adding entrance animations & initializing functions
    ff_ajax.before_render = function($html){
        $html.addClass('intro-animate');
    }
    
});
</script>
				
			

before_render_modify_html

returns the DOM from jquery selector, use this to modify the html markup, e.g: adding extra containers/html

				
					<script>
// Example of adding extra container to the items grouped by category
document.addEventListener('DOMContentLoaded', function(){
    if( typeof FF_Ajax === 'undefined' ) return;

    var el = document.getElementById('<?php echo $ff_ajax->id; ?>');
    var ff_ajax = el.ff_ajax;
    
    ff_ajax.before_render_modify_html = function(html){
        return group_items(html);
    }

    // add custom container to items grouped by category
    function group_items(html){
        
        // group items
        var groups = {};
        html.each(function(){
            // category data in html data attribute
            var category = this.dataset.category;
            if( typeof groups[category] === 'undefined' ) groups[category] = [];
            groups[category].push(jQuery(this));
        })

        // add container html for each group
        var new_html = '';
        var categories = Object.keys(groups);
        for( var i = 0; i < categories.length; i++ ) {
            var category_name = categories[i];
            new_html += '<div class="group" data-group="'+ category_name +'">';
                new_html += '<h3>'+ category_name +'</h3>';
                new_html += '<div class="sub_items">';
                    for( var j = 0; j < groups[category_name].length; j++ ) {
                        new_html += groups[category_name][j].html();
                    }
                new_html += '</div>';
            new_html += '</div>';
        }

        return new_html;
    }
    
});
</script>
				
			

after_render

After the ajax query renders the html items

				
					ff_ajax.after_render = function(){

    // hide/show clear button after filter change
    if( ff_ajax.clear_filters_button ) {
        ff_ajax.clear_filters_button.style.display = !ff_ajax.have_filters() ? 'none' : '';
    }
    
}
				
			

Share This

Select your desired option below to share a direct link to this page.
Your friends or family will thank you later.