Reputation: 16271
This function can paginate an array of items:
function paginate(res,page,page_size,max_page_size) {
page=page||1;
page_size=page_size||10;
max_page_size=max_page_size||100;
page_size=page_size>max_page_size?max_page_size:page_size;
var pages=Math.round( res.length / page_size),
items=[];
for( var p=1; p <= pages; p++) {
var start= Math.round( page_size * (p-1) );
items.push( res.slice(start,start+page_size) );
}
return page < items.length?items[page-1]:items[ items.length-1 ];
}
having
function paginate(res, page, page_size, max_page_size) {
page = page || 1;
page_size = page_size || 10;
max_page_size = max_page_size || 100;
page_size = page_size > max_page_size ? max_page_size : page_size;
var pages = Math.round(res.length / page_size),
items = [];
for (var p = 1; p <= pages; p++) {
var start = Math.round(page_size * (p - 1));
items.push(res.slice(start, start + page_size));
}
return page < items.length ? items[page - 1] : items[items.length - 1];
}
var list = Array.apply(null, Array(10)).map(function() {
return Array.apply(null, Array(Math.floor(Math.random() * 10 + 3))).map(function() {
return String.fromCharCode(Math.floor(Math.random() * (123 - 97) + 97));
}).join('')
});
console.log(list)
for (var i = 1; i < 8; i++) {
console.log("page", i, paginate(list, i, 2, 2))
}
This function has a bug, since as soon as it reaches the last paginated result, it returns always the same page. Why? Is there an alternative solution?
[UPDATE]
The issue was in the indexes calculation, this is the right version:
function paginate(res,page,page_size,max_page_size) {
page=page||1;
page_size=page_size||10;
max_page_size=max_page_size||100;
page_size=page_size>max_page_size?max_page_size:page_size;
var pages=Math.ceil( res.length / page_size),
items=[];
for( var p=1; p <= pages; p++) {
var start= page_size * (p-1)
items.push( res.slice(start,start+page_size) );
}
return page <= items.length?items[page-1]:[];
}
There were 2 errors: Math.round
instead of Math.ceil
and the last ternary operator page <= items.length?items[page-1]:[];
Upvotes: 1
Views: 8005
Reputation: 8589
Haven't identified the exact issue with your code yet, but I remember struggling alot with keeping state and resetting the index when I reached the end of the array while using rounding functions.
In the end I just made a 'chunker' to divide an array into chunks and hooked that up to something that rendered the array contents using the previous() and next() methods to grab the correct art of the array. Which page it actualy represents in the view, is up to the view to cache.
var Chunker = function Chunker( config ) {
if ( !Array.isArray( config.data ) ) {
throw new Error('chunker source is not an array');
return false;
}
this.data = config.data;
this.index = 0;
this.length = config.len || config.data.length; // Amount of items per chunk. When not defined, will return the entire array.
};
Chunker.prototype = {
'constructor' : Chunker,
'index' : function index( number ) { // => current index (getter) || => this (setter)
if ( number !== undefined ) {
this.index = index;
return this;
}
else return this.index;
},
'current' : function current() { // => { "index", "data" }
return {
"index" : this.index,
"data" : this.data.slice( this.index, this.index + this.length )
};
},
'next' : function next() { // => next chunk
this.index += this.length;
if ( this.index > this.data.length ) this.index = this.data.length - (this.data.length % this.length);
return this.current();
},
'previous' : function previous() { // => previous chunk
this.index -= this.length;
if (this.index < 0 ) this.index = 0;
return this.current();
},
'reset' : function reset() { // => this
this.index(0);
return this;
}
};
Upvotes: 1