Skip to Content


Allows for post listings to have AJAX page traversal.

PHP April 26, 2017


nebula()->infinite_load_query($args, $loop)


(Optional) (Array) An array of options
Default: See below

(Optional) (Boolean) A custom loop function or page template.
Default: loop.php

Parameter Notes

$args are identical to WP_Query or query_posts() in WordPress.

$loop is a function or page template to use instead of the standard loop.

Request or provide clarification »


Infinite Load Example

The most optimal way to load CSS and JS in Nebula
Loading resources the standard way of registering and enqueuing will make every speed test complain. Unless you are using that resource on every single page, there is a better way to load it. Preparing your stylesheet or JavaScript file The first thing to do is decide where you will be calling your asset file from. Read More »

Source File

Located in /libs/Functions.php on line 1632.

2 Hooks

Find these filters and actions in the source code below to hook into them. Use do_action() and add_filter() in your functions file or plugin.

Need a new filter hook? Request one here.

Need a new action hook? Request one here.

Note: This function contains 1 to-do comment.

        public function infinite_load_query($args=array('post_status' => 'publish', 'showposts' => 4), $loop=false){
            $timer_name = $this->timer('Infinite Load Query');

            $override = apply_filters('pre_nebula_infinite_load_query', null);
            if ( isset($override) ){return;}

            global $wp_query;
            if ( empty($args['paged']) ){
                $args['paged'] = 1;
                if ( get_query_var('paged') ){
                    $args['paged'] = get_query_var('paged');
                    <div class="infinite-start-note">
                        <a href="<?php echo get_the_permalink(); ?>">&laquo; <?php _e('Back to page 1', 'nebula'); ?></a>
                } elseif ( !empty($wp_query->query['paged']) ){
                    $args['paged'] = $wp_query->query['paged'];
                    <div class="infinite-start-note">
                        <a href="<?php echo get_the_permalink(); ?>">&laquo; <?php _e('Back to page 1', 'nebula'); ?></a>


            if ( empty($args['post_type']) ){
                $post_type_label = 'posts';
            } else {
                $post_type = ( is_array($args['post_type']) )? $args['post_type'][0] : $args['post_type'];
                $post_type_obj = get_post_type_object($args['post_type']);
                $post_type_label = lcfirst($post_type_obj->label);

            <div id="infinite-posts-list" data-max-pages="<?php echo $wp_query->max_num_pages; ?>" data-max-posts="<?php echo $wp_query->found_posts; ?>">
                $loop = sanitize_text_field($loop);
                if ( !$loop ){
                } else {
                    if ( function_exists($loop) ){
                    } elseif ( locate_template($loop . '.php') ){
                    } else {
                        if ( $this->is_dev() ){
                            echo '<strong>Warning:</strong> The custom loop template or function ' . $loop . ' does not exist! Falling back to loop.php.';

            <?php do_action('nebula_infinite_before_load_more'); ?>

            <div class="loadmorecon <?php echo ( $args['paged'] >= $wp_query->max_num_pages )? 'disabled' : ''; ?>">
                <a class="infinite-load-more" href="#"><?php echo ( $args['paged'] >= $wp_query->max_num_pages )? 'No more ' . $post_type_label . '.' : 'Load More'; ?></a>
                <div class="infinite-loading">
                    <div class="a"></div> <div class="b"></div> <div class="c"></div>

            <script><?php //Must be in PHP so $args can be encoded. @todo "Nebula" 0: This must have to load in the footer if jQuery is set to the footer...? ?>
                window.addEventListener('load', function(){
                    var pageNumber = <?php echo $args['paged']; ?>+1;

                    document.querySelector('.infinite-load-more').addEventListener('click', function(e){
                        var maxPages = document.getElementById('infinite-posts-list').getAttribute('data-max-pages');
                        var maxPosts = document.getElementById('infinite-posts-list').getAttribute('data-max-posts');

                        if ( pageNumber <= maxPages ){

                            fetch(, {
                                method: 'POST',
                                credentials: 'same-origin',
                                headers: {
                                    'Content-Type': 'application/x-www-form-urlencoded',
                                    'Cache-Control': 'no-cache',
                                body: new URLSearchParams({
                                    action: 'nebula_infinite_load',
                                    page: pageNumber,
                                    args: JSON.stringify(<?php echo json_encode($args); ?>),
                                    loop: <?php echo json_encode($loop); ?>,
                                if ( response.ok ){
                                    return response.text();
                                let newDiv = document.createElement('div');
                                newDiv.className = 'clearfix infinite-page infinite-page-' + (pageNumber-1) + ' sliding';
                                newDiv.setAttribute('style', 'display: none;');
                                newDiv.innerHTML = response;

                                jQuery('.infinite-page-' + (pageNumber-1)).slideDown({ //I would like to remove this jQuery so this embedded script tag does not have a potential race condition depending on where jQuery is loaded. Try animating the height some other way
                                    duration: 750,
                                    //easing: 'easeInOutQuad',
                                    complete: function(){
                                        document.dispatchEvent(new Event('nebula_infinite_slidedown_complete'));

                                if ( pageNumber >= maxPages ){
                                    document.querySelector('.loadmorecon').classList.add('disabled').querySelector('a').innerHTML = '<?php __('No more', 'nebula'); ?> <?php echo $post_type_label; ?>.';

                                var newQueryStrings = '';
                                if ( typeof document.URL.split('?')[1] !== 'undefined' ){
                                    newQueryStrings = '?' + document.URL.split('?')[1].replace(/[?&]paged=\d+/, '');

                                history.replaceState(null, document.title, + 'page/' + pageNumber + newQueryStrings);
                                document.dispatchEvent(new Event('nebula_infinite_finish'));

                                ga('send', 'event', 'Infinite Query', 'Load More', 'Loaded page ' + pageNumber);
                                document.dispatchEvent(new Event('nebula_infinite_finish'));
                                ga('send', 'event', 'Error', 'AJAX Error', 'Infinite Query Load More AJAX');

            $this->timer($timer_name, 'end');


To override this PHP function, use this hook in your child theme or plugin ("my_custom" can be changed):

add_filter('pre_nebula_infinite_load_query', 'my_custom_infinite_load_query', 10, 3); //The last integer must be 1 more than the actual parameters
function my_custom_infinite_load_query($null, $args, $loop){ //$null is required, but can be ignored
    //Write your own code here

    return true; //Return true to prevent the original function from running afterwords

You can completely disable this PHP function with a single line actions:

 add_filter('pre_nebula_infinite_load_query', '__return_false');