In our previous series release Build a quote generator with typescript, we converted a regular Javascript
code to Typescript
, and it was fun. In today's release, we'd be converting an Infinite Gallery viewer built with Javascript
to Typescript
.
Disclaimer: This article is part of
ZTM
Andre Negeoi's Portfolio enhancement course
The Javascript codebase is on GitHub. You should obtain the site structure and stylesheet from there. We'd focus on the Typescript
conversion here.
Setup Typescript
If you need help setting up your Typescript environment for this exercise, see the setup from our last series here
Getting an Unsplash API key
Head on to Unsplash and register, next click on api/developers
tab from the profile menu, then click on Your apps
. Follow the guide to create a new app and get your API_KEY.
Writing the App.ts
Let's start with our variables and interface definitions:
const imageContainer = document.getElementById('image-container');
const loader = document.getElementById('loader');
let photosArray: GalleryData[];
let ready = false;
let imagesLoaded = 0;
let totalImages = 0;
let count = 5;
const API_KEY = <your_api_key>;
let API_URL = `https://api.unsplash.com/photos/random/?client_id=${API_KEY}&count=${count}
`;
interface GalleryData {
alt_description: string;
urls: {
regular: string;
};
links: {
html: string;
}
}
interface Attribute {
src?: string;
alt?: string;
href?: string;
title?: string;
target?: string;
}
The functions
Our first function would be the imageLoaded
function.
// Check if all images were loaded
function imageLoaded() {
imagesLoaded++;
if (imagesLoaded === totalImages) {
ready = true;
loader!.hidden = true;
count = 30;
API_URL = `https://api.unsplash.com/photos/random/?client_id=${API_KEY}&count=${count}
`;
}
}
The special conversion highlight here is loader!.hidden = true
; When we defined the loader
element initially with this const loader = document.getElementById('loader');
, we could either have the HTMLElement
or null
. To tell typescript that we are sure that the element exists on the page, we use the !
before the element name. That overrides typescript's strict null check.
Pro-Tip: Use only when you are double sure that the element exists on the page and will not be removed throughout the lifetime of your code.
setAttribute Helper function
This function will help us stay DRY
. Typescript warns when we do not type our parameters. Our function would need
- A HTMLElement to set the attributes against, this will be the first parameter.
- An object that contains the attributes we want to set and their values.
// Helper function to set attributes on DOM elements
function setAttributes(element: HTMLElement, attributes: Attribute) {
for (const [key, value] of Object.entries(attributes as Record<string, string>)) {
element.setAttribute(key, value);
}
}
Pro Tip: To use
Object.entries
, ensure you add"ES2017"
or later to yourtsconfig.json
's lib.
displayPhotos function
The displayPhotos
function generates the DOM elements and renders it to the screen.
// Display photos
const displayPhotos = () => {
totalImages = photosArray.length;
imagesLoaded = 0;
photosArray.forEach(photo => {
// Create <a> linking to unsplash
const item = document.createElement('a');
setAttributes(item, {
href: photo.links.html,
target: '_blank'
})
// Create <img> for photo
const img = document.createElement('img');
setAttributes(img, {
src: photo.urls.regular,
alt: photo.alt_description,
title: photo.alt_description
});
// Event Listerner, check when each is finished loading
img.addEventListener('load', imageLoaded)
// Put <img> inside <a>, then put both in the imageContainer;
item.appendChild(img)
imageContainer!.appendChild(item);
});
}
Finally, we will add the getPhotos
function and attach our scroll
event to the windows object.
// Get photos from Unsplash API
const getPhotos = async () => {
try {
const response = await fetch(API_URL);
photosArray = await response.json()
displayPhotos();
} catch (error) {
}
}
// Hook up the scroll event
window.addEventListener('scroll', () => {
if (
window.innerHeight + window.scrollY >=
document.body.offsetHeight - 1000 &&
ready
) {
ready = false;
getPhotos();
}
})
// On load
getPhotos();
Now run the tsc --build tsconfig.json
to build your .ts
files into the required .js
equivalence.
This was super exciting for me, I hope you enjoy it.