NOVINKA: Staň se datovým analytikem od 0 Kč a získej jistotu práce, lepší plat a nové kariérní možnosti. Více informací:

Lekce 12 - AJAX v JavaScriptu - Prohlížeč pokémonů

V minulé lekci, AJAX v JavaScriptu - Základní dotazy, jsme si zkusili základní použití technologie AJAX na našem novém projektu prohlížeče pokémonů. Stáhli jsme si data o pokémonech z webového API.

V dnešním tutoriálu OOP v JavaScriptu budeme pokračovat s tvorbou prohlížeče pokémonů pomocí AJAXu.

Odpověď serveru

Zaměřme se nyní na vrácená data ve formátu JSON. Odpověď serveru vypadá následovně (již jsme ji viděli, tak ji zde zkrátíme a také lépe naformátujeme):

{
    "count":964,
    "next":"https://pokeapi.co/api/v2/pokemon?offset=20&limit=20",
    "previous":null,
    "results":
    [
        {"name":"bulbasaur","url":"https://pokeapi.co/api/v2/pokemon/1/"},
        {"name":"ivysaur","url":"https://pokeapi.co/api/v2/pokemon/2/"},
        ...,
        {"name":"raticate","url":"https://pokeapi.co/api/v2/pokemon/20/"}
    ]
}

Hned první položka (count) na vráceném objektu nám říká, že již existuje neuvěřitelných 964 pokémonů. Nejvíce nás zajímá pole results, kde jsou objekty se jmény pokémonů a adresami na API s jejich detaily. Jak to, že je v poli ale pouze 20 pokémonů, když jich je celkem skoro 1000? Není to chyba, je to tím, že zdroj na této URL se chová tak, že vrátí pouze prvních 20 pokémonů, aby nezatěžoval server. V položce next nám navíc nabídne URL, která načte 20 následujících pokémonů. Zpravidla totiž nepotřebujeme uživateli zobrazit 1000 položek najednou, místo toho API očekává, že je budeme načítat průběžně (třeba při scrollování stránkou dolů). Pokud bychom chtěli stáhnout všechny pokémony najednou, musíme upravit parametr limit v URL: https://pokeapi.co/api/v2/pokemon?limit=1000.

Prohlížeč pokémonů

Nyní tedy umíme stahovat data a je jen na nás, jak s nimi naložíme. Pojďme si naprogramovat jednoduchý prohlížeč pokémonů.

Funkce stahniJSON()

Budeme již dělat více requestů, proto si to zjednodušíme novou funkcí stahniJSON(). Náš dosavadní kód v souboru obsluha.js tedy smažeme a přidáme si definici nové funkce stahniJSON():

function stahniJSON(url, callback)
{
    const xhr = new XMLHttpRequest();
    xhr.onload = () => {
        callback(JSON.parse(xhr.response));
    };
    xhr.open("GET", url);
    xhr.send();
}

Funkce jen obaluje vytvoření, otevření a odeslání požadavku, abychom nemuseli psát pokaždé to samé znovu. Přijímá dva parametry:

  • url – Adresa, ze které chceme stáhnout data.
  • callback – Funkce, kterou voláme po úspěšném stažení dat ze serveru. Stažená data této funkci předáváme parametrem.

Všimněme si parsování JSON do objektu pomocí JSON.parse(), protože odpovědí serveru je text.

HTML kostra

Připravíme si základní HTML kostru stránky, do které budeme AJAXem stahovat seznam pokémonů a následně dokonce zobrazovat detaily vybraného pokémona, včetně jeho obrázku :) Budeme tedy potřebovat jeden <div> pro seznam pokémonů a jeden pro detaily jednoho pokémona. Oba obalíme třetím elementem <div> a vložíme na začátek elementu <body> souboru index.html:

<div id="poke-container">
    <div id="poke-seznam"></div>
    <div id="poke-detaily"></div>
</div>

Načítání pokémonů

Nyní budeme potřebovat další dvě funkce – nactiSeznam() a nactiPokemona(), které stáhnou data a přepíšou obsah na stránce. Pojďme si je naprogramovat.

Načtení seznamu

Do souboru obsluha.js tedy vložíme další funkci nactiSeznam() s následujícím kódem:

function nactiSeznam(url) {
    const seznamDivElement = document.getElementById("poke-seznam");
    seznamDivElement.innerHTML = "<ul id='poke-seznam-ul'></ul>";
    const seznamElement = document.getElementById("poke-seznam-ul");

    stahniJSON(url, (data) => {
        for (const pokemon of data.results) {
            const urlPokemona = pokemon.url;

            const tlacitko = document.createElement("button");
            tlacitko.innerHTML = pokemon.name;
            tlacitko.onclick = () => {
                nactiPokemona(urlPokemona);
            };

            const novaPolozka = document.createElement("li");
            novaPolozka.appendChild(tlacitko);
            seznamElement.appendChild(novaPolozka);
        }
    });
}

Funkce v parametru přijímá adresu API, ze kterého budeme stahovat data. V těle funkce si nejprve vytváříme element seznamu, do kterého pokémony vypíšeme. Jde o základní práci s DOM elementy. Samotné pokémony následně stahujeme pomocí naší funkce stahniJSON(). Té předáváme adresu API a anonymní funkci, která se zavolá po úspěšném stažení dat.

Tato anonymní funkce má pouze jeden parametr s objektem obsahujícím stažená data. Pokémoni jsou obsaženi ve vlastnosti results. Pokémony procházíme cyklem a pro každého vytváříme položku seznamu s tlačítkem. Každému tlačítku přidáváme obsluhu události onclick, ve které voláme funkci nactiPokemona() s patřičnou URL získanou z dat API.

Každé API pochopitelně odpovídá ve specifickém formátu a musíme si nastudovat, jak s ním pracovat.

Načtení detailu pokémona

Podívejme se, jak vypadá JSON s detailem nějakého pokémona, což nám osvětlí, jaká data přenést do naší aplikace. Kvůli všem útokům pokémona a jejich detailům je JSON opravdu vyčerpávající, pro naše účely si tyto části uvádět nebudeme, níže jsou nahrazeny třemi tečkami ...:

{
    "abilities": [
        ...
    ],
    "base_experience": 64,
    "forms": [
        ...
    ],
    "game_indices": [
        ...
    ],
    "height": 7,
    "held_items": [],
    "id": 1,
    "is_default": true,
    "location_area_encounters": "https://pokeapi.co/api/v2/pokemon/1/encounters",
    "moves": [
        ...
            ]
        }
    ],
    "name": "bulbasaur",
    "order": 1,
    "species": {
        "name": "bulbasaur",
        "url": "https://pokeapi.co/api/v2/pokemon-species/1/"
    },
    "sprites": {
        "back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/1.png",
        "back_female": null,
        "back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/shiny/1.png",
        "back_shiny_female": null,
        "front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png",
        "front_female": null,
        "front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/1.png",
        "front_shiny_female": null
    },
    "stats": [
        ...
    ],
    "types": [
        {
            "slot": 2,
            "type": {
                "name": "poison",
                "url": "https://pokeapi.co/api/v2/type/4/"
            }
        },
        {
            "slot": 1,
            "type": {
                "name": "grass",
                "url": "https://pokeapi.co/api/v2/type/12/"
            }
        }
    ],
    "weight": 69
}

Výše vidíme JSON pro Bulbasaura, konkrétně stažený z URL https://pokeapi.co/api/v2/pokemon/1/, kde parametr 1 udává číslo pokémona. Zajímá nás zejména vlastnost name s názvem pokémona, sprites s jeho obrázky, height s výškou a weight s váhou dané potvůrky. Samozřejmě bychom mohli i vypsat například typy pokémona, vidíme, že zrovna Bulbasaur je jedovatý a zároveň travní typ.

V souboru obsluha.js si vytvoříme další funkci posílající dotaz na konkrétního pokémona s následujícím kódem:

function nactiPokemona(url) {
    const detailyDivElement = document.getElementById("poke-detaily");

    stahniJSON(url, (data) => {
        detailyDivElement.innerHTML = `
            <img src="${data.sprites.front_default}" />
            <ul>
                <li>Název: ${data.name}</li>
                <li>Výška: ${data.height}</li>
                <li>Váha: ${data.weight}</li>
            </ul>
        `;
    });
}

Zavolání načtení seznamu

Vše máme připraveno. Stačí již jen jako poslední řádek našeho javascriptového souboru zavolat načtení seznamu:

nactiSeznam("https://pokeapi.co/api/v2/pokemon");

CSS styly

Aby náš prohlížeč vypadal trochu líbivěji, přidáme si ještě nějaké CSS styly. Ve složce css/ si vytvoříme soubor styly.css s následujícím kódem:

#poke-container {
    display: flex;
    gap: 2rem;
}

#poke-detaily {
    text-align: center;
    margin-left: 10px;
}

#poke-container ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
}

#poke-seznam li button {
    width: 100%;
    padding: 5px 20px;
    background-color: #e0ffe0;
    cursor: pointer;
    border: 0;
    border-bottom: 1px solid green;
}

#poke-seznam li button:hover {
    background-color: green;
}

Nezapomeneme si je samozřejmě nalinkovat v hlavičce souboru index.html:

<head>
    <meta charset="UTF-8">
    <title>Prohlížeč pokémonů</title>
    <link href="css/styly.css" rel="stylesheet">
</head>

Interaktivní ukázka

Výsledek bude vypadat takto:

Prohlížeč pokémonů
localhost

Po kliknutí na položku se načtou základní informace o pokémonovi a obrázek.

Tímto možnosti API s pokémony opravdu nekončí :) Jak sami vidíte, API pokémonů je velmi chytré a všude nám nabízí další URL, přes které se dostaneme k dalším datům, třeba k abilitám.

V příští lekci, AJAX v JavaScriptu - POST a další HTTP dotazy, pošleme AJAX požadavky pro ukládání a zpracování dat a ukážeme si jak zpracovat chyby.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 345x (2.86 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

Předchozí článek
AJAX v JavaScriptu - Základní dotazy
Všechny články v sekci
Objektově orientované programování v JavaScriptu
Přeskočit článek
(nedoporučujeme)
AJAX v JavaScriptu - POST a další HTTP dotazy
Článek pro vás napsal Radek Veverka
Avatar
Uživatelské hodnocení:
249 hlasů
Jsem student VUT FIT v třetím ročníku. Nejraději mám Typescript a C#.
Aktivity