Skip to main content

Loaders

Loading indicator with dependency on received data​

tsc script.ts

https://jsonplaceholder.typicode.com/ used for this example

Real fetching data​

In this example, real data is being fetched, but due to the absence of a Content-Length header in the resource https://jsonplaceholder.typicode.com/, a different example with emulated progress for the progress bar is used below.

document.addEventListener("DOMContentLoaded", function () {
const progressBar = document.getElementById(
"progress-bar",
) as HTMLDivElement | null;
const progressText = document.getElementById(
"progress-text",
) as HTMLDivElement | null;
const progressContainer = document.querySelector(
".progress-container",
) as HTMLDivElement | null;
let timeoutId: number | undefined;

function updateProgress(event: ProgressEvent<XMLHttpRequestEventTarget>) {
if (event.lengthComputable && progressBar && progressText) {
const percentComplete = Math.round((event.loaded / event.total) * 100);
progressBar.style.width = percentComplete + "%";
progressText.textContent = percentComplete + "%";
}
}

function fetchData() {
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/photos", true);
xhr.responseType = "json";

xhr.onprogress = updateProgress;

xhr.onload = function () {
if (xhr.status === 200 && progressText && progressContainer) {
progressText.textContent = "Load Complete";
timeoutId = window.setTimeout(() => {
progressContainer.style.opacity = "0";
window.setTimeout(() => {
progressContainer.style.display = "none";
}, 500);
}, 1000);
}
};

xhr.onerror = function () {
if (progressText) {
progressText.textContent = "Error loading data";
}
};

xhr.send();
}

fetchData();
});

Emulation​

document.addEventListener("DOMContentLoaded", function () {
const progressBar = document.getElementById("progress-bar") as HTMLDivElement;
const progressText = document.getElementById(
"progress-text",
) as HTMLDivElement;
const progressContainer = document.querySelector(
".progress-container",
) as HTMLDivElement;
let progress: number = 0;

// Simulate progress incrementally
function simulateProgress(): void {
if (progress < 100) {
progress += 1;
progressBar.style.width = `${progress}%`;
progressText.textContent = `${progress}%`;
setTimeout(simulateProgress, 50); // Delay of 50 milliseconds for visual demonstration
} else {
progressText.textContent = "Load Complete";
setTimeout(() => {
progressContainer.style.opacity = "0"; // Smoothly hide the progress bar
setTimeout(() => {
progressContainer.style.display = "none"; // Remove the element from the DOM
}, 500); // Delay before removal to complete the animation
}, 1000);
}
}

simulateProgress();
});