Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij podzimní akce 30% výuky zdarma!

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();
}
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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 si, 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:

Your page
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.

V následujícím cvičení, Řešené úlohy k 6.-12. lekci OOP v JavaScriptu, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
AJAX v JavaScriptu - Základní dotazy
Všechny články v sekci
Objektově orientované programování v JavaScriptu
Článek pro vás napsal Radek Veverka
Avatar
Jak se ti líbí článek?
1 hlasů
Jsem student VUT FIT v druhém ročníku. Nejraději mám Typescript a C#.
Aktivity (5)

 

 

Komentáře

Avatar
Vladislav Ladicky:12. března 13:27

Keď už sa ukazuje práca s AJAX starším, legacy spôsobom, vyhol by som sa používaniu arrow funkcií. A hlavne by som sa pri práci s cudzím API vyhol používaniu innerHTML atribútu. Získané texty treba treba použiť výlučne cez textContent atribút. To by malo byť aj vyslovene spomenuté ako základný bezpečnostný princíp.

 
Odpovědět
12. března 13:27
Avatar
Miloš Pabel
Člen
Avatar
Miloš Pabel:17. března 17:42

V HTML je chyba , píšeš místo atributu id v div elementu class a v JS pak voláš metodu getElementById kde dostaneš null.

 
Odpovědět
17. března 17:42
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Samuel Hél
Tým ITnetwork
Avatar
Odpovídá na Miloš Pabel
Samuel Hél:27. dubna 16:01

Díky, hned to opravím :)

 
Odpovědět
27. dubna 16:01
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 3 zpráv z 3.