Introduction
- This tutorial will explain how to create your own custom AJAX load more plugin very easily and responsively
- This plugin is developed using plain JS instead of the jQuery library
- This plugin will load a set of posts of the specific category in grid-card fashion with a load more button
- To load remaining posts of that specific category click the load more button
- You can download the plugin source from GitHub
- Each card holds post image, title, excerpt and read more button for reference you can check the below image

Let’s Explore The ShortCode
- As described in the readme file of the GitHub source the shortcode can be expressed as
[vg_ajax_posts category_name="post-formats" posts_per_page="6"]
- In the above shortcode
vg_ajax_posts
is the shortcode’s name which has two attributes - The first attribute is
category_name
which accepts any post category slug - The second attribute is
posts_per_page
which accepts the maximum number of posts to show on every fetch
Let’s Explore The Plugin’s main class
- This 100 lines of code are the kernel of this plugin lets we inspect each method of the class
VG_Infinite_Scroll
in its own sections - If you closely noted all the methods are static method to callback the method in hooks without object instantiation
Method get_custom_posts
:
- line 24 : the method accepts a single parameter
$atts
which is an array that contains key-value options passed in the shortcode - line 28: we calling WordPress function
shortcode_atts
with the first parameter as default value array and the second parameter as user passed value through shortcode - The function
shortcode_atts
will check if the user passed keys are available in the first parameter if present then it will push that to output array which is returned by this function if not present then the default value is considered and push to the output array - If any attribute’s key passed in the shortcode is not match with any key of the default array then that attributes are simply ignored
- line 33: we calling Transient API function
set_transient
which set or update the value to the given key - The transient data can be cached timely fashion say 1 day or no expiration this can be in database or Redis or Memcache based on your configuration by default the transient cache storage is the database
- This function accepts three parameters they are transient name, transient value, TTL (Time To Live) the third parameter accepts some predefined constants as we passed
DAY_IN_SECONDS
- The reason here why we add our shortcode attributes to the transient data is we can use it in
AJAX
call - line 34: we call the static method
posts_ui
which return the HTML structure of the series of posts of the specific category we will see more about this function on its own section as for now just note that it returns the HTML of our cards structure - line 36: we wrap our series of cards into the parent HTML which forms 3 columns or 1 column card(s) based on the screen resolution to be clear it returns an HTML to render to form the grid of posts in the card layout
- This static method is hooked into the shortcode with the shortcode name
vg_ajax_posts
have you noted this is the name we used to call our shortcode in the backend page or post editor
Method posts_ui
:
- The
posts_ui
is the private static method which is used to generate the cards HTML and return that HTML - Line 42: we pass our shortcode attributes to the function
set_query_var
the purpose of this function is globalizing the value by assigning the key-value pair to the global variable$wp_query
here the first parameter is the key of data type string and the second parameter is the value of data type mixed - Line 44: called the one of the PHP output control function
ob_start()
which initiates the output buffering it means all the generated output will be stored in an internal buffer - Line 45: called the method
load_template
which will output the template by referencing the path which we passed as the first parameter - The rendered HTML is stored in a temporary buffer
- Line 46: called the PHP function
ob_get_contents()
which returns the content of the output buffer which we initiated at line 44 and assign it to the variable$output
- Line 47: called the PHP function
ob_end_clean()
which clean and silently discard the buffer contents - Line 49: return the rendered HTML lets we see about that template file which is located in the plugin root path
templates/vg-posts-content.php
- Line 2: instantiates a
WP_Query
object with the parameter$att
assign it to the variable$vg_posts_ui_query
- Line 4: we call
WP_Query
member methodhave_posts()
in a conditional statement to check if we have posts for our queried query - If we have posts for our query the conditional statement will allow further execution as the method
have_posts()
return booleanTrue
- Line 6: method
the_post()
retrieves the next post in every loop till the loop ends - The remaining HTML part between the
<article>...</article>
tag is a self-explanatory one
Method fetch_remaining_posts
:
- This method is used for AJAX call to fetch remaining posts using offset
- Line 59: we call the function
get_transient
with the keyget_custom_posts_att
which retrieve the transient value - Line 60: we fetch our offset post data from AJAX and push it to the array variable
$att
with the associative indexoffset
- Line 62: we call our template rendering method
posts_ui
with the query parameter passed through$att
- Finally, we terminate the method call using the function
die()
Method get_post_count
:
- This method is used to get the total number of posts present in a queried post category
- Line 73: we fetch our shortcode’s transient data
- Line 74: to fetch total count we have to unset our
posts_per_page
element from the transient data - Line 76: instantiate
WP_Query
with arguments to filter - Line 78: return count of the number of posts found
Method add_assets
:
- This method is responsible for importing static content like JS, CSS and pass data to client end i.e. to HTML page
- Line 88 & 89: we import our plugin’s required JS & CSS using the enqueuing process
- Line 90: function
wp_localize_script
is used to passing data to main.js by using same handle name as we used in enqueuing themain.js
file in the first argument, the second argument string value is used as JS object in the frontend, the third argument holds the object’s properties as key-value pair
Hooking Class Method
- Line 97: The function
add_shortcode
creates a new shortcode here with the namevg_ajax_posts
- The second parameter is the callback to call
- Our callback function is a class method so we call by passing an array the first index holds the class name as a string and the second index holds the method name as a string
- Line 98: hooked our assets method to the action
wp_enqueue_scripts
, irrespective of its name ends with scripts which is responsible for bringing the CSS and JS to the frontend - Line 99 & 100: these two actions are like two sides of a coin either one will be triggered these two hooks responsible fire an ajax call
- You can check the source code of the ajax implementation in WordPress
Let’s Explore The Plain JavaScript
Override Native Fetch Function
- Line 3: Assign the native JavaScript
fetch
function to a variable - Line 6: declare a function
fetch
under thewindow
object to override the existingfetch
function - Because the native
fetch
function doesn’t support event to identify ajax start and end so we overrode that function - Line 9 & 10: two new event with the name
fetchStart
andfetchEnd
created - Line 13: call the native
fetch
with the argument passed to our customfetch
and assign the native fetch return value to the variablefetchCall
- Line 16: the
fetchStart
event is dispatched the listening function codes will be executed during the event dispatch - Line 18 – 24:
fetchEnd
event is dispatched either during the call success or any exception is thrown - Line 26: return the variable
fetchCall
which was assigned with nativefetch
return
Listening To The Events
- Line 29: implemented an event listener function for
fetchStart
event - Line 30: added our spinner class
vg-spinner
to load more button which displays a loading spinner animation to indicate posts are fetching - Line 31: turned off the pointer event i.e. clicking of the load more button won’t trigger any functionality by assigning
none
to thepointerEvents
property - The reason to disabled pointer event is to avoid consecutive ajax call
- Line 34: implemented an event listener function for
fetchEnd
event - Here we do quite the opposite of what we did in previous listener function
- Line 35: removed our spinner animation by removing the CSS class
vg-spinner
to indicate ajax fetch has been completed - Line 36: turned on the pointer event by assigning the
pointerEvents
property with the valueauto
which results in event triggering capability enabled to the load more button - Line 38 – 42: the reason for wrapping our core logic inside an anonymous function of
setTimeout
is used to avoid the race condition of execution our code even before the button generated and rendered in the DOM - The conditional statement compares whether the displayed post card element count is equal to the total record count fetched from WP localize variable
- If it is equal then conditional statement be boolean true which results in the execution of inner block whose functionality is to hide the load more button after fetching all posts of the particular category
Frontend Kernel Function
- Line 45 – 54: this anonymous function which is called on the
onLoad
event is the heart (no! no! brain) of functionality which triggers our ajax functionactionAjax()
- Line 46: fetch the DOM object of the load more button and assign it to the variable
loadMoreButtonObj
- Line 48: conditional check to confirm
loadMoreButtonObj
is set to a value and it’s not an undefined one - Line 49: if the condition is validated to true then to the load more button click event we register our ajax function
actionAjax()
Get Loaded Posts Count
- Line 56: the function
get_loaded_post_count()
is the simple function to get the count of total loaded posts - Line 57: here we called
length
property of the methodquerySelectorAll
which retrieves all the matched DOM object for the passed selector string as an argument
JavaScript AJAX Call
- Line 60: we declared our ajax function
actionAjax
- Line 61: called our overridden
fetch
API function with the localized object propertyfetch_remaining_post.ajaxurl
- This
fetch
API will work in all modern browser if your’s is legacy one then go for a polyfill - To learn more about fetch API read the MDN documentation
- The fetch API second parameter is the object with key-value pair of additional properties to handle the current ajax call
- Line 62: call our ajax in
POST
method type instead of the defaultGet
method type - Line 63: we set a header to handle our data as form data
- Line 64 – 67: we pass our query parameters through
URLSearchParams
utility method - Line 69: the first chained promise takes the fetch API’s
response
object and thetext()
method of this object returns all the streamed text in Unicode string - Line 70: the second chained promise execute after retrieval of all streamed data and append it at the end of the post grid
Conclusion
- Through this tutorial, you learned to create a plugin to load posts excerpts elegantly
- Learned about backend technologies like WordPress plugin creation, shortcode hook, Transient API, passing value to JavaScript, doing Ajax call
- Learned about overriding native function, fetch API to do ajax call, adding and listening custom event, promise function and catch the exception, using CSS like selector to fetch DOM object, manipulating DOM using its method and properties, hooking a function in JavaScript events, method chaining
- The thing we left is CSS file of this plugin which is self-explanatory so we left it out for you as homework to play and learn with the CSS