Appending pagination after click
See original GitHub issueHello,
I contacted email support and Sylvain Utard asked me to ask this here, since he thinks that is makes a lot of sense to integrate it by default in instantsearch.js.
I’m building a pagination widget that appends the results. I based it on the infinite scrolling widget.
Code:
function getTemplate(templateName) {
return document.getElementById(templateName + '-template').innerHTML;
}
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
var cursor;
var index;
var page;
var nbPages;
var loading;
var hoganTemplate;
var hoganTemplateItem;
var paginator
var hitsDiv = document.getElementById('hits');
function renderTemplate(hoganTemplate, res) {
var results = document.createElement('div');
results.innerHTML = hoganTemplate.render(res);
return results;
}
function searchNewRecords(scope) {
addSearchedRecords.call(scope);
}
function addSearchedRecords() {
if (!loading && page < nbPages - 1) {
loading = true;
page += 1;
var stateObject = {paginator: (page+1)};
history.pushState(stateObject, '', '?paginator='+stateObject.paginator);
helper.searchOnce({page: page}, appendSearchResults.bind(this));
}
else if(page >= nbPages - 1)
{
document.getElementById('bcPagination').className="hidden";
}
}
function appendSearchResults(err, res, state) {
if (err) { throw err; }
page = res.page;
_.assign(res, {pageNo: page + 1});
loading = false;
var container = this.container;
hoganTemplateItem = this.hoganTemplateItem;
_.forEach(res.hits, function(value)
{
var result = renderTemplate(hoganTemplateItem, value);
container.appendChild(result);
});
if (page === nbPages - 1 && (this.args.results.nbHits > nbPages * this.args.results.hitsPerPage)) {
index = helper.client.initIndex(this.args.state.index);
}
}
function appendBrowsedResults(err, res) {
if (err) { throw err; }
cursor = res.cursor;
var result = renderTemplate(hoganTemplateItem, res);
this.container.appendChild(result);
loading = false;
}
function initialRender(container, args, hoganTemplateItem, hoganTemplateEmpty, parent) {
var results;
if (args.results.nbHits) {
_.assign(args.results, {pageNo: page + 1});
results = renderTemplate(hoganTemplateItem, args.results);
} else {
results = renderTemplate(hoganTemplateEmpty, args.results);
}
container.innerHTML = '';
container.appendChild(results);
}
function bcPagination(options) {
var container = document.querySelector(options.container);
var templates = options.templates;
var hoganTemplateItem = Hogan.compile(templates.item);
var hoganTemplateEmpty = Hogan.compile(templates.empty);
var offset = parseInt(options.offset, 10);
if (!container) {
throw new Error('BCPagination: cannot select \'' + options.container + '\'');
}
return {
init: function ({helper}) {
page = undefined;
nbPages = undefined;
paginator = getParameterByName('paginator');
//initialRender(container, args, hoganTemplateItem, hoganTemplateEmpty);
},
render: function (args) {
helper = args.helper;
page = args.state.page;
nbPages = args.results.nbPages;
paginator = page;
var scope = {
hoganTemplateItem: hoganTemplateItem,
hoganTemplateEmpty: hoganTemplateEmpty,
container: container,
args: args,
offset: offset
};
initialRender(container, args, hoganTemplateItem, hoganTemplateEmpty);
var $bcPage = this;
if (args.results.nbHits) {
if(nbPages > 1){
document.getElementById('bcPagination').className="text-center";
}
else{
document.getElementById('bcPagination').className="hidden";
}
$(document).on('click', '#bcPagination a', function(e)
{
e.preventDefault();
searchNewRecords(scope);
});
}
}
};
}
instantsearch.widgets.bcPagination = bcPagination;
search.addWidget(
instantsearch.widgets.bcPagination({
container: '#hits',
hitsPerPage: 10,
templates: {
item: getTemplate('hit'),
empty: getTemplate('no-results')
}
})
);
The default functionality is working, but I also want to save the state in the url so when a page is reloaded or a visitor uses the back button in the browser the same amount of items are loaded (so when a user visited page 5 before there should be 40 extra results loaded automatically).
I’m quite sure I can build the initial loading, but the main issue is in de history.pushState, I can’t figure out how to retrieve the other filters’ data…
How do I use the Instantsearch functions for this? Since I saw there were some functions in the instantsearch.js file that handle this functionality?
Or if there is going to be a default widget that handles this type of pagination, when can I expect this? Since I’m sure your code will be much better than mine and when it’s integrated in the instantsearch.js project it will be more future proof.
Issue Analytics
- State:
- Created 7 years ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
Ok, no problem. This is good enough for now 👍
Hmm this is not currently doable sadly, we have #1068 that would allow you to do custom actions when you refine on something.
In the meantime I do not see any quickfix to do that.