Multiple Load More buttons on the same template (content representations and AJAX)

Hey there,

Guided by the K2 Load More tutorial, I’m trying to have a single page (projects.php) house two sections with thumbnails of both projects (project.php) and also ā€˜resources’ (resource.php). In terms of content structure, it goes ā€˜Projects’ > ā€˜Project’ and ā€˜Resources’ > ā€˜Resource’.

For some reason, everything works fine on using the Load More button for the projects, but with the Resources, it seems to completely ignore the count, offset and limit and not only loads all of the resource blocks into the container, but loads each one twice. This doesn’t seem to be happening in my resources.json file, which is super strange!

My code and jQuery is split entirely into two (very sloppy, I know), as you can probably see, because for the life of me I’ve tried everything and this has got me the closest.

I think this may be complicated by multiple content representations etc.

Heres the html for the ā€˜Projects section’

<div class="grid grid--3-col projects" data-page="<?= $page->url() ?>" data-limit="<?= $limit ?>">
  <?php foreach( $projects as $project ) : ?>
    <?php snippet('project', compact('project')) ?>
  <?php endforeach ?>
</div>

Then for the ā€˜Resources’ section

<?php $resourcePage = $pages->find('resources') ?>
<div class="grid grid--3-col resources" data-page="<?= $pages->find('resources')->url() ?>" data-r_limit="<?= $r_limit ?>">
  <?php foreach ( $resources as $resource ) : ?>
    <?php snippet('resource', compact('resource') ) ?>
  <?php endforeach ?>
</div>

I’m using the controller of the ā€˜Projects.php’ page, because that’s where it’s all getting displayed:

<?php 

return function( $site, $pages, $page ) {
  // Set PROJECT variables 
  $projects = $page->children()->listed()->offset(3);
  $count = $projects->count();
  $more = false;

  // Resources
  $resources = $pages->find('resources')->children()->listed();

  // check if the request is an Ajax request and if the limit and offset keys are set
  if( 
    !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' 
    && get('offset') 
    && get('limit')
  ) {

      // convert limit and offset values to integer
      $offset = intval(get('offset'));
      $limit  = intval(get('limit'));

      // limit projects using offset and limit values
      $projects = $projects->offset($offset)->limit($limit);

      // check if there are more projects left
      $more = $count > $offset + $limit;

  // otherwise set the number of projects initially displayed
  } else {

    // PROJECTS
    $offset   = 0;
    $limit    = 6;
    $projects = $projects->offset($offset)->limit($limit);

    // Resource variables for page load
    $r_offset = 0;
    $r_limit = $limit;
    $resources = $resources->offset($r_offset)->limit($r_limit);

  }

  return compact('offset', 'limit', 'projects', 'more', 'r_offset', 'r_limit', 'resources', 'r_more');
  
}

?>

But then also the controller of the ā€˜resources.php’ page handles some of the logic for creating the content representation:

<?php 

return function( $site, $pages, $page ) {

  $resources = $pages->find('resources')->children()->listed();
  $r_count = $resources->count();
  $r_more = false;

  if( 
    !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' 
    && get('r_offset') 
    && get('r_limit') 
  ) {

    // convert limit and offset values to integer
    $r_offset = intval(get('r_offset'));
    $r_limit  = intval(get('r_limit'));

    // limit projects using offset and limit values
    $resources = $resources->offset($r_offset)->limit($r_limit);

    // check if there are more projects left
    $r_more = $r_count > $r_offset + $r_limit;

  // otherwise set the number of projects initially displayed
  }

  return compact('r_offset', 'r_limit', 'resources', 'r_more');
  
}

?>

jQuery:

function loadMoreProjects() {
  var element = $('.projects');
  var url   = element.data('page') + '.json';
  var limit   = parseInt(element.data('limit'));
  var offset  = limit;
  var projects = true;

  $('.load-more-projects').click(function(e) {
    
    $.get(url, {limit: limit, offset: offset, projects: projects}, function(data) {

      if(data.more === false) {
        element.next().hide();
      }

      element.children().last().after(data.html);
      offset += limit;

    }); 

  });
}

function loadMoreResources() {
  var r_element     = $('.resources');
  var r_url         = r_element.data('page') + '.json';
  var r_limit       = parseInt(r_element.data('r_limit'));
  var r_offset      = r_limit;
  var resources = true;

  $('.load-more-resources').click(function(e) {
    
    $.get(r_url, {r_limit: r_limit, r_offset: r_offset, resources: resources}, function(r_data) {

      if(r_data.r_more === false) {
        r_element.next().hide();
      }

      r_element.children().last().after(r_data.r_html);
      r_offset += r_limit;

    }); 

  });
}

And the content representations are basically exactly the same except with different variables, ie ā€œ$moreā€ vs ā€œr_moreā€.

Long-winded but I hope someone out there is able to help!

Thank you,

I think you have to put the logic into the projects.php controller, not the resources.php controller.

From testing though I need the resources.php controller to set up the variables in order to create the resources.json.php content representation.