Hi there - have you ever seen “infinite scroll” mechanism?
You know it, you can scroll forever through posts (and ads), like on TikTok or Instagram
Is there some magic going on there? Nah, it’s just code
Today, we’ll be creating such thing - and I’ll also talk about how it works. As it’s possible because of AJAX
But, what is it? Let’s dive right into it.
We’ll start with quick explanation. Then PHP comes in place and we end everything by applying knowledge from first paragraphs in javascript.
Now for real, off we go!
Intro to AJAX and quick history lesson
AJAX stands for Asynchronous JavaScript And XML
It’s a mechanism for JavaScript to send requests to the server without using any other technology (such as HTML forms)
This technology is pretty old. According to Wikipedia it appeared first time in 1999 - so 25 years ago.
It used to use XML (Extensible Markup Language) as a response format. That’s why it has X
in its abbreviation
Hold on. Response? What is that?
HTTP protocol 101
This is not an article about HTTP - but we need a brief overview anyways.
Hypertext Transfer Protocol (or HTTP in short) is application level, client-server protocol used for fetching resources, for example in the internet. Client sends some data, like what site do we want to visit, to the server and it handles those.
This data sent by client (browser, app, API, whatever else) is called request Answer from the server (like HTML document or HTTP code) is called response
All right - if you want to know more check out MDN and Cloudflare For solely techincal information - RFC 2616 is your friend
No more about networking. We’re comming back to javascript
Old way - XMLHttpRequest
Before all newer solutions, there was an object called XMLHttpRequest
To start - you need to create it
const xhr = new XMLHttpRequest();
Then, specify destination of a request and define its type. I’ll go with file called data.json
xhr.open('GET', `data.json`);
xhr.responseType = 'json';
Now, we’re ready to send it
xhr.send();
Yeah cool, but we want those precious data! And we can get it
Check if request even made it and then we can parse JSON
xhr.addEventListener("load", ()=>{
const jsonResp = xhr.response
})
And we can do whatever we want to with those. Overall code looks like this
const xhr = new XMLHttpRequest();
xhr.open('GET', `data.json`);
xhr.responseType = 'json';
xhr.send();
xhr.addEventListener("load", ()=>{
const jsonResp = xhr.response;
})
JSON this, JSON that - What is it actually?
JSON - data storing done better
Back in the days, most of the data going around the internet was in either XML or HTML format.
But now, it changes. New king has come
JSON - Javascript Object Notation.
It uses data object with attribute-value pairs and arrays.
Here’s a quick example of such JSON:
{
"name": "John Doe",
"age": 30,
"city": "New York",
"email": "john.doe@example.com",
"phone": "123-456-7890",
"is_student": false,
"hobbies": ["reading", "hiking", "photography"],
"address": {
"street": "123 Main St",
"city": "New York",
"zip": "10001"
}
}
Looks like JS object - right? And as you see, it can be nested.
So we can put object in object and so on.
Basic structure looks like this
{
"attribute": "value",
"attribute": "value",
"array": ["some", "array", "data"],
"object":{
"property": "1",
"property2": "2",
"property3": "3"
}
}
With all of this said, let’s see what we’ll be doing today
fetch
- new way of sending requests
In 2015, a new feature was presented - Fetch API
It was meant to replace XMLHttpRequest
and it actuall did it. So, how do we use it?
First, specify what do we want to grab
const url = "http://example.com/data.json"
Now, we’re ready to make the requests
fetch()
function takes 2 arguments -
- Location of reesource we want to fetch
- Additional options, like
POST
data, credentials, headers - you can find it all here
Then, we can parse data to JSON (or text) and do whatever we want to
fetch(url, {
"method": "GET"
})
.then( req => req.json())
.then( data => console.log(data))
With this said, let’s start coding actual project
Coding infinite scroll
What will we be doing today?
We’re gonna code a site that showcases a load of names pulled in from PHP.
We’ll first get a bundle of 20 names - then with each click of the button add additional
Backend mechanics in PHP
Start with creating new file - I called it api.php
I’ve created 2 arrays with bunch of first and last names. That’s where our data will come from
<?php
$firstNames = [
"John", "Emma", "Michael", "Olivia", "William", "Ava", "James", "Sophia", "Benjamin", "Isabella",
"Jacob", "Mia", "Ethan", "Charlotte", "Alexander", "Amelia", "Henry", "Harper", "Daniel", "Evelyn",
"Matthew", "Abigail", "Jackson", "Emily", "Samuel", "Elizabeth", "Sebastian", "Sofia", "David", "Avery",
"Joseph", "Ella", "Luke", "Grace", "Gabriel", "Chloe", "Andrew", "Victoria", "Nathan", "Lily",
"Christopher", "Madison", "Ryan", "Scarlett", "Christian", "Zoey", "Jonathan", "Layla", "Noah", "Natalie"
];
$lastNames = [
"Smith", "Johnson", "Williams", "Jones", "Brown", "Davis", "Miller", "Wilson", "Moore", "Taylor",
"Anderson", "Thomas", "Jackson", "White", "Harris", "Martin", "Thompson", "Garcia", "Martinez", "Robinson",
"Clark", "Rodriguez", "Lewis", "Lee", "Walker", "Hall", "Allen", "Young", "Hernandez", "King",
"Wright", "Lopez", "Hill", "Scott", "Green", "Adams", "Baker", "Gonzalez", "Nelson", "Carter",
"Mitchell", "Perez", "Roberts", "Turner", "Phillips", "Campbell", "Parker", "Evans", "Edwards", "Collins"
];
Then, let’s generate the bundle of 20 names and encode it to JSON
$dataBundle = [];
for($i = 0; $i < 20; $i++){
$name = $firstNames[array_rand( $firstNames )] . ' ' . $lastNames[array_rand($lastNames)];
array_push($dataBundle, ['id' => rand(), 'name' => $name]);
}
echo json_encode($dataBundle);
Whole code looks like this
<?php
$firstNames = [
"John", "Emma", "Michael", "Olivia", "William", "Ava", "James", "Sophia", "Benjamin", "Isabella",
"Jacob", "Mia", "Ethan", "Charlotte", "Alexander", "Amelia", "Henry", "Harper", "Daniel", "Evelyn",
"Matthew", "Abigail", "Jackson", "Emily", "Samuel", "Elizabeth", "Sebastian", "Sofia", "David", "Avery",
"Joseph", "Ella", "Luke", "Grace", "Gabriel", "Chloe", "Andrew", "Victoria", "Nathan", "Lily",
"Christopher", "Madison", "Ryan", "Scarlett", "Christian", "Zoey", "Jonathan", "Layla", "Noah", "Natalie"
];
$lastNames = [
"Smith", "Johnson", "Williams", "Jones", "Brown", "Davis", "Miller", "Wilson", "Moore", "Taylor",
"Anderson", "Thomas", "Jackson", "White", "Harris", "Martin", "Thompson", "Garcia", "Martinez", "Robinson",
"Clark", "Rodriguez", "Lewis", "Lee", "Walker", "Hall", "Allen", "Young", "Hernandez", "King",
"Wright", "Lopez", "Hill", "Scott", "Green", "Adams", "Baker", "Gonzalez", "Nelson", "Carter",
"Mitchell", "Perez", "Roberts", "Turner", "Phillips", "Campbell", "Parker", "Evans", "Edwards", "Collins"
];
$dataBundle = [];
for($i = 0; $i < 10; $i++){
$name = $firstNames[array_rand( $firstNames )] . ' ' . $lastNames[array_rand($lastNames)];
array_push($dataBundle, ['id' => rand(), 'name' => $name]);
}
echo json_encode($dataBundle);
Right now, if you visit this page in the browser, you will see JSON with new names every time you refresh the page.
That’s what we needed - now time for JS
Frontend - AJAX in action
I’ll start with simple HTML template - create 2 files index.html
and styles.css
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Random names</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class = "header">
<h1>A page with unlimited names</h1>
</header>
<main id = "names">
</main>
<script src="fetch-names.js"></script>
</body>
</html>
body{
text-align: center;
}
.big-name{
font-size: xx-large;
padding-top: 15px;
}
There’s not much of it - I’ve placed there a heading and centered everything
This is where the fun beggins
Fetch names from PHP in JS
As we’ll be accessing data on the server a couple of times, I decided to create a function
const fetchNames = () =>{
}
Inside, let’s execute our fetch
command
fetch("http://localhost/infinite-scroll-plain/api.php", {
method: "GET"
})
This will send GET
request to fetch data from our PHP script. If you have another url for this (for example, because you named the folder differently), replace that URL with one working for you
We need to handle what we got as well. Append (or add in the next line)
.then(res => res.json())
That’s how we can parse response body as JSON - so then we access it like a normal object
To finish, call function displayNames
which will be the one responsible for putting those onto a page
.then(data => {
displayNames(data);
})
But, what if something went wrong? We need to be prepared as well
.catch(error =>{ displayNames([])})
When request meseses up, just return empty array Overall, this function is finished. And it looks like this
const fetchNames = () =>{
fetch("http://localhost/infinite-scroll-plain/api.php", {
method: "GET"
})
.then(res => res.json())
.then(data => {
displayNames(data);
})
.catch(error =>{ displayNames([])})
}
We’ve got 2 more things to do
Display names in the browser
When we have names fetched, time to show those
We want to display names 2 times
- When site is loaded
- When user scrolls
So, let’s code displayNames
function
const displayNames = (names) =>{
}
Grab main
element with id
equal to “names”
const dest = document.querySelector("#names");
And create a for-each loop, which will append names from the argument as children for <main>
element
names.forEach(name => {
const p = document.createElement("p")
p.textContent = name
p.className = 'big-name'
dest.appendChild(p)
});
I also added class big-name
, so these tags appear bigger
Last thing
Piece everything togehter - event handling
As we’ve set before, we need to create 2 event listeners for infinite scroll to work
- When page is loaded ```js window.addEventListener(“load”, fetchNames(), false)
2. And when user finishes scrolling
```js
document.addEventListener("scrollend", fetchNames)
To sum up - our javascript looks like this
const fetchNames = () =>{
console.log("called")
fetch("http://localhost/infinite-scroll-plain/api.php", {
method: "GET"
})
.then(res => res.json())
.then(data => {
displayNames(data);
})
.catch(error =>{ displayNames([])})
}
const displayNames = (names) =>{
const dest = document.querySelector("#names");
names.forEach(name => {
const p = document.createElement("p")
p.textContent = name['name']
p.className = 'big-name'
dest.appendChild(p)
});
}
window.addEventListener("load", fetchNames(), false)
document.addEventListener("scrollend", fetchNames)
And that’s it - we made it
Conclusion
Thanks for reading this article, I hope you’ve enjoyed it. If you found it useful, share it with your friends
Also, I need to think a little about what to post next - I’m open for any suggestions Code will be available on my GitHub
That’s about it - see you next time