/**
* api-demo.js
* Fetch & API Demo – jsonplaceholder.typicode.com/users
* Lädt Benutzer per fetch(), rendert sie im DOM, mit Fehlerbehandlung & Filterung.
*/
document.addEventListener('DOMContentLoaded', function () {
// ── DOM-Referenzen ────────────────────────────────────────────────────────
const userList = document.getElementById('user-list');
const loadingEl = document.getElementById('api-loading');
const errorEl = document.getElementById('api-error');
const errorMsgEl = document.getElementById('api-error-msg');
const countEl = document.getElementById('user-count');
const searchInput = document.getElementById('api-search');
const btnReload = document.getElementById('btn-reload');
const btnRetry = document.getElementById('btn-retry');
// Nur auf der API-Demo-Seite ausführen
if (!userList) return;
// Alle geladenen User merken (für Client-seitigen Filter)
let allUsers = [];
// ── Hilfsfunktionen ───────────────────────────────────────────────────────
/** Zeigt den Lade-Spinner */
function showLoading () {
loadingEl.removeAttribute('hidden');
errorEl.setAttribute('hidden', '');
userList.innerHTML = '';
countEl.textContent = '';
if (btnReload) btnReload.disabled = true;
}
/** Versteckt den Lade-Spinner */
function hideLoading () {
loadingEl.setAttribute('hidden', '');
if (btnReload) btnReload.disabled = false;
}
/** Zeigt eine Fehlermeldung an */
function showApiError (message) {
hideLoading();
errorMsgEl.textContent = message;
errorEl.removeAttribute('hidden');
countEl.textContent = '';
}
/**
* Erstellt eine User-Karte als
-Element
* @param {Object} user – JSON-Objekt aus der API
* @returns {HTMLLIElement}
*/
function createUserCard (user) {
const li = document.createElement('li');
li.className = 'api-user-card';
li.innerHTML = `
${user.name.charAt(0).toUpperCase()}
${user.name}
@${user.username}
`;
return li;
}
/**
* Rendert eine Liste von Usern in den DOM
* @param {Array} users
*/
function renderUsers (users) {
userList.innerHTML = '';
if (users.length === 0) {
userList.innerHTML = 'Keine Benutzer gefunden. 🔍';
countEl.textContent = '';
return;
}
// DocumentFragment für performantes Einfügen (ein Reflow statt n)
const fragment = document.createDocumentFragment();
users.forEach(function (user) {
fragment.appendChild(createUserCard(user));
});
userList.appendChild(fragment);
countEl.textContent = users.length + ' Benutzer geladen ✅';
}
// ── Haupt-Fetch-Funktion ──────────────────────────────────────────────────
function loadUsers () {
showLoading();
// ① fetch() aufrufen
fetch('https://jsonplaceholder.typicode.com/users')
// ② Antwort prüfen & als JSON parsen
.then(function (response) {
if (!response.ok) {
throw new Error('HTTP-Fehler: ' + response.status + ' ' + response.statusText);
}
return response.json();
})
// ③ Daten verarbeiten & im DOM rendern
.then(function (users) {
console.log('✅ API-Antwort erhalten:', users);
console.table(users.map(function (u) {
return { Name: u.name, 'E-Mail': u.email, Stadt: u.address.city, Firma: u.company.name };
}));
allUsers = users;
hideLoading();
renderUsers(allUsers);
// Suchfeld zurücksetzen
if (searchInput) searchInput.value = '';
})
// ④ Fehlerbehandlung
.catch(function (err) {
console.error('❌ Fetch-Fehler:', err);
showApiError(err.message || 'Unbekannter Fehler. Bitte Internetverbindung prüfen.');
});
}
// ── Client-seitiger Filter ────────────────────────────────────────────────
function filterUsers (query) {
if (!query.trim()) {
renderUsers(allUsers);
return;
}
const q = query.toLowerCase();
const filtered = allUsers.filter(function (user) {
return (
user.name.toLowerCase().includes(q) ||
user.username.toLowerCase().includes(q) ||
user.address.city.toLowerCase().includes(q) ||
user.company.name.toLowerCase().includes(q) ||
user.email.toLowerCase().includes(q)
);
});
renderUsers(filtered);
}
// ── Event Listener ────────────────────────────────────────────────────────
if (btnReload) btnReload.addEventListener('click', loadUsers);
if (btnRetry) btnRetry.addEventListener('click', loadUsers);
if (searchInput) {
searchInput.addEventListener('input', function () {
filterUsers(this.value);
});
}
// ── Beim Seitenaufruf automatisch laden ───────────────────────────────────
loadUsers();
});