Adding Load More button for infinite scrolling of Ghost Casper

I’m customizing the Casper theme and have some valuable links in footer. Auto Infinite scroll makes it impossible user to access footer as it keeps getting pushed down.

How can I add a LOAD MORE button and let visitor to click to load more article instead of automatically loading at scrolling?

Thank you!

I guess I’m the only one struggling with this :sweat_smile:

Nope, you’re not. I’m investigating this one now as I need it for a custom theme. Will notify you once I’m making progress

Okay, I got something.

In the official Casper theme, this problem is tackled using an infinite scroll.

I’ve taken the core of this function and migrated it into my own (Typescript) class.

  1. I check if there are more items to load
  2. If not, I hide the “Load More” button
  3. If there are, I’m loading the next page with an XMLHttpRequest

This page has all the basic document methods, e.g., querySelectorAll. So I query my post items and inject them into my own DOM

This is my function to load the next page. You could use a similar approach if you left out all the types in JS

fetchNextPage(): Promise<Document> {
	return new Promise((resolve, reject) => {
		const xhr = new window.XMLHttpRequest();
		xhr.responseType = 'document';
		// @ts-ignore
		xhr.addEventListener('load', (event) => resolve(event.target.response));
		xhr.open('GET', this.nextElement.href);
		xhr.send(null);
	});
}

This is my method to load and append new items into the DOM

private async loadAndAppendPosts() {
	const nextPage = await this.fetchNextPage();
	const postCards = nextPage.querySelectorAll('.postcard');
	const postFeeds = nextPage.querySelectorAll('.postfeed');
	postCards.forEach((card) => this.postContainer.appendChild(document.importNode(card, true)));
	postFeeds.forEach((feed) => this.feedContainer.appendChild(document.importNode(feed, true)));
	this.nextElement = nextPage.querySelector('link[rel=next]');
}

And finally, this is the function I bind to the button:

private async loadMorePosts() {
	if (this.nextElement) {
		return this.loadAndAppendPosts();
	}
	this.loadMoreButton.remove();
}
public init() {
	if (!this.nextElement) {
		this.loadMoreButton.remove();
	}
	if (this.valid) {
		this.loadMoreButton.addEventListener('click', () => this.loadMorePosts());
	}
}