Hi
Adding the following to template_preprocess_views_views_json_style_simple will give an additional root object 'pager' with keys total and current for the total number of pages and current page respectively if the view has a pager enabled. You can use this to setup your own pagers with ajax.

  global $pager_total, $pager_page_array;
  $element = $vars['view']->pager['element'];
  $vars['rows']['pager'] = array(
    'total' => $pager_total[$element],
    'current' => $pager_page_array[$element]
  );

For those who need this but don't want to hack the module, implement it as hook_preprocess_views_views_json_style_simple (&$vars) in your own module.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mcantelon’s picture

larowlan's hack works great. Please add this to this super useful module!

zeemp’s picture

Category: feature » support

Any clue on how to setup your own pagers with ajax? How can I print it inside the json view file?

larowlan’s picture

Category: support » feature

For those unsure what implementing the hook in your own module means you can do this in your theme:

YOURTHEMENAME_preprocess_views_views_json_style_simple (&$vars)
  global $pager_total, $pager_page_array;
  $element = $vars['view']->pager['element'];
  $vars['rows']['pager'] = array(
    'total' => $pager_total[$element],
    'current' => $pager_page_array[$element]
  );
}

From memory, that's all you should need

zeemp’s picture

This is what happened in the json file when I paste the code into the template.php

40 ( // one null node was created, I had 39, is this the normal behaviour?
	Object { node={...}}
	
pager
	Object { total=3, current=0}
	
total
	3
	
current
	0

The pager appeared below nodes, is this all the info I need to build the ul class="pager", with the li's inside it? some js code is enough?

Thanks so much!

zeemp’s picture

For those who want to know the javascript required to build the pager. I've acomplished it with the code below. Don't forget #3 before pasting the code into you javascript file.

callView('view_url_here');

function callView(url) {
		
	var results = $("#results");			
	results.html('');
			
	var jqxhr = $.ajax({
		url: url,
		dataType:'json',
		success: function(data) {					
			$.each(data.nodes, function(i,node){
				results.append("...");
			}					
			pager(data,url);										
		},
		error: function () {
			results.html("Error");
		}
	});		
			
}
	
function pager(data,url) {
		
	url = url.split('?', 1)[0];
	var current = parseInt(data.pager.current);
	var total = parseInt(data.pager.total);

	if (total > 1) {
		if(current == 0) {				
			var pagination = 
				"<li class='pager-current first'>"+(current+1)+"</li>"+	
				"<li class='pager-item'><a class='active' title='Go to page "+(current+2)+"' href='"+url+"?page="+(current+1)+"'>"+(current+2)+"</a></li>"+
				"<li class='pager-item'><a class='active' title='Go to page "+(current+3)+"' href='"+url+"?page="+(current+2)+"'>"+(current+3)+"</a></li>"+							
				"<li class='pager-next'><a class='active' title='Go to next page' href='"+url+"?page="+(current+1)+"'>next &#187;</a></li>"+
				"<li class='pager-last last'><a class='active' title='Go to last page' href='"+url+"?page="+(total-1)+"'>last &#187;</a></li>";
		
		} else if (current == total - 1) {			
			var pagination = 
				"<li class='pager-first first'><a class='active' title='Go to first page' href='"+url+"'>&#171; first</a></li>"+
				"<li class='pager-previous'><a class='active' title='Go to previous page' href='"+url+"?page="+(current-1)+"'>&#171; previous</a></li>"+
				"<li class='pager-item'><a class='active' title='Go to page "+(current-1)+"' href='"+url+"?page="+(current-2)+"'>"+(current-1)+"</a></li>"+
				"<li class='pager-item'><a class='active' title='Go to page "+(current)+"' href='"+url+"?page="+(current-1)+"'>"+(current)+"</a></li>"+	
				"<li class='pager-current first'>"+(current+1)+"</li>";
					
		} else {				
			var pagination = 
				"<li class='pager-first first'><a class='active' title='Go to first page' href='"+url+"'>&#171; first</a></li>"+																				
				"<li class='pager-item'><a class='active' title='Go to page "+(current)+"' href='/zeemp/"+url+"?page="+(current-1)+"'>"+(current)+"</a></li>"+										
				"<li class='pager-current first'>"+(current+1)+"</li>"+
				"<li class='pager-item'><a class='active' title='Go to page "+(current+2)+"' href='"+url+"?page="+(current+1)+"'>"+(current+2)+"</a></li>"+										
				"<li class='pager-last last'><a class='active' title='Go to last page' href='"+url+"?page="+(total-1)+"'>last &#187;</a></li>";
				
		}
                $('#content-inner .item-list').remove();
		$("#content-inner").append("<div class='item-list'><ul class='pager'>"+pagination+"</ul></div>");
					
		$(".pager li a").click(function(e) {			
			e.preventDefault();
			var url = $(this).attr("href");
			callView(url, '');								
		})
	} 		
}	

Any improvements are welcome.

larowlan’s picture

Here's how I did it:

  var p = data.pager;
  if (p.total > 1) {
    // Logic borrowed from theme_pager
    var pager = $('<div class="pager-wrapper"></div>');
    p.mid = 3; //middle 
    p.active = p.current + 1; //active page
    p.first = p.active - 2; //we want 5 links
    p.last = p.active + 2; //5 links
    p.i = p.first;
    if (p.last > p.total) {
      p.i = p.i + p.total - p.last;
    }
    if (p.i <= 0) {
      p.last = p.last + (1 - p.i);
      p.i = 1;
    }
    if (p.i > 1) {
      pager.append('<a href="#" rel="0" class="pager-link first">«</a>');
      pager.append('<a href="#" rel="'+ (p.active - 2) +'" class="pager-link previous">‹</a>');
      pager.append($('<span class="ellipsis">...</span>'));
    }
    for (; p.i <= p.last && p.i <= p.total; p.i++) {
      if (p.i == p.active) {
        pager.append('<a href="#" rel="'+ (p.i - 1) +'" class="pager-link current">'+ p.i +'</a>');              
      }
      else {
        pager.append('<a href="#" rel="'+ (p.i - 1) +'" class="pager-link">'+ p.i +'</a>');
      }
    }
    if (p.i < p.total) {
      pager.append($('<span class="ellipsis">...</span>'));
      pager.append('<a href="#" rel="'+ (p.active) +'" class="pager-link next">›</a>');
      pager.append('<a href="#" rel="'+ (p.total - 1) +'" class="pager-link last">»</a>');
    }
    pager.find('a.pager-link').click(function() {
      Drupal.MYMODULENAMESPACE.MYMODULEUPDATEFUNCTION($(this).attr('rel'));
      return false;
    })
  }
  if (pager) {
    MYDIV.append(pager);
  }

rayvan’s picture

There was a syntax error in zeemp's callView function code above (missing closing parenthesis near .each), here is the correct version:

function callView(url) {

var results = $("#results");
results.html('');

$.ajax({
url: url,
dataType:'json',
success: function(data) {
$.each(data.nodes, function(i,node){
results.append("...");
})
pager(data,url);
},
error: function () {
results.html("Error");
}
});

}

I haven't gone through implementing the rest of the code yet but makes sense from a high level.

Thank you. And yes, this should be added to the module's default data presentation of json.

bodrin’s picture

Version: 6.x-1.0-beta2 » 7.x-1.x-dev

Hi, I have added the following to my theme (danland) template.php in a drupal 7.17 installation:

function danland_preprocess_views_views_json_style_simple(&$vars) {
  global $pager_total, $pager_page_array;
  $element = $vars['view']->pager['element'];
  $vars['rows']['pager'] = array(
    'total' => $pager_total[$element],
    'current' => $pager_page_array[$element]
  );
}

I'm getting this output:
{"nodes":[{"node":{"title":"news2","field_news_image":"http://example.com/vakt/sites/v-akt/files/logo.png"}}],"pager":{"total":null,"current":null}}

The reason is that $element = $vars['view']->pager['element']; is null. Any idea about why?

Note that If I use the arrays directly:

function danland_preprocess_views_views_json_style_simple(&$vars) {
  global $pager_total, $pager_page_array;
  $element = $vars['view']->pager['element'];
  $vars['rows']['pager'] = array(
    'total' => $pager_total,
    'current' => $pager_page_array
  );
}

I get
{"nodes":[{"node":{"title":"news2","field_news_image":"http://example.com/vakt/sites/v-akt/files/logo.png"}}],"pager":{"total":[2],"current":[0]}}

Which is ok.
I know that I have only a single pager in this page and I can hardcode it probably but ..is there a better way to solve this?

yannickoo’s picture

Status: Needs review » Active

Here is no patch, so I set it back to "active".

tyler.frankenstein’s picture

For D7, Views 3.x, add this to your module to get the total number of pages, the current page, the total result count, and the limit per page:

/**
 * Implements hook_preprocess_views_views_json_style_simple().
 */
function my_module_preprocess_views_views_json_style_simple(&$vars) {
  global $pager_total, $pager_page_array, $pager_total_items, $pager_limits;
  $vars['rows']['pager'] = array(
    'pages' => $pager_total[0],
    'page' => $pager_page_array[0],
    'count' => intval($pager_total_items[0]),
    'limit' => intval($pager_limits[0])
  );
}

We can assume index 0 on each of the pager arrays since there will only be one pager whenever we are fetching JSON from a View.

The result JSON will now look something like this:

{
  "nodes":[{"node":{"title":"Hello World"}}],
  "pager":{"pages":3,"page":0,"count":3,"limit":1}
}

The above result says we have a total of 3 pages, we're currently on the first page (zero), there are a total of 3 results, and 1 result per page.

Thanks to @larowlan and @bodrin for their code above.

rjdjohnston’s picture

Issue summary: View changes

Thanks @tyler.frankenstein it works beautifully!

dark_kz’s picture

Not worked for me :(
If I add ?page=1 to url it shows next nodes, but #10 code only show 0 and 10 (per page node count).
I have a normal view with output and pager, and it works ok. Query string are the same. Where should I search error?

hubobbb’s picture

nice !
edit in file: views_views_json_style.theme.inc
...
}
$objects[] = $object;
}

// check if user wants nested arrays
$vars["rows"] = strlen($root_object) != 0 ? array($root_object => $objects) : $objects;
// ADD CODE BEGIN
global $pager_total, $pager_page_array, $pager_total_items, $pager_limits;
$vars['rows']['pager'] = array(
'pages' => $pager_total[0],
'page' => $pager_page_array[0],
'count' => intval($pager_total_items[0]),
'limit' => intval($pager_limits[0])
);
$vars["rows"]["pager"]=$vars["rows"]["pager"];
//print_r($vars['rows']['pager']);
//ADD CODE END
}

function template_preprocess_views_views_json_style_exhibit(&$vars) {
$view = $vars["view"];
$rows = $vars["rows"];......
=======================================
here is result of new json code case:
....,"pager":{"pages":9,"page":2,"count":101,"limit":12}}

othermachines’s picture

Status: Active » Needs review
FileSize
1.51 KB

I love me a nice patch. ;)

bburg’s picture

If this were used on the views_xml module, would it generate invalid xml? Since the root element is the "nodes" array.

msti’s picture

FileSize
19.34 KB

The patch at #14 works for me with views_json. check screenshot.

Chris Charlton’s picture

How many more validations do we need for RTBC?

msti’s picture

Status: Needs review » Reviewed & tested by the community

let's just add the reviewed and tested status and the maintainer will tell us if she/he is alright

ZeiP’s picture

FileSize
964 bytes

Thanks for the patch! It seems quite reasonable; however, I think it's best if the pagination element is only shown when pagination is enabled in the views. I also moved all the code to one place. Attached is a new patch.

  • ZeiP committed 26ba4b9 on 7.x-1.x
    Issue #905440 by othermachines, ZeiP, larowlan, bodrin, tyler....
ZeiP’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 7.x-1.x. Thanks everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.