NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

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, kdy jsme si stáhli data o pokémonech z webového API.

Dnes naprogramujeme prohlíž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ím a také lépe naformátuji):

{
    "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":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ů.

stahniJSON()

Budeme již dělat více requestů, proto si to zjednodušíme novou funkcí stahniJSON(url, callback):

function stahniJSON(url, callback)
{
    let 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. Všimněte si parsování JSON do objektu pomocí JSON.parse(), protože odpovědí serveru je samozřejmě 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:

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

Nyní se budou hodit funkce nactiSeznam(url) a nactiPokemona(url), které stáhnou data a přepíšou obsah na stránce. Pojďme si je naprogramovat.

Načtení seznamu

Kód funkce, která pošle na server dotaz na seznam pokémonů a pak jej vypíše do stránky, je následující:

function nactiSeznam(url)
{
    let seznam_div = document.getElementById("poke-seznam");
    seznam_div.innerHTML = "<ul id='poke-seznam-ul'></ul>";
    let seznam_ul = document.getElementById("poke-seznam-ul");

    stahniJSON(url, (data) => {
        for (let pokemon of data.results)
        {
            let novaPolozka = document.createElement("li");
            novaPolozka.innerText = pokemon.name;
            seznam_ul.appendChild(novaPolozka);
            let poke_url = pokemon.url;
            novaPolozka.addEventListener("click", () => nactiPokemona(poke_url));
        }
    });
}

Na kódu není moc co vysvětlovat, jde o základní práci s DOM elementy. Pokémony ve vlastnosti results JSON objektu vráceného pomocí API projedeme cyklem a pro každého vytvoříme položku seznamu. Za zmínku stojí, že ke každé položce přidáme event listener, který zavolá nactiPokemona() s patřičnou URL získanou z dat API, když se na položku klikne.

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

Načtení 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ř. typy pokémona, vidíme, že zrovna Bulbasaur je jedovatý a zároveň travní typ.

Kód funkce posílající dotaz na konkrétního pokémona je pak následující:

function nactiPokemona(url)
{
    let detaily_div = document.getElementById("poke-detaily");
    stahniJSON(url, (data) => {
        let html = `
            <img src="${data.sprites.back_default}" />
            <ul>
                <li>Název: ${data.name}</li>
                <li>Výška: ${data.height}</li>
                <li>Váha: ${data.weight}</li>
            </ul>
        `;

        detaily_div.innerHTML = html;
    });
}

Zavolání načtení seznamu

Vše máme připraveno. Stačí již jen zavolat načtení seznamu:

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

Interaktivní ukázka

Výsledek může vypadat třeba takto, záleží na vašem ostylování. Po kliku na položku se načtou základní informace o pokémonovi a obrázek. Zkuste si to na interaktivním prohlížeči níže:

Tvoje stránka
localhost

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. Pokud vám cokoli nefunguje, pod lekcí je ke stažení archiv se zdrojovými kódy :-)

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 297x (1.42 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í:
210 hlasů
Jsem student VUT FIT v třetím ročníku. Nejraději mám Typescript a C#.
Aktivity