140 lines
4.8 KiB
JavaScript
140 lines
4.8 KiB
JavaScript
|
/**
|
||
|
* The base URI for the WordPress API. Don't forget `http(s)://`!
|
||
|
* Depending on where your WordPress blog is hosted, this could be something like: `https://example.wordpress.com`
|
||
|
*
|
||
|
* @type {String}
|
||
|
*/
|
||
|
const wordPressBaseUri = 'https://wptest.decicus.com';
|
||
|
|
||
|
/**
|
||
|
* Fetches 10 posts from WordPress API.
|
||
|
* Uses: https://developer.wordpress.org/rest-api/reference/posts/#list-posts
|
||
|
*
|
||
|
* @param {Number} page Which page to fetch, by default the first page (1)
|
||
|
* @param {Number} perPage How many posts to fetch per page, by default 10
|
||
|
* @returns {Array}
|
||
|
*/
|
||
|
async function fetchPosts(page = 1, perPage = 10)
|
||
|
{
|
||
|
const response = await fetch(`${wordPressBaseUri}/wp-json/wp/v2/posts?page=${page}&per_page=${perPage}`);
|
||
|
const json = await response.json();
|
||
|
return json;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Used for tracking what "page" from the WordPress API we should be fetching.
|
||
|
* You should generally not change this value.
|
||
|
*/
|
||
|
let nextPage = 1;
|
||
|
|
||
|
/**
|
||
|
* Can be used for tweaking how many posts to get per page.
|
||
|
* Will also affect how many times you have to click "View more" to get all posts
|
||
|
*/
|
||
|
const perPage = 10;
|
||
|
|
||
|
const viewMoreButton = document.querySelector('#view-more');
|
||
|
async function getPosts()
|
||
|
{
|
||
|
// Disable the "View More" button while we're fetching posts, to avoid people spamming the button
|
||
|
viewMoreButton.setAttribute('disabled', '1');
|
||
|
|
||
|
// Get the first set of posts from the API
|
||
|
const posts = await fetchPosts(nextPage, perPage);
|
||
|
|
||
|
// Get the container where we want to put the posts. By default this can just be an empty div.
|
||
|
const postsContainer = document.querySelector('#blog-posts');
|
||
|
|
||
|
/**
|
||
|
* Style points only
|
||
|
*/
|
||
|
let firstPostId = null;
|
||
|
|
||
|
// Loop though the posts and create the HTML elements for each post
|
||
|
for (const post of posts)
|
||
|
{
|
||
|
/**
|
||
|
* Style points only
|
||
|
*
|
||
|
* Since `firstPostId` is still `null`, we set it to the post's ID.
|
||
|
* Any further posts in this batch will *not* override it.
|
||
|
* Meaning it will in fact be "the first post" (of this batch).
|
||
|
*/
|
||
|
if (firstPostId === null)
|
||
|
{
|
||
|
firstPostId = post.id;
|
||
|
}
|
||
|
|
||
|
// Create post's parent div
|
||
|
const postElement = document.createElement('div');
|
||
|
postElement.setAttribute('data-post-id', post.id);
|
||
|
postElement.classList.add('post');
|
||
|
|
||
|
// Purely for styling, can ignore this part
|
||
|
postElement.classList.add('bg-rose-900');
|
||
|
postElement.classList.add('p-4');
|
||
|
postElement.classList.add('my-4');
|
||
|
|
||
|
// Create post's title as a h2
|
||
|
const postTitle = document.createElement('h2');
|
||
|
postTitle.textContent = post.title.rendered;
|
||
|
|
||
|
// Purely for styling, can ignore this part
|
||
|
postTitle.classList.add('text-xl');
|
||
|
postTitle.classList.add('font-bold');
|
||
|
postTitle.classList.add('mb-2');
|
||
|
|
||
|
// Create post's content. This is a div because WordPress will give you a lot of HTML tags in the content (e.g. `p`).
|
||
|
const postContent = document.createElement('div');
|
||
|
postContent.innerHTML = post.content.rendered;
|
||
|
|
||
|
// Append the title and content to the post's parent div
|
||
|
postElement.appendChild(postTitle);
|
||
|
postElement.appendChild(postContent);
|
||
|
|
||
|
// Append the post's parent div to the container
|
||
|
postsContainer.appendChild(postElement);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Style points only
|
||
|
* Only trigger this logic after the "view more" button has been pressed
|
||
|
*/
|
||
|
if (nextPage > 1) {
|
||
|
/**
|
||
|
* Style points only
|
||
|
* Scroll to the first post we got from the API.
|
||
|
* This will scroll to the first post of the current batch of posts
|
||
|
*/
|
||
|
const firstPost = document.querySelector(`[data-post-id="${firstPostId}"]`);
|
||
|
firstPost.scrollIntoView({ behavior: 'smooth' });
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If the amount of posts we got from the API is less than the amount of posts we requested,
|
||
|
* then we know that we have reached the end of the posts and we can hide the "View More" button.
|
||
|
*/
|
||
|
const viewMoreClasses = viewMoreButton.classList;
|
||
|
if (posts.length >= perPage)
|
||
|
{
|
||
|
viewMoreClasses.remove('hidden');
|
||
|
|
||
|
// Increase `nextPage` by 1 so that the next time we fetch posts, we get the next page
|
||
|
nextPage++;
|
||
|
}
|
||
|
/**
|
||
|
* If the amount of posts we got from the API is less than the amount of posts we requested,
|
||
|
* then we know that we have reached the end of the posts and we can hide the "View More" button.
|
||
|
*/
|
||
|
else {
|
||
|
viewMoreClasses.add('hidden');
|
||
|
}
|
||
|
|
||
|
// Re-enable the "View More" button
|
||
|
viewMoreButton.removeAttribute('disabled');
|
||
|
}
|
||
|
|
||
|
// Add an event listener to the "View More" button so that we can fetch more posts when it's clicked
|
||
|
viewMoreButton.addEventListener('click', getPosts);
|
||
|
|
||
|
getPosts();
|